From 66aaabf4ae05508ea8fa223c84b7a78aa754c7f9 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 1 Mar 2008 00:05:12 -0500 Subject: X86: Don't map the local APIC into the physical address space in SE mode. --HG-- extra : convert_revision : b7103974b12130bbf43583c4cb5294b808add208 --- src/arch/x86/tlb.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index a87abf212..3e720c9ae 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -592,6 +592,7 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) req->setPaddr(vaddr); } // Check for an access to the local APIC +#if FULL_SYSTEM LocalApicBase localApicBase = tc->readMiscRegNoEffect(MISCREG_APIC_BASE); Addr baseAddr = localApicBase.base << 12; Addr paddr = req->getPaddr(); @@ -733,6 +734,7 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) } req->setPaddr(regNum * sizeof(MiscReg)); } +#endif return NoFault; }; -- cgit v1.2.3 From 21fd15ad9a79510be1f4474e135a22f6742327f6 Mon Sep 17 00:00:00 2001 From: Vilas Sridharan Date: Thu, 6 Mar 2008 00:27:09 -0500 Subject: O3CPU: Don't call dumpInsts if DEBUG is not defined --HG-- extra : convert_revision : 3194bde4c624d118969bfbf92282539963a72245 --- src/cpu/base_dyn_inst_impl.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/cpu/base_dyn_inst_impl.hh b/src/cpu/base_dyn_inst_impl.hh index 5c18ae694..66075c60a 100644 --- a/src/cpu/base_dyn_inst_impl.hh +++ b/src/cpu/base_dyn_inst_impl.hh @@ -171,8 +171,8 @@ BaseDynInst::initVars() ++instcount; if (instcount > 1500) { - cpu->dumpInsts(); #ifdef DEBUG + cpu->dumpInsts(); dumpSNList(); #endif assert(instcount <= 1500); -- cgit v1.2.3 From a245b0eedfac7ba25656661868fbf3bd8eaf1ccd Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 6 Mar 2008 20:37:28 -0500 Subject: X86: Refine the local APIC. --HG-- extra : convert_revision : 2789c54ed555fed2f2a333fcc7dc6454f294ebf2 --- src/arch/x86/miscregfile.cc | 59 +++++++++++++++------------------------------ src/arch/x86/miscregs.hh | 2 ++ 2 files changed, 22 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc index 3b4dc3407..5d75af0cf 100644 --- a/src/arch/x86/miscregfile.cc +++ b/src/arch/x86/miscregfile.cc @@ -156,12 +156,8 @@ MiscReg MiscRegFile::readReg(int miscReg, ThreadContext * tc) case MISCREG_APIC_DESTINATION_FORMAT: panic("Local APIC Destination Format register unimplemented.\n"); break; - case MISCREG_APIC_SPURIOUS_INTERRUPT_VECTOR: - panic("Local APIC Spurious Interrupt Vector" - " register unimplemented.\n"); - break; case MISCREG_APIC_ERROR_STATUS: - panic("Local APIC Error Status register unimplemented.\n"); + regVal[MISCREG_APIC_INTERNAL_STATE] &= ~ULL(0x1); break; case MISCREG_APIC_INTERRUPT_COMMAND_LOW: panic("Local APIC Interrupt Command low" @@ -171,25 +167,6 @@ MiscReg MiscRegFile::readReg(int miscReg, ThreadContext * tc) panic("Local APIC Interrupt Command high" " register unimplemented.\n"); break; - case MISCREG_APIC_LVT_TIMER: - panic("Local APIC LVT Timer register unimplemented.\n"); - break; - case MISCREG_APIC_LVT_THERMAL_SENSOR: - panic("Local APIC LVT Thermal Sensor register unimplemented.\n"); - break; - case MISCREG_APIC_LVT_PERFORMANCE_MONITORING_COUNTERS: - panic("Local APIC LVT Performance Monitoring Counters" - " register unimplemented.\n"); - break; - case MISCREG_APIC_LVT_LINT0: - panic("Local APIC LVT LINT0 register unimplemented.\n"); - break; - case MISCREG_APIC_LVT_LINT1: - panic("Local APIC LVT LINT1 register unimplemented.\n"); - break; - case MISCREG_APIC_LVT_ERROR: - panic("Local APIC LVT Error register unimplemented.\n"); - break; case MISCREG_APIC_INITIAL_COUNT: panic("Local APIC Initial Count register unimplemented.\n"); break; @@ -261,11 +238,22 @@ void MiscRegFile::setReg(int miscReg, panic("Local APIC Destination Format register unimplemented.\n"); break; case MISCREG_APIC_SPURIOUS_INTERRUPT_VECTOR: - panic("Local APIC Spurious Interrupt Vector" - " register unimplemented.\n"); + regVal[MISCREG_APIC_INTERNAL_STATE] &= ~ULL(1 << 1); + regVal[MISCREG_APIC_INTERNAL_STATE] |= val & (1 << 8); + if (val & (1 << 9)) + warn("Focus processor checking not implemented.\n"); break; case MISCREG_APIC_ERROR_STATUS: - panic("Local APIC Error Status register unimplemented.\n"); + { + if (regVal[MISCREG_APIC_INTERNAL_STATE] & 0x1) { + regVal[MISCREG_APIC_INTERNAL_STATE] &= ~ULL(0x1); + newVal = 0; + } else { + regVal[MISCREG_APIC_INTERNAL_STATE] |= ULL(0x1); + return; + } + + } break; case MISCREG_APIC_INTERRUPT_COMMAND_LOW: panic("Local APIC Interrupt Command low" @@ -276,23 +264,16 @@ void MiscRegFile::setReg(int miscReg, " register unimplemented.\n"); break; case MISCREG_APIC_LVT_TIMER: - panic("Local APIC LVT Timer register unimplemented.\n"); - break; case MISCREG_APIC_LVT_THERMAL_SENSOR: - panic("Local APIC LVT Thermal Sensor register unimplemented.\n"); - break; case MISCREG_APIC_LVT_PERFORMANCE_MONITORING_COUNTERS: - panic("Local APIC LVT Performance Monitoring Counters" - " register unimplemented.\n"); - break; case MISCREG_APIC_LVT_LINT0: - panic("Local APIC LVT LINT0 register unimplemented.\n"); - break; case MISCREG_APIC_LVT_LINT1: - panic("Local APIC LVT LINT1 register unimplemented.\n"); - break; case MISCREG_APIC_LVT_ERROR: - panic("Local APIC LVT Error register unimplemented.\n"); + { + uint64_t readOnlyMask = (1 << 12) | (1 << 14); + newVal = (val & ~readOnlyMask) | + (regVal[miscReg] & readOnlyMask); + } break; case MISCREG_APIC_INITIAL_COUNT: panic("Local APIC Initial Count register unimplemented.\n"); diff --git a/src/arch/x86/miscregs.hh b/src/arch/x86/miscregs.hh index d1016d2a9..15ea0d77b 100644 --- a/src/arch/x86/miscregs.hh +++ b/src/arch/x86/miscregs.hh @@ -373,6 +373,8 @@ namespace X86ISA MISCREG_APIC_DIVIDE_COUNT, MISCREG_APIC_END = MISCREG_APIC_DIVIDE_COUNT, + MISCREG_APIC_INTERNAL_STATE, + // "Fake" MSRs for internally implemented devices MISCREG_PCI_CONFIG_ADDRESS, -- cgit v1.2.3 From 19c367fa8fa0c330676c1b7aacb532b8871164cf Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Sat, 15 Mar 2008 05:03:55 -0700 Subject: Fix subtle cache bug where read could return stale data if a prior write miss arrived while an even earlier read miss was still outstanding. --HG-- extra : convert_revision : 4924e145829b2ecf4610b88d33f4773510c6801a --- src/mem/cache/cache_impl.hh | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index e546e2a9a..5aecea7d5 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -825,6 +825,10 @@ Cache::handleResponse(PacketPtr pkt) } if (mshr->promoteDeferredTargets()) { + assert(mshr->needsExclusive() && !blk->isWritable()); + // avoid later read getting stale data while write miss is + // outstanding.. see comment in timingAccess() + blk->status &= ~BlkReadable; MSHRQueue *mq = mshr->queue; mq->markPending(mshr); requestMemSideBus((RequestCause)mq->index, pkt->finishTime); -- cgit v1.2.3 From 131c65f4293c76f2c9b0b98c62b1937cd0aea4ce Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Mon, 17 Mar 2008 03:07:38 -0400 Subject: Restructure bus timing calcs to cope with pkt being deleted by target. --HG-- extra : convert_revision : db8497e73a44f2a06aab121e797e88b4c0c31330 --- src/mem/bus.cc | 44 ++++++++++++++++++++++++-------------------- src/mem/bus.hh | 8 +++++--- 2 files changed, 29 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/mem/bus.cc b/src/mem/bus.cc index ff4512aca..3bf1c6cfc 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -110,21 +110,22 @@ const char * Bus::BusFreeEvent::description() const return "bus became available"; } -void Bus::preparePacket(PacketPtr pkt, Tick & headerTime) +Tick Bus::calcPacketTiming(PacketPtr pkt) { - //Bring tickNextIdle up to the present tick - //There is some potential ambiguity where a cycle starts, which might make - //a difference when devices are acting right around a cycle boundary. Using - //a < allows things which happen exactly on a cycle boundary to take up - //only the following cycle. Anything that happens later will have to "wait" - //for the end of that cycle, and then start using the bus after that. + // Bring tickNextIdle up to the present tick. + // There is some potential ambiguity where a cycle starts, which + // might make a difference when devices are acting right around a + // cycle boundary. Using a < allows things which happen exactly on + // a cycle boundary to take up only the following cycle. Anything + // that happens later will have to "wait" for the end of that + // cycle, and then start using the bus after that. if (tickNextIdle < curTick) { tickNextIdle = curTick; if (tickNextIdle % clock != 0) tickNextIdle = curTick - (curTick % clock) + clock; } - headerTime = tickNextIdle + headerCycles * clock; + Tick headerTime = tickNextIdle + headerCycles * clock; // The packet will be sent. Figure out how long it occupies the bus, and // how much of that time is for the first "word", aka bus width. @@ -142,10 +143,17 @@ void Bus::preparePacket(PacketPtr pkt, Tick & headerTime) pkt->firstWordTime = headerTime + clock; pkt->finishTime = headerTime + numCycles * clock; + + return headerTime; } void Bus::occupyBus(Tick until) { + if (until == 0) { + // shortcut for express snoop packets + return; + } + tickNextIdle = until; if (!busIdle.scheduled()) { @@ -190,11 +198,8 @@ Bus::recvTiming(PacketPtr pkt) DPRINTF(Bus, "recvTiming: src %d dst %d %s 0x%x\n", src, pkt->getDest(), pkt->cmdString(), pkt->getAddr()); - Tick headerTime = 0; - - if (!pkt->isExpressSnoop()) { - preparePacket(pkt, headerTime); - } + Tick headerFinishTime = pkt->isExpressSnoop() ? 0 : calcPacketTiming(pkt); + Tick packetFinishTime = pkt->isExpressSnoop() ? 0 : pkt->finishTime; short dest = pkt->getDest(); int dest_port_id; @@ -243,17 +248,16 @@ Bus::recvTiming(PacketPtr pkt) DPRINTF(Bus, "recvTiming: src %d dst %d %s 0x%x TGT RETRY\n", src, pkt->getDest(), pkt->cmdString(), pkt->getAddr()); addToRetryList(src_port); - if (!pkt->isExpressSnoop()) { - occupyBus(headerTime); - } + occupyBus(headerFinishTime); return false; } - // send OK, fall through + // send OK, fall through... pkt may have been deleted by + // target at this point, so it should *not* be referenced + // again. We'll set it to NULL here just to be safe. + pkt = NULL; } - if (!pkt->isExpressSnoop()) { - occupyBus(pkt->finishTime); - } + occupyBus(packetFinishTime); // Packet was successfully sent. // Also take care of retries diff --git a/src/mem/bus.hh b/src/mem/bus.hh index 274c02de4..74901d626 100644 --- a/src/mem/bus.hh +++ b/src/mem/bus.hh @@ -245,10 +245,12 @@ class Bus : public MemObject */ void addressRanges(AddrRangeList &resp, bool &snoop, int id); - /** Prepare a packet to be sent on the bus. The header finishes at tick - * headerTime + /** Calculate the timing parameters for the packet. Updates the + * firstWordTime and finishTime fields of the packet object. + * Returns the tick at which the packet header is completed (which + * will be all that is sent if the target rejects the packet). */ - void preparePacket(PacketPtr pkt, Tick & headerTime); + Tick calcPacketTiming(PacketPtr pkt); /** Occupy the bus until until */ void occupyBus(Tick until); -- cgit v1.2.3 From b051ae6acc5a4e98ba60478f42ba2a2b92cb5ff1 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Mon, 17 Mar 2008 03:08:28 -0400 Subject: Fix a few Packet memory leaks. --HG-- extra : convert_revision : 00db19f0698c0786f0dff561eea9217860a5a05a --- src/mem/cache/cache_impl.hh | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 5aecea7d5..cf9528a75 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -407,6 +407,9 @@ Cache::timingAccess(PacketPtr pkt) memSidePort->sendTiming(snoopPkt); // main memory will delete snoopPkt } + // since we're the official target but we aren't responding, + // delete the packet now. + delete pkt; return true; } @@ -1092,6 +1095,11 @@ Cache::handleSnoop(PacketPtr pkt, BlkType *blk, pkt->makeAtomicResponse(); pkt->setDataFromBlock(blk->data, blkSize); } + } else if (is_timing && is_deferred) { + // if it's a deferred timing snoop then we've made a copy of + // the packet, and so if we're not using that copy to respond + // then we need to delete it here. + delete pkt; } // Do this last in case it deallocates block data or something @@ -1160,6 +1168,7 @@ Cache::snoopTiming(PacketPtr pkt) if (pkt->isInvalidate()) { // Invalidation trumps our writeback... discard here markInService(mshr); + delete wb_pkt; } // If this was a shared writeback, there may still be -- cgit v1.2.3 From 3fe1af795243b42bd957d5fc6f243bb63f603f7d Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 20 Mar 2008 02:10:21 -0400 Subject: MIPS: Check endianness of binaries in SE mode. --HG-- extra : convert_revision : e6c4bda6078eb68a26f8834411f744078c6bf5a9 --- src/base/loader/elf_object.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/base/loader/elf_object.cc b/src/base/loader/elf_object.cc index 8e41ffd16..4c3f694e5 100644 --- a/src/base/loader/elf_object.cc +++ b/src/base/loader/elf_object.cc @@ -79,7 +79,13 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data) arch = ObjectFile::SPARC32; } else if (ehdr.e_machine == EM_MIPS && ehdr.e_ident[EI_CLASS] == ELFCLASS32) { - arch = ObjectFile::Mips; + if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) { + arch = ObjectFile::Mips; + } else { + fatal("The binary you're trying to load is compiled for big " + "endian MIPS. M5\nonly supports little endian MIPS. " + "Please recompile your binary.\n"); + } } else if (ehdr.e_machine == EM_X86_64 && ehdr.e_ident[EI_CLASS] == ELFCLASS64) { //In the future, we might want to differentiate between 32 bit -- cgit v1.2.3 From 407710d387497f44de53baf0ae60a2c426c1bb74 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Sat, 22 Mar 2008 22:17:15 -0400 Subject: Fix cache problem with writes to tempBlock getting wrong writeback address. --HG-- extra : convert_revision : 023dfb69c227c13a69bfe2744c6af75a45828b0b --- src/mem/cache/cache_impl.hh | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index cf9528a75..2f4567e0d 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -941,6 +941,7 @@ Cache::handleFill(PacketPtr pkt, BlkType *blk, assert(!tempBlock->isValid()); blk = tempBlock; tempBlock->set = tags->extractSet(addr); + tempBlock->tag = tags->extractTag(addr); DPRINTF(Cache, "using temp block for %x\n", addr); } } else { -- cgit v1.2.3 From 627592c2f2a9d2774df50b2b5039efcb71432bc7 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Mon, 24 Mar 2008 01:08:02 -0400 Subject: Add FAST_ALLOC_DEBUG and FAST_ALLOC_STATS as SConstruct options. --HG-- extra : convert_revision : 56a7f646f2ac87019c78ba7fa62c5f4bdc00ba44 --- src/base/fast_alloc.cc | 12 +++++++----- src/base/fast_alloc.hh | 20 +++++++------------- 2 files changed, 14 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/base/fast_alloc.cc b/src/base/fast_alloc.cc index e1298a8bd..e263df893 100644 --- a/src/base/fast_alloc.cc +++ b/src/base/fast_alloc.cc @@ -45,7 +45,7 @@ void *FastAlloc::freeLists[Num_Buckets]; -#ifdef FAST_ALLOC_STATS +#if FAST_ALLOC_STATS unsigned FastAlloc::newCount[Num_Buckets]; unsigned FastAlloc::deleteCount[Num_Buckets]; unsigned FastAlloc::allocCount[Num_Buckets]; @@ -59,7 +59,7 @@ void *FastAlloc::moreStructs(int bucket) const int nstructs = Num_Structs_Per_New; // how many to allocate? char *p = ::new char[nstructs * sz]; -#ifdef FAST_ALLOC_STATS +#if FAST_ALLOC_STATS ++allocCount[bucket]; #endif @@ -72,7 +72,7 @@ void *FastAlloc::moreStructs(int bucket) } -#ifdef FAST_ALLOC_DEBUG +#if FAST_ALLOC_DEBUG #include #include @@ -167,9 +167,9 @@ FastAlloc::dump_oldest(int n) return; } - for (FastAlloc *p = inUseHead.inUsePrev; + for (FastAlloc *p = inUseHead.inUseNext; p != &inUseHead && n > 0; - p = p->inUsePrev, --n) + p = p->inUseNext, --n) { cout << p << " " << typeid(*p).name() << endl; } @@ -180,11 +180,13 @@ FastAlloc::dump_oldest(int n) // C interfaces to FastAlloc::dump_summary() and FastAlloc::dump_oldest(). // gdb seems to have trouble with calling C++ functions directly. // +void fast_alloc_summary() { FastAlloc::dump_summary(); } +void fast_alloc_oldest(int n) { FastAlloc::dump_oldest(n); diff --git a/src/base/fast_alloc.hh b/src/base/fast_alloc.hh index 3e22e59c1..50b761c9c 100644 --- a/src/base/fast_alloc.hh +++ b/src/base/fast_alloc.hh @@ -62,15 +62,9 @@ // collapse the destructor call chain back up the inheritance // hierarchy. -// Uncomment this #define to track in-use objects -// (for debugging memory leaks). -//#define FAST_ALLOC_DEBUG - -// Uncomment this #define to count news, deletes, and chunk allocations -// (by bucket). -// #define FAST_ALLOC_STATS - #include "config/no_fast_alloc.hh" +#include "config/fast_alloc_debug.hh" +#include "config/fast_alloc_stats.hh" #if NO_FAST_ALLOC @@ -88,7 +82,7 @@ class FastAlloc { void *operator new(size_t); void operator delete(void *, size_t); -#ifdef FAST_ALLOC_DEBUG +#if FAST_ALLOC_DEBUG FastAlloc(); FastAlloc(FastAlloc*,FastAlloc*); // for inUseHead, see below virtual ~FastAlloc(); @@ -121,13 +115,13 @@ class FastAlloc { static void *freeLists[Num_Buckets]; -#ifdef FAST_ALLOC_STATS +#if FAST_ALLOC_STATS static unsigned newCount[Num_Buckets]; static unsigned deleteCount[Num_Buckets]; static unsigned allocCount[Num_Buckets]; #endif -#ifdef FAST_ALLOC_DEBUG +#if FAST_ALLOC_DEBUG // per-object debugging fields bool inUse; // in-use flag FastAlloc *inUsePrev; // ptrs to build list of in-use objects @@ -170,7 +164,7 @@ void *FastAlloc::allocate(size_t sz) else p = moreStructs(b); -#ifdef FAST_ALLOC_STATS +#if FAST_ALLOC_STATS ++newCount[b]; #endif @@ -192,7 +186,7 @@ void FastAlloc::deallocate(void *p, size_t sz) b = bucketFor(sz); *(void **)p = freeLists[b]; freeLists[b] = p; -#ifdef FAST_ALLOC_STATS +#if FAST_ALLOC_STATS ++deleteCount[b]; #endif } -- cgit v1.2.3 From 93ab43288a75061746701c9d22a355793f330a9c Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Mon, 24 Mar 2008 01:08:02 -0400 Subject: Don't FastAlloc MSHRs since we don't allocate them on the fly. --HG-- extra : convert_revision : 02775cfb460afe6df0df0938c62cccd93a71e775 --- src/cpu/memtest/memtest.hh | 3 ++- src/cpu/o3/lsq_unit.hh | 3 ++- src/cpu/ozone/lw_lsq.hh | 3 ++- src/dev/io_device.hh | 3 ++- src/mem/bridge.hh | 3 ++- src/mem/cache/cache_impl.hh | 3 ++- src/mem/packet.hh | 4 ++-- 7 files changed, 14 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/cpu/memtest/memtest.hh b/src/cpu/memtest/memtest.hh index ac2d0a058..43f141af6 100644 --- a/src/cpu/memtest/memtest.hh +++ b/src/cpu/memtest/memtest.hh @@ -35,6 +35,7 @@ #include #include "base/statistics.hh" +#include "base/fast_alloc.hh" #include "params/MemTest.hh" #include "sim/eventq.hh" #include "sim/sim_exit.hh" @@ -116,7 +117,7 @@ class MemTest : public MemObject bool snoopRangeSent; - class MemTestSenderState : public Packet::SenderState + class MemTestSenderState : public Packet::SenderState, public FastAlloc { public: /** Constructor. */ diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh index 128a71dbc..3ae69723d 100644 --- a/src/cpu/o3/lsq_unit.hh +++ b/src/cpu/o3/lsq_unit.hh @@ -40,6 +40,7 @@ #include "arch/faults.hh" #include "arch/locked_mem.hh" #include "config/full_system.hh" +#include "base/fast_alloc.hh" #include "base/hashmap.hh" #include "cpu/inst_seq.hh" #include "mem/packet.hh" @@ -245,7 +246,7 @@ class LSQUnit { Port *dcachePort; /** Derived class to hold any sender state the LSQ needs. */ - class LSQSenderState : public Packet::SenderState + class LSQSenderState : public Packet::SenderState, public FastAlloc { public: /** Default constructor. */ diff --git a/src/cpu/ozone/lw_lsq.hh b/src/cpu/ozone/lw_lsq.hh index 7fc8b6307..2525da76e 100644 --- a/src/cpu/ozone/lw_lsq.hh +++ b/src/cpu/ozone/lw_lsq.hh @@ -39,6 +39,7 @@ #include "arch/faults.hh" #include "arch/types.hh" #include "config/full_system.hh" +#include "base/fast_alloc.hh" #include "base/hashmap.hh" #include "cpu/inst_seq.hh" #include "mem/packet.hh" @@ -301,7 +302,7 @@ class OzoneLWLSQ { }; /** Derived class to hold any sender state the LSQ needs. */ - class LSQSenderState : public Packet::SenderState + class LSQSenderState : public Packet::SenderState, public FastAlloc { public: /** Default constructor. */ diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh index 876166adb..44aa01798 100644 --- a/src/dev/io_device.hh +++ b/src/dev/io_device.hh @@ -32,6 +32,7 @@ #ifndef __DEV_IO_DEVICE_HH__ #define __DEV_IO_DEVICE_HH__ +#include "base/fast_alloc.hh" #include "mem/mem_object.hh" #include "mem/packet.hh" #include "mem/tport.hh" @@ -73,7 +74,7 @@ class PioPort : public SimpleTimingPort class DmaPort : public Port { protected: - struct DmaReqState : public Packet::SenderState + struct DmaReqState : public Packet::SenderState, public FastAlloc { /** Event to call on the device when this transaction (all packets) * complete. */ diff --git a/src/mem/bridge.hh b/src/mem/bridge.hh index 1331a45f9..a9dd67a2b 100644 --- a/src/mem/bridge.hh +++ b/src/mem/bridge.hh @@ -42,6 +42,7 @@ #include #include +#include "base/fast_alloc.hh" #include "mem/mem_object.hh" #include "mem/packet.hh" #include "mem/port.hh" @@ -73,7 +74,7 @@ class Bridge : public MemObject /** Pass ranges from one side of the bridge to the other? */ std::vector > filterRanges; - class PacketBuffer : public Packet::SenderState { + class PacketBuffer : public Packet::SenderState, public FastAlloc { public: Tick ready; diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 2f4567e0d..47d20f915 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -38,6 +38,7 @@ */ #include "sim/host.hh" +#include "base/fast_alloc.hh" #include "base/misc.hh" #include "base/range_ops.hh" @@ -346,7 +347,7 @@ Cache::access(PacketPtr pkt, BlkType *&blk, int &lat) } -class ForwardResponseRecord : public Packet::SenderState +class ForwardResponseRecord : public Packet::SenderState, public FastAlloc { Packet::SenderState *prevSenderState; int prevSrc; diff --git a/src/mem/packet.hh b/src/mem/packet.hh index 05442b369..7aad9de98 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -295,7 +295,7 @@ class Packet : public FastAlloc, public Printable * needed to process it. A specific subclass would be derived * from this to carry state specific to a particular sending * device. */ - class SenderState : public FastAlloc { + class SenderState { public: virtual ~SenderState() {} }; @@ -304,7 +304,7 @@ class Packet : public FastAlloc, public Printable * Object used to maintain state of a PrintReq. The senderState * field of a PrintReq should always be of this type. */ - class PrintReqState : public SenderState { + class PrintReqState : public SenderState, public FastAlloc { /** An entry in the label stack. */ class LabelStackEntry { public: -- cgit v1.2.3 From 623dd7ed3a66e71e241dc8365c079cb5b42fa918 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Mon, 24 Mar 2008 01:08:02 -0400 Subject: Delete the Request for a no-response Packet when the Packet is deleted, since the requester can't possibly do it. --HG-- extra : convert_revision : 8571b144ecb3c70efc06d09faa8b3161fb58352d --- src/mem/packet.hh | 10 +++++++++- src/mem/tport.cc | 1 - 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/mem/packet.hh b/src/mem/packet.hh index 7aad9de98..a278a3945 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -455,7 +455,15 @@ class Packet : public FastAlloc, public Printable /** Destructor. */ ~Packet() - { if (staticData || dynamicData) deleteData(); } + { + // If this is a request packet for which there's no response, + // delete the request object here, since the requester will + // never get the chance. + if (req && isRequest() && !needsResponse()) + delete req; + if (staticData || dynamicData) + deleteData(); + } /** Reinitialize packet address and size from the associated * Request object, and reset other fields that may have been diff --git a/src/mem/tport.cc b/src/mem/tport.cc index 9fa27046b..ad5e95909 100644 --- a/src/mem/tport.cc +++ b/src/mem/tport.cc @@ -83,7 +83,6 @@ SimpleTimingPort::recvTiming(PacketPtr pkt) assert(pkt->isResponse()); schedSendTiming(pkt, curTick + latency); } else { - delete pkt->req; delete pkt; } -- cgit v1.2.3 From b0c52885ce5164c2c6105a1de1963c1d761477d1 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 25 Mar 2008 02:06:53 -0400 Subject: X86: Change the Opteron platform to be the PC platform. --HG-- extra : convert_revision : 2c6ffebbad04a21cef6ba3fbc1803218908a6c37 --- src/dev/x86/Opteron.py | 18 -------- src/dev/x86/PC.py | 57 ++++++++++++++++++++++++++ src/dev/x86/SConscript | 4 +- src/dev/x86/opteron.cc | 109 ------------------------------------------------- src/dev/x86/opteron.hh | 92 ----------------------------------------- src/dev/x86/pc.cc | 109 +++++++++++++++++++++++++++++++++++++++++++++++++ src/dev/x86/pc.hh | 92 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 260 insertions(+), 221 deletions(-) delete mode 100644 src/dev/x86/Opteron.py create mode 100644 src/dev/x86/PC.py delete mode 100644 src/dev/x86/opteron.cc delete mode 100644 src/dev/x86/opteron.hh create mode 100644 src/dev/x86/pc.cc create mode 100644 src/dev/x86/pc.hh (limited to 'src') diff --git a/src/dev/x86/Opteron.py b/src/dev/x86/Opteron.py deleted file mode 100644 index cb015e2e7..000000000 --- a/src/dev/x86/Opteron.py +++ /dev/null @@ -1,18 +0,0 @@ -from m5.params import * -from m5.proxy import * -from Device import BasicPioDevice, PioDevice, IsaFake, BadAddr -from Uart import Uart8250 -from Platform import Platform -from Pci import PciConfigAll -from SimConsole import SimConsole - -class Opteron(Platform): - type = 'Opteron' - system = Param.System(Parent.any, "system") - - pciconfig = PciConfigAll() - - def attachIO(self, bus): - self.pciconfig.pio = bus.default - bus.responder_set = True - bus.responder = self.pciconfig diff --git a/src/dev/x86/PC.py b/src/dev/x86/PC.py new file mode 100644 index 000000000..3314e7741 --- /dev/null +++ b/src/dev/x86/PC.py @@ -0,0 +1,57 @@ +# Copyright (c) 2008 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +from m5.params import * +from m5.proxy import * +from Device import BasicPioDevice, PioDevice, IsaFake, BadAddr +from Uart import Uart8250 +from Platform import Platform +from Pci import PciConfigAll +from SimConsole import SimConsole + +def x86IOAddress(port): + IO_address_space_base = 0x8000000000000000 + return IO_address_space_base + port; + +class PC(Platform): + type = 'PC' + system = Param.System(Parent.any, "system") + + pciconfig = PciConfigAll() + + # Serial port and console + console = SimConsole() + com_1 = Uart8250() + com_1.pio_addr = x86IOAddress(0x3f8) + com_1.sim_console = console + + def attachIO(self, bus): + self.com_1.pio = bus.port + self.pciconfig.pio = bus.default + bus.responder_set = True + bus.responder = self.pciconfig diff --git a/src/dev/x86/SConscript b/src/dev/x86/SConscript index c500531b1..6ebaed265 100644 --- a/src/dev/x86/SConscript +++ b/src/dev/x86/SConscript @@ -32,6 +32,6 @@ Import('*') if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'x86': - SimObject('Opteron.py') + SimObject('PC.py') - Source('opteron.cc') + Source('pc.cc') diff --git a/src/dev/x86/opteron.cc b/src/dev/x86/opteron.cc deleted file mode 100644 index ba46f2dfa..000000000 --- a/src/dev/x86/opteron.cc +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -/** @file - * Implementation of Opteron platform. - */ - -#include -#include -#include - -#include "arch/x86/x86_traits.hh" -#include "cpu/intr_control.hh" -#include "dev/simconsole.hh" -#include "dev/x86/opteron.hh" -#include "sim/system.hh" - -using namespace std; -using namespace TheISA; - -Opteron::Opteron(const Params *p) - : Platform(p), system(p->system) -{ - // set the back pointer from the system to myself - system->platform = this; -} - -Tick -Opteron::intrFrequency() -{ - panic("Need implementation\n"); - M5_DUMMY_RETURN -} - -void -Opteron::postConsoleInt() -{ - warn_once("Don't know what interrupt to post for console.\n"); - //panic("Need implementation\n"); -} - -void -Opteron::clearConsoleInt() -{ - warn_once("Don't know what interrupt to clear for console.\n"); - //panic("Need implementation\n"); -} - -void -Opteron::postPciInt(int line) -{ - panic("Need implementation\n"); -} - -void -Opteron::clearPciInt(int line) -{ - panic("Need implementation\n"); -} - -Addr -Opteron::pciToDma(Addr pciAddr) const -{ - panic("Need implementation\n"); - M5_DUMMY_RETURN -} - - -Addr -Opteron::calcConfigAddr(int bus, int dev, int func) -{ - assert(func < 8); - assert(dev < 32); - assert(bus == 0); - return (PhysAddrPrefixPciConfig | (func << 8) | (dev << 11)); -} - -Opteron * -OpteronParams::create() -{ - return new Opteron(this); -} diff --git a/src/dev/x86/opteron.hh b/src/dev/x86/opteron.hh deleted file mode 100644 index 3026bce73..000000000 --- a/src/dev/x86/opteron.hh +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -/** - * @file - * Declaration of top level class for the Opteron platform chips. This class - * just retains pointers to all its children so the children can communicate. - */ - -#ifndef __DEV_Opteron_HH__ -#define __DEV_Opteron_HH__ - -#include "dev/platform.hh" -#include "params/Opteron.hh" - -class IdeController; -class System; - -class Opteron : public Platform -{ - public: - /** Pointer to the system */ - System *system; - - public: - typedef OpteronParams Params; - - Opteron(const Params *p); - - /** - * Return the interrupting frequency to AlphaAccess - * @return frequency of RTC interrupts - */ - virtual Tick intrFrequency(); - - /** - * Cause the cpu to post a serial interrupt to the CPU. - */ - virtual void postConsoleInt(); - - /** - * Clear a posted CPU interrupt - */ - virtual void clearConsoleInt(); - - /** - * Cause the chipset to post a pci interrupt to the CPU. - */ - virtual void postPciInt(int line); - - /** - * Clear a posted PCI->CPU interrupt - */ - virtual void clearPciInt(int line); - - - virtual Addr pciToDma(Addr pciAddr) const; - - /** - * Calculate the configuration address given a bus/dev/func. - */ - virtual Addr calcConfigAddr(int bus, int dev, int func); -}; - -#endif // __DEV_OPTERON_HH__ diff --git a/src/dev/x86/pc.cc b/src/dev/x86/pc.cc new file mode 100644 index 000000000..148ba92f7 --- /dev/null +++ b/src/dev/x86/pc.cc @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +/** @file + * Implementation of PC platform. + */ + +#include +#include +#include + +#include "arch/x86/x86_traits.hh" +#include "cpu/intr_control.hh" +#include "dev/simconsole.hh" +#include "dev/x86/pc.hh" +#include "sim/system.hh" + +using namespace std; +using namespace TheISA; + +PC::PC(const Params *p) + : Platform(p), system(p->system) +{ + // set the back pointer from the system to myself + system->platform = this; +} + +Tick +PC::intrFrequency() +{ + panic("Need implementation\n"); + M5_DUMMY_RETURN +} + +void +PC::postConsoleInt() +{ + warn_once("Don't know what interrupt to post for console.\n"); + //panic("Need implementation\n"); +} + +void +PC::clearConsoleInt() +{ + warn_once("Don't know what interrupt to clear for console.\n"); + //panic("Need implementation\n"); +} + +void +PC::postPciInt(int line) +{ + panic("Need implementation\n"); +} + +void +PC::clearPciInt(int line) +{ + panic("Need implementation\n"); +} + +Addr +PC::pciToDma(Addr pciAddr) const +{ + panic("Need implementation\n"); + M5_DUMMY_RETURN +} + + +Addr +PC::calcConfigAddr(int bus, int dev, int func) +{ + assert(func < 8); + assert(dev < 32); + assert(bus == 0); + return (PhysAddrPrefixPciConfig | (func << 8) | (dev << 11)); +} + +PC * +PCParams::create() +{ + return new PC(this); +} diff --git a/src/dev/x86/pc.hh b/src/dev/x86/pc.hh new file mode 100644 index 000000000..6e3a7f45e --- /dev/null +++ b/src/dev/x86/pc.hh @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +/** + * @file + * Declaration of top level class for PC platform components. This class + * just retains pointers to all its children so the children can communicate. + */ + +#ifndef __DEV_PC_HH__ +#define __DEV_PC_HH__ + +#include "dev/platform.hh" +#include "params/PC.hh" + +class IdeController; +class System; + +class PC : public Platform +{ + public: + /** Pointer to the system */ + System *system; + + public: + typedef PCParams Params; + + PC(const Params *p); + + /** + * Return the interrupting frequency to AlphaAccess + * @return frequency of RTC interrupts + */ + virtual Tick intrFrequency(); + + /** + * Cause the cpu to post a serial interrupt to the CPU. + */ + virtual void postConsoleInt(); + + /** + * Clear a posted CPU interrupt + */ + virtual void clearConsoleInt(); + + /** + * Cause the chipset to post a pci interrupt to the CPU. + */ + virtual void postPciInt(int line); + + /** + * Clear a posted PCI->CPU interrupt + */ + virtual void clearPciInt(int line); + + + virtual Addr pciToDma(Addr pciAddr) const; + + /** + * Calculate the configuration address given a bus/dev/func. + */ + virtual Addr calcConfigAddr(int bus, int dev, int func); +}; + +#endif // __DEV_PC_HH__ -- cgit v1.2.3 From 48409ca512da9e972b159d45068a1173d2ae1759 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 25 Mar 2008 02:08:54 -0400 Subject: X86: Start implementing the south bridge stuff. --HG-- extra : convert_revision : 92918c05eb3363155d78889bdab17baa8eae9dca --- src/arch/x86/x86_traits.hh | 12 +++ src/dev/x86/PC.py | 10 ++- src/dev/x86/SConscript | 3 +- src/dev/x86/south_bridge/SConscript | 42 +++++++++++ src/dev/x86/south_bridge/SouthBridge.py | 35 +++++++++ src/dev/x86/south_bridge/cmos.cc | 126 +++++++++++++++++++++++++++++++ src/dev/x86/south_bridge/cmos.hh | 81 ++++++++++++++++++++ src/dev/x86/south_bridge/i8254.cc | 86 +++++++++++++++++++++ src/dev/x86/south_bridge/i8254.hh | 63 ++++++++++++++++ src/dev/x86/south_bridge/i8259.cc | 45 +++++++++++ src/dev/x86/south_bridge/i8259.hh | 60 +++++++++++++++ src/dev/x86/south_bridge/south_bridge.cc | 86 +++++++++++++++++++++ src/dev/x86/south_bridge/south_bridge.hh | 84 +++++++++++++++++++++ src/dev/x86/south_bridge/speaker.cc | 64 ++++++++++++++++ src/dev/x86/south_bridge/speaker.hh | 60 +++++++++++++++ src/dev/x86/south_bridge/sub_device.hh | 79 +++++++++++++++++++ 16 files changed, 933 insertions(+), 3 deletions(-) create mode 100644 src/dev/x86/south_bridge/SConscript create mode 100644 src/dev/x86/south_bridge/SouthBridge.py create mode 100644 src/dev/x86/south_bridge/cmos.cc create mode 100644 src/dev/x86/south_bridge/cmos.hh create mode 100644 src/dev/x86/south_bridge/i8254.cc create mode 100644 src/dev/x86/south_bridge/i8254.hh create mode 100644 src/dev/x86/south_bridge/i8259.cc create mode 100644 src/dev/x86/south_bridge/i8259.hh create mode 100644 src/dev/x86/south_bridge/south_bridge.cc create mode 100644 src/dev/x86/south_bridge/south_bridge.hh create mode 100644 src/dev/x86/south_bridge/speaker.cc create mode 100644 src/dev/x86/south_bridge/speaker.hh create mode 100644 src/dev/x86/south_bridge/sub_device.hh (limited to 'src') diff --git a/src/arch/x86/x86_traits.hh b/src/arch/x86/x86_traits.hh index d605ce218..f46279c81 100644 --- a/src/arch/x86/x86_traits.hh +++ b/src/arch/x86/x86_traits.hh @@ -90,6 +90,18 @@ namespace X86ISA const Addr PhysAddrPrefixIO = ULL(0x8000000000000000); const Addr PhysAddrPrefixPciConfig = ULL(0xC000000000000000); + + static inline Addr + x86IOAddress(const uint32_t port) + { + return PhysAddrPrefixIO | port; + } + + static inline Addr + x86PciConfigAddress(const uint32_t addr) + { + return PhysAddrPrefixPciConfig | addr; + } } #endif //__ARCH_X86_X86TRAITS_HH__ diff --git a/src/dev/x86/PC.py b/src/dev/x86/PC.py index 3314e7741..86ae4c3ba 100644 --- a/src/dev/x86/PC.py +++ b/src/dev/x86/PC.py @@ -28,8 +28,9 @@ from m5.params import * from m5.proxy import * -from Device import BasicPioDevice, PioDevice, IsaFake, BadAddr from Uart import Uart8250 +from Device import IsaFake +from SouthBridge import SouthBridge from Platform import Platform from Pci import PciConfigAll from SimConsole import SimConsole @@ -44,6 +45,11 @@ class PC(Platform): pciconfig = PciConfigAll() + south_bridge = SouthBridge() + + # "Non-existant" port used for timing purposes by the linux kernel + i_dont_exist = IsaFake(pio_addr=x86IOAddress(0x80), pio_size=1) + # Serial port and console console = SimConsole() com_1 = Uart8250() @@ -51,6 +57,8 @@ class PC(Platform): com_1.sim_console = console def attachIO(self, bus): + self.south_bridge.pio = bus.port + self.i_dont_exist.pio = bus.port self.com_1.pio = bus.port self.pciconfig.pio = bus.default bus.responder_set = True diff --git a/src/dev/x86/SConscript b/src/dev/x86/SConscript index 6ebaed265..463344001 100644 --- a/src/dev/x86/SConscript +++ b/src/dev/x86/SConscript @@ -26,8 +26,7 @@ # (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: Steve Reinhardt -# Gabe Black +# Authors: Gabe Black Import('*') diff --git a/src/dev/x86/south_bridge/SConscript b/src/dev/x86/south_bridge/SConscript new file mode 100644 index 000000000..a7cb77b9b --- /dev/null +++ b/src/dev/x86/south_bridge/SConscript @@ -0,0 +1,42 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +Import('*') + +if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'x86': + # Main device + SimObject('SouthBridge.py') + Source('south_bridge.cc') + + # Sub devices + Source('cmos.cc') + Source('i8254.cc') + Source('i8259.cc') + Source('speaker.cc') diff --git a/src/dev/x86/south_bridge/SouthBridge.py b/src/dev/x86/south_bridge/SouthBridge.py new file mode 100644 index 000000000..bec3c4223 --- /dev/null +++ b/src/dev/x86/south_bridge/SouthBridge.py @@ -0,0 +1,35 @@ +# Copyright (c) 2008 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +from m5.params import * +from m5.proxy import * +from Device import PioDevice + +class SouthBridge(PioDevice): + type = 'SouthBridge' + pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") diff --git a/src/dev/x86/south_bridge/cmos.cc b/src/dev/x86/south_bridge/cmos.cc new file mode 100644 index 000000000..43ada42e8 --- /dev/null +++ b/src/dev/x86/south_bridge/cmos.cc @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "dev/x86/south_bridge/cmos.hh" +#include "mem/packet_access.hh" + +Tick +X86ISA::Cmos::read(PacketPtr pkt) +{ + assert(pkt->getSize() == 1); + switch(pkt->getAddr() - addrRange.start) + { + case 0x0: + pkt->set(address); + break; + case 0x1: + pkt->set(readRegister(address)); + break; + default: + panic("Read from undefined CMOS port.\n"); + } + return latency; +} + +Tick +X86ISA::Cmos::write(PacketPtr pkt) +{ + assert(pkt->getSize() == 1); + switch(pkt->getAddr() - addrRange.start) + { + case 0x0: + address = pkt->get(); + break; + case 0x1: + writeRegister(address, pkt->get()); + break; + default: + panic("Write to undefined CMOS port.\n"); + } + return latency; +} + +uint8_t +X86ISA::Cmos::readRegister(uint8_t reg) +{ + assert(reg < numRegs); + switch(reg) + { + case 0x0: + case 0x1: + case 0x2: + case 0x3: + case 0x4: + case 0x5: + case 0x6: + case 0x7: + case 0x8: + case 0x9: + case 0xA: + case 0xB: + case 0xC: + case 0xD: + warn("Reading RTC in the CMOS.\n"); + break; + default: + warn("Reading non-volitile CMOS address %x as %x.\n", reg, regs[reg]); + break; + } + return regs[reg]; +} + +void +X86ISA::Cmos::writeRegister(uint8_t reg, uint8_t val) +{ + assert(reg < numRegs); + switch(reg) + { + case 0x0: + case 0x1: + case 0x2: + case 0x3: + case 0x4: + case 0x5: + case 0x6: + case 0x7: + case 0x8: + case 0x9: + case 0xA: + case 0xB: + case 0xC: + case 0xD: + warn("Writing RTC in the CMOS.\n"); + break; + default: + warn("Writing non-volitile CMOS address %x with %x.\n", reg, val); + break; + } + regs[reg] = val; +} diff --git a/src/dev/x86/south_bridge/cmos.hh b/src/dev/x86/south_bridge/cmos.hh new file mode 100644 index 000000000..cd3fab280 --- /dev/null +++ b/src/dev/x86/south_bridge/cmos.hh @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __DEV_X86_SOUTH_BRIDGE_CMOS_HH__ +#define __DEV_X86_SOUTH_BRIDGE_CMOS_HH__ + +#include "arch/x86/x86_traits.hh" +#include "base/range.hh" +#include "dev/x86/south_bridge/sub_device.hh" + +namespace X86ISA +{ + +class Cmos : public SubDevice +{ + protected: + uint8_t address; + + static const int numRegs = 128; + + uint8_t regs[numRegs]; + + uint8_t readRegister(uint8_t reg); + void writeRegister(uint8_t reg, uint8_t val); + + public: + + Cmos() + { + memset(regs, 0, numRegs * sizeof(uint8_t)); + address = 0; + } + + Cmos(Tick _latency) : SubDevice(_latency) + { + memset(regs, 0, numRegs * sizeof(uint8_t)); + address = 0; + } + + Cmos(Addr start, Addr size, Tick _latency) : + SubDevice(start, size, _latency) + { + memset(regs, 0, numRegs * sizeof(uint8_t)); + address = 0; + } + + Tick read(PacketPtr pkt); + + Tick write(PacketPtr pkt); +}; + +}; // namespace X86ISA + +#endif //__DEV_X86_SOUTH_BRIDGE_CMOS_HH__ diff --git a/src/dev/x86/south_bridge/i8254.cc b/src/dev/x86/south_bridge/i8254.cc new file mode 100644 index 000000000..fb6723a51 --- /dev/null +++ b/src/dev/x86/south_bridge/i8254.cc @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "dev/x86/south_bridge/i8254.hh" +#include "mem/packet_access.hh" + +Tick +X86ISA::I8254::read(PacketPtr pkt) +{ + assert(pkt->getSize() == 1); + switch(pkt->getAddr() - addrRange.start) + { + case 0x0: + warn("Reading from timer 0 counter.\n"); + break; + case 0x1: + warn("Reading from timer 1 counter.\n"); + break; + case 0x2: + warn("Reading from timer 2 counter.\n"); + break; + case 0x3: + fatal("Reading from timer control word which is read only.\n"); + break; + default: + panic("Read from undefined i8254 register.\n"); + } + return SubDevice::read(pkt); +} + +Tick +X86ISA::I8254::write(PacketPtr pkt) +{ + assert(pkt->getSize() == 1); + switch(pkt->getAddr() - addrRange.start) + { + case 0x0: + warn("Writing to timer 0 counter.\n"); + break; + case 0x1: + warn("Writing to timer 1 counter.\n"); + break; + case 0x2: + warn("Writing to timer 2 counter.\n"); + break; + case 0x3: + processControlWord(pkt->get()); + return latency; + default: + panic("Write to undefined i8254 register.\n"); + } + return SubDevice::write(pkt); +} + +void +X86ISA::I8254::processControlWord(uint8_t word) +{ + warn("I8254 received control word %x.\n", word); +} diff --git a/src/dev/x86/south_bridge/i8254.hh b/src/dev/x86/south_bridge/i8254.hh new file mode 100644 index 000000000..f246fd8e4 --- /dev/null +++ b/src/dev/x86/south_bridge/i8254.hh @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __DEV_X86_SOUTH_BRIDGE_I8254_HH__ +#define __DEV_X86_SOUTH_BRIDGE_I8254_HH__ + +#include "arch/x86/x86_traits.hh" +#include "base/range.hh" +#include "dev/x86/south_bridge/sub_device.hh" + +namespace X86ISA +{ + +class I8254 : public SubDevice +{ + protected: + void processControlWord(uint8_t word); + + public: + + I8254() + {} + I8254(Tick _latency) : SubDevice(_latency) + {} + I8254(Addr start, Addr size, Tick _latency) : + SubDevice(start, size, _latency) + {} + + Tick read(PacketPtr pkt); + + Tick write(PacketPtr pkt); +}; + +}; // namespace X86ISA + +#endif //__DEV_X86_SOUTH_BRIDGE_I8254_HH__ diff --git a/src/dev/x86/south_bridge/i8259.cc b/src/dev/x86/south_bridge/i8259.cc new file mode 100644 index 000000000..0cf83dece --- /dev/null +++ b/src/dev/x86/south_bridge/i8259.cc @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "dev/x86/south_bridge/i8259.hh" + +Tick +X86ISA::I8259::read(PacketPtr pkt) +{ + warn("Reading from PIC device.\n"); + return SubDevice::read(pkt); +} + +Tick +X86ISA::I8259::write(PacketPtr pkt) +{ + warn("Writing to PIC device.\n"); + return SubDevice::write(pkt); +} diff --git a/src/dev/x86/south_bridge/i8259.hh b/src/dev/x86/south_bridge/i8259.hh new file mode 100644 index 000000000..3fda75dfb --- /dev/null +++ b/src/dev/x86/south_bridge/i8259.hh @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __DEV_X86_SOUTH_BRIDGE_I8259_HH__ +#define __DEV_X86_SOUTH_BRIDGE_I8259_HH__ + +#include "arch/x86/x86_traits.hh" +#include "base/range.hh" +#include "dev/x86/south_bridge/sub_device.hh" + +namespace X86ISA +{ + +class I8259 : public SubDevice +{ + public: + + I8259() + {} + I8259(Tick _latency) : SubDevice(_latency) + {} + I8259(Addr start, Addr size, Tick _latency) : + SubDevice(start, size, _latency) + {} + + Tick read(PacketPtr pkt); + + Tick write(PacketPtr pkt); +}; + +}; // namespace X86ISA + +#endif //__DEV_X86_SOUTH_BRIDGE_I8259_HH__ diff --git a/src/dev/x86/south_bridge/south_bridge.cc b/src/dev/x86/south_bridge/south_bridge.cc new file mode 100644 index 000000000..f25b3b811 --- /dev/null +++ b/src/dev/x86/south_bridge/south_bridge.cc @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/x86/x86_traits.hh" +#include "base/range.hh" +#include "dev/x86/south_bridge/south_bridge.hh" + +using namespace X86ISA; + +void +SouthBridge::addDevice(X86ISA::SubDevice & sub) +{ + rangeList.push_back(sub.addrRange); + rangeMap.insert(sub.addrRange, &sub); +} + +void +SouthBridge::addressRanges(AddrRangeList &range_list) +{ + range_list = rangeList; +} + +Tick +SouthBridge::read(PacketPtr pkt) +{ + RangeMapIt sub = + rangeMap.find(RangeSize(pkt->getAddr(), 1)); + assert(sub != rangeMap.end()); + return sub->second->read(pkt); +} + +Tick +SouthBridge::write(PacketPtr pkt) +{ + RangeMapIt sub = + rangeMap.find(RangeSize(pkt->getAddr(), 1)); + assert(sub != rangeMap.end()); + return sub->second->write(pkt); +} + +SouthBridge::SouthBridge(const Params *p) : PioDevice(p), + pic1(0x20, 2, p->pio_latency), + pic2(0xA0, 2, p->pio_latency), + pit(0x40, 4, p->pio_latency), + cmos(0x70, 2, p->pio_latency), + speaker(0x61, 1, p->pio_latency) +{ + addDevice(pic1); + addDevice(pic2); + addDevice(pit); + addDevice(cmos); + addDevice(speaker); +} + +SouthBridge * +SouthBridgeParams::create() +{ + return new SouthBridge(this); +} diff --git a/src/dev/x86/south_bridge/south_bridge.hh b/src/dev/x86/south_bridge/south_bridge.hh new file mode 100644 index 000000000..28936fb91 --- /dev/null +++ b/src/dev/x86/south_bridge/south_bridge.hh @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __DEV_X86_SOUTH_BRIDGE_SOUTH_BRIDGE_HH__ +#define __DEV_X86_SOUTH_BRIDGE_SOUTH_BRIDGE_HH__ + +#include "base/range_map.hh" +#include "dev/io_device.hh" +#include "dev/x86/south_bridge/cmos.hh" +#include "dev/x86/south_bridge/i8254.hh" +#include "dev/x86/south_bridge/i8259.hh" +#include "dev/x86/south_bridge/speaker.hh" +#include "dev/x86/south_bridge/sub_device.hh" +#include "params/SouthBridge.hh" + +class SouthBridge : public PioDevice +{ + protected: + // PICs + X86ISA::I8259 pic1; + X86ISA::I8259 pic2; + + // I8254 Programmable Interval Timer + X86ISA::I8254 pit; + + // CMOS apperature + X86ISA::Cmos cmos; + + // PC speaker + X86ISA::Speaker speaker; + + AddrRangeList rangeList; + + typedef range_map RangeMap; + typedef RangeMap::iterator RangeMapIt; + RangeMap rangeMap; + + + void addDevice(X86ISA::SubDevice &); + + public: + void addressRanges(AddrRangeList &range_list); + + Tick read(PacketPtr pkt); + Tick write(PacketPtr pkt); + + typedef SouthBridgeParams Params; + SouthBridge(const Params *p); + + const Params * + params() const + { + return dynamic_cast(_params); + } +}; + +#endif //__DEV_X86_SOUTH_BRIDGE_SOUTH_BRIDGE_HH__ diff --git a/src/dev/x86/south_bridge/speaker.cc b/src/dev/x86/south_bridge/speaker.cc new file mode 100644 index 000000000..734dba4c2 --- /dev/null +++ b/src/dev/x86/south_bridge/speaker.cc @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "base/bitunion.hh" +#include "dev/x86/south_bridge/speaker.hh" +#include "mem/packet_access.hh" + +BitUnion8(SpeakerControl) + Bitfield<0> gate; + Bitfield<1> speaker; + Bitfield<5> timer; +EndBitUnion(SpeakerControl) + +Tick +X86ISA::Speaker::read(PacketPtr pkt) +{ + assert(pkt->getAddr() == addrRange.start); + assert(pkt->getSize() == 1); + SpeakerControl val = 0xFF; + warn("Reading from speaker device: gate %s, speaker %s, output %s.\n", + val.gate ? "on" : "off", + val.speaker ? "on" : "off", + val.timer ? "on" : "off"); + pkt->set((uint8_t)val); + return latency; +} + +Tick +X86ISA::Speaker::write(PacketPtr pkt) +{ + assert(pkt->getAddr() == addrRange.start); + assert(pkt->getSize() == 1); + SpeakerControl val = pkt->get(); + warn("Writing to speaker device: gate %s, speaker %s.\n", + val.gate ? "on" : "off", val.speaker ? "on" : "off"); + return latency; +} diff --git a/src/dev/x86/south_bridge/speaker.hh b/src/dev/x86/south_bridge/speaker.hh new file mode 100644 index 000000000..df738e42b --- /dev/null +++ b/src/dev/x86/south_bridge/speaker.hh @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __DEV_X86_SOUTH_BRIDGE_SPEAKER_HH__ +#define __DEV_X86_SOUTH_BRIDGE_SPEAKER_HH__ + +#include "arch/x86/x86_traits.hh" +#include "base/range.hh" +#include "dev/x86/south_bridge/sub_device.hh" + +namespace X86ISA +{ + +class Speaker : public SubDevice +{ + public: + + Speaker() + {} + Speaker(Tick _latency) : SubDevice(_latency) + {} + Speaker(Addr start, Addr size, Tick _latency) : + SubDevice(start, size, _latency) + {} + + Tick read(PacketPtr pkt); + + Tick write(PacketPtr pkt); +}; + +}; // namespace X86ISA + +#endif //__DEV_X86_SOUTH_BRIDGE_SPEAKER_HH__ diff --git a/src/dev/x86/south_bridge/sub_device.hh b/src/dev/x86/south_bridge/sub_device.hh new file mode 100644 index 000000000..3cc51bdd9 --- /dev/null +++ b/src/dev/x86/south_bridge/sub_device.hh @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __DEV_X86_SOUTH_BRIDGE_SUB_DEVICE_HH__ +#define __DEV_X86_SOUTH_BRIDGE_SUB_DEVICE_HH__ + +#include "arch/x86/x86_traits.hh" +#include "base/range.hh" +#include "mem/packet.hh" + +namespace X86ISA +{ + +class SubDevice +{ + public: + + Range addrRange; + Tick latency; + + virtual + ~SubDevice() + {} + + SubDevice() + {} + SubDevice(Tick _latency) : latency(_latency) + {} + SubDevice(Addr start, Addr size, Tick _latency) : + addrRange(RangeSize(x86IOAddress(start), size)), latency(_latency) + {} + + virtual Tick + read(PacketPtr pkt) + { + assert(pkt->getSize() <= 4); + pkt->allocate(); + const uint32_t neg1 = -1; + pkt->setData((uint8_t *)(&neg1)); + return latency; + } + + virtual Tick + write(PacketPtr pkt) + { + return latency; + } +}; + +}; // namespace X86ISA + +#endif //__DEV_X86_SOUTH_BRIDGE_SUB_DEVICE_HH__ -- cgit v1.2.3 From af9a57566afae30b4739b37fe1fa7048cbca9a85 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 25 Mar 2008 02:09:18 -0400 Subject: X86: Turn #defines into consts. --HG-- extra : convert_revision : c0416de5d88ca39f54494418768e68a93aa4f2aa --- src/dev/rtcreg.h | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/dev/rtcreg.h b/src/dev/rtcreg.h index 37255777b..b1406c464 100644 --- a/src/dev/rtcreg.h +++ b/src/dev/rtcreg.h @@ -30,32 +30,32 @@ * Nathan Binkert */ -#define RTC_SEC 0x00 -#define RTC_SEC_ALRM 0x01 -#define RTC_MIN 0x02 -#define RTC_MIN_ALRM 0x03 -#define RTC_HR 0x04 -#define RTC_HR_ALRM 0x05 -#define RTC_DOW 0x06 -#define RTC_DOM 0x07 -#define RTC_MON 0x08 -#define RTC_YEAR 0x09 +static const int RTC_SEC = 0x00; +static const int RTC_SEC_ALRM = 0x01; +static const int RTC_MIN = 0x02; +static const int RTC_MIN_ALRM = 0x03; +static const int RTC_HR = 0x04; +static const int RTC_HR_ALRM = 0x05; +static const int RTC_DOW = 0x06; +static const int RTC_DOM = 0x07; +static const int RTC_MON = 0x08; +static const int RTC_YEAR = 0x09; -#define RTC_STAT_REGA 0x0A -#define RTCA_1024HZ 0x06 /* 1024Hz periodic interrupt frequency */ -#define RTCA_32768HZ 0x20 /* 22-stage divider, 32.768KHz timebase */ -#define RTCA_UIP 0x80 /* 1 = date and time update in progress */ +static const int RTC_STAT_REGA = 0x0A; +static const int RTCA_1024HZ = 0x06; /* 1024Hz periodic interrupt frequency */ +static const int RTCA_32768HZ = 0x20; /* 22-stage divider, 32.768KHz timebase */ +static const int RTCA_UIP = 0x80; /* 1 = date and time update in progress */ -#define RTC_STAT_REGB 0x0B -#define RTCB_DST 0x01 /* USA Daylight Savings Time enable */ -#define RTCB_24HR 0x02 /* 0 = 12 hours, 1 = 24 hours */ -#define RTCB_BIN 0x04 /* 0 = BCD, 1 = Binary coded time */ -#define RTCB_SQWE 0x08 /* 1 = output sqare wave at SQW pin */ -#define RTCB_UPDT_IE 0x10 /* 1 = enable update-ended interrupt */ -#define RTCB_ALRM_IE 0x20 /* 1 = enable alarm interrupt */ -#define RTCB_PRDC_IE 0x40 /* 1 = enable periodic clock interrupt */ -#define RTCB_NO_UPDT 0x80 /* stop clock updates */ +static const int RTC_STAT_REGB = 0x0B; +static const int RTCB_DST = 0x01; /* USA Daylight Savings Time enable */ +static const int RTCB_24HR = 0x02; /* 0 = 12 hours, 1 = 24 hours */ +static const int RTCB_BIN = 0x04; /* 0 = BCD, 1 = Binary coded time */ +static const int RTCB_SQWE = 0x08; /* 1 = output sqare wave at SQW pin */ +static const int RTCB_UPDT_IE = 0x10; /* 1 = enable update-ended interrupt */ +static const int RTCB_ALRM_IE = 0x20; /* 1 = enable alarm interrupt */ +static const int RTCB_PRDC_IE = 0x40; /* 1 = enable periodic clock interrupt */ +static const int RTCB_NO_UPDT = 0x80; /* stop clock updates */ -#define RTC_STAT_REGC 0x0C -#define RTC_STAT_REGD 0x0D +static const int RTC_STAT_REGC = 0x0C; +static const int RTC_STAT_REGD = 0x0D; -- cgit v1.2.3 From e5bdae15f3651d8f0fc63e483e73e8ea742135e3 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 25 Mar 2008 02:15:06 -0400 Subject: Devices: Separate out the MC146818 RTC so both Alpha and X86 can use it. --HG-- extra : convert_revision : 1e7f5185654ed0845678c2169c702d3b977159ed --- src/dev/SConscript | 2 + src/dev/alpha/SConscript | 1 - src/dev/alpha/tsunami_io.cc | 162 ++------------------------------------ src/dev/alpha/tsunami_io.hh | 97 ++++------------------- src/dev/mc146818.cc | 184 ++++++++++++++++++++++++++++++++++++++++++++ src/dev/mc146818.hh | 128 ++++++++++++++++++++++++++++++ 6 files changed, 336 insertions(+), 238 deletions(-) create mode 100644 src/dev/mc146818.cc create mode 100644 src/dev/mc146818.hh (limited to 'src') diff --git a/src/dev/SConscript b/src/dev/SConscript index 0aba8ac35..ee7adb8c8 100644 --- a/src/dev/SConscript +++ b/src/dev/SConscript @@ -56,6 +56,7 @@ if env['FULL_SYSTEM']: Source('ide_disk.cc') Source('io_device.cc') Source('isa_fake.cc') + Source('mc146818.cc') Source('ns_gige.cc') Source('pciconfigall.cc') Source('pcidev.cc') @@ -84,6 +85,7 @@ if env['FULL_SYSTEM']: TraceFlag('IdeCtrl') TraceFlag('IdeDisk') TraceFlag('IsaFake') + TraceFlag('MC146818') TraceFlag('PCIDEV') TraceFlag('PciConfigAll') TraceFlag('SimpleDisk') diff --git a/src/dev/alpha/SConscript b/src/dev/alpha/SConscript index 2292c3c57..6bd26a9b1 100644 --- a/src/dev/alpha/SConscript +++ b/src/dev/alpha/SConscript @@ -42,5 +42,4 @@ if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'alpha': Source('tsunami_pchip.cc') TraceFlag('AlphaConsole') - TraceFlag('MC146818') TraceFlag('Tsunami') diff --git a/src/dev/alpha/tsunami_io.cc b/src/dev/alpha/tsunami_io.cc index 710aca48d..88999ecc5 100644 --- a/src/dev/alpha/tsunami_io.cc +++ b/src/dev/alpha/tsunami_io.cc @@ -57,157 +57,9 @@ using namespace std; //Should this be AlphaISA? using namespace TheISA; -TsunamiIO::RTC::RTC(const string &n, Tsunami* tsunami, - const TsunamiIO::Params *p) - : _name(n), event(tsunami, p->frequency), addr(0) +TsunamiIO::TsunamiRTC::TsunamiRTC(const string &n, const TsunamiIOParams *p) : + MC146818(n, p->time, p->year_is_bcd, p->frequency), tsunami(p->tsunami) { - memset(clock_data, 0, sizeof(clock_data)); - stat_regA = RTCA_32768HZ | RTCA_1024HZ; - stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR; - - year = p->time.tm_year; - - if (p->year_is_bcd) { - // The datasheet says that the year field can be either BCD or - // years since 1900. Linux seems to be happy with years since - // 1900. - year = year % 100; - int tens = year / 10; - int ones = year % 10; - year = (tens << 4) + ones; - } - - // Unix is 0-11 for month, data seet says start at 1 - mon = p->time.tm_mon + 1; - mday = p->time.tm_mday; - hour = p->time.tm_hour; - min = p->time.tm_min; - sec = p->time.tm_sec; - - // Datasheet says 1 is sunday - wday = p->time.tm_wday + 1; - - DPRINTFN("Real-time clock set to %s", asctime(&p->time)); -} - -void -TsunamiIO::RTC::writeAddr(const uint8_t data) -{ - if (data <= RTC_STAT_REGD) - addr = data; - else - panic("RTC addresses over 0xD are not implemented.\n"); -} - -void -TsunamiIO::RTC::writeData(const uint8_t data) -{ - if (addr < RTC_STAT_REGA) - clock_data[addr] = data; - else { - switch (addr) { - case RTC_STAT_REGA: - if (data != (RTCA_32768HZ | RTCA_1024HZ)) - panic("Unimplemented RTC register A value write!\n"); - stat_regA = data; - break; - case RTC_STAT_REGB: - if ((data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR)) - panic("Write to RTC reg B bits that are not implemented!\n"); - - if (data & RTCB_PRDC_IE) { - if (!event.scheduled()) - event.scheduleIntr(); - } else { - if (event.scheduled()) - event.deschedule(); - } - stat_regB = data; - break; - case RTC_STAT_REGC: - case RTC_STAT_REGD: - panic("RTC status registers C and D are not implemented.\n"); - break; - } - } -} - -uint8_t -TsunamiIO::RTC::readData() -{ - if (addr < RTC_STAT_REGA) - return clock_data[addr]; - else { - switch (addr) { - case RTC_STAT_REGA: - // toggle UIP bit for linux - stat_regA ^= RTCA_UIP; - return stat_regA; - break; - case RTC_STAT_REGB: - return stat_regB; - break; - case RTC_STAT_REGC: - case RTC_STAT_REGD: - return 0x00; - break; - default: - panic("Shouldn't be here"); - } - } -} - -void -TsunamiIO::RTC::serialize(const string &base, ostream &os) -{ - paramOut(os, base + ".addr", addr); - arrayParamOut(os, base + ".clock_data", clock_data, sizeof(clock_data)); - paramOut(os, base + ".stat_regA", stat_regA); - paramOut(os, base + ".stat_regB", stat_regB); -} - -void -TsunamiIO::RTC::unserialize(const string &base, Checkpoint *cp, - const string §ion) -{ - paramIn(cp, section, base + ".addr", addr); - arrayParamIn(cp, section, base + ".clock_data", clock_data, - sizeof(clock_data)); - paramIn(cp, section, base + ".stat_regA", stat_regA); - paramIn(cp, section, base + ".stat_regB", stat_regB); - - // We're not unserializing the event here, but we need to - // rescehedule the event since curTick was moved forward by the - // checkpoint - event.reschedule(curTick + event.interval); -} - -TsunamiIO::RTC::RTCEvent::RTCEvent(Tsunami*t, Tick i) - : Event(&mainEventQueue), tsunami(t), interval(i) -{ - DPRINTF(MC146818, "RTC Event Initilizing\n"); - schedule(curTick + interval); -} - -void -TsunamiIO::RTC::RTCEvent::scheduleIntr() -{ - schedule(curTick + interval); -} - -void -TsunamiIO::RTC::RTCEvent::process() -{ - DPRINTF(MC146818, "RTC Timer Interrupt\n"); - schedule(curTick + interval); - //Actually interrupt the processor here - tsunami->cchip->postRTC(); -} - -const char * -TsunamiIO::RTC::RTCEvent::description() const -{ - return "tsunami RTC interrupt"; } TsunamiIO::PITimer::PITimer(const string &name) @@ -436,7 +288,7 @@ TsunamiIO::PITimer::Counter::CounterEvent::description() const TsunamiIO::TsunamiIO(const Params *p) : BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"), - rtc(p->name + ".rtc", p->tsunami, p) + rtc(p->name + ".rtc", p) { pioSize = 0x100; @@ -495,7 +347,7 @@ TsunamiIO::read(PacketPtr pkt) pkt->set(pitimer.counter2.read()); break; case TSDEV_RTC_DATA: - pkt->set(rtc.readData()); + pkt->set(rtc.readData(rtcAddr)); break; case TSDEV_CTRL_PORTB: if (pitimer.counter2.outputHigh()) @@ -573,10 +425,10 @@ TsunamiIO::write(PacketPtr pkt) pitimer.writeControl(pkt->get()); break; case TSDEV_RTC_ADDR: - rtc.writeAddr(pkt->get()); + rtcAddr = pkt->get(); break; case TSDEV_RTC_DATA: - rtc.writeData(pkt->get()); + rtc.writeData(rtcAddr, pkt->get()); break; case TSDEV_KBD: case TSDEV_DMA1_CMND: @@ -623,6 +475,7 @@ TsunamiIO::clearPIC(uint8_t bitvector) void TsunamiIO::serialize(ostream &os) { + SERIALIZE_SCALAR(rtcAddr); SERIALIZE_SCALAR(timerData); SERIALIZE_SCALAR(mask1); SERIALIZE_SCALAR(mask2); @@ -639,6 +492,7 @@ TsunamiIO::serialize(ostream &os) void TsunamiIO::unserialize(Checkpoint *cp, const string §ion) { + UNSERIALIZE_SCALAR(rtcAddr); UNSERIALIZE_SCALAR(timerData); UNSERIALIZE_SCALAR(mask1); UNSERIALIZE_SCALAR(mask2); diff --git a/src/dev/alpha/tsunami_io.hh b/src/dev/alpha/tsunami_io.hh index 05c4ee910..3972efa48 100644 --- a/src/dev/alpha/tsunami_io.hh +++ b/src/dev/alpha/tsunami_io.hh @@ -39,6 +39,7 @@ #include "base/range.hh" #include "dev/alpha/tsunami.hh" +#include "dev/mc146818.hh" #include "dev/io_device.hh" #include "params/TsunamiIO.hh" #include "sim/eventq.hh" @@ -53,91 +54,19 @@ class TsunamiIO : public BasicPioDevice struct tm tm; protected: - /** Real-Time Clock (MC146818) */ - class RTC - { - private: - /** Event for RTC periodic interrupt */ - struct RTCEvent : public Event - { - /** A pointer back to tsunami to create interrupt the processor. */ - Tsunami* tsunami; - Tick interval; - - RTCEvent(Tsunami* t, Tick i); - - /** Schedule the RTC periodic interrupt */ - void scheduleIntr(); - - /** Event process to occur at interrupt*/ - virtual void process(); - - /** Event description */ - virtual const char *description() const; - }; - - private: - std::string _name; - const std::string &name() const { return _name; } - - /** RTC periodic interrupt event */ - RTCEvent event; - - /** Current RTC register address/index */ - int addr; - - /** Data for real-time clock function */ - union { - uint8_t clock_data[10]; - - struct { - uint8_t sec; - uint8_t sec_alrm; - uint8_t min; - uint8_t min_alrm; - uint8_t hour; - uint8_t hour_alrm; - uint8_t wday; - uint8_t mday; - uint8_t mon; - uint8_t year; - }; - }; - - /** RTC status register A */ - uint8_t stat_regA; - - /** RTC status register B */ - uint8_t stat_regB; + class TsunamiRTC : public MC146818 + { public: - RTC(const std::string &name, Tsunami* tsunami, - const TsunamiIOParams *params); - - /** RTC address port: write address of RTC RAM data to access */ - void writeAddr(const uint8_t data); - - /** RTC write data */ - void writeData(const uint8_t data); - - /** RTC read data */ - uint8_t readData(); + Tsunami * tsunami; + TsunamiRTC(const std::string &n, const TsunamiIOParams *p); - /** - * Serialize this object to the given output stream. - * @param base The base name of the counter object. - * @param os The stream to serialize to. - */ - void serialize(const std::string &base, std::ostream &os); - - /** - * Reconstruct the state of this object from a checkpoint. - * @param base The base name of the counter object. - * @param cp The checkpoint use. - * @param section The section name of this object - */ - void unserialize(const std::string &base, Checkpoint *cp, - const std::string §ion); + protected: + void handleEvent() + { + //Actually interrupt the processor here + tsunami->cchip->postRTC(); + } }; /** Programmable Interval Timer (Intel 8254) */ @@ -296,7 +225,9 @@ class TsunamiIO : public BasicPioDevice /** Intel 8253 Periodic Interval Timer */ PITimer pitimer; - RTC rtc; + TsunamiRTC rtc; + + uint8_t rtcAddr; /** The interval is set via two writes to the PIT. * This variable contains a flag as to how many writes have happened, and diff --git a/src/dev/mc146818.cc b/src/dev/mc146818.cc new file mode 100644 index 000000000..984422105 --- /dev/null +++ b/src/dev/mc146818.cc @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + * Andrew Schultz + * Miguel Serrano + */ + +#include +#include + +#include + +#include "base/time.hh" +#include "base/trace.hh" +#include "dev/mc146818.hh" +#include "dev/rtcreg.h" + +using namespace std; + +MC146818::MC146818(const string &n, const struct tm time, + bool bcd, Tick frequency) + : _name(n), event(this, frequency) +{ + memset(clock_data, 0, sizeof(clock_data)); + stat_regA = RTCA_32768HZ | RTCA_1024HZ; + stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR; + + year = time.tm_year; + + if (bcd) { + // The datasheet says that the year field can be either BCD or + // years since 1900. Linux seems to be happy with years since + // 1900. + year = year % 100; + int tens = year / 10; + int ones = year % 10; + year = (tens << 4) + ones; + } + + // Unix is 0-11 for month, data seet says start at 1 + mon = time.tm_mon + 1; + mday = time.tm_mday; + hour = time.tm_hour; + min = time.tm_min; + sec = time.tm_sec; + + // Datasheet says 1 is sunday + wday = time.tm_wday + 1; + + DPRINTFN("Real-time clock set to %s", asctime(&time)); +} + +void +MC146818::writeData(const uint8_t addr, const uint8_t data) +{ + if (addr < RTC_STAT_REGA) + clock_data[addr] = data; + else { + switch (addr) { + case RTC_STAT_REGA: + if (data != (RTCA_32768HZ | RTCA_1024HZ)) + panic("Unimplemented RTC register A value write!\n"); + stat_regA = data; + break; + case RTC_STAT_REGB: + if ((data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR)) + panic("Write to RTC reg B bits that are not implemented!\n"); + + if (data & RTCB_PRDC_IE) { + if (!event.scheduled()) + event.scheduleIntr(); + } else { + if (event.scheduled()) + event.deschedule(); + } + stat_regB = data; + break; + case RTC_STAT_REGC: + case RTC_STAT_REGD: + panic("RTC status registers C and D are not implemented.\n"); + break; + } + } +} + +uint8_t +MC146818::readData(uint8_t addr) +{ + if (addr < RTC_STAT_REGA) + return clock_data[addr]; + else { + switch (addr) { + case RTC_STAT_REGA: + // toggle UIP bit for linux + stat_regA ^= RTCA_UIP; + return stat_regA; + break; + case RTC_STAT_REGB: + return stat_regB; + break; + case RTC_STAT_REGC: + case RTC_STAT_REGD: + return 0x00; + break; + default: + panic("Shouldn't be here"); + } + } +} + +void +MC146818::serialize(const string &base, ostream &os) +{ + arrayParamOut(os, base + ".clock_data", clock_data, sizeof(clock_data)); + paramOut(os, base + ".stat_regA", stat_regA); + paramOut(os, base + ".stat_regB", stat_regB); +} + +void +MC146818::unserialize(const string &base, Checkpoint *cp, + const string §ion) +{ + arrayParamIn(cp, section, base + ".clock_data", clock_data, + sizeof(clock_data)); + paramIn(cp, section, base + ".stat_regA", stat_regA); + paramIn(cp, section, base + ".stat_regB", stat_regB); + + // We're not unserializing the event here, but we need to + // rescehedule the event since curTick was moved forward by the + // checkpoint + event.reschedule(curTick + event.interval); +} + +MC146818::RTCEvent::RTCEvent(MC146818 * _parent, Tick i) + : Event(&mainEventQueue), parent(_parent), interval(i) +{ + DPRINTF(MC146818, "RTC Event Initilizing\n"); + schedule(curTick + interval); +} + +void +MC146818::RTCEvent::scheduleIntr() +{ + schedule(curTick + interval); +} + +void +MC146818::RTCEvent::process() +{ + DPRINTF(MC146818, "RTC Timer Interrupt\n"); + schedule(curTick + interval); + parent->handleEvent(); +} + +const char * +MC146818::RTCEvent::description() const +{ + return "RTC interrupt"; +} diff --git a/src/dev/mc146818.hh b/src/dev/mc146818.hh new file mode 100644 index 000000000..f91e462d9 --- /dev/null +++ b/src/dev/mc146818.hh @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + * Andrew Schultz + * Miguel Serrano + */ + +#ifndef __DEV_MC146818_HH__ +#define __DEV_MC146818_HH__ + +#include "base/range.hh" +#include "sim/eventq.hh" + +/** Real-Time Clock (MC146818) */ +class MC146818 +{ + protected: + virtual void handleEvent() + { + warn("No RTC event handler defined.\n"); + } + + private: + /** Event for RTC periodic interrupt */ + struct RTCEvent : public Event + { + MC146818 * parent; + Tick interval; + + RTCEvent(MC146818 * _parent, Tick i); + + /** Schedule the RTC periodic interrupt */ + void scheduleIntr(); + + /** Event process to occur at interrupt*/ + virtual void process(); + + /** Event description */ + virtual const char *description() const; + }; + + private: + std::string _name; + const std::string &name() const { return _name; } + + /** RTC periodic interrupt event */ + RTCEvent event; + + /** Data for real-time clock function */ + union { + uint8_t clock_data[10]; + + struct { + uint8_t sec; + uint8_t sec_alrm; + uint8_t min; + uint8_t min_alrm; + uint8_t hour; + uint8_t hour_alrm; + uint8_t wday; + uint8_t mday; + uint8_t mon; + uint8_t year; + }; + }; + + /** RTC status register A */ + uint8_t stat_regA; + + /** RTC status register B */ + uint8_t stat_regB; + + public: + virtual ~MC146818() + {} + + MC146818(const std::string &name, const struct tm time, + bool bcd, Tick frequency); + + /** RTC write data */ + void writeData(const uint8_t addr, const uint8_t data); + + /** RTC read data */ + uint8_t readData(const uint8_t addr); + + /** + * Serialize this object to the given output stream. + * @param base The base name of the counter object. + * @param os The stream to serialize to. + */ + void serialize(const std::string &base, std::ostream &os); + + /** + * Reconstruct the state of this object from a checkpoint. + * @param base The base name of the counter object. + * @param cp The checkpoint use. + * @param section The section name of this object + */ + void unserialize(const std::string &base, Checkpoint *cp, + const std::string §ion); +}; + +#endif // __DEV_MC146818_HH__ -- cgit v1.2.3 From 93dd1978a7750ba7cce04ae4401f5c6689290038 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 25 Mar 2008 02:15:23 -0400 Subject: X86: Put an RTC into the CMOS part of the southbridge. --HG-- extra : convert_revision : a614373236fe75db6e6181fc152a02b541a131f3 --- src/dev/x86/south_bridge/cmos.cc | 47 ++++++---------------------------------- src/dev/x86/south_bridge/cmos.hh | 25 ++++++++++++++++++--- 2 files changed, 29 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/dev/x86/south_bridge/cmos.cc b/src/dev/x86/south_bridge/cmos.cc index 43ada42e8..164b23d84 100644 --- a/src/dev/x86/south_bridge/cmos.cc +++ b/src/dev/x86/south_bridge/cmos.cc @@ -71,27 +71,10 @@ uint8_t X86ISA::Cmos::readRegister(uint8_t reg) { assert(reg < numRegs); - switch(reg) - { - case 0x0: - case 0x1: - case 0x2: - case 0x3: - case 0x4: - case 0x5: - case 0x6: - case 0x7: - case 0x8: - case 0x9: - case 0xA: - case 0xB: - case 0xC: - case 0xD: - warn("Reading RTC in the CMOS.\n"); - break; - default: + if (reg <= 0xD) { + return rtc.readData(reg); + } else { warn("Reading non-volitile CMOS address %x as %x.\n", reg, regs[reg]); - break; } return regs[reg]; } @@ -100,27 +83,11 @@ void X86ISA::Cmos::writeRegister(uint8_t reg, uint8_t val) { assert(reg < numRegs); - switch(reg) - { - case 0x0: - case 0x1: - case 0x2: - case 0x3: - case 0x4: - case 0x5: - case 0x6: - case 0x7: - case 0x8: - case 0x9: - case 0xA: - case 0xB: - case 0xC: - case 0xD: - warn("Writing RTC in the CMOS.\n"); - break; - default: + if (reg <= 0xD) { + rtc.writeData(reg, val); + return; + } else { warn("Writing non-volitile CMOS address %x with %x.\n", reg, val); - break; } regs[reg] = val; } diff --git a/src/dev/x86/south_bridge/cmos.hh b/src/dev/x86/south_bridge/cmos.hh index cd3fab280..6fd7613bc 100644 --- a/src/dev/x86/south_bridge/cmos.hh +++ b/src/dev/x86/south_bridge/cmos.hh @@ -33,6 +33,7 @@ #include "arch/x86/x86_traits.hh" #include "base/range.hh" +#include "dev/mc146818.hh" #include "dev/x86/south_bridge/sub_device.hh" namespace X86ISA @@ -43,6 +44,8 @@ class Cmos : public SubDevice protected: uint8_t address; + struct tm foo_time; + static const int numRegs = 128; uint8_t regs[numRegs]; @@ -50,22 +53,38 @@ class Cmos : public SubDevice uint8_t readRegister(uint8_t reg); void writeRegister(uint8_t reg, uint8_t val); + class X86RTC : public MC146818 + { + public: + X86RTC(const std::string &n, const struct tm time, + bool bcd, Tick frequency) : MC146818(n, time, bcd, frequency) + { + } + protected: + void handleEvent() + { + return; + } + } rtc; + public: - Cmos() + Cmos() : rtc("rtc", foo_time, true, 5000000000) { memset(regs, 0, numRegs * sizeof(uint8_t)); address = 0; } - Cmos(Tick _latency) : SubDevice(_latency) + Cmos(Tick _latency) : SubDevice(_latency), + rtc("rtc", foo_time, true, 5000000000) { memset(regs, 0, numRegs * sizeof(uint8_t)); address = 0; } Cmos(Addr start, Addr size, Tick _latency) : - SubDevice(start, size, _latency) + SubDevice(start, size, _latency), + rtc("rtc", foo_time, true, 5000000000) { memset(regs, 0, numRegs * sizeof(uint8_t)); address = 0; -- cgit v1.2.3 From 29be31ce3139c36f596e6edafbd3d253ee2200b3 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Tue, 25 Mar 2008 10:01:21 -0400 Subject: Fix handling of writeback-induced writebacks in atomic mode. --HG-- extra : convert_revision : 4fa64f8a929f1aa36a9d5a71b8d1816b497aca4c --- src/mem/cache/cache.hh | 3 ++- src/mem/cache/cache_impl.hh | 50 ++++++++++++++++++++------------------------- 2 files changed, 24 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh index f5f65d4dd..88c9deb7b 100644 --- a/src/mem/cache/cache.hh +++ b/src/mem/cache/cache.hh @@ -162,7 +162,8 @@ class Cache : public BaseCache * @return Pointer to the cache block touched by the request. NULL if it * was a miss. */ - bool access(PacketPtr pkt, BlkType *&blk, int &lat); + bool access(PacketPtr pkt, BlkType *&blk, + int &lat, PacketList &writebacks); /** *Handle doing the Compare and Swap function for SPARC. diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 47d20f915..7bab3012b 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -260,7 +260,8 @@ Cache::squash(int threadNum) template bool -Cache::access(PacketPtr pkt, BlkType *&blk, int &lat) +Cache::access(PacketPtr pkt, BlkType *&blk, + int &lat, PacketList &writebacks) { if (pkt->req->isUncacheable()) { blk = NULL; @@ -308,7 +309,6 @@ Cache::access(PacketPtr pkt, BlkType *&blk, int &lat) // into the cache without having a writeable copy (or any copy at // all). if (pkt->cmd == MemCmd::Writeback) { - PacketList writebacks; assert(blkSize == pkt->getSize()); if (blk == NULL) { // need to do a replacement @@ -323,12 +323,6 @@ Cache::access(PacketPtr pkt, BlkType *&blk, int &lat) } std::memcpy(blk->data, pkt->getPtr(), blkSize); blk->status |= BlkDirty; - // copy writebacks from replacement to write buffer - while (!writebacks.empty()) { - PacketPtr wbPkt = writebacks.front(); - allocateWriteBuffer(wbPkt, curTick + hitLatency, true); - writebacks.pop_front(); - } // nothing else to do; writeback doesn't expect response assert(!pkt->needsResponse()); hits[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++; @@ -427,13 +421,13 @@ Cache::timingAccess(PacketPtr pkt) int lat = hitLatency; BlkType *blk = NULL; - bool satisfied = access(pkt, blk, lat); + PacketList writebacks; + + bool satisfied = access(pkt, blk, lat, writebacks); #if 0 /** @todo make the fast write alloc (wh64) work with coherence. */ - PacketList writebacks; - // If this is a block size write/hint (WH64) allocate the block here // if the coherence protocol allows it. if (!blk && pkt->getSize() >= blkSize && coherence->allowFastWrites() && @@ -451,13 +445,6 @@ Cache::timingAccess(PacketPtr pkt) ++fastWrites; } } - - // copy writebacks to write buffer - while (!writebacks.empty()) { - PacketPtr wbPkt = writebacks.front(); - allocateWriteBuffer(wbPkt, time, true); - writebacks.pop_front(); - } #endif bool needsResponse = pkt->needsResponse(); @@ -527,6 +514,13 @@ Cache::timingAccess(PacketPtr pkt) } } + // copy writebacks to write buffer + while (!writebacks.empty()) { + PacketPtr wbPkt = writebacks.front(); + allocateWriteBuffer(wbPkt, time, true); + writebacks.pop_front(); + } + return true; } @@ -614,8 +608,9 @@ Cache::atomicAccess(PacketPtr pkt) // access in timing mode BlkType *blk = NULL; + PacketList writebacks; - if (!access(pkt, blk, lat)) { + if (!access(pkt, blk, lat, writebacks)) { // MISS PacketPtr busPkt = getBusPacket(pkt, blk, pkt->needsExclusive()); @@ -646,21 +641,20 @@ Cache::atomicAccess(PacketPtr pkt) pkt->makeAtomicResponse(); pkt->copyError(busPkt); } else if (isCacheFill && !is_error) { - PacketList writebacks; blk = handleFill(busPkt, blk, writebacks); satisfyCpuSideRequest(pkt, blk); delete busPkt; - - // Handle writebacks if needed - while (!writebacks.empty()){ - PacketPtr wbPkt = writebacks.front(); - memSidePort->sendAtomic(wbPkt); - writebacks.pop_front(); - delete wbPkt; - } } } + // Handle writebacks if needed + while (!writebacks.empty()){ + PacketPtr wbPkt = writebacks.front(); + memSidePort->sendAtomic(wbPkt); + writebacks.pop_front(); + delete wbPkt; + } + // We now have the block one way or another (hit or completed miss) if (pkt->needsResponse()) { -- cgit v1.2.3 From 1605fbebc86a46daa5487056cb170e10a2fcb40b Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Tue, 25 Mar 2008 15:58:54 -0400 Subject: IGbE: Fix bug that limits wire performance a bit --HG-- extra : convert_revision : 3f93c17f647a6955dab861da211174de856ee02c --- src/dev/i8254xGBe.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/dev/i8254xGBe.cc b/src/dev/i8254xGBe.cc index 3f56ec53a..44e056fc3 100644 --- a/src/dev/i8254xGBe.cc +++ b/src/dev/i8254xGBe.cc @@ -1412,6 +1412,7 @@ IGbE::ethTxDone() txTick = true; restartClock(); + txWire(); DPRINTF(EthernetSM, "TxFIFO: Transmission complete\n"); } -- cgit v1.2.3 From ed27c4c52183d9527a0c123b9be84bbe968f4afa Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Tue, 8 Apr 2008 11:08:26 -0400 Subject: SCons: Manually specifying header only directories with Dir() works around the problem --HG-- extra : convert_revision : d9713228d934cf4a45114a972603b8bca2bd27d3 --- src/cpu/SConscript | 2 ++ src/mem/SConscript | 2 ++ 2 files changed, 4 insertions(+) (limited to 'src') diff --git a/src/cpu/SConscript b/src/cpu/SConscript index c7d0c33bd..2abddef22 100644 --- a/src/cpu/SConscript +++ b/src/cpu/SConscript @@ -148,6 +148,8 @@ if env['USE_CHECKER']: print i, print ", please set USE_CHECKER=False or use one of those CPU models" Exit(1) +else: + Dir('checker') TraceFlag('Activity') TraceFlag('Commit') diff --git a/src/mem/SConscript b/src/mem/SConscript index b572f703c..0fdf9f9bb 100644 --- a/src/mem/SConscript +++ b/src/mem/SConscript @@ -35,6 +35,8 @@ SimObject('Bus.py') SimObject('PhysicalMemory.py') SimObject('MemObject.py') +Dir('config') + Source('bridge.cc') Source('bus.cc') Source('dram.cc') -- cgit v1.2.3 From fe12f3835354e62aca078789f4b07470f35396a2 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Thu, 10 Apr 2008 14:44:52 -0400 Subject: PhysicalMemory: Add parameter for variance in memory delay. --HG-- extra : convert_revision : b931472e81dedb650b7accb9061cb426f1c32e66 --- src/mem/PhysicalMemory.py | 3 ++- src/mem/physical.cc | 9 +++++++-- src/mem/physical.hh | 1 + 3 files changed, 10 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/mem/PhysicalMemory.py b/src/mem/PhysicalMemory.py index 99bd27f2b..4e8a830de 100644 --- a/src/mem/PhysicalMemory.py +++ b/src/mem/PhysicalMemory.py @@ -1,4 +1,4 @@ -# Copyright (c) 2005-2007 The Regents of The University of Michigan +# Copyright (c) 2005-2008 The Regents of The University of Michigan # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -36,6 +36,7 @@ class PhysicalMemory(MemObject): range = Param.AddrRange(AddrRange('128MB'), "Device Address") file = Param.String('', "memory mapped file") latency = Param.Latency('1t', "latency of an access") + latency_var = Param.Latency('0ns', "access variablity") zero = Param.Bool(False, "zero initialize memory") class DRAMMemory(PhysicalMemory): diff --git a/src/mem/physical.cc b/src/mem/physical.cc index 3560fc670..c06dd3170 100644 --- a/src/mem/physical.cc +++ b/src/mem/physical.cc @@ -41,6 +41,7 @@ #include "arch/isa_traits.hh" #include "base/misc.hh" +#include "base/random.hh" #include "config/full_system.hh" #include "mem/packet_access.hh" #include "mem/physical.hh" @@ -51,7 +52,8 @@ using namespace std; using namespace TheISA; PhysicalMemory::PhysicalMemory(const Params *p) - : MemObject(p), pmemAddr(NULL), lat(p->latency) + : MemObject(p), pmemAddr(NULL), lat(p->latency), + lat_var(p->latency_var) { if (params()->range.size() % TheISA::PageBytes != 0) panic("Memory Size not divisible by page size\n"); @@ -116,7 +118,10 @@ PhysicalMemory::deviceBlockSize() Tick PhysicalMemory::calculateLatency(PacketPtr pkt) { - return lat; + Tick latency = lat; + if (lat_var != 0) + latency += random_mt.random(0, lat_var); + return latency; } diff --git a/src/mem/physical.hh b/src/mem/physical.hh index c3749bd5b..ceb36b5c0 100644 --- a/src/mem/physical.hh +++ b/src/mem/physical.hh @@ -146,6 +146,7 @@ class PhysicalMemory : public MemObject uint8_t *pmemAddr; int pagePtr; Tick lat; + Tick lat_var; std::vector ports; typedef std::vector::iterator PortIterator; -- cgit v1.2.3 From 8af6dc118c28a0d24315290e136204c50f1d6d8a Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Thu, 10 Apr 2008 15:38:10 -0400 Subject: SCons: add comments to SConscript documenting bug workaround --HG-- extra : convert_revision : e6cdffe953d56b96c76c7ff14d2dcc3de3ccfcc3 --- src/cpu/SConscript | 2 ++ src/mem/SConscript | 2 ++ 2 files changed, 4 insertions(+) (limited to 'src') diff --git a/src/cpu/SConscript b/src/cpu/SConscript index 2abddef22..c6a959d9d 100644 --- a/src/cpu/SConscript +++ b/src/cpu/SConscript @@ -148,6 +148,8 @@ if env['USE_CHECKER']: print i, print ", please set USE_CHECKER=False or use one of those CPU models" Exit(1) +# Workaround for bug in SCons version > 0.97d20071212 +# Scons bug id: 2006 M5 Bug id: 308 else: Dir('checker') diff --git a/src/mem/SConscript b/src/mem/SConscript index 0fdf9f9bb..d391fbd5c 100644 --- a/src/mem/SConscript +++ b/src/mem/SConscript @@ -35,6 +35,8 @@ SimObject('Bus.py') SimObject('PhysicalMemory.py') SimObject('MemObject.py') +# Workaround for bug in SCons version > 0.97d20071212 +# Scons bug id: 2006 M5 Bug id: 308 Dir('config') Source('bridge.cc') -- cgit v1.2.3 From 4a4317ae18504226d298d42929b9882837ab1b44 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Tue, 6 May 2008 16:22:14 -0400 Subject: SCons: More scons fixing for SCons bug 2006 --HG-- extra : convert_revision : d3656ab1e3c18251d4bcf6f5a31103d4b2dfdc43 --- src/kern/SConscript | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/kern/SConscript b/src/kern/SConscript index 509e6b3f7..fd1181710 100644 --- a/src/kern/SConscript +++ b/src/kern/SConscript @@ -48,3 +48,9 @@ if env['FULL_SYSTEM']: Source('tru64/tru64_syscalls.cc') TraceFlag('BADADDR') +# Workaround for bug in SCons version > 0.97d20071212 +# Scons bug id: 2006 M5 Bug id: 308 +else: + Dir('linux') + if env['TARGET_ISA'] == 'alpha': + Dir('tru64') -- cgit v1.2.3 From e71a5270a2fe040e0542bc2c74a11a303688f6ae Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Thu, 15 May 2008 19:10:26 -0400 Subject: Make sure that output files are always checked success before they're used. Make OutputDirectory::resolve() private and change the functions using resolve() to instead use create(). --HG-- extra : convert_revision : 36d4be629764d0c4c708cec8aa712cd15f966453 --- src/base/output.cc | 4 ++-- src/base/output.hh | 3 ++- src/dev/etherdump.cc | 14 +++++++------- src/dev/etherdump.hh | 2 +- src/mem/cache/tags/split.cc | 5 ++--- 5 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/base/output.cc b/src/base/output.cc index 9d02a4a71..5a1768a76 100644 --- a/src/base/output.cc +++ b/src/base/output.cc @@ -98,7 +98,7 @@ OutputDirectory::create(const string &name, bool binary) ofstream *file = new ofstream(resolve(name).c_str(), ios::trunc | binary ? ios::binary : (ios::openmode)0); if (!file->is_open()) - panic("Cannot open file %s", name); + fatal("Cannot open file %s", name); return file; } @@ -119,7 +119,7 @@ OutputDirectory::find(const string &name) ofstream *file = new ofstream(filename.c_str(), ios::trunc); if (!file->is_open()) - panic("Cannot open file %s", filename); + fatal("Cannot open file %s", filename); files[filename] = file; return file; diff --git a/src/base/output.hh b/src/base/output.hh index 5de0c4005..b1d1d7e7d 100644 --- a/src/base/output.hh +++ b/src/base/output.hh @@ -43,6 +43,8 @@ class OutputDirectory map_t files; std::string dir; + std::string resolve(const std::string &name); + public: OutputDirectory(); ~OutputDirectory(); @@ -50,7 +52,6 @@ class OutputDirectory void setDirectory(const std::string &dir); const std::string &directory(); - std::string resolve(const std::string &name); std::ostream *create(const std::string &name, bool binary = false); std::ostream *find(const std::string &name); diff --git a/src/dev/etherdump.cc b/src/dev/etherdump.cc index 471093521..07e52f36d 100644 --- a/src/dev/etherdump.cc +++ b/src/dev/etherdump.cc @@ -45,7 +45,7 @@ using std::string; EtherDump::EtherDump(const Params *p) - : SimObject(p), stream(simout.resolve(p->file).c_str()), + : SimObject(p), stream(simout.create(p->file, true)), maxlen(p->maxlen) { } @@ -86,7 +86,7 @@ EtherDump::init() hdr.sigfigs = 0; hdr.linktype = DLT_EN10MB; - stream.write(reinterpret_cast(&hdr), sizeof(hdr)); + stream->write(reinterpret_cast(&hdr), sizeof(hdr)); /* * output an empty packet with the current time so that we know @@ -98,9 +98,9 @@ EtherDump::init() pkthdr.microseconds = 0; pkthdr.caplen = 0; pkthdr.len = 0; - stream.write(reinterpret_cast(&pkthdr), sizeof(pkthdr)); + stream->write(reinterpret_cast(&pkthdr), sizeof(pkthdr)); - stream.flush(); + stream->flush(); } void @@ -111,9 +111,9 @@ EtherDump::dumpPacket(EthPacketPtr &packet) pkthdr.microseconds = (curTick / Clock::Int::us) % ULL(1000000); pkthdr.caplen = std::min(packet->length, maxlen); pkthdr.len = packet->length; - stream.write(reinterpret_cast(&pkthdr), sizeof(pkthdr)); - stream.write(reinterpret_cast(packet->data), pkthdr.caplen); - stream.flush(); + stream->write(reinterpret_cast(&pkthdr), sizeof(pkthdr)); + stream->write(reinterpret_cast(packet->data), pkthdr.caplen); + stream->flush(); } EtherDump * diff --git a/src/dev/etherdump.hh b/src/dev/etherdump.hh index 1027ce4d0..733e61c97 100644 --- a/src/dev/etherdump.hh +++ b/src/dev/etherdump.hh @@ -46,7 +46,7 @@ class EtherDump : public SimObject { private: - std::ofstream stream; + std::ostream *stream; const int maxlen; void dumpPacket(EthPacketPtr &packet); void init(); diff --git a/src/mem/cache/tags/split.cc b/src/mem/cache/tags/split.cc index 0df85cc92..5bed44bd3 100644 --- a/src/mem/cache/tags/split.cc +++ b/src/mem/cache/tags/split.cc @@ -379,13 +379,12 @@ Split::cleanupRefs() else if (lru_net) lru_net->cleanupRefs(); - ofstream memPrint(simout.resolve("memory_footprint.txt").c_str(), - ios::trunc); + ostream *memPrint = simout.create("memory_footprint.txt"); // this shouldn't be here but it happens at the end, which is what i want memIter end = memHash.end(); for (memIter iter = memHash.begin(); iter != end; ++iter) { - ccprintf(memPrint, "%8x\t%d\n", (*iter).first, (*iter).second); + ccprintf(*memPrint, "%8x\t%d\n", (*iter).first, (*iter).second); } } -- cgit v1.2.3 From b7af65f414d34cb6b3817bc748fd053f505b0fea Mon Sep 17 00:00:00 2001 From: Stephen Hines Date: Tue, 20 May 2008 14:04:53 -0400 Subject: SCons: Fixing SCons bug 2006 issues for non-alpha ISAs --HG-- extra : convert_revision : 26e3edef06d6f82aaf162825c151d18faadd6e72 --- src/arch/mips/SConscript | 3 +++ src/arch/sparc/SConscript | 4 ++++ src/kern/SConscript | 2 ++ 3 files changed, 9 insertions(+) (limited to 'src') diff --git a/src/arch/mips/SConscript b/src/arch/mips/SConscript index 8be445c99..844e7ba15 100644 --- a/src/arch/mips/SConscript +++ b/src/arch/mips/SConscript @@ -33,6 +33,9 @@ Import('*') if env['TARGET_ISA'] == 'mips': +# Workaround for bug in SCons version > 0.97d20071212 +# Scons bug id: 2006 M5 Bug id: 308 + Dir('isa/formats') Source('faults.cc') Source('regfile/int_regfile.cc') Source('regfile/float_regfile.cc') diff --git a/src/arch/sparc/SConscript b/src/arch/sparc/SConscript index a86c00250..d4d68a6bd 100644 --- a/src/arch/sparc/SConscript +++ b/src/arch/sparc/SConscript @@ -32,6 +32,10 @@ Import('*') if env['TARGET_ISA'] == 'sparc': +# Workaround for bug in SCons version > 0.97d20071212 +# Scons bug id: 2006 M5 Bug id: 308 + Dir('isa/formats') + Dir('isa/formats/mem') Source('asi.cc') Source('faults.cc') Source('floatregfile.cc') diff --git a/src/kern/SConscript b/src/kern/SConscript index fd1181710..43848aada 100644 --- a/src/kern/SConscript +++ b/src/kern/SConscript @@ -54,3 +54,5 @@ else: Dir('linux') if env['TARGET_ISA'] == 'alpha': Dir('tru64') + elif env['TARGET_ISA'] == 'sparc': + Dir('solaris') -- cgit v1.2.3 From f5e36d156dc33a6c01c69c19efc2b5b0450496f6 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Tue, 20 May 2008 16:06:56 -0400 Subject: IGbE: Implement sending packet that is contained in more than 2 descriptors. --HG-- extra : convert_revision : 8fb7d5fad5cb840f69c31aa8b331dbe09e46ee9d --- src/dev/i8254xGBe.cc | 19 ++++++++++++------- src/dev/i8254xGBe.hh | 9 +++++++++ 2 files changed, 21 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/dev/i8254xGBe.cc b/src/dev/i8254xGBe.cc index 44e056fc3..ff255d5f7 100644 --- a/src/dev/i8254xGBe.cc +++ b/src/dev/i8254xGBe.cc @@ -919,7 +919,7 @@ IGbE::TxDescCache::getPacketData(EthPacketPtr p) pktWaiting = true; - DPRINTF(EthernetDesc, "Starting DMA of packet\n"); + DPRINTF(EthernetDesc, "Starting DMA of packet at offset %d\n", p->length); igbe->dmaRead(igbe->platform->pciToDma(TxdOp::getBuf(desc)), TxdOp::getLen(desc), &pktEvent, p->data + p->length); @@ -943,20 +943,22 @@ IGbE::TxDescCache::pktComplete() DPRINTF(EthernetDesc, "TxDescriptor data d1: %#llx d2: %#llx\n", desc->d1, desc->d2); if (!TxdOp::eop(desc)) { - // This only supports two descriptors per tx packet - assert(pktPtr->length == 0); - pktPtr->length = TxdOp::getLen(desc); + pktPtr->length += TxdOp::getLen(desc); unusedCache.pop_front(); usedCache.push_back(desc); pktDone = true; pktWaiting = false; + pktMultiDesc = true; + + DPRINTF(EthernetDesc, "Partial Packet Descriptor of %d bytes Done\n", + pktPtr->length); pktPtr = NULL; - DPRINTF(EthernetDesc, "Partial Packet Descriptor Done\n"); enableSm(); igbe->checkDrain(); return; } + pktMultiDesc = false; // Set the length of the data in the EtherPacket pktPtr->length += TxdOp::getLen(desc); @@ -988,7 +990,7 @@ IGbE::TxDescCache::pktComplete() if (TxdOp::isData(desc) && ( TxdOp::ixsm(desc) || TxdOp::txsm(desc)) ) { DPRINTF(EthernetDesc, "Calculating checksums for packet\n"); IpPtr ip(pktPtr); - + assert(ip); if (TxdOp::ixsm(desc)) { ip->sum(0); ip->sum(cksum(ip)); @@ -1058,6 +1060,7 @@ IGbE::TxDescCache::serialize(std::ostream &os) SERIALIZE_SCALAR(pktDone); SERIALIZE_SCALAR(isTcp); SERIALIZE_SCALAR(pktWaiting); + SERIALIZE_SCALAR(pktMultiDesc); } void @@ -1067,6 +1070,7 @@ IGbE::TxDescCache::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(pktDone); UNSERIALIZE_SCALAR(isTcp); UNSERIALIZE_SCALAR(pktWaiting); + UNSERIALIZE_SCALAR(pktMultiDesc); } bool @@ -1172,7 +1176,8 @@ IGbE::txStateMachine() // If we have a packet available and it's length is not 0 (meaning it's not // a multidescriptor packet) put it in the fifo, otherwise an the next // iteration we'll get the rest of the data - if (txPacket && txDescCache.packetAvailable() && txPacket->length) { + if (txPacket && txDescCache.packetAvailable() + && !txDescCache.packetMultiDesc() && txPacket->length) { bool success; DPRINTF(EthernetSM, "TXS: packet placed in TX FIFO\n"); diff --git a/src/dev/i8254xGBe.hh b/src/dev/i8254xGBe.hh index 9403c87b6..0daf094c1 100644 --- a/src/dev/i8254xGBe.hh +++ b/src/dev/i8254xGBe.hh @@ -564,6 +564,7 @@ class IGbE : public EtherDevice bool pktDone; bool isTcp; bool pktWaiting; + bool pktMultiDesc; public: TxDescCache(IGbE *i, std::string n, int s); @@ -586,6 +587,14 @@ class IGbE : public EtherDevice */ bool packetWaiting() { return pktWaiting; } + /** Ask if this packet is composed of multiple descriptors + * so even if we've got data, we need to wait for more before + * we can send it out. + * @return packet can't be sent out because it's a multi-descriptor + * packet + */ + bool packetMultiDesc() { return pktMultiDesc;} + /** Called by event when dma to write packet is completed */ void pktComplete(); -- cgit v1.2.3 From fd3e661cd3c9d6e5424864b3986a51b940ce01eb Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Wed, 11 Jun 2008 10:54:08 -0400 Subject: SCons: Fix more SCons version issues --- src/arch/x86/SConscript | 14 ++++++++++++++ src/kern/SConscript | 4 ++++ 2 files changed, 18 insertions(+) (limited to 'src') diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript index 674cd54c2..09967b0d3 100644 --- a/src/arch/x86/SConscript +++ b/src/arch/x86/SConscript @@ -353,3 +353,17 @@ if env['TARGET_ISA'] == 'x86': # Only non-header files need to be compiled. if not f.path.endswith('.hh'): Source(f) + + # Workaround for bug in SCons version > 0.97d20071212 + # Scons bug id: 2006 M5 Bug id: 308 + from os.path import dirname, join as joinpath + + Dir('isa') + Dir('isa/microops') + Dir('isa/decoder') + Dir('isa/formats') + Dir('isa/insts') + isa_dirs = set(map(lambda x:dirname(x), python_files)) + for d in isa_dirs: + Dir(joinpath('isa/insts', d)) + diff --git a/src/kern/SConscript b/src/kern/SConscript index 43848aada..b905a8b41 100644 --- a/src/kern/SConscript +++ b/src/kern/SConscript @@ -40,6 +40,10 @@ if env['FULL_SYSTEM']: Source('linux/events.cc') Source('linux/linux_syscalls.cc') Source('linux/printk.cc') + + # Workaround for bug in SCons version > 0.97d20071212 + # Scons bug id: 2006 M5 Bug id: 308 + Dir('tru64') if env['TARGET_ISA'] == 'alpha': Source('tru64/dump_mbuf.cc') -- cgit v1.2.3 From 5797ff10160df8fa9f51196753ab702cf190163f Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Wed, 11 Jun 2008 10:54:12 -0400 Subject: X86: Fix building on *BSD hosts --- src/arch/x86/linux/linux.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/linux/linux.hh b/src/arch/x86/linux/linux.hh index 8a78d5320..8d6468f06 100644 --- a/src/arch/x86/linux/linux.hh +++ b/src/arch/x86/linux/linux.hh @@ -82,7 +82,7 @@ class X86Linux64 : public Linux uint64_t st_mtime_nsec; uint64_t st_ctimeX; uint64_t st_ctime_nsec; - int64_t __unused[3]; + int64_t unused0[3]; } tgt_stat64; static OpenFlagTransTable openFlagTable[]; -- cgit v1.2.3 From d093fcb07924cc4341b8142c448b905dd94f7125 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:35:50 -0400 Subject: CPU: Make the simple cpu trace data for loads/stores. --- src/cpu/simple/atomic.cc | 6 ++++++ src/cpu/simple/timing.cc | 6 ++++++ 2 files changed, 12 insertions(+) (limited to 'src') diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 23bd40b9b..acd280568 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -355,6 +355,9 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags) if (secondAddr <= addr) { data = gtoh(data); + if (traceData) { + traceData->setData(data); + } return fault; } @@ -568,6 +571,9 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) // If the write needs to have a fault on the access, consider // calling changeStatus() and changing it to "bad addr write" // or something. + if (traceData) { + traceData->setData(data); + } return fault; } diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index a76824ff3..d0c7dd787 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -296,6 +296,9 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) delete req; } + if (traceData) { + traceData->setData(data); + } return fault; } @@ -431,6 +434,9 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) delete req; } + if (traceData) { + traceData->setData(data); + } // If the write needs to have a fault on the access, consider calling // changeStatus() and changing it to "bad addr write" or something. -- cgit v1.2.3 From 8501a90f59c73896b4eea6d7ce8f1d1cc8685d53 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:39:10 -0400 Subject: X86: Add in some support for the tsc register. --- src/arch/x86/isa/decoder/two_byte_opcodes.isa | 2 +- src/arch/x86/isa/insts/system/msrs.py | 8 ++++++++ src/arch/x86/isa/microops/regop.isa | 12 +++++++++++- src/arch/x86/isa/operands.isa | 3 ++- src/arch/x86/miscregfile.cc | 8 ++++++++ 5 files changed, 30 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index 8135a1fdb..e2d968c17 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -317,7 +317,7 @@ } 0x06: decode OPCODE_OP_BOTTOM3 { 0x0: Inst::WRMSR(); - 0x1: rdtsc(); + 0x1: Inst::RDTSC(); 0x2: Inst::RDMSR(); 0x3: rdpmc(); 0x4: sysenter(); diff --git a/src/arch/x86/isa/insts/system/msrs.py b/src/arch/x86/isa/insts/system/msrs.py index 1acb4c792..461ed1054 100644 --- a/src/arch/x86/isa/insts/system/msrs.py +++ b/src/arch/x86/isa/insts/system/msrs.py @@ -99,4 +99,12 @@ def macroop WRMSR or t2, t2, t3, dataSize=8 st t2, intseg, [8, t1, rcx], dataSize=8, addressSize=4 }; + +def macroop RDTSC +{ + rdtsc t1 + mov rax, rax, t1, dataSize=4 + srli t1, t1, 32, dataSize=8 + mov rdx, rdx, t1, dataSize=4 +}; ''' diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index e761f0034..03a7515ed 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2007 The Hewlett-Packard Development Company +// Copyright (c) 2007-2008 The Hewlett-Packard Development Company // All rights reserved. // // Redistribution and use of this software in source and binary forms, @@ -1018,6 +1018,16 @@ let {{ ''' + class Wrtsc(WrRegOp): + code = ''' + TscOp = psrc1; + ''' + + class Rdtsc(RdRegOp): + code = ''' + DestReg = TscOp; + ''' + class Wrdl(RegOp): code = ''' SegDescriptor desc = SrcReg1; diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa index 9345158e9..87fd28a6a 100644 --- a/src/arch/x86/isa/operands.isa +++ b/src/arch/x86/isa/operands.isa @@ -26,7 +26,7 @@ // // Authors: Gabe Black -// Copyright (c) 2007 The Hewlett-Packard Development Company +// Copyright (c) 2007-2008 The Hewlett-Packard Development Company // All rights reserved. // // Redistribution and use of this software in source and binary forms, @@ -146,5 +146,6 @@ def operands {{ 'GDTRBase': ('ControlReg', 'uqw', 'MISCREG_TSG_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 205), 'GDTRLimit': ('ControlReg', 'uqw', 'MISCREG_TSG_LIMIT', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 206), 'CSBase': ('ControlReg', 'udw', 'MISCREG_CS_EFF_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 207), + 'TscOp': ('ControlReg', 'udw', 'MISCREG_TSC', (None, None, ['IsSerializeAfter', 'IsSerializing', 'IsNonSpeculative']), 208), 'Mem': ('Mem', 'uqw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 300) }}; diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc index 5d75af0cf..930bf53c7 100644 --- a/src/arch/x86/miscregfile.cc +++ b/src/arch/x86/miscregfile.cc @@ -87,6 +87,7 @@ #include "arch/x86/miscregfile.hh" #include "arch/x86/tlb.hh" +#include "cpu/base.hh" #include "cpu/thread_context.hh" #include "sim/serialize.hh" @@ -178,6 +179,10 @@ MiscReg MiscRegFile::readReg(int miscReg, ThreadContext * tc) break; } } + switch (miscReg) { + case MISCREG_TSC: + return regVal[MISCREG_TSC] + tc->getCpuPtr()->curCycle(); + } return readRegNoEffect(miscReg); } @@ -377,6 +382,9 @@ void MiscRegFile::setReg(int miscReg, MISCREG_SEG_BASE_BASE)] = val; } break; + case MISCREG_TSC: + regVal[MISCREG_TSC] = val - tc->getCpuPtr()->curCycle(); + return; } setRegNoEffect(miscReg, newVal); } -- cgit v1.2.3 From 254cc076500ab7ee382d76a92db3a5a3c2ec1e62 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:45:22 -0400 Subject: X86: Fix a byte register indexing issue in the sign extending move from memory microcode. --- src/arch/x86/isa/insts/general_purpose/data_transfer/move.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py index 3b8608c48..16196bcc8 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py +++ b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -130,14 +130,14 @@ def macroop MOVSX_B_R_R { }; def macroop MOVSX_B_R_M { - ld reg, seg, sib, disp, dataSize=1 - sexti reg, reg, 7 + ld t1, seg, sib, disp, dataSize=1 + sexti reg, t1, 7 }; def macroop MOVSX_B_R_P { rdip t7 - ld reg, seg, riprel, disp, dataSize=1 - sexti reg, reg, 7 + ld t1, seg, riprel, disp, dataSize=1 + sexti reg, t1, 7 }; def macroop MOVSX_W_R_R { -- cgit v1.2.3 From 16e189fad21cd30a84fa736ac0dd7eb3dc9ba724 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:45:52 -0400 Subject: X86: Bit scan forward/reverse were accidentally transposed. --- .../isa/insts/general_purpose/compare_and_test/bit_scan.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py b/src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py index 71059e80d..a18437df3 100644 --- a/src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py +++ b/src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py @@ -82,7 +82,7 @@ # Authors: Gabe Black microcode = ''' -def macroop BSF_R_R { +def macroop BSR_R_R { # Determine if the input was zero, and also move it to a temp reg. movi t1, t1, t0, dataSize=8 and t1, regm, regm, flags=(ZF,) @@ -131,7 +131,7 @@ end: fault "NoFault" }; -def macroop BSF_R_M { +def macroop BSR_R_M { movi t1, t1, t0, dataSize=8 ld t1, seg, sib, disp @@ -183,7 +183,7 @@ end: fault "NoFault" }; -def macroop BSF_R_P { +def macroop BSR_R_P { rdip t7 movi t1, t1, t0, dataSize=8 @@ -236,7 +236,7 @@ end: fault "NoFault" }; -def macroop BSR_R_R { +def macroop BSF_R_R { # Determine if the input was zero, and also move it to a temp reg. mov t1, t1, t0, dataSize=8 and t1, regm, regm, flags=(ZF,) @@ -282,7 +282,7 @@ end: fault "NoFault" }; -def macroop BSR_R_M { +def macroop BSF_R_M { mov t1, t1, t0, dataSize=8 ld t1, seg, sib, disp @@ -331,7 +331,7 @@ end: fault "NoFault" }; -def macroop BSR_R_P { +def macroop BSF_R_P { rdip t7 mov t1, t1, t0, dataSize=8 -- cgit v1.2.3 From 8e2991b529fd63f4d7c56518ebfbd2424f964172 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:46:04 -0400 Subject: X86: Fix the implementation of BSF. --- .../general_purpose/compare_and_test/bit_scan.py | 90 +++++++++++++--------- 1 file changed, 54 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py b/src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py index a18437df3..f2a3db8a3 100644 --- a/src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py +++ b/src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py @@ -250,33 +250,39 @@ def macroop BSF_R_R { # Bit 6 srli t3, t1, 32, dataSize=8 - andi t3, t3, 32 - or reg, reg, t3 + andi t4, t3, 32, flags=(EZF,) + or reg, reg, t4 + mov t1, t1, t3, flags=(nCEZF,) # Bit 5 srli t3, t1, 16, dataSize=8 - andi t3, t3, 16 - or reg, reg, t3 + andi t4, t3, 16, flags=(EZF,) + or reg, reg, t4 + mov t1, t1, t3, flags=(nCEZF,) # Bit 4 srli t3, t1, 8, dataSize=8 - andi t3, t3, 8 - or reg, reg, t3 + andi t4, t3, 8, flags=(EZF,) + or reg, reg, t4 + mov t1, t1, t3, flags=(nCEZF,) # Bit 3 srli t3, t1, 4, dataSize=8 - andi t3, t3, 4 - or reg, reg, t3 + andi t4, t3, 4, flags=(EZF,) + or reg, reg, t4 + mov t1, t1, t3, flags=(nCEZF,) # Bit 2 srli t3, t1, 2, dataSize=8 - andi t3, t3, 2 - or reg, reg, t3 + andi t4, t3, 2, flags=(EZF,) + or reg, reg, t4 + mov t1, t1, t3, flags=(nCEZF,) # Bit 1 srli t3, t1, 1, dataSize=8 - andi t3, t3, 1 - or reg, reg, t3 + andi t4, t3, 1, flags=(EZF,) + or reg, reg, t4 + mov t1, t1, t3, flags=(nCEZF,) end: fault "NoFault" @@ -299,33 +305,39 @@ def macroop BSF_R_M { # Bit 6 srli t3, t1, 32, dataSize=8 - andi t3, t3, 32 - or reg, reg, t3 + andi t4, t3, 32, flags=(EZF,) + or reg, reg, t4 + mov t1, t1, t3, flags=(nCEZF,) # Bit 5 srli t3, t1, 16, dataSize=8 - andi t3, t3, 16 - or reg, reg, t3 + andi t4, t3, 16, flags=(EZF,) + or reg, reg, t4 + mov t1, t1, t3, flags=(nCEZF,) # Bit 4 srli t3, t1, 8, dataSize=8 - andi t3, t3, 8 - or reg, reg, t3 + andi t4, t3, 8, flags=(EZF,) + or reg, reg, t4 + mov t1, t1, t3, flags=(nCEZF,) # Bit 3 srli t3, t1, 4, dataSize=8 - andi t3, t3, 4 - or reg, reg, t3 + andi t4, t3, 4, flags=(EZF,) + or reg, reg, t4 + mov t1, t1, t3, flags=(nCEZF,) # Bit 2 srli t3, t1, 2, dataSize=8 - andi t3, t3, 2 - or reg, reg, t3 + andi t4, t3, 2, flags=(EZF,) + or reg, reg, t4 + mov t1, t1, t3, flags=(nCEZF,) # Bit 1 srli t3, t1, 1, dataSize=8 - andi t3, t3, 1 - or reg, reg, t3 + andi t4, t3, 1, flags=(EZF,) + or reg, reg, t4 + mov t1, t1, t3, flags=(nCEZF,) end: fault "NoFault" @@ -349,33 +361,39 @@ def macroop BSF_R_P { # Bit 6 srli t3, t1, 32, dataSize=8 - andi t3, t3, 32 - or reg, reg, t3 + andi t4, t3, 32, flags=(EZF,) + or reg, reg, t4 + mov t1, t1, t3, flags=(nCEZF,) # Bit 5 srli t3, t1, 16, dataSize=8 - andi t3, t3, 16 - or reg, reg, t3 + andi t4, t3, 16, flags=(EZF,) + or reg, reg, t4 + mov t1, t1, t3, flags=(nCEZF,) # Bit 4 srli t3, t1, 8, dataSize=8 - andi t3, t3, 8 - or reg, reg, t3 + andi t4, t3, 8, flags=(EZF,) + or reg, reg, t4 + mov t1, t1, t3, flags=(nCEZF,) # Bit 3 srli t3, t1, 4, dataSize=8 - andi t3, t3, 4 - or reg, reg, t3 + andi t4, t3, 4, flags=(EZF,) + or reg, reg, t4 + mov t1, t1, t3, flags=(nCEZF,) # Bit 2 srli t3, t1, 2, dataSize=8 - andi t3, t3, 2 - or reg, reg, t3 + andi t4, t3, 2, flags=(EZF,) + or reg, reg, t4 + mov t1, t1, t3, flags=(nCEZF,) # Bit 1 srli t3, t1, 1, dataSize=8 - andi t3, t3, 1 - or reg, reg, t3 + andi t4, t3, 1, flags=(EZF,) + or reg, reg, t4 + mov t1, t1, t3, flags=(nCEZF,) end: fault "NoFault" -- cgit v1.2.3 From b3e55339f90dbf7f719e8f8348356e1ad03d74bb Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:46:22 -0400 Subject: X86: Remove enforcement of APIC register access alignment. Panic if more than one register is accessed at a time. --- src/arch/x86/mmaped_ipr.hh | 29 ++++++++++++----------------- src/arch/x86/tlb.cc | 15 +++++++++++++-- 2 files changed, 25 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/arch/x86/mmaped_ipr.hh b/src/arch/x86/mmaped_ipr.hh index eda85c084..cf3eba5e9 100644 --- a/src/arch/x86/mmaped_ipr.hh +++ b/src/arch/x86/mmaped_ipr.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 The Hewlett-Packard Development Company + * Copyright (c) 2007-2008 The Hewlett-Packard Development Company * All rights reserved. * * Redistribution and use of this software in source and binary forms, @@ -78,15 +78,12 @@ namespace X86ISA #if !FULL_SYSTEM panic("Shouldn't have a memory mapped register in SE\n"); #else + Addr offset = pkt->getAddr() & mask(3); MiscRegIndex index = (MiscRegIndex)(pkt->getAddr() / sizeof(MiscReg)); - if (index == MISCREG_PCI_CONFIG_ADDRESS || - (index >= MISCREG_APIC_START && - index <= MISCREG_APIC_END)) { - pkt->set((uint32_t)(xc->readMiscReg(pkt->getAddr() / - sizeof(MiscReg)))); - } else { - pkt->set(xc->readMiscReg(pkt->getAddr() / sizeof(MiscReg))); - } + MiscReg data = htog(xc->readMiscReg(index)); + // Make sure we don't trot off the end of data. + assert(offset + pkt->getSize() <= sizeof(MiscReg)); + pkt->setData(((uint8_t *)&data) + offset); #endif return xc->getCpuPtr()->ticks(1); } @@ -97,15 +94,13 @@ namespace X86ISA #if !FULL_SYSTEM panic("Shouldn't have a memory mapped register in SE\n"); #else + Addr offset = pkt->getAddr() & mask(3); MiscRegIndex index = (MiscRegIndex)(pkt->getAddr() / sizeof(MiscReg)); - if (index == MISCREG_PCI_CONFIG_ADDRESS || - (index >= MISCREG_APIC_START && - index <= MISCREG_APIC_END)) { - xc->setMiscReg(index, gtoh(pkt->get())); - } else { - xc->setMiscReg(pkt->getAddr() / sizeof(MiscReg), - gtoh(pkt->get())); - } + MiscReg data = htog(xc->readMiscRegNoEffect(index)); + // Make sure we don't trot off the end of data. + assert(offset + pkt->getSize() <= sizeof(MiscReg)); + pkt->writeData(((uint8_t *)&data) + offset); + xc->setMiscReg(index, gtoh(data)); #endif return xc->getCpuPtr()->ticks(1); } diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index 3e720c9ae..cbd59c19e 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 The Hewlett-Packard Development Company + * Copyright (c) 2007-2008 The Hewlett-Packard Development Company * All rights reserved. * * Redistribution and use of this software in source and binary forms, @@ -598,13 +598,24 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) Addr paddr = req->getPaddr(); if (baseAddr <= paddr && baseAddr + (1 << 12) > paddr) { req->setMmapedIpr(true); + // The Intel developer's manuals say the below restrictions apply, + // but the linux kernel, because of a compiler optimization, breaks + // them. + /* // Check alignment if (paddr & ((32/8) - 1)) return new GeneralProtection(0); // Check access size if (req->getSize() != (32/8)) return new GeneralProtection(0); + */ + + //Make sure we're at least only accessing one register. + if ((paddr & ~mask(3)) != ((paddr + req->getSize()) & ~mask(3))) + panic("Accessed more than one register at a time in the APIC!\n"); MiscReg regNum; + Addr offset = paddr & mask(3); + paddr &= ~mask(3); switch (paddr - baseAddr) { case 0x20: @@ -732,7 +743,7 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) return new GeneralProtection(0); break; } - req->setPaddr(regNum * sizeof(MiscReg)); + req->setPaddr(regNum * sizeof(MiscReg) + offset); } #endif return NoFault; -- cgit v1.2.3 From a8e3001df85bc1e435a8abe77141ba0f6c9b7f9e Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:47:25 -0400 Subject: X86: Bypass unaligned access support for register addressed MSRs. --- .../isa/insts/general_purpose/input_output/general_io.py | 14 ++++++-------- .../isa/insts/general_purpose/input_output/string_io.py | 14 +++++--------- src/arch/x86/isa/insts/system/msrs.py | 8 ++++---- src/arch/x86/tlb.cc | 3 ++- 4 files changed, 17 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/input_output/general_io.py b/src/arch/x86/isa/insts/general_purpose/input_output/general_io.py index 1986a322e..aba318d73 100644 --- a/src/arch/x86/isa/insts/general_purpose/input_output/general_io.py +++ b/src/arch/x86/isa/insts/general_purpose/input_output/general_io.py @@ -84,25 +84,23 @@ microcode = ''' def macroop IN_R_I { .adjust_imm trimImm(8) - limm t1, "IntAddrPrefixIO", dataSize=8 - ld reg, intseg, [1, t1, t0], imm, addressSize=8 + limm t1, imm, dataSize=asz + ld reg, intseg, [1, t1, t0], "IntAddrPrefixIO << 3", addressSize=4 }; def macroop IN_R_R { - limm t1, "IntAddrPrefixIO", dataSize=8 zexti t2, regm, 15, dataSize=2 - ld reg, intseg, [1, t1, t2], addressSize=8 + ld reg, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=4 }; def macroop OUT_I_R { .adjust_imm trimImm(8) - limm t1, "IntAddrPrefixIO", dataSize=8 - st reg, intseg, [1, t1, t0], imm, addressSize=8 + limm t1, imm, dataSize=8 + st reg, intseg, [1, t1, t0], "IntAddrPrefixIO << 3", addressSize=4 }; def macroop OUT_R_R { - limm t1, "IntAddrPrefixIO", dataSize=8 zexti t2, reg, 15, dataSize=2 - st regm, intseg, [1, t1, t2], addressSize=8 + st regm, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=4 }; ''' diff --git a/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py b/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py index b44203d9c..1b4e086d2 100644 --- a/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py +++ b/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -61,10 +61,9 @@ def macroop INS_M_R { subi t4, t0, dsz, dataSize=asz mov t3, t3, t4, flags=(nCEZF,), dataSize=asz - limm t1, "IntAddrPrefixIO" zexti t2, reg, 15, dataSize=2 - ld t6, intseg, [1, t1, t2], addressSize=8 + ld t6, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8 st t6, es, [1, t0, rdi] add rdi, rdi, t3, dataSize=asz @@ -77,11 +76,10 @@ def macroop INS_E_M_R { subi t4, t0, dsz, dataSize=asz mov t3, t3, t4, flags=(nCEZF,), dataSize=asz - limm t1, "IntAddrPrefixIO" zexti t2, reg, 15, dataSize=2 topOfLoop: - ld t6, intseg, [1, t1, t2], addressSize=8 + ld t6, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8 st t6, es, [1, t0, rdi] subi rcx, rcx, 1, flags=(EZF,), dataSize=asz @@ -97,11 +95,10 @@ def macroop OUTS_R_M { subi t4, t0, dsz, dataSize=asz mov t3, t3, t4, flags=(nCEZF,), dataSize=asz - limm t1, "IntAddrPrefixIO" zexti t2, reg, 15, dataSize=2 ld t6, ds, [1, t0, rsi] - st t6, intseg, [1, t1, t2], addressSize=8 + st t6, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8 add rsi, rsi, t3, dataSize=asz }; @@ -113,12 +110,11 @@ def macroop OUTS_E_R_M { subi t4, t0, dsz, dataSize=asz mov t3, t3, t4, flags=(nCEZF,), dataSize=asz - limm t1, "IntAddrPrefixIO" zexti t2, reg, 15, dataSize=2 topOfLoop: ld t6, ds, [1, t0, rsi] - st t6, intseg, [1, t1, t2], addressSize=8 + st t6, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8 subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rsi, rsi, t3, dataSize=asz diff --git a/src/arch/x86/isa/insts/system/msrs.py b/src/arch/x86/isa/insts/system/msrs.py index 461ed1054..f3c867398 100644 --- a/src/arch/x86/isa/insts/system/msrs.py +++ b/src/arch/x86/isa/insts/system/msrs.py @@ -84,8 +84,8 @@ microcode = ''' def macroop RDMSR { - limm t1, "IntAddrPrefixMSR >> 3" - ld t2, intseg, [8, t1, rcx], dataSize=8, addressSize=4 + ld t2, intseg, [8, rcx, t0], "IntAddrPrefixMSR << 3", \ + dataSize=8, addressSize=4 mov rax, rax, t2, dataSize=4 srli t2, t2, 32, dataSize=8 mov rdx, rdx, t2, dataSize=4 @@ -93,11 +93,11 @@ def macroop RDMSR def macroop WRMSR { - limm t1, "IntAddrPrefixMSR >> 3" mov t2, t2, rax, dataSize=4 slli t3, rdx, 32, dataSize=8 or t2, t2, t3, dataSize=8 - st t2, intseg, [8, t1, rcx], dataSize=8, addressSize=4 + st t2, intseg, [8, rcx, t0], "IntAddrPrefixMSR << 3", \ + dataSize=8, addressSize=4 }; def macroop RDTSC diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index cbd59c19e..b6793245e 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -206,10 +206,11 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) // value. if (seg == SEGMENT_REG_MS) { DPRINTF(TLB, "Addresses references internal memory.\n"); - Addr prefix = vaddr & IntAddrPrefixMask; + Addr prefix = (vaddr >> 3) & IntAddrPrefixMask; if (prefix == IntAddrPrefixCPUID) { panic("CPUID memory space not yet implemented!\n"); } else if (prefix == IntAddrPrefixMSR) { + vaddr = vaddr >> 3; req->setMmapedIpr(true); Addr regNum = 0; switch (vaddr & ~IntAddrPrefixMask) { -- cgit v1.2.3 From 8688ef3fe523bf40a0b90d88fb986c25571b298a Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:48:02 -0400 Subject: X86: Have all 8 machine check registers since the kernel assumes they're there. --- src/arch/x86/miscregs.hh | 14 +++++++++++++- src/arch/x86/tlb.cc | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/miscregs.hh b/src/arch/x86/miscregs.hh index 15ea0d77b..83ba3c0c5 100644 --- a/src/arch/x86/miscregs.hh +++ b/src/arch/x86/miscregs.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 The Hewlett-Packard Development Company + * Copyright (c) 2007-2008 The Hewlett-Packard Development Company * All rights reserved. * * Redistribution and use of this software in source and binary forms, @@ -183,6 +183,9 @@ namespace X86ISA MISCREG_MC2_CTL, MISCREG_MC3_CTL, MISCREG_MC4_CTL, + MISCREG_MC5_CTL, + MISCREG_MC6_CTL, + MISCREG_MC7_CTL, MISCREG_MC_STATUS_BASE, MISCREG_MC0_STATUS = MISCREG_MC_STATUS_BASE, @@ -190,6 +193,9 @@ namespace X86ISA MISCREG_MC2_STATUS, MISCREG_MC3_STATUS, MISCREG_MC4_STATUS, + MISCREG_MC5_STATUS, + MISCREG_MC6_STATUS, + MISCREG_MC7_STATUS, MISCREG_MC_ADDR_BASE, MISCREG_MC0_ADDR = MISCREG_MC_ADDR_BASE, @@ -197,6 +203,9 @@ namespace X86ISA MISCREG_MC2_ADDR, MISCREG_MC3_ADDR, MISCREG_MC4_ADDR, + MISCREG_MC5_ADDR, + MISCREG_MC6_ADDR, + MISCREG_MC7_ADDR, MISCREG_MC_MISC_BASE, MISCREG_MC0_MISC = MISCREG_MC_MISC_BASE, @@ -204,6 +213,9 @@ namespace X86ISA MISCREG_MC2_MISC, MISCREG_MC3_MISC, MISCREG_MC4_MISC, + MISCREG_MC5_MISC, + MISCREG_MC6_MISC, + MISCREG_MC7_MISC, // Extended feature enable register MISCREG_EFER, diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index b6793245e..f5e214a88 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -358,6 +358,15 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) case 0x410: regNum = MISCREG_MC4_CTL; break; + case 0x414: + regNum = MISCREG_MC5_CTL; + break; + case 0x418: + regNum = MISCREG_MC6_CTL; + break; + case 0x41C: + regNum = MISCREG_MC7_CTL; + break; case 0x401: regNum = MISCREG_MC0_STATUS; break; @@ -373,6 +382,15 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) case 0x411: regNum = MISCREG_MC4_STATUS; break; + case 0x415: + regNum = MISCREG_MC5_STATUS; + break; + case 0x419: + regNum = MISCREG_MC6_STATUS; + break; + case 0x41D: + regNum = MISCREG_MC7_STATUS; + break; case 0x402: regNum = MISCREG_MC0_ADDR; break; @@ -388,6 +406,15 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) case 0x412: regNum = MISCREG_MC4_ADDR; break; + case 0x416: + regNum = MISCREG_MC5_ADDR; + break; + case 0x41A: + regNum = MISCREG_MC6_ADDR; + break; + case 0x41E: + regNum = MISCREG_MC7_ADDR; + break; case 0x403: regNum = MISCREG_MC0_MISC; break; @@ -403,6 +430,15 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) case 0x413: regNum = MISCREG_MC4_MISC; break; + case 0x417: + regNum = MISCREG_MC5_MISC; + break; + case 0x41B: + regNum = MISCREG_MC6_MISC; + break; + case 0x41F: + regNum = MISCREG_MC7_MISC; + break; case 0xC0000080: regNum = MISCREG_EFER; break; -- cgit v1.2.3 From de6eeaaa27543f27386b1d9c6528bd60faf75296 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:48:15 -0400 Subject: X86: Make string instructions work when rcx=0. --- .../isa/insts/general_purpose/input_output/string_io.py | 6 ++++++ .../isa/insts/general_purpose/string/compare_strings.py | 16 +++++++++++++--- .../x86/isa/insts/general_purpose/string/load_string.py | 5 ++++- .../x86/isa/insts/general_purpose/string/move_string.py | 5 ++++- .../x86/isa/insts/general_purpose/string/scan_string.py | 16 +++++++++++++--- .../x86/isa/insts/general_purpose/string/store_string.py | 5 ++++- 6 files changed, 44 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py b/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py index 1b4e086d2..29b722d66 100644 --- a/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py +++ b/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py @@ -70,6 +70,8 @@ def macroop INS_M_R { }; def macroop INS_E_M_R { + and t0, rcx, rcx, flags=(EZF,), dataSize=asz + bri t0, label("end"), flags=(CEZF,) # Find the constant we need to either add or subtract from rdi ruflag t0, 10 movi t3, t3, dsz, flags=(CEZF,), dataSize=asz @@ -85,6 +87,7 @@ topOfLoop: subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rdi, rdi, t3, dataSize=asz bri t0, label("topOfLoop"), flags=(nCEZF,) +end: fault "NoFault" }; @@ -104,6 +107,8 @@ def macroop OUTS_R_M { }; def macroop OUTS_E_R_M { + and t0, rcx, rcx, flags=(EZF,), dataSize=asz + bri t0, label("end"), flags=(CEZF,) # Find the constant we need to either add or subtract from rdi ruflag t0, 10 movi t3, t3, dsz, flags=(CEZF,), dataSize=asz @@ -119,6 +124,7 @@ topOfLoop: subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rsi, rsi, t3, dataSize=asz bri t0, label("topOfLoop"), flags=(nCEZF,) +end: fault "NoFault" }; ''' diff --git a/src/arch/x86/isa/insts/general_purpose/string/compare_strings.py b/src/arch/x86/isa/insts/general_purpose/string/compare_strings.py index 71b8511b4..9810fe3c2 100644 --- a/src/arch/x86/isa/insts/general_purpose/string/compare_strings.py +++ b/src/arch/x86/isa/insts/general_purpose/string/compare_strings.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -75,12 +75,16 @@ def macroop CMPS_M_M { # def macroop CMPS_E_M_M { + and t0, rcx, rcx, flags=(EZF,), dataSize=asz + bri t0, label("end"), flags=(CEZF,) + # Find the constant we need to either add or subtract from rdi ruflag t0, 10 movi t3, t3, dsz, flags=(CEZF,), dataSize=asz subi t4, t0, dsz, dataSize=asz mov t3, t3, t4, flags=(nCEZF,), dataSize=asz +topOfLoop: ld t1, seg, [1, t0, rsi] ld t2, es, [1, t0, rdi] sub t0, t1, t2, flags=(OF, SF, ZF, AF, PF, CF) @@ -88,17 +92,22 @@ def macroop CMPS_E_M_M { subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rdi, rdi, t3, dataSize=asz add rsi, rsi, t3, dataSize=asz - bri t0, 4, flags=(CSTRZnEZF,) + bri t0, label("topOfLoop"), flags=(CSTRZnEZF,) +end: fault "NoFault" }; def macroop CMPS_N_M_M { + and t0, rcx, rcx, flags=(EZF,), dataSize=asz + bri t0, label("end"), flags=(CEZF,) + # Find the constant we need to either add or subtract from rdi ruflag t0, 10 movi t3, t3, dsz, flags=(CEZF,), dataSize=asz subi t4, t0, dsz, dataSize=asz mov t3, t3, t4, flags=(nCEZF,), dataSize=asz +topOfLoop: ld t1, seg, [1, t0, rsi] ld t2, es, [1, t0, rdi] sub t0, t1, t2, flags=(OF, SF, ZF, AF, PF, CF) @@ -106,7 +115,8 @@ def macroop CMPS_N_M_M { subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rdi, rdi, t3, dataSize=asz add rsi, rsi, t3, dataSize=asz - bri t0, 4, flags=(CSTRnZnEZF,) + bri t0, label("topOfLoop"), flags=(CSTRnZnEZF,) +end: fault "NoFault" }; ''' diff --git a/src/arch/x86/isa/insts/general_purpose/string/load_string.py b/src/arch/x86/isa/insts/general_purpose/string/load_string.py index 61525c2f2..8cf07fea6 100644 --- a/src/arch/x86/isa/insts/general_purpose/string/load_string.py +++ b/src/arch/x86/isa/insts/general_purpose/string/load_string.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -67,6 +67,8 @@ def macroop LODS_M { }; def macroop LODS_E_M { + and t0, rcx, rcx, flags=(EZF,), dataSize=asz + bri t0, label("end"), flags=(CEZF,) # Find the constant we need to either add or subtract from rdi ruflag t0, 10 movi t3, t3, dsz, flags=(CEZF,), dataSize=asz @@ -79,6 +81,7 @@ topOfLoop: subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rdi, rdi, t3, dataSize=asz bri t0, label("topOfLoop"), flags=(nCEZF,) +end: fault "NoFault" }; ''' diff --git a/src/arch/x86/isa/insts/general_purpose/string/move_string.py b/src/arch/x86/isa/insts/general_purpose/string/move_string.py index b64acfdc2..1d7dd75ad 100644 --- a/src/arch/x86/isa/insts/general_purpose/string/move_string.py +++ b/src/arch/x86/isa/insts/general_purpose/string/move_string.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -69,6 +69,8 @@ def macroop MOVS_M_M { }; def macroop MOVS_E_M_M { + and t0, rcx, rcx, flags=(EZF,), dataSize=asz + bri t0, label("end"), flags=(CEZF,) # Find the constant we need to either add or subtract from rdi ruflag t0, 10 movi t3, t3, dsz, flags=(CEZF,), dataSize=asz @@ -83,6 +85,7 @@ topOfLoop: add rdi, rdi, t3, dataSize=asz add rsi, rsi, t3, dataSize=asz bri t0, label("topOfLoop"), flags=(nCEZF,) +end: fault "NoFault" }; ''' diff --git a/src/arch/x86/isa/insts/general_purpose/string/scan_string.py b/src/arch/x86/isa/insts/general_purpose/string/scan_string.py index b038cc00a..b37e367be 100644 --- a/src/arch/x86/isa/insts/general_purpose/string/scan_string.py +++ b/src/arch/x86/isa/insts/general_purpose/string/scan_string.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -73,34 +73,44 @@ def macroop SCAS_M { # def macroop SCAS_E_M { + and t0, rcx, rcx, flags=(EZF,), dataSize=asz + bri t0, label("end"), flags=(CEZF,) + # Find the constant we need to either add or subtract from rdi ruflag t0, 10 movi t2, t2, dsz, flags=(CEZF,), dataSize=asz subi t3, t0, dsz, dataSize=asz mov t2, t2, t3, flags=(nCEZF,), dataSize=asz +topOfLoop: ld t1, es, [1, t0, rdi] sub t0, t1, rax, flags=(OF, SF, ZF, AF, PF, CF) subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rdi, rdi, t2, dataSize=asz - bri t0, 4, flags=(CSTRZnEZF,) + bri t0, label("topOfLoop"), flags=(CSTRZnEZF,) +end: fault "NoFault" }; def macroop SCAS_N_M { + and t0, rcx, rcx, flags=(EZF,), dataSize=asz + bri t0, label("end"), flags=(CEZF,) + # Find the constant we need to either add or subtract from rdi ruflag t0, 10 movi t2, t2, dsz, flags=(CEZF,), dataSize=asz subi t3, t0, dsz, dataSize=asz mov t2, t2, t3, flags=(nCEZF,), dataSize=asz +topOfLoop: ld t1, es, [1, t0, rdi] sub t0, t1, rax, flags=(OF, SF, ZF, AF, PF, CF) subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rdi, rdi, t2, dataSize=asz - bri t0, 4, flags=(CSTRnZnEZF,) + bri t0, label("topOfLoop"), flags=(CSTRnZnEZF,) +end: fault "NoFault" }; diff --git a/src/arch/x86/isa/insts/general_purpose/string/store_string.py b/src/arch/x86/isa/insts/general_purpose/string/store_string.py index a8d558929..b52b1f1fb 100644 --- a/src/arch/x86/isa/insts/general_purpose/string/store_string.py +++ b/src/arch/x86/isa/insts/general_purpose/string/store_string.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -67,6 +67,8 @@ def macroop STOS_M { }; def macroop STOS_E_M { + and t0, rcx, rcx, flags=(EZF,), dataSize=asz + bri t0, label("end"), flags=(CEZF,) # Find the constant we need to either add or subtract from rdi ruflag t0, 10 movi t3, t3, dsz, flags=(CEZF,), dataSize=asz @@ -79,6 +81,7 @@ topOfLoop: subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rdi, rdi, t3, dataSize=asz bri t0, label("topOfLoop"), flags=(nCEZF,) +end: fault "NoFault" }; ''' -- cgit v1.2.3 From dfc2d44ea346f9e64059f0738c87519adf3fe4d7 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:48:46 -0400 Subject: X86: Flesh out 3dnow instruction decoding a bit and grab the byte immediate. --- src/arch/x86/isa/decoder/two_byte_opcodes.isa | 6 +++--- src/arch/x86/predecoder_tables.cc | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index e2d968c17..5ada6fd4f 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -181,9 +181,9 @@ 0x2: Inst::UD2(); 0x3: Inst::UD2(); 0x4: Inst::UD2(); - 0x5: threednow(); - 0x6: threednow(); - 0x7: threednow(); + 0x5: prefetch(); + 0x6: FailUnimpl::femms(); + 0x7: FailUnimpl::threednow(); } 0x02: decode LEGACY_DECODEVAL { // no prefix diff --git a/src/arch/x86/predecoder_tables.cc b/src/arch/x86/predecoder_tables.cc index a8c719054..f8aff39f1 100644 --- a/src/arch/x86/predecoder_tables.cc +++ b/src/arch/x86/predecoder_tables.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 The Hewlett-Packard Development Company + * Copyright (c) 2007-2008 The Hewlett-Packard Development Company * All rights reserved. * * Redistribution and use of this software in source and binary forms, @@ -201,7 +201,7 @@ namespace X86ISA //For two byte instructions { //LSB // MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F -/* 0 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* 0 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , BY , /* 0 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 2 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 3 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , -- cgit v1.2.3 From 6106b05b6e9cabe3a06da8407818479a5781d249 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:48:58 -0400 Subject: X86: Redo BSF. --- .../general_purpose/compare_and_test/bit_scan.py | 113 ++++++++++----------- 1 file changed, 55 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py b/src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py index f2a3db8a3..bfc0af900 100644 --- a/src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py +++ b/src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py @@ -125,7 +125,6 @@ def macroop BSR_R_R { srli t3, t1, 1, dataSize=8, flags=(EZF,) ori t4, reg, 0x1 mov reg, reg, t4, flags=(nCEZF,) - mov t1, t1, t3, flags=(nCEZF,) end: fault "NoFault" @@ -177,7 +176,6 @@ def macroop BSR_R_M { srli t3, t1, 1, dataSize=8, flags=(EZF,) ori t4, reg, 0x1 mov reg, reg, t4, flags=(nCEZF,) - mov t1, t1, t3, flags=(nCEZF,) end: fault "NoFault" @@ -230,7 +228,6 @@ def macroop BSR_R_P { srli t3, t1, 1, dataSize=8, flags=(EZF,) ori t4, reg, 0x1 mov reg, reg, t4, flags=(nCEZF,) - mov t1, t1, t3, flags=(nCEZF,) end: fault "NoFault" @@ -248,41 +245,41 @@ def macroop BSF_R_R { subi t2, t1, 1 xor t1, t2, t1 + # Bit 6 - srli t3, t1, 32, dataSize=8 - andi t4, t3, 32, flags=(EZF,) - or reg, reg, t4 + srli t3, t1, 32, dataSize=8, flags=(EZF,) + ori t4, reg, 32 + mov reg, reg, t4, flags=(nCEZF,) mov t1, t1, t3, flags=(nCEZF,) # Bit 5 - srli t3, t1, 16, dataSize=8 - andi t4, t3, 16, flags=(EZF,) - or reg, reg, t4 + srli t3, t1, 16, dataSize=8, flags=(EZF,) + ori t4, reg, 16 + mov reg, reg, t4, flags=(nCEZF,) mov t1, t1, t3, flags=(nCEZF,) # Bit 4 - srli t3, t1, 8, dataSize=8 - andi t4, t3, 8, flags=(EZF,) - or reg, reg, t4 + srli t3, t1, 8, dataSize=8, flags=(EZF,) + ori t4, reg, 8 + mov reg, reg, t4, flags=(nCEZF,) mov t1, t1, t3, flags=(nCEZF,) # Bit 3 - srli t3, t1, 4, dataSize=8 - andi t4, t3, 4, flags=(EZF,) - or reg, reg, t4 + srli t3, t1, 4, dataSize=8, flags=(EZF,) + ori t4, reg, 4 + mov reg, reg, t4, flags=(nCEZF,) mov t1, t1, t3, flags=(nCEZF,) # Bit 2 - srli t3, t1, 2, dataSize=8 - andi t4, t3, 2, flags=(EZF,) - or reg, reg, t4 + srli t3, t1, 2, dataSize=8, flags=(EZF,) + ori t4, reg, 2 + mov reg, reg, t4, flags=(nCEZF,) mov t1, t1, t3, flags=(nCEZF,) # Bit 1 - srli t3, t1, 1, dataSize=8 - andi t4, t3, 1, flags=(EZF,) - or reg, reg, t4 - mov t1, t1, t3, flags=(nCEZF,) + srli t3, t1, 1, dataSize=8, flags=(EZF,) + ori t4, reg, 1 + mov reg, reg, t4, flags=(nCEZF,) end: fault "NoFault" @@ -304,39 +301,39 @@ def macroop BSF_R_M { xor t1, t2, t1 # Bit 6 - srli t3, t1, 32, dataSize=8 - andi t4, t3, 32, flags=(EZF,) - or reg, reg, t4 + srli t3, t1, 32, dataSize=8, flags=(EZF,) + ori t4, reg, 32 + mov reg, reg, t4, flags=(nCEZF,) mov t1, t1, t3, flags=(nCEZF,) # Bit 5 - srli t3, t1, 16, dataSize=8 - andi t4, t3, 16, flags=(EZF,) - or reg, reg, t4 + srli t3, t1, 16, dataSize=8, flags=(EZF,) + ori t4, reg, 16 + mov reg, reg, t4, flags=(nCEZF,) mov t1, t1, t3, flags=(nCEZF,) # Bit 4 - srli t3, t1, 8, dataSize=8 - andi t4, t3, 8, flags=(EZF,) - or reg, reg, t4 + srli t3, t1, 8, dataSize=8, flags=(EZF,) + ori t4, reg, 8 + mov reg, reg, t4, flags=(nCEZF,) mov t1, t1, t3, flags=(nCEZF,) # Bit 3 - srli t3, t1, 4, dataSize=8 - andi t4, t3, 4, flags=(EZF,) - or reg, reg, t4 + srli t3, t1, 4, dataSize=8, flags=(EZF,) + ori t4, reg, 4 + mov reg, reg, t4, flags=(nCEZF,) mov t1, t1, t3, flags=(nCEZF,) # Bit 2 - srli t3, t1, 2, dataSize=8 - andi t4, t3, 2, flags=(EZF,) - or reg, reg, t4 + srli t3, t1, 2, dataSize=8, flags=(EZF,) + ori t4, reg, 2 + mov reg, reg, t4, flags=(nCEZF,) mov t1, t1, t3, flags=(nCEZF,) # Bit 1 - srli t3, t1, 1, dataSize=8 - andi t4, t3, 1, flags=(EZF,) - or reg, reg, t4 + srli t3, t1, 1, dataSize=8, flags=(EZF,) + ori t4, reg, 1 + mov reg, reg, t4, flags=(nCEZF,) mov t1, t1, t3, flags=(nCEZF,) end: @@ -360,39 +357,39 @@ def macroop BSF_R_P { xor t1, t2, t1 # Bit 6 - srli t3, t1, 32, dataSize=8 - andi t4, t3, 32, flags=(EZF,) - or reg, reg, t4 + srli t3, t1, 32, dataSize=8, flags=(EZF,) + ori t4, reg, 32 + mov reg, reg, t4, flags=(nCEZF,) mov t1, t1, t3, flags=(nCEZF,) # Bit 5 - srli t3, t1, 16, dataSize=8 - andi t4, t3, 16, flags=(EZF,) - or reg, reg, t4 + srli t3, t1, 16, dataSize=8, flags=(EZF,) + ori t4, reg, 16 + mov reg, reg, t4, flags=(nCEZF,) mov t1, t1, t3, flags=(nCEZF,) # Bit 4 - srli t3, t1, 8, dataSize=8 - andi t4, t3, 8, flags=(EZF,) - or reg, reg, t4 + srli t3, t1, 8, dataSize=8, flags=(EZF,) + ori t4, reg, 8 + mov reg, reg, t4, flags=(nCEZF,) mov t1, t1, t3, flags=(nCEZF,) # Bit 3 - srli t3, t1, 4, dataSize=8 - andi t4, t3, 4, flags=(EZF,) - or reg, reg, t4 + srli t3, t1, 4, dataSize=8, flags=(EZF,) + ori t4, reg, 4 + mov reg, reg, t4, flags=(nCEZF,) mov t1, t1, t3, flags=(nCEZF,) # Bit 2 - srli t3, t1, 2, dataSize=8 - andi t4, t3, 2, flags=(EZF,) - or reg, reg, t4 + srli t3, t1, 2, dataSize=8, flags=(EZF,) + ori t4, reg, 2 + mov reg, reg, t4, flags=(nCEZF,) mov t1, t1, t3, flags=(nCEZF,) # Bit 1 - srli t3, t1, 1, dataSize=8 - andi t4, t3, 1, flags=(EZF,) - or reg, reg, t4 + srli t3, t1, 1, dataSize=8, flags=(EZF,) + ori t4, reg, 1 + mov reg, reg, t4, flags=(nCEZF,) mov t1, t1, t3, flags=(nCEZF,) end: -- cgit v1.2.3 From bbc1f394ffd9d3add42494ad852ac29c3e5e7711 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:49:16 -0400 Subject: X86: Truncate descriptors to 16 bits. --- src/arch/x86/isa/microops/regop.isa | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 03a7515ed..35f1fef02 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -988,20 +988,20 @@ let {{ class Chks(SegOp): code = ''' - // The selector is in source 1. + // The selector is in source 1 and can be at most 16 bits. SegSelector selector = psrc1; // Compute the address of the descriptor and set DestReg to it. if (selector.ti) { // A descriptor in the LDT - Addr target = (selector.esi << 3) + LDTRBase; - if (!LDTRSel || (selector.esi << 3) + dataSize > LDTRLimit) + Addr target = (selector.si << 3) + LDTRBase; + if (!LDTRSel || (selector.si << 3) + dataSize > LDTRLimit) fault = new GeneralProtection(selector & mask(16)); DestReg = target; } else { // A descriptor in the GDT - Addr target = (selector.esi << 3) + GDTRBase; - if ((selector.esi << 3) + dataSize > GDTRLimit) + Addr target = (selector.si << 3) + GDTRBase; + if ((selector.si << 3) + dataSize > GDTRLimit) fault = new GeneralProtection(selector & mask(16)); DestReg = target; } @@ -1009,7 +1009,7 @@ let {{ flag_code = ''' // Check for a NULL selector and set ZF,EZF appropriately. ccFlagBits = ccFlagBits & ~(ext & (ZFBit | EZFBit)); - if (!selector.esi && !selector.ti) + if (!selector.si && !selector.ti) ccFlagBits = ccFlagBits | (ext & (ZFBit | EZFBit)); ''' -- cgit v1.2.3 From 2bb8933f789d65f47a322e1384eb2e500699bf14 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:49:25 -0400 Subject: X86: Add microops which panic, fatal, warn, and warn_once. --- src/arch/x86/isa/includes.isa | 3 +- src/arch/x86/isa/microops/debug.isa | 229 +++++++++++++++++++++++++++++++++ src/arch/x86/isa/microops/microops.isa | 5 +- 3 files changed, 235 insertions(+), 2 deletions(-) create mode 100644 src/arch/x86/isa/microops/debug.isa (limited to 'src') diff --git a/src/arch/x86/isa/includes.isa b/src/arch/x86/isa/includes.isa index 6724ea9b0..6d0fe6d86 100644 --- a/src/arch/x86/isa/includes.isa +++ b/src/arch/x86/isa/includes.isa @@ -26,7 +26,7 @@ // // Authors: Gabe Black -// Copyright (c) 2007 The Hewlett-Packard Development Company +// Copyright (c) 2007-2008 The Hewlett-Packard Development Company // All rights reserved. // // Redistribution and use of this software in source and binary forms, @@ -117,6 +117,7 @@ output decoder {{ #include "arch/x86/segmentregs.hh" #include "base/cprintf.hh" #include "base/loader/symtab.hh" +#include "base/misc.hh" #include "cpu/thread_context.hh" // for Jump::branchTarget() #include "mem/packet.hh" diff --git a/src/arch/x86/isa/microops/debug.isa b/src/arch/x86/isa/microops/debug.isa new file mode 100644 index 000000000..7456b0d4e --- /dev/null +++ b/src/arch/x86/isa/microops/debug.isa @@ -0,0 +1,229 @@ +// Copyright (c) 2008 The Hewlett-Packard Development Company +// All rights reserved. +// +// Redistribution and use of this software in source and binary forms, +// with or without modification, are permitted provided that the +// following conditions are met: +// +// The software must be used only for Non-Commercial Use which means any +// use which is NOT directed to receiving any direct monetary +// compensation for, or commercial advantage from such use. Illustrative +// examples of non-commercial use are academic research, personal study, +// teaching, education and corporate research & development. +// Illustrative examples of commercial use are distributing products for +// commercial advantage and providing services using the software for +// commercial advantage. +// +// If you wish to use this software or functionality therein that may be +// covered by patents for commercial use, please contact: +// Director of Intellectual Property Licensing +// Office of Strategy and Technology +// Hewlett-Packard Company +// 1501 Page Mill Road +// Palo Alto, California 94304 +// +// 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. No right of +// sublicense is granted herewith. Derivatives of the software and +// output created using the software may be prepared, but only for +// Non-Commercial Uses. Derivatives of the software may be shared with +// others provided: (i) the others agree to abide by the list of +// conditions herein which includes the Non-Commercial Use restrictions; +// and (ii) such Derivatives of the software include the above copyright +// notice to acknowledge the contribution from this software where +// applicable, this list of conditions and the disclaimer below. +// +// 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: Gabe Black + +////////////////////////////////////////////////////////////////////////// +// +// Debug Microops +// +////////////////////////////////////////////////////////////////////////// + +output header {{ + class MicroDebugBase : public X86ISA::X86MicroopBase + { + protected: + std::string message; + uint8_t cc; + + public: + MicroDebugBase(ExtMachInst _machInst, const char * mnem, + const char * instMnem, + bool isMicro, bool isDelayed, bool isFirst, bool isLast, + std::string _message, uint8_t _cc); + + MicroDebugBase(ExtMachInst _machInst, const char * mnem, + const char * instMnem, std::string _message, uint8_t _cc); + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + }; +}}; + +def template MicroDebugDeclare {{ + class %(class_name)s : public %(base_class)s + { + private: + void buildMe(); + public: + %(class_name)s(ExtMachInst _machInst, const char * instMnem, + bool isMicro, bool isDelayed, bool isFirst, bool isLast, + std::string _message, uint8_t _cc); + + %(class_name)s(ExtMachInst _machInst, const char * instMnem, + std::string _message, uint8_t _cc); + + %(BasicExecDeclare)s + }; +}}; + +def template MicroDebugExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + %(op_decl)s + %(op_rd)s + if (%(cond_test)s) { + %(func)s(message + "\n"); + } + return NoFault; + } +}}; + +output decoder {{ + inline MicroDebugBase::MicroDebugBase( + ExtMachInst machInst, const char * mnem, const char * instMnem, + std::string _message, uint8_t _cc) : + X86MicroopBase(machInst, mnem, instMnem, + false, false, false, false, No_OpClass), + message(_message), cc(_cc) + { + } + + inline MicroDebugBase::MicroDebugBase( + ExtMachInst machInst, const char * mnem, const char * instMnem, + bool isMicro, bool isDelayed, bool isFirst, bool isLast, + std::string _message, uint8_t _cc) : + X86MicroopBase(machInst, mnem, instMnem, + isMicro, isDelayed, isFirst, isLast, No_OpClass), + message(_message), cc(_cc) + { + } +}}; + +def template MicroDebugConstructor {{ + + inline void %(class_name)s::buildMe() + { + %(constructor)s; + } + + inline %(class_name)s::%(class_name)s( + ExtMachInst machInst, const char * instMnem, + std::string _message, uint8_t _cc) : + %(base_class)s(machInst, "%(func)s", instMnem, _message, _cc) + { + buildMe(); + } + + inline %(class_name)s::%(class_name)s( + ExtMachInst machInst, const char * instMnem, + bool isMicro, bool isDelayed, bool isFirst, bool isLast, + std::string _message, uint8_t _cc) : + %(base_class)s(machInst, "%(func)s", instMnem, + isMicro, isDelayed, isFirst, isLast, _message, _cc) + { + buildMe(); + } +}}; + +output decoder {{ + std::string MicroDebugBase::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, instMnem, mnemonic); + response << "\"" << message << "\""; + + return response.str(); + } +}}; + +let {{ + class MicroDebug(X86Microop): + def __init__(self, message, flags=None): + self.message = message + if flags: + if not isinstance(flags, (list, tuple)): + raise Exception, "flags must be a list or tuple of flags" + self.cond = " | ".join(flags) + self.className += "Flags" + else: + self.cond = "0" + + def getAllocator(self, *microFlags): + allocator = '''new %(class_name)s(machInst, mnemonic + %(flags)s, "%(message)s", %(cc)s)''' % { + "class_name" : self.className, + "flags" : self.microFlagsText(microFlags), + "message" : self.message, + "cc" : self.cond} + return allocator + + exec_output = "" + header_output = "" + decoder_output = "" + + def buildDebugMicro(func): + global exec_output, header_output, decoder_output + + iop = InstObjParams(func, "Micro%sFlags" % func.capitalize(), + "MicroDebugBase", + {"code": "", + "func": func, + "cond_test": "checkCondition(ccFlagBits, cc)"}) + exec_output += MicroDebugExecute.subst(iop) + header_output += MicroDebugDeclare.subst(iop) + decoder_output += MicroDebugConstructor.subst(iop) + + iop = InstObjParams(func, "Micro%s" % func.capitalize(), + "MicroDebugBase", + {"code": "", + "func": func, + "cond_test": "true"}) + exec_output += MicroDebugExecute.subst(iop) + header_output += MicroDebugDeclare.subst(iop) + decoder_output += MicroDebugConstructor.subst(iop) + + class MicroDebugChild(MicroDebug): + className = "Micro%s" % func.capitalize() + + global microopClasses + microopClasses[func] = MicroDebugChild + + buildDebugMicro("panic") + buildDebugMicro("fatal") + buildDebugMicro("warn") + buildDebugMicro("warn_once") +}}; diff --git a/src/arch/x86/isa/microops/microops.isa b/src/arch/x86/isa/microops/microops.isa index 53f34d3f2..1c9e8358a 100644 --- a/src/arch/x86/isa/microops/microops.isa +++ b/src/arch/x86/isa/microops/microops.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2007 The Hewlett-Packard Development Company +// Copyright (c) 2007-2008 The Hewlett-Packard Development Company // All rights reserved. // // Redistribution and use of this software in source and binary forms, @@ -70,3 +70,6 @@ //Miscellaneous microop definitions ##include "specop.isa" + +//Microops for printing out debug messages through M5 +##include "debug.isa" -- cgit v1.2.3 From e0c20386ac0f8f54db2e8947793b4c2debabcefc Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:49:50 -0400 Subject: X86: Add microops and supporting code to manipulate the whole rflags register. --- .../insts/general_purpose/flags/push_and_pop.py | 8 +++---- src/arch/x86/isa/microasm.isa | 5 ++-- src/arch/x86/isa/microops/regop.isa | 27 ++++++++++++++++++++++ src/arch/x86/isa/operands.isa | 7 ++++-- src/arch/x86/miscregs.hh | 12 ++++++++++ 5 files changed, 50 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/flags/push_and_pop.py b/src/arch/x86/isa/insts/general_purpose/flags/push_and_pop.py index fe60350c1..5937ac074 100644 --- a/src/arch/x86/isa/insts/general_purpose/flags/push_and_pop.py +++ b/src/arch/x86/isa/insts/general_purpose/flags/push_and_pop.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -57,8 +57,7 @@ microcode = ''' def macroop PUSHF { .adjust_env oszIn64Override - # This should really read the whole flags register, not just user flags. - ruflags t1 + rflags t1 stupd t1, ss, [1, t0, rsp], "-env.dataSize" }; @@ -67,7 +66,6 @@ def macroop POPF { ld t1, ss, [1, t0, rsp] addi rsp, rsp, dsz - # This should really write the whole flags register, not just user flags. - wruflags t1, t0 + wrflags t1, t0 }; ''' diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa index 78ae34f52..18abdf09b 100644 --- a/src/arch/x86/isa/microasm.isa +++ b/src/arch/x86/isa/microasm.isa @@ -1,6 +1,6 @@ // -*- mode:c++ -*- -// Copyright (c) 2007 The Hewlett-Packard Development Company +// Copyright (c) 2007-2008 The Hewlett-Packard Development Company // All rights reserved. // // Redistribution and use of this software in source and binary forms, @@ -135,7 +135,8 @@ let {{ for reg in range(15): assembler.symbols["cr%d" % reg] = "MISCREG_CR%d" % reg - for flag in ('CF', 'PF', 'ECF', 'AF', 'EZF', 'ZF', 'SF', 'OF'): + for flag in ('CF', 'PF', 'ECF', 'AF', 'EZF', 'ZF', 'SF', 'OF', \ + 'TF', 'IF', 'NT', 'RF', 'VM', 'AC', 'VIF', 'VIP', 'ID'): assembler.symbols[flag] = flag + "Bit" for cond in ('True', 'False', 'ECF', 'EZF', 'SZnZF', diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 35f1fef02..0187567e9 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -845,12 +845,25 @@ let {{ class Wruflags(WrRegOp): code = 'ccFlagBits = psrc1 ^ op2' + class Wrflags(WrRegOp): + code = ''' + MiscReg newFlags = psrc1 ^ op2; + MiscReg userFlagMask = 0xDD5; + // Get only the user flags + ccFlagBits = newFlags & userFlagMask; + // Get everything else + nccFlagBits = newFlags & ~userFlagMask; + ''' + class Rdip(RdRegOp): code = 'DestReg = RIP - CSBase' class Ruflags(RdRegOp): code = 'DestReg = ccFlagBits' + class Rflags(RdRegOp): + code = 'DestReg = ccFlagBits | nccFlagBits' + class Ruflag(RegOp): code = ''' int flag = bits(ccFlagBits, imm8); @@ -863,6 +876,20 @@ let {{ super(Ruflag, self).__init__(dest, \ "NUM_INTREGS", imm, flags, dataSize) + class Rflag(RegOp): + code = ''' + MiscReg flagMask = 0x3F7FDD5; + MiscReg flags = (nccFlagBits | ccFlagBits) & flagMask; + int flag = bits(flags, imm8); + DestReg = merge(DestReg, flag, dataSize); + ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) : + (ccFlagBits & ~EZFBit); + ''' + def __init__(self, dest, imm, flags=None, \ + dataSize="env.dataSize"): + super(Rflag, self).__init__(dest, \ + "NUM_INTREGS", imm, flags, dataSize) + class Sext(RegOp): code = ''' IntReg val = psrc1; diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa index 87fd28a6a..b48e8759f 100644 --- a/src/arch/x86/isa/operands.isa +++ b/src/arch/x86/isa/operands.isa @@ -117,10 +117,13 @@ def operands {{ 'RIP': ('NPC', 'uqw', None, (None, None, 'IsControl'), 50), 'uIP': ('UPC', 'uqw', None, (None, None, 'IsControl'), 51), 'nuIP': ('NUPC', 'uqw', None, (None, None, 'IsControl'), 52), + # This holds the condition code portion of the flag register. The + # nccFlagBits version holds the rest. 'ccFlagBits': ('IntReg', 'uqw', 'INTREG_PSEUDO(0)', None, 60), - # The TOP register should needs to be more protected so that later + # These register should needs to be more protected so that later # instructions don't map their indexes with an old value. - 'TOP': ('ControlReg', 'ub', 'MISCREG_X87_TOP', None, 61), + 'nccFlagBits': ('ControlReg', 'uqw', 'MISCREG_RFLAGS', None, 61), + 'TOP': ('ControlReg', 'ub', 'MISCREG_X87_TOP', None, 62), # The segment base as used by memory instructions. 'SegBase': ('ControlReg', 'uqw', 'MISCREG_SEG_EFF_BASE(segment)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 70), diff --git a/src/arch/x86/miscregs.hh b/src/arch/x86/miscregs.hh index 83ba3c0c5..90f1d9fda 100644 --- a/src/arch/x86/miscregs.hh +++ b/src/arch/x86/miscregs.hh @@ -82,6 +82,18 @@ namespace X86ISA OFBit = 1 << 11 }; + enum RFLAGBit { + TFBit = 1 << 8, + IFBit = 1 << 9, + NTBit = 1 << 14, + RFBit = 1 << 16, + VMBit = 1 << 17, + ACBit = 1 << 18, + VIFBit = 1 << 19, + VIPBit = 1 << 20, + IDBit = 1 << 21 + }; + enum MiscRegIndex { // Control registers -- cgit v1.2.3 From 6bd9cf3594b0150c8cb39a23ca2cfb465b6e09bb Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:50:05 -0400 Subject: X86: Add a microop to read a segments attribute register. --- src/arch/x86/isa/microops/regop.isa | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 0187567e9..48aecf138 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -1008,6 +1008,11 @@ let {{ DestReg = SegLimitSrc1; ''' + class RdAttr(SegOp): + code = ''' + DestReg = SegAttrSrc1; + ''' + class Rdsel(SegOp): code = ''' DestReg = SegSelSrc1; -- cgit v1.2.3 From fa7c81c6df5fdc1a17ffebbf431cb57ac84d79d0 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:50:10 -0400 Subject: X86: Change what the microop chks does. Instead of computing the segment descriptor address, this now checks if a selector value/descriptor are legal for a particular purpose. --- src/arch/x86/isa/microasm.isa | 5 +++++ src/arch/x86/isa/microops/regop.isa | 42 ++++++++++++++++++++++++++++++++++++- src/arch/x86/isa/operands.isa | 3 ++- 3 files changed, 48 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa index 18abdf09b..735a7722c 100644 --- a/src/arch/x86/isa/microasm.isa +++ b/src/arch/x86/isa/microasm.isa @@ -81,6 +81,11 @@ let {{ for letter in ("C", "D", "E", "F", "G", "S"): assembler.symbols["%ss" % letter.lower()] = "SEGMENT_REG_%sS" % letter + # Add in symbols for the various checks of segment selectors. + for check in ("NoCheck", "CSCheck", "CallGateCheck", + "SSCheck", "IretCheck", "IntCSCheck"): + assembler.symbols[check] = "Seg%s" % check + for reg in ("TR", "IDTR"): assembler.symbols[reg.lower()] = "SYS_SEGMENT_REG_%s" % reg diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 48aecf138..6bd26608e 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -231,6 +231,11 @@ output header {{ void divide(uint64_t dividend, uint64_t divisor, uint64_t "ient, uint64_t &remainder); + + enum SegmentSelectorCheck { + SegNoCheck, SegCSCheck, SegCallGateCheck, + SegSSCheck, SegIretCheck, SegIntCSCheck + }; }}; output decoder {{ @@ -1018,11 +1023,46 @@ let {{ DestReg = SegSelSrc1; ''' - class Chks(SegOp): + class Chks(RegOp): + def __init__(self, dest, src1, src2=0, + flags=None, dataSize="env.dataSize"): + super(Chks, self).__init__(dest, + src1, src2, flags, dataSize) code = ''' // The selector is in source 1 and can be at most 16 bits. SegSelector selector = psrc1; + switch (imm8) + { + case SegNoCheck: + break; + case SegCSCheck: + panic("CS checks for far calls/jumps not implemented.\\n"); + break; + case SegCallGateCheck: + panic("CS checks for far calls/jumps through call gates" + "not implemented.\\n"); + break; + case SegSSCheck: + panic("SS selector checks not implemented.\\n"); + break; + case SegIretCheck: + { + SegAttr csAttr = CSAttr; + if (!selector.si && !selector.ti) + return new GeneralProtection(psrc1 & 0xFFFF); + if (selector.rpl < csAttr.dpl) + return new GeneralProtection(psrc1 & 0xFFFF); + break; + } + case SegIntCSCheck: + panic("CS selector checks for interrupts and exceptions" + "not implemented.\\n"); + break; + default: + panic("Undefined segment check type.\\n"); + } + // Compute the address of the descriptor and set DestReg to it. if (selector.ti) { // A descriptor in the LDT diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa index b48e8759f..f002b2cea 100644 --- a/src/arch/x86/isa/operands.isa +++ b/src/arch/x86/isa/operands.isa @@ -149,6 +149,7 @@ def operands {{ 'GDTRBase': ('ControlReg', 'uqw', 'MISCREG_TSG_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 205), 'GDTRLimit': ('ControlReg', 'uqw', 'MISCREG_TSG_LIMIT', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 206), 'CSBase': ('ControlReg', 'udw', 'MISCREG_CS_EFF_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 207), - 'TscOp': ('ControlReg', 'udw', 'MISCREG_TSC', (None, None, ['IsSerializeAfter', 'IsSerializing', 'IsNonSpeculative']), 208), + 'CSAttr': ('ControlReg', 'udw', 'MISCREG_CS_ATTR', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 208), + 'TscOp': ('ControlReg', 'udw', 'MISCREG_TSC', (None, None, ['IsSerializeAfter', 'IsSerializing', 'IsNonSpeculative']), 209), 'Mem': ('Mem', 'uqw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 300) }}; -- cgit v1.2.3 From d4e7c7edd35d1f5e6771077eeca83369c1169a33 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:50:25 -0400 Subject: X86: Keep handy values like the operating mode in one register. --- src/arch/x86/isa/microops/regop.isa | 5 +++++ src/arch/x86/isa/operands.isa | 1 + src/arch/x86/miscregfile.cc | 30 +++++++++++++++++++++++++++++- src/arch/x86/miscregs.hh | 9 +++++++++ 4 files changed, 44 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 6bd26608e..35f319528 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -1100,6 +1100,11 @@ let {{ DestReg = TscOp; ''' + class Rdm5reg(RdRegOp): + code = ''' + DestReg = M5Reg; + ''' + class Wrdl(RegOp): code = ''' SegDescriptor desc = SrcReg1; diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa index f002b2cea..446580c1b 100644 --- a/src/arch/x86/isa/operands.isa +++ b/src/arch/x86/isa/operands.isa @@ -151,5 +151,6 @@ def operands {{ 'CSBase': ('ControlReg', 'udw', 'MISCREG_CS_EFF_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 207), 'CSAttr': ('ControlReg', 'udw', 'MISCREG_CS_ATTR', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 208), 'TscOp': ('ControlReg', 'udw', 'MISCREG_TSC', (None, None, ['IsSerializeAfter', 'IsSerializing', 'IsNonSpeculative']), 209), + 'M5Reg': ('ControlReg', 'udw', 'MISCREG_M5_REG', (None, None, None), 210), 'Mem': ('Mem', 'uqw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 300) }}; diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc index 930bf53c7..6abeb7d34 100644 --- a/src/arch/x86/miscregfile.cc +++ b/src/arch/x86/miscregfile.cc @@ -300,17 +300,39 @@ void MiscRegFile::setReg(int miscReg, CR0 toggled = regVal[miscReg] ^ val; CR0 newCR0 = val; Efer efer = regVal[MISCREG_EFER]; + HandyM5Reg m5reg = regVal[MISCREG_M5_REG]; if (toggled.pg && efer.lme) { if (newCR0.pg) { //Turning on long mode efer.lma = 1; + m5reg.mode = LongMode; regVal[MISCREG_EFER] = efer; } else { //Turning off long mode efer.lma = 0; + m5reg.mode = LegacyMode; regVal[MISCREG_EFER] = efer; } } + // Figure out what submode we're in. + if (m5reg.mode == LongMode) { + SegAttr csAttr = regVal[MISCREG_CS_ATTR]; + if (csAttr.longMode) + m5reg.submode = SixtyFourBitMode; + else + m5reg.submode = CompatabilityMode; + } else { + if (newCR0.pe) { + RFLAGS rflags = regVal[MISCREG_RFLAGS]; + if (rflags.vm) + m5reg.submode = Virtual8086Mode; + else + m5reg.submode = ProtectedMode; + } else { + m5reg.submode = RealMode; + } + } + regVal[MISCREG_M5_REG] = m5reg; if (toggled.pg) { tc->getITBPtr()->invalidateAll(); tc->getDTBPtr()->invalidateAll(); @@ -341,20 +363,26 @@ void MiscRegFile::setReg(int miscReg, { SegAttr toggled = regVal[miscReg] ^ val; SegAttr newCSAttr = val; + HandyM5Reg m5reg = regVal[MISCREG_M5_REG]; if (toggled.longMode) { - SegAttr newCSAttr = val; if (newCSAttr.longMode) { + if (m5reg.mode == LongMode) + m5reg.submode = SixtyFourBitMode; regVal[MISCREG_ES_EFF_BASE] = 0; regVal[MISCREG_CS_EFF_BASE] = 0; regVal[MISCREG_SS_EFF_BASE] = 0; regVal[MISCREG_DS_EFF_BASE] = 0; } else { + if (m5reg.mode == LongMode) + m5reg.submode = CompatabilityMode; regVal[MISCREG_ES_EFF_BASE] = regVal[MISCREG_ES_BASE]; regVal[MISCREG_CS_EFF_BASE] = regVal[MISCREG_CS_BASE]; regVal[MISCREG_SS_EFF_BASE] = regVal[MISCREG_SS_BASE]; regVal[MISCREG_DS_EFF_BASE] = regVal[MISCREG_DS_BASE]; } } + m5reg.cpl = newCSAttr.dpl; + regVal[MISCREG_M5_REG] = m5reg; } break; // These segments always actually use their bases, or in other words diff --git a/src/arch/x86/miscregs.hh b/src/arch/x86/miscregs.hh index 90f1d9fda..caa1e817b 100644 --- a/src/arch/x86/miscregs.hh +++ b/src/arch/x86/miscregs.hh @@ -130,6 +130,9 @@ namespace X86ISA // Flags register MISCREG_RFLAGS = MISCREG_DR_BASE + NumDRegs, + //Register to keep handy values like the CPU mode in. + MISCREG_M5_REG, + /* * Model Specific Registers */ @@ -563,6 +566,12 @@ namespace X86ISA Bitfield<0> cf; // Carry Flag EndBitUnion(RFLAGS) + BitUnion64(HandyM5Reg) + Bitfield<0> mode; + Bitfield<3, 1> submode; + Bitfield<5, 4> cpl; + EndBitUnion(HandyM5Reg) + /** * Control registers */ -- cgit v1.2.3 From a8384311d544391b03ff55f9384fdf8da2fa8bf6 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:51:14 -0400 Subject: X86: Take advantage of the new meta register. --- src/arch/x86/predecoder.cc | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/arch/x86/predecoder.cc b/src/arch/x86/predecoder.cc index 407a09ec0..1d415ffea 100644 --- a/src/arch/x86/predecoder.cc +++ b/src/arch/x86/predecoder.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 The Hewlett-Packard Development Company + * Copyright (c) 2007-2008 The Hewlett-Packard Development Company * All rights reserved. * * Redistribution and use of this software in source and binary forms, @@ -55,9 +55,11 @@ * Authors: Gabe Black */ +#include "arch/x86/miscregs.hh" #include "arch/x86/predecoder.hh" #include "base/misc.hh" #include "base/trace.hh" +#include "cpu/thread_context.hh" #include "sim/host.hh" namespace X86ISA @@ -78,7 +80,9 @@ namespace X86ISA emi.modRM = 0; emi.sib = 0; - emi.mode = 0; + HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); + emi.mode.mode = m5reg.mode; + emi.mode.submode = m5reg.submode; } void Predecoder::process() @@ -209,10 +213,12 @@ namespace X86ISA DPRINTF(Predecoder, "Found opcode %#x.\n", nextByte); emi.opcode.op = nextByte; + SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR); + //Figure out the effective operand size. This can be overriden to //a fixed value at the decoder level. int logOpSize; - if(/*FIXME long mode*/1) + if (emi.mode.submode == SixtyFourBitMode) { if(emi.rex.w) logOpSize = 3; // 64 bit operand size @@ -221,7 +227,7 @@ namespace X86ISA else logOpSize = 2; // 32 bit operand size } - else if(/*FIXME default 32*/1) + else if(csAttr.defaultSize) { if(emi.legacy.op) logOpSize = 1; // 16 bit operand size @@ -242,14 +248,14 @@ namespace X86ISA //Figure out the effective address size. This can be overriden to //a fixed value at the decoder level. int logAddrSize; - if(/*FIXME 64-bit mode*/1) + if(emi.mode.submode == SixtyFourBitMode) { if(emi.legacy.addr) logAddrSize = 2; // 32 bit address size else logAddrSize = 3; // 64 bit address size } - else if(/*FIXME default 32*/1) + else if(csAttr.defaultSize) { if(emi.legacy.addr) logAddrSize = 1; // 16 bit address size @@ -264,6 +270,16 @@ namespace X86ISA logAddrSize = 1; // 16 bit address size } + SegAttr ssAttr = tc->readMiscRegNoEffect(MISCREG_SS_ATTR); + //Figure out the effective stack width. This can be overriden to + //a fixed value at the decoder level. + if(emi.mode.submode == SixtyFourBitMode) + emi.stackSize = 8; // 64 bit stack width + else if(ssAttr.defaultSize) + emi.stackSize = 4; // 32 bit stack width + else + emi.stackSize = 2; // 16 bit stack width + //Set the actual address size emi.addrSize = 1 << logAddrSize; @@ -299,7 +315,9 @@ namespace X86ISA ModRM modRM; modRM = nextByte; DPRINTF(Predecoder, "Found modrm byte %#x.\n", nextByte); - if (0) {//FIXME in 16 bit mode + SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR); + if (emi.mode.submode != SixtyFourBitMode && + !csAttr.defaultSize) { //figure out 16 bit displacement size if(modRM.mod == 0 && modRM.rm == 6 || modRM.mod == 2) displacementSize = 2; -- cgit v1.2.3 From b05299253fdd5a8a913f2799b7cdd2df040c8559 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:51:50 -0400 Subject: X86: In non 64bit mode, throw a fault when a NULL segment is accessed. --- src/arch/x86/tlb.cc | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index f5e214a88..5d101a5ae 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -571,6 +571,9 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) // If we're not in 64-bit mode, do protection/limit checks if (!efer.lma || !csAttr.longMode) { DPRINTF(TLB, "Not in long mode. Checking segment protection.\n"); + // Check for a NULL segment selector. + if (!tc->readMiscRegNoEffect(MISCREG_SEG_SEL(seg))) + return new GeneralProtection(0); SegAttr attr = tc->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg)); if (!attr.writable && write) return new GeneralProtection(0); -- cgit v1.2.3 From 129831c116a6c7031093df624761f8d67bf4e115 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:51:57 -0400 Subject: X86: Make pushes and pops use the stack size instead of the data size. --- .../data_transfer/stack_operations.py | 96 +++++++++++----------- .../insts/general_purpose/flags/push_and_pop.py | 6 +- 2 files changed, 51 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py b/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py index 6c51f3171..64efd7dc9 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py +++ b/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -58,8 +58,8 @@ def macroop POP_R { # Make the default data size of pops 64 bits in 64 bit mode .adjust_env oszIn64Override - ld t1, ss, [1, t0, rsp] - addi rsp, rsp, dsz + ld t1, ss, [1, t0, rsp], dataSize=ssz + addi rsp, rsp, ssz, dataSize=asz mov reg, reg, t1 }; @@ -67,10 +67,10 @@ def macroop POP_M { # Make the default data size of pops 64 bits in 64 bit mode .adjust_env oszIn64Override - ld t1, ss, [1, t0, rsp] - cda seg, sib, disp - addi rsp, rsp, dsz - st t1, seg, sib, disp + ld t1, ss, [1, t0, rsp], dataSize=ssz + cda seg, sib, disp, dataSize=ssz + addi rsp, rsp, ssz, dataSize=asz + st t1, seg, sib, disp, dataSize=ssz }; def macroop POP_P { @@ -78,17 +78,17 @@ def macroop POP_P { .adjust_env oszIn64Override rdip t7 - ld t1, ss, [1, t0, rsp] - cda seg, sib, disp - addi rsp, rsp, dsz - st t1, seg, riprel, disp + ld t1, ss, [1, t0, rsp], dataSize=ssz + cda seg, sib, disp, dataSize=ssz + addi rsp, rsp, ssz, dataSize=asz + st t1, seg, riprel, disp, dataSize=ssz }; def macroop PUSH_R { # Make the default data size of pops 64 bits in 64 bit mode .adjust_env oszIn64Override - stupd reg, ss, [1, t0, rsp], "-env.dataSize" + stupd reg, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz }; def macroop PUSH_I { @@ -96,15 +96,15 @@ def macroop PUSH_I { .adjust_env oszIn64Override limm t1, imm - stupd t1, ss, [1, t0, rsp], "-env.dataSize" + stupd t1, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz }; def macroop PUSH_M { # Make the default data size of pops 64 bits in 64 bit mode .adjust_env oszIn64Override - ld t1, seg, sib, disp - stupd t1, ss, [1, t0, rsp], "-env.dataSize" + ld t1, seg, sib, disp, dataSize=ssz + stupd t1, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz }; def macroop PUSH_P { @@ -112,48 +112,48 @@ def macroop PUSH_P { .adjust_env oszIn64Override rdip t7 - ld t1, seg, riprel, disp - stupd t1, ss, [1, t0, rsp], "-env.dataSize" + ld t1, seg, riprel, disp, dataSize=ssz + stupd t1, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz }; def macroop PUSHA { # Check all the stack addresses. We'll assume that if the beginning and # end are ok, then the stuff in the middle should be as well. - cda ss, [1, t0, rsp], "-env.dataSize" - cda ss, [1, t0, rsp], "-8 * env.dataSize" - stupd rax, ss, [1, t0, rsp], "-env.dataSize" - stupd rcx, ss, [1, t0, rsp], "-env.dataSize" - stupd rdx, ss, [1, t0, rsp], "-env.dataSize" - stupd rbx, ss, [1, t0, rsp], "-env.dataSize" - stupd rsp, ss, [1, t0, rsp], "-env.dataSize" - stupd rbp, ss, [1, t0, rsp], "-env.dataSize" - stupd rsi, ss, [1, t0, rsp], "-env.dataSize" - stupd rdi, ss, [1, t0, rsp], "-env.dataSize" + cda ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz + cda ss, [1, t0, rsp], "-8 * env.stackSize", dataSize=ssz + stupd rax, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz + stupd rcx, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz + stupd rdx, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz + stupd rbx, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz + stupd rsp, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz + stupd rbp, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz + stupd rsi, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz + stupd rdi, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz }; def macroop POPA { # Check all the stack addresses. We'll assume that if the beginning and # end are ok, then the stuff in the middle should be as well. - ld t1, ss, [1, t0, rsp], "0 * env.dataSize" - ld t2, ss, [1, t0, rsp], "7 * env.dataSize" - mov rdi, rdi, t1 - ld rsi, ss, [1, t0, rsp], "1 * env.dataSize" - ld rbp, ss, [1, t0, rsp], "2 * env.dataSize" - ld rbx, ss, [1, t0, rsp], "4 * env.dataSize" - ld rdx, ss, [1, t0, rsp], "5 * env.dataSize" - ld rcx, ss, [1, t0, rsp], "6 * env.dataSize" - mov rax, rax, t2 - addi rsp, rsp, "8 * env.dataSize" + ld t1, ss, [1, t0, rsp], "0 * env.stackSize", dataSize=ssz + ld t2, ss, [1, t0, rsp], "7 * env.stackSize", dataSize=ssz + mov rdi, rdi, t1, dataSize=ssz + ld rsi, ss, [1, t0, rsp], "1 * env.stackSize", dataSize=ssz + ld rbp, ss, [1, t0, rsp], "2 * env.stackSize", dataSize=ssz + ld rbx, ss, [1, t0, rsp], "4 * env.stackSize", dataSize=ssz + ld rdx, ss, [1, t0, rsp], "5 * env.stackSize", dataSize=ssz + ld rcx, ss, [1, t0, rsp], "6 * env.stackSize", dataSize=ssz + mov rax, rax, t2, dataSize=ssz + addi rsp, rsp, "8 * env.stackSize", dataSize=asz }; def macroop LEAVE { # Make the default data size of pops 64 bits in 64 bit mode .adjust_env oszIn64Override - mov t1, t1, rbp - ld rbp, ss, [1, t0, t1] - mov rsp, rsp, t1 - addi rsp, rsp, dsz + mov t1, t1, rbp, dataSize=asz + ld rbp, ss, [1, t0, t1], dataSize=ssz + mov rsp, rsp, t1, dataSize=asz + addi rsp, rsp, ssz, dataSize=asz }; def macroop ENTER_I_I { @@ -168,10 +168,10 @@ def macroop ENTER_I_I { # t1 is now the masked nesting level, and t2 is the amount of storage. # Push rbp. - stupd rbp, ss, [1, t0, rsp], "-env.dataSize" + stupd rbp, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz # Save the stack pointer for later - mov t6, t6, rsp + mov t6, t6, rsp, dataSize=asz # If the nesting level is zero, skip all this stuff. subi t0, t1, t0, flags=(EZF,), dataSize=2 @@ -183,8 +183,8 @@ def macroop ENTER_I_I { limm t4, "ULL(-1)", dataSize=8 topOfLoop: - ld t5, ss, [dsz, t4, rbp] - stupd t5, ss, [1, t0, rsp], "-env.dataSize" + ld t5, ss, [ssz, t4, rbp], dataSize=ssz + stupd t5, ss, [1, t0, rsp], "-env.stackSize" # If we're not done yet, loop subi t4, t4, 1, dataSize=8 @@ -193,10 +193,10 @@ topOfLoop: bottomOfLoop: # Push the old rbp onto the stack - stupd t6, ss, [1, t0, rsp], "-env.dataSize" + stupd t6, ss, [1, t0, rsp], "-env.stackSize" skipLoop: - sub rsp, rsp, t2 - mov rbp, rbp, t6 + sub rsp, rsp, t2, dataSize=asz + mov rbp, rbp, t6, dataSize=asz }; ''' diff --git a/src/arch/x86/isa/insts/general_purpose/flags/push_and_pop.py b/src/arch/x86/isa/insts/general_purpose/flags/push_and_pop.py index 5937ac074..59f6aaec2 100644 --- a/src/arch/x86/isa/insts/general_purpose/flags/push_and_pop.py +++ b/src/arch/x86/isa/insts/general_purpose/flags/push_and_pop.py @@ -58,14 +58,14 @@ def macroop PUSHF { .adjust_env oszIn64Override rflags t1 - stupd t1, ss, [1, t0, rsp], "-env.dataSize" + stupd t1, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz }; def macroop POPF { .adjust_env oszIn64Override - ld t1, ss, [1, t0, rsp] - addi rsp, rsp, dsz + ld t1, ss, [1, t0, rsp], dataSize=ssz + addi rsp, rsp, ssz wrflags t1, t0 }; ''' -- cgit v1.2.3 From 66f54a6037873420dbc3bc2c91723225538feddb Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:52:12 -0400 Subject: X86: Change how segment loading is performed. --- .../general_purpose/control_transfer/xreturn.py | 21 +++-- .../insts/general_purpose/data_transfer/move.py | 105 ++++++++++++++------- src/arch/x86/isa/microops/regop.isa | 98 ++++++++++--------- src/arch/x86/tlb.cc | 16 ++-- 4 files changed, 151 insertions(+), 89 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py b/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py index 0b2e81cbd..b18d48264 100644 --- a/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py +++ b/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -85,7 +85,7 @@ def macroop RET_FAR { ld t1, ss, [1, t0, rsp] # Get the return CS - ld t2, ss, [1, t0, rsp], dsz + ld t2, ss, [1, t0, rsp], ssz # Get the rpl andi t3, t2, 0x3 @@ -96,12 +96,21 @@ def macroop RET_FAR { # that doesn't happen yet. # Do stuff if they're equal - chks t4, t2, flags=(EZF,) - fault "new GeneralProtection(0)", flags=(CEZF,) - ld t3, flatseg, [1, t0, t4], addressSize=8, dataSize=8 - wrdl cs, t3, t2 + andi t0, t2, 0xFC, flags=(EZF,), dataSize=2 + bri t0, label("processDescriptor"), flags=(CEZF,) + andi t3, t2, 0xF8, dataSize=8 + andi t0, t2, 0x4, flags=(EZF,), dataSize=2 + bri t0, label("globalDescriptor"), flags=(CEZF,) + ld t3, tsl, [1, t0, t3], dataSize=8 + bri t0, label("processDescriptor") +globalDescriptor: + ld t3, tsg, [1, t0, t3], dataSize=8 +processDescriptor: + chks t2, t3, IretCheck, dataSize=8 # There should be validity checks on the RIP checks here, but I'll do # that later. + wrdl reg, t3, t2 + wrsel reg, t2 wrip t0, t1 bri t0, label("end") diff --git a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py index 16196bcc8..d9a83dfde 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py +++ b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py @@ -237,65 +237,104 @@ def macroop MOV_REAL_S_P { }; def macroop MOV_S_R { - chks t1, regm, flags=(EZF,), dataSize=8 - bri t0, label("end"), flags=(CEZF,) - ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8 - wrdl reg, t2, regm -end: + andi t0, regm, 0xFC, flags=(EZF,), dataSize=2 + bri t0, label("processDescriptor"), flags=(CEZF,) + andi t2, regm, 0xF8, dataSize=8 + andi t0, regm, 0x4, flags=(EZF,), dataSize=2 + bri t0, label("globalDescriptor"), flags=(CEZF,) + ld t3, tsl, [1, t0, t2], dataSize=8 + bri t0, label("processDescriptor") +globalDescriptor: + ld t3, tsg, [1, t0, t2], dataSize=8 +processDescriptor: + chks regm, t3, dataSize=8 + wrdl reg, t3, regm wrsel reg, regm }; def macroop MOV_S_M { ld t1, seg, sib, disp, dataSize=2 - chks t2, t1, flags=(EZF,), dataSize=8 - bri t0, label("end"), flags=(CEZF,) - ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8 - wrdl reg, t2, t1 -end: + andi t0, t1, 0xFC, flags=(EZF,), dataSize=2 + bri t0, label("processDescriptor"), flags=(CEZF,) + andi t2, t1, 0xF8, dataSize=8 + andi t0, t1, 0x4, flags=(EZF,), dataSize=2 + bri t0, label("globalDescriptor"), flags=(CEZF,) + ld t3, tsl, [1, t0, t2], dataSize=8 + bri t0, label("processDescriptor") +globalDescriptor: + ld t3, tsg, [1, t0, t2], dataSize=8 +processDescriptor: + chks t1, t3, dataSize=8 + wrdl reg, t3, t1 wrsel reg, t1 }; def macroop MOV_S_P { rdip t7 ld t1, seg, riprel, disp, dataSize=2 - chks t2, t1, flags=(EZF,), dataSize=8 - bri t0, label("end"), flags=(CEZF,) - ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8 - wrdl reg, t2, t1 -end: + andi t0, t1, 0xFC, flags=(EZF,), dataSize=2 + bri t0, label("processDescriptor"), flags=(CEZF,) + andi t2, t1, 0xF8, dataSize=8 + andi t0, t1, 0x4, flags=(EZF,), dataSize=2 + bri t0, label("globalDescriptor"), flags=(CEZF,) + ld t3, tsl, [1, t0, t2], dataSize=8 + bri t0, label("processDescriptor") +globalDescriptor: + ld t3, tsg, [1, t0, t2], dataSize=8 +processDescriptor: + chks t1, t3, dataSize=8 + wrdl reg, t3, t1 wrsel reg, t1 }; def macroop MOVSS_S_R { - chks t1, regm, flags=(EZF,), dataSize=8 - # This actually needs to use the selector as the error code, but it would - # be hard to get that information into the instruction at the moment. - fault "new GeneralProtection(0)", flags=(CEZF,) - ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8 - wrdl reg, t2, regm + andi t0, regm, 0xFC, flags=(EZF,), dataSize=2 + bri t0, label("processDescriptor"), flags=(CEZF,) + andi t2, regm, 0xF8, dataSize=8 + andi t0, regm, 0x4, flags=(EZF,), dataSize=2 + bri t0, label("globalDescriptor"), flags=(CEZF,) + ld t3, tsl, [1, t0, t2], dataSize=8 + bri t0, label("processDescriptor") +globalDescriptor: + ld t3, tsg, [1, t0, t2], dataSize=8 +processDescriptor: + chks regm, t3, SSCheck, dataSize=8 + wrdl reg, t3, regm wrsel reg, regm }; def macroop MOVSS_S_M { ld t1, seg, sib, disp, dataSize=2 - chks t2, t1, flags=(EZF,), dataSize=8 - # This actually needs to use the selector as the error code, but it would - # be hard to get that information into the instruction at the moment. - fault "new GeneralProtection(0)", flags=(CEZF,) - ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8 - wrdl reg, t2, t1 + andi t0, t1, 0xFC, flags=(EZF,), dataSize=2 + bri t0, label("processDescriptor"), flags=(CEZF,) + andi t2, t1, 0xF8, dataSize=8 + andi t0, t1, 0x4, flags=(EZF,), dataSize=2 + bri t0, label("globalDescriptor"), flags=(CEZF,) + ld t3, tsl, [1, t0, t2], dataSize=8 + bri t0, label("processDescriptor") +globalDescriptor: + ld t3, tsg, [1, t0, t2], dataSize=8 +processDescriptor: + chks t1, t3, SSCheck, dataSize=8 + wrdl reg, t3, t1 wrsel reg, t1 }; def macroop MOVSS_S_P { rdip t7 ld t1, seg, riprel, disp, dataSize=2 - chks t2, t1, flags=(EZF,), dataSize=8 - # This actually needs to use the selector as the error code, but it would - # be hard to get that information into the instruction at the moment. - fault "new GeneralProtection(0)", flags=(CEZF,) - ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8 - wrdl reg, t2, t1 + andi t0, t1, 0xFC, flags=(EZF,), dataSize=2 + bri t0, label("processDescriptor"), flags=(CEZF,) + andi t2, t1, 0xF8, dataSize=8 + andi t0, t1, 0x4, flags=(EZF,), dataSize=2 + bri t0, label("globalDescriptor"), flags=(CEZF,) + ld t3, tsl, [1, t0, t2], dataSize=8 + bri t0, label("processDescriptor") +globalDescriptor: + ld t3, tsg, [1, t0, t2], dataSize=8 +processDescriptor: + chks t1, t3, SSCheck, dataSize=8 + wrdl reg, t3, t1 wrsel reg, t1 }; ''' diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 35f319528..b751b9b4f 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -1030,7 +1030,9 @@ let {{ src1, src2, flags, dataSize) code = ''' // The selector is in source 1 and can be at most 16 bits. - SegSelector selector = psrc1; + SegSelector selector = DestReg; + SegDescriptor desc = SrcReg1; + HandyM5Reg m5reg = M5Reg; switch (imm8) { @@ -1044,15 +1046,31 @@ let {{ "not implemented.\\n"); break; case SegSSCheck: - panic("SS selector checks not implemented.\\n"); + if (selector.si || selector.ti) { + if (!desc.p) { + //FIXME This needs to also push the selector. + return new StackFault; + } + } else { + if ((m5reg.mode != SixtyFourBitMode || m5reg.cpl == 3) || + !(desc.s == 1 && + desc.type.codeOrData == 0 && desc.type.w) || + (desc.dpl != m5reg.cpl) || + (selector.rpl != m5reg.cpl)) { + return new GeneralProtection(psrc1 & 0xFFFF); + } + } break; case SegIretCheck: { - SegAttr csAttr = CSAttr; - if (!selector.si && !selector.ti) - return new GeneralProtection(psrc1 & 0xFFFF); - if (selector.rpl < csAttr.dpl) + if ((!selector.si && !selector.ti) || + (selector.rpl < m5reg.cpl) || + !(desc.s == 1 && desc.type.codeOrData == 1) || + (!desc.type.c && desc.dpl != selector.rpl) || + (desc.type.c && desc.dpl > selector.rpl)) return new GeneralProtection(psrc1 & 0xFFFF); + if (!desc.p) + return new SegmentNotPresent; break; } case SegIntCSCheck: @@ -1062,21 +1080,6 @@ let {{ default: panic("Undefined segment check type.\\n"); } - - // Compute the address of the descriptor and set DestReg to it. - if (selector.ti) { - // A descriptor in the LDT - Addr target = (selector.si << 3) + LDTRBase; - if (!LDTRSel || (selector.si << 3) + dataSize > LDTRLimit) - fault = new GeneralProtection(selector & mask(16)); - DestReg = target; - } else { - // A descriptor in the GDT - Addr target = (selector.si << 3) + GDTRBase; - if ((selector.si << 3) + dataSize > GDTRLimit) - fault = new GeneralProtection(selector & mask(16)); - DestReg = target; - } ''' flag_code = ''' // Check for a NULL selector and set ZF,EZF appropriately. @@ -1108,32 +1111,39 @@ let {{ class Wrdl(RegOp): code = ''' SegDescriptor desc = SrcReg1; - SegAttr attr = 0; - attr.dpl = desc.dpl; - attr.defaultSize = desc.d; - if (!desc.s) { + SegSelector selector = SrcReg2; + if (selector.si || selector.ti) { + SegAttr attr = 0; + attr.dpl = desc.dpl; + attr.defaultSize = desc.d; + if (!desc.s) { + SegBaseDest = SegBaseDest; + SegLimitDest = SegLimitDest; + SegAttrDest = SegAttrDest; + panic("System segment encountered.\\n"); + } else { + if (!desc.p) + panic("Segment not present.\\n"); + if (desc.type.codeOrData) { + attr.readable = desc.type.r; + attr.longMode = desc.l; + } else { + attr.expandDown = desc.type.e; + attr.readable = 1; + attr.writable = desc.type.w; + } + Addr base = desc.baseLow | (desc.baseHigh << 24); + Addr limit = desc.limitLow | (desc.limitHigh << 16); + if (desc.g) + limit = (limit << 12) | mask(12); + SegBaseDest = base; + SegLimitDest = limit; + SegAttrDest = attr; + } + } else { SegBaseDest = SegBaseDest; SegLimitDest = SegLimitDest; SegAttrDest = SegAttrDest; - panic("System segment encountered.\\n"); - } else { - if (!desc.p) - panic("Segment not present.\\n"); - if (desc.type.codeOrData) { - attr.readable = desc.type.r; - attr.longMode = desc.l; - } else { - attr.expandDown = desc.type.e; - attr.readable = 1; - attr.writable = desc.type.w; - } - Addr base = desc.baseLow | (desc.baseHigh << 24); - Addr limit = desc.limitLow | (desc.limitHigh << 16); - if (desc.g) - limit = (limit << 12) | mask(12); - SegBaseDest = base; - SegLimitDest = limit; - SegAttrDest = attr; } ''' }}; diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index 5d101a5ae..ba8f63a0e 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -574,14 +574,18 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) // Check for a NULL segment selector. if (!tc->readMiscRegNoEffect(MISCREG_SEG_SEL(seg))) return new GeneralProtection(0); - SegAttr attr = tc->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg)); - if (!attr.writable && write) - return new GeneralProtection(0); - if (!attr.readable && !write && !execute) - return new GeneralProtection(0); + bool expandDown = false; + if (seg >= SEGMENT_REG_ES && seg <= SEGMENT_REG_HS) { + SegAttr attr = tc->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg)); + if (!attr.writable && write) + return new GeneralProtection(0); + if (!attr.readable && !write && !execute) + return new GeneralProtection(0); + expandDown = attr.expandDown; + } Addr base = tc->readMiscRegNoEffect(MISCREG_SEG_BASE(seg)); Addr limit = tc->readMiscRegNoEffect(MISCREG_SEG_LIMIT(seg)); - if (!attr.expandDown) { + if (expandDown) { DPRINTF(TLB, "Checking an expand down segment.\n"); // We don't have to worry about the access going around the // end of memory because accesses will be broken up into -- cgit v1.2.3 From 8d2416c6e9ec56dc2addd594eb7f7cab0d58b951 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:53:01 -0400 Subject: X86: Implement a partial, sort of correct version of the protected mode variant of iret. --- src/arch/x86/isa/decoder/one_byte_opcodes.isa | 8 +- .../control_transfer/interrupts_and_exceptions.py | 193 ++++++++++++++++++++- 2 files changed, 191 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa index 332ae1641..8729f417d 100644 --- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2007 The Hewlett-Packard Development Company +// Copyright (c) 2007-2008 The Hewlett-Packard Development Company // All rights reserved. // // Redistribution and use of this software in source and binary forms, @@ -423,7 +423,11 @@ 0x0: Inst::UD2(); default: into(); } - 0x7: iret(); + 0x7: decode MODE_SUBMODE { + 0x4: Inst::IRET_REAL(); + 0x3: Inst::IRET_VIRT(); + default: Inst::IRET_PROT(); + } } } 0x1A: decode OPCODE_OP_BOTTOM3 { diff --git a/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py b/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py index 7039b4b5c..327361746 100644 --- a/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py +++ b/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -53,16 +53,193 @@ # # Authors: Gabe Black -microcode = "" +microcode = ''' +def macroop IRET_REAL { + panic "Real mode iret isn't implemented!" +}; + +def macroop IRET_PROT { + .adjust_env oszIn64Override + + # Check for a nested task. This isn't supported at the moment. + rflag t1, NT + panic "Task switching with iret is unimplemented!", flags=(nCEZF,) + + #t1 = temp_RIP + #t2 = temp_CS + #t3 = temp_RFLAGS + #t4 = handy m5 register + + # Pop temp_RIP, temp_CS, and temp_RFLAGS + ld t1, ss, [1, t0, rsp], "0 * env.stackSize", dataSize=ssz + ld t2, ss, [1, t0, rsp], "1 * env.stackSize", dataSize=ssz + ld t3, ss, [1, t0, rsp], "2 * env.stackSize", dataSize=ssz + + + +### +### Handle if we're returning to virtual 8086 mode. +### + + #IF ((temp_RFLAGS.VM=1) && (CPL=0) && (LEGACY_MODE)) + # IRET_FROM_PROTECTED_TO_VIRTUAL + + #temp_RFLAGS.VM != 1 + rcri t0, t3, 18, flags=(ECF,) + bri t0, label("protToVirtFallThrough"), flags=(nCECF,) + + #CPL=0 + rdm5reg t4 + andi t0, t4, 0x30, flags=(EZF,) + bri t0, label("protToVirtFallThrough"), flags=(nCEZF,) + + #(LEGACY_MODE) + rcri t0, t4, 1, flags=(ECF,) + bri t0, label("protToVirtFallThrough"), flags=(nCECF,) + + panic "iret to virtual mode not supported" + +protToVirtFallThrough: + + + + #temp_CPL = temp_CS.rpl + andi t5, t2, 0x3 + + +### +### Read in the info for the new CS segment. +### + + #CS = READ_DESCRIPTOR (temp_CS, iret_chk) + andi t0, t2, 0xFC, flags=(EZF,), dataSize=2 + bri t0, label("processCSDescriptor"), flags=(CEZF,) + andi t6, t2, 0xF8, dataSize=8 + andi t0, t2, 0x4, flags=(EZF,), dataSize=2 + bri t0, label("globalCSDescriptor"), flags=(CEZF,) + ld t6, tsl, [1, t0, t6], dataSize=8 + bri t0, label("processCSDescriptor") +globalCSDescriptor: + ld t6, tsg, [1, t0, t6], dataSize=8 +processCSDescriptor: + chks t2, t6, dataSize=8 + + # This actually updates state which is wrong. It should wait until we know + # we're not going to fault. Unfortunately, that's hard to do. + wrdl cs, t6, t2 + wrsel cs, t2 + + #CPL = temp_CPL + + +### +### Get the new stack pointer and stack segment off the old stack if necessary, +### and piggyback on the logic to check the new RIP value. +### + #IF ((64BIT_MODE) || (temp_CPL!=CPL)) + #{ + + #(64BIT_MODE) + andi t0, t4, 0xE, flags=(EZF,) + # Since we just found out we're in 64 bit mode, take advantage and + # do the appropriate RIP checks. + bri t0, label("doPopStackStuffAndCheckRIP"), flags=(CEZF,) + + # Here, we know we're -not- in 64 bit mode, so we should do the + # appropriate/other RIP checks. + # if temp_RIP > CS.limit throw #GP(0) + rdlimit t6, cs + subi t0, t1, t6, flags=(ECF,) + fault "new GeneralProtection(0)", flags=(CECF,) + + #(temp_CPL!=CPL) + srli t7, t4, 4 + xor t7, t7, t5 + andi t0, t7, 0x3, flags=(EZF,) + bri t0, label("doPopStackStuff"), flags=(nCEZF,) + # We can modify user visible state here because we're know + # we're done with things that can fault. + addi rsp, rsp, "3 * env.stackSize" + bri t0, label("fallThroughPopStackStuff") + +doPopStackStuffAndCheckRIP: + # Check if the RIP is canonical. + sra t7, t1, 47, flags=(EZF,), dataSize=ssz + # if t7 isn't 0 or -1, it wasn't canonical. + bri t0, label("doPopStackStuff"), flags=(CEZF,) + addi t0, t7, 1, flags=(EZF,), dataSize=ssz + fault "new GeneralProtection(0)", flags=(nCEZF,) + +doPopStackStuff: + # POP.v temp_RSP + ld t6, ss, [1, t0, rsp], "3 * env.dataSize", dataSize=ssz + # POP.v temp_SS + ld t2, ss, [1, t0, rsp], "4 * env.dataSize", dataSize=ssz + # SS = READ_DESCRIPTOR (temp_SS, ss_chk) + andi t0, t2, 0xFC, flags=(EZF,), dataSize=2 + bri t0, label("processSSDescriptor"), flags=(CEZF,) + andi t7, t2, 0xF8, dataSize=8 + andi t0, t2, 0x4, flags=(EZF,), dataSize=2 + bri t0, label("globalSSDescriptor"), flags=(CEZF,) + ld t7, tsl, [1, t0, t7], dataSize=8 + bri t0, label("processSSDescriptor") +globalSSDescriptor: + ld t7, tsg, [1, t0, t7], dataSize=8 +processSSDescriptor: + chks t2, t7, dataSize=8 + + # This actually updates state which is wrong. It should wait until we know + # we're not going to fault. Unfortunately, that's hard to do. + wrdl cs, t7, t2 + wrsel cs, t2 + +### +### From this point downwards, we can't fault. We can update user visible state. +### + # RSP.s = temp_RSP + mov rsp, rsp, t6, dataSize=ssz + + #} + +fallThroughPopStackStuff: + + #IF (changing CPL) + #{ + srli t7, t4, 4 + xor t7, t7, t5 + andi t0, t7, 0x3, flags=(EZF,) + bri t0, label("skipSegmentSquashing"), flags=(CEZF,) + + # The attribute register needs to keep track of more info before this will + # work the way it needs to. + # FOR (seg = ES, DS, FS, GS) + # IF ((seg.attr.dpl < cpl && ((seg.attr.type = 'data') + # || (seg.attr.type = 'non-conforming-code'))) + # { + # seg = NULL + # } + #} + +skipSegmentSquashing: + + # Ignore this for now. + #RFLAGS.v = temp_RFLAGS + # VIF,VIP,IOPL only changed if (old_CPL = 0) + # IF only changed if (old_CPL <= old_RFLAGS.IOPL) + # VM unchanged + # RF cleared + + #RIP = temp_RIP + wrip t0, t1, dataSize=ssz +}; + +def macroop IRET_VIRT { + panic "Virtual mode iret isn't implemented!" +}; +''' #let {{ # class INT(Inst): # "GenFault ${new UnimpInstFault}" # class INTO(Inst): # "GenFault ${new UnimpInstFault}" -# class IRET(Inst): -# "GenFault ${new UnimpInstFault}" -# class IRETD(Inst): -# "GenFault ${new UnimpInstFault}" -# class IRETQ(Inst): -# "GenFault ${new UnimpInstFault}" #}}; -- cgit v1.2.3 From 8a6723e0380bf501e305fb2dd72f0e9079f158b2 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:53:37 -0400 Subject: X86: Make the apic version register work. --- src/arch/x86/miscregfile.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc index 6abeb7d34..7fce43c1d 100644 --- a/src/arch/x86/miscregfile.cc +++ b/src/arch/x86/miscregfile.cc @@ -222,8 +222,8 @@ void MiscRegFile::setReg(int miscReg, panic("Local APIC ID register unimplemented.\n"); break; case MISCREG_APIC_VERSION: - panic("Local APIC Version register is read only.\n"); - break; + // The Local APIC Version register is read only. + return; case MISCREG_APIC_TASK_PRIORITY: panic("Local APIC Task Priority register unimplemented.\n"); break; -- cgit v1.2.3 From ed23a4970bde6eea4a72aa0e33a87aad5713a427 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:53:43 -0400 Subject: X86: Make the apic ID register work. --- src/arch/x86/miscregfile.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc index 7fce43c1d..d52d56915 100644 --- a/src/arch/x86/miscregfile.cc +++ b/src/arch/x86/miscregfile.cc @@ -219,7 +219,7 @@ void MiscRegFile::setReg(int miscReg, } switch (miscReg) { case MISCREG_APIC_ID: - panic("Local APIC ID register unimplemented.\n"); + newVal = val & 0xFF; break; case MISCREG_APIC_VERSION: // The Local APIC Version register is read only. -- cgit v1.2.3 From e9c481ea4ae7d72d6a53bc80c7f867578179f00c Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:53:50 -0400 Subject: X86: Make the logical destination and destination format work. --- src/arch/x86/miscregfile.cc | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc index d52d56915..46ee3a7db 100644 --- a/src/arch/x86/miscregfile.cc +++ b/src/arch/x86/miscregfile.cc @@ -106,6 +106,8 @@ void MiscRegFile::clear() { // Blank everything. 0 might not be an appropriate value for some things. memset(regVal, 0, NumMiscRegs * sizeof(MiscReg)); + //Set the local apic DFR to the flat model. + regVal[MISCREG_APIC_DESTINATION_FORMAT] = (MiscReg)(-1); } MiscReg MiscRegFile::readRegNoEffect(int miscReg) @@ -151,12 +153,6 @@ MiscReg MiscRegFile::readReg(int miscReg, ThreadContext * tc) case MISCREG_APIC_EOI: panic("Local APIC EOI register unimplemented.\n"); break; - case MISCREG_APIC_LOGICAL_DESTINATION: - panic("Local APIC Logical Destination register unimplemented.\n"); - break; - case MISCREG_APIC_DESTINATION_FORMAT: - panic("Local APIC Destination Format register unimplemented.\n"); - break; case MISCREG_APIC_ERROR_STATUS: regVal[MISCREG_APIC_INTERNAL_STATE] &= ~ULL(0x1); break; @@ -237,10 +233,10 @@ void MiscRegFile::setReg(int miscReg, panic("Local APIC EOI register unimplemented.\n"); break; case MISCREG_APIC_LOGICAL_DESTINATION: - panic("Local APIC Logical Destination register unimplemented.\n"); + newVal = val & 0xFF000000; break; case MISCREG_APIC_DESTINATION_FORMAT: - panic("Local APIC Destination Format register unimplemented.\n"); + newVal = val | 0x0FFFFFFF; break; case MISCREG_APIC_SPURIOUS_INTERRUPT_VECTOR: regVal[MISCREG_APIC_INTERNAL_STATE] &= ~ULL(1 << 1); -- cgit v1.2.3 From 69000baef3ad409607ca8682d4d0afd29bc8f263 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:54:01 -0400 Subject: X86: Make the apic task priority register work. --- src/arch/x86/miscregfile.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src') diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc index 46ee3a7db..ee71842d2 100644 --- a/src/arch/x86/miscregfile.cc +++ b/src/arch/x86/miscregfile.cc @@ -141,9 +141,6 @@ MiscReg MiscRegFile::readReg(int miscReg, ThreadContext * tc) "are unimplemented.\n"); } switch (miscReg) { - case MISCREG_APIC_TASK_PRIORITY: - panic("Local APIC Task Priority register unimplemented.\n"); - break; case MISCREG_APIC_ARBITRATION_PRIORITY: panic("Local APIC Arbitration Priority register unimplemented.\n"); break; @@ -221,7 +218,7 @@ void MiscRegFile::setReg(int miscReg, // The Local APIC Version register is read only. return; case MISCREG_APIC_TASK_PRIORITY: - panic("Local APIC Task Priority register unimplemented.\n"); + newVal = val & 0xFF; break; case MISCREG_APIC_ARBITRATION_PRIORITY: panic("Local APIC Arbitration Priority register unimplemented.\n"); -- cgit v1.2.3 From b10742ee2b01213999ba9a3706093f5946097341 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:54:05 -0400 Subject: X86: Make the apic isr and irr work. --- src/arch/x86/miscregfile.cc | 9 --------- 1 file changed, 9 deletions(-) (limited to 'src') diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc index ee71842d2..1e02391e6 100644 --- a/src/arch/x86/miscregfile.cc +++ b/src/arch/x86/miscregfile.cc @@ -127,19 +127,10 @@ MiscReg MiscRegFile::readRegNoEffect(int miscReg) MiscReg MiscRegFile::readReg(int miscReg, ThreadContext * tc) { if (miscReg >= MISCREG_APIC_START && miscReg <= MISCREG_APIC_END) { - if (miscReg >= MISCREG_APIC_IN_SERVICE(0) && - miscReg <= MISCREG_APIC_IN_SERVICE(15)) { - panic("Local APIC In-Service registers are unimplemented.\n"); - } if (miscReg >= MISCREG_APIC_TRIGGER_MODE(0) && miscReg <= MISCREG_APIC_TRIGGER_MODE(15)) { panic("Local APIC Trigger Mode registers are unimplemented.\n"); } - if (miscReg >= MISCREG_APIC_INTERRUPT_REQUEST(0) && - miscReg <= MISCREG_APIC_INTERRUPT_REQUEST(15)) { - panic("Local APIC Interrupt Request registers " - "are unimplemented.\n"); - } switch (miscReg) { case MISCREG_APIC_ARBITRATION_PRIORITY: panic("Local APIC Arbitration Priority register unimplemented.\n"); -- cgit v1.2.3 From 6b8d0363ee271a1b36dd03e3bac5e62efc52aad4 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:54:12 -0400 Subject: X86: Rename the divide count register to divide configuration. --- src/arch/x86/miscregfile.cc | 7 ++----- src/arch/x86/miscregs.hh | 4 ++-- src/arch/x86/tlb.cc | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc index 1e02391e6..64dac6147 100644 --- a/src/arch/x86/miscregfile.cc +++ b/src/arch/x86/miscregfile.cc @@ -158,9 +158,6 @@ MiscReg MiscRegFile::readReg(int miscReg, ThreadContext * tc) case MISCREG_APIC_CURRENT_COUNT: panic("Local APIC Current Count register unimplemented.\n"); break; - case MISCREG_APIC_DIVIDE_COUNT: - panic("Local APIC Divide Count register unimplemented.\n"); - break; } } switch (miscReg) { @@ -270,8 +267,8 @@ void MiscRegFile::setReg(int miscReg, case MISCREG_APIC_CURRENT_COUNT: panic("Local APIC Current Count register unimplemented.\n"); break; - case MISCREG_APIC_DIVIDE_COUNT: - panic("Local APIC Divide Count register unimplemented.\n"); + case MISCREG_APIC_DIVIDE_CONFIGURATION: + newVal = val & 0xB; break; } setRegNoEffect(miscReg, newVal); diff --git a/src/arch/x86/miscregs.hh b/src/arch/x86/miscregs.hh index caa1e817b..5a6ee752d 100644 --- a/src/arch/x86/miscregs.hh +++ b/src/arch/x86/miscregs.hh @@ -397,8 +397,8 @@ namespace X86ISA MISCREG_APIC_LVT_ERROR, MISCREG_APIC_INITIAL_COUNT, MISCREG_APIC_CURRENT_COUNT, - MISCREG_APIC_DIVIDE_COUNT, - MISCREG_APIC_END = MISCREG_APIC_DIVIDE_COUNT, + MISCREG_APIC_DIVIDE_CONFIGURATION, + MISCREG_APIC_END = MISCREG_APIC_DIVIDE_CONFIGURATION, MISCREG_APIC_INTERNAL_STATE, diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index ba8f63a0e..692d6d022 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -780,7 +780,7 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) regNum = MISCREG_APIC_CURRENT_COUNT; break; case 0x3E0: - regNum = MISCREG_APIC_DIVIDE_COUNT; + regNum = MISCREG_APIC_DIVIDE_CONFIGURATION; break; default: // A reserved register field. -- cgit v1.2.3 From 81936ae2ed0368f4687e74374bf32575376bf9df Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:54:19 -0400 Subject: X86: Add an event for the apic timer timeout. It doesn't get used yet. --- src/arch/x86/miscregfile.cc | 28 +++++++++++++++++++++------- src/arch/x86/miscregfile.hh | 19 ++++++++++++++++++- 2 files changed, 39 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc index 64dac6147..f40b1adf5 100644 --- a/src/arch/x86/miscregfile.cc +++ b/src/arch/x86/miscregfile.cc @@ -110,6 +110,16 @@ void MiscRegFile::clear() regVal[MISCREG_APIC_DESTINATION_FORMAT] = (MiscReg)(-1); } +int divideFromConf(MiscReg conf) +{ + // This figures out what division we want from the division configuration + // register in the local APIC. The encoding is a little odd but it can + // be deciphered fairly easily. + int shift = ((conf & 0x8) >> 1) | (conf & 0x3); + shift = (shift + 1) % 8; + return 1 << shift; +}; + MiscReg MiscRegFile::readRegNoEffect(int miscReg) { // Make sure we're not dealing with an illegal control register. @@ -152,11 +162,10 @@ MiscReg MiscRegFile::readReg(int miscReg, ThreadContext * tc) panic("Local APIC Interrupt Command high" " register unimplemented.\n"); break; - case MISCREG_APIC_INITIAL_COUNT: - panic("Local APIC Initial Count register unimplemented.\n"); - break; case MISCREG_APIC_CURRENT_COUNT: - panic("Local APIC Current Count register unimplemented.\n"); + return (regVal[miscReg] - tc->getCpuPtr()->curCycle()) / + (16 * divideFromConf( + regVal[MISCREG_APIC_DIVIDE_CONFIGURATION])); break; } } @@ -262,11 +271,16 @@ void MiscRegFile::setReg(int miscReg, } break; case MISCREG_APIC_INITIAL_COUNT: - panic("Local APIC Initial Count register unimplemented.\n"); + newVal = bits(val, 31, 0); + regVal[MISCREG_APIC_CURRENT_COUNT] = + tc->getCpuPtr()->curCycle() + + (16 * divideFromConf( + regVal[MISCREG_APIC_DIVIDE_CONFIGURATION])) * newVal; + //FIXME This should schedule the timer event. break; case MISCREG_APIC_CURRENT_COUNT: - panic("Local APIC Current Count register unimplemented.\n"); - break; + //Local APIC Current Count register is read only. + return; case MISCREG_APIC_DIVIDE_CONFIGURATION: newVal = val & 0xB; break; diff --git a/src/arch/x86/miscregfile.hh b/src/arch/x86/miscregfile.hh index e095e06e9..3abe4ec58 100644 --- a/src/arch/x86/miscregfile.hh +++ b/src/arch/x86/miscregfile.hh @@ -29,7 +29,7 @@ */ /* - * Copyright (c) 2007 The Hewlett-Packard Development Company + * Copyright (c) 2007-2008 The Hewlett-Packard Development Company * All rights reserved. * * Redistribution and use of this software in source and binary forms, @@ -91,6 +91,8 @@ #include "arch/x86/faults.hh" #include "arch/x86/miscregs.hh" #include "arch/x86/types.hh" +#include "sim/eventq.hh" +#include "sim/host.hh" #include @@ -98,6 +100,7 @@ class Checkpoint; namespace X86ISA { + std::string getMiscRegName(RegIndex); //These will have to be updated in the future. @@ -109,6 +112,20 @@ namespace X86ISA protected: MiscReg regVal[NumMiscRegs]; + class ApicTimerEvent : public Event + { + public: + ApicTimerEvent() : Event(&mainEventQueue) + {} + + void process() + { + warn("Local APIC timer event doesn't do anything!\n"); + } + }; + + ApicTimerEvent apicTimerEvent; + public: void clear(); -- cgit v1.2.3 From 0368ccdedaa6b6fecb0f04924456953c92396188 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:54:32 -0400 Subject: BitUnion: Take out namespace declaration so bitunions can be declared inside classes. --- src/base/bitunion.hh | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/base/bitunion.hh b/src/base/bitunion.hh index 7f7b06966..507fafecd 100644 --- a/src/base/bitunion.hh +++ b/src/base/bitunion.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2005 The Regents of The University of Michigan + * Copyright (c) 2007-2008 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -242,11 +242,7 @@ namespace BitfieldBackend //bitfields which are defined in the union, creating shared storage with no //overhead. #define __BitUnion(type, name) \ - namespace BitfieldUnderlyingClasses \ - { \ - class name; \ - } \ - class BitfieldUnderlyingClasses::name : \ + class BitfieldUnderlyingClasses##name : \ public BitfieldBackend::BitfieldTypes \ { \ public: \ @@ -262,8 +258,8 @@ namespace BitfieldBackend }; \ }; \ typedef BitfieldBackend::BitUnionOperators< \ - BitfieldUnderlyingClasses::name::__DataType, \ - BitfieldUnderlyingClasses::name> name; + BitfieldUnderlyingClasses##name::__DataType, \ + BitfieldUnderlyingClasses##name> name; //This sets up a bitfield which has other bitfields nested inside of it. The //__data member functions like the "underlying storage" of the top level -- cgit v1.2.3 From 4f9a0402f629dbd78494bd7e820ffa41b0a5f245 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:54:48 -0400 Subject: Dev: Seperate the 8254 timer from tsunami and use it in that and the PC. --- src/dev/SConscript | 2 + src/dev/alpha/tsunami_io.cc | 224 --------------------------- src/dev/alpha/tsunami_io.hh | 135 +--------------- src/dev/intel_8254_timer.cc | 255 +++++++++++++++++++++++++++++++ src/dev/intel_8254_timer.hh | 206 +++++++++++++++++++++++++ src/dev/pitreg.h | 75 --------- src/dev/x86/south_bridge/i8254.cc | 30 ++-- src/dev/x86/south_bridge/i8254.hh | 16 +- src/dev/x86/south_bridge/south_bridge.cc | 4 +- 9 files changed, 489 insertions(+), 458 deletions(-) create mode 100644 src/dev/intel_8254_timer.cc create mode 100644 src/dev/intel_8254_timer.hh delete mode 100644 src/dev/pitreg.h (limited to 'src') diff --git a/src/dev/SConscript b/src/dev/SConscript index ee7adb8c8..bd6b16c43 100644 --- a/src/dev/SConscript +++ b/src/dev/SConscript @@ -54,6 +54,7 @@ if env['FULL_SYSTEM']: Source('i8254xGBe.cc') Source('ide_ctrl.cc') Source('ide_disk.cc') + Source('intel_8254_timer.cc') Source('io_device.cc') Source('isa_fake.cc') Source('mc146818.cc') @@ -84,6 +85,7 @@ if env['FULL_SYSTEM']: TraceFlag('EthernetSM') TraceFlag('IdeCtrl') TraceFlag('IdeDisk') + TraceFlag('Intel8254Timer') TraceFlag('IsaFake') TraceFlag('MC146818') TraceFlag('PCIDEV') diff --git a/src/dev/alpha/tsunami_io.cc b/src/dev/alpha/tsunami_io.cc index 88999ecc5..3496aed14 100644 --- a/src/dev/alpha/tsunami_io.cc +++ b/src/dev/alpha/tsunami_io.cc @@ -62,230 +62,6 @@ TsunamiIO::TsunamiRTC::TsunamiRTC(const string &n, const TsunamiIOParams *p) : { } -TsunamiIO::PITimer::PITimer(const string &name) - : _name(name), counter0(name + ".counter0"), counter1(name + ".counter1"), - counter2(name + ".counter2") -{ - counter[0] = &counter0; - counter[1] = &counter0; - counter[2] = &counter0; -} - -void -TsunamiIO::PITimer::writeControl(const uint8_t data) -{ - int rw; - int sel; - - sel = GET_CTRL_SEL(data); - - if (sel == PIT_READ_BACK) - panic("PITimer Read-Back Command is not implemented.\n"); - - rw = GET_CTRL_RW(data); - - if (rw == PIT_RW_LATCH_COMMAND) - counter[sel]->latchCount(); - else { - counter[sel]->setRW(rw); - counter[sel]->setMode(GET_CTRL_MODE(data)); - counter[sel]->setBCD(GET_CTRL_BCD(data)); - } -} - -void -TsunamiIO::PITimer::serialize(const string &base, ostream &os) -{ - // serialize the counters - counter0.serialize(base + ".counter0", os); - counter1.serialize(base + ".counter1", os); - counter2.serialize(base + ".counter2", os); -} - -void -TsunamiIO::PITimer::unserialize(const string &base, Checkpoint *cp, - const string §ion) -{ - // unserialze the counters - counter0.unserialize(base + ".counter0", cp, section); - counter1.unserialize(base + ".counter1", cp, section); - counter2.unserialize(base + ".counter2", cp, section); -} - -TsunamiIO::PITimer::Counter::Counter(const string &name) - : _name(name), event(this), count(0), latched_count(0), period(0), - mode(0), output_high(false), latch_on(false), read_byte(LSB), - write_byte(LSB) -{ - -} - -void -TsunamiIO::PITimer::Counter::latchCount() -{ - // behave like a real latch - if(!latch_on) { - latch_on = true; - read_byte = LSB; - latched_count = count; - } -} - -uint8_t -TsunamiIO::PITimer::Counter::read() -{ - if (latch_on) { - switch (read_byte) { - case LSB: - read_byte = MSB; - return (uint8_t)latched_count; - break; - case MSB: - read_byte = LSB; - latch_on = false; - return latched_count >> 8; - break; - default: - panic("Shouldn't be here"); - } - } else { - switch (read_byte) { - case LSB: - read_byte = MSB; - return (uint8_t)count; - break; - case MSB: - read_byte = LSB; - return count >> 8; - break; - default: - panic("Shouldn't be here"); - } - } -} - -void -TsunamiIO::PITimer::Counter::write(const uint8_t data) -{ - switch (write_byte) { - case LSB: - count = (count & 0xFF00) | data; - - if (event.scheduled()) - event.deschedule(); - output_high = false; - write_byte = MSB; - break; - - case MSB: - count = (count & 0x00FF) | (data << 8); - period = count; - - if (period > 0) { - DPRINTF(Tsunami, "Timer set to curTick + %d\n", - count * event.interval); - event.schedule(curTick + count * event.interval); - } - write_byte = LSB; - break; - } -} - -void -TsunamiIO::PITimer::Counter::setRW(int rw_val) -{ - if (rw_val != PIT_RW_16BIT) - panic("Only LSB/MSB read/write is implemented.\n"); -} - -void -TsunamiIO::PITimer::Counter::setMode(int mode_val) -{ - if(mode_val != PIT_MODE_INTTC && mode_val != PIT_MODE_RATEGEN && - mode_val != PIT_MODE_SQWAVE) - panic("PIT mode %#x is not implemented: \n", mode_val); - - mode = mode_val; -} - -void -TsunamiIO::PITimer::Counter::setBCD(int bcd_val) -{ - if (bcd_val != PIT_BCD_FALSE) - panic("PITimer does not implement BCD counts.\n"); -} - -bool -TsunamiIO::PITimer::Counter::outputHigh() -{ - return output_high; -} - -void -TsunamiIO::PITimer::Counter::serialize(const string &base, ostream &os) -{ - paramOut(os, base + ".count", count); - paramOut(os, base + ".latched_count", latched_count); - paramOut(os, base + ".period", period); - paramOut(os, base + ".mode", mode); - paramOut(os, base + ".output_high", output_high); - paramOut(os, base + ".latch_on", latch_on); - paramOut(os, base + ".read_byte", read_byte); - paramOut(os, base + ".write_byte", write_byte); - - Tick event_tick = 0; - if (event.scheduled()) - event_tick = event.when(); - paramOut(os, base + ".event_tick", event_tick); -} - -void -TsunamiIO::PITimer::Counter::unserialize(const string &base, Checkpoint *cp, - const string §ion) -{ - paramIn(cp, section, base + ".count", count); - paramIn(cp, section, base + ".latched_count", latched_count); - paramIn(cp, section, base + ".period", period); - paramIn(cp, section, base + ".mode", mode); - paramIn(cp, section, base + ".output_high", output_high); - paramIn(cp, section, base + ".latch_on", latch_on); - paramIn(cp, section, base + ".read_byte", read_byte); - paramIn(cp, section, base + ".write_byte", write_byte); - - Tick event_tick; - paramIn(cp, section, base + ".event_tick", event_tick); - if (event_tick) - event.schedule(event_tick); -} - -TsunamiIO::PITimer::Counter::CounterEvent::CounterEvent(Counter* c_ptr) - : Event(&mainEventQueue) -{ - interval = (Tick)(Clock::Float::s / 1193180.0); - counter = c_ptr; -} - -void -TsunamiIO::PITimer::Counter::CounterEvent::process() -{ - DPRINTF(Tsunami, "Timer Interrupt\n"); - switch (counter->mode) { - case PIT_MODE_INTTC: - counter->output_high = true; - case PIT_MODE_RATEGEN: - case PIT_MODE_SQWAVE: - break; - default: - panic("Unimplemented PITimer mode.\n"); - } -} - -const char * -TsunamiIO::PITimer::Counter::CounterEvent::description() const -{ - return "tsunami 8254 Interval timer"; -} - TsunamiIO::TsunamiIO(const Params *p) : BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"), rtc(p->name + ".rtc", p) diff --git a/src/dev/alpha/tsunami_io.hh b/src/dev/alpha/tsunami_io.hh index 3972efa48..736f498c7 100644 --- a/src/dev/alpha/tsunami_io.hh +++ b/src/dev/alpha/tsunami_io.hh @@ -39,6 +39,7 @@ #include "base/range.hh" #include "dev/alpha/tsunami.hh" +#include "dev/intel_8254_timer.hh" #include "dev/mc146818.hh" #include "dev/io_device.hh" #include "params/TsunamiIO.hh" @@ -69,138 +70,6 @@ class TsunamiIO : public BasicPioDevice } }; - /** Programmable Interval Timer (Intel 8254) */ - class PITimer - { - /** Counter element for PIT */ - class Counter - { - /** Event for counter interrupt */ - class CounterEvent : public Event - { - private: - /** Pointer back to Counter */ - Counter* counter; - Tick interval; - - public: - CounterEvent(Counter*); - - /** Event process */ - virtual void process(); - - /** Event description */ - virtual const char *description() const; - - friend class Counter; - }; - - private: - std::string _name; - const std::string &name() const { return _name; } - - CounterEvent event; - - /** Current count value */ - uint16_t count; - - /** Latched count */ - uint16_t latched_count; - - /** Interrupt period */ - uint16_t period; - - /** Current mode of operation */ - uint8_t mode; - - /** Output goes high when the counter reaches zero */ - bool output_high; - - /** State of the count latch */ - bool latch_on; - - /** Set of values for read_byte and write_byte */ - enum {LSB, MSB}; - - /** Determine which byte of a 16-bit count value to read/write */ - uint8_t read_byte, write_byte; - - public: - Counter(const std::string &name); - - /** Latch the current count (if one is not already latched) */ - void latchCount(); - - /** Set the read/write mode */ - void setRW(int rw_val); - - /** Set operational mode */ - void setMode(int mode_val); - - /** Set count encoding */ - void setBCD(int bcd_val); - - /** Read a count byte */ - uint8_t read(); - - /** Write a count byte */ - void write(const uint8_t data); - - /** Is the output high? */ - bool outputHigh(); - - /** - * Serialize this object to the given output stream. - * @param base The base name of the counter object. - * @param os The stream to serialize to. - */ - void serialize(const std::string &base, std::ostream &os); - - /** - * Reconstruct the state of this object from a checkpoint. - * @param base The base name of the counter object. - * @param cp The checkpoint use. - * @param section The section name of this object - */ - void unserialize(const std::string &base, Checkpoint *cp, - const std::string §ion); - }; - - private: - std::string _name; - const std::string &name() const { return _name; } - - /** PIT has three seperate counters */ - Counter *counter[3]; - - public: - /** Public way to access individual counters (avoid array accesses) */ - Counter counter0; - Counter counter1; - Counter counter2; - - PITimer(const std::string &name); - - /** Write control word */ - void writeControl(const uint8_t data); - - /** - * Serialize this object to the given output stream. - * @param base The base name of the counter object. - * @param os The stream to serialize to. - */ - void serialize(const std::string &base, std::ostream &os); - - /** - * Reconstruct the state of this object from a checkpoint. - * @param base The base name of the counter object. - * @param cp The checkpoint use. - * @param section The section name of this object - */ - void unserialize(const std::string &base, Checkpoint *cp, - const std::string §ion); - }; - /** Mask of the PIC1 */ uint8_t mask1; @@ -223,7 +92,7 @@ class TsunamiIO : public BasicPioDevice Tsunami *tsunami; /** Intel 8253 Periodic Interval Timer */ - PITimer pitimer; + Intel8254Timer pitimer; TsunamiRTC rtc; diff --git a/src/dev/intel_8254_timer.cc b/src/dev/intel_8254_timer.cc new file mode 100644 index 000000000..16d09f582 --- /dev/null +++ b/src/dev/intel_8254_timer.cc @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2004, 2005 + * The Regents of The University of Michigan + * All Rights Reserved + * + * This code is part of the M5 simulator. + * + * Permission is granted to use, copy, create derivative works and + * redistribute this software and such derivative works for any + * purpose, so long as the copyright notice above, this grant of + * permission, and the disclaimer below appear in all copies made; and + * so long as the name of The University of Michigan is not used in + * any advertising or publicity pertaining to the use or distribution + * of this software without specific, written prior authorization. + * + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE + * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND + * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE + * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM + * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGES. + * + * Authors: Ali G. Saidi + * Andrew L. Schultz + * Miguel J. Serrano + */ + +#include "base/misc.hh" +#include "dev/intel_8254_timer.hh" + +using namespace std; + +Intel8254Timer::Intel8254Timer(const string &name) + : _name(name), counter0(name + ".counter0"), counter1(name + ".counter1"), + counter2(name + ".counter2") +{ + counter[0] = &counter0; + counter[1] = &counter0; + counter[2] = &counter0; +} + +void +Intel8254Timer::writeControl(const CtrlReg data) +{ + int sel = data.sel; + + if (sel == ReadBackCommand) + panic("PITimer Read-Back Command is not implemented.\n"); + + if (data.rw == LatchCommand) + counter[sel]->latchCount(); + else { + counter[sel]->setRW(data.rw); + counter[sel]->setMode(data.mode); + counter[sel]->setBCD(data.bcd); + } +} + +void +Intel8254Timer::serialize(const string &base, ostream &os) +{ + // serialize the counters + counter0.serialize(base + ".counter0", os); + counter1.serialize(base + ".counter1", os); + counter2.serialize(base + ".counter2", os); +} + +void +Intel8254Timer::unserialize(const string &base, Checkpoint *cp, + const string §ion) +{ + // unserialze the counters + counter0.unserialize(base + ".counter0", cp, section); + counter1.unserialize(base + ".counter1", cp, section); + counter2.unserialize(base + ".counter2", cp, section); +} + +Intel8254Timer::Counter::Counter(const string &name) + : _name(name), event(this), count(0), latched_count(0), period(0), + mode(0), output_high(false), latch_on(false), read_byte(LSB), + write_byte(LSB) +{ + +} + +void +Intel8254Timer::Counter::latchCount() +{ + // behave like a real latch + if(!latch_on) { + latch_on = true; + read_byte = LSB; + latched_count = count; + } +} + +uint8_t +Intel8254Timer::Counter::read() +{ + if (latch_on) { + switch (read_byte) { + case LSB: + read_byte = MSB; + return (uint8_t)latched_count; + break; + case MSB: + read_byte = LSB; + latch_on = false; + return latched_count >> 8; + break; + default: + panic("Shouldn't be here"); + } + } else { + switch (read_byte) { + case LSB: + read_byte = MSB; + return (uint8_t)count; + break; + case MSB: + read_byte = LSB; + return count >> 8; + break; + default: + panic("Shouldn't be here"); + } + } +} + +void +Intel8254Timer::Counter::write(const uint8_t data) +{ + switch (write_byte) { + case LSB: + count = (count & 0xFF00) | data; + + if (event.scheduled()) + event.deschedule(); + output_high = false; + write_byte = MSB; + break; + + case MSB: + count = (count & 0x00FF) | (data << 8); + period = count; + + if (period > 0) { + DPRINTF(Intel8254Timer, "Timer set to curTick + %d\n", + count * event.interval); + event.schedule(curTick + count * event.interval); + } + write_byte = LSB; + break; + } +} + +void +Intel8254Timer::Counter::setRW(int rw_val) +{ + if (rw_val != TwoPhase) + panic("Only LSB/MSB read/write is implemented.\n"); +} + +void +Intel8254Timer::Counter::setMode(int mode_val) +{ + if(mode_val != InitTc && mode_val != RateGen && + mode_val != SquareWave) + panic("PIT mode %#x is not implemented: \n", mode_val); + + mode = mode_val; +} + +void +Intel8254Timer::Counter::setBCD(int bcd_val) +{ + if (bcd_val) + panic("PITimer does not implement BCD counts.\n"); +} + +bool +Intel8254Timer::Counter::outputHigh() +{ + return output_high; +} + +void +Intel8254Timer::Counter::serialize(const string &base, ostream &os) +{ + paramOut(os, base + ".count", count); + paramOut(os, base + ".latched_count", latched_count); + paramOut(os, base + ".period", period); + paramOut(os, base + ".mode", mode); + paramOut(os, base + ".output_high", output_high); + paramOut(os, base + ".latch_on", latch_on); + paramOut(os, base + ".read_byte", read_byte); + paramOut(os, base + ".write_byte", write_byte); + + Tick event_tick = 0; + if (event.scheduled()) + event_tick = event.when(); + paramOut(os, base + ".event_tick", event_tick); +} + +void +Intel8254Timer::Counter::unserialize(const string &base, Checkpoint *cp, + const string §ion) +{ + paramIn(cp, section, base + ".count", count); + paramIn(cp, section, base + ".latched_count", latched_count); + paramIn(cp, section, base + ".period", period); + paramIn(cp, section, base + ".mode", mode); + paramIn(cp, section, base + ".output_high", output_high); + paramIn(cp, section, base + ".latch_on", latch_on); + paramIn(cp, section, base + ".read_byte", read_byte); + paramIn(cp, section, base + ".write_byte", write_byte); + + Tick event_tick; + paramIn(cp, section, base + ".event_tick", event_tick); + if (event_tick) + event.schedule(event_tick); +} + +Intel8254Timer::Counter::CounterEvent::CounterEvent(Counter* c_ptr) + : Event(&mainEventQueue) +{ + interval = (Tick)(Clock::Float::s / 1193180.0); + counter = c_ptr; +} + +void +Intel8254Timer::Counter::CounterEvent::process() +{ + DPRINTF(Intel8254Timer, "Timer Interrupt\n"); + switch (counter->mode) { + case InitTc: + counter->output_high = true; + case RateGen: + case SquareWave: + break; + default: + panic("Unimplemented PITimer mode.\n"); + } +} + +const char * +Intel8254Timer::Counter::CounterEvent::description() const +{ + return "tsunami 8254 Interval timer"; +} diff --git a/src/dev/intel_8254_timer.hh b/src/dev/intel_8254_timer.hh new file mode 100644 index 000000000..c7c2b1591 --- /dev/null +++ b/src/dev/intel_8254_timer.hh @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2004, 2005 + * The Regents of The University of Michigan + * All Rights Reserved + * + * This code is part of the M5 simulator. + * + * Permission is granted to use, copy, create derivative works and + * redistribute this software and such derivative works for any + * purpose, so long as the copyright notice above, this grant of + * permission, and the disclaimer below appear in all copies made; and + * so long as the name of The University of Michigan is not used in + * any advertising or publicity pertaining to the use or distribution + * of this software without specific, written prior authorization. + * + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE + * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND + * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE + * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM + * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGES. + * + * Authors: Ali G. Saidi + * Andrew L. Schultz + * Miguel J. Serrano + */ + +#ifndef __DEV_8254_HH__ +#define __DEV_8254_HH__ + +#include "base/bitunion.hh" +#include "sim/eventq.hh" +#include "sim/host.hh" +#include "sim/serialize.hh" + +#include +#include + +/** Programmable Interval Timer (Intel 8254) */ +class Intel8254Timer +{ + BitUnion8(CtrlReg) + Bitfield<7, 6> sel; + Bitfield<5, 4> rw; + Bitfield<3, 1> mode; + Bitfield<0> bcd; + EndBitUnion(CtrlReg) + + enum SelectVal { + SelectCounter0, + SelectCounter1, + SelectCounter2, + ReadBackCommand + }; + + enum ReadWriteVal { + LatchCommand, + LsbOnly, + MsbOnly, + TwoPhase + }; + + enum ModeVal { + InitTc, + OneShot, + RateGen, + SquareWave, + SoftwareStrobe, + HardwareStrobe + }; + + /** Counter element for PIT */ + class Counter + { + /** Event for counter interrupt */ + class CounterEvent : public Event + { + private: + /** Pointer back to Counter */ + Counter* counter; + Tick interval; + + public: + CounterEvent(Counter*); + + /** Event process */ + virtual void process(); + + /** Event description */ + virtual const char *description() const; + + friend class Counter; + }; + + private: + std::string _name; + const std::string &name() const { return _name; } + + CounterEvent event; + + /** Current count value */ + uint16_t count; + + /** Latched count */ + uint16_t latched_count; + + /** Interrupt period */ + uint16_t period; + + /** Current mode of operation */ + uint8_t mode; + + /** Output goes high when the counter reaches zero */ + bool output_high; + + /** State of the count latch */ + bool latch_on; + + /** Set of values for read_byte and write_byte */ + enum {LSB, MSB}; + + /** Determine which byte of a 16-bit count value to read/write */ + uint8_t read_byte, write_byte; + + public: + Counter(const std::string &name); + + /** Latch the current count (if one is not already latched) */ + void latchCount(); + + /** Set the read/write mode */ + void setRW(int rw_val); + + /** Set operational mode */ + void setMode(int mode_val); + + /** Set count encoding */ + void setBCD(int bcd_val); + + /** Read a count byte */ + uint8_t read(); + + /** Write a count byte */ + void write(const uint8_t data); + + /** Is the output high? */ + bool outputHigh(); + + /** + * Serialize this object to the given output stream. + * @param base The base name of the counter object. + * @param os The stream to serialize to. + */ + void serialize(const std::string &base, std::ostream &os); + + /** + * Reconstruct the state of this object from a checkpoint. + * @param base The base name of the counter object. + * @param cp The checkpoint use. + * @param section The section name of this object + */ + void unserialize(const std::string &base, Checkpoint *cp, + const std::string §ion); + }; + + private: + std::string _name; + const std::string &name() const { return _name; } + + /** PIT has three seperate counters */ + Counter *counter[3]; + + public: + /** Public way to access individual counters (avoid array accesses) */ + Counter counter0; + Counter counter1; + Counter counter2; + + Intel8254Timer(const std::string &name); + + /** Write control word */ + void writeControl(const CtrlReg data); + + /** + * Serialize this object to the given output stream. + * @param base The base name of the counter object. + * @param os The stream to serialize to. + */ + void serialize(const std::string &base, std::ostream &os); + + /** + * Reconstruct the state of this object from a checkpoint. + * @param base The base name of the counter object. + * @param cp The checkpoint use. + * @param section The section name of this object + */ + void unserialize(const std::string &base, Checkpoint *cp, + const std::string §ion); +}; + +#endif // __DEV_8254_HH__ diff --git a/src/dev/pitreg.h b/src/dev/pitreg.h deleted file mode 100644 index d42925a41..000000000 --- a/src/dev/pitreg.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2001-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Miguel Serrano - */ - -/* @file - * Device register definitions for a device's PCI config space - */ - -#ifndef __PITREG_H__ -#define __PITREG_H__ - -#include - -// Control Word Format - -#define PIT_SEL_SHFT 0x6 -#define PIT_RW_SHFT 0x4 -#define PIT_MODE_SHFT 0x1 -#define PIT_BCD_SHFT 0x0 - -#define PIT_SEL_MASK 0x3 -#define PIT_RW_MASK 0x3 -#define PIT_MODE_MASK 0x7 -#define PIT_BCD_MASK 0x1 - -#define GET_CTRL_FIELD(x, s, m) (((x) >> s) & m) -#define GET_CTRL_SEL(x) GET_CTRL_FIELD(x, PIT_SEL_SHFT, PIT_SEL_MASK) -#define GET_CTRL_RW(x) GET_CTRL_FIELD(x, PIT_RW_SHFT, PIT_RW_MASK) -#define GET_CTRL_MODE(x) GET_CTRL_FIELD(x, PIT_MODE_SHFT, PIT_MODE_MASK) -#define GET_CTRL_BCD(x) GET_CTRL_FIELD(x, PIT_BCD_SHFT, PIT_BCD_MASK) - -#define PIT_READ_BACK 0x3 - -#define PIT_RW_LATCH_COMMAND 0x0 -#define PIT_RW_LSB_ONLY 0x1 -#define PIT_RW_MSB_ONLY 0x2 -#define PIT_RW_16BIT 0x3 - -#define PIT_MODE_INTTC 0x0 -#define PIT_MODE_ONESHOT 0x1 -#define PIT_MODE_RATEGEN 0x2 -#define PIT_MODE_SQWAVE 0x3 -#define PIT_MODE_SWSTROBE 0x4 -#define PIT_MODE_HWSTROBE 0x5 - -#define PIT_BCD_FALSE 0x0 -#define PIT_BCD_TRUE 0x1 - -#endif // __PITREG_H__ diff --git a/src/dev/x86/south_bridge/i8254.cc b/src/dev/x86/south_bridge/i8254.cc index fb6723a51..7c3501c37 100644 --- a/src/dev/x86/south_bridge/i8254.cc +++ b/src/dev/x86/south_bridge/i8254.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2005 The Regents of The University of Michigan + * Copyright (c) 2008 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,21 +38,21 @@ X86ISA::I8254::read(PacketPtr pkt) switch(pkt->getAddr() - addrRange.start) { case 0x0: - warn("Reading from timer 0 counter.\n"); + pkt->set(pit.counter0.read()); break; case 0x1: - warn("Reading from timer 1 counter.\n"); + pkt->set(pit.counter1.read()); break; case 0x2: - warn("Reading from timer 2 counter.\n"); + pkt->set(pit.counter2.read()); break; case 0x3: - fatal("Reading from timer control word which is read only.\n"); + pkt->set(uint8_t(-1)); break; default: panic("Read from undefined i8254 register.\n"); } - return SubDevice::read(pkt); + return latency; } Tick @@ -62,25 +62,19 @@ X86ISA::I8254::write(PacketPtr pkt) switch(pkt->getAddr() - addrRange.start) { case 0x0: - warn("Writing to timer 0 counter.\n"); + pit.counter0.write(pkt->get()); break; case 0x1: - warn("Writing to timer 1 counter.\n"); + pit.counter1.write(pkt->get()); break; case 0x2: - warn("Writing to timer 2 counter.\n"); + pit.counter2.write(pkt->get()); break; case 0x3: - processControlWord(pkt->get()); - return latency; + pit.writeControl(pkt->get()); + break; default: panic("Write to undefined i8254 register.\n"); } - return SubDevice::write(pkt); -} - -void -X86ISA::I8254::processControlWord(uint8_t word) -{ - warn("I8254 received control word %x.\n", word); + return latency; } diff --git a/src/dev/x86/south_bridge/i8254.hh b/src/dev/x86/south_bridge/i8254.hh index f246fd8e4..519049e93 100644 --- a/src/dev/x86/south_bridge/i8254.hh +++ b/src/dev/x86/south_bridge/i8254.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2005 The Regents of The University of Michigan + * Copyright (c) 2008 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,24 +33,28 @@ #include "arch/x86/x86_traits.hh" #include "base/range.hh" +#include "dev/intel_8254_timer.hh" #include "dev/x86/south_bridge/sub_device.hh" +#include + namespace X86ISA { class I8254 : public SubDevice { protected: - void processControlWord(uint8_t word); + Intel8254Timer pit; public: - I8254() + I8254(const std::string &name) : pit(name) {} - I8254(Tick _latency) : SubDevice(_latency) + I8254(const std::string &name, Tick _latency) : + SubDevice(_latency), pit(name) {} - I8254(Addr start, Addr size, Tick _latency) : - SubDevice(start, size, _latency) + I8254(const std::string &name, Addr start, Addr size, Tick _latency) : + SubDevice(start, size, _latency), pit(name) {} Tick read(PacketPtr pkt); diff --git a/src/dev/x86/south_bridge/south_bridge.cc b/src/dev/x86/south_bridge/south_bridge.cc index f25b3b811..cc20ea09e 100644 --- a/src/dev/x86/south_bridge/south_bridge.cc +++ b/src/dev/x86/south_bridge/south_bridge.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2005 The Regents of The University of Michigan + * Copyright (c) 2008 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -68,7 +68,7 @@ SouthBridge::write(PacketPtr pkt) SouthBridge::SouthBridge(const Params *p) : PioDevice(p), pic1(0x20, 2, p->pio_latency), pic2(0xA0, 2, p->pio_latency), - pit(0x40, 4, p->pio_latency), + pit(p->name + ".pit", 0x40, 4, p->pio_latency), cmos(0x70, 2, p->pio_latency), speaker(0x61, 1, p->pio_latency) { -- cgit v1.2.3 From da7f5120671ffd7acd65f66452bdf959a56a5855 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:56:07 -0400 Subject: Timer: Fill out the periodic modes a little. --- src/dev/intel_8254_timer.cc | 27 +++++++++++++++++++++------ src/dev/intel_8254_timer.hh | 2 ++ 2 files changed, 23 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/dev/intel_8254_timer.cc b/src/dev/intel_8254_timer.cc index 16d09f582..802dd44f5 100644 --- a/src/dev/intel_8254_timer.cc +++ b/src/dev/intel_8254_timer.cc @@ -147,13 +147,16 @@ Intel8254Timer::Counter::write(const uint8_t data) case MSB: count = (count & 0x00FF) | (data << 8); - period = count; + // In the RateGen or SquareWave modes, the timer wraps around and + // triggers on a value of 1, not 0. + if (mode == RateGen || mode == SquareWave) + period = count - 1; + else + period = count; + + if (period > 0) + event.setTo(period); - if (period > 0) { - DPRINTF(Intel8254Timer, "Timer set to curTick + %d\n", - count * event.interval); - event.schedule(curTick + count * event.interval); - } write_byte = LSB; break; } @@ -240,14 +243,26 @@ Intel8254Timer::Counter::CounterEvent::process() switch (counter->mode) { case InitTc: counter->output_high = true; + break; case RateGen: case SquareWave: + setTo(counter->period); break; default: panic("Unimplemented PITimer mode.\n"); } } +void +Intel8254Timer::Counter::CounterEvent::setTo(int clocks) +{ + if (clocks == 0) + panic("Timer can't be set to go off instantly.\n"); + DPRINTF(Intel8254Timer, "Timer set to curTick + %d\n", + clocks * interval); + schedule(curTick + clocks * interval); +} + const char * Intel8254Timer::Counter::CounterEvent::description() const { diff --git a/src/dev/intel_8254_timer.hh b/src/dev/intel_8254_timer.hh index c7c2b1591..23596a687 100644 --- a/src/dev/intel_8254_timer.hh +++ b/src/dev/intel_8254_timer.hh @@ -95,6 +95,8 @@ class Intel8254Timer virtual const char *description() const; friend class Counter; + + void setTo(int clocks); }; private: -- cgit v1.2.3 From 16e26fbf03260f362f6090503626f2068d76f89e Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:56:17 -0400 Subject: X86: Hook the speaker device to the pit device. --- src/dev/x86/south_bridge/SConscript | 4 +++- src/dev/x86/south_bridge/i8254.hh | 4 +--- src/dev/x86/south_bridge/south_bridge.cc | 2 +- src/dev/x86/south_bridge/speaker.cc | 36 +++++++++++++++++++------------- src/dev/x86/south_bridge/speaker.hh | 24 ++++++++++++++++----- 5 files changed, 45 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/dev/x86/south_bridge/SConscript b/src/dev/x86/south_bridge/SConscript index a7cb77b9b..d01106c5c 100644 --- a/src/dev/x86/south_bridge/SConscript +++ b/src/dev/x86/south_bridge/SConscript @@ -1,6 +1,6 @@ # -*- mode:python -*- -# Copyright (c) 2006 The Regents of The University of Michigan +# Copyright (c) 2008 The Regents of The University of Michigan # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -40,3 +40,5 @@ if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'x86': Source('i8254.cc') Source('i8259.cc') Source('speaker.cc') + + TraceFlag('PCSpeaker') diff --git a/src/dev/x86/south_bridge/i8254.hh b/src/dev/x86/south_bridge/i8254.hh index 519049e93..6f718a853 100644 --- a/src/dev/x86/south_bridge/i8254.hh +++ b/src/dev/x86/south_bridge/i8254.hh @@ -43,10 +43,8 @@ namespace X86ISA class I8254 : public SubDevice { - protected: - Intel8254Timer pit; - public: + Intel8254Timer pit; I8254(const std::string &name) : pit(name) {} diff --git a/src/dev/x86/south_bridge/south_bridge.cc b/src/dev/x86/south_bridge/south_bridge.cc index cc20ea09e..57cc27bcc 100644 --- a/src/dev/x86/south_bridge/south_bridge.cc +++ b/src/dev/x86/south_bridge/south_bridge.cc @@ -70,7 +70,7 @@ SouthBridge::SouthBridge(const Params *p) : PioDevice(p), pic2(0xA0, 2, p->pio_latency), pit(p->name + ".pit", 0x40, 4, p->pio_latency), cmos(0x70, 2, p->pio_latency), - speaker(0x61, 1, p->pio_latency) + speaker(&pit, 0x61, 1, p->pio_latency) { addDevice(pic1); addDevice(pic2); diff --git a/src/dev/x86/south_bridge/speaker.cc b/src/dev/x86/south_bridge/speaker.cc index 734dba4c2..784c9504b 100644 --- a/src/dev/x86/south_bridge/speaker.cc +++ b/src/dev/x86/south_bridge/speaker.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2005 The Regents of The University of Michigan + * Copyright (c) 2008 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,26 +29,23 @@ */ #include "base/bitunion.hh" +#include "base/trace.hh" +#include "dev/x86/south_bridge/i8254.hh" #include "dev/x86/south_bridge/speaker.hh" #include "mem/packet_access.hh" -BitUnion8(SpeakerControl) - Bitfield<0> gate; - Bitfield<1> speaker; - Bitfield<5> timer; -EndBitUnion(SpeakerControl) - Tick X86ISA::Speaker::read(PacketPtr pkt) { assert(pkt->getAddr() == addrRange.start); assert(pkt->getSize() == 1); - SpeakerControl val = 0xFF; - warn("Reading from speaker device: gate %s, speaker %s, output %s.\n", - val.gate ? "on" : "off", - val.speaker ? "on" : "off", - val.timer ? "on" : "off"); - pkt->set((uint8_t)val); + controlVal.timer = timer->pit.counter2.outputHigh() ? 1 : 0; + DPRINTF(PCSpeaker, + "Reading from speaker device: gate %s, speaker %s, output %s.\n", + controlVal.gate ? "on" : "off", + controlVal.speaker ? "on" : "off", + controlVal.timer ? "on" : "off"); + pkt->set((uint8_t)controlVal); return latency; } @@ -58,7 +55,16 @@ X86ISA::Speaker::write(PacketPtr pkt) assert(pkt->getAddr() == addrRange.start); assert(pkt->getSize() == 1); SpeakerControl val = pkt->get(); - warn("Writing to speaker device: gate %s, speaker %s.\n", - val.gate ? "on" : "off", val.speaker ? "on" : "off"); + controlVal.gate = val.gate; + //Change the gate value in the timer. + if (!val.gate) + warn("The gate bit of the pc speaker isn't implemented and " + "is always on.\n"); + //This would control whether the timer output is hooked up to a physical + //speaker. Since M5 can't make noise, it's value doesn't actually do + //anything. + controlVal.speaker = val.speaker; + DPRINTF(PCSpeaker, "Writing to speaker device: gate %s, speaker %s.\n", + controlVal.gate ? "on" : "off", controlVal.speaker ? "on" : "off"); return latency; } diff --git a/src/dev/x86/south_bridge/speaker.hh b/src/dev/x86/south_bridge/speaker.hh index df738e42b..2385b80cc 100644 --- a/src/dev/x86/south_bridge/speaker.hh +++ b/src/dev/x86/south_bridge/speaker.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2005 The Regents of The University of Michigan + * Copyright (c) 2008 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,16 +38,30 @@ namespace X86ISA { +class I8254; + class Speaker : public SubDevice { + protected: + BitUnion8(SpeakerControl) + Bitfield<0> gate; + Bitfield<1> speaker; + Bitfield<5> timer; + EndBitUnion(SpeakerControl) + + SpeakerControl controlVal; + + I8254 * timer; + public: - Speaker() + Speaker(I8254 * _timer) : timer(_timer) {} - Speaker(Tick _latency) : SubDevice(_latency) + Speaker(I8254 * _timer, Tick _latency) : + SubDevice(_latency), timer(_timer) {} - Speaker(Addr start, Addr size, Tick _latency) : - SubDevice(start, size, _latency) + Speaker(I8254 * _timer, Addr start, Addr size, Tick _latency) : + SubDevice(start, size, _latency), timer(_timer) {} Tick read(PacketPtr pkt); -- cgit v1.2.3 From 1f5b992b582f0d8de792df24a81d4a25642b3e45 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:56:54 -0400 Subject: X86: Make the platform object initialize channel 0 of the PIT. --- src/dev/x86/pc.cc | 18 +++++++++++++++++- src/dev/x86/pc.hh | 9 ++++++++- src/dev/x86/south_bridge/south_bridge.cc | 6 ++++++ src/dev/x86/south_bridge/south_bridge.hh | 22 ++++++++++++---------- 4 files changed, 43 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/dev/x86/pc.cc b/src/dev/x86/pc.cc index 148ba92f7..0881672d2 100644 --- a/src/dev/x86/pc.cc +++ b/src/dev/x86/pc.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2005 The Regents of The University of Michigan + * Copyright (c) 2008 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,6 +37,7 @@ #include #include "arch/x86/x86_traits.hh" +#include "dev/intel_8254_timer.hh" #include "cpu/intr_control.hh" #include "dev/simconsole.hh" #include "dev/x86/pc.hh" @@ -48,10 +49,25 @@ using namespace TheISA; PC::PC(const Params *p) : Platform(p), system(p->system) { + southBridge = NULL; // set the back pointer from the system to myself system->platform = this; } +void +PC::init() +{ + assert(southBridge); + Intel8254Timer & timer = southBridge->pit.pit; + //Timer 0, mode 2, no bcd, 16 bit count + timer.writeControl(0x34); + //Timer 0, latch command + timer.writeControl(0x00); + //Write a 16 bit count of 0 + timer.counter0.write(0); + timer.counter0.write(0); +} + Tick PC::intrFrequency() { diff --git a/src/dev/x86/pc.hh b/src/dev/x86/pc.hh index 6e3a7f45e..3a042fc46 100644 --- a/src/dev/x86/pc.hh +++ b/src/dev/x86/pc.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2005 The Regents of The University of Michigan + * Copyright (c) 2008 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,6 +38,7 @@ #define __DEV_PC_HH__ #include "dev/platform.hh" +#include "dev/x86/south_bridge/south_bridge.hh" #include "params/PC.hh" class IdeController; @@ -48,10 +49,16 @@ class PC : public Platform public: /** Pointer to the system */ System *system; + SouthBridge * southBridge; public: typedef PCParams Params; + /** + * Do platform initialization stuff + */ + void init(); + PC(const Params *p); /** diff --git a/src/dev/x86/south_bridge/south_bridge.cc b/src/dev/x86/south_bridge/south_bridge.cc index 57cc27bcc..b1f0abfe6 100644 --- a/src/dev/x86/south_bridge/south_bridge.cc +++ b/src/dev/x86/south_bridge/south_bridge.cc @@ -30,6 +30,7 @@ #include "arch/x86/x86_traits.hh" #include "base/range.hh" +#include "dev/x86/pc.hh" #include "dev/x86/south_bridge/south_bridge.hh" using namespace X86ISA; @@ -77,6 +78,11 @@ SouthBridge::SouthBridge(const Params *p) : PioDevice(p), addDevice(pit); addDevice(cmos); addDevice(speaker); + + // Let the platform know where we are + PC * pc = dynamic_cast(platform); + assert(pc); + pc->southBridge = this; } SouthBridge * diff --git a/src/dev/x86/south_bridge/south_bridge.hh b/src/dev/x86/south_bridge/south_bridge.hh index 28936fb91..203cb6ee2 100644 --- a/src/dev/x86/south_bridge/south_bridge.hh +++ b/src/dev/x86/south_bridge/south_bridge.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2005 The Regents of The University of Michigan + * Copyright (c) 2008 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,6 +43,16 @@ class SouthBridge : public PioDevice { protected: + AddrRangeList rangeList; + + typedef range_map RangeMap; + typedef RangeMap::iterator RangeMapIt; + RangeMap rangeMap; + + + void addDevice(X86ISA::SubDevice &); + + public: // PICs X86ISA::I8259 pic1; X86ISA::I8259 pic2; @@ -56,16 +66,8 @@ class SouthBridge : public PioDevice // PC speaker X86ISA::Speaker speaker; - AddrRangeList rangeList; - - typedef range_map RangeMap; - typedef RangeMap::iterator RangeMapIt; - RangeMap rangeMap; - - - void addDevice(X86ISA::SubDevice &); - public: + void addressRanges(AddrRangeList &range_list); Tick read(PacketPtr pkt); -- cgit v1.2.3 From da20c0ec54d322cbffe3c7d0053ea4dc8be24d94 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:58:13 -0400 Subject: X86: Make sure there's something to catch when the kernel messes with ports "behind" the pci config magic ports. --- src/dev/x86/PC.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/dev/x86/PC.py b/src/dev/x86/PC.py index 86ae4c3ba..4ba9e7a8a 100644 --- a/src/dev/x86/PC.py +++ b/src/dev/x86/PC.py @@ -50,6 +50,10 @@ class PC(Platform): # "Non-existant" port used for timing purposes by the linux kernel i_dont_exist = IsaFake(pio_addr=x86IOAddress(0x80), pio_size=1) + # Ports behind the pci config and data regsiters. These don't do anything, + # but the linux kernel fiddles with them anway. + behind_pci = IsaFake(pio_addr=x86IOAddress(0xcf8), pio_size=8) + # Serial port and console console = SimConsole() com_1 = Uart8250() @@ -59,6 +63,7 @@ class PC(Platform): def attachIO(self, bus): self.south_bridge.pio = bus.port self.i_dont_exist.pio = bus.port + self.behind_pci.pio = bus.port self.com_1.pio = bus.port self.pciconfig.pio = bus.default bus.responder_set = True -- cgit v1.2.3 From 31d40ad7c22651eb88271abddacf416aa7c2adf2 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:58:19 -0400 Subject: X86: Implement and hook up STI and CLI instructions. --- src/arch/x86/isa/decoder/one_byte_opcodes.isa | 4 ++-- .../insts/general_purpose/flags/set_and_clear.py | 22 +++++++++++++++------- 2 files changed, 17 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa index 8729f417d..005864f02 100644 --- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa @@ -553,8 +553,8 @@ 0x1F: decode OPCODE_OP_BOTTOM3 { 0x0: CLC(); 0x1: STC(); - 0x2: WarnUnimpl::cli(); - 0x3: WarnUnimpl::sti(); + 0x2: CLI(); + 0x3: STI(); 0x4: CLD(); 0x5: STD(); //0x6: group4(); diff --git a/src/arch/x86/isa/insts/general_purpose/flags/set_and_clear.py b/src/arch/x86/isa/insts/general_purpose/flags/set_and_clear.py index 4c655e0b2..e151dc61d 100644 --- a/src/arch/x86/isa/insts/general_purpose/flags/set_and_clear.py +++ b/src/arch/x86/isa/insts/general_purpose/flags/set_and_clear.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -84,10 +84,18 @@ def macroop CMC { ruflags t1 wruflagsi t1, "CFBit" }; + +def macroop STI { + rflags t1 + limm t2, "IFBit" + or t1, t1, t2 + wrflags t1, t0 +}; + +def macroop CLI { + rflags t1 + limm t2, "~IFBit" + and t1, t1, t2 + wrflags t1, t0 +}; ''' -#let {{ -# class CLI(Inst): -# "GenFault ${new UnimpInstFault}" -# class STI(Inst): -# "GenFault ${new UnimpInstFault}" -#}}; -- cgit v1.2.3 From 4f4ff17578846018e06b0b9b047df96a8346efd9 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:58:27 -0400 Subject: X86: Make the disassembly for halt conform with the other microops. --- src/arch/x86/isa/microops/specop.isa | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/isa/microops/specop.isa b/src/arch/x86/isa/microops/specop.isa index 6bcc7ff91..ad14b54a3 100644 --- a/src/arch/x86/isa/microops/specop.isa +++ b/src/arch/x86/isa/microops/specop.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2007 The Hewlett-Packard Development Company +// Copyright (c) 2007-2008 The Hewlett-Packard Development Company // All rights reserved. // // Redistribution and use of this software in source and binary forms, @@ -95,6 +95,9 @@ output header {{ } %(BasicExecDeclare)s + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; }; }}; @@ -201,6 +204,16 @@ output decoder {{ return response.str(); } + + std::string MicroHalt::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, instMnem, mnemonic); + + return response.str(); + } }}; let {{ -- cgit v1.2.3 From bceaa257a38d62c91317cecc78f4dba46654eb93 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:58:36 -0400 Subject: X86: Make the e820 table manually or automatically configurable from python. --- src/arch/x86/SConscript | 2 + src/arch/x86/X86System.py | 6 ++- src/arch/x86/bios/E820.py | 73 ++++++++++++++++++++++++++++++ src/arch/x86/bios/e820.cc | 103 +++++++++++++++++++++++++++++++++++++++++++ src/arch/x86/bios/e820.hh | 100 +++++++++++++++++++++++++++++++++++++++++ src/arch/x86/linux/system.cc | 61 ++----------------------- src/arch/x86/linux/system.hh | 4 +- 7 files changed, 289 insertions(+), 60 deletions(-) create mode 100644 src/arch/x86/bios/E820.py create mode 100644 src/arch/x86/bios/e820.cc create mode 100644 src/arch/x86/bios/e820.hh (limited to 'src') diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript index 09967b0d3..184bb4809 100644 --- a/src/arch/x86/SConscript +++ b/src/arch/x86/SConscript @@ -110,8 +110,10 @@ if env['TARGET_ISA'] == 'x86': if env['FULL_SYSTEM']: SimObject('X86System.py') + SimObject('bios/E820.py') # Full-system sources + Source('bios/e820.cc') Source('linux/system.cc') Source('pagetable_walker.cc') Source('smbios.cc') diff --git a/src/arch/x86/X86System.py b/src/arch/x86/X86System.py index f73764540..b4ec393c3 100644 --- a/src/arch/x86/X86System.py +++ b/src/arch/x86/X86System.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -54,6 +54,7 @@ # Authors: Gabe Black from m5.params import * +from E820 import X86E820Table, X86E820Entry from System import System class X86System(System): @@ -61,3 +62,6 @@ class X86System(System): class LinuxX86System(X86System): type = 'LinuxX86System' + + e820_table = Param.X86E820Table( + X86E820Table(), 'E820 map of physical memory') diff --git a/src/arch/x86/bios/E820.py b/src/arch/x86/bios/E820.py new file mode 100644 index 000000000..e161cd56f --- /dev/null +++ b/src/arch/x86/bios/E820.py @@ -0,0 +1,73 @@ +# Copyright (c) 2008 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use of this software in source and binary forms, +# with or without modification, are permitted provided that the +# following conditions are met: +# +# The software must be used only for Non-Commercial Use which means any +# use which is NOT directed to receiving any direct monetary +# compensation for, or commercial advantage from such use. Illustrative +# examples of non-commercial use are academic research, personal study, +# teaching, education and corporate research & development. +# Illustrative examples of commercial use are distributing products for +# commercial advantage and providing services using the software for +# commercial advantage. +# +# If you wish to use this software or functionality therein that may be +# covered by patents for commercial use, please contact: +# Director of Intellectual Property Licensing +# Office of Strategy and Technology +# Hewlett-Packard Company +# 1501 Page Mill Road +# Palo Alto, California 94304 +# +# 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. No right of +# sublicense is granted herewith. Derivatives of the software and +# output created using the software may be prepared, but only for +# Non-Commercial Uses. Derivatives of the software may be shared with +# others provided: (i) the others agree to abide by the list of +# conditions herein which includes the Non-Commercial Use restrictions; +# and (ii) such Derivatives of the software include the above copyright +# notice to acknowledge the contribution from this software where +# applicable, this list of conditions and the disclaimer below. +# +# 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: Gabe Black + +from m5.params import * +from m5.SimObject import SimObject + +class X86E820Entry(SimObject): + type = 'X86E820Entry' + cxx_namespace = 'X86ISA' + cxx_class = 'E820Entry' + + addr = Param.Addr(0, 'address of the beginning of the region') + size = Param.MemorySize('0B', 'size of the region') + range_type = Param.UInt64('type of the region') + +class X86E820Table(SimObject): + type = 'X86E820Table' + cxx_namespace = 'X86ISA' + cxx_class = 'E820Table' + + entries = VectorParam.X86E820Entry([], 'entries for the e820 table') diff --git a/src/arch/x86/bios/e820.cc b/src/arch/x86/bios/e820.cc new file mode 100644 index 000000000..47adb703a --- /dev/null +++ b/src/arch/x86/bios/e820.cc @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2008 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * 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: Gabe Black + */ + +#include "arch/x86/bios/e820.hh" +#include "arch/x86/isa_traits.hh" +#include "mem/port.hh" +#include "sim/byteswap.hh" + +using namespace std; +using namespace X86ISA; + +template +void writeVal(T val, Port * port, Addr &addr) +{ + T guestVal = htog(val); + port->writeBlob(addr, (uint8_t *)&guestVal, sizeof(T)); + addr += sizeof(T); +} + +void X86ISA::E820Table::writeTo(Port * port, Addr countAddr, Addr addr) +{ + uint8_t e820Nr = entries.size(); + + // Make sure the number of entries isn't bigger than what the kernel + // would be capable of handling. + assert(e820Nr <= 128); + + uint8_t guestE820Nr = htog(e820Nr); + + port->writeBlob(countAddr, (uint8_t *)&guestE820Nr, sizeof(guestE820Nr)); + + for (int i = 0; i < e820Nr; i++) { + writeVal(entries[i]->addr, port, addr); + writeVal(entries[i]->size, port, addr); + writeVal(entries[i]->type, port, addr); + } +} + +E820Table * +X86E820TableParams::create() +{ + return new E820Table(this); +} + +E820Entry * +X86E820EntryParams::create() +{ + return new E820Entry(this); +} diff --git a/src/arch/x86/bios/e820.hh b/src/arch/x86/bios/e820.hh new file mode 100644 index 000000000..da738343b --- /dev/null +++ b/src/arch/x86/bios/e820.hh @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2008 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * 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: Gabe Black + */ + +#ifndef __ARCH_X86_BIOS_E820_HH__ +#define __ARCH_X86_BIOS_E820_HH__ + +#include "params/X86E820Entry.hh" +#include "params/X86E820Table.hh" +#include "sim/host.hh" +#include "sim/sim_object.hh" + +#include + +class Port; + +namespace X86ISA +{ + class E820Entry : public SimObject + { + public: + Addr addr; + Addr size; + uint32_t type; + + public: + typedef X86E820EntryParams Params; + E820Entry(Params *p) : + SimObject(p), addr(p->addr), size(p->size), type(p->range_type) + {} + }; + + class E820Table : public SimObject + { + public: + std::vector entries; + + public: + typedef X86E820TableParams Params; + E820Table(Params *p) : SimObject(p), entries(p->entries) + {} + + void writeTo(Port * port, Addr countAddr, Addr addr); + }; +}; + +#endif // __ARCH_X86_BIOS_E820_HH__ diff --git a/src/arch/x86/linux/system.cc b/src/arch/x86/linux/system.cc index 944bb2930..c2d9cb35c 100644 --- a/src/arch/x86/linux/system.cc +++ b/src/arch/x86/linux/system.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 The Hewlett-Packard Development Company + * Copyright (c) 2007-2008 The Hewlett-Packard Development Company * All rights reserved. * * Redistribution and use of this software in source and binary forms, @@ -68,7 +68,7 @@ using namespace LittleEndianGuest; using namespace X86ISA; LinuxX86System::LinuxX86System(Params *p) - : X86System(p), commandLine(p->boot_osflags) + : X86System(p), commandLine(p->boot_osflags), e820Table(p->e820_table) { } @@ -144,62 +144,7 @@ LinuxX86System::startup() // A pointer to the buffer for E820 entries. const Addr e820MapPointer = realModeData + 0x2d0; - struct e820Entry - { - Addr addr; - Addr size; - uint32_t type; - }; - - // The size is computed this way to ensure no padding sneaks in. - int e820EntrySize = - sizeof(e820Entry().addr) + - sizeof(e820Entry().size) + - sizeof(e820Entry().type); - - // I'm not sure what these should actually be. On a real machine they - // would be generated by the BIOS, and they need to reflect the regions - // which are actually available/reserved. These values are copied from - // my development machine. - e820Entry e820Map[] = { - {ULL(0x0), ULL(0x9d400), 1}, - {ULL(0x9d400), ULL(0xa0000) - ULL(0x9d400), 2}, - {ULL(0xe8000), ULL(0x100000) - ULL(0xe8000), 2}, - {ULL(0x100000), ULL(0xcfff9300) - ULL(0x100000), 1}, - {ULL(0xcfff9300), ULL(0xd0000000) - ULL(0xcfff9300), 2}, - {ULL(0xfec00000), ULL(0x100000000) - ULL(0xfec00000), 2} - }; - - uint8_t e820Nr = sizeof(e820Map) / sizeof(e820Entry); - - // Make sure the number of entries isn't bigger than what the kernel - // would be capable of providing. - assert(e820Nr <= 128); - - uint8_t guestE820Nr = X86ISA::htog(e820Nr); - physPort->writeBlob(e820MapNrPointer, - (uint8_t *)&guestE820Nr, sizeof(guestE820Nr)); - - for (int i = 0; i < e820Nr; i++) { - e820Entry guestE820Entry; - guestE820Entry.addr = X86ISA::htog(e820Map[i].addr); - guestE820Entry.size = X86ISA::htog(e820Map[i].size); - guestE820Entry.type = X86ISA::htog(e820Map[i].type); - physPort->writeBlob(e820MapPointer + e820EntrySize * i, - (uint8_t *)&guestE820Entry.addr, - sizeof(guestE820Entry.addr)); - physPort->writeBlob( - e820MapPointer + e820EntrySize * i + - sizeof(guestE820Entry.addr), - (uint8_t *)&guestE820Entry.size, - sizeof(guestE820Entry.size)); - physPort->writeBlob( - e820MapPointer + e820EntrySize * i + - sizeof(guestE820Entry.addr) + - sizeof(guestE820Entry.size), - (uint8_t *)&guestE820Entry.type, - sizeof(guestE820Entry.type)); - } + e820Table->writeTo(physPort, e820MapNrPointer, e820MapPointer); /* * Pass the location of the real mode data structure to the kernel diff --git a/src/arch/x86/linux/system.hh b/src/arch/x86/linux/system.hh index fc725ad45..a9c5f4ca9 100644 --- a/src/arch/x86/linux/system.hh +++ b/src/arch/x86/linux/system.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 The Hewlett-Packard Development Company + * Copyright (c) 2007-2008 The Hewlett-Packard Development Company * All rights reserved. * * Redistribution and use of this software in source and binary forms, @@ -62,12 +62,14 @@ #include #include "params/LinuxX86System.hh" +#include "arch/x86/bios/e820.hh" #include "arch/x86/system.hh" class LinuxX86System : public X86System { protected: std::string commandLine; + X86ISA::E820Table * e820Table; public: typedef LinuxX86SystemParams Params; -- cgit v1.2.3 From 23c04b8c666b062cf97ad127805bf56e0797303b Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 00:59:58 -0400 Subject: Params: Remove an unnecessary include. --- src/python/m5/params.py | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/python/m5/params.py b/src/python/m5/params.py index 241d4ceaf..a895549ca 100644 --- a/src/python/m5/params.py +++ b/src/python/m5/params.py @@ -406,7 +406,6 @@ class MemorySize32(CheckedInt): class Addr(CheckedInt): cxx_type = 'Addr' - cxx_predecls = ['#include "arch/isa_traits.hh"'] size = 64 unsigned = True def __init__(self, value): -- cgit v1.2.3 From c625cf0ae1ea00ed87d336ea5569fdbd7f9de4a2 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 01:00:05 -0400 Subject: X86: Make the code compile as 32 bit. --- src/dev/x86/south_bridge/cmos.hh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/dev/x86/south_bridge/cmos.hh b/src/dev/x86/south_bridge/cmos.hh index 6fd7613bc..d1aa74b72 100644 --- a/src/dev/x86/south_bridge/cmos.hh +++ b/src/dev/x86/south_bridge/cmos.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2005 The Regents of The University of Michigan + * Copyright (c) 2008 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -69,14 +69,14 @@ class Cmos : public SubDevice public: - Cmos() : rtc("rtc", foo_time, true, 5000000000) + Cmos() : rtc("rtc", foo_time, true, ULL(5000000000)) { memset(regs, 0, numRegs * sizeof(uint8_t)); address = 0; } Cmos(Tick _latency) : SubDevice(_latency), - rtc("rtc", foo_time, true, 5000000000) + rtc("rtc", foo_time, true, ULL(5000000000)) { memset(regs, 0, numRegs * sizeof(uint8_t)); address = 0; @@ -84,7 +84,7 @@ class Cmos : public SubDevice Cmos(Addr start, Addr size, Tick _latency) : SubDevice(start, size, _latency), - rtc("rtc", foo_time, true, 5000000000) + rtc("rtc", foo_time, true, ULL(5000000000)) { memset(regs, 0, numRegs * sizeof(uint8_t)); address = 0; -- cgit v1.2.3 From 5b5875341cb7d86ad7ce497666f0af526158775f Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 01:00:19 -0400 Subject: X86: Make the cpuid processor identifier return a real string. --- .../insts/general_purpose/processor_information.py | 29 ++++++++++------------ 1 file changed, 13 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/processor_information.py b/src/arch/x86/isa/insts/general_purpose/processor_information.py index 6070169ac..4b73789af 100644 --- a/src/arch/x86/isa/insts/general_purpose/processor_information.py +++ b/src/arch/x86/isa/insts/general_purpose/processor_information.py @@ -1,4 +1,4 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -149,33 +149,30 @@ extendedStart: fault "NoFault" # 0x80000002 -- Processor Name String Identifier - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 + limm rax, 0x656B6146, dataSize=4 + limm rbx, 0x20354D20, dataSize=4 + limm rcx, 0x5F363878, dataSize=4 + limm rdx, 0x43203436, dataSize=4 bri t0, label("end") fault "NoFault" fault "NoFault" fault "NoFault" # 0x80000003 -- Processor Name String Identifier - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 + limm rax, 0x00005550, dataSize=4 + limm rbx, 0x00000000, dataSize=4 + limm rdx, 0x00000000, dataSize=4 + limm rcx, 0x00000000, dataSize=4 bri t0, label("end") fault "NoFault" fault "NoFault" fault "NoFault" # 0x80000004 -- Processor Name String Identifier - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 + limm rax, 0x00000000, dataSize=4 + limm rbx, 0x00000000, dataSize=4 + limm rdx, 0x00000000, dataSize=4 + limm rcx, 0x00000000, dataSize=4 bri t0, label("end") fault "NoFault" fault "NoFault" -- cgit v1.2.3 From 7be8e671f1fac98fb26155d4804ba005e6b75b0f Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 01:00:29 -0400 Subject: Params: Allow nested namespaces in cxx_namespace --- src/python/m5/SimObject.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index 78df6bef1..d1aec44b3 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -217,7 +217,10 @@ class MetaSimObject(type): # just declaring a pointer. decl = 'class %s;' % _cxx_class if namespace: - decl = 'namespace %s { %s }' % (namespace, decl) + namespaces = namespace.split('::') + namespaces.reverse() + for namespace in namespaces: + decl = 'namespace %s { %s }' % (namespace, decl) cls._value_dict['cxx_predecls'] = [decl] if 'swig_predecls' not in cls._value_dict: -- cgit v1.2.3 From 2b4874449ce45504a1759c593a1f9b00983fca01 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Jun 2008 01:54:21 -0400 Subject: Alpha: Get rid of an old include of a non-existant file. --- src/dev/alpha/tsunami_io.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/dev/alpha/tsunami_io.cc b/src/dev/alpha/tsunami_io.cc index 3496aed14..fa4e697cf 100644 --- a/src/dev/alpha/tsunami_io.cc +++ b/src/dev/alpha/tsunami_io.cc @@ -42,7 +42,6 @@ #include "base/time.hh" #include "base/trace.hh" -#include "dev/pitreg.h" #include "dev/rtcreg.h" #include "dev/alpha/tsunami_cchip.hh" #include "dev/alpha/tsunami.hh" -- cgit v1.2.3 From 907b28cc626e8b156d98187b0f91f5e8df0e9d56 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Fri, 13 Jun 2008 01:09:04 -0400 Subject: HG: Add compiled hg revision and date to the standard M5 output. --- src/SConscript | 14 +++++++++++++- src/python/generate.py | 35 +++++++++++++++++++++++++++++++++-- src/python/m5/main.py | 4 ++++ src/python/swig/core.i | 4 ++++ 4 files changed, 54 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/SConscript b/src/SConscript index 69c5b946d..e360611a0 100644 --- a/src/SConscript +++ b/src/SConscript @@ -332,6 +332,10 @@ env.Command('base/traceflags.hh', flags, generate.traceFlagsHH) env.Command('base/traceflags.cc', flags, generate.traceFlagsCC) Source('base/traceflags.cc') +# Generate program_info.cc +env.Command('base/program_info.cc', + Value(str(SCons.Node.FS.default_fs.SConstruct_dir)), generate.programInfo) + # Build the zip file py_compiled = [] py_zip_depends = [] @@ -364,11 +368,19 @@ envList = [] # date.cc. def make_objs(sources, env): objs = [env.Object(s) for s in sources] + # make date.cc depend on all other objects so it always gets # recompiled whenever anything else does date_obj = env.Object('base/date.cc') + + # Make the generation of program_info.cc dependend on all + # the other cc files and the compiling of program_info.cc + # dependent on all the objects but program_info.o + pinfo_obj = env.Object('base/program_info.cc') + env.Depends('base/program_info.cc', sources) env.Depends(date_obj, objs) - objs.append(date_obj) + env.Depends(pinfo_obj, objs) + objs.extend([date_obj,pinfo_obj]) return objs # Function to create a new build environment as clone of current diff --git a/src/python/generate.py b/src/python/generate.py index eead6ff5d..f4d923870 100644 --- a/src/python/generate.py +++ b/src/python/generate.py @@ -31,8 +31,7 @@ import py_compile import sys import zipfile -from os.path import basename -from os.path import exists +from os.path import basename, exists, isdir, join class DictImporter(object): '''This importer takes a dictionary of arbitrary module names that @@ -527,3 +526,35 @@ extern const Flags *compoundFlags[]; ''' f.close() + + def programInfo(self, target, source, env): + def gen_file(target, rev, node, date): + pi_stats = file(target, 'w') + print >>pi_stats, 'const char *hgRev = "%s:%s";' % (rev, node) + print >>pi_stats, 'const char *hgDate = "%s";' % date + pi_stats.close() + + target = str(target[0]) + scons_dir = eval(str(source[0])) + try: + import mercurial.demandimport, mercurial.hg, mercurial.ui + import mercurial.util, mercurial.node + if not exists(scons_dir) or not isdir(scons_dir) or \ + not exists(join(scons_dir, ".hg")): + raise ValueError + repo = mercurial.hg.repository(mercurial.ui.ui(), scons_dir) + rev = mercurial.node.nullrev + repo.changelog.count() + changenode = repo.changelog.node(rev) + changes = repo.changelog.read(changenode) + date = mercurial.util.datestr(changes[2]) + + gen_file(target, rev, mercurial.node.hex(changenode), date) + + mercurial.demandimport.disable() + except ImportError: + gen_file(target, "Unknown", "Unknown", "Unknown") + + except: + print "in except" + gen_file(target, "Unknown", "Unknown", "Unknown") + mercurial.demandimport.disable() diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 4bcca46d2..cbdd65492 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -268,6 +268,10 @@ def main(): print "M5 compiled %s" % internal.core.cvar.compileDate; print "M5 started %s" % datetime.datetime.now().ctime() print "M5 executing on %s" % socket.gethostname() + + print "M5 revision %s" % internal.core.cvar.hgRev + print "M5 commit date %s" % internal.core.cvar.hgDate + print "command line:", for argv in sys.argv: print argv, diff --git a/src/python/swig/core.i b/src/python/swig/core.i index 770765ca4..567eff591 100644 --- a/src/python/swig/core.i +++ b/src/python/swig/core.i @@ -39,6 +39,8 @@ #include "sim/startup.hh" extern const char *compileDate; +extern const char *hgRev; +extern const char *hgDate; %} %include "stdint.i" @@ -51,6 +53,8 @@ void SimStartup(); void doExitCleanup(); char *compileDate; +char *hgRev; +char *hgDate; void setClockFrequency(Tick ticksPerSecond); -- cgit v1.2.3 From 024ec4c5c310b1225a52532d41d5cc9f2633ae6c Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Fri, 13 Jun 2008 01:29:20 -0400 Subject: Get rid of bogus cache assertion. I was asserting that the only reason you would defer targets is if a write came in while you had an outstanding read miss, but there's another case where you could get a read access after you've snooped an invalidation and buffered it because it applies to a prior outstanding miss. --- src/mem/cache/cache_impl.hh | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 7bab3012b..3b56c0a2e 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -823,7 +823,6 @@ Cache::handleResponse(PacketPtr pkt) } if (mshr->promoteDeferredTargets()) { - assert(mshr->needsExclusive() && !blk->isWritable()); // avoid later read getting stale data while write miss is // outstanding.. see comment in timingAccess() blk->status &= ~BlkReadable; -- cgit v1.2.3 From caccbd1edcacc82a952429950fcd4314b86b5b89 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Fri, 13 Jun 2008 01:33:49 -0400 Subject: Get rid of bogus bus assertion. It runs out that if a MemObject turns around and does a send in its receive callback, and there are other sends already scheduled, then it could observe a state where it's not at the head of the list but the bus's sendEvent is not scheduled (because we're still in the middle of processing the prior sendEvent). --- src/mem/tport.cc | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src') diff --git a/src/mem/tport.cc b/src/mem/tport.cc index ad5e95909..15c7fdf9f 100644 --- a/src/mem/tport.cc +++ b/src/mem/tport.cc @@ -103,11 +103,6 @@ SimpleTimingPort::schedSendTiming(PacketPtr pkt, Tick when) return; } - // list is non-empty and this is not the head, so event should - // already be scheduled - assert(waitingOnRetry || - (sendEvent->scheduled() && sendEvent->when() <= when)); - // list is non-empty & this belongs at the end if (when >= transmitList.back().tick) { transmitList.push_back(DeferredPacket(when, pkt)); -- cgit v1.2.3 From fe4fd9f4146684a649131d09bbf85ecb96ef4ba7 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 13 Jun 2008 17:34:22 -0700 Subject: scons: fix program_info.cc generation --- src/SConscript | 3 ++- src/python/generate.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/SConscript b/src/SConscript index e360611a0..b9c83af9e 100644 --- a/src/SConscript +++ b/src/SConscript @@ -334,7 +334,8 @@ Source('base/traceflags.cc') # Generate program_info.cc env.Command('base/program_info.cc', - Value(str(SCons.Node.FS.default_fs.SConstruct_dir)), generate.programInfo) + Value(str(SCons.Node.FS.default_fs.SConstruct_dir)), + generate.programInfo) # Build the zip file py_compiled = [] diff --git a/src/python/generate.py b/src/python/generate.py index f4d923870..c32204bc9 100644 --- a/src/python/generate.py +++ b/src/python/generate.py @@ -535,7 +535,7 @@ extern const Flags *compoundFlags[]; pi_stats.close() target = str(target[0]) - scons_dir = eval(str(source[0])) + scons_dir = str(source[0]) try: import mercurial.demandimport, mercurial.hg, mercurial.ui import mercurial.util, mercurial.node -- cgit v1.2.3 From 2d037682ff800fa44e715250b07d708bbf4bde91 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 14 Jun 2008 10:30:18 -0700 Subject: scons: proper fix for hg version stuff --- src/python/generate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/python/generate.py b/src/python/generate.py index c32204bc9..e6c36ecd2 100644 --- a/src/python/generate.py +++ b/src/python/generate.py @@ -535,7 +535,7 @@ extern const Flags *compoundFlags[]; pi_stats.close() target = str(target[0]) - scons_dir = str(source[0]) + scons_dir = str(source[0].get_contents()) try: import mercurial.demandimport, mercurial.hg, mercurial.ui import mercurial.util, mercurial.node -- cgit v1.2.3 From 7a58b5a38a15b5e025435820a2679c34eb2c47a4 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 14 Jun 2008 12:10:50 -0700 Subject: Add missing dependencies on .i files --- src/SConscript | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/SConscript b/src/SConscript index b9c83af9e..7a6a762fe 100644 --- a/src/SConscript +++ b/src/SConscript @@ -266,6 +266,7 @@ for name,simobj in generate.sim_objects.iteritems(): env.Depends(hh_file, depends + extra_deps) # Generate any parameter header files needed +params_i_files = [] for name,param in generate.params.iteritems(): if isinstance(param, m5.params.VectorParamDesc): ext = 'vptype' @@ -273,6 +274,7 @@ for name,param in generate.params.iteritems(): ext = 'ptype' i_file = File('params/%s_%s.i' % (name, ext)) + params_i_files.append(i_file) env.Command(i_file, Value(name), generate.createSwigParam) env.Depends(i_file, depends) @@ -295,7 +297,7 @@ params_file = File('params/params.i') names = sort_list(generate.sim_objects.keys()) env.Command(params_file, [ Value(v) for v in names ], generate.buildParams) -env.Depends(params_file, params_hh_files + depends) +env.Depends(params_file, params_hh_files + params_i_files + depends) SwigSource('m5.objects', params_file) # Build all swig modules -- cgit v1.2.3 From ce43e46576ccf09d56aeb7021d3decd75d08d90c Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 14 Jun 2008 12:57:21 -0700 Subject: Fix various SWIG warnings --- src/arch/mips/MipsTLB.py | 4 +--- src/arch/x86/X86TLB.py | 2 -- src/python/swig/event.i | 4 ++-- src/python/swig/range.i | 2 ++ 4 files changed, 5 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/arch/mips/MipsTLB.py b/src/arch/mips/MipsTLB.py index ce8847365..1d0244e22 100644 --- a/src/arch/mips/MipsTLB.py +++ b/src/arch/mips/MipsTLB.py @@ -33,10 +33,8 @@ from m5.SimObject import SimObject from m5.params import * class MipsTLB(SimObject): - abstract = True type = 'MipsTLB' - cxx_namespace = 'MipsISA' - cxx_class = 'TLB' + abstract = True size = Param.Int("TLB size") class MipsDTB(MipsTLB): diff --git a/src/arch/x86/X86TLB.py b/src/arch/x86/X86TLB.py index dc080f37e..8dd53620e 100644 --- a/src/arch/x86/X86TLB.py +++ b/src/arch/x86/X86TLB.py @@ -69,8 +69,6 @@ if build_env['FULL_SYSTEM']: class X86TLB(SimObject): type = 'X86TLB' - cxx_namespace = 'X86ISA' - cxx_class = 'TLB' abstract = True size = Param.Int("TLB size") if build_env['FULL_SYSTEM']: diff --git a/src/python/swig/event.i b/src/python/swig/event.i index 9a2093c99..ee1f3d00b 100644 --- a/src/python/swig/event.i +++ b/src/python/swig/event.i @@ -44,8 +44,8 @@ void create(PyObject *object, Tick when); -class Event; -class CountedDrainEvent : public Event { +class CountedDrainEvent +{ public: void setCount(int _count); }; diff --git a/src/python/swig/range.i b/src/python/swig/range.i index 40809dae4..309e6a8ba 100644 --- a/src/python/swig/range.i +++ b/src/python/swig/range.i @@ -28,6 +28,8 @@ * Authors: Nathan Binkert */ +%rename(assign) *::operator=; + %include "base/range.hh" %include "sim/host.hh" -- cgit v1.2.3 From fe325c7f4341b25cae65cbe529caa0a46140501a Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 14 Jun 2008 19:39:01 -0700 Subject: MemReq: Add option to reset the time on a request. --- src/mem/request.hh | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/mem/request.hh b/src/mem/request.hh index cc9c6b8bf..85ff8a445 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -220,6 +220,7 @@ class Request : public FastAlloc int getSize() { assert(validPaddr || validAsidVaddr); return size; } /** Accessor for time. */ Tick getTime() { assert(validPaddr || validAsidVaddr); return time; } + void resetTime() { assert(validPaddr || validAsidVaddr); time = curTick; } /** Accessor for flags. */ uint32_t getFlags() { assert(validPaddr || validAsidVaddr); return flags; } -- cgit v1.2.3 From f82d4e2364e9df683b6891c04efaa861093a50ec Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 14 Jun 2008 20:19:49 -0700 Subject: python: Move various utility classes into a new m5.util package so they're all in the same place. This also involves having just one jobfile.py and moving it into the utils directory to avoid duplication. Lots of improvements to the utility as well. --HG-- rename : src/python/m5/attrdict.py => src/python/m5/util/attrdict.py rename : util/pbs/jobfile.py => src/python/m5/util/jobfile.py rename : src/python/m5/util.py => src/python/m5/util/misc.py rename : src/python/m5/multidict.py => src/python/m5/util/multidict.py rename : util/stats/orderdict.py => src/python/m5/util/orderdict.py --- src/python/SConscript | 8 +- src/python/m5/SimObject.py | 1 - src/python/m5/attrdict.py | 61 ------ src/python/m5/main.py | 2 +- src/python/m5/multidict.py | 182 ---------------- src/python/m5/util.py | 59 ------ src/python/m5/util/__init__.py | 32 +++ src/python/m5/util/attrdict.py | 70 +++++++ src/python/m5/util/jobfile.py | 450 ++++++++++++++++++++++++++++++++++++++++ src/python/m5/util/misc.py | 87 ++++++++ src/python/m5/util/multidict.py | 182 ++++++++++++++++ src/python/m5/util/orderdict.py | 80 +++++++ 12 files changed, 907 insertions(+), 307 deletions(-) delete mode 100644 src/python/m5/attrdict.py delete mode 100644 src/python/m5/multidict.py delete mode 100644 src/python/m5/util.py create mode 100644 src/python/m5/util/__init__.py create mode 100644 src/python/m5/util/attrdict.py create mode 100644 src/python/m5/util/jobfile.py create mode 100644 src/python/m5/util/misc.py create mode 100644 src/python/m5/util/multidict.py create mode 100644 src/python/m5/util/orderdict.py (limited to 'src') diff --git a/src/python/SConscript b/src/python/SConscript index b39c9ea9c..0785b4307 100644 --- a/src/python/SConscript +++ b/src/python/SConscript @@ -36,18 +36,20 @@ Source('swig/pyobject.cc') PySource('m5', 'm5/__init__.py') PySource('m5', 'm5/SimObject.py') -PySource('m5', 'm5/attrdict.py') PySource('m5', 'm5/convert.py') PySource('m5', 'm5/event.py') PySource('m5', 'm5/main.py') -PySource('m5', 'm5/multidict.py') PySource('m5', 'm5/params.py') PySource('m5', 'm5/proxy.py') PySource('m5', 'm5/simulate.py') PySource('m5', 'm5/smartdict.py') PySource('m5', 'm5/stats.py') PySource('m5', 'm5/ticks.py') -PySource('m5', 'm5/util.py') +PySource('m5.util', 'm5/util/__init__.py') +PySource('m5.util', 'm5/util/attrdict.py') +PySource('m5.util', 'm5/util/jobfile.py') +PySource('m5.util', 'm5/util/misc.py') +PySource('m5.util', 'm5/util/multidict.py') SwigSource('m5.internal', 'swig/core.i') SwigSource('m5.internal', 'swig/debug.i') diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index d1aec44b3..41ed3df9e 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -32,7 +32,6 @@ import sys, types import proxy import m5 from util import * -from multidict import multidict # These utility functions have to come first because they're # referenced in params.py... otherwise they won't be defined when we diff --git a/src/python/m5/attrdict.py b/src/python/m5/attrdict.py deleted file mode 100644 index 4ee7f1b8c..000000000 --- a/src/python/m5/attrdict.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright (c) 2006 The Regents of The University of Michigan -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer; -# redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution; -# neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Authors: Nathan Binkert - -__all__ = [ 'attrdict' ] - -class attrdict(dict): - def __getattr__(self, attr): - if attr in self: - return self.__getitem__(attr) - return super(attrdict, self).__getattribute__(attr) - - def __setattr__(self, attr, value): - if attr in dir(self): - return super(attrdict, self).__setattr__(attr, value) - return self.__setitem__(attr, value) - - def __delattr__(self, attr): - if attr in self: - return self.__delitem__(attr) - return super(attrdict, self).__delattr__(attr, value) - -if __name__ == '__main__': - x = attrdict() - x.y = 1 - x['z'] = 2 - print x['y'], x.y - print x['z'], x.z - print dir(x) - print x - - print - - del x['y'] - del x.z - print dir(x) - print(x) diff --git a/src/python/m5/main.py b/src/python/m5/main.py index cbdd65492..5c3324224 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -33,7 +33,7 @@ import os import socket import sys -from attrdict import attrdict +from util import attrdict import defines import traceflags diff --git a/src/python/m5/multidict.py b/src/python/m5/multidict.py deleted file mode 100644 index b5cd700ef..000000000 --- a/src/python/m5/multidict.py +++ /dev/null @@ -1,182 +0,0 @@ -# Copyright (c) 2005 The Regents of The University of Michigan -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer; -# redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution; -# neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Authors: Nathan Binkert - -__all__ = [ 'multidict' ] - -class multidict(object): - def __init__(self, parent = {}, **kwargs): - self.local = dict(**kwargs) - self.parent = parent - self.deleted = {} - - def __str__(self): - return str(dict(self.items())) - - def __repr__(self): - return `dict(self.items())` - - def __contains__(self, key): - return self.local.has_key(key) or self.parent.has_key(key) - - def __delitem__(self, key): - try: - del self.local[key] - except KeyError, e: - if key in self.parent: - self.deleted[key] = True - else: - raise KeyError, e - - def __setitem__(self, key, value): - self.deleted.pop(key, False) - self.local[key] = value - - def __getitem__(self, key): - try: - return self.local[key] - except KeyError, e: - if not self.deleted.get(key, False) and key in self.parent: - return self.parent[key] - else: - raise KeyError, e - - def __len__(self): - return len(self.local) + len(self.parent) - - def next(self): - for key,value in self.local.items(): - yield key,value - - if self.parent: - for key,value in self.parent.next(): - if key not in self.local and key not in self.deleted: - yield key,value - - def has_key(self, key): - return key in self - - def iteritems(self): - for item in self.next(): - yield item - - def items(self): - return [ item for item in self.next() ] - - def iterkeys(self): - for key,value in self.next(): - yield key - - def keys(self): - return [ key for key,value in self.next() ] - - def itervalues(self): - for key,value in self.next(): - yield value - - def values(self): - return [ value for key,value in self.next() ] - - def get(self, key, default=None): - try: - return self[key] - except KeyError, e: - return default - - def setdefault(self, key, default): - try: - return self[key] - except KeyError: - self.deleted.pop(key, False) - self.local[key] = default - return default - - def _dump(self): - print 'multidict dump' - node = self - while isinstance(node, multidict): - print ' ', node.local - node = node.parent - - def _dumpkey(self, key): - values = [] - node = self - while isinstance(node, multidict): - if key in node.local: - values.append(node.local[key]) - node = node.parent - print key, values - -if __name__ == '__main__': - test1 = multidict() - test2 = multidict(test1) - test3 = multidict(test2) - test4 = multidict(test3) - - test1['a'] = 'test1_a' - test1['b'] = 'test1_b' - test1['c'] = 'test1_c' - test1['d'] = 'test1_d' - test1['e'] = 'test1_e' - - test2['a'] = 'test2_a' - del test2['b'] - test2['c'] = 'test2_c' - del test1['a'] - - test2.setdefault('f', multidict) - - print 'test1>', test1.items() - print 'test2>', test2.items() - #print test1['a'] - print test1['b'] - print test1['c'] - print test1['d'] - print test1['e'] - - print test2['a'] - #print test2['b'] - print test2['c'] - print test2['d'] - print test2['e'] - - for key in test2.iterkeys(): - print key - - test2.get('g', 'foo') - #test2.get('b') - test2.get('b', 'bar') - test2.setdefault('b', 'blah') - print test1 - print test2 - print `test2` - - print len(test2) - - test3['a'] = [ 0, 1, 2, 3 ] - - print test4 diff --git a/src/python/m5/util.py b/src/python/m5/util.py deleted file mode 100644 index 28b8b1b94..000000000 --- a/src/python/m5/util.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (c) 2004-2006 The Regents of The University of Michigan -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer; -# redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution; -# neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Authors: Steve Reinhardt -# Nathan Binkert - -############################# -# -# Utility classes & methods -# -############################# - -class Singleton(type): - def __call__(cls, *args, **kwargs): - if hasattr(cls, '_instance'): - return cls._instance - - cls._instance = super(Singleton, cls).__call__(*args, **kwargs) - return cls._instance - -# Apply method to object. -# applyMethod(obj, 'meth', ) is equivalent to obj.meth() -def applyMethod(obj, meth, *args, **kwargs): - return getattr(obj, meth)(*args, **kwargs) - -# If the first argument is an (non-sequence) object, apply the named -# method with the given arguments. If the first argument is a -# sequence, apply the method to each element of the sequence (a la -# 'map'). -def applyOrMap(objOrSeq, meth, *args, **kwargs): - if not isinstance(objOrSeq, (list, tuple)): - return applyMethod(objOrSeq, meth, *args, **kwargs) - else: - return [applyMethod(o, meth, *args, **kwargs) for o in objOrSeq] - - diff --git a/src/python/m5/util/__init__.py b/src/python/m5/util/__init__.py new file mode 100644 index 000000000..f82de696a --- /dev/null +++ b/src/python/m5/util/__init__.py @@ -0,0 +1,32 @@ +# Copyright (c) 2008 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +from attrdict import attrdict, optiondict +from misc import * +from multidict import multidict +import jobfile diff --git a/src/python/m5/util/attrdict.py b/src/python/m5/util/attrdict.py new file mode 100644 index 000000000..44479c456 --- /dev/null +++ b/src/python/m5/util/attrdict.py @@ -0,0 +1,70 @@ +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +__all__ = [ 'attrdict', 'optiondict' ] + +class attrdict(dict): + def __getattr__(self, attr): + if attr in self: + return self.__getitem__(attr) + return super(attrdict, self).__getattribute__(attr) + + def __setattr__(self, attr, value): + if attr in dir(self): + return super(attrdict, self).__setattr__(attr, value) + return self.__setitem__(attr, value) + + def __delattr__(self, attr): + if attr in self: + return self.__delitem__(attr) + return super(attrdict, self).__delattr__(attr, value) + +class optiondict(attrdict): + def __getattr__(self, attr): + try: + return super(optiondict, self).__getattr__(attr) + except AttributeError: + #d = optionsdict() + #setattr(self, attr, d) + return None + +if __name__ == '__main__': + x = attrdict() + x.y = 1 + x['z'] = 2 + print x['y'], x.y + print x['z'], x.z + print dir(x) + print x + + print + + del x['y'] + del x.z + print dir(x) + print(x) diff --git a/src/python/m5/util/jobfile.py b/src/python/m5/util/jobfile.py new file mode 100644 index 000000000..5e015c4ad --- /dev/null +++ b/src/python/m5/util/jobfile.py @@ -0,0 +1,450 @@ +# Copyright (c) 2005-2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +import sys + +from attrdict import attrdict, optiondict +from misc import crossproduct, flatten + +class Data(object): + def __init__(self, name, desc, **kwargs): + self.name = name + self.desc = desc + self.__dict__.update(kwargs) + + def update(self, obj): + if not isinstance(obj, Data): + raise AttributeError, "can only update from Data object" + + for k,v in obj.__dict__.iteritems(): + if not k.startswith('_'): + self.__dict__[k] = v + if hasattr(self, 'system') and hasattr(obj, 'system'): + if self.system != obj.system: + raise AttributeError, \ + "conflicting values for system: '%s'/'%s'" % \ + (self.system, obj.system) + + def printinfo(self): + if self.name: + print 'name: %s' % self.name + if self.desc: + print 'desc: %s' % self.desc + try: + if self.system: + print 'system: %s' % self.system + except AttributeError: + pass + + def printverbose(self): + for key in self: + val = self[key] + if isinstance(val, dict): + import pprint + val = pprint.pformat(val) + print '%-20s = %s' % (key, val) + print + + def __contains__(self, attr): + if attr.startswith('_'): + return False + return attr in self.__dict__ + + def __getitem__(self, key): + if key.startswith('_'): + raise KeyError, "Key '%s' not found" % attr + return self.__dict__[key] + + def __iter__(self): + keys = self.__dict__.keys() + keys.sort() + for key in keys: + if not key.startswith('_'): + yield key + + def optiondict(self): + result = optiondict() + for key in self: + result[key] = self[key] + return result + + def __str__(self): + return self.name + +class Job(Data): + def __init__(self, options): + super(Job, self).__init__('', '') + + config = options[0]._config + for opt in options: + if opt._config != config: + raise AttributeError, \ + "All options are not from the same Configuration" + + self._config = config + self._groups = [ opt._group for opt in options ] + self._options = options + + self.update(self._config) + for group in self._groups: + self.update(group) + + self._is_checkpoint = True + + for option in self._options: + self.update(option) + if not option._group._checkpoint: + self._is_checkpoint = False + + if option._suboption: + self.update(option._suboption) + self._is_checkpoint = False + + names = [ ] + for opt in self._options: + if opt.name: + names.append(opt.name) + self.name = ':'.join(names) + + descs = [ ] + for opt in self._options: + if opt.desc: + descs.append(opt.desc) + self.desc = ', '.join(descs) + + self._checkpoint = None + if not self._is_checkpoint: + opts = [] + for opt in options: + cpt = opt._group._checkpoint + if not cpt: + continue + if isinstance(cpt, Option): + opt = cpt.clone(suboptions=False) + else: + opt = opt.clone(suboptions=False) + + opts.append(opt) + + if opts: + self._checkpoint = Job(opts) + + def clone(self): + return Job(self._options) + + def printinfo(self): + super(Job, self).printinfo() + if self._checkpoint: + print 'checkpoint: %s' % self._checkpoint.name + print 'config: %s' % self._config.name + print 'groups: %s' % [ g.name for g in self._groups ] + print 'options: %s' % [ o.name for o in self._options ] + super(Job, self).printverbose() + +class SubOption(Data): + def __init__(self, name, desc, **kwargs): + super(SubOption, self).__init__(name, desc, **kwargs) + self._number = None + +class Option(Data): + def __init__(self, name, desc, **kwargs): + super(Option, self).__init__(name, desc, **kwargs) + self._suboptions = [] + self._suboption = None + self._number = None + + def __getattribute__(self, attr): + if attr == 'name': + name = self.__dict__[attr] + if self._suboption is not None: + name = '%s:%s' % (name, self._suboption.name) + return name + + if attr == 'desc': + desc = [ self.__dict__[attr] ] + if self._suboption is not None and self._suboption.desc: + desc.append(self._suboption.desc) + return ', '.join(desc) + + return super(Option, self).__getattribute__(attr) + + def suboption(self, name, desc, **kwargs): + subo = SubOption(name, desc, **kwargs) + subo._config = self._config + subo._group = self._group + subo._option = self + subo._number = len(self._suboptions) + self._suboptions.append(subo) + return subo + + def clone(self, suboptions=True): + option = Option(self.__dict__['name'], self.__dict__['desc']) + option.update(self) + option._group = self._group + option._config = self._config + option._number = self._number + if suboptions: + option._suboptions.extend(self._suboptions) + option._suboption = self._suboption + return option + + def subopts(self): + if not self._suboptions: + return [ self ] + + subopts = [] + for subo in self._suboptions: + option = self.clone() + option._suboption = subo + subopts.append(option) + + return subopts + + def printinfo(self): + super(Option, self).printinfo() + print 'config: %s' % self._config.name + super(Option, self).printverbose() + +class Group(Data): + def __init__(self, name, desc, **kwargs): + super(Group, self).__init__(name, desc, **kwargs) + self._options = [] + self._number = None + self._checkpoint = False + + def option(self, name, desc, **kwargs): + opt = Option(name, desc, **kwargs) + opt._config = self._config + opt._group = self + opt._number = len(self._options) + self._options.append(opt) + return opt + + def options(self): + return self._options + + def subopts(self): + subopts = [] + for opt in self._options: + for subo in opt.subopts(): + subopts.append(subo) + return subopts + + def printinfo(self): + super(Group, self).printinfo() + print 'config: %s' % self._config.name + print 'options: %s' % [ o.name for o in self._options ] + super(Group, self).printverbose() + +class Configuration(Data): + def __init__(self, name, desc, **kwargs): + super(Configuration, self).__init__(name, desc, **kwargs) + self._groups = [] + self._posfilters = [] + self._negfilters = [] + + def group(self, name, desc, **kwargs): + grp = Group(name, desc, **kwargs) + grp._config = self + grp._number = len(self._groups) + self._groups.append(grp) + return grp + + def groups(self): + return self._groups + + def checkchildren(self, kids): + for kid in kids: + if kid._config != self: + raise AttributeError, "child from the wrong configuration" + + def sortgroups(self, groups): + groups = [ (grp._number, grp) for grp in groups ] + groups.sort() + return [ grp[1] for grp in groups ] + + def options(self, groups=None, checkpoint=False): + if groups is None: + groups = self._groups + self.checkchildren(groups) + groups = self.sortgroups(groups) + if checkpoint: + groups = [ grp for grp in groups if grp._checkpoint ] + optgroups = [ g.options() for g in groups ] + else: + optgroups = [ g.subopts() for g in groups ] + if not optgroups: + return + for options in crossproduct(optgroups): + for opt in options: + cpt = opt._group._checkpoint + if not isinstance(cpt, bool) and cpt != opt: + if checkpoint: + break + else: + yield options + else: + if checkpoint: + yield options + + def addfilter(self, filt, pos=True): + import re + filt = re.compile(filt) + if pos: + self._posfilters.append(filt) + else: + self._negfilters.append(filt) + + def jobfilter(self, job): + for filt in self._negfilters: + if filt.match(job.name): + return False + + if not self._posfilters: + return True + + for filt in self._posfilters: + if filt.match(job.name): + return True + + return False + + def checkpoints(self, groups=None): + for options in self.options(groups, True): + job = Job(options) + if self.jobfilter(job): + yield job + + def jobs(self, groups=None): + for options in self.options(groups, False): + job = Job(options) + if self.jobfilter(job): + yield job + + def alljobs(self, groups=None): + for options in self.options(groups, True): + yield Job(options) + for options in self.options(groups, False): + yield Job(options) + + def find(self, jobname): + for job in self.alljobs(): + if job.name == jobname: + return job + else: + raise AttributeError, "job '%s' not found" % jobname + + def job(self, options): + self.checkchildren(options) + options = [ (opt._group._number, opt) for opt in options ] + options.sort() + options = [ opt[1] for opt in options ] + job = Job(options) + return job + + def printinfo(self): + super(Configuration, self).printinfo() + print 'groups: %s' % [ g.name for g in self._groups ] + super(Configuration, self).printverbose() + +def JobFile(jobfile): + from os.path import expanduser, isfile, join as joinpath + filename = expanduser(jobfile) + + # Can't find filename in the current path, search sys.path + if not isfile(filename): + for path in sys.path: + testname = joinpath(path, filename) + if isfile(testname): + filename = testname + break + else: + raise AttributeError, \ + "Could not find file '%s'" % jobfile + + data = {} + execfile(filename, data) + if 'conf' not in data: + raise ImportError, 'cannot import name conf from %s' % jobfile + conf = data['conf'] + import jobfile + if not isinstance(conf, Configuration): + raise AttributeError, \ + 'conf in jobfile: %s (%s) is not type %s' % \ + (jobfile, type(conf), Configuration) + return conf + +def main(conf=None): + import sys + + usage = 'Usage: %s [-b] [-c] [-v] ' % sys.argv[0] + + try: + import getopt + opts, args = getopt.getopt(sys.argv[1:], '-bcv') + except getopt.GetoptError: + sys.exit(usage) + + both = False + checkpoint = False + verbose = False + for opt,arg in opts: + if opt == '-b': + both = True + checkpoint = True + if opt == '-c': + checkpoint = True + if opt == '-v': + verbose = True + + if conf is None: + if len(args) != 1: + raise AttributeError, usage + conf = JobFile(args[0]) + else: + if len(args) != 0: + raise AttributeError, usage + + if both: + jobs = conf.alljobs() + elif checkpoint: + jobs = conf.checkpoints() + else: + jobs = conf.jobs() + + for job in jobs: + if verbose: + job.printinfo() + else: + cpt = '' + if job._checkpoint: + cpt = job._checkpoint.name + print job.name, cpt + +if __name__ == '__main__': + main() diff --git a/src/python/m5/util/misc.py b/src/python/m5/util/misc.py new file mode 100644 index 000000000..094e3ed9a --- /dev/null +++ b/src/python/m5/util/misc.py @@ -0,0 +1,87 @@ +# Copyright (c) 2004-2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Steve Reinhardt +# Nathan Binkert + +############################# +# +# Utility classes & methods +# +############################# + +class Singleton(type): + def __call__(cls, *args, **kwargs): + if hasattr(cls, '_instance'): + return cls._instance + + cls._instance = super(Singleton, cls).__call__(*args, **kwargs) + return cls._instance + +# Apply method to object. +# applyMethod(obj, 'meth', ) is equivalent to obj.meth() +def applyMethod(obj, meth, *args, **kwargs): + return getattr(obj, meth)(*args, **kwargs) + +# If the first argument is an (non-sequence) object, apply the named +# method with the given arguments. If the first argument is a +# sequence, apply the method to each element of the sequence (a la +# 'map'). +def applyOrMap(objOrSeq, meth, *args, **kwargs): + if not isinstance(objOrSeq, (list, tuple)): + return applyMethod(objOrSeq, meth, *args, **kwargs) + else: + return [applyMethod(o, meth, *args, **kwargs) for o in objOrSeq] + +def crossproduct(items): + if not isinstance(items, (list, tuple)): + raise AttributeError, 'crossproduct works only on sequences' + + if not items: + yield None + return + + current = items[0] + remainder = items[1:] + + if not hasattr(current, '__iter__'): + current = [ current ] + + for item in current: + for rem in crossproduct(remainder): + data = [ item ] + if rem: + data += rem + yield data + +def flatten(items): + if not isinstance(items, (list, tuple)): + yield items + return + + for item in items: + for flat in flatten(item): + yield flat diff --git a/src/python/m5/util/multidict.py b/src/python/m5/util/multidict.py new file mode 100644 index 000000000..b5cd700ef --- /dev/null +++ b/src/python/m5/util/multidict.py @@ -0,0 +1,182 @@ +# Copyright (c) 2005 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +__all__ = [ 'multidict' ] + +class multidict(object): + def __init__(self, parent = {}, **kwargs): + self.local = dict(**kwargs) + self.parent = parent + self.deleted = {} + + def __str__(self): + return str(dict(self.items())) + + def __repr__(self): + return `dict(self.items())` + + def __contains__(self, key): + return self.local.has_key(key) or self.parent.has_key(key) + + def __delitem__(self, key): + try: + del self.local[key] + except KeyError, e: + if key in self.parent: + self.deleted[key] = True + else: + raise KeyError, e + + def __setitem__(self, key, value): + self.deleted.pop(key, False) + self.local[key] = value + + def __getitem__(self, key): + try: + return self.local[key] + except KeyError, e: + if not self.deleted.get(key, False) and key in self.parent: + return self.parent[key] + else: + raise KeyError, e + + def __len__(self): + return len(self.local) + len(self.parent) + + def next(self): + for key,value in self.local.items(): + yield key,value + + if self.parent: + for key,value in self.parent.next(): + if key not in self.local and key not in self.deleted: + yield key,value + + def has_key(self, key): + return key in self + + def iteritems(self): + for item in self.next(): + yield item + + def items(self): + return [ item for item in self.next() ] + + def iterkeys(self): + for key,value in self.next(): + yield key + + def keys(self): + return [ key for key,value in self.next() ] + + def itervalues(self): + for key,value in self.next(): + yield value + + def values(self): + return [ value for key,value in self.next() ] + + def get(self, key, default=None): + try: + return self[key] + except KeyError, e: + return default + + def setdefault(self, key, default): + try: + return self[key] + except KeyError: + self.deleted.pop(key, False) + self.local[key] = default + return default + + def _dump(self): + print 'multidict dump' + node = self + while isinstance(node, multidict): + print ' ', node.local + node = node.parent + + def _dumpkey(self, key): + values = [] + node = self + while isinstance(node, multidict): + if key in node.local: + values.append(node.local[key]) + node = node.parent + print key, values + +if __name__ == '__main__': + test1 = multidict() + test2 = multidict(test1) + test3 = multidict(test2) + test4 = multidict(test3) + + test1['a'] = 'test1_a' + test1['b'] = 'test1_b' + test1['c'] = 'test1_c' + test1['d'] = 'test1_d' + test1['e'] = 'test1_e' + + test2['a'] = 'test2_a' + del test2['b'] + test2['c'] = 'test2_c' + del test1['a'] + + test2.setdefault('f', multidict) + + print 'test1>', test1.items() + print 'test2>', test2.items() + #print test1['a'] + print test1['b'] + print test1['c'] + print test1['d'] + print test1['e'] + + print test2['a'] + #print test2['b'] + print test2['c'] + print test2['d'] + print test2['e'] + + for key in test2.iterkeys(): + print key + + test2.get('g', 'foo') + #test2.get('b') + test2.get('b', 'bar') + test2.setdefault('b', 'blah') + print test1 + print test2 + print `test2` + + print len(test2) + + test3['a'] = [ 0, 1, 2, 3 ] + + print test4 diff --git a/src/python/m5/util/orderdict.py b/src/python/m5/util/orderdict.py new file mode 100644 index 000000000..3f755d299 --- /dev/null +++ b/src/python/m5/util/orderdict.py @@ -0,0 +1,80 @@ +# Copyright (c) 2005 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +__all__ = [ 'orderdict' ] + +class orderdict(dict): + def __init__(self, d = {}): + self._keys = d.keys() + super(orderdict, self).__init__(d) + + def __setitem__(self, key, item): + super(orderdict, self).__setitem__(key, item) + if not hasattr(self, '_keys'): + self._keys = [key,] + if key not in self._keys: + self._keys.append(key) + + def __delitem__(self, key): + super(orderdict, self).__delitem__(key) + self._keys.remove(key) + + def clear(self): + super(orderdict, self).clear() + self._keys = [] + + def items(self): + for i in self._keys: + yield i, self[i] + + def keys(self): + return self._keys + + def popitem(self): + if len(self._keys) == 0: + raise KeyError('dictionary is empty') + else: + key = self._keys[-1] + val = self[key] + del self[key] + return key, val + + def setdefault(self, key, failobj = None): + super(orderdict, self).setdefault(key, failobj) + if key not in self._keys: + self._keys.append(key) + + def update(self, d): + for key in d.keys(): + if not self.has_key(key): + self._keys.append(key) + super(orderdict, self).update(d) + + def values(self): + for i in self._keys: + yield self[i] -- cgit v1.2.3 From 3d2e7797ccb554092a4140fc8e11407edd7eedc4 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 14 Jun 2008 20:39:31 -0700 Subject: params: Fix floating point parameters --- src/python/m5/params.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/python/m5/params.py b/src/python/m5/params.py index a895549ca..c8d0d8f46 100644 --- a/src/python/m5/params.py +++ b/src/python/m5/params.py @@ -379,6 +379,13 @@ class Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100 class Float(ParamValue, float): cxx_type = 'double' + def __init__(self, value): + if isinstance(value, (int, long, float, NumericParamValue, Float)): + self.value = float(value) + else: + raise TypeError, "Can't convert object of type %s to Float" \ + % type(value).__name__ + def getValue(self): return float(self.value) @@ -895,7 +902,9 @@ class MemoryBandwidth(float,ParamValue): def getValue(self): # convert to seconds per byte - value = 1.0 / float(self) + value = float(self) + if value: + value = 1.0 / float(self) # convert to ticks per byte value = ticks.fromSeconds(value) return float(value) -- cgit v1.2.3 From 4afdc40d70db76d895cc9bfe6bf3786d379589b7 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 14 Jun 2008 20:42:45 -0700 Subject: params: Fix the memory bandwidth parameter --- src/python/m5/params.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/python/m5/params.py b/src/python/m5/params.py index c8d0d8f46..938278541 100644 --- a/src/python/m5/params.py +++ b/src/python/m5/params.py @@ -892,7 +892,7 @@ class NetworkBandwidth(float,ParamValue): class MemoryBandwidth(float,ParamValue): cxx_type = 'float' - def __new__(self, value): + def __new__(cls, value): # we want the number of ticks per byte of data val = convert.toMemoryBandwidth(value) return super(cls, MemoryBandwidth).__new__(cls, val) -- cgit v1.2.3 From 779c31077c965e28575fca3c065d651fcc87c134 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 14 Jun 2008 21:15:58 -0700 Subject: python: Separate the options parsing stuff. Remove options parsing stuff from main.py so things are a bit more obvious. --- src/python/SConscript | 1 + src/python/m5/main.py | 114 +++++++------------------------------ src/python/m5/options.py | 145 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+), 94 deletions(-) create mode 100644 src/python/m5/options.py (limited to 'src') diff --git a/src/python/SConscript b/src/python/SConscript index 0785b4307..cca9217b0 100644 --- a/src/python/SConscript +++ b/src/python/SConscript @@ -39,6 +39,7 @@ PySource('m5', 'm5/SimObject.py') PySource('m5', 'm5/convert.py') PySource('m5', 'm5/event.py') PySource('m5', 'm5/main.py') +PySource('m5', 'm5/options.py') PySource('m5', 'm5/params.py') PySource('m5', 'm5/proxy.py') PySource('m5', 'm5/simulate.py') diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 5c3324224..8011c64b8 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -28,25 +28,17 @@ import code import datetime -import optparse import os import socket import sys from util import attrdict import defines +from options import OptionParser import traceflags __all__ = [ 'options', 'arguments', 'main' ] -usage="%prog [m5 options] script.py [script options]" -version="%prog 2.0" -brief_copyright=''' -Copyright (c) 2001-2008 -The Regents of The University of Michigan -All Rights Reserved -''' - def print_list(items, indent=4): line = ' ' * indent for i,item in enumerate(items): @@ -60,64 +52,19 @@ def print_list(items, indent=4): line += item print line -# there's only one option parsing done, so make it global and add some -# helper functions to make it work well. -parser = optparse.OptionParser(usage=usage, version=version, - description=brief_copyright, - formatter=optparse.TitledHelpFormatter()) -parser.disable_interspersed_args() - -# current option group -group = None - -def set_group(*args, **kwargs): - '''set the current option group''' - global group - if not args and not kwargs: - group = None - else: - group = parser.add_option_group(*args, **kwargs) - -class splitter(object): - def __init__(self, split): - self.split = split - def __call__(self, option, opt_str, value, parser): - getattr(parser.values, option.dest).extend(value.split(self.split)) - -def add_option(*args, **kwargs): - '''add an option to the current option group, or global none set''' - - # if action=split, but allows the option arguments - # themselves to be lists separated by the split variable''' - - if kwargs.get('action', None) == 'append' and 'split' in kwargs: - split = kwargs.pop('split') - kwargs['default'] = [] - kwargs['type'] = 'string' - kwargs['action'] = 'callback' - kwargs['callback'] = splitter(split) - - if group: - return group.add_option(*args, **kwargs) - - return parser.add_option(*args, **kwargs) - -def bool_option(name, default, help): - '''add a boolean option called --name and --no-name. - Display help depending on which is the default''' - - tname = '--%s' % name - fname = '--no-%s' % name - dest = name.replace('-', '_') - if default: - thelp = optparse.SUPPRESS_HELP - fhelp = help - else: - thelp = help - fhelp = optparse.SUPPRESS_HELP +usage="%prog [m5 options] script.py [script options]" +version="%prog 2.0" +brief_copyright=''' +Copyright (c) 2001-2008 +The Regents of The University of Michigan +All Rights Reserved +''' - add_option(tname, action="store_true", default=default, help=thelp) - add_option(fname, action="store_false", dest=dest, help=fhelp) +options = OptionParser(usage=usage, version=version, + description=brief_copyright) +add_option = options.add_option +set_group = options.set_group +usage = options.usage # Help options add_option('-A', "--authors", action="store_true", default=False, @@ -168,39 +115,13 @@ add_option("--trace-file", metavar="FILE", default="cout", add_option("--trace-ignore", metavar="EXPR", action='append', split=':', help="Ignore EXPR sim objects") -options = attrdict() -arguments = [] - -def usage(exitcode=None): - parser.print_help() - if exitcode is not None: - sys.exit(exitcode) - -def parse_args(): - _opts,args = parser.parse_args() - opts = attrdict(_opts.__dict__) - - # setting verbose and quiet at the same time doesn't make sense - if opts.verbose > 0 and opts.quiet > 0: - usage(2) - - # store the verbosity in a single variable. 0 is default, - # negative numbers represent quiet and positive values indicate verbose - opts.verbose -= opts.quiet - - del opts.quiet - - options.update(opts) - arguments.extend(args) - return opts,args - def main(): import defines import event import info import internal - parse_args() + arguments = options.parse_args() done = False @@ -261,6 +182,11 @@ def main(): if done: sys.exit(0) + # setting verbose and quiet at the same time doesn't make sense + if options.verbose > 0 and options.quiet > 0: + options.usage(2) + + verbose = options.verbose - options.quiet if options.verbose >= 0: print "M5 Simulator System" print brief_copyright @@ -282,7 +208,7 @@ def main(): if arguments and not os.path.isfile(arguments[0]): print "Script %s not found" % arguments[0] - usage(2) + options.usage(2) # tell C++ about output directory internal.core.setOutputDir(options.outdir) diff --git a/src/python/m5/options.py b/src/python/m5/options.py new file mode 100644 index 000000000..50eea429c --- /dev/null +++ b/src/python/m5/options.py @@ -0,0 +1,145 @@ +# Copyright (c) 2005 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +import optparse +import sys +import util + +from optparse import * + +class nodefault(object): pass + +class splitter(object): + def __init__(self, split): + self.split = split + def __call__(self, option, opt_str, value, parser): + values = value.split(self.split) + dest = getattr(parser.values, option.dest) + if dest is None: + setattr(parser.values, option.dest, values) + else: + dest.extend(values) + +class OptionParser(object): + def __init__(self, *args, **kwargs): + kwargs.setdefault('formatter', optparse.TitledHelpFormatter()) + self._optparse = optparse.OptionParser(*args, **kwargs) + self._optparse.disable_interspersed_args() + + self._allopts = {} + self._defaults = {} + self._options = util.attrdict() + + # current option group + self._group = self._optparse + + def set_group(self, *args, **kwargs): + '''set the current option group''' + if not args and not kwargs: + self._group = self._optparse + else: + self._group = self._optparse.add_option_group(*args, **kwargs) + + def add_option(self, *args, **kwargs): + '''add an option to the current option group, or global none set''' + + # if action=split, but allows the option arguments + # themselves to be lists separated by the split variable''' + + if kwargs.get('action', None) == 'append' and 'split' in kwargs: + split = kwargs.pop('split') + kwargs['default'] = [] + kwargs['type'] = 'string' + kwargs['action'] = 'callback' + kwargs['callback'] = splitter(split) + + default = kwargs.pop('default', nodefault) + option = self._group.add_option(*args, **kwargs) + dest = option.dest + if dest not in self._allopts: + self._allopts[dest] = option + + if default != nodefault: + if dest not in self._options: + self._options[dest] = default + + return option + + def bool_option(self, name, default, help): + '''add a boolean option called --name and --no-name. + Display help depending on which is the default''' + + tname = '--%s' % name + fname = '--no-%s' % name + dest = name.replace('-', '_') + if default: + thelp = optparse.SUPPRESS_HELP + fhelp = help + else: + thelp = help + fhelp = optparse.SUPPRESS_HELP + + topt = self.add_option(tname, action="store_true", default=default, + help=thelp) + fopt = self.add_option(fname, action="store_false", dest=dest, + help=fhelp) + + return topt,fopt + + def __getattr__(self, attr): + if attr.startswith('_'): + return super(OptionParser, self).__getattr__(attr) + + if attr in self._options: + return self._options[attr] + + raise AttributeError, "Option %s not found" % attr + + def __setattr__(self, attr, value): + if attr.startswith('_'): + return super(OptionParser, self).__setattr__(attr, value) + + if attr in self._options: + self._options[attr] = value + + return super(OptionParser, self).__setattr__(attr, value) + + def parse_args(self): + opts,args = self._optparse.parse_args() + + for key,val in opts.__dict__.iteritems(): + if val is not None or key not in self._options: + self._options[key] = val + + return args + + def usage(self, exitcode=None): + self._optparse.print_help() + if exitcode is not None: + sys.exit(exitcode) + -- cgit v1.2.3 From fc48d1dcf55d7195bf79cddb93dfd341a5fada7e Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 14 Jun 2008 21:15:59 -0700 Subject: Add .m5 configuration directory --- src/python/SConscript | 1 + src/python/m5/config.py | 42 ++++++++++++++++++++++++++++++++++++++++++ src/python/m5/main.py | 1 + 3 files changed, 44 insertions(+) create mode 100644 src/python/m5/config.py (limited to 'src') diff --git a/src/python/SConscript b/src/python/SConscript index cca9217b0..32bab4526 100644 --- a/src/python/SConscript +++ b/src/python/SConscript @@ -36,6 +36,7 @@ Source('swig/pyobject.cc') PySource('m5', 'm5/__init__.py') PySource('m5', 'm5/SimObject.py') +PySource('m5', 'm5/config.py') PySource('m5', 'm5/convert.py') PySource('m5', 'm5/event.py') PySource('m5', 'm5/main.py') diff --git a/src/python/m5/config.py b/src/python/m5/config.py new file mode 100644 index 000000000..7fb531a18 --- /dev/null +++ b/src/python/m5/config.py @@ -0,0 +1,42 @@ +# Copyright (c) 2008 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +import os +from os.path import isdir, isfile, join as joinpath + +homedir = os.environ['HOME'] +confdir = os.environ.get('M5_CONFIG', joinpath(homedir, '.m5')) +def get(name): + if not isdir(confdir): + return None + conffile = joinpath(confdir, name) + if not isfile(conffile): + return None + + return conffile + diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 8011c64b8..c4f26c472 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -33,6 +33,7 @@ import socket import sys from util import attrdict +import config import defines from options import OptionParser import traceflags -- cgit v1.2.3 From bbeb8082a56b765181b769c5e1f41e173c0444fa Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 14 Jun 2008 21:16:00 -0700 Subject: main: add .m5/options.py processing. This file is processed before arguments are parsed so that they can change the default options for various config parameters. --- src/python/m5/main.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/python/m5/main.py b/src/python/m5/main.py index c4f26c472..4f28cf385 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -122,6 +122,13 @@ def main(): import info import internal + # load the options.py config file to allow people to set their own + # default options + options_file = config.get('options.py') + if options_file: + scope = { 'options' : options } + execfile(options_file, scope) + arguments = options.parse_args() done = False -- cgit v1.2.3 From b2036bfda88aa99304e48f26541e5d84ada34db9 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 14 Jun 2008 21:51:08 -0700 Subject: Command line option to print out List of SimObjects and their parameters --- src/python/m5/main.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'src') diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 4f28cf385..dbabd9600 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -116,6 +116,11 @@ add_option("--trace-file", metavar="FILE", default="cout", add_option("--trace-ignore", metavar="EXPR", action='append', split=':', help="Ignore EXPR sim objects") +# Help options +set_group("Help Options") +add_option("--list-sim-objects", action='store_true', default=False, + help="List all built-in SimObjects, their parameters and default values") + def main(): import defines import event @@ -187,6 +192,27 @@ def main(): print_list(traceflags.compoundFlagMap[flag], indent=8) print + if options.list_sim_objects: + import SimObject + done = True + print "SimObjects:" + objects = SimObject.allClasses.keys() + objects.sort() + for name in objects: + obj = SimObject.allClasses[name] + print " %s" % obj + params = obj._params.keys() + params.sort() + for pname in params: + param = obj._params[pname] + default = getattr(param, 'default', '') + print " %s" % pname + if default: + print " default: %s" % default + print " desc: %s" % param.desc + print + print + if done: sys.exit(0) -- cgit v1.2.3 From 6dedc645f7f54df021e0aa9a5b48015f984a2e39 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sun, 15 Jun 2008 20:56:35 -0700 Subject: add compile flags to m5 --- src/python/swig/core.i | 7 +++++++ src/sim/SConscript | 1 + src/sim/compile_info.cc | 56 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 src/sim/compile_info.cc (limited to 'src') diff --git a/src/python/swig/core.i b/src/python/swig/core.i index 567eff591..53d992ac6 100644 --- a/src/python/swig/core.i +++ b/src/python/swig/core.i @@ -39,12 +39,14 @@ #include "sim/startup.hh" extern const char *compileDate; +std::vector compileFlags(); extern const char *hgRev; extern const char *hgDate; %} %include "stdint.i" %include "std_string.i" +%include "std_vector.i" %include "sim/host.hh" void setOutputDir(const std::string &dir); @@ -52,7 +54,12 @@ void setOutputFile(const std::string &file); void SimStartup(); void doExitCleanup(); +%immutable compileDate; char *compileDate; + +namespace std { %template(StringVector) vector; } +std::vector compileFlags(); + char *hgRev; char *hgDate; diff --git a/src/sim/SConscript b/src/sim/SConscript index 0b39ab8e8..c9e4415f5 100644 --- a/src/sim/SConscript +++ b/src/sim/SConscript @@ -35,6 +35,7 @@ SimObject('System.py') SimObject('InstTracer.py') Source('async.cc') +Source('compile_info.cc') Source('core.cc') Source('debug.cc') Source('eventq.cc') diff --git a/src/sim/compile_info.cc b/src/sim/compile_info.cc new file mode 100644 index 000000000..482972f9f --- /dev/null +++ b/src/sim/compile_info.cc @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2008 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Steve Reinhardt + */ + +#include +#include + +std::vector +compileFlags() +{ + static const char *flags[] = { +#ifdef DEBUG + "DEBUG", +#endif +#ifdef NDEBUG + "NDEBUG", +#endif +#if TRACING_ON + "TRACING_ON", +#endif + }; + + std::vector result; + for (int i = 0; i < sizeof(flags) / sizeof(flags[0]); ++i) + result.push_back(flags[i]); + + return result; +} + -- cgit v1.2.3 From b429b1759defba2f8da1f894f6a3500e3f2c78d2 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sun, 15 Jun 2008 21:26:33 -0700 Subject: params: Prevent people from setting attributes on vector params. --- src/python/m5/params.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/python/m5/params.py b/src/python/m5/params.py index 938278541..9394b11e2 100644 --- a/src/python/m5/params.py +++ b/src/python/m5/params.py @@ -166,6 +166,10 @@ class ParamDesc(object): class VectorParamValue(list): __metaclass__ = MetaParamValue + def __setattr__(self, attr, value): + raise AttributeError, \ + "Not allowed to set %s on '%s'" % (attr, type(self).__name__) + def ini_str(self): return ' '.join([v.ini_str() for v in self]) -- cgit v1.2.3 From e3c267a3dbe628516777dd74662c786ef4eedceb Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sun, 15 Jun 2008 21:34:32 -0700 Subject: port: Clean up default port setup and port switchover code. --- src/cpu/base.cc | 17 ++++++----------- src/mem/bridge.cc | 2 +- src/mem/port.cc | 26 +++++++++++++++++--------- src/mem/port.hh | 9 +++++---- 4 files changed, 29 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 23195f720..6ce082996 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -351,22 +351,17 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc) // Connect new CPU to old CPU's memory only if new CPU isn't // connected to anything. Also connect old CPU's memory to new // CPU. - Port *peer; - if (ic->getPeer() == NULL || ic->getPeer()->isDefaultPort()) { - peer = oldCPU->getPort("icache_port")->getPeer(); + if (!ic->isConnected()) { + Port *peer = oldCPU->getPort("icache_port")->getPeer(); ic->setPeer(peer); - } else { - peer = ic->getPeer(); + peer->setPeer(ic); } - peer->setPeer(ic); - if (dc->getPeer() == NULL || dc->getPeer()->isDefaultPort()) { - peer = oldCPU->getPort("dcache_port")->getPeer(); + if (!dc->isConnected()) { + Port *peer = oldCPU->getPort("dcache_port")->getPeer(); dc->setPeer(peer); - } else { - peer = dc->getPeer(); + peer->setPeer(dc); } - peer->setPeer(dc); } diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc index 3d3966491..c09cacc00 100644 --- a/src/mem/bridge.cc +++ b/src/mem/bridge.cc @@ -89,7 +89,7 @@ void Bridge::init() { // Make sure that both sides are connected to. - if (portA.getPeer() == NULL || portB.getPeer() == NULL) + if (!portA.isConnected() || !portB.isConnected()) fatal("Both ports of bus bridge are not connected to a bus.\n"); if (portA.peerBlockSize() != portB.peerBlockSize()) diff --git a/src/mem/port.cc b/src/mem/port.cc index ce3f6c74b..0e03194c9 100644 --- a/src/mem/port.cc +++ b/src/mem/port.cc @@ -39,17 +39,18 @@ #include "mem/mem_object.hh" #include "mem/port.hh" -class defaultPeerPortClass: public Port +class DefaultPeerPort : public Port { protected: void blowUp() { - fatal("Unconnected port!"); + fatal("%s: Unconnected port!", peer->name()); } public: - defaultPeerPortClass() : Port("default_port") - {} + DefaultPeerPort() + : Port("default_port") + { } bool recvTiming(PacketPtr) { @@ -84,16 +85,22 @@ class defaultPeerPortClass: public Port blowUp(); } - bool isDefaultPort() { return true; } + bool isDefaultPort() const { return true; } +}; -} defaultPeerPort; +DefaultPeerPort defaultPeerPort; -Port::Port() : peer(&defaultPeerPort), owner(NULL) +Port::Port() + : peer(&defaultPeerPort), owner(NULL) { } -Port::Port(const std::string &_name, MemObject *_owner) : - portName(_name), peer(&defaultPeerPort), owner(_owner) +Port::Port(const std::string &_name, MemObject *_owner) + : portName(_name), peer(&defaultPeerPort), owner(_owner) +{ +} + +Port::~Port() { } @@ -101,6 +108,7 @@ void Port::setPeer(Port *port) { DPRINTF(Config, "setting peer to %s\n", port->name()); + peer = port; } diff --git a/src/mem/port.hh b/src/mem/port.hh index f66b566ea..15fda2164 100644 --- a/src/mem/port.hh +++ b/src/mem/port.hh @@ -73,8 +73,7 @@ class MemObject; */ class Port { - private: - + protected: /** Descriptive name (for DPRINTF output) */ mutable std::string portName; @@ -103,7 +102,7 @@ class Port /** Return port name (for DPRINTF). */ const std::string &name() const { return portName; } - virtual ~Port() {}; + virtual ~Port(); // mey be better to use subclasses & RTTI? /** Holds the ports status. Currently just that a range recomputation needs @@ -131,7 +130,9 @@ class Port * demise. */ void removeConn(); - virtual bool isDefaultPort() { return false; } + virtual bool isDefaultPort() const { return false; } + + bool isConnected() { return peer && !peer->isDefaultPort(); } protected: -- cgit v1.2.3 From fa8f91fdc0609fb9cb8bcde22b440b40e52f1cc8 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sun, 15 Jun 2008 21:39:29 -0700 Subject: physmem: Add a null option to physical memory so it doesn't store data. --- src/mem/PhysicalMemory.py | 1 + src/mem/physical.cc | 35 ++++++++++++++++++++++------------- 2 files changed, 23 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/mem/PhysicalMemory.py b/src/mem/PhysicalMemory.py index 4e8a830de..e512cea1c 100644 --- a/src/mem/PhysicalMemory.py +++ b/src/mem/PhysicalMemory.py @@ -38,6 +38,7 @@ class PhysicalMemory(MemObject): latency = Param.Latency('1t', "latency of an access") latency_var = Param.Latency('0ns', "access variablity") zero = Param.Bool(False, "zero initialize memory") + null = Param.Bool(False, "do not store data, always return zero") class DRAMMemory(PhysicalMemory): type = 'DRAMMemory' diff --git a/src/mem/physical.cc b/src/mem/physical.cc index c06dd3170..325606eb1 100644 --- a/src/mem/physical.cc +++ b/src/mem/physical.cc @@ -52,12 +52,16 @@ using namespace std; using namespace TheISA; PhysicalMemory::PhysicalMemory(const Params *p) - : MemObject(p), pmemAddr(NULL), lat(p->latency), - lat_var(p->latency_var) + : MemObject(p), pmemAddr(NULL), pagePtr(0), + lat(p->latency), lat_var(p->latency_var), + cachedSize(params()->range.size()), cachedStart(params()->range.start) { if (params()->range.size() % TheISA::PageBytes != 0) panic("Memory Size not divisible by page size\n"); + if (params()->null) + return; + int map_flags = MAP_ANON | MAP_PRIVATE; pmemAddr = (uint8_t *)mmap(NULL, params()->range.size(), PROT_READ | PROT_WRITE, map_flags, -1, 0); @@ -70,12 +74,6 @@ PhysicalMemory::PhysicalMemory(const Params *p) //If requested, initialize all the memory to 0 if (p->zero) memset(pmemAddr, 0, p->range.size()); - - pagePtr = 0; - - cachedSize = params()->range.size(); - cachedStart = params()->range.start; - } void @@ -257,6 +255,8 @@ PhysicalMemory::doAtomicAccess(PacketPtr pkt) uint64_t condition_val64; uint32_t condition_val32; + if (!pmemAddr) + panic("Swap only works if there is real memory (i.e. null=False)"); assert(sizeof(IntReg) >= pkt->getSize()); overwrite_mem = true; @@ -287,11 +287,13 @@ PhysicalMemory::doAtomicAccess(PacketPtr pkt) if (pkt->isLocked()) { trackLoadLocked(pkt); } - memcpy(pkt->getPtr(), hostAddr, pkt->getSize()); + if (pmemAddr) + memcpy(pkt->getPtr(), hostAddr, pkt->getSize()); TRACE_PACKET("Read"); } else if (pkt->isWrite()) { if (writeOK(pkt)) { - memcpy(hostAddr, pkt->getPtr(), pkt->getSize()); + if (pmemAddr) + memcpy(hostAddr, pkt->getPtr(), pkt->getSize()); TRACE_PACKET("Write"); } } else if (pkt->isInvalidate()) { @@ -320,11 +322,13 @@ PhysicalMemory::doFunctionalAccess(PacketPtr pkt) uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start(); if (pkt->isRead()) { - memcpy(pkt->getPtr(), hostAddr, pkt->getSize()); + if (pmemAddr) + memcpy(pkt->getPtr(), hostAddr, pkt->getSize()); TRACE_PACKET("Read"); pkt->makeAtomicResponse(); } else if (pkt->isWrite()) { - memcpy(hostAddr, pkt->getPtr(), pkt->getSize()); + if (pmemAddr) + memcpy(hostAddr, pkt->getPtr(), pkt->getSize()); TRACE_PACKET("Write"); pkt->makeAtomicResponse(); } else if (pkt->isPrint()) { @@ -448,6 +452,9 @@ PhysicalMemory::drain(Event *de) void PhysicalMemory::serialize(ostream &os) { + if (!pmemAddr) + return; + gzFile compressedMem; string filename = name() + ".physmem"; @@ -480,6 +487,9 @@ PhysicalMemory::serialize(ostream &os) void PhysicalMemory::unserialize(Checkpoint *cp, const string §ion) { + if (!pmemAddr) + return; + gzFile compressedMem; long *tempPage; long *pmem_current; @@ -487,7 +497,6 @@ PhysicalMemory::unserialize(Checkpoint *cp, const string §ion) uint32_t bytesRead; const int chunkSize = 16384; - string filename; UNSERIALIZE_SCALAR(filename); -- cgit v1.2.3 From 00df9016fead5f7427576acf6d3faee29779f0a1 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Tue, 17 Jun 2008 20:29:06 -0700 Subject: Rename SimConsole to Terminal since it makes more sense --HG-- rename : src/dev/SimConsole.py => src/dev/Terminal.py rename : src/dev/simconsole.cc => src/dev/terminal.cc rename : src/dev/simconsole.hh => src/dev/terminal.hh --- src/dev/SConscript | 8 +- src/dev/SimConsole.py | 39 ----- src/dev/Terminal.py | 39 +++++ src/dev/Uart.py | 2 +- src/dev/alpha/AlphaConsole.py | 2 +- src/dev/alpha/Tsunami.py | 5 +- src/dev/alpha/console.cc | 8 +- src/dev/alpha/console.hh | 4 +- src/dev/alpha/tsunami.cc | 2 +- src/dev/mips/MipsConsole.py | 2 +- src/dev/mips/console.cc | 8 +- src/dev/mips/console.hh | 6 +- src/dev/mips/malta.cc | 2 +- src/dev/platform.hh | 2 +- src/dev/simconsole.cc | 337 ------------------------------------------ src/dev/simconsole.hh | 146 ------------------ src/dev/sparc/T1000.py | 12 +- src/dev/sparc/t1000.cc | 2 +- src/dev/terminal.cc | 337 ++++++++++++++++++++++++++++++++++++++++++ src/dev/terminal.hh | 146 ++++++++++++++++++ src/dev/uart.cc | 8 +- src/dev/uart.hh | 4 +- src/dev/uart8250.cc | 16 +- src/dev/uart8250.hh | 2 +- src/dev/x86/PC.py | 15 +- src/dev/x86/pc.cc | 2 +- 26 files changed, 579 insertions(+), 577 deletions(-) delete mode 100644 src/dev/SimConsole.py create mode 100644 src/dev/Terminal.py delete mode 100644 src/dev/simconsole.cc delete mode 100644 src/dev/simconsole.hh create mode 100644 src/dev/terminal.cc create mode 100644 src/dev/terminal.hh (limited to 'src') diff --git a/src/dev/SConscript b/src/dev/SConscript index bd6b16c43..82fa5cb02 100644 --- a/src/dev/SConscript +++ b/src/dev/SConscript @@ -39,8 +39,8 @@ if env['FULL_SYSTEM']: SimObject('Ide.py') SimObject('Pci.py') SimObject('Platform.py') - SimObject('SimConsole.py') SimObject('SimpleDisk.py') + SimObject('Terminal.py') SimObject('Uart.py') Source('baddev.cc') @@ -63,14 +63,12 @@ if env['FULL_SYSTEM']: Source('pcidev.cc') Source('pktfifo.cc') Source('platform.cc') - Source('simconsole.cc') Source('simple_disk.cc') Source('sinic.cc') + Source('terminal.cc') Source('uart.cc') Source('uart8250.cc') - TraceFlag('Console') - TraceFlag('ConsoleVerbose') TraceFlag('DiskImageRead') TraceFlag('DiskImageWrite') TraceFlag('DMA') @@ -92,6 +90,8 @@ if env['FULL_SYSTEM']: TraceFlag('PciConfigAll') TraceFlag('SimpleDisk') TraceFlag('SimpleDiskData') + TraceFlag('Terminal') + TraceFlag('TerminalVerbose') TraceFlag('Uart') CompoundFlag('DiskImageAll', [ 'DiskImageRead', 'DiskImageWrite' ]) diff --git a/src/dev/SimConsole.py b/src/dev/SimConsole.py deleted file mode 100644 index bb8420527..000000000 --- a/src/dev/SimConsole.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (c) 2005-2007 The Regents of The University of Michigan -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer; -# redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution; -# neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Authors: Nathan Binkert - -from m5.SimObject import SimObject -from m5.params import * -from m5.proxy import * - -class SimConsole(SimObject): - type = 'SimConsole' - append_name = Param.Bool(True, "append name() to filename") - intr_control = Param.IntrControl(Parent.any, "interrupt controller") - port = Param.TcpPort(3456, "listen port") - number = Param.Int(0, "console number") - output = Param.String('console', "file to dump output to") diff --git a/src/dev/Terminal.py b/src/dev/Terminal.py new file mode 100644 index 000000000..3d97070ba --- /dev/null +++ b/src/dev/Terminal.py @@ -0,0 +1,39 @@ +# Copyright (c) 2005-2007 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +from m5.SimObject import SimObject +from m5.params import * +from m5.proxy import * + +class Terminal(SimObject): + type = 'Terminal' + append_name = Param.Bool(True, "append name() to filename") + intr_control = Param.IntrControl(Parent.any, "interrupt controller") + port = Param.TcpPort(3456, "listen port") + number = Param.Int(0, "terminal number") + output = Param.String('console', "file to dump output to") diff --git a/src/dev/Uart.py b/src/dev/Uart.py index e32517a4c..c5db3c42f 100644 --- a/src/dev/Uart.py +++ b/src/dev/Uart.py @@ -34,7 +34,7 @@ from Device import BasicPioDevice class Uart(BasicPioDevice): type = 'Uart' abstract = True - sim_console = Param.SimConsole(Parent.any, "The console") + terminal = Param.Terminal(Parent.any, "The terminal") class Uart8250(Uart): type = 'Uart8250' diff --git a/src/dev/alpha/AlphaConsole.py b/src/dev/alpha/AlphaConsole.py index 43c7ef954..8983fcbed 100644 --- a/src/dev/alpha/AlphaConsole.py +++ b/src/dev/alpha/AlphaConsole.py @@ -34,5 +34,5 @@ class AlphaConsole(BasicPioDevice): type = 'AlphaConsole' cpu = Param.BaseCPU(Parent.cpu[0], "Processor") disk = Param.SimpleDisk("Simple Disk") - sim_console = Param.SimConsole(Parent.any, "The Simulator Console") + terminal = Param.Terminal(Parent.any, "The console terminal") system = Param.AlphaSystem(Parent.any, "system object") diff --git a/src/dev/alpha/Tsunami.py b/src/dev/alpha/Tsunami.py index 484976c09..5c5207a33 100644 --- a/src/dev/alpha/Tsunami.py +++ b/src/dev/alpha/Tsunami.py @@ -87,7 +87,8 @@ class Tsunami(Platform): fb = BadDevice(pio_addr=0x801fc0003d0, devicename='FrameBuffer') io = TsunamiIO(pio_addr=0x801fc000000) uart = Uart8250(pio_addr=0x801fc0003f8) - console = AlphaConsole(pio_addr=0x80200000000, disk=Parent.simple_disk) + alpha_console = AlphaConsole(pio_addr=0x80200000000, + disk=Parent.simple_disk) # Attach I/O devices to specified bus object. Can't do this # earlier, since the bus object itself is typically defined at the @@ -120,4 +121,4 @@ class Tsunami(Platform): self.fb.pio = bus.port self.io.pio = bus.port self.uart.pio = bus.port - self.console.pio = bus.port + self.alpha_console.pio = bus.port diff --git a/src/dev/alpha/console.cc b/src/dev/alpha/console.cc index 493a21f99..d7b2b5b02 100644 --- a/src/dev/alpha/console.cc +++ b/src/dev/alpha/console.cc @@ -46,8 +46,8 @@ #include "cpu/thread_context.hh" #include "dev/alpha/console.hh" #include "dev/platform.hh" -#include "dev/simconsole.hh" #include "dev/simple_disk.hh" +#include "dev/terminal.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" #include "mem/physical.hh" @@ -58,7 +58,7 @@ using namespace std; using namespace AlphaISA; AlphaConsole::AlphaConsole(const Params *p) - : BasicPioDevice(p), disk(p->disk), console(p->sim_console), + : BasicPioDevice(p), disk(p->disk), terminal(p->terminal), system(p->system), cpu(p->cpu) { @@ -139,7 +139,7 @@ AlphaConsole::read(PacketPtr pkt) switch (daddr) { case offsetof(AlphaAccess, inputChar): - pkt->set(console->console_in()); + pkt->set(terminal->console_in()); break; case offsetof(AlphaAccess, cpuClock): pkt->set(alphaAccess->cpuClock); @@ -228,7 +228,7 @@ AlphaConsole::write(PacketPtr pkt) break; case offsetof(AlphaAccess, outputChar): - console->out((char)(val & 0xff)); + terminal->out((char)(val & 0xff)); break; default: diff --git a/src/dev/alpha/console.hh b/src/dev/alpha/console.hh index e77a7fad6..b6145ef38 100644 --- a/src/dev/alpha/console.hh +++ b/src/dev/alpha/console.hh @@ -43,7 +43,7 @@ #include "sim/sim_object.hh" class BaseCPU; -class SimConsole; +class Terminal; class AlphaSystem; class SimpleDisk; @@ -90,7 +90,7 @@ class AlphaConsole : public BasicPioDevice SimpleDisk *disk; /** the system console (the terminal) is accessable from the console */ - SimConsole *console; + Terminal *terminal; /** a pointer to the system we are running in */ AlphaSystem *system; diff --git a/src/dev/alpha/tsunami.cc b/src/dev/alpha/tsunami.cc index 5bc0de5da..7923fc3f1 100644 --- a/src/dev/alpha/tsunami.cc +++ b/src/dev/alpha/tsunami.cc @@ -37,11 +37,11 @@ #include #include "cpu/intr_control.hh" -#include "dev/simconsole.hh" #include "dev/alpha/tsunami_cchip.hh" #include "dev/alpha/tsunami_pchip.hh" #include "dev/alpha/tsunami_io.hh" #include "dev/alpha/tsunami.hh" +#include "dev/terminal.hh" #include "sim/system.hh" using namespace std; diff --git a/src/dev/mips/MipsConsole.py b/src/dev/mips/MipsConsole.py index 36575677a..8b724991a 100644 --- a/src/dev/mips/MipsConsole.py +++ b/src/dev/mips/MipsConsole.py @@ -34,5 +34,5 @@ class MipsConsole(BasicPioDevice): type = 'MipsConsole' cpu = Param.BaseCPU(Parent.cpu[0], "Processor") disk = Param.SimpleDisk("Simple Disk") - sim_console = Param.SimConsole(Parent.any, "The Simulator Console") + terminal = Param.Terminal(Parent.any, "The console terminal") system = Param.MipsSystem(Parent.any, "system object") diff --git a/src/dev/mips/console.cc b/src/dev/mips/console.cc index 185e1acbc..d1663999a 100755 --- a/src/dev/mips/console.cc +++ b/src/dev/mips/console.cc @@ -45,8 +45,8 @@ #include "cpu/thread_context.hh" #include "dev/mips/console.hh" #include "dev/platform.hh" -#include "dev/simconsole.hh" #include "dev/simple_disk.hh" +#include "dev/terminal.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" #include "mem/physical.hh" @@ -58,7 +58,7 @@ using namespace std; using namespace MipsISA; MipsConsole::MipsConsole(const Params *p) - : BasicPioDevice(p), disk(p->disk), console(p->sim_console), + : BasicPioDevice(p), disk(p->disk), terminal(p->terminal), system(p->system), cpu(p->cpu) { @@ -125,7 +125,7 @@ MipsConsole::read(PacketPtr pkt) pkt->set(mipsAccess->intrClockFrequency); break; case offsetof(MipsAccess, inputChar): - pkt->set(console->console_in()); + pkt->set(terminal->console_in()); break; case offsetof(MipsAccess, cpuClock): pkt->set(mipsAccess->cpuClock); @@ -215,7 +215,7 @@ MipsConsole::write(PacketPtr pkt) break; case offsetof(MipsAccess, outputChar): - console->out((char)(val & 0xff)); + terminal->out((char)(val & 0xff)); break; default: diff --git a/src/dev/mips/console.hh b/src/dev/mips/console.hh index 34792090d..a78343f35 100755 --- a/src/dev/mips/console.hh +++ b/src/dev/mips/console.hh @@ -43,7 +43,7 @@ #include "sim/sim_object.hh" class BaseCPU; -class SimConsole; +class Terminal; class MipsSystem; class SimpleDisk; @@ -89,8 +89,8 @@ class MipsConsole : public BasicPioDevice /** the disk must be accessed from the console */ SimpleDisk *disk; - /** the system console (the terminal) is accessable from the console */ - SimConsole *console; + /** the system terminal is accessable from the console */ + Terminal *terminal; /** a pointer to the system we are running in */ MipsSystem *system; diff --git a/src/dev/mips/malta.cc b/src/dev/mips/malta.cc index 0b1fa15ba..21e79d999 100755 --- a/src/dev/mips/malta.cc +++ b/src/dev/mips/malta.cc @@ -38,11 +38,11 @@ #include #include "cpu/intr_control.hh" -#include "dev/simconsole.hh" #include "dev/mips/malta_cchip.hh" #include "dev/mips/malta_pchip.hh" #include "dev/mips/malta_io.hh" #include "dev/mips/malta.hh" +#include "dev/terminal.hh" #include "params/Malta.hh" #include "sim/system.hh" diff --git a/src/dev/platform.hh b/src/dev/platform.hh index 699b168ce..fc556787d 100644 --- a/src/dev/platform.hh +++ b/src/dev/platform.hh @@ -46,7 +46,7 @@ class PciConfigAll; class IntrControl; -class SimConsole; +class Terminal; class Uart; class System; diff --git a/src/dev/simconsole.cc b/src/dev/simconsole.cc deleted file mode 100644 index e8dc1b210..000000000 --- a/src/dev/simconsole.cc +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright (c) 2001-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Nathan Binkert - * Ali Saidi - */ - -/* @file - * Implements the user interface to a serial console - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "base/misc.hh" -#include "base/output.hh" -#include "base/socket.hh" -#include "base/trace.hh" -#include "dev/platform.hh" -#include "dev/simconsole.hh" -#include "dev/uart.hh" - -using namespace std; - - -/* - * Poll event for the listen socket - */ -SimConsole::ListenEvent::ListenEvent(SimConsole *c, int fd, int e) - : PollEvent(fd, e), cons(c) -{ -} - -void -SimConsole::ListenEvent::process(int revent) -{ - cons->accept(); -} - -/* - * Poll event for the data socket - */ -SimConsole::DataEvent::DataEvent(SimConsole *c, int fd, int e) - : PollEvent(fd, e), cons(c) -{ -} - -void -SimConsole::DataEvent::process(int revent) -{ - if (revent & POLLIN) - cons->data(); - else if (revent & POLLNVAL) - cons->detach(); -} - -/* - * SimConsole code - */ -SimConsole::SimConsole(const Params *p) - : SimObject(p), listenEvent(NULL), dataEvent(NULL), number(p->number), - data_fd(-1), txbuf(16384), rxbuf(16384), outfile(NULL) -#if TRACING_ON == 1 - , linebuf(16384) -#endif -{ - if (!p->output.empty()) { - if (p->append_name) - outfile = simout.find(p->output + "." + p->name); - else - outfile = simout.find(p->output); - - outfile->setf(ios::unitbuf); - } - - if (p->port) - listen(p->port); -} - -SimConsole::~SimConsole() -{ - if (data_fd != -1) - ::close(data_fd); - - if (listenEvent) - delete listenEvent; - - if (dataEvent) - delete dataEvent; -} - -/////////////////////////////////////////////////////////////////////// -// socket creation and console attach -// - -void -SimConsole::listen(int port) -{ - while (!listener.listen(port, true)) { - DPRINTF(Console, - ": can't bind address console port %d inuse PID %d\n", - port, getpid()); - port++; - } - - int p1, p2; - p2 = name().rfind('.') - 1; - p1 = name().rfind('.', p2); - ccprintf(cerr, "Listening for %s connection on port %d\n", - name().substr(p1+1,p2-p1), port); - - listenEvent = new ListenEvent(this, listener.getfd(), POLLIN); - pollQueue.schedule(listenEvent); -} - -void -SimConsole::accept() -{ - if (!listener.islistening()) - panic("%s: cannot accept a connection if not listening!", name()); - - int fd = listener.accept(true); - if (data_fd != -1) { - char message[] = "console already attached!\n"; - ::write(fd, message, sizeof(message)); - ::close(fd); - return; - } - - data_fd = fd; - dataEvent = new DataEvent(this, data_fd, POLLIN); - pollQueue.schedule(dataEvent); - - stringstream stream; - ccprintf(stream, "==== m5 slave console: Console %d ====", number); - - // we need an actual carriage return followed by a newline for the - // terminal - stream << "\r\n"; - - write((const uint8_t *)stream.str().c_str(), stream.str().size()); - - DPRINTFN("attach console %d\n", number); - - txbuf.readall(data_fd); -} - -void -SimConsole::detach() -{ - if (data_fd != -1) { - ::close(data_fd); - data_fd = -1; - } - - pollQueue.remove(dataEvent); - delete dataEvent; - dataEvent = NULL; - - DPRINTFN("detach console %d\n", number); -} - -void -SimConsole::data() -{ - uint8_t buf[1024]; - int len; - - len = read(buf, sizeof(buf)); - if (len) { - rxbuf.write((char *)buf, len); - // Inform the UART there is data available - uart->dataAvailable(); - } -} - -size_t -SimConsole::read(uint8_t *buf, size_t len) -{ - if (data_fd < 0) - panic("Console not properly attached.\n"); - - size_t ret; - do { - ret = ::read(data_fd, buf, len); - } while (ret == -1 && errno == EINTR); - - - if (ret < 0) - DPRINTFN("Read failed.\n"); - - if (ret <= 0) { - detach(); - return 0; - } - - return ret; -} - -// Console output. -size_t -SimConsole::write(const uint8_t *buf, size_t len) -{ - if (data_fd < 0) - panic("Console not properly attached.\n"); - - size_t ret; - for (;;) { - ret = ::write(data_fd, buf, len); - - if (ret >= 0) - break; - - if (errno != EINTR) - detach(); - } - - return ret; -} - -#define MORE_PENDING (ULL(1) << 61) -#define RECEIVE_SUCCESS (ULL(0) << 62) -#define RECEIVE_NONE (ULL(2) << 62) -#define RECEIVE_ERROR (ULL(3) << 62) - -uint8_t -SimConsole::in() -{ - bool empty; - uint8_t c; - - empty = rxbuf.empty(); - assert(!empty); - rxbuf.read((char *)&c, 1); - empty = rxbuf.empty(); - - - DPRINTF(ConsoleVerbose, "in: \'%c\' %#02x more: %d\n", - isprint(c) ? c : ' ', c, !empty); - - return c; -} - -uint64_t -SimConsole::console_in() -{ - uint64_t value; - - if (dataAvailable()) { - value = RECEIVE_SUCCESS | in(); - if (!rxbuf.empty()) - value |= MORE_PENDING; - } else { - value = RECEIVE_NONE; - } - - DPRINTF(ConsoleVerbose, "console_in: return: %#x\n", value); - - return value; -} - -void -SimConsole::out(char c) -{ -#if TRACING_ON == 1 - if (DTRACE(Console)) { - static char last = '\0'; - - if (c != '\n' && c != '\r' || - last != '\n' && last != '\r') { - if (c == '\n' || c == '\r') { - int size = linebuf.size(); - char *buffer = new char[size + 1]; - linebuf.read(buffer, size); - buffer[size] = '\0'; - DPRINTF(Console, "%s\n", buffer); - delete [] buffer; - } else { - linebuf.write(c); - } - } - - last = c; - } -#endif - - txbuf.write(c); - - if (data_fd >= 0) - write(c); - - if (outfile) - outfile->write(&c, 1); - - DPRINTF(ConsoleVerbose, "out: \'%c\' %#02x\n", - isprint(c) ? c : ' ', (int)c); - -} - -SimConsole * -SimConsoleParams::create() -{ - return new SimConsole(this); -} diff --git a/src/dev/simconsole.hh b/src/dev/simconsole.hh deleted file mode 100644 index c8d453960..000000000 --- a/src/dev/simconsole.hh +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2001-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Nathan Binkert - * Ali Saidi - */ - -/* @file - * User Console Interface - */ - -#ifndef __CONSOLE_HH__ -#define __CONSOLE_HH__ - -#include - -#include "base/circlebuf.hh" -#include "cpu/intr_control.hh" -#include "base/pollevent.hh" -#include "base/socket.hh" -#include "sim/sim_object.hh" -#include "params/SimConsole.hh" - -class ConsoleListener; -class Uart; - -class SimConsole : public SimObject -{ - public: - Uart *uart; - - protected: - class ListenEvent : public PollEvent - { - protected: - SimConsole *cons; - - public: - ListenEvent(SimConsole *c, int fd, int e); - void process(int revent); - }; - - friend class ListenEvent; - ListenEvent *listenEvent; - - class DataEvent : public PollEvent - { - protected: - SimConsole *cons; - - public: - DataEvent(SimConsole *c, int fd, int e); - void process(int revent); - }; - - friend class DataEvent; - DataEvent *dataEvent; - - protected: - int number; - int data_fd; - - public: - typedef SimConsoleParams Params; - SimConsole(const Params *p); - ~SimConsole(); - - protected: - ListenSocket listener; - - void listen(int port); - void accept(); - - protected: - CircleBuf txbuf; - CircleBuf rxbuf; - std::ostream *outfile; -#if TRACING_ON == 1 - CircleBuf linebuf; -#endif - - public: - /////////////////////// - // Terminal Interface - - void data(); - - void read(uint8_t &c) { read(&c, 1); } - size_t read(uint8_t *buf, size_t len); - void write(uint8_t c) { write(&c, 1); } - size_t write(const uint8_t *buf, size_t len); - void detach(); - - public: - ///////////////// - // OS interface - - // Get a character from the console. - uint8_t in(); - - // get a character from the console in the console specific format - // corresponds to GETC: - // retval<63:61> - // 000: success: character received - // 001: success: character received, more pending - // 100: failure: no character ready - // 110: failure: character received with error - // 111: failure: character received with error, more pending - // retval<31:0> - // character read from console - // - // Interrupts are cleared when the buffer is empty. - uint64_t console_in(); - - // Send a character to the console - void out(char c); - - //Ask the console if data is available - bool dataAvailable() { return !rxbuf.empty(); } -}; - -#endif // __CONSOLE_HH__ diff --git a/src/dev/sparc/T1000.py b/src/dev/sparc/T1000.py index a033e27e2..cbf390737 100644 --- a/src/dev/sparc/T1000.py +++ b/src/dev/sparc/T1000.py @@ -29,9 +29,9 @@ from m5.params import * from m5.proxy import * from Device import BasicPioDevice, PioDevice, IsaFake, BadAddr -from Uart import Uart8250 from Platform import Platform -from SimConsole import SimConsole +from Terminal import Terminal +from Uart import Uart8250 class MmDisk(BasicPioDevice): @@ -98,11 +98,11 @@ class T1000(Platform): fake_ssi = IsaFake(pio_addr=0xff00000000, pio_size=0x10000000) #warn_access="Accessing SSI -- Unimplemented!") - hconsole = SimConsole() + hterm = Terminal() hvuart = Uart8250(pio_addr=0xfff0c2c000) htod = DumbTOD() - pconsole = SimConsole() + pterm = Terminal() puart0 = Uart8250(pio_addr=0x1f10000000) iob = Iob() @@ -116,8 +116,8 @@ class T1000(Platform): # earlier, since the bus object itself is typically defined at the # System level. def attachIO(self, bus): - self.hvuart.sim_console = self.hconsole - self.puart0.sim_console = self.pconsole + self.hvuart.terminal = self.hterm + self.puart0.terminal = self.pterm self.fake_clk.pio = bus.port self.fake_membnks.pio = bus.port self.fake_l2_1.pio = bus.port diff --git a/src/dev/sparc/t1000.cc b/src/dev/sparc/t1000.cc index 49e44af55..d42b442a1 100644 --- a/src/dev/sparc/t1000.cc +++ b/src/dev/sparc/t1000.cc @@ -37,8 +37,8 @@ #include #include "cpu/intr_control.hh" -#include "dev/simconsole.hh" #include "dev/sparc/t1000.hh" +#include "dev/terminal.hh" #include "sim/system.hh" using namespace std; diff --git a/src/dev/terminal.cc b/src/dev/terminal.cc new file mode 100644 index 000000000..18c9945bc --- /dev/null +++ b/src/dev/terminal.cc @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2001-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Ali Saidi + */ + +/* @file + * Implements the user interface to a serial terminal + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "base/misc.hh" +#include "base/output.hh" +#include "base/socket.hh" +#include "base/trace.hh" +#include "dev/platform.hh" +#include "dev/terminal.hh" +#include "dev/uart.hh" + +using namespace std; + + +/* + * Poll event for the listen socket + */ +Terminal::ListenEvent::ListenEvent(Terminal *t, int fd, int e) + : PollEvent(fd, e), term(t) +{ +} + +void +Terminal::ListenEvent::process(int revent) +{ + term->accept(); +} + +/* + * Poll event for the data socket + */ +Terminal::DataEvent::DataEvent(Terminal *t, int fd, int e) + : PollEvent(fd, e), term(t) +{ +} + +void +Terminal::DataEvent::process(int revent) +{ + if (revent & POLLIN) + term->data(); + else if (revent & POLLNVAL) + term->detach(); +} + +/* + * Terminal code + */ +Terminal::Terminal(const Params *p) + : SimObject(p), listenEvent(NULL), dataEvent(NULL), number(p->number), + data_fd(-1), txbuf(16384), rxbuf(16384), outfile(NULL) +#if TRACING_ON == 1 + , linebuf(16384) +#endif +{ + if (!p->output.empty()) { + if (p->append_name) + outfile = simout.find(p->output + "." + p->name); + else + outfile = simout.find(p->output); + + outfile->setf(ios::unitbuf); + } + + if (p->port) + listen(p->port); +} + +Terminal::~Terminal() +{ + if (data_fd != -1) + ::close(data_fd); + + if (listenEvent) + delete listenEvent; + + if (dataEvent) + delete dataEvent; +} + +/////////////////////////////////////////////////////////////////////// +// socket creation and terminal attach +// + +void +Terminal::listen(int port) +{ + while (!listener.listen(port, true)) { + DPRINTF(Terminal, + ": can't bind address terminal port %d inuse PID %d\n", + port, getpid()); + port++; + } + + int p1, p2; + p2 = name().rfind('.') - 1; + p1 = name().rfind('.', p2); + ccprintf(cerr, "Listening for %s connection on port %d\n", + name().substr(p1+1,p2-p1), port); + + listenEvent = new ListenEvent(this, listener.getfd(), POLLIN); + pollQueue.schedule(listenEvent); +} + +void +Terminal::accept() +{ + if (!listener.islistening()) + panic("%s: cannot accept a connection if not listening!", name()); + + int fd = listener.accept(true); + if (data_fd != -1) { + char message[] = "terminal already attached!\n"; + ::write(fd, message, sizeof(message)); + ::close(fd); + return; + } + + data_fd = fd; + dataEvent = new DataEvent(this, data_fd, POLLIN); + pollQueue.schedule(dataEvent); + + stringstream stream; + ccprintf(stream, "==== m5 slave terminal: Terminal %d ====", number); + + // we need an actual carriage return followed by a newline for the + // terminal + stream << "\r\n"; + + write((const uint8_t *)stream.str().c_str(), stream.str().size()); + + DPRINTFN("attach terminal %d\n", number); + + txbuf.readall(data_fd); +} + +void +Terminal::detach() +{ + if (data_fd != -1) { + ::close(data_fd); + data_fd = -1; + } + + pollQueue.remove(dataEvent); + delete dataEvent; + dataEvent = NULL; + + DPRINTFN("detach terminal %d\n", number); +} + +void +Terminal::data() +{ + uint8_t buf[1024]; + int len; + + len = read(buf, sizeof(buf)); + if (len) { + rxbuf.write((char *)buf, len); + // Inform the UART there is data available + uart->dataAvailable(); + } +} + +size_t +Terminal::read(uint8_t *buf, size_t len) +{ + if (data_fd < 0) + panic("Terminal not properly attached.\n"); + + size_t ret; + do { + ret = ::read(data_fd, buf, len); + } while (ret == -1 && errno == EINTR); + + + if (ret < 0) + DPRINTFN("Read failed.\n"); + + if (ret <= 0) { + detach(); + return 0; + } + + return ret; +} + +// Terminal output. +size_t +Terminal::write(const uint8_t *buf, size_t len) +{ + if (data_fd < 0) + panic("Terminal not properly attached.\n"); + + size_t ret; + for (;;) { + ret = ::write(data_fd, buf, len); + + if (ret >= 0) + break; + + if (errno != EINTR) + detach(); + } + + return ret; +} + +#define MORE_PENDING (ULL(1) << 61) +#define RECEIVE_SUCCESS (ULL(0) << 62) +#define RECEIVE_NONE (ULL(2) << 62) +#define RECEIVE_ERROR (ULL(3) << 62) + +uint8_t +Terminal::in() +{ + bool empty; + uint8_t c; + + empty = rxbuf.empty(); + assert(!empty); + rxbuf.read((char *)&c, 1); + empty = rxbuf.empty(); + + + DPRINTF(TerminalVerbose, "in: \'%c\' %#02x more: %d\n", + isprint(c) ? c : ' ', c, !empty); + + return c; +} + +uint64_t +Terminal::console_in() +{ + uint64_t value; + + if (dataAvailable()) { + value = RECEIVE_SUCCESS | in(); + if (!rxbuf.empty()) + value |= MORE_PENDING; + } else { + value = RECEIVE_NONE; + } + + DPRINTF(TerminalVerbose, "console_in: return: %#x\n", value); + + return value; +} + +void +Terminal::out(char c) +{ +#if TRACING_ON == 1 + if (DTRACE(Terminal)) { + static char last = '\0'; + + if (c != '\n' && c != '\r' || + last != '\n' && last != '\r') { + if (c == '\n' || c == '\r') { + int size = linebuf.size(); + char *buffer = new char[size + 1]; + linebuf.read(buffer, size); + buffer[size] = '\0'; + DPRINTF(Terminal, "%s\n", buffer); + delete [] buffer; + } else { + linebuf.write(c); + } + } + + last = c; + } +#endif + + txbuf.write(c); + + if (data_fd >= 0) + write(c); + + if (outfile) + outfile->write(&c, 1); + + DPRINTF(TerminalVerbose, "out: \'%c\' %#02x\n", + isprint(c) ? c : ' ', (int)c); + +} + +Terminal * +TerminalParams::create() +{ + return new Terminal(this); +} diff --git a/src/dev/terminal.hh b/src/dev/terminal.hh new file mode 100644 index 000000000..d2499b6b2 --- /dev/null +++ b/src/dev/terminal.hh @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2001-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Ali Saidi + */ + +/* @file + * User Terminal Interface + */ + +#ifndef __DEV_TERMINAL_HH__ +#define __DEV_TERMINAL_HH__ + +#include + +#include "base/circlebuf.hh" +#include "cpu/intr_control.hh" +#include "base/pollevent.hh" +#include "base/socket.hh" +#include "sim/sim_object.hh" +#include "params/Terminal.hh" + +class TerminalListener; +class Uart; + +class Terminal : public SimObject +{ + public: + Uart *uart; + + protected: + class ListenEvent : public PollEvent + { + protected: + Terminal *term; + + public: + ListenEvent(Terminal *t, int fd, int e); + void process(int revent); + }; + + friend class ListenEvent; + ListenEvent *listenEvent; + + class DataEvent : public PollEvent + { + protected: + Terminal *term; + + public: + DataEvent(Terminal *t, int fd, int e); + void process(int revent); + }; + + friend class DataEvent; + DataEvent *dataEvent; + + protected: + int number; + int data_fd; + + public: + typedef TerminalParams Params; + Terminal(const Params *p); + ~Terminal(); + + protected: + ListenSocket listener; + + void listen(int port); + void accept(); + + protected: + CircleBuf txbuf; + CircleBuf rxbuf; + std::ostream *outfile; +#if TRACING_ON == 1 + CircleBuf linebuf; +#endif + + public: + /////////////////////// + // Terminal Interface + + void data(); + + void read(uint8_t &c) { read(&c, 1); } + size_t read(uint8_t *buf, size_t len); + void write(uint8_t c) { write(&c, 1); } + size_t write(const uint8_t *buf, size_t len); + void detach(); + + public: + ///////////////// + // OS interface + + // Get a character from the terminal. + uint8_t in(); + + // get a character from the terminal in the console specific format + // corresponds to GETC: + // retval<63:61> + // 000: success: character received + // 001: success: character received, more pending + // 100: failure: no character ready + // 110: failure: character received with error + // 111: failure: character received with error, more pending + // retval<31:0> + // character read from console + // + // Interrupts are cleared when the buffer is empty. + uint64_t console_in(); + + // Send a character to the terminal + void out(char c); + + // Ask the terminal if data is available + bool dataAvailable() { return !rxbuf.empty(); } +}; + +#endif // __DEV_TERMINAL_HH__ diff --git a/src/dev/uart.cc b/src/dev/uart.cc index c9a2ae964..ab0ebde2c 100644 --- a/src/dev/uart.cc +++ b/src/dev/uart.cc @@ -32,17 +32,17 @@ * Implements a base class for UARTs */ -#include "dev/simconsole.hh" -#include "dev/uart.hh" #include "dev/platform.hh" +#include "dev/terminal.hh" +#include "dev/uart.hh" using namespace std; Uart::Uart(const Params *p) - : BasicPioDevice(p), platform(p->platform), cons(p->sim_console) + : BasicPioDevice(p), platform(p->platform), term(p->terminal) { status = 0; // set back pointers - cons->uart = this; + term->uart = this; } diff --git a/src/dev/uart.hh b/src/dev/uart.hh index f5d5e2855..ba10c204c 100644 --- a/src/dev/uart.hh +++ b/src/dev/uart.hh @@ -39,7 +39,7 @@ #include "dev/io_device.hh" #include "params/Uart.hh" -class SimConsole; +class Terminal; class Platform; const int RX_INT = 0x1; @@ -51,7 +51,7 @@ class Uart : public BasicPioDevice protected: int status; Platform *platform; - SimConsole *cons; + Terminal *term; public: typedef UartParams Params; diff --git a/src/dev/uart8250.cc b/src/dev/uart8250.cc index b4dc93645..eefda76e5 100644 --- a/src/dev/uart8250.cc +++ b/src/dev/uart8250.cc @@ -38,9 +38,9 @@ #include "base/inifile.hh" #include "base/str.hh" // for to_number #include "base/trace.hh" -#include "dev/simconsole.hh" -#include "dev/uart8250.hh" #include "dev/platform.hh" +#include "dev/terminal.hh" +#include "dev/uart8250.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" @@ -120,8 +120,8 @@ Uart8250::read(PacketPtr pkt) switch (daddr) { case 0x0: if (!(LCR & 0x80)) { // read byte - if (cons->dataAvailable()) - pkt->set(cons->in()); + if (term->dataAvailable()) + pkt->set(term->in()); else { pkt->set((uint8_t)0); // A limited amount of these are ok. @@ -130,7 +130,7 @@ Uart8250::read(PacketPtr pkt) status &= ~RX_INT; platform->clearConsoleInt(); - if (cons->dataAvailable() && (IER & UART_IER_RDI)) + if (term->dataAvailable() && (IER & UART_IER_RDI)) rxIntrEvent.scheduleIntr(); } else { // dll divisor latch ; @@ -165,7 +165,7 @@ Uart8250::read(PacketPtr pkt) uint8_t lsr; lsr = 0; // check if there are any bytes to be read - if (cons->dataAvailable()) + if (term->dataAvailable()) lsr = UART_LSR_DR; lsr |= UART_LSR_TEMT | UART_LSR_THRE; pkt->set(lsr); @@ -201,7 +201,7 @@ Uart8250::write(PacketPtr pkt) switch (daddr) { case 0x0: if (!(LCR & 0x80)) { // write byte - cons->out(pkt->get()); + term->out(pkt->get()); platform->clearConsoleInt(); status &= ~TX_INT; if (UART_IER_THRI & IER) @@ -237,7 +237,7 @@ Uart8250::write(PacketPtr pkt) status &= ~TX_INT; } - if ((UART_IER_RDI & IER) && cons->dataAvailable()) { + if ((UART_IER_RDI & IER) && term->dataAvailable()) { DPRINTF(Uart, "IER: IER_RDI set, scheduling RX intrrupt\n"); rxIntrEvent.scheduleIntr(); } else { diff --git a/src/dev/uart8250.hh b/src/dev/uart8250.hh index 2c69667e1..79c31d5cf 100644 --- a/src/dev/uart8250.hh +++ b/src/dev/uart8250.hh @@ -65,7 +65,7 @@ const uint8_t UART_LSR_DR = 0x01; const uint8_t UART_MCR_LOOP = 0x10; -class SimConsole; +class Terminal; class Platform; class Uart8250 : public Uart diff --git a/src/dev/x86/PC.py b/src/dev/x86/PC.py index 4ba9e7a8a..5165308ed 100644 --- a/src/dev/x86/PC.py +++ b/src/dev/x86/PC.py @@ -28,12 +28,13 @@ from m5.params import * from m5.proxy import * -from Uart import Uart8250 + from Device import IsaFake -from SouthBridge import SouthBridge -from Platform import Platform from Pci import PciConfigAll -from SimConsole import SimConsole +from Platform import Platform +from SouthBridge import SouthBridge +from Terminal import Terminal +from Uart import Uart8250 def x86IOAddress(port): IO_address_space_base = 0x8000000000000000 @@ -54,11 +55,11 @@ class PC(Platform): # but the linux kernel fiddles with them anway. behind_pci = IsaFake(pio_addr=x86IOAddress(0xcf8), pio_size=8) - # Serial port and console - console = SimConsole() + # Serial port and terminal + terminal = Terminal() com_1 = Uart8250() com_1.pio_addr = x86IOAddress(0x3f8) - com_1.sim_console = console + com_1.terminal = terminal def attachIO(self, bus): self.south_bridge.pio = bus.port diff --git a/src/dev/x86/pc.cc b/src/dev/x86/pc.cc index 0881672d2..d04529ab9 100644 --- a/src/dev/x86/pc.cc +++ b/src/dev/x86/pc.cc @@ -39,7 +39,7 @@ #include "arch/x86/x86_traits.hh" #include "dev/intel_8254_timer.hh" #include "cpu/intr_control.hh" -#include "dev/simconsole.hh" +#include "dev/terminal.hh" #include "dev/x86/pc.hh" #include "sim/system.hh" -- cgit v1.2.3 From 6ff4539901c6efa05ecad20149342fe8d64e7ba9 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Tue, 17 Jun 2008 20:30:37 -0700 Subject: Change the default output filename for the terminal so it's more obvious. --HG-- rename : tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-atomic-dual/console.system.sim_console => tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-atomic-dual/system.terminal rename : tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-atomic/console.system.sim_console => tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-atomic/system.terminal rename : tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-timing-dual/console.system.sim_console => tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-timing-dual/system.terminal rename : tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-timing/console.system.sim_console => tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-timing/system.terminal rename : tests/quick/80.netperf-stream/ref/alpha/linux/twosys-tsunami-simple-atomic/console.drivesys.sim_console => tests/quick/80.netperf-stream/ref/alpha/linux/twosys-tsunami-simple-atomic/drivesys.terminal rename : tests/quick/80.netperf-stream/ref/alpha/linux/twosys-tsunami-simple-atomic/console.testsys.sim_console => tests/quick/80.netperf-stream/ref/alpha/linux/twosys-tsunami-simple-atomic/testsys.terminal --- src/dev/Terminal.py | 3 +-- src/dev/terminal.cc | 8 ++------ 2 files changed, 3 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/dev/Terminal.py b/src/dev/Terminal.py index 3d97070ba..d67019198 100644 --- a/src/dev/Terminal.py +++ b/src/dev/Terminal.py @@ -32,8 +32,7 @@ from m5.proxy import * class Terminal(SimObject): type = 'Terminal' - append_name = Param.Bool(True, "append name() to filename") intr_control = Param.IntrControl(Parent.any, "interrupt controller") port = Param.TcpPort(3456, "listen port") number = Param.Int(0, "terminal number") - output = Param.String('console', "file to dump output to") + output = Param.Bool(True, "Enable output dump to file") diff --git a/src/dev/terminal.cc b/src/dev/terminal.cc index 18c9945bc..47f280ad3 100644 --- a/src/dev/terminal.cc +++ b/src/dev/terminal.cc @@ -97,12 +97,8 @@ Terminal::Terminal(const Params *p) , linebuf(16384) #endif { - if (!p->output.empty()) { - if (p->append_name) - outfile = simout.find(p->output + "." + p->name); - else - outfile = simout.find(p->output); - + if (p->output) { + outfile = simout.find(p->name); outfile->setf(ios::unitbuf); } -- cgit v1.2.3 From 934523c3a07ffc729f05b82dd622f9a63c39401d Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Tue, 17 Jun 2008 20:36:39 -0700 Subject: rename AlphaConsole to AlphaBackdoor --HG-- rename : src/dev/alpha/AlphaConsole.py => src/dev/alpha/AlphaBackdoor.py rename : src/dev/alpha/console.cc => src/dev/alpha/backdoor.cc rename : src/dev/alpha/console.hh => src/dev/alpha/backdoor.hh --- src/dev/alpha/AlphaBackdoor.py | 38 +++++ src/dev/alpha/AlphaConsole.py | 38 ----- src/dev/alpha/SConscript | 6 +- src/dev/alpha/Tsunami.py | 11 +- src/dev/alpha/backdoor.cc | 310 +++++++++++++++++++++++++++++++++++++++++ src/dev/alpha/backdoor.hh | 126 +++++++++++++++++ src/dev/alpha/console.cc | 310 ----------------------------------------- src/dev/alpha/console.hh | 126 ----------------- 8 files changed, 482 insertions(+), 483 deletions(-) create mode 100644 src/dev/alpha/AlphaBackdoor.py delete mode 100644 src/dev/alpha/AlphaConsole.py create mode 100644 src/dev/alpha/backdoor.cc create mode 100644 src/dev/alpha/backdoor.hh delete mode 100644 src/dev/alpha/console.cc delete mode 100644 src/dev/alpha/console.hh (limited to 'src') diff --git a/src/dev/alpha/AlphaBackdoor.py b/src/dev/alpha/AlphaBackdoor.py new file mode 100644 index 000000000..fa9627164 --- /dev/null +++ b/src/dev/alpha/AlphaBackdoor.py @@ -0,0 +1,38 @@ +# Copyright (c) 2005-2007 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +from m5.params import * +from m5.proxy import * +from Device import BasicPioDevice + +class AlphaBackdoor(BasicPioDevice): + type = 'AlphaBackdoor' + cpu = Param.BaseCPU(Parent.cpu[0], "Processor") + disk = Param.SimpleDisk("Simple Disk") + terminal = Param.Terminal(Parent.any, "The console terminal") + system = Param.AlphaSystem(Parent.any, "system object") diff --git a/src/dev/alpha/AlphaConsole.py b/src/dev/alpha/AlphaConsole.py deleted file mode 100644 index 8983fcbed..000000000 --- a/src/dev/alpha/AlphaConsole.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (c) 2005-2007 The Regents of The University of Michigan -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer; -# redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution; -# neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Authors: Nathan Binkert - -from m5.params import * -from m5.proxy import * -from Device import BasicPioDevice - -class AlphaConsole(BasicPioDevice): - type = 'AlphaConsole' - cpu = Param.BaseCPU(Parent.cpu[0], "Processor") - disk = Param.SimpleDisk("Simple Disk") - terminal = Param.Terminal(Parent.any, "The console terminal") - system = Param.AlphaSystem(Parent.any, "system object") diff --git a/src/dev/alpha/SConscript b/src/dev/alpha/SConscript index 6bd26a9b1..4dbb73903 100644 --- a/src/dev/alpha/SConscript +++ b/src/dev/alpha/SConscript @@ -32,14 +32,14 @@ Import('*') if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'alpha': - SimObject('AlphaConsole.py') + SimObject('AlphaBackdoor.py') SimObject('Tsunami.py') - Source('console.cc') + Source('backdoor.cc') Source('tsunami.cc') Source('tsunami_cchip.cc') Source('tsunami_io.cc') Source('tsunami_pchip.cc') - TraceFlag('AlphaConsole') + TraceFlag('AlphaBackdoor') TraceFlag('Tsunami') diff --git a/src/dev/alpha/Tsunami.py b/src/dev/alpha/Tsunami.py index 5c5207a33..5440486b6 100644 --- a/src/dev/alpha/Tsunami.py +++ b/src/dev/alpha/Tsunami.py @@ -28,12 +28,12 @@ from m5.params import * from m5.proxy import * +from BadDevice import BadDevice +from AlphaBackdoor import AlphaBackdoor from Device import BasicPioDevice, IsaFake, BadAddr +from Pci import PciConfigAll from Platform import Platform -from AlphaConsole import AlphaConsole from Uart import Uart8250 -from Pci import PciConfigAll -from BadDevice import BadDevice class TsunamiCChip(BasicPioDevice): type = 'TsunamiCChip' @@ -87,8 +87,7 @@ class Tsunami(Platform): fb = BadDevice(pio_addr=0x801fc0003d0, devicename='FrameBuffer') io = TsunamiIO(pio_addr=0x801fc000000) uart = Uart8250(pio_addr=0x801fc0003f8) - alpha_console = AlphaConsole(pio_addr=0x80200000000, - disk=Parent.simple_disk) + backdoor = AlphaBackdoor(pio_addr=0x80200000000, disk=Parent.simple_disk) # Attach I/O devices to specified bus object. Can't do this # earlier, since the bus object itself is typically defined at the @@ -121,4 +120,4 @@ class Tsunami(Platform): self.fb.pio = bus.port self.io.pio = bus.port self.uart.pio = bus.port - self.alpha_console.pio = bus.port + self.backdoor.pio = bus.port diff --git a/src/dev/alpha/backdoor.cc b/src/dev/alpha/backdoor.cc new file mode 100644 index 000000000..3ba6cbd24 --- /dev/null +++ b/src/dev/alpha/backdoor.cc @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2001-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Ali Saidi + * Steve Reinhardt + * Erik Hallnor + */ + +/** @file + * Alpha Console Backdoor Definition + */ + +#include +#include + +#include "arch/alpha/system.hh" +#include "base/inifile.hh" +#include "base/str.hh" +#include "base/trace.hh" +#include "cpu/base.hh" +#include "cpu/thread_context.hh" +#include "dev/alpha/backdoor.hh" +#include "dev/platform.hh" +#include "dev/simple_disk.hh" +#include "dev/terminal.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" +#include "mem/physical.hh" +#include "params/AlphaBackdoor.hh" +#include "sim/sim_object.hh" + +using namespace std; +using namespace AlphaISA; + +AlphaBackdoor::AlphaBackdoor(const Params *p) + : BasicPioDevice(p), disk(p->disk), terminal(p->terminal), + system(p->system), cpu(p->cpu) +{ + + pioSize = sizeof(struct AlphaAccess); + + alphaAccess = new Access(); + alphaAccess->last_offset = pioSize - 1; + + alphaAccess->version = ALPHA_ACCESS_VERSION; + alphaAccess->diskUnit = 1; + + alphaAccess->diskCount = 0; + alphaAccess->diskPAddr = 0; + alphaAccess->diskBlock = 0; + alphaAccess->diskOperation = 0; + alphaAccess->outputChar = 0; + alphaAccess->inputChar = 0; + std::memset(alphaAccess->cpuStack, 0, sizeof(alphaAccess->cpuStack)); + +} + +void +AlphaBackdoor::startup() +{ + system->setAlphaAccess(pioAddr); + alphaAccess->numCPUs = system->getNumCPUs(); + alphaAccess->kernStart = system->getKernelStart(); + alphaAccess->kernEnd = system->getKernelEnd(); + alphaAccess->entryPoint = system->getKernelEntry(); + alphaAccess->mem_size = system->physmem->size(); + alphaAccess->cpuClock = cpu->frequency() / 1000000; // In MHz + alphaAccess->intrClockFrequency = params()->platform->intrFrequency(); +} + +Tick +AlphaBackdoor::read(PacketPtr pkt) +{ + + /** XXX Do we want to push the addr munging to a bus brige or something? So + * the device has it's physical address and then the bridge adds on whatever + * machine dependent address swizzle is required? + */ + + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); + + Addr daddr = pkt->getAddr() - pioAddr; + + pkt->allocate(); + pkt->makeAtomicResponse(); + + switch (pkt->getSize()) + { + case sizeof(uint32_t): + switch (daddr) + { + case offsetof(AlphaAccess, last_offset): + pkt->set(alphaAccess->last_offset); + break; + case offsetof(AlphaAccess, version): + pkt->set(alphaAccess->version); + break; + case offsetof(AlphaAccess, numCPUs): + pkt->set(alphaAccess->numCPUs); + break; + case offsetof(AlphaAccess, intrClockFrequency): + pkt->set(alphaAccess->intrClockFrequency); + break; + default: + /* Old console code read in everyting as a 32bit int + * we now break that for better error checking. + */ + pkt->setBadAddress(); + } + DPRINTF(AlphaBackdoor, "read: offset=%#x val=%#x\n", daddr, + pkt->get()); + break; + case sizeof(uint64_t): + switch (daddr) + { + case offsetof(AlphaAccess, inputChar): + pkt->set(terminal->console_in()); + break; + case offsetof(AlphaAccess, cpuClock): + pkt->set(alphaAccess->cpuClock); + break; + case offsetof(AlphaAccess, mem_size): + pkt->set(alphaAccess->mem_size); + break; + case offsetof(AlphaAccess, kernStart): + pkt->set(alphaAccess->kernStart); + break; + case offsetof(AlphaAccess, kernEnd): + pkt->set(alphaAccess->kernEnd); + break; + case offsetof(AlphaAccess, entryPoint): + pkt->set(alphaAccess->entryPoint); + break; + case offsetof(AlphaAccess, diskUnit): + pkt->set(alphaAccess->diskUnit); + break; + case offsetof(AlphaAccess, diskCount): + pkt->set(alphaAccess->diskCount); + break; + case offsetof(AlphaAccess, diskPAddr): + pkt->set(alphaAccess->diskPAddr); + break; + case offsetof(AlphaAccess, diskBlock): + pkt->set(alphaAccess->diskBlock); + break; + case offsetof(AlphaAccess, diskOperation): + pkt->set(alphaAccess->diskOperation); + break; + case offsetof(AlphaAccess, outputChar): + pkt->set(alphaAccess->outputChar); + break; + default: + int cpunum = (daddr - offsetof(AlphaAccess, cpuStack)) / + sizeof(alphaAccess->cpuStack[0]); + + if (cpunum >= 0 && cpunum < 64) + pkt->set(alphaAccess->cpuStack[cpunum]); + else + panic("Unknown 64bit access, %#x\n", daddr); + } + DPRINTF(AlphaBackdoor, "read: offset=%#x val=%#x\n", daddr, + pkt->get()); + break; + default: + pkt->setBadAddress(); + } + return pioDelay; +} + +Tick +AlphaBackdoor::write(PacketPtr pkt) +{ + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); + Addr daddr = pkt->getAddr() - pioAddr; + + uint64_t val = pkt->get(); + assert(pkt->getSize() == sizeof(uint64_t)); + + switch (daddr) { + case offsetof(AlphaAccess, diskUnit): + alphaAccess->diskUnit = val; + break; + + case offsetof(AlphaAccess, diskCount): + alphaAccess->diskCount = val; + break; + + case offsetof(AlphaAccess, diskPAddr): + alphaAccess->diskPAddr = val; + break; + + case offsetof(AlphaAccess, diskBlock): + alphaAccess->diskBlock = val; + break; + + case offsetof(AlphaAccess, diskOperation): + if (val == 0x13) + disk->read(alphaAccess->diskPAddr, alphaAccess->diskBlock, + alphaAccess->diskCount); + else + panic("Invalid disk operation!"); + + break; + + case offsetof(AlphaAccess, outputChar): + terminal->out((char)(val & 0xff)); + break; + + default: + int cpunum = (daddr - offsetof(AlphaAccess, cpuStack)) / + sizeof(alphaAccess->cpuStack[0]); + warn("%d: Trying to launch CPU number %d!", curTick, cpunum); + assert(val > 0 && "Must not access primary cpu"); + if (cpunum >= 0 && cpunum < 64) + alphaAccess->cpuStack[cpunum] = val; + else + panic("Unknown 64bit access, %#x\n", daddr); + } + + pkt->makeAtomicResponse(); + + return pioDelay; +} + +void +AlphaBackdoor::Access::serialize(ostream &os) +{ + SERIALIZE_SCALAR(last_offset); + SERIALIZE_SCALAR(version); + SERIALIZE_SCALAR(numCPUs); + SERIALIZE_SCALAR(mem_size); + SERIALIZE_SCALAR(cpuClock); + SERIALIZE_SCALAR(intrClockFrequency); + SERIALIZE_SCALAR(kernStart); + SERIALIZE_SCALAR(kernEnd); + SERIALIZE_SCALAR(entryPoint); + SERIALIZE_SCALAR(diskUnit); + SERIALIZE_SCALAR(diskCount); + SERIALIZE_SCALAR(diskPAddr); + SERIALIZE_SCALAR(diskBlock); + SERIALIZE_SCALAR(diskOperation); + SERIALIZE_SCALAR(outputChar); + SERIALIZE_SCALAR(inputChar); + SERIALIZE_ARRAY(cpuStack,64); +} + +void +AlphaBackdoor::Access::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_SCALAR(last_offset); + UNSERIALIZE_SCALAR(version); + UNSERIALIZE_SCALAR(numCPUs); + UNSERIALIZE_SCALAR(mem_size); + UNSERIALIZE_SCALAR(cpuClock); + UNSERIALIZE_SCALAR(intrClockFrequency); + UNSERIALIZE_SCALAR(kernStart); + UNSERIALIZE_SCALAR(kernEnd); + UNSERIALIZE_SCALAR(entryPoint); + UNSERIALIZE_SCALAR(diskUnit); + UNSERIALIZE_SCALAR(diskCount); + UNSERIALIZE_SCALAR(diskPAddr); + UNSERIALIZE_SCALAR(diskBlock); + UNSERIALIZE_SCALAR(diskOperation); + UNSERIALIZE_SCALAR(outputChar); + UNSERIALIZE_SCALAR(inputChar); + UNSERIALIZE_ARRAY(cpuStack, 64); +} + +void +AlphaBackdoor::serialize(ostream &os) +{ + alphaAccess->serialize(os); +} + +void +AlphaBackdoor::unserialize(Checkpoint *cp, const std::string §ion) +{ + alphaAccess->unserialize(cp, section); +} + +AlphaBackdoor * +AlphaBackdoorParams::create() +{ + return new AlphaBackdoor(this); +} diff --git a/src/dev/alpha/backdoor.hh b/src/dev/alpha/backdoor.hh new file mode 100644 index 000000000..ad3c79823 --- /dev/null +++ b/src/dev/alpha/backdoor.hh @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2001-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +/** @file + * System Console Backdoor Interface + */ + +#ifndef __DEV_ALPHA_BACKDOOR_HH__ +#define __DEV_ALPHA_BACKDOOR_HH__ + +#include "base/range.hh" +#include "dev/alpha/access.h" +#include "dev/io_device.hh" +#include "params/AlphaBackdoor.hh" +#include "sim/host.hh" +#include "sim/sim_object.hh" + +class BaseCPU; +class Terminal; +class AlphaSystem; +class SimpleDisk; + +/** + * Memory mapped interface to the system console. This device + * represents a shared data region between the OS Kernel and the + * System Console Backdoor. + * + * The system console is a small standalone program that is initially + * run when the system boots. It contains the necessary code to + * access the boot disk, to read/write from the console, and to pass + * boot parameters to the kernel. + * + * This version of the system console is very different from the one + * that would be found in a real system. Many of the functions use + * some sort of backdoor to get their job done. For example, reading + * from the boot device on a real system would require a minimal + * device driver to access the disk controller, but since we have a + * simulator here, we are able to bypass the disk controller and + * access the disk image directly. There are also some things like + * reading the kernel off the disk image into memory that are normally + * taken care of by the console that are now taken care of by the + * simulator. + * + * These shortcuts are acceptable since the system console is + * primarily used doing boot before the kernel has loaded its device + * drivers. + */ +class AlphaBackdoor : public BasicPioDevice +{ + protected: + struct Access : public AlphaAccess + { + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); + }; + + union { + Access *alphaAccess; + uint8_t *consoleData; + }; + + /** the disk must be accessed from the console */ + SimpleDisk *disk; + + /** the system console (the terminal) is accessable from the console */ + Terminal *terminal; + + /** a pointer to the system we are running in */ + AlphaSystem *system; + + /** a pointer to the CPU boot cpu */ + BaseCPU *cpu; + + public: + typedef AlphaBackdoorParams Params; + AlphaBackdoor(const Params *p); + + const Params * + params() const + { + return dynamic_cast(_params); + } + + virtual void startup(); + + /** + * memory mapped reads and writes + */ + virtual Tick read(PacketPtr pkt); + virtual Tick write(PacketPtr pkt); + + /** + * standard serialization routines for checkpointing + */ + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); +}; + +#endif // __DEV_ALPHA_BACKDOOR_HH__ diff --git a/src/dev/alpha/console.cc b/src/dev/alpha/console.cc deleted file mode 100644 index d7b2b5b02..000000000 --- a/src/dev/alpha/console.cc +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright (c) 2001-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Nathan Binkert - * Ali Saidi - * Steve Reinhardt - * Erik Hallnor - */ - -/** @file - * Alpha Console Definition - */ - -#include -#include - -#include "arch/alpha/system.hh" -#include "base/inifile.hh" -#include "base/str.hh" -#include "base/trace.hh" -#include "cpu/base.hh" -#include "cpu/thread_context.hh" -#include "dev/alpha/console.hh" -#include "dev/platform.hh" -#include "dev/simple_disk.hh" -#include "dev/terminal.hh" -#include "mem/packet.hh" -#include "mem/packet_access.hh" -#include "mem/physical.hh" -#include "params/AlphaConsole.hh" -#include "sim/sim_object.hh" - -using namespace std; -using namespace AlphaISA; - -AlphaConsole::AlphaConsole(const Params *p) - : BasicPioDevice(p), disk(p->disk), terminal(p->terminal), - system(p->system), cpu(p->cpu) -{ - - pioSize = sizeof(struct AlphaAccess); - - alphaAccess = new Access(); - alphaAccess->last_offset = pioSize - 1; - - alphaAccess->version = ALPHA_ACCESS_VERSION; - alphaAccess->diskUnit = 1; - - alphaAccess->diskCount = 0; - alphaAccess->diskPAddr = 0; - alphaAccess->diskBlock = 0; - alphaAccess->diskOperation = 0; - alphaAccess->outputChar = 0; - alphaAccess->inputChar = 0; - std::memset(alphaAccess->cpuStack, 0, sizeof(alphaAccess->cpuStack)); - -} - -void -AlphaConsole::startup() -{ - system->setAlphaAccess(pioAddr); - alphaAccess->numCPUs = system->getNumCPUs(); - alphaAccess->kernStart = system->getKernelStart(); - alphaAccess->kernEnd = system->getKernelEnd(); - alphaAccess->entryPoint = system->getKernelEntry(); - alphaAccess->mem_size = system->physmem->size(); - alphaAccess->cpuClock = cpu->frequency() / 1000000; // In MHz - alphaAccess->intrClockFrequency = params()->platform->intrFrequency(); -} - -Tick -AlphaConsole::read(PacketPtr pkt) -{ - - /** XXX Do we want to push the addr munging to a bus brige or something? So - * the device has it's physical address and then the bridge adds on whatever - * machine dependent address swizzle is required? - */ - - assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); - - Addr daddr = pkt->getAddr() - pioAddr; - - pkt->allocate(); - pkt->makeAtomicResponse(); - - switch (pkt->getSize()) - { - case sizeof(uint32_t): - switch (daddr) - { - case offsetof(AlphaAccess, last_offset): - pkt->set(alphaAccess->last_offset); - break; - case offsetof(AlphaAccess, version): - pkt->set(alphaAccess->version); - break; - case offsetof(AlphaAccess, numCPUs): - pkt->set(alphaAccess->numCPUs); - break; - case offsetof(AlphaAccess, intrClockFrequency): - pkt->set(alphaAccess->intrClockFrequency); - break; - default: - /* Old console code read in everyting as a 32bit int - * we now break that for better error checking. - */ - pkt->setBadAddress(); - } - DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr, - pkt->get()); - break; - case sizeof(uint64_t): - switch (daddr) - { - case offsetof(AlphaAccess, inputChar): - pkt->set(terminal->console_in()); - break; - case offsetof(AlphaAccess, cpuClock): - pkt->set(alphaAccess->cpuClock); - break; - case offsetof(AlphaAccess, mem_size): - pkt->set(alphaAccess->mem_size); - break; - case offsetof(AlphaAccess, kernStart): - pkt->set(alphaAccess->kernStart); - break; - case offsetof(AlphaAccess, kernEnd): - pkt->set(alphaAccess->kernEnd); - break; - case offsetof(AlphaAccess, entryPoint): - pkt->set(alphaAccess->entryPoint); - break; - case offsetof(AlphaAccess, diskUnit): - pkt->set(alphaAccess->diskUnit); - break; - case offsetof(AlphaAccess, diskCount): - pkt->set(alphaAccess->diskCount); - break; - case offsetof(AlphaAccess, diskPAddr): - pkt->set(alphaAccess->diskPAddr); - break; - case offsetof(AlphaAccess, diskBlock): - pkt->set(alphaAccess->diskBlock); - break; - case offsetof(AlphaAccess, diskOperation): - pkt->set(alphaAccess->diskOperation); - break; - case offsetof(AlphaAccess, outputChar): - pkt->set(alphaAccess->outputChar); - break; - default: - int cpunum = (daddr - offsetof(AlphaAccess, cpuStack)) / - sizeof(alphaAccess->cpuStack[0]); - - if (cpunum >= 0 && cpunum < 64) - pkt->set(alphaAccess->cpuStack[cpunum]); - else - panic("Unknown 64bit access, %#x\n", daddr); - } - DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr, - pkt->get()); - break; - default: - pkt->setBadAddress(); - } - return pioDelay; -} - -Tick -AlphaConsole::write(PacketPtr pkt) -{ - assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); - Addr daddr = pkt->getAddr() - pioAddr; - - uint64_t val = pkt->get(); - assert(pkt->getSize() == sizeof(uint64_t)); - - switch (daddr) { - case offsetof(AlphaAccess, diskUnit): - alphaAccess->diskUnit = val; - break; - - case offsetof(AlphaAccess, diskCount): - alphaAccess->diskCount = val; - break; - - case offsetof(AlphaAccess, diskPAddr): - alphaAccess->diskPAddr = val; - break; - - case offsetof(AlphaAccess, diskBlock): - alphaAccess->diskBlock = val; - break; - - case offsetof(AlphaAccess, diskOperation): - if (val == 0x13) - disk->read(alphaAccess->diskPAddr, alphaAccess->diskBlock, - alphaAccess->diskCount); - else - panic("Invalid disk operation!"); - - break; - - case offsetof(AlphaAccess, outputChar): - terminal->out((char)(val & 0xff)); - break; - - default: - int cpunum = (daddr - offsetof(AlphaAccess, cpuStack)) / - sizeof(alphaAccess->cpuStack[0]); - warn("%d: Trying to launch CPU number %d!", curTick, cpunum); - assert(val > 0 && "Must not access primary cpu"); - if (cpunum >= 0 && cpunum < 64) - alphaAccess->cpuStack[cpunum] = val; - else - panic("Unknown 64bit access, %#x\n", daddr); - } - - pkt->makeAtomicResponse(); - - return pioDelay; -} - -void -AlphaConsole::Access::serialize(ostream &os) -{ - SERIALIZE_SCALAR(last_offset); - SERIALIZE_SCALAR(version); - SERIALIZE_SCALAR(numCPUs); - SERIALIZE_SCALAR(mem_size); - SERIALIZE_SCALAR(cpuClock); - SERIALIZE_SCALAR(intrClockFrequency); - SERIALIZE_SCALAR(kernStart); - SERIALIZE_SCALAR(kernEnd); - SERIALIZE_SCALAR(entryPoint); - SERIALIZE_SCALAR(diskUnit); - SERIALIZE_SCALAR(diskCount); - SERIALIZE_SCALAR(diskPAddr); - SERIALIZE_SCALAR(diskBlock); - SERIALIZE_SCALAR(diskOperation); - SERIALIZE_SCALAR(outputChar); - SERIALIZE_SCALAR(inputChar); - SERIALIZE_ARRAY(cpuStack,64); -} - -void -AlphaConsole::Access::unserialize(Checkpoint *cp, const std::string §ion) -{ - UNSERIALIZE_SCALAR(last_offset); - UNSERIALIZE_SCALAR(version); - UNSERIALIZE_SCALAR(numCPUs); - UNSERIALIZE_SCALAR(mem_size); - UNSERIALIZE_SCALAR(cpuClock); - UNSERIALIZE_SCALAR(intrClockFrequency); - UNSERIALIZE_SCALAR(kernStart); - UNSERIALIZE_SCALAR(kernEnd); - UNSERIALIZE_SCALAR(entryPoint); - UNSERIALIZE_SCALAR(diskUnit); - UNSERIALIZE_SCALAR(diskCount); - UNSERIALIZE_SCALAR(diskPAddr); - UNSERIALIZE_SCALAR(diskBlock); - UNSERIALIZE_SCALAR(diskOperation); - UNSERIALIZE_SCALAR(outputChar); - UNSERIALIZE_SCALAR(inputChar); - UNSERIALIZE_ARRAY(cpuStack, 64); -} - -void -AlphaConsole::serialize(ostream &os) -{ - alphaAccess->serialize(os); -} - -void -AlphaConsole::unserialize(Checkpoint *cp, const std::string §ion) -{ - alphaAccess->unserialize(cp, section); -} - -AlphaConsole * -AlphaConsoleParams::create() -{ - return new AlphaConsole(this); -} diff --git a/src/dev/alpha/console.hh b/src/dev/alpha/console.hh deleted file mode 100644 index b6145ef38..000000000 --- a/src/dev/alpha/console.hh +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2001-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Nathan Binkert - */ - -/** @file - * System Console Interface - */ - -#ifndef __ALPHA_CONSOLE_HH__ -#define __ALPHA_CONSOLE_HH__ - -#include "base/range.hh" -#include "dev/alpha/access.h" -#include "dev/io_device.hh" -#include "params/AlphaConsole.hh" -#include "sim/host.hh" -#include "sim/sim_object.hh" - -class BaseCPU; -class Terminal; -class AlphaSystem; -class SimpleDisk; - -/** - * Memory mapped interface to the system console. This device - * represents a shared data region between the OS Kernel and the - * System Console. - * - * The system console is a small standalone program that is initially - * run when the system boots. It contains the necessary code to - * access the boot disk, to read/write from the console, and to pass - * boot parameters to the kernel. - * - * This version of the system console is very different from the one - * that would be found in a real system. Many of the functions use - * some sort of backdoor to get their job done. For example, reading - * from the boot device on a real system would require a minimal - * device driver to access the disk controller, but since we have a - * simulator here, we are able to bypass the disk controller and - * access the disk image directly. There are also some things like - * reading the kernel off the disk image into memory that are normally - * taken care of by the console that are now taken care of by the - * simulator. - * - * These shortcuts are acceptable since the system console is - * primarily used doing boot before the kernel has loaded its device - * drivers. - */ -class AlphaConsole : public BasicPioDevice -{ - protected: - struct Access : public AlphaAccess - { - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); - }; - - union { - Access *alphaAccess; - uint8_t *consoleData; - }; - - /** the disk must be accessed from the console */ - SimpleDisk *disk; - - /** the system console (the terminal) is accessable from the console */ - Terminal *terminal; - - /** a pointer to the system we are running in */ - AlphaSystem *system; - - /** a pointer to the CPU boot cpu */ - BaseCPU *cpu; - - public: - typedef AlphaConsoleParams Params; - AlphaConsole(const Params *p); - - const Params * - params() const - { - return dynamic_cast(_params); - } - - virtual void startup(); - - /** - * memory mapped reads and writes - */ - virtual Tick read(PacketPtr pkt); - virtual Tick write(PacketPtr pkt); - - /** - * standard serialization routines for checkpointing - */ - virtual void serialize(std::ostream &os); - virtual void unserialize(Checkpoint *cp, const std::string §ion); -}; - -#endif // __ALPHA_CONSOLE_HH__ -- cgit v1.2.3 From 9dc4e2952cf34a794c18c7b98010c0b496123f9e Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Tue, 17 Jun 2008 20:39:51 -0700 Subject: rename MipsConsole to MipsBackdoor --HG-- rename : src/dev/mips/MipsConsole.py => src/dev/mips/MipsBackdoor.py rename : src/dev/mips/console.cc => src/dev/mips/backdoor.cc rename : src/dev/mips/console.hh => src/dev/mips/backdoor.hh --- src/dev/mips/Malta.py | 11 +- src/dev/mips/MipsBackdoor.py | 38 ++++++ src/dev/mips/MipsConsole.py | 38 ------ src/dev/mips/SConscript | 4 +- src/dev/mips/backdoor.cc | 297 +++++++++++++++++++++++++++++++++++++++++++ src/dev/mips/backdoor.hh | 126 ++++++++++++++++++ src/dev/mips/console.cc | 297 ------------------------------------------- src/dev/mips/console.hh | 126 ------------------ 8 files changed, 469 insertions(+), 468 deletions(-) create mode 100644 src/dev/mips/MipsBackdoor.py delete mode 100644 src/dev/mips/MipsConsole.py create mode 100755 src/dev/mips/backdoor.cc create mode 100755 src/dev/mips/backdoor.hh delete mode 100755 src/dev/mips/console.cc delete mode 100755 src/dev/mips/console.hh (limited to 'src') diff --git a/src/dev/mips/Malta.py b/src/dev/mips/Malta.py index d321a6361..d215bf329 100755 --- a/src/dev/mips/Malta.py +++ b/src/dev/mips/Malta.py @@ -28,12 +28,13 @@ from m5.params import * from m5.proxy import * + +from BadDevice import BadDevice from Device import BasicPioDevice +from MipsBackdoor import MipsBackdoor +from Pci import PciConfigAll from Platform import Platform -from MipsConsole import MipsConsole from Uart import Uart8250 -from Pci import PciConfigAll -from BadDevice import BadDevice class MaltaCChip(BasicPioDevice): type = 'MaltaCChip' @@ -56,7 +57,7 @@ class Malta(Platform): cchip = MaltaCChip(pio_addr=0x801a0000000) io = MaltaIO(pio_addr=0x801fc000000) uart = Uart8250(pio_addr=0xBFD003F8) - console = MipsConsole(pio_addr=0xBFD00F00, disk=Parent.simple_disk) + backdoor = MipsBackdoor(pio_addr=0xBFD00F00, disk=Parent.simple_disk) # Attach I/O devices to specified bus object. Can't do this # earlier, since the bus object itself is typically defined at the @@ -65,4 +66,4 @@ class Malta(Platform): self.cchip.pio = bus.port self.io.pio = bus.port self.uart.pio = bus.port - self.console.pio = bus.port + self.backdoor.pio = bus.port diff --git a/src/dev/mips/MipsBackdoor.py b/src/dev/mips/MipsBackdoor.py new file mode 100644 index 000000000..f65250238 --- /dev/null +++ b/src/dev/mips/MipsBackdoor.py @@ -0,0 +1,38 @@ +# Copyright (c) 2007 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Korey Sewell + +from m5.params import * +from m5.proxy import * +from Device import BasicPioDevice + +class MipsBackdoor(BasicPioDevice): + type = 'MipsBackdoor' + cpu = Param.BaseCPU(Parent.cpu[0], "Processor") + disk = Param.SimpleDisk("Simple Disk") + terminal = Param.Terminal(Parent.any, "The console terminal") + system = Param.MipsSystem(Parent.any, "system object") diff --git a/src/dev/mips/MipsConsole.py b/src/dev/mips/MipsConsole.py deleted file mode 100644 index 8b724991a..000000000 --- a/src/dev/mips/MipsConsole.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (c) 2007 The Regents of The University of Michigan -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer; -# redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution; -# neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Authors: Korey Sewell - -from m5.params import * -from m5.proxy import * -from Device import BasicPioDevice - -class MipsConsole(BasicPioDevice): - type = 'MipsConsole' - cpu = Param.BaseCPU(Parent.cpu[0], "Processor") - disk = Param.SimpleDisk("Simple Disk") - terminal = Param.Terminal(Parent.any, "The console terminal") - system = Param.MipsSystem(Parent.any, "system object") diff --git a/src/dev/mips/SConscript b/src/dev/mips/SConscript index 22e91ff09..e83e47ebd 100755 --- a/src/dev/mips/SConscript +++ b/src/dev/mips/SConscript @@ -32,13 +32,13 @@ Import('*') if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'mips': - SimObject('MipsConsole.py') + SimObject('MipsBackdoor.py') SimObject('Malta.py') TraceFlag('Malta') TraceFlag('MC146818') - Source('console.cc') + Source('backdoor.cc') Source('malta.cc') Source('malta_cchip.cc') Source('malta_io.cc') diff --git a/src/dev/mips/backdoor.cc b/src/dev/mips/backdoor.cc new file mode 100755 index 000000000..313f12567 --- /dev/null +++ b/src/dev/mips/backdoor.cc @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2001-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Ali Saidi + * Steve Reinhardt + * Erik Hallnor + */ + +/** @file + * Mips Console Backdoor Definition + */ +#include +#include + +#include "arch/mips/system.hh" +#include "base/inifile.hh" +#include "base/str.hh" +#include "base/trace.hh" +#include "cpu/base.hh" +#include "cpu/thread_context.hh" +#include "dev/mips/backdoor.hh" +#include "dev/platform.hh" +#include "dev/simple_disk.hh" +#include "dev/terminal.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" +#include "mem/physical.hh" +#include "params/MipsBackdoor.hh" +#include "sim/sim_object.hh" + + +using namespace std; +using namespace MipsISA; + +MipsBackdoor::MipsBackdoor(const Params *p) + : BasicPioDevice(p), disk(p->disk), terminal(p->terminal), + system(p->system), cpu(p->cpu) +{ + + pioSize = sizeof(struct MipsAccess); + + mipsAccess = new Access(); + mipsAccess->last_offset = pioSize - 1; + + mipsAccess->version = MIPS_ACCESS_VERSION; + mipsAccess->diskUnit = 1; + + mipsAccess->diskCount = 0; + mipsAccess->diskPAddr = 0; + mipsAccess->diskBlock = 0; + mipsAccess->diskOperation = 0; + mipsAccess->outputChar = 0; + mipsAccess->inputChar = 0; + bzero(mipsAccess->cpuStack, sizeof(mipsAccess->cpuStack)); + +} + +void +MipsBackdoor::startup() +{ + system->setMipsAccess(pioAddr); + mipsAccess->numCPUs = system->getNumCPUs(); + mipsAccess->kernStart = MipsISA::Phys2K0Seg(system->getKernelStart()); + mipsAccess->kernEnd = MipsISA::Phys2K0Seg(system->getKernelEnd()); + mipsAccess->entryPoint = MipsISA::Phys2K0Seg(system->getKernelEntry()); + mipsAccess->mem_size = system->physmem->size(); + mipsAccess->cpuClock = cpu->frequency() / 1000000; // In MHz + mipsAccess->intrClockFrequency = params()->platform->intrFrequency(); +} + +Tick +MipsBackdoor::read(PacketPtr pkt) +{ + + /** XXX Do we want to push the addr munging to a bus brige or something? So + * the device has it's physical address and then the bridge adds on whatever + * machine dependent address swizzle is required? + */ + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); + + Addr daddr = pkt->getAddr() - pioAddr; + + pkt->allocate(); + + switch (pkt->getSize()) + { + case sizeof(uint32_t): + switch (daddr) + { + case offsetof(MipsAccess, last_offset): + pkt->set(mipsAccess->last_offset); + break; + case offsetof(MipsAccess, version): + pkt->set(mipsAccess->version); + break; + case offsetof(MipsAccess, numCPUs): + pkt->set(mipsAccess->numCPUs); + break; + case offsetof(MipsAccess, intrClockFrequency): + pkt->set(mipsAccess->intrClockFrequency); + break; + case offsetof(MipsAccess, inputChar): + pkt->set(terminal->console_in()); + break; + case offsetof(MipsAccess, cpuClock): + pkt->set(mipsAccess->cpuClock); + break; + case offsetof(MipsAccess, mem_size): + pkt->set(mipsAccess->mem_size); + break; + case offsetof(MipsAccess, kernStart): + pkt->set(mipsAccess->kernStart); + break; + case offsetof(MipsAccess, kernEnd): + pkt->set(mipsAccess->kernEnd); + break; + case offsetof(MipsAccess, entryPoint): + pkt->set(mipsAccess->entryPoint); + break; + case offsetof(MipsAccess, diskUnit): + pkt->set(mipsAccess->diskUnit); + break; + case offsetof(MipsAccess, diskCount): + pkt->set(mipsAccess->diskCount); + break; + case offsetof(MipsAccess, diskPAddr): + pkt->set(mipsAccess->diskPAddr); + break; + case offsetof(MipsAccess, diskBlock): + pkt->set(mipsAccess->diskBlock); + break; + case offsetof(MipsAccess, diskOperation): + pkt->set(mipsAccess->diskOperation); + break; + case offsetof(MipsAccess, outputChar): + pkt->set(mipsAccess->outputChar); + break; + default: + int cpunum = (daddr - offsetof(MipsAccess, cpuStack)) / + sizeof(mipsAccess->cpuStack[0]); + + if (cpunum >= 0 && cpunum < 64) + pkt->set(mipsAccess->cpuStack[cpunum]); + else + panic("Unknown 32bit access, %#x\n", daddr); + } + //DPRINTF(MipsBackdoor, "read: offset=%#x val=%#x\n", daddr, + // pkt->get()); + break; + default: + pkt->setBadAddress(); + } + + pkt->makeAtomicResponse(); + return pioDelay; +} + +Tick +MipsBackdoor::write(PacketPtr pkt) +{ + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); + Addr daddr = pkt->getAddr() - pioAddr; + + uint32_t val = pkt->get(); + assert(pkt->getSize() == sizeof(uint32_t)); + switch (daddr) { + case offsetof(MipsAccess, diskUnit): + mipsAccess->diskUnit = val; + break; + + case offsetof(MipsAccess, diskCount): + mipsAccess->diskCount = val; + break; + + case offsetof(MipsAccess, diskPAddr): + mipsAccess->diskPAddr = val; + break; + + case offsetof(MipsAccess, diskBlock): + mipsAccess->diskBlock = val; + break; + + case offsetof(MipsAccess, diskOperation): + if (val == 0x13) + disk->read(mipsAccess->diskPAddr, mipsAccess->diskBlock, + mipsAccess->diskCount); + else + panic("Invalid disk operation!"); + + break; + + case offsetof(MipsAccess, outputChar): + terminal->out((char)(val & 0xff)); + break; + + default: + int cpunum = (daddr - offsetof(MipsAccess, cpuStack)) / + sizeof(mipsAccess->cpuStack[0]); + warn("%d: Trying to launch CPU number %d!", curTick, cpunum); + assert(val > 0 && "Must not access primary cpu"); + if (cpunum >= 0 && cpunum < 64) + mipsAccess->cpuStack[cpunum] = val; + else + panic("Unknown 32bit access, %#x\n", daddr); + } + + pkt->makeAtomicResponse(); + + return pioDelay; +} + +void +MipsBackdoor::Access::serialize(ostream &os) +{ + SERIALIZE_SCALAR(last_offset); + SERIALIZE_SCALAR(version); + SERIALIZE_SCALAR(numCPUs); + SERIALIZE_SCALAR(mem_size); + SERIALIZE_SCALAR(cpuClock); + SERIALIZE_SCALAR(intrClockFrequency); + SERIALIZE_SCALAR(kernStart); + SERIALIZE_SCALAR(kernEnd); + SERIALIZE_SCALAR(entryPoint); + SERIALIZE_SCALAR(diskUnit); + SERIALIZE_SCALAR(diskCount); + SERIALIZE_SCALAR(diskPAddr); + SERIALIZE_SCALAR(diskBlock); + SERIALIZE_SCALAR(diskOperation); + SERIALIZE_SCALAR(outputChar); + SERIALIZE_SCALAR(inputChar); + SERIALIZE_ARRAY(cpuStack,64); +} + +void +MipsBackdoor::Access::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_SCALAR(last_offset); + UNSERIALIZE_SCALAR(version); + UNSERIALIZE_SCALAR(numCPUs); + UNSERIALIZE_SCALAR(mem_size); + UNSERIALIZE_SCALAR(cpuClock); + UNSERIALIZE_SCALAR(intrClockFrequency); + UNSERIALIZE_SCALAR(kernStart); + UNSERIALIZE_SCALAR(kernEnd); + UNSERIALIZE_SCALAR(entryPoint); + UNSERIALIZE_SCALAR(diskUnit); + UNSERIALIZE_SCALAR(diskCount); + UNSERIALIZE_SCALAR(diskPAddr); + UNSERIALIZE_SCALAR(diskBlock); + UNSERIALIZE_SCALAR(diskOperation); + UNSERIALIZE_SCALAR(outputChar); + UNSERIALIZE_SCALAR(inputChar); + UNSERIALIZE_ARRAY(cpuStack, 64); +} + +void +MipsBackdoor::serialize(ostream &os) +{ + mipsAccess->serialize(os); +} + +void +MipsBackdoor::unserialize(Checkpoint *cp, const std::string §ion) +{ + mipsAccess->unserialize(cp, section); +} + +MipsBackdoor * +MipsBackdoorParams::create() +{ + return new MipsBackdoor(this); +} diff --git a/src/dev/mips/backdoor.hh b/src/dev/mips/backdoor.hh new file mode 100755 index 000000000..b8cc0ae46 --- /dev/null +++ b/src/dev/mips/backdoor.hh @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2001-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +/** @file + * System Console Backdoor Interface + */ + +#ifndef __DEV_MIPS_BACKDOOR_HH__ +#define __DEV_MIPS_BACKDOOR_HH__ + +#include "base/range.hh" +#include "dev/mips/access.h" +#include "dev/io_device.hh" +#include "params/MipsBackdoor.hh" +#include "sim/host.hh" +#include "sim/sim_object.hh" + +class BaseCPU; +class Terminal; +class MipsSystem; +class SimpleDisk; + +/** + * Memory mapped interface to the system console. This device + * represents a shared data region between the OS Kernel and the + * System Console Backdoor. + * + * The system console is a small standalone program that is initially + * run when the system boots. It contains the necessary code to + * access the boot disk, to read/write from the console, and to pass + * boot parameters to the kernel. + * + * This version of the system console is very different from the one + * that would be found in a real system. Many of the functions use + * some sort of backdoor to get their job done. For example, reading + * from the boot device on a real system would require a minimal + * device driver to access the disk controller, but since we have a + * simulator here, we are able to bypass the disk controller and + * access the disk image directly. There are also some things like + * reading the kernel off the disk image into memory that are normally + * taken care of by the console that are now taken care of by the + * simulator. + * + * These shortcuts are acceptable since the system console is + * primarily used doing boot before the kernel has loaded its device + * drivers. + */ +class MipsBackdoor : public BasicPioDevice +{ + protected: + struct Access : public MipsAccess + { + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); + }; + + union { + Access *mipsAccess; + uint8_t *consoleData; + }; + + /** the disk must be accessed from the console */ + SimpleDisk *disk; + + /** the system terminal is accessable from the console */ + Terminal *terminal; + + /** a pointer to the system we are running in */ + MipsSystem *system; + + /** a pointer to the CPU boot cpu */ + BaseCPU *cpu; + + public: + typedef MipsBackdoorParams Params; + MipsBackdoor(const Params *p); + + const Params * + params() const + { + return dynamic_cast(_params); + } + + virtual void startup(); + + /** + * memory mapped reads and writes + */ + virtual Tick read(PacketPtr pkt); + virtual Tick write(PacketPtr pkt); + + /** + * standard serialization routines for checkpointing + */ + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); +}; + +#endif // __DEV_MIPS_BACKDOOR_HH__ diff --git a/src/dev/mips/console.cc b/src/dev/mips/console.cc deleted file mode 100755 index d1663999a..000000000 --- a/src/dev/mips/console.cc +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright (c) 2001-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Nathan Binkert - * Ali Saidi - * Steve Reinhardt - * Erik Hallnor - */ - -/** @file - * Mips Console Definition - */ -#include -#include - -#include "arch/mips/system.hh" -#include "base/inifile.hh" -#include "base/str.hh" -#include "base/trace.hh" -#include "cpu/base.hh" -#include "cpu/thread_context.hh" -#include "dev/mips/console.hh" -#include "dev/platform.hh" -#include "dev/simple_disk.hh" -#include "dev/terminal.hh" -#include "mem/packet.hh" -#include "mem/packet_access.hh" -#include "mem/physical.hh" -#include "params/MipsConsole.hh" -#include "sim/sim_object.hh" - - -using namespace std; -using namespace MipsISA; - -MipsConsole::MipsConsole(const Params *p) - : BasicPioDevice(p), disk(p->disk), terminal(p->terminal), - system(p->system), cpu(p->cpu) -{ - - pioSize = sizeof(struct MipsAccess); - - mipsAccess = new Access(); - mipsAccess->last_offset = pioSize - 1; - - mipsAccess->version = MIPS_ACCESS_VERSION; - mipsAccess->diskUnit = 1; - - mipsAccess->diskCount = 0; - mipsAccess->diskPAddr = 0; - mipsAccess->diskBlock = 0; - mipsAccess->diskOperation = 0; - mipsAccess->outputChar = 0; - mipsAccess->inputChar = 0; - bzero(mipsAccess->cpuStack, sizeof(mipsAccess->cpuStack)); - -} - -void -MipsConsole::startup() -{ - system->setMipsAccess(pioAddr); - mipsAccess->numCPUs = system->getNumCPUs(); - mipsAccess->kernStart = MipsISA::Phys2K0Seg(system->getKernelStart()); - mipsAccess->kernEnd = MipsISA::Phys2K0Seg(system->getKernelEnd()); - mipsAccess->entryPoint = MipsISA::Phys2K0Seg(system->getKernelEntry()); - mipsAccess->mem_size = system->physmem->size(); - mipsAccess->cpuClock = cpu->frequency() / 1000000; // In MHz - mipsAccess->intrClockFrequency = params()->platform->intrFrequency(); -} - -Tick -MipsConsole::read(PacketPtr pkt) -{ - - /** XXX Do we want to push the addr munging to a bus brige or something? So - * the device has it's physical address and then the bridge adds on whatever - * machine dependent address swizzle is required? - */ - assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); - - Addr daddr = pkt->getAddr() - pioAddr; - - pkt->allocate(); - - switch (pkt->getSize()) - { - case sizeof(uint32_t): - switch (daddr) - { - case offsetof(MipsAccess, last_offset): - pkt->set(mipsAccess->last_offset); - break; - case offsetof(MipsAccess, version): - pkt->set(mipsAccess->version); - break; - case offsetof(MipsAccess, numCPUs): - pkt->set(mipsAccess->numCPUs); - break; - case offsetof(MipsAccess, intrClockFrequency): - pkt->set(mipsAccess->intrClockFrequency); - break; - case offsetof(MipsAccess, inputChar): - pkt->set(terminal->console_in()); - break; - case offsetof(MipsAccess, cpuClock): - pkt->set(mipsAccess->cpuClock); - break; - case offsetof(MipsAccess, mem_size): - pkt->set(mipsAccess->mem_size); - break; - case offsetof(MipsAccess, kernStart): - pkt->set(mipsAccess->kernStart); - break; - case offsetof(MipsAccess, kernEnd): - pkt->set(mipsAccess->kernEnd); - break; - case offsetof(MipsAccess, entryPoint): - pkt->set(mipsAccess->entryPoint); - break; - case offsetof(MipsAccess, diskUnit): - pkt->set(mipsAccess->diskUnit); - break; - case offsetof(MipsAccess, diskCount): - pkt->set(mipsAccess->diskCount); - break; - case offsetof(MipsAccess, diskPAddr): - pkt->set(mipsAccess->diskPAddr); - break; - case offsetof(MipsAccess, diskBlock): - pkt->set(mipsAccess->diskBlock); - break; - case offsetof(MipsAccess, diskOperation): - pkt->set(mipsAccess->diskOperation); - break; - case offsetof(MipsAccess, outputChar): - pkt->set(mipsAccess->outputChar); - break; - default: - int cpunum = (daddr - offsetof(MipsAccess, cpuStack)) / - sizeof(mipsAccess->cpuStack[0]); - - if (cpunum >= 0 && cpunum < 64) - pkt->set(mipsAccess->cpuStack[cpunum]); - else - panic("Unknown 32bit access, %#x\n", daddr); - } - //DPRINTF(MipsConsole, "read: offset=%#x val=%#x\n", daddr, - // pkt->get()); - break; - default: - pkt->setBadAddress(); - } - - pkt->makeAtomicResponse(); - return pioDelay; -} - -Tick -MipsConsole::write(PacketPtr pkt) -{ - assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); - Addr daddr = pkt->getAddr() - pioAddr; - - uint32_t val = pkt->get(); - assert(pkt->getSize() == sizeof(uint32_t)); - switch (daddr) { - case offsetof(MipsAccess, diskUnit): - mipsAccess->diskUnit = val; - break; - - case offsetof(MipsAccess, diskCount): - mipsAccess->diskCount = val; - break; - - case offsetof(MipsAccess, diskPAddr): - mipsAccess->diskPAddr = val; - break; - - case offsetof(MipsAccess, diskBlock): - mipsAccess->diskBlock = val; - break; - - case offsetof(MipsAccess, diskOperation): - if (val == 0x13) - disk->read(mipsAccess->diskPAddr, mipsAccess->diskBlock, - mipsAccess->diskCount); - else - panic("Invalid disk operation!"); - - break; - - case offsetof(MipsAccess, outputChar): - terminal->out((char)(val & 0xff)); - break; - - default: - int cpunum = (daddr - offsetof(MipsAccess, cpuStack)) / - sizeof(mipsAccess->cpuStack[0]); - warn("%d: Trying to launch CPU number %d!", curTick, cpunum); - assert(val > 0 && "Must not access primary cpu"); - if (cpunum >= 0 && cpunum < 64) - mipsAccess->cpuStack[cpunum] = val; - else - panic("Unknown 32bit access, %#x\n", daddr); - } - - pkt->makeAtomicResponse(); - - return pioDelay; -} - -void -MipsConsole::Access::serialize(ostream &os) -{ - SERIALIZE_SCALAR(last_offset); - SERIALIZE_SCALAR(version); - SERIALIZE_SCALAR(numCPUs); - SERIALIZE_SCALAR(mem_size); - SERIALIZE_SCALAR(cpuClock); - SERIALIZE_SCALAR(intrClockFrequency); - SERIALIZE_SCALAR(kernStart); - SERIALIZE_SCALAR(kernEnd); - SERIALIZE_SCALAR(entryPoint); - SERIALIZE_SCALAR(diskUnit); - SERIALIZE_SCALAR(diskCount); - SERIALIZE_SCALAR(diskPAddr); - SERIALIZE_SCALAR(diskBlock); - SERIALIZE_SCALAR(diskOperation); - SERIALIZE_SCALAR(outputChar); - SERIALIZE_SCALAR(inputChar); - SERIALIZE_ARRAY(cpuStack,64); -} - -void -MipsConsole::Access::unserialize(Checkpoint *cp, const std::string §ion) -{ - UNSERIALIZE_SCALAR(last_offset); - UNSERIALIZE_SCALAR(version); - UNSERIALIZE_SCALAR(numCPUs); - UNSERIALIZE_SCALAR(mem_size); - UNSERIALIZE_SCALAR(cpuClock); - UNSERIALIZE_SCALAR(intrClockFrequency); - UNSERIALIZE_SCALAR(kernStart); - UNSERIALIZE_SCALAR(kernEnd); - UNSERIALIZE_SCALAR(entryPoint); - UNSERIALIZE_SCALAR(diskUnit); - UNSERIALIZE_SCALAR(diskCount); - UNSERIALIZE_SCALAR(diskPAddr); - UNSERIALIZE_SCALAR(diskBlock); - UNSERIALIZE_SCALAR(diskOperation); - UNSERIALIZE_SCALAR(outputChar); - UNSERIALIZE_SCALAR(inputChar); - UNSERIALIZE_ARRAY(cpuStack, 64); -} - -void -MipsConsole::serialize(ostream &os) -{ - mipsAccess->serialize(os); -} - -void -MipsConsole::unserialize(Checkpoint *cp, const std::string §ion) -{ - mipsAccess->unserialize(cp, section); -} - -MipsConsole * -MipsConsoleParams::create() -{ - return new MipsConsole(this); -} diff --git a/src/dev/mips/console.hh b/src/dev/mips/console.hh deleted file mode 100755 index a78343f35..000000000 --- a/src/dev/mips/console.hh +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2001-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Nathan Binkert - */ - -/** @file - * System Console Interface - */ - -#ifndef __MIPS_CONSOLE_HH__ -#define __MIPS_CONSOLE_HH__ - -#include "base/range.hh" -#include "dev/mips/access.h" -#include "dev/io_device.hh" -#include "params/MipsConsole.hh" -#include "sim/host.hh" -#include "sim/sim_object.hh" - -class BaseCPU; -class Terminal; -class MipsSystem; -class SimpleDisk; - -/** - * Memory mapped interface to the system console. This device - * represents a shared data region between the OS Kernel and the - * System Console. - * - * The system console is a small standalone program that is initially - * run when the system boots. It contains the necessary code to - * access the boot disk, to read/write from the console, and to pass - * boot parameters to the kernel. - * - * This version of the system console is very different from the one - * that would be found in a real system. Many of the functions use - * some sort of backdoor to get their job done. For example, reading - * from the boot device on a real system would require a minimal - * device driver to access the disk controller, but since we have a - * simulator here, we are able to bypass the disk controller and - * access the disk image directly. There are also some things like - * reading the kernel off the disk image into memory that are normally - * taken care of by the console that are now taken care of by the - * simulator. - * - * These shortcuts are acceptable since the system console is - * primarily used doing boot before the kernel has loaded its device - * drivers. - */ -class MipsConsole : public BasicPioDevice -{ - protected: - struct Access : public MipsAccess - { - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); - }; - - union { - Access *mipsAccess; - uint8_t *consoleData; - }; - - /** the disk must be accessed from the console */ - SimpleDisk *disk; - - /** the system terminal is accessable from the console */ - Terminal *terminal; - - /** a pointer to the system we are running in */ - MipsSystem *system; - - /** a pointer to the CPU boot cpu */ - BaseCPU *cpu; - - public: - typedef MipsConsoleParams Params; - MipsConsole(const Params *p); - - const Params * - params() const - { - return dynamic_cast(_params); - } - - virtual void startup(); - - /** - * memory mapped reads and writes - */ - virtual Tick read(PacketPtr pkt); - virtual Tick write(PacketPtr pkt); - - /** - * standard serialization routines for checkpointing - */ - virtual void serialize(std::ostream &os); - virtual void unserialize(Checkpoint *cp, const std::string §ion); -}; - -#endif // __MIPS_CONSOLE_HH__ -- cgit v1.2.3 From 163465ac08674125fed1d4e843cab6c1c2bf2033 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Tue, 17 Jun 2008 21:11:20 -0700 Subject: ThreadState: Ensure that kernelStats is properly initialized --- src/cpu/simple_thread.cc | 5 +---- src/cpu/thread_state.cc | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index 93772fbe1..5a5444de4 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -86,11 +86,8 @@ SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys, profileNode = &dummyNode; profilePC = 3; - if (use_kernel_stats) { + if (use_kernel_stats) kernelStats = new TheISA::Kernel::Statistics(system); - } else { - kernelStats = NULL; - } } #else SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, Process *_process, diff --git a/src/cpu/thread_state.cc b/src/cpu/thread_state.cc index be8f822f2..bcfc9c924 100644 --- a/src/cpu/thread_state.cc +++ b/src/cpu/thread_state.cc @@ -46,7 +46,7 @@ ThreadState::ThreadState(BaseCPU *cpu, int _cpuId, int _tid) : baseCpu(cpu), cpuId(_cpuId), tid(_tid), lastActivate(0), lastSuspend(0), profile(NULL), profileNode(NULL), profilePC(0), quiesceEvent(NULL), - physPort(NULL), virtPort(NULL), + kernelStats(NULL), physPort(NULL), virtPort(NULL), microPC(0), nextMicroPC(1), funcExeInst(0), storeCondFailures(0) #else ThreadState::ThreadState(BaseCPU *cpu, int _cpuId, int _tid, Process *_process, -- cgit v1.2.3 From 8042b8f4c75164c6c6d5a71e171bc7193b85057a Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Tue, 17 Jun 2008 21:34:27 -0700 Subject: PacketFifo: Get slack out of the EthPacketData structure. This allows a packet to exist in multiple FIFOs if desired. --- src/dev/etherpkt.cc | 2 - src/dev/etherpkt.hh | 17 +++------ src/dev/pktfifo.cc | 55 +++++++++++++++++--------- src/dev/pktfifo.hh | 108 +++++++++++++++++++++++++++++++++++----------------- src/dev/sinic.cc | 6 +-- 5 files changed, 119 insertions(+), 69 deletions(-) (limited to 'src') diff --git a/src/dev/etherpkt.cc b/src/dev/etherpkt.cc index 5c552b4bd..2c8343eb0 100644 --- a/src/dev/etherpkt.cc +++ b/src/dev/etherpkt.cc @@ -40,7 +40,6 @@ void EthPacketData::serialize(const string &base, ostream &os) { paramOut(os, base + ".length", length); - paramOut(os, base + ".slack", slack); arrayParamOut(os, base + ".data", data, length); } @@ -49,7 +48,6 @@ EthPacketData::unserialize(const string &base, Checkpoint *cp, const string §ion) { paramIn(cp, section, base + ".length", length); - paramIn(cp, section, base + ".slack", slack); if (length) arrayParamIn(cp, section, base + ".data", data, length); } diff --git a/src/dev/etherpkt.hh b/src/dev/etherpkt.hh index db2e0d6b5..623895ba8 100644 --- a/src/dev/etherpkt.hh +++ b/src/dev/etherpkt.hh @@ -60,24 +60,17 @@ class EthPacketData : public RefCounted */ int length; - /* - * Extra space taken up by the packet in whatever data structure - * it is in. - * - * NOTE: This can only be use by *one* data structure at a time! - */ - int slack; - public: - EthPacketData() : data(NULL), length(0), slack(0) + EthPacketData() + : data(NULL), length(0) { } explicit EthPacketData(size_t size) - : data(new uint8_t[size]), length(0), slack(0) + : data(new uint8_t[size]), length(0) { } - EthPacketData(std::auto_ptr d, int l, int s = 0) - : data(d.release()), length(l), slack(s) + EthPacketData(std::auto_ptr d, int l) + : data(d.release()), length(l) { } ~EthPacketData() { if (data) delete [] data; } diff --git a/src/dev/pktfifo.cc b/src/dev/pktfifo.cc index 37f7ff680..97d6c04af 100644 --- a/src/dev/pktfifo.cc +++ b/src/dev/pktfifo.cc @@ -40,29 +40,50 @@ PacketFifo::copyout(void *dest, int offset, int len) if (offset + len >= size()) return false; - list::iterator p = fifo.begin(); - list::iterator end = fifo.end(); + iterator i = fifo.begin(); + iterator end = fifo.end(); while (len > 0) { - while (offset >= (*p)->length) { - offset -= (*p)->length; - ++p; + EthPacketPtr &pkt = i->packet; + while (offset >= pkt->length) { + offset -= pkt->length; + ++i; } - if (p == end) + if (i == end) panic("invalid fifo"); - int size = min((*p)->length - offset, len); - memcpy(data, (*p)->data, size); + int size = min(pkt->length - offset, len); + memcpy(data, pkt->data, size); offset = 0; len -= size; data += size; - ++p; + ++i; } return true; } +void +PacketFifoEntry::serialize(const string &base, ostream &os) +{ + packet->serialize(base + ".packet", os); + paramOut(os, base + ".slack", slack); + paramOut(os, base + ".number", number); + paramOut(os, base + ".priv", priv); +} + +void +PacketFifoEntry::unserialize(const string &base, Checkpoint *cp, + const string §ion) +{ + packet = new EthPacketData(16384); + packet->unserialize(base + ".packet", cp, section); + paramIn(cp, section, base + ".slack", slack); + paramIn(cp, section, base + ".number", number); + paramIn(cp, section, base + ".priv", priv); +} + void PacketFifo::serialize(const string &base, ostream &os) { @@ -72,11 +93,11 @@ PacketFifo::serialize(const string &base, ostream &os) paramOut(os, base + ".packets", fifo.size()); int i = 0; - list::iterator p = fifo.begin(); - list::iterator end = fifo.end(); - while (p != end) { - (*p)->serialize(csprintf("%s.packet%d", base, i), os); - ++p; + iterator entry = fifo.begin(); + iterator end = fifo.end(); + while (entry != end) { + entry->serialize(csprintf("%s.entry%d", base, i), os); + ++entry; ++i; } } @@ -94,8 +115,8 @@ PacketFifo::unserialize(const string &base, Checkpoint *cp, fifo.clear(); for (int i = 0; i < fifosize; ++i) { - EthPacketPtr p = new EthPacketData(16384); - p->unserialize(csprintf("%s.packet%d", base, i), cp, section); - fifo.push_back(p); + PacketFifoEntry entry; + entry.unserialize(csprintf("%s.entry%d", base, i), cp, section); + fifo.push_back(entry); } } diff --git a/src/dev/pktfifo.hh b/src/dev/pktfifo.hh index 45157ba41..6ded248be 100644 --- a/src/dev/pktfifo.hh +++ b/src/dev/pktfifo.hh @@ -39,20 +39,59 @@ #include "sim/serialize.hh" class Checkpoint; + +struct PacketFifoEntry +{ + EthPacketPtr packet; + uint64_t number; + int slack; + int priv; + + PacketFifoEntry() + { + clear(); + } + + PacketFifoEntry(const PacketFifoEntry &s) + : packet(s.packet), number(s.number), slack(s.slack), priv(s.priv) + { + } + + PacketFifoEntry(EthPacketPtr p, uint64_t n) + : packet(p), number(n), slack(0), priv(-1) + { + } + + void clear() + { + packet = NULL; + number = 0; + slack = 0; + priv = -1; + } + + void serialize(const std::string &base, std::ostream &os); + void unserialize(const std::string &base, Checkpoint *cp, + const std::string §ion); +}; + class PacketFifo { public: - typedef std::list fifo_list; + + typedef std::list fifo_list; typedef fifo_list::iterator iterator; protected: - std::list fifo; + std::list fifo; + uint64_t _counter; int _maxsize; int _size; int _reserved; public: - explicit PacketFifo(int max) : _maxsize(max), _size(0), _reserved(0) {} + explicit PacketFifo(int max) + : _counter(0), _maxsize(max), _size(0), _reserved(0) {} virtual ~PacketFifo() {} int packets() const { return fifo.size(); } @@ -73,18 +112,21 @@ class PacketFifo iterator begin() { return fifo.begin(); } iterator end() { return fifo.end(); } - EthPacketPtr front() { return fifo.front(); } + EthPacketPtr front() { return fifo.begin()->packet; } bool push(EthPacketPtr ptr) { assert(ptr->length); assert(_reserved <= ptr->length); - assert(ptr->slack == 0); if (avail() < ptr->length - _reserved) return false; _size += ptr->length; - fifo.push_back(ptr); + + PacketFifoEntry entry; + entry.packet = ptr; + entry.number = _counter++; + fifo.push_back(entry); _reserved = 0; return true; } @@ -94,18 +136,17 @@ class PacketFifo if (empty()) return; - EthPacketPtr &packet = fifo.front(); - _size -= packet->length; - _size -= packet->slack; - packet->slack = 0; - packet = NULL; + iterator entry = fifo.begin(); + _size -= entry->packet->length; + _size -= entry->slack; + entry->packet = NULL; fifo.pop_front(); } void clear() { for (iterator i = begin(); i != end(); ++i) - (*i)->slack = 0; + i->clear(); fifo.clear(); _size = 0; _reserved = 0; @@ -113,51 +154,48 @@ class PacketFifo void remove(iterator i) { - EthPacketPtr &packet = *i; if (i != fifo.begin()) { iterator prev = i; --prev; assert(prev != fifo.end()); - (*prev)->slack += packet->length; + prev->slack += i->packet->length; + prev->slack += i->slack; } else { - _size -= packet->length; - _size -= packet->slack; + _size -= i->packet->length; + _size -= i->slack; } - packet->slack = 0; - packet = NULL; + i->clear(); fifo.erase(i); } bool copyout(void *dest, int offset, int len); - int countPacketsBefore(iterator end) + int countPacketsBefore(iterator i) { - iterator i = fifo.begin(); - int count = 0; - - while (i != end) { - ++count; - ++i; - } - - return count; + if (i == fifo.end()) + return 0; + return i->number - fifo.begin()->number; } int countPacketsAfter(iterator i) { iterator end = fifo.end(); - int count = 0; + if (i == end) + return 0; + return (--end)->number - i->number; + } - while (i != end) { - ++count; - ++i; - } + void check() + { + int total = 0; + for (iterator i = begin(); i != end(); ++i) + total += i->packet->length + i->slack; - return count; + if (total != _size) + panic("total (%d) is not == to size (%d)\n", total, _size); } - /** * Serialization stuff */ diff --git a/src/dev/sinic.cc b/src/dev/sinic.cc index c63966528..e875a8bcc 100644 --- a/src/dev/sinic.cc +++ b/src/dev/sinic.cc @@ -893,12 +893,12 @@ Device::rxKick() // Grab a new packet from the fifo. vnic->rxPacket = rxFifoPtr++; vnic->rxPacketOffset = 0; - vnic->rxPacketBytes = (*vnic->rxPacket)->length; + vnic->rxPacketBytes = vnic->rxPacket->packet->length; assert(vnic->rxPacketBytes); vnic->rxDoneData = 0; /* scope for variables */ { - IpPtr ip(*vnic->rxPacket); + IpPtr ip(vnic->rxPacket->packet); if (ip) { DPRINTF(Ethernet, "ID is %d\n", ip->id()); vnic->rxDoneData |= Regs::RxDone_IpPacket; @@ -941,7 +941,7 @@ Device::rxKick() Regs::get_RxData_Addr(vnic->RxData)); rxDmaLen = std::min(Regs::get_RxData_Len(vnic->RxData), vnic->rxPacketBytes); - rxDmaData = (*vnic->rxPacket)->data + vnic->rxPacketOffset; + rxDmaData = vnic->rxPacket->packet->data + vnic->rxPacketOffset; rxState = rxCopy; if (rxDmaAddr == 1LL) { rxState = rxCopyDone; -- cgit v1.2.3 From 87d03d00cd204346efb162c89375be724707e5a6 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Tue, 17 Jun 2008 22:14:12 -0700 Subject: inet: initialization fixes. Make sure variables are properly initialized and also make sure that truth testing works properly. --- src/base/inet.hh | 80 ++++++++++++++++++++++++------------------------------ src/dev/ns_gige.cc | 33 ++++++++++++++++------ 2 files changed, 59 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/base/inet.hh b/src/base/inet.hh index 1bf7c585f..e88c0f75f 100644 --- a/src/base/inet.hh +++ b/src/base/inet.hh @@ -179,32 +179,31 @@ class IpPtr friend class UdpPtr; EthPacketPtr p; - const IpHdr *h() const - { return (const IpHdr *)(p->data + sizeof(eth_hdr)); } - IpHdr *h() { return (IpHdr *)(p->data + sizeof(eth_hdr)); } - void set(const EthPacketPtr &ptr) { - EthHdr *eth = (EthHdr *)ptr->data; - if (eth->type() == ETH_TYPE_IP) - p = ptr; - else - p = 0; + p = 0; + + if (ptr) { + EthHdr *eth = (EthHdr *)ptr->data; + if (eth->type() == ETH_TYPE_IP) + p = ptr; + } } public: - IpPtr() {} - IpPtr(const EthPacketPtr &ptr) { set(ptr); } - IpPtr(const EthPtr &ptr) { set(ptr.p); } + IpPtr() : p(0) {} + IpPtr(const EthPacketPtr &ptr) : p(0) { set(ptr); } + IpPtr(const EthPtr &ptr) : p(0) { set(ptr.p); } IpPtr(const IpPtr &ptr) : p(ptr.p) { } - IpHdr *operator->() { return h(); } - IpHdr &operator*() { return *h(); } - operator IpHdr *() { return h(); } + IpHdr *get() { return (IpHdr *)(p->data + sizeof(eth_hdr)); } + IpHdr *operator->() { return get(); } + IpHdr &operator*() { return *get(); } - const IpHdr *operator->() const { return h(); } - const IpHdr &operator*() const { return *h(); } - operator const IpHdr *() const { return h(); } + const IpHdr *get() const + { return (const IpHdr *)(p->data + sizeof(eth_hdr)); } + const IpHdr *operator->() const { return get(); } + const IpHdr &operator*() const { return *get(); } const IpPtr &operator=(const EthPacketPtr &ptr) { set(ptr); return *this; } const IpPtr &operator=(const EthPtr &ptr) { set(ptr.p); return *this; } @@ -214,7 +213,6 @@ class IpPtr EthPacketPtr packet() { return p; } bool operator!() const { return !p; } operator bool() const { return p; } - operator bool() { return p; } }; uint16_t cksum(const IpPtr &ptr); @@ -278,30 +276,27 @@ class TcpPtr EthPacketPtr p; int off; - const TcpHdr *h() const { return (const TcpHdr *)(p->data + off); } - TcpHdr *h() { return (TcpHdr *)(p->data + off); } - void set(const EthPacketPtr &ptr, int offset) { p = ptr; off = offset; } void set(const IpPtr &ptr) { - if (ptr->proto() == IP_PROTO_TCP) + if (ptr && ptr->proto() == IP_PROTO_TCP) set(ptr.p, sizeof(eth_hdr) + ptr->hlen()); else set(0, 0); } public: - TcpPtr() {} - TcpPtr(const IpPtr &ptr) { set(ptr); } + TcpPtr() : p(0), off(0) {} + TcpPtr(const IpPtr &ptr) : p(0), off(0) { set(ptr); } TcpPtr(const TcpPtr &ptr) : p(ptr.p), off(ptr.off) {} - TcpHdr *operator->() { return h(); } - TcpHdr &operator*() { return *h(); } - operator TcpHdr *() { return h(); } + TcpHdr *get() { return (TcpHdr *)(p->data + off); } + TcpHdr *operator->() { return get(); } + TcpHdr &operator*() { return *get(); } - const TcpHdr *operator->() const { return h(); } - const TcpHdr &operator*() const { return *h(); } - operator const TcpHdr *() const { return h(); } + const TcpHdr *get() const { return (const TcpHdr *)(p->data + off); } + const TcpHdr *operator->() const { return get(); } + const TcpHdr &operator*() const { return *get(); } const TcpPtr &operator=(const IpPtr &i) { set(i); return *this; } const TcpPtr &operator=(const TcpPtr &t) { set(t.p, t.off); return *this; } @@ -310,7 +305,6 @@ class TcpPtr EthPacketPtr packet() { return p; } bool operator!() const { return !p; } operator bool() const { return p; } - operator bool() { return p; } }; uint16_t cksum(const TcpPtr &ptr); @@ -368,30 +362,27 @@ class UdpPtr EthPacketPtr p; int off; - const UdpHdr *h() const { return (const UdpHdr *)(p->data + off); } - UdpHdr *h() { return (UdpHdr *)(p->data + off); } - void set(const EthPacketPtr &ptr, int offset) { p = ptr; off = offset; } void set(const IpPtr &ptr) { - if (ptr->proto() == IP_PROTO_UDP) + if (ptr && ptr->proto() == IP_PROTO_UDP) set(ptr.p, sizeof(eth_hdr) + ptr->hlen()); else set(0, 0); } public: - UdpPtr() {} - UdpPtr(const IpPtr &ptr) { set(ptr); } + UdpPtr() : p(0), off(0) {} + UdpPtr(const IpPtr &ptr) : p(0), off(0) { set(ptr); } UdpPtr(const UdpPtr &ptr) : p(ptr.p), off(ptr.off) {} - UdpHdr *operator->() { return h(); } - UdpHdr &operator*() { return *h(); } - operator UdpHdr *() { return h(); } + UdpHdr *get() { return (UdpHdr *)(p->data + off); } + UdpHdr *operator->() { return get(); } + UdpHdr &operator*() { return *get(); } - const UdpHdr *operator->() const { return h(); } - const UdpHdr &operator*() const { return *h(); } - operator const UdpHdr *() const { return h(); } + const UdpHdr *get() const { return (const UdpHdr *)(p->data + off); } + const UdpHdr *operator->() const { return get(); } + const UdpHdr &operator*() const { return *get(); } const UdpPtr &operator=(const IpPtr &i) { set(i); return *this; } const UdpPtr &operator=(const UdpPtr &t) { set(t.p, t.off); return *this; } @@ -400,7 +391,6 @@ class UdpPtr EthPacketPtr packet() { return p; } bool operator!() const { return !p; } operator bool() const { return p; } - operator bool() { return p; } }; uint16_t cksum(const UdpPtr &ptr); diff --git a/src/dev/ns_gige.cc b/src/dev/ns_gige.cc index bd48bdca5..5767d8c79 100644 --- a/src/dev/ns_gige.cc +++ b/src/dev/ns_gige.cc @@ -2036,19 +2036,34 @@ NSGigE::txKick() IpPtr ip(txPacket); if (extsts & EXTSTS_UDPPKT) { UdpPtr udp(ip); - udp->sum(0); - udp->sum(cksum(udp)); - txUdpChecksums++; + if (udp) { + udp->sum(0); + udp->sum(cksum(udp)); + txUdpChecksums++; + } else { + debug_break(); + warn_once("UDPPKT set, but not UDP!\n"); + } } else if (extsts & EXTSTS_TCPPKT) { TcpPtr tcp(ip); - tcp->sum(0); - tcp->sum(cksum(tcp)); - txTcpChecksums++; + if (tcp) { + tcp->sum(0); + tcp->sum(cksum(tcp)); + txTcpChecksums++; + } else { + debug_break(); + warn_once("TCPPKT set, but not UDP!\n"); + } } if (extsts & EXTSTS_IPPKT) { - ip->sum(0); - ip->sum(cksum(ip)); - txIpChecksums++; + if (ip) { + ip->sum(0); + ip->sum(cksum(ip)); + txIpChecksums++; + } else { + debug_break(); + warn_once("IPPKT set, but not UDP!\n"); + } } } -- cgit v1.2.3 From 1099a9838abcb158b47714c800a9666eb82c97ea Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Tue, 17 Jun 2008 22:22:44 -0700 Subject: Ethernet: share statistics between all ethernet devices and apply some of those statistics to the e1000 model. --- src/dev/SConscript | 1 + src/dev/etherdevice.cc | 367 +++++++++++++++++++++++++++++++++++++++++++++++++ src/dev/etherdevice.hh | 54 ++++++++ src/dev/i8254xGBe.cc | 14 ++ src/dev/i8254xGBe.hh | 1 - src/dev/ns_gige.cc | 340 +-------------------------------------------- src/dev/ns_gige.hh | 55 -------- 7 files changed, 437 insertions(+), 395 deletions(-) create mode 100644 src/dev/etherdevice.cc (limited to 'src') diff --git a/src/dev/SConscript b/src/dev/SConscript index 82fa5cb02..54148b68b 100644 --- a/src/dev/SConscript +++ b/src/dev/SConscript @@ -46,6 +46,7 @@ if env['FULL_SYSTEM']: Source('baddev.cc') Source('disk_image.cc') Source('etherbus.cc') + Source('etherdevice.cc') Source('etherdump.cc') Source('etherint.cc') Source('etherlink.cc') diff --git a/src/dev/etherdevice.cc b/src/dev/etherdevice.cc new file mode 100644 index 000000000..5341c02c4 --- /dev/null +++ b/src/dev/etherdevice.cc @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Lisa Hsu + */ + +#include "dev/etherdevice.hh" +#include "sim/stats.hh" + +void +EtherDevice::regStats() +{ + txBytes + .name(name() + ".txBytes") + .desc("Bytes Transmitted") + .prereq(txBytes) + ; + + rxBytes + .name(name() + ".rxBytes") + .desc("Bytes Received") + .prereq(rxBytes) + ; + + txPackets + .name(name() + ".txPackets") + .desc("Number of Packets Transmitted") + .prereq(txBytes) + ; + + rxPackets + .name(name() + ".rxPackets") + .desc("Number of Packets Received") + .prereq(rxBytes) + ; + + txIpChecksums + .name(name() + ".txIpChecksums") + .desc("Number of tx IP Checksums done by device") + .precision(0) + .prereq(txBytes) + ; + + rxIpChecksums + .name(name() + ".rxIpChecksums") + .desc("Number of rx IP Checksums done by device") + .precision(0) + .prereq(rxBytes) + ; + + txTcpChecksums + .name(name() + ".txTcpChecksums") + .desc("Number of tx TCP Checksums done by device") + .precision(0) + .prereq(txBytes) + ; + + rxTcpChecksums + .name(name() + ".rxTcpChecksums") + .desc("Number of rx TCP Checksums done by device") + .precision(0) + .prereq(rxBytes) + ; + + txUdpChecksums + .name(name() + ".txUdpChecksums") + .desc("Number of tx UDP Checksums done by device") + .precision(0) + .prereq(txBytes) + ; + + rxUdpChecksums + .name(name() + ".rxUdpChecksums") + .desc("Number of rx UDP Checksums done by device") + .precision(0) + .prereq(rxBytes) + ; + + descDmaReads + .name(name() + ".descDMAReads") + .desc("Number of descriptors the device read w/ DMA") + .precision(0) + ; + + descDmaWrites + .name(name() + ".descDMAWrites") + .desc("Number of descriptors the device wrote w/ DMA") + .precision(0) + ; + + descDmaRdBytes + .name(name() + ".descDmaReadBytes") + .desc("number of descriptor bytes read w/ DMA") + .precision(0) + ; + + descDmaWrBytes + .name(name() + ".descDmaWriteBytes") + .desc("number of descriptor bytes write w/ DMA") + .precision(0) + ; + + txBandwidth + .name(name() + ".txBandwidth") + .desc("Transmit Bandwidth (bits/s)") + .precision(0) + .prereq(txBytes) + ; + + rxBandwidth + .name(name() + ".rxBandwidth") + .desc("Receive Bandwidth (bits/s)") + .precision(0) + .prereq(rxBytes) + ; + + totBandwidth + .name(name() + ".totBandwidth") + .desc("Total Bandwidth (bits/s)") + .precision(0) + .prereq(totBytes) + ; + + totPackets + .name(name() + ".totPackets") + .desc("Total Packets") + .precision(0) + .prereq(totBytes) + ; + + totBytes + .name(name() + ".totBytes") + .desc("Total Bytes") + .precision(0) + .prereq(totBytes) + ; + + totPacketRate + .name(name() + ".totPPS") + .desc("Total Tranmission Rate (packets/s)") + .precision(0) + .prereq(totBytes) + ; + + txPacketRate + .name(name() + ".txPPS") + .desc("Packet Tranmission Rate (packets/s)") + .precision(0) + .prereq(txBytes) + ; + + rxPacketRate + .name(name() + ".rxPPS") + .desc("Packet Reception Rate (packets/s)") + .precision(0) + .prereq(rxBytes) + ; + + postedSwi + .name(name() + ".postedSwi") + .desc("number of software interrupts posted to CPU") + .precision(0) + ; + + totalSwi + .name(name() + ".totalSwi") + .desc("total number of Swi written to ISR") + .precision(0) + ; + + coalescedSwi + .name(name() + ".coalescedSwi") + .desc("average number of Swi's coalesced into each post") + .precision(0) + ; + + postedRxIdle + .name(name() + ".postedRxIdle") + .desc("number of rxIdle interrupts posted to CPU") + .precision(0) + ; + + totalRxIdle + .name(name() + ".totalRxIdle") + .desc("total number of RxIdle written to ISR") + .precision(0) + ; + + coalescedRxIdle + .name(name() + ".coalescedRxIdle") + .desc("average number of RxIdle's coalesced into each post") + .precision(0) + ; + + postedRxOk + .name(name() + ".postedRxOk") + .desc("number of RxOk interrupts posted to CPU") + .precision(0) + ; + + totalRxOk + .name(name() + ".totalRxOk") + .desc("total number of RxOk written to ISR") + .precision(0) + ; + + coalescedRxOk + .name(name() + ".coalescedRxOk") + .desc("average number of RxOk's coalesced into each post") + .precision(0) + ; + + postedRxDesc + .name(name() + ".postedRxDesc") + .desc("number of RxDesc interrupts posted to CPU") + .precision(0) + ; + + totalRxDesc + .name(name() + ".totalRxDesc") + .desc("total number of RxDesc written to ISR") + .precision(0) + ; + + coalescedRxDesc + .name(name() + ".coalescedRxDesc") + .desc("average number of RxDesc's coalesced into each post") + .precision(0) + ; + + postedTxOk + .name(name() + ".postedTxOk") + .desc("number of TxOk interrupts posted to CPU") + .precision(0) + ; + + totalTxOk + .name(name() + ".totalTxOk") + .desc("total number of TxOk written to ISR") + .precision(0) + ; + + coalescedTxOk + .name(name() + ".coalescedTxOk") + .desc("average number of TxOk's coalesced into each post") + .precision(0) + ; + + postedTxIdle + .name(name() + ".postedTxIdle") + .desc("number of TxIdle interrupts posted to CPU") + .precision(0) + ; + + totalTxIdle + .name(name() + ".totalTxIdle") + .desc("total number of TxIdle written to ISR") + .precision(0) + ; + + coalescedTxIdle + .name(name() + ".coalescedTxIdle") + .desc("average number of TxIdle's coalesced into each post") + .precision(0) + ; + + postedTxDesc + .name(name() + ".postedTxDesc") + .desc("number of TxDesc interrupts posted to CPU") + .precision(0) + ; + + totalTxDesc + .name(name() + ".totalTxDesc") + .desc("total number of TxDesc written to ISR") + .precision(0) + ; + + coalescedTxDesc + .name(name() + ".coalescedTxDesc") + .desc("average number of TxDesc's coalesced into each post") + .precision(0) + ; + + postedRxOrn + .name(name() + ".postedRxOrn") + .desc("number of RxOrn posted to CPU") + .precision(0) + ; + + totalRxOrn + .name(name() + ".totalRxOrn") + .desc("total number of RxOrn written to ISR") + .precision(0) + ; + + coalescedRxOrn + .name(name() + ".coalescedRxOrn") + .desc("average number of RxOrn's coalesced into each post") + .precision(0) + ; + + coalescedTotal + .name(name() + ".coalescedTotal") + .desc("average number of interrupts coalesced into each post") + .precision(0) + ; + + postedInterrupts + .name(name() + ".postedInterrupts") + .desc("number of posts to CPU") + .precision(0) + ; + + droppedPackets + .name(name() + ".droppedPackets") + .desc("number of packets dropped") + .precision(0) + ; + + coalescedSwi = totalSwi / postedInterrupts; + coalescedRxIdle = totalRxIdle / postedInterrupts; + coalescedRxOk = totalRxOk / postedInterrupts; + coalescedRxDesc = totalRxDesc / postedInterrupts; + coalescedTxOk = totalTxOk / postedInterrupts; + coalescedTxIdle = totalTxIdle / postedInterrupts; + coalescedTxDesc = totalTxDesc / postedInterrupts; + coalescedRxOrn = totalRxOrn / postedInterrupts; + + coalescedTotal = (totalSwi + totalRxIdle + totalRxOk + totalRxDesc + + totalTxOk + totalTxIdle + totalTxDesc + + totalRxOrn) / postedInterrupts; + + txBandwidth = txBytes * Stats::constant(8) / simSeconds; + rxBandwidth = rxBytes * Stats::constant(8) / simSeconds; + totBandwidth = txBandwidth + rxBandwidth; + totBytes = txBytes + rxBytes; + totPackets = txPackets + rxPackets; + + txPacketRate = txPackets / simSeconds; + rxPacketRate = rxPackets / simSeconds; +} diff --git a/src/dev/etherdevice.hh b/src/dev/etherdevice.hh index a0df0d741..e43f3b686 100644 --- a/src/dev/etherdevice.hh +++ b/src/dev/etherdevice.hh @@ -36,6 +36,7 @@ #ifndef __DEV_ETHERDEVICE_HH__ #define __DEV_ETHERDEVICE_HH__ +#include "base/statistics.hh" #include "dev/pcidev.hh" #include "params/EtherDevice.hh" #include "sim/sim_object.hh" @@ -64,6 +65,59 @@ class EtherDevice : public PciDev /** Additional function to return the Port of a memory object. */ virtual EtherInt *getEthPort(const std::string &if_name, int idx = -1) = 0; + public: + void regStats(); + + protected: + Stats::Scalar<> txBytes; + Stats::Scalar<> rxBytes; + Stats::Scalar<> txPackets; + Stats::Scalar<> rxPackets; + Stats::Scalar<> txIpChecksums; + Stats::Scalar<> rxIpChecksums; + Stats::Scalar<> txTcpChecksums; + Stats::Scalar<> rxTcpChecksums; + Stats::Scalar<> txUdpChecksums; + Stats::Scalar<> rxUdpChecksums; + Stats::Scalar<> descDmaReads; + Stats::Scalar<> descDmaWrites; + Stats::Scalar<> descDmaRdBytes; + Stats::Scalar<> descDmaWrBytes; + Stats::Formula totBandwidth; + Stats::Formula totPackets; + Stats::Formula totBytes; + Stats::Formula totPacketRate; + Stats::Formula txBandwidth; + Stats::Formula rxBandwidth; + Stats::Formula txPacketRate; + Stats::Formula rxPacketRate; + Stats::Scalar<> postedSwi; + Stats::Formula coalescedSwi; + Stats::Scalar<> totalSwi; + Stats::Scalar<> postedRxIdle; + Stats::Formula coalescedRxIdle; + Stats::Scalar<> totalRxIdle; + Stats::Scalar<> postedRxOk; + Stats::Formula coalescedRxOk; + Stats::Scalar<> totalRxOk; + Stats::Scalar<> postedRxDesc; + Stats::Formula coalescedRxDesc; + Stats::Scalar<> totalRxDesc; + Stats::Scalar<> postedTxOk; + Stats::Formula coalescedTxOk; + Stats::Scalar<> totalTxOk; + Stats::Scalar<> postedTxIdle; + Stats::Formula coalescedTxIdle; + Stats::Scalar<> totalTxIdle; + Stats::Scalar<> postedTxDesc; + Stats::Formula coalescedTxDesc; + Stats::Scalar<> totalTxDesc; + Stats::Scalar<> postedRxOrn; + Stats::Formula coalescedRxOrn; + Stats::Scalar<> totalRxOrn; + Stats::Formula coalescedTotal; + Stats::Scalar<> postedInterrupts; + Stats::Scalar<> droppedPackets; }; #endif //__DEV_ETHERDEVICE_HH__ diff --git a/src/dev/i8254xGBe.cc b/src/dev/i8254xGBe.cc index ff255d5f7..3b1970432 100644 --- a/src/dev/i8254xGBe.cc +++ b/src/dev/i8254xGBe.cc @@ -584,6 +584,7 @@ IGbE::postInterrupt(IntTypes t, bool now) if (interEvent.scheduled()) { interEvent.deschedule(); } + postedInterrupts++; cpuPostInt(); } else { DPRINTF(EthernetIntr, "EINT: Scheduling timer interrupt for %d ticks\n", @@ -740,6 +741,7 @@ IGbE::RxDescCache::pktComplete() DPRINTF(EthernetDesc, "Checking IP checksum\n"); status |= RXDS_IPCS; desc->csum = htole(cksum(ip)); + igbe->rxIpChecksums++; if (cksum(ip) != 0) { err |= RXDE_IPE; DPRINTF(EthernetDesc, "Checksum is bad!!\n"); @@ -750,6 +752,7 @@ IGbE::RxDescCache::pktComplete() DPRINTF(EthernetDesc, "Checking TCP checksum\n"); status |= RXDS_TCPCS; desc->csum = htole(cksum(tcp)); + igbe->rxTcpChecksums++; if (cksum(tcp) != 0) { DPRINTF(EthernetDesc, "Checksum is bad!!\n"); err |= RXDE_TCPE; @@ -761,6 +764,7 @@ IGbE::RxDescCache::pktComplete() DPRINTF(EthernetDesc, "Checking UDP checksum\n"); status |= RXDS_UDPCS; desc->csum = htole(cksum(udp)); + igbe->rxUdpChecksums++; if (cksum(udp) != 0) { DPRINTF(EthernetDesc, "Checksum is bad!!\n"); err |= RXDE_TCPE; @@ -994,6 +998,7 @@ IGbE::TxDescCache::pktComplete() if (TxdOp::ixsm(desc)) { ip->sum(0); ip->sum(cksum(ip)); + igbe->txIpChecksums++; DPRINTF(EthernetDesc, "Calculated IP checksum\n"); } if (TxdOp::txsm(desc)) { @@ -1002,11 +1007,13 @@ IGbE::TxDescCache::pktComplete() if (tcp) { tcp->sum(0); tcp->sum(cksum(tcp)); + igbe->txTcpChecksums++; DPRINTF(EthernetDesc, "Calculated TCP checksum\n"); } else if (udp) { assert(udp); udp->sum(0); udp->sum(cksum(udp)); + igbe->txUdpChecksums++; DPRINTF(EthernetDesc, "Calculated UDP checksum\n"); } else { panic("Told to checksum, but don't know how\n"); @@ -1247,6 +1254,9 @@ IGbE::txStateMachine() bool IGbE::ethRxPkt(EthPacketPtr pkt) { + rxBytes += pkt->length; + rxPackets++; + DPRINTF(Ethernet, "RxFIFO: Receiving pcakte from wire\n"); if (!regs.rctl.en()) { @@ -1380,6 +1390,10 @@ IGbE::txWire() } DPRINTF(EthernetSM, "TxFIFO: Successful transmit, bytes available in fifo: %d\n", txFifo.avail()); + + txBytes += txFifo.front()->length; + txPackets++; + txFifo.pop(); } else { // We'll get woken up when the packet ethTxDone() gets called diff --git a/src/dev/i8254xGBe.hh b/src/dev/i8254xGBe.hh index 0daf094c1..7957eb515 100644 --- a/src/dev/i8254xGBe.hh +++ b/src/dev/i8254xGBe.hh @@ -39,7 +39,6 @@ #include #include "base/inet.hh" -#include "base/statistics.hh" #include "dev/etherdevice.hh" #include "dev/etherint.hh" #include "dev/etherpkt.hh" diff --git a/src/dev/ns_gige.cc b/src/dev/ns_gige.cc index 5767d8c79..f19ca20e5 100644 --- a/src/dev/ns_gige.cc +++ b/src/dev/ns_gige.cc @@ -46,7 +46,6 @@ #include "params/NSGigE.hh" #include "sim/debug.hh" #include "sim/host.hh" -#include "sim/stats.hh" #include "sim/system.hh" const char *NsRxStateStrings[] = @@ -131,341 +130,6 @@ NSGigE::NSGigE(Params *p) NSGigE::~NSGigE() {} -void -NSGigE::regStats() -{ - txBytes - .name(name() + ".txBytes") - .desc("Bytes Transmitted") - .prereq(txBytes) - ; - - rxBytes - .name(name() + ".rxBytes") - .desc("Bytes Received") - .prereq(rxBytes) - ; - - txPackets - .name(name() + ".txPackets") - .desc("Number of Packets Transmitted") - .prereq(txBytes) - ; - - rxPackets - .name(name() + ".rxPackets") - .desc("Number of Packets Received") - .prereq(rxBytes) - ; - - txIpChecksums - .name(name() + ".txIpChecksums") - .desc("Number of tx IP Checksums done by device") - .precision(0) - .prereq(txBytes) - ; - - rxIpChecksums - .name(name() + ".rxIpChecksums") - .desc("Number of rx IP Checksums done by device") - .precision(0) - .prereq(rxBytes) - ; - - txTcpChecksums - .name(name() + ".txTcpChecksums") - .desc("Number of tx TCP Checksums done by device") - .precision(0) - .prereq(txBytes) - ; - - rxTcpChecksums - .name(name() + ".rxTcpChecksums") - .desc("Number of rx TCP Checksums done by device") - .precision(0) - .prereq(rxBytes) - ; - - txUdpChecksums - .name(name() + ".txUdpChecksums") - .desc("Number of tx UDP Checksums done by device") - .precision(0) - .prereq(txBytes) - ; - - rxUdpChecksums - .name(name() + ".rxUdpChecksums") - .desc("Number of rx UDP Checksums done by device") - .precision(0) - .prereq(rxBytes) - ; - - descDmaReads - .name(name() + ".descDMAReads") - .desc("Number of descriptors the device read w/ DMA") - .precision(0) - ; - - descDmaWrites - .name(name() + ".descDMAWrites") - .desc("Number of descriptors the device wrote w/ DMA") - .precision(0) - ; - - descDmaRdBytes - .name(name() + ".descDmaReadBytes") - .desc("number of descriptor bytes read w/ DMA") - .precision(0) - ; - - descDmaWrBytes - .name(name() + ".descDmaWriteBytes") - .desc("number of descriptor bytes write w/ DMA") - .precision(0) - ; - - txBandwidth - .name(name() + ".txBandwidth") - .desc("Transmit Bandwidth (bits/s)") - .precision(0) - .prereq(txBytes) - ; - - rxBandwidth - .name(name() + ".rxBandwidth") - .desc("Receive Bandwidth (bits/s)") - .precision(0) - .prereq(rxBytes) - ; - - totBandwidth - .name(name() + ".totBandwidth") - .desc("Total Bandwidth (bits/s)") - .precision(0) - .prereq(totBytes) - ; - - totPackets - .name(name() + ".totPackets") - .desc("Total Packets") - .precision(0) - .prereq(totBytes) - ; - - totBytes - .name(name() + ".totBytes") - .desc("Total Bytes") - .precision(0) - .prereq(totBytes) - ; - - totPacketRate - .name(name() + ".totPPS") - .desc("Total Tranmission Rate (packets/s)") - .precision(0) - .prereq(totBytes) - ; - - txPacketRate - .name(name() + ".txPPS") - .desc("Packet Tranmission Rate (packets/s)") - .precision(0) - .prereq(txBytes) - ; - - rxPacketRate - .name(name() + ".rxPPS") - .desc("Packet Reception Rate (packets/s)") - .precision(0) - .prereq(rxBytes) - ; - - postedSwi - .name(name() + ".postedSwi") - .desc("number of software interrupts posted to CPU") - .precision(0) - ; - - totalSwi - .name(name() + ".totalSwi") - .desc("total number of Swi written to ISR") - .precision(0) - ; - - coalescedSwi - .name(name() + ".coalescedSwi") - .desc("average number of Swi's coalesced into each post") - .precision(0) - ; - - postedRxIdle - .name(name() + ".postedRxIdle") - .desc("number of rxIdle interrupts posted to CPU") - .precision(0) - ; - - totalRxIdle - .name(name() + ".totalRxIdle") - .desc("total number of RxIdle written to ISR") - .precision(0) - ; - - coalescedRxIdle - .name(name() + ".coalescedRxIdle") - .desc("average number of RxIdle's coalesced into each post") - .precision(0) - ; - - postedRxOk - .name(name() + ".postedRxOk") - .desc("number of RxOk interrupts posted to CPU") - .precision(0) - ; - - totalRxOk - .name(name() + ".totalRxOk") - .desc("total number of RxOk written to ISR") - .precision(0) - ; - - coalescedRxOk - .name(name() + ".coalescedRxOk") - .desc("average number of RxOk's coalesced into each post") - .precision(0) - ; - - postedRxDesc - .name(name() + ".postedRxDesc") - .desc("number of RxDesc interrupts posted to CPU") - .precision(0) - ; - - totalRxDesc - .name(name() + ".totalRxDesc") - .desc("total number of RxDesc written to ISR") - .precision(0) - ; - - coalescedRxDesc - .name(name() + ".coalescedRxDesc") - .desc("average number of RxDesc's coalesced into each post") - .precision(0) - ; - - postedTxOk - .name(name() + ".postedTxOk") - .desc("number of TxOk interrupts posted to CPU") - .precision(0) - ; - - totalTxOk - .name(name() + ".totalTxOk") - .desc("total number of TxOk written to ISR") - .precision(0) - ; - - coalescedTxOk - .name(name() + ".coalescedTxOk") - .desc("average number of TxOk's coalesced into each post") - .precision(0) - ; - - postedTxIdle - .name(name() + ".postedTxIdle") - .desc("number of TxIdle interrupts posted to CPU") - .precision(0) - ; - - totalTxIdle - .name(name() + ".totalTxIdle") - .desc("total number of TxIdle written to ISR") - .precision(0) - ; - - coalescedTxIdle - .name(name() + ".coalescedTxIdle") - .desc("average number of TxIdle's coalesced into each post") - .precision(0) - ; - - postedTxDesc - .name(name() + ".postedTxDesc") - .desc("number of TxDesc interrupts posted to CPU") - .precision(0) - ; - - totalTxDesc - .name(name() + ".totalTxDesc") - .desc("total number of TxDesc written to ISR") - .precision(0) - ; - - coalescedTxDesc - .name(name() + ".coalescedTxDesc") - .desc("average number of TxDesc's coalesced into each post") - .precision(0) - ; - - postedRxOrn - .name(name() + ".postedRxOrn") - .desc("number of RxOrn posted to CPU") - .precision(0) - ; - - totalRxOrn - .name(name() + ".totalRxOrn") - .desc("total number of RxOrn written to ISR") - .precision(0) - ; - - coalescedRxOrn - .name(name() + ".coalescedRxOrn") - .desc("average number of RxOrn's coalesced into each post") - .precision(0) - ; - - coalescedTotal - .name(name() + ".coalescedTotal") - .desc("average number of interrupts coalesced into each post") - .precision(0) - ; - - postedInterrupts - .name(name() + ".postedInterrupts") - .desc("number of posts to CPU") - .precision(0) - ; - - droppedPackets - .name(name() + ".droppedPackets") - .desc("number of packets dropped") - .precision(0) - ; - - coalescedSwi = totalSwi / postedInterrupts; - coalescedRxIdle = totalRxIdle / postedInterrupts; - coalescedRxOk = totalRxOk / postedInterrupts; - coalescedRxDesc = totalRxDesc / postedInterrupts; - coalescedTxOk = totalTxOk / postedInterrupts; - coalescedTxIdle = totalTxIdle / postedInterrupts; - coalescedTxDesc = totalTxDesc / postedInterrupts; - coalescedRxOrn = totalRxOrn / postedInterrupts; - - coalescedTotal = (totalSwi + totalRxIdle + totalRxOk + totalRxDesc + - totalTxOk + totalTxIdle + totalTxDesc + - totalRxOrn) / postedInterrupts; - - txBandwidth = txBytes * Stats::constant(8) / simSeconds; - rxBandwidth = rxBytes * Stats::constant(8) / simSeconds; - totBandwidth = txBandwidth + rxBandwidth; - totBytes = txBytes + rxBytes; - totPackets = txPackets + rxPackets; - - txPacketRate = txPackets / simSeconds; - rxPacketRate = rxPackets / simSeconds; -} - - /** * This is to write to the PCI general configuration registers */ @@ -1186,6 +850,7 @@ NSGigE::devIntrPost(uint32_t interrupts) Tick when = curTick; if ((regs.isr & regs.imr & ISR_NODELAY) == 0) when += intrDelay; + postedInterrupts++; cpuIntrPost(when); } } @@ -1226,9 +891,6 @@ NSGigE::devIntrClear(uint32_t interrupts) postedRxOrn++; } - if (regs.isr & regs.imr & ISR_IMPL) - postedInterrupts++; - interrupts &= ~ISR_NOIMPL; regs.isr &= ~interrupts; diff --git a/src/dev/ns_gige.hh b/src/dev/ns_gige.hh index dfdd81b66..a55a1c75e 100644 --- a/src/dev/ns_gige.hh +++ b/src/dev/ns_gige.hh @@ -38,7 +38,6 @@ #define __DEV_NS_GIGE_HH__ #include "base/inet.hh" -#include "base/statistics.hh" #include "dev/etherdevice.hh" #include "dev/etherint.hh" #include "dev/etherpkt.hh" @@ -372,60 +371,6 @@ class NSGigE : public EtherDevice virtual void unserialize(Checkpoint *cp, const std::string §ion); virtual void resume(); - - public: - void regStats(); - - private: - Stats::Scalar<> txBytes; - Stats::Scalar<> rxBytes; - Stats::Scalar<> txPackets; - Stats::Scalar<> rxPackets; - Stats::Scalar<> txIpChecksums; - Stats::Scalar<> rxIpChecksums; - Stats::Scalar<> txTcpChecksums; - Stats::Scalar<> rxTcpChecksums; - Stats::Scalar<> txUdpChecksums; - Stats::Scalar<> rxUdpChecksums; - Stats::Scalar<> descDmaReads; - Stats::Scalar<> descDmaWrites; - Stats::Scalar<> descDmaRdBytes; - Stats::Scalar<> descDmaWrBytes; - Stats::Formula totBandwidth; - Stats::Formula totPackets; - Stats::Formula totBytes; - Stats::Formula totPacketRate; - Stats::Formula txBandwidth; - Stats::Formula rxBandwidth; - Stats::Formula txPacketRate; - Stats::Formula rxPacketRate; - Stats::Scalar<> postedSwi; - Stats::Formula coalescedSwi; - Stats::Scalar<> totalSwi; - Stats::Scalar<> postedRxIdle; - Stats::Formula coalescedRxIdle; - Stats::Scalar<> totalRxIdle; - Stats::Scalar<> postedRxOk; - Stats::Formula coalescedRxOk; - Stats::Scalar<> totalRxOk; - Stats::Scalar<> postedRxDesc; - Stats::Formula coalescedRxDesc; - Stats::Scalar<> totalRxDesc; - Stats::Scalar<> postedTxOk; - Stats::Formula coalescedTxOk; - Stats::Scalar<> totalTxOk; - Stats::Scalar<> postedTxIdle; - Stats::Formula coalescedTxIdle; - Stats::Scalar<> totalTxIdle; - Stats::Scalar<> postedTxDesc; - Stats::Formula coalescedTxDesc; - Stats::Scalar<> totalTxDesc; - Stats::Scalar<> postedRxOrn; - Stats::Formula coalescedRxOrn; - Stats::Scalar<> totalRxOrn; - Stats::Formula coalescedTotal; - Stats::Scalar<> postedInterrupts; - Stats::Scalar<> droppedPackets; }; /* -- cgit v1.2.3 From 67a33eed40f0a551fdf9bf1059928cda1c2d7fdb Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Wed, 18 Jun 2008 10:15:21 -0700 Subject: AtomicSimpleCPU: Separate data stalls from instruction stalls. Separate simulation of icache stalls and dat stalls. --- src/cpu/simple/AtomicSimpleCPU.py | 3 ++- src/cpu/simple/atomic.cc | 39 +++++++++++++++++++++++++-------------- src/cpu/simple/atomic.hh | 6 ++++-- 3 files changed, 31 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/cpu/simple/AtomicSimpleCPU.py b/src/cpu/simple/AtomicSimpleCPU.py index 28c2aa9c9..a0b358439 100644 --- a/src/cpu/simple/AtomicSimpleCPU.py +++ b/src/cpu/simple/AtomicSimpleCPU.py @@ -33,7 +33,8 @@ from BaseCPU import BaseCPU class AtomicSimpleCPU(BaseCPU): type = 'AtomicSimpleCPU' width = Param.Int(1, "CPU width") - simulate_stalls = Param.Bool(False, "Simulate cache stall cycles") + simulate_data_stalls = Param.Bool(False, "Simulate dcache stall cycles") + simulate_inst_stalls = Param.Bool(False, "Simulate icache stall cycles") function_trace = Param.Bool(False, "Enable function trace") function_trace_start = Param.Tick(0, "Cycle to start function trace") if build_env['FULL_SYSTEM']: diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index acd280568..b25d3330f 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -153,8 +153,9 @@ AtomicSimpleCPU::DcachePort::setPeer(Port *port) } AtomicSimpleCPU::AtomicSimpleCPU(Params *p) - : BaseSimpleCPU(p), tickEvent(this), - width(p->width), simulate_stalls(p->simulate_stalls), + : BaseSimpleCPU(p), tickEvent(this), width(p->width), + simulate_data_stalls(p->simulate_data_stalls), + simulate_inst_stalls(p->simulate_inst_stalls), icachePort(name() + "-iport", this), dcachePort(name() + "-iport", this), physmemPort(name() + "-iport", this), hasPhysMemPort(false) { @@ -711,7 +712,7 @@ AtomicSimpleCPU::tick() { DPRINTF(SimpleCPU, "Tick\n"); - Tick latency = ticks(1); // instruction takes one cycle by default + Tick latency = 0; for (int i = 0; i < width; ++i) { numCycles++; @@ -769,16 +770,21 @@ AtomicSimpleCPU::tick() curStaticInst->isFirstMicroop())) instCnt++; - if (simulate_stalls) { - Tick icache_stall = - icache_access ? icache_latency - ticks(1) : 0; - Tick dcache_stall = - dcache_access ? dcache_latency - ticks(1) : 0; - Tick stall_cycles = (icache_stall + dcache_stall) / ticks(1); - if (ticks(stall_cycles) < (icache_stall + dcache_stall)) - latency += ticks(stall_cycles+1); - else - latency += ticks(stall_cycles); + Tick stall_ticks = 0; + if (simulate_inst_stalls && icache_access) + stall_ticks += icache_latency; + + if (simulate_data_stalls && dcache_access) + stall_ticks += dcache_latency; + + if (stall_ticks) { + Tick stall_cycles = stall_ticks / ticks(1); + Tick aligned_stall_ticks = ticks(stall_cycles); + + if (aligned_stall_ticks < stall_ticks) + aligned_stall_ticks += 1; + + latency += aligned_stall_ticks; } } @@ -786,6 +792,10 @@ AtomicSimpleCPU::tick() advancePC(fault); } + // instruction takes at least one cycle + if (latency < ticks(1)) + latency = ticks(1); + if (_status != Idle) tickEvent.schedule(curTick + latency); } @@ -819,7 +829,8 @@ AtomicSimpleCPUParams::create() params->functionTrace = function_trace; params->functionTraceStart = function_trace_start; params->width = width; - params->simulate_stalls = simulate_stalls; + params->simulate_data_stalls = simulate_data_stalls; + params->simulate_inst_stalls = simulate_inst_stalls; params->system = system; params->cpu_id = cpu_id; params->tracer = tracer; diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh index 19bc0e13b..ccea15073 100644 --- a/src/cpu/simple/atomic.hh +++ b/src/cpu/simple/atomic.hh @@ -39,7 +39,8 @@ class AtomicSimpleCPU : public BaseSimpleCPU struct Params : public BaseSimpleCPU::Params { int width; - bool simulate_stalls; + bool simulate_data_stalls; + bool simulate_inst_stalls; }; AtomicSimpleCPU(Params *params); @@ -74,7 +75,8 @@ class AtomicSimpleCPU : public BaseSimpleCPU TickEvent tickEvent; const int width; - const bool simulate_stalls; + const bool simulate_data_stalls; + const bool simulate_inst_stalls; // main simulation loop (one cycle) void tick(); -- cgit v1.2.3 From c1584e422783a33731c7dfa23517d30bcecf28bc Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Wed, 18 Jun 2008 12:07:15 -0700 Subject: imported patch sim_object_params.diff --- src/python/generate.py | 1 + src/python/m5/SimObject.py | 19 +++++++++++------- src/sim/sim_object_params.hh | 48 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 7 deletions(-) create mode 100644 src/sim/sim_object_params.hh (limited to 'src') diff --git a/src/python/generate.py b/src/python/generate.py index e6c36ecd2..7b69ad876 100644 --- a/src/python/generate.py +++ b/src/python/generate.py @@ -300,6 +300,7 @@ class Generate(object): print >>out, code + print >>out, '%%include "src/sim/sim_object_params.hh"' % obj for obj in ordered_objs: print >>out, '%%include "params/%s.hh"' % obj diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index 41ed3df9e..4cf0f7a3d 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -396,13 +396,21 @@ class MetaSimObject(type): code += '#include "enums/%s.hh"\n' % ptype.__name__ code += "\n\n" + code += cls.cxx_struct(base, params) + + # close #ifndef __PARAMS__* guard + code += "\n#endif\n" + return code + + def cxx_struct(cls, base, params): + if cls == SimObject: + return '#include "sim/sim_object_params.hh"\n' + # now generate the actual param struct - code += "struct %sParams" % cls + code = "struct %sParams" % cls if base: code += " : public %sParams" % base code += "\n{\n" - if cls == SimObject: - code += " virtual ~%sParams() {}\n" % cls if not hasattr(cls, 'abstract') or not cls.abstract: if 'type' in cls.__dict__: code += " %s create();\n" % cls.cxx_type @@ -411,8 +419,6 @@ class MetaSimObject(type): code += "".join([" %s\n" % d for d in decls]) code += "};\n" - # close #ifndef __PARAMS__* guard - code += "\n#endif\n" return code def cxx_type_decl(cls): @@ -483,7 +489,6 @@ class SimObject(object): type = 'SimObject' abstract = True - name = Param.String("Object name") swig_objdecls = [ '%include "python/swig/sim_object.i"' ] # Initialize new instance. For objects with SimObject-valued @@ -762,7 +767,7 @@ class SimObject(object): cc_params_struct = getattr(m5.objects.params, '%sParams' % self.type) cc_params = cc_params_struct() - cc_params.object = self + cc_params.pyobj = self cc_params.name = str(self) param_names = self._params.keys() diff --git a/src/sim/sim_object_params.hh b/src/sim/sim_object_params.hh new file mode 100644 index 000000000..4179a37bf --- /dev/null +++ b/src/sim/sim_object_params.hh @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2001-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Steve Reinhardt + * Nathan Binkert + */ + +#ifndef __SIM_SIM_OBJECT_PARAMS_HH__ +#define __SIM_SIM_OBJECT_PARAMS_HH__ + +#ifndef PY_VERSION +struct PyObject; +#endif + +struct SimObjectParams +{ + virtual ~SimObjectParams() {} + + std::string name; + PyObject *pyobj; +}; + + +#endif // __SIM_SIM_OBJECT_PARAMS_HH__ -- cgit v1.2.3 From 6b45238316052f458ba9ebc9d24a91cfa9e41cf1 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Sat, 21 Jun 2008 01:04:43 -0400 Subject: Generate more useful error messages for unconnected ports. Force all non-default ports to provide a name and an owner in the constructor. --- src/cpu/o3/fetch.hh | 4 +-- src/cpu/o3/fetch_impl.hh | 2 +- src/cpu/o3/lsq.hh | 4 +-- src/cpu/o3/lsq_impl.hh | 2 +- src/cpu/o3/thread_context_impl.hh | 1 - src/cpu/ozone/cpu_impl.hh | 1 - src/cpu/simple_thread.cc | 1 - src/cpu/thread_state.cc | 4 +-- src/mem/bridge.cc | 2 +- src/mem/bus.cc | 7 +++-- src/mem/bus.hh | 2 +- src/mem/cache/cache.hh | 2 +- src/mem/cache/cache_impl.hh | 5 +-- src/mem/mem_object.cc | 4 +-- src/mem/mem_object.hh | 10 ++++-- src/mem/port.cc | 65 +++++++++++++++++++++++++++++---------- src/mem/port.hh | 22 ++++++------- 17 files changed, 84 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index d954bd1e7..3ada0328f 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -80,8 +80,8 @@ class DefaultFetch public: /** Default constructor. */ - IcachePort(DefaultFetch *_fetch) - : Port(_fetch->name() + "-iport"), fetch(_fetch) + IcachePort(DefaultFetch *_fetch, O3CPU *_cpu) + : Port(_fetch->name() + "-iport", _cpu), fetch(_fetch) { } bool snoopRangeSent; diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 7d344fa33..ecfbacd98 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -167,7 +167,7 @@ DefaultFetch::DefaultFetch(O3CPU *_cpu, Params *params) instSize = sizeof(TheISA::MachInst); // Name is finally available, so create the port. - icachePort = new IcachePort(this); + icachePort = new IcachePort(this, cpu); icachePort->snoopRangeSent = false; diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh index 06de608e0..82d73c6ee 100644 --- a/src/cpu/o3/lsq.hh +++ b/src/cpu/o3/lsq.hh @@ -296,8 +296,8 @@ class LSQ { public: /** Default constructor. */ - DcachePort(LSQ *_lsq) - : Port(_lsq->name() + "-dport"), lsq(_lsq) + DcachePort(LSQ *_lsq, O3CPU *_cpu) + : Port(_lsq->name() + "-dport", _cpu), lsq(_lsq) { } bool snoopRangeSent; diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh index 8ed6f7f54..41ab66dd0 100644 --- a/src/cpu/o3/lsq_impl.hh +++ b/src/cpu/o3/lsq_impl.hh @@ -112,7 +112,7 @@ LSQ::DcachePort::recvRetry() template LSQ::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, Params *params) - : cpu(cpu_ptr), iewStage(iew_ptr), dcachePort(this), + : cpu(cpu_ptr), iewStage(iew_ptr), dcachePort(this, cpu_ptr), LQEntries(params->LQEntries), SQEntries(params->SQEntries), numThreads(params->numberOfThreads), diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index 865d58635..514d3de64 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -103,7 +103,6 @@ void O3ThreadContext::delVirtPort(VirtualPort *vp) { if (vp != thread->getVirtPort()) { - vp->removeConn(); delete vp; } } diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index 0c7105382..4cb55fa23 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -747,7 +747,6 @@ template void OzoneCPU::OzoneTC::delVirtPort(VirtualPort *vp) { - vp->removeConn(); delete vp; } #endif diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index 5a5444de4..47b69d05f 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -302,7 +302,6 @@ void SimpleThread::delVirtPort(VirtualPort *vp) { if (vp != virtPort) { - vp->removeConn(); delete vp; } } diff --git a/src/cpu/thread_state.cc b/src/cpu/thread_state.cc index bcfc9c924..56839ca7f 100644 --- a/src/cpu/thread_state.cc +++ b/src/cpu/thread_state.cc @@ -126,7 +126,7 @@ ThreadState::connectPhysPort() // already existed. Fix this memory leak once the bus port IDs // for functional ports is resolved. if (physPort) - physPort->removeConn(); + physPort->disconnectFromPeer(); else physPort = new FunctionalPort(csprintf("%s-%d-funcport", baseCpu->name(), tid)); @@ -140,7 +140,7 @@ ThreadState::connectVirtPort() // already existed. Fix this memory leak once the bus port IDs // for functional ports is resolved. if (virtPort) - virtPort->removeConn(); + virtPort->disconnectFromPeer(); else virtPort = new VirtualPort(csprintf("%s-%d-vport", baseCpu->name(), tid)); diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc index c09cacc00..25c6e5d19 100644 --- a/src/mem/bridge.cc +++ b/src/mem/bridge.cc @@ -47,7 +47,7 @@ Bridge::BridgePort::BridgePort(const std::string &_name, int _delay, int _nack_delay, int _req_limit, int _resp_limit, std::vector > filter_ranges) - : Port(_name), bridge(_bridge), otherPort(_otherPort), + : 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) diff --git a/src/mem/bus.cc b/src/mem/bus.cc index 3bf1c6cfc..9dd3353fd 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -72,8 +72,8 @@ Bus::getPort(const std::string &if_name, int idx) return bp; } -void -Bus::deletePortRefs(Port *p) +bool +Bus::deletePort(Port *p) { BusPort *bp = dynamic_cast(p); @@ -81,10 +81,11 @@ Bus::deletePortRefs(Port *p) panic("Couldn't convert Port* to BusPort*\n"); // If this is our one functional port if (funcPort == bp) - return; + return false; interfaces.erase(bp->getId()); clearBusCache(); delete bp; + return true; } /** Get the ranges of anyone other buses that we are connected to. */ diff --git a/src/mem/bus.hh b/src/mem/bus.hh index 74901d626..7d476bb65 100644 --- a/src/mem/bus.hh +++ b/src/mem/bus.hh @@ -364,7 +364,7 @@ class Bus : public MemObject /** 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 bool deletePort(Port *p); virtual void init(); virtual void startup(); diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh index 88c9deb7b..56ae811a3 100644 --- a/src/mem/cache/cache.hh +++ b/src/mem/cache/cache.hh @@ -217,7 +217,7 @@ 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); + virtual bool deletePort(Port *p); void regStats(); diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 3b56c0a2e..a3dae7b2a 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -105,13 +105,14 @@ Cache::getPort(const std::string &if_name, int idx) } template -void -Cache::deletePortRefs(Port *p) +bool +Cache::deletePort(Port *p) { if (cpuSidePort == p || memSidePort == p) panic("Can only delete functional ports\n"); delete p; + return true; } diff --git a/src/mem/mem_object.cc b/src/mem/mem_object.cc index ce2a1107e..7d27db763 100644 --- a/src/mem/mem_object.cc +++ b/src/mem/mem_object.cc @@ -43,8 +43,8 @@ MemObject::makeParams(const std::string &name) return params; } -void -MemObject::deletePortRefs(Port *p) +bool +MemObject::deletePort(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 33b56dfd4..a91ea5ac4 100644 --- a/src/mem/mem_object.hh +++ b/src/mem/mem_object.hh @@ -64,9 +64,13 @@ class MemObject : public SimObject /** 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) ; + /** Tell MemObject that this port is no longer in use, so it + * should remove it from any structures that it's keeping it in. + * If the port was allocated dynamically for this connection, it + * should be deleted here. + * @return True if the port was deleted, false if it still exists. + */ + virtual bool deletePort(Port *p); }; #endif //__MEM_MEM_OBJECT_HH__ diff --git a/src/mem/port.cc b/src/mem/port.cc index 0e03194c9..1e6989750 100644 --- a/src/mem/port.cc +++ b/src/mem/port.cc @@ -39,17 +39,25 @@ #include "mem/mem_object.hh" #include "mem/port.hh" +/** + * Special class for port objects that are used as peers for + * unconnected ports. Assigning instances of this class to newly + * allocated ports allows us to guarantee that every port has a peer + * object (so there's no need to check for null peer pointers), while + * catching uses of unconnected ports. + */ class DefaultPeerPort : public Port { protected: void blowUp() { - fatal("%s: Unconnected port!", peer->name()); + Port *peer = getPeer(); + fatal("unconnected port: %s", peer ? peer->name() : ""); } public: - DefaultPeerPort() - : Port("default_port") + DefaultPeerPort(Port *_peer) + : Port("default_port", NULL, _peer) { } bool recvTiming(PacketPtr) @@ -88,36 +96,59 @@ class DefaultPeerPort : public Port bool isDefaultPort() const { return true; } }; -DefaultPeerPort defaultPeerPort; -Port::Port() - : peer(&defaultPeerPort), owner(NULL) +Port::Port(const std::string &_name, MemObject *_owner, Port *_peer) : + portName(_name), + peer(_peer ? _peer : new DefaultPeerPort(this)), + owner(_owner) { } -Port::Port(const std::string &_name, MemObject *_owner) - : portName(_name), peer(&defaultPeerPort), owner(_owner) +Port::~Port() { + disconnectFromPeer(); } -Port::~Port() +void +Port::disconnectFromPeer() { + if (peer) { + assert(peer->getPeer() == this); + peer->disconnect(); + } } void -Port::setPeer(Port *port) +Port::disconnect() { - DPRINTF(Config, "setting peer to %s\n", port->name()); - - peer = port; + // This notification should come only from our peer, so we must + // have one, + assert(peer != NULL); + // We must clear 'peer' here, else if owner->deletePort() calls + // delete on us then we'll recurse infinitely through the Port + // destructor. + peer = NULL; + // If owner->deletePort() returns true, then we've been deleted, + // so don't do anything but get out of here. If not, reset peer + // pointer to a DefaultPeerPort. + if (!(owner && owner->deletePort(this))) + peer = new DefaultPeerPort(this); } void -Port::removeConn() +Port::setPeer(Port *port) { - if (peer->getOwner()) - peer->getOwner()->deletePortRefs(peer); - peer = NULL; + DPRINTF(Config, "setting peer to %s, old peer %s\n", + port->name(), peer ? peer->name() : ""); + + // You'd think we'd want to disconnect from the previous peer + // here, but it turns out that with some functional ports the old + // peer keeps using the connection, and it works because + // functional ports are unidirectional. + // + // disconnectFromPeer(); + + peer = port; } void diff --git a/src/mem/port.hh b/src/mem/port.hh index 15fda2164..4e0d91e75 100644 --- a/src/mem/port.hh +++ b/src/mem/port.hh @@ -87,17 +87,14 @@ class Port public: - Port(); - /** * Constructor. * * @param _name Port name for DPRINTF output. Should include name * of memory system object to which the port belongs. * @param _owner Pointer to the MemObject that owns this port. - * Will not necessarily be set. */ - Port(const std::string &_name, MemObject *_owner = NULL); + Port(const std::string &_name, MemObject *_owner, Port *_peer = NULL); /** Return port name (for DPRINTF). */ const std::string &name() const { return portName; } @@ -111,24 +108,18 @@ class Port RangeChange }; - void setName(const std::string &name) - { portName = name; } - /** Function to set the pointer for the peer port. */ virtual void setPeer(Port *port); /** Function to get the pointer to the peer port. */ Port *getPeer() { return peer; } - /** Function to set the owner of this port. */ - void setOwner(MemObject *_owner) { owner = _owner; } - /** 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(); + /** Notify my peer port that I'm disconnecting (by calling its + * disconnect() method) so it can clean up. */ + void disconnectFromPeer(); virtual bool isDefaultPort() const { return false; } @@ -254,6 +245,11 @@ class Port /** Internal helper function for read/writeBlob(). */ void blobHelper(Addr addr, uint8_t *p, int size, MemCmd cmd); + + /** Receive notification that my peer is disconnecting and clean + * up (potentially deleting myself in the process). Should be + * called only from peer's disconnectFromPeer(). */ + void disconnect(); }; /** A simple functional port that is only meant for one way communication to -- cgit v1.2.3 From 1434b8694319047ba7f35cc6c1a9c965ccba3f22 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Sat, 21 Jun 2008 01:06:27 -0400 Subject: Make bus address conflict error more informative --- src/mem/bus.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/mem/bus.cc b/src/mem/bus.cc index 9dd3353fd..4468262ac 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -524,9 +524,12 @@ Bus::recvStatusChange(Port::Status status, int id) for (iter = ranges.begin(); iter != ranges.end(); iter++) { DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for id %d\n", iter->start, iter->end, id); - if (portMap.insert(*iter, id) == portMap.end()) - panic("Two devices with same range\n"); - + if (portMap.insert(*iter, id) == portMap.end()) { + int conflict_id = portMap.find(*iter)->second; + fatal("%s has two ports with same range:\n\t%s\n\t%s\n", + name(), interfaces[id]->getPeer()->name(), + interfaces[conflict_id]->getPeer()->name()); + } } } DPRINTF(MMU, "port list has %d entries\n", portMap.size()); -- cgit v1.2.3 From 18c83be50702e27ef092a3c7630514b364f60aa0 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 21 Jun 2008 14:23:58 -0400 Subject: SimObject: Add in missing includes of and fix minor style problem. --- src/sim/sim_object.hh | 5 +++-- src/sim/sim_object_params.hh | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/sim/sim_object.hh b/src/sim/sim_object.hh index ec565ce82..00bb3fee6 100644 --- a/src/sim/sim_object.hh +++ b/src/sim/sim_object.hh @@ -36,10 +36,11 @@ #ifndef __SIM_OBJECT_HH__ #define __SIM_OBJECT_HH__ -#include +#include #include +#include +#include #include -#include #include "params/SimObject.hh" #include "sim/serialize.hh" diff --git a/src/sim/sim_object_params.hh b/src/sim/sim_object_params.hh index 4179a37bf..5a629a949 100644 --- a/src/sim/sim_object_params.hh +++ b/src/sim/sim_object_params.hh @@ -36,6 +36,8 @@ struct PyObject; #endif +#include + struct SimObjectParams { virtual ~SimObjectParams() {} -- cgit v1.2.3 From 57b5de6b9f9150ceda46c52b3621e60f667138d4 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Tue, 24 Jun 2008 15:48:45 -0400 Subject: Checkpoinging/SWIG: Undo part of changeset 5464 since it broke checkpointing. --- src/python/swig/event.i | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/python/swig/event.i b/src/python/swig/event.i index ee1f3d00b..9a2093c99 100644 --- a/src/python/swig/event.i +++ b/src/python/swig/event.i @@ -44,8 +44,8 @@ void create(PyObject *object, Tick when); -class CountedDrainEvent -{ +class Event; +class CountedDrainEvent : public Event { public: void setCount(int _count); }; -- cgit v1.2.3 From caaac16803db6eaf3ee20b5d062ec2211fe6584d Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Sat, 28 Jun 2008 13:19:38 -0400 Subject: Backed out changeset 94a7bb476fca: caused memory leak. --- src/cpu/o3/fetch.hh | 4 +-- src/cpu/o3/fetch_impl.hh | 2 +- src/cpu/o3/lsq.hh | 4 +-- src/cpu/o3/lsq_impl.hh | 2 +- src/cpu/o3/thread_context_impl.hh | 1 + src/cpu/ozone/cpu_impl.hh | 1 + src/cpu/simple_thread.cc | 1 + src/cpu/thread_state.cc | 4 +-- src/mem/bridge.cc | 2 +- src/mem/bus.cc | 7 ++--- src/mem/bus.hh | 2 +- src/mem/cache/cache.hh | 2 +- src/mem/cache/cache_impl.hh | 5 ++- src/mem/mem_object.cc | 4 +-- src/mem/mem_object.hh | 10 ++---- src/mem/port.cc | 65 ++++++++++----------------------------- src/mem/port.hh | 22 +++++++------ 17 files changed, 54 insertions(+), 84 deletions(-) (limited to 'src') diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index 3ada0328f..d954bd1e7 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -80,8 +80,8 @@ class DefaultFetch public: /** Default constructor. */ - IcachePort(DefaultFetch *_fetch, O3CPU *_cpu) - : Port(_fetch->name() + "-iport", _cpu), fetch(_fetch) + IcachePort(DefaultFetch *_fetch) + : Port(_fetch->name() + "-iport"), fetch(_fetch) { } bool snoopRangeSent; diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index ecfbacd98..7d344fa33 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -167,7 +167,7 @@ DefaultFetch::DefaultFetch(O3CPU *_cpu, Params *params) instSize = sizeof(TheISA::MachInst); // Name is finally available, so create the port. - icachePort = new IcachePort(this, cpu); + icachePort = new IcachePort(this); icachePort->snoopRangeSent = false; diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh index 82d73c6ee..06de608e0 100644 --- a/src/cpu/o3/lsq.hh +++ b/src/cpu/o3/lsq.hh @@ -296,8 +296,8 @@ class LSQ { public: /** Default constructor. */ - DcachePort(LSQ *_lsq, O3CPU *_cpu) - : Port(_lsq->name() + "-dport", _cpu), lsq(_lsq) + DcachePort(LSQ *_lsq) + : Port(_lsq->name() + "-dport"), lsq(_lsq) { } bool snoopRangeSent; diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh index 41ab66dd0..8ed6f7f54 100644 --- a/src/cpu/o3/lsq_impl.hh +++ b/src/cpu/o3/lsq_impl.hh @@ -112,7 +112,7 @@ LSQ::DcachePort::recvRetry() template LSQ::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, Params *params) - : cpu(cpu_ptr), iewStage(iew_ptr), dcachePort(this, cpu_ptr), + : cpu(cpu_ptr), iewStage(iew_ptr), dcachePort(this), LQEntries(params->LQEntries), SQEntries(params->SQEntries), numThreads(params->numberOfThreads), diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index 514d3de64..865d58635 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -103,6 +103,7 @@ void O3ThreadContext::delVirtPort(VirtualPort *vp) { if (vp != thread->getVirtPort()) { + vp->removeConn(); delete vp; } } diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index 4cb55fa23..0c7105382 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -747,6 +747,7 @@ template void OzoneCPU::OzoneTC::delVirtPort(VirtualPort *vp) { + vp->removeConn(); delete vp; } #endif diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index 47b69d05f..5a5444de4 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -302,6 +302,7 @@ void SimpleThread::delVirtPort(VirtualPort *vp) { if (vp != virtPort) { + vp->removeConn(); delete vp; } } diff --git a/src/cpu/thread_state.cc b/src/cpu/thread_state.cc index 56839ca7f..bcfc9c924 100644 --- a/src/cpu/thread_state.cc +++ b/src/cpu/thread_state.cc @@ -126,7 +126,7 @@ ThreadState::connectPhysPort() // already existed. Fix this memory leak once the bus port IDs // for functional ports is resolved. if (physPort) - physPort->disconnectFromPeer(); + physPort->removeConn(); else physPort = new FunctionalPort(csprintf("%s-%d-funcport", baseCpu->name(), tid)); @@ -140,7 +140,7 @@ ThreadState::connectVirtPort() // already existed. Fix this memory leak once the bus port IDs // for functional ports is resolved. if (virtPort) - virtPort->disconnectFromPeer(); + virtPort->removeConn(); else virtPort = new VirtualPort(csprintf("%s-%d-vport", baseCpu->name(), tid)); diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc index 25c6e5d19..c09cacc00 100644 --- a/src/mem/bridge.cc +++ b/src/mem/bridge.cc @@ -47,7 +47,7 @@ Bridge::BridgePort::BridgePort(const std::string &_name, int _delay, int _nack_delay, int _req_limit, int _resp_limit, std::vector > filter_ranges) - : Port(_name, _bridge), bridge(_bridge), otherPort(_otherPort), + : Port(_name), 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) diff --git a/src/mem/bus.cc b/src/mem/bus.cc index 9dd3353fd..3bf1c6cfc 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -72,8 +72,8 @@ Bus::getPort(const std::string &if_name, int idx) return bp; } -bool -Bus::deletePort(Port *p) +void +Bus::deletePortRefs(Port *p) { BusPort *bp = dynamic_cast(p); @@ -81,11 +81,10 @@ Bus::deletePort(Port *p) panic("Couldn't convert Port* to BusPort*\n"); // If this is our one functional port if (funcPort == bp) - return false; + return; interfaces.erase(bp->getId()); clearBusCache(); delete bp; - return true; } /** Get the ranges of anyone other buses that we are connected to. */ diff --git a/src/mem/bus.hh b/src/mem/bus.hh index 7d476bb65..74901d626 100644 --- a/src/mem/bus.hh +++ b/src/mem/bus.hh @@ -364,7 +364,7 @@ class Bus : public MemObject /** A function used to return the port associated with this bus object. */ virtual Port *getPort(const std::string &if_name, int idx = -1); - virtual bool deletePort(Port *p); + virtual void deletePortRefs(Port *p); virtual void init(); virtual void startup(); diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh index 56ae811a3..88c9deb7b 100644 --- a/src/mem/cache/cache.hh +++ b/src/mem/cache/cache.hh @@ -217,7 +217,7 @@ class Cache : public BaseCache Cache(const Params *p, TagStore *tags, BasePrefetcher *prefetcher); virtual Port *getPort(const std::string &if_name, int idx = -1); - virtual bool deletePort(Port *p); + virtual void deletePortRefs(Port *p); void regStats(); diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index a3dae7b2a..3b56c0a2e 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -105,14 +105,13 @@ Cache::getPort(const std::string &if_name, int idx) } template -bool -Cache::deletePort(Port *p) +void +Cache::deletePortRefs(Port *p) { if (cpuSidePort == p || memSidePort == p) panic("Can only delete functional ports\n"); delete p; - return true; } diff --git a/src/mem/mem_object.cc b/src/mem/mem_object.cc index 7d27db763..ce2a1107e 100644 --- a/src/mem/mem_object.cc +++ b/src/mem/mem_object.cc @@ -43,8 +43,8 @@ MemObject::makeParams(const std::string &name) return params; } -bool -MemObject::deletePort(Port *p) +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 a91ea5ac4..33b56dfd4 100644 --- a/src/mem/mem_object.hh +++ b/src/mem/mem_object.hh @@ -64,13 +64,9 @@ class MemObject : public SimObject /** Additional function to return the Port of a memory object. */ virtual Port *getPort(const std::string &if_name, int idx = -1) = 0; - /** Tell MemObject that this port is no longer in use, so it - * should remove it from any structures that it's keeping it in. - * If the port was allocated dynamically for this connection, it - * should be deleted here. - * @return True if the port was deleted, false if it still exists. - */ - virtual bool deletePort(Port *p); + /** 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/port.cc b/src/mem/port.cc index 1e6989750..0e03194c9 100644 --- a/src/mem/port.cc +++ b/src/mem/port.cc @@ -39,25 +39,17 @@ #include "mem/mem_object.hh" #include "mem/port.hh" -/** - * Special class for port objects that are used as peers for - * unconnected ports. Assigning instances of this class to newly - * allocated ports allows us to guarantee that every port has a peer - * object (so there's no need to check for null peer pointers), while - * catching uses of unconnected ports. - */ class DefaultPeerPort : public Port { protected: void blowUp() { - Port *peer = getPeer(); - fatal("unconnected port: %s", peer ? peer->name() : ""); + fatal("%s: Unconnected port!", peer->name()); } public: - DefaultPeerPort(Port *_peer) - : Port("default_port", NULL, _peer) + DefaultPeerPort() + : Port("default_port") { } bool recvTiming(PacketPtr) @@ -96,59 +88,36 @@ class DefaultPeerPort : public Port bool isDefaultPort() const { return true; } }; +DefaultPeerPort defaultPeerPort; -Port::Port(const std::string &_name, MemObject *_owner, Port *_peer) : - portName(_name), - peer(_peer ? _peer : new DefaultPeerPort(this)), - owner(_owner) +Port::Port() + : peer(&defaultPeerPort), owner(NULL) { } -Port::~Port() +Port::Port(const std::string &_name, MemObject *_owner) + : portName(_name), peer(&defaultPeerPort), owner(_owner) { - disconnectFromPeer(); } -void -Port::disconnectFromPeer() +Port::~Port() { - if (peer) { - assert(peer->getPeer() == this); - peer->disconnect(); - } } void -Port::disconnect() +Port::setPeer(Port *port) { - // This notification should come only from our peer, so we must - // have one, - assert(peer != NULL); - // We must clear 'peer' here, else if owner->deletePort() calls - // delete on us then we'll recurse infinitely through the Port - // destructor. - peer = NULL; - // If owner->deletePort() returns true, then we've been deleted, - // so don't do anything but get out of here. If not, reset peer - // pointer to a DefaultPeerPort. - if (!(owner && owner->deletePort(this))) - peer = new DefaultPeerPort(this); + DPRINTF(Config, "setting peer to %s\n", port->name()); + + peer = port; } void -Port::setPeer(Port *port) +Port::removeConn() { - DPRINTF(Config, "setting peer to %s, old peer %s\n", - port->name(), peer ? peer->name() : ""); - - // You'd think we'd want to disconnect from the previous peer - // here, but it turns out that with some functional ports the old - // peer keeps using the connection, and it works because - // functional ports are unidirectional. - // - // disconnectFromPeer(); - - peer = port; + if (peer->getOwner()) + peer->getOwner()->deletePortRefs(peer); + peer = NULL; } void diff --git a/src/mem/port.hh b/src/mem/port.hh index 4e0d91e75..15fda2164 100644 --- a/src/mem/port.hh +++ b/src/mem/port.hh @@ -87,14 +87,17 @@ class Port public: + Port(); + /** * Constructor. * * @param _name Port name for DPRINTF output. Should include name * of memory system object to which the port belongs. * @param _owner Pointer to the MemObject that owns this port. + * Will not necessarily be set. */ - Port(const std::string &_name, MemObject *_owner, Port *_peer = NULL); + Port(const std::string &_name, MemObject *_owner = NULL); /** Return port name (for DPRINTF). */ const std::string &name() const { return portName; } @@ -108,18 +111,24 @@ class Port RangeChange }; + void setName(const std::string &name) + { portName = name; } + /** Function to set the pointer for the peer port. */ virtual void setPeer(Port *port); /** Function to get the pointer to the peer port. */ Port *getPeer() { return peer; } + /** Function to set the owner of this port. */ + void setOwner(MemObject *_owner) { owner = _owner; } + /** Function to return the owner of this port. */ MemObject *getOwner() { return owner; } - /** Notify my peer port that I'm disconnecting (by calling its - * disconnect() method) so it can clean up. */ - void disconnectFromPeer(); + /** Inform the peer port to delete itself and notify it's owner about it's + * demise. */ + void removeConn(); virtual bool isDefaultPort() const { return false; } @@ -245,11 +254,6 @@ class Port /** Internal helper function for read/writeBlob(). */ void blobHelper(Addr addr, uint8_t *p, int size, MemCmd cmd); - - /** Receive notification that my peer is disconnecting and clean - * up (potentially deleting myself in the process). Should be - * called only from peer's disconnectFromPeer(). */ - void disconnect(); }; /** A simple functional port that is only meant for one way communication to -- cgit v1.2.3 From 9bd0bfe559d8c9633c5686ccf100ab921eb6eda2 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Tue, 1 Jul 2008 10:24:09 -0400 Subject: After a checkpoint (and thus a stats reset), the not_idle_fraction/notIdleFraction statistic is really wrong. The notIdleFraction statistic isn't updated when the statistics reset, probably because the cpu Status information was pulled into the atomic and timing cpus. This changeset pulls Status back into the BaseSimpleCPU object. Anyone care to comment on the odd naming of the Status instance? It shouldn't just be status because that is confusing with Port::Status, but _status seems a bit strage too. --- src/cpu/simple/atomic.cc | 5 +---- src/cpu/simple/atomic.hh | 13 ------------- src/cpu/simple/base.cc | 4 +++- src/cpu/simple/base.hh | 14 ++++++++++++++ src/cpu/simple/timing.cc | 4 ++-- src/cpu/simple/timing.hh | 18 ------------------ 6 files changed, 20 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index b25d3330f..6b07502ef 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -176,8 +176,6 @@ AtomicSimpleCPU::serialize(ostream &os) { SimObject::State so_state = SimObject::getState(); SERIALIZE_ENUM(so_state); - Status _status = status(); - SERIALIZE_ENUM(_status); BaseSimpleCPU::serialize(os); nameOut(os, csprintf("%s.tickEvent", name())); tickEvent.serialize(os); @@ -188,7 +186,6 @@ AtomicSimpleCPU::unserialize(Checkpoint *cp, const string §ion) { SimObject::State so_state; UNSERIALIZE_ENUM(so_state); - UNSERIALIZE_ENUM(_status); BaseSimpleCPU::unserialize(cp, section); tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); } @@ -213,7 +210,7 @@ AtomicSimpleCPU::resume() void AtomicSimpleCPU::switchOut() { - assert(status() == Running || status() == Idle); + assert(_status == Running || _status == Idle); _status = SwitchedOut; tickEvent.squash(); diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh index ccea15073..008397533 100644 --- a/src/cpu/simple/atomic.hh +++ b/src/cpu/simple/atomic.hh @@ -48,19 +48,6 @@ class AtomicSimpleCPU : public BaseSimpleCPU virtual void init(); - public: - // - enum Status { - Running, - Idle, - SwitchedOut - }; - - protected: - Status _status; - - Status status() const { return _status; } - private: struct TickEvent : public Event diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index 4a91a9e12..0c1162032 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -174,12 +174,13 @@ void BaseSimpleCPU::resetStats() { // startNumInst = numInst; - // notIdleFraction = (_status != Idle); + notIdleFraction = (_status != Idle); } void BaseSimpleCPU::serialize(ostream &os) { + SERIALIZE_ENUM(_status); BaseCPU::serialize(os); // SERIALIZE_SCALAR(inst); nameOut(os, csprintf("%s.xc.0", name())); @@ -189,6 +190,7 @@ BaseSimpleCPU::serialize(ostream &os) void BaseSimpleCPU::unserialize(Checkpoint *cp, const string §ion) { + UNSERIALIZE_ENUM(_status); BaseCPU::unserialize(cp, section); // UNSERIALIZE_SCALAR(inst); thread->unserialize(cp, csprintf("%s.xc.0", section)); diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index 918965fdb..62bb31de8 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -129,6 +129,20 @@ class BaseSimpleCPU : public BaseCPU protected: int cpuId; + enum Status { + Idle, + Running, + IcacheRetry, + IcacheWaitResponse, + IcacheWaitSwitch, + DcacheRetry, + DcacheWaitResponse, + DcacheWaitSwitch, + SwitchedOut + }; + + Status _status; + public: #if FULL_SYSTEM diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index d0c7dd787..2cf7d584d 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -145,7 +145,7 @@ TimingSimpleCPU::drain(Event *drain_event) { // TimingSimpleCPU is ready to drain if it's not waiting for // an access to complete. - if (status() == Idle || status() == Running || status() == SwitchedOut) { + if (_status == Idle || _status == Running || _status == SwitchedOut) { changeState(SimObject::Drained); return 0; } else { @@ -179,7 +179,7 @@ TimingSimpleCPU::resume() void TimingSimpleCPU::switchOut() { - assert(status() == Running || status() == Idle); + assert(_status == Running || _status == Idle); _status = SwitchedOut; numCycles += tickToCycles(curTick - previousTick); diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index f8b77604a..a748d47b4 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -46,24 +46,6 @@ class TimingSimpleCPU : public BaseSimpleCPU virtual void init(); public: - // - enum Status { - Idle, - Running, - IcacheRetry, - IcacheWaitResponse, - IcacheWaitSwitch, - DcacheRetry, - DcacheWaitResponse, - DcacheWaitSwitch, - SwitchedOut - }; - - protected: - Status _status; - - Status status() const { return _status; } - Event *drainEvent; private: -- cgit v1.2.3 From 50e3e50e1ac592b357a47eecdc3c99a528172870 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Tue, 1 Jul 2008 10:24:16 -0400 Subject: Make the cached virtPort have a thread context so it can do everything that a newly created one can. --- src/cpu/o3/cpu.cc | 2 +- src/cpu/o3/thread_context.hh | 2 +- src/cpu/simple/atomic.cc | 2 +- src/cpu/simple/timing.cc | 2 +- src/cpu/thread_context.hh | 4 ++-- src/cpu/thread_state.cc | 8 ++++---- src/cpu/thread_state.hh | 6 +++--- 7 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index c75a08213..fac214174 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -788,7 +788,7 @@ FullO3CPU::updateMemPorts() // Update all ThreadContext's memory ports (Functional/Virtual // Ports) for (int i = 0; i < thread.size(); ++i) - thread[i]->connectMemPorts(); + thread[i]->connectMemPorts(thread[i]->getTC()); } #endif diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index e7bdc6de5..44e26729c 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -98,7 +98,7 @@ class O3ThreadContext : public ThreadContext void delVirtPort(VirtualPort *vp); - virtual void connectMemPorts() { thread->connectMemPorts(); } + virtual void connectMemPorts(ThreadContext *tc) { thread->connectMemPorts(tc); } #else virtual TranslatingPort *getMemPort() { return thread->getMemPort(); } diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 6b07502ef..0e04a36b2 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -148,7 +148,7 @@ AtomicSimpleCPU::DcachePort::setPeer(Port *port) #if FULL_SYSTEM // Update the ThreadContext's memory ports (Functional/Virtual // Ports) - cpu->tcBase()->connectMemPorts(); + cpu->tcBase()->connectMemPorts(cpu->tcBase()); #endif } diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 2cf7d584d..b86d4b2d7 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -766,7 +766,7 @@ TimingSimpleCPU::DcachePort::setPeer(Port *port) #if FULL_SYSTEM // Update the ThreadContext's memory ports (Functional/Virtual // Ports) - cpu->tcBase()->connectMemPorts(); + cpu->tcBase()->connectMemPorts(cpu->tcBase()); #endif } diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index cf51c1637..b25a67d59 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -134,7 +134,7 @@ class ThreadContext virtual void delVirtPort(VirtualPort *vp) = 0; - virtual void connectMemPorts() = 0; + virtual void connectMemPorts(ThreadContext *tc) = 0; #else virtual TranslatingPort *getMemPort() = 0; @@ -325,7 +325,7 @@ class ProxyThreadContext : public ThreadContext void delVirtPort(VirtualPort *vp) { return actualTC->delVirtPort(vp); } - void connectMemPorts() { actualTC->connectMemPorts(); } + void connectMemPorts(ThreadContext *tc) { actualTC->connectMemPorts(tc); } #else TranslatingPort *getMemPort() { return actualTC->getMemPort(); } diff --git a/src/cpu/thread_state.cc b/src/cpu/thread_state.cc index bcfc9c924..18845baf7 100644 --- a/src/cpu/thread_state.cc +++ b/src/cpu/thread_state.cc @@ -113,10 +113,10 @@ ThreadState::unserialize(Checkpoint *cp, const std::string §ion) #if FULL_SYSTEM void -ThreadState::connectMemPorts() +ThreadState::connectMemPorts(ThreadContext *tc) { connectPhysPort(); - connectVirtPort(); + connectVirtPort(tc); } void @@ -134,7 +134,7 @@ ThreadState::connectPhysPort() } void -ThreadState::connectVirtPort() +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 @@ -143,7 +143,7 @@ ThreadState::connectVirtPort() virtPort->removeConn(); else virtPort = new VirtualPort(csprintf("%s-%d-vport", - baseCpu->name(), tid)); + baseCpu->name(), tid), tc); connectToMemFunc(virtPort); } diff --git a/src/cpu/thread_state.hh b/src/cpu/thread_state.hh index 4f878db1f..b6a62eebc 100644 --- a/src/cpu/thread_state.hh +++ b/src/cpu/thread_state.hh @@ -91,11 +91,11 @@ struct ThreadState { Tick readLastSuspend() { return lastSuspend; } #if FULL_SYSTEM - void connectMemPorts(); + void connectMemPorts(ThreadContext *tc); void connectPhysPort(); - void connectVirtPort(); + void connectVirtPort(ThreadContext *tc); void dumpFuncProfile(); @@ -201,7 +201,7 @@ struct ThreadState { FunctionalPort *physPort; /** A functional port, outgoing only, for functional accesse to virtual - * addresses. That doen't require execution context information */ + * addresses. */ VirtualPort *virtPort; #else TranslatingPort *port; -- cgit v1.2.3 From c5fbbf376a6be4bb3ad7ddc64841450541c16db6 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Tue, 1 Jul 2008 10:24:19 -0400 Subject: Change everything to use the cached virtPort rather than created their own each time. This appears to work, but I don't want to commit it until it gets tested a lot more. I haven't deleted the functionality in this patch that will come later, but one question is how to enforce encourage objects that call getVirtPort() to not cache the virtual port since if the CPU changes out from under them it will be worse than useless. Perhaps a null function like delVirtPort() is still useful in that case. --- src/arch/alpha/utility.cc | 2 +- src/arch/mips/utility.cc | 2 +- src/arch/sparc/utility.cc | 2 +- src/base/remote_gdb.cc | 4 ++-- src/mem/vport.cc | 8 ++++---- src/sim/vptr.hh | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/utility.cc b/src/arch/alpha/utility.cc index f1864203b..94e82adf3 100644 --- a/src/arch/alpha/utility.cc +++ b/src/arch/alpha/utility.cc @@ -49,7 +49,7 @@ uint64_t getArgument(ThreadContext *tc, int number, bool fp) return tc->readIntReg(ArgumentReg[number]); } else { Addr sp = tc->readIntReg(StackPointerReg); - VirtualPort *vp = tc->getVirtPort(tc); + VirtualPort *vp = tc->getVirtPort(); uint64_t arg = vp->read(sp + (number-NumArgumentRegs) * sizeof(uint64_t)); tc->delVirtPort(vp); diff --git a/src/arch/mips/utility.cc b/src/arch/mips/utility.cc index c254811fa..52c52f8e7 100644 --- a/src/arch/mips/utility.cc +++ b/src/arch/mips/utility.cc @@ -59,7 +59,7 @@ getArgument(ThreadContext *tc, int number, bool fp) return tc->readIntReg(ArgumentReg[number]); } else { Addr sp = tc->readIntReg(StackPointerReg); - VirtualPort *vp = tc->getVirtPort(tc); + VirtualPort *vp = tc->getVirtPort(); uint64_t arg = vp->read(sp + (number-NumArgumentRegs) * sizeof(uint64_t)); tc->delVirtPort(vp); diff --git a/src/arch/sparc/utility.cc b/src/arch/sparc/utility.cc index 6d4358603..0677823af 100644 --- a/src/arch/sparc/utility.cc +++ b/src/arch/sparc/utility.cc @@ -50,7 +50,7 @@ uint64_t getArgument(ThreadContext *tc, int number, bool fp) { return tc->readIntReg(ArgumentReg[number]); } else { Addr sp = tc->readIntReg(StackPointerReg); - VirtualPort *vp = tc->getVirtPort(tc); + VirtualPort *vp = tc->getVirtPort(); uint64_t arg = vp->read(sp + 92 + (number-NumArgumentRegs) * sizeof(uint64_t)); tc->delVirtPort(vp); diff --git a/src/base/remote_gdb.cc b/src/base/remote_gdb.cc index d5095e7f9..1a858a3f3 100644 --- a/src/base/remote_gdb.cc +++ b/src/base/remote_gdb.cc @@ -454,7 +454,7 @@ BaseRemoteGDB::read(Addr vaddr, size_t size, char *data) DPRINTF(GDBRead, "read: addr=%#x, size=%d", vaddr, size); #if FULL_SYSTEM - VirtualPort *port = context->getVirtPort(context); + VirtualPort *port = context->getVirtPort(); #else TranslatingPort *port = context->getMemPort(); #endif @@ -499,7 +499,7 @@ BaseRemoteGDB::write(Addr vaddr, size_t size, const char *data) DPRINTFNR("\n"); } #if FULL_SYSTEM - VirtualPort *port = context->getVirtPort(context); + VirtualPort *port = context->getVirtPort(); #else TranslatingPort *port = context->getMemPort(); #endif diff --git a/src/mem/vport.cc b/src/mem/vport.cc index 6cc4d9ca9..a2f8b1ecc 100644 --- a/src/mem/vport.cc +++ b/src/mem/vport.cc @@ -75,7 +75,7 @@ void CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen) { uint8_t *dst = (uint8_t *)dest; - VirtualPort *vp = tc->getVirtPort(tc); + VirtualPort *vp = tc->getVirtPort(); vp->readBlob(src, dst, cplen); @@ -87,7 +87,7 @@ void CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen) { uint8_t *src = (uint8_t *)source; - VirtualPort *vp = tc->getVirtPort(tc); + VirtualPort *vp = tc->getVirtPort(); vp->writeBlob(dest, src, cplen); @@ -99,7 +99,7 @@ CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen) { int len = 0; char *start = dst; - VirtualPort *vp = tc->getVirtPort(tc); + VirtualPort *vp = tc->getVirtPort(); do { vp->readBlob(vaddr++, (uint8_t*)dst++, 1); @@ -112,7 +112,7 @@ CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen) void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr) { - VirtualPort *vp = tc->getVirtPort(tc); + VirtualPort *vp = tc->getVirtPort(); for (ChunkGenerator gen(vaddr, strlen(src), TheISA::PageBytes); !gen.done(); gen.next()) { diff --git a/src/sim/vptr.hh b/src/sim/vptr.hh index 383f65351..88b515c13 100644 --- a/src/sim/vptr.hh +++ b/src/sim/vptr.hh @@ -71,7 +71,7 @@ class VPtr if (!ptr) return; - VirtualPort *port = tc->getVirtPort(tc); + VirtualPort *port = tc->getVirtPort(); port->readBlob(ptr, buffer, sizeof(T)); tc->delVirtPort(port); } -- cgit v1.2.3 From a4a7a09e9622d6ad1ca91a4df253b9768c73de90 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Tue, 1 Jul 2008 10:25:07 -0400 Subject: Remove delVirtPort() and make getVirtPort() only return cached version. --- src/arch/alpha/linux/system.cc | 1 - src/arch/alpha/stacktrace.cc | 4 ---- src/arch/alpha/utility.cc | 1 - src/arch/mips/linux/system.cc | 1 - src/arch/mips/stacktrace.cc | 4 ---- src/arch/mips/utility.cc | 1 - src/arch/sparc/stacktrace.cc | 4 ---- src/arch/sparc/utility.cc | 1 - src/arch/x86/stacktrace.cc | 4 ---- src/base/remote_gdb.cc | 7 +------ src/cpu/checker/thread_context.hh | 4 +--- src/cpu/o3/thread_context.hh | 4 +--- src/cpu/o3/thread_context_impl.hh | 23 ++--------------------- src/cpu/ozone/cpu.hh | 6 ++---- src/cpu/ozone/cpu_impl.hh | 10 ---------- src/cpu/simple_thread.cc | 23 ----------------------- src/cpu/simple_thread.hh | 11 +++++------ src/cpu/thread_context.hh | 8 ++------ src/cpu/thread_state.hh | 4 +--- src/mem/vport.cc | 7 ------- src/sim/vptr.hh | 1 - 21 files changed, 15 insertions(+), 114 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/linux/system.cc b/src/arch/alpha/linux/system.cc index 102598716..a52bcae36 100644 --- a/src/arch/alpha/linux/system.cc +++ b/src/arch/alpha/linux/system.cc @@ -169,7 +169,6 @@ LinuxAlphaSystem::setDelayLoop(ThreadContext *tc) vp = tc->getVirtPort(); vp->writeHtoG(addr, (uint32_t)((cpuFreq / intrFreq) * 0.9988)); - tc->delVirtPort(vp); } } diff --git a/src/arch/alpha/stacktrace.cc b/src/arch/alpha/stacktrace.cc index c16498e72..124949781 100644 --- a/src/arch/alpha/stacktrace.cc +++ b/src/arch/alpha/stacktrace.cc @@ -71,8 +71,6 @@ namespace AlphaISA if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr)) panic("thread info not compiled into kernel\n"); name_off = vp->readGtoH(addr); - - tc->delVirtPort(vp); } Addr @@ -88,7 +86,6 @@ namespace AlphaISA vp = tc->getVirtPort(); tsk = vp->readGtoH(base + task_off); - tc->delVirtPort(vp); return tsk; } @@ -106,7 +103,6 @@ namespace AlphaISA vp = tc->getVirtPort(); pd = vp->readGtoH(task + pid_off); - tc->delVirtPort(vp); return pd; } diff --git a/src/arch/alpha/utility.cc b/src/arch/alpha/utility.cc index 94e82adf3..23abceb93 100644 --- a/src/arch/alpha/utility.cc +++ b/src/arch/alpha/utility.cc @@ -52,7 +52,6 @@ uint64_t getArgument(ThreadContext *tc, int number, bool fp) VirtualPort *vp = tc->getVirtPort(); uint64_t arg = vp->read(sp + (number-NumArgumentRegs) * sizeof(uint64_t)); - tc->delVirtPort(vp); return arg; } #else diff --git a/src/arch/mips/linux/system.cc b/src/arch/mips/linux/system.cc index bed863e9d..23062c96b 100644 --- a/src/arch/mips/linux/system.cc +++ b/src/arch/mips/linux/system.cc @@ -168,7 +168,6 @@ LinuxMipsSystem::setDelayLoop(ThreadContext *tc) vp = tc->getVirtPort(); vp->writeHtoG(addr, (uint32_t)((cpuFreq / intrFreq) * 0.9988)); - tc->delVirtPort(vp); } } diff --git a/src/arch/mips/stacktrace.cc b/src/arch/mips/stacktrace.cc index 6c6f6bb3c..482d264e8 100644 --- a/src/arch/mips/stacktrace.cc +++ b/src/arch/mips/stacktrace.cc @@ -70,8 +70,6 @@ ProcessInfo::ProcessInfo(ThreadContext *_tc) // if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr)) // panic("thread info not compiled into kernel\n"); // name_off = vp->readGtoH(addr); - - tc->delVirtPort(vp); } Addr @@ -87,7 +85,6 @@ ProcessInfo::task(Addr ksp) const vp = tc->getVirtPort(); tsk = vp->readGtoH(base + task_off); - tc->delVirtPort(vp); return tsk; } @@ -105,7 +102,6 @@ ProcessInfo::pid(Addr ksp) const vp = tc->getVirtPort(); pd = vp->readGtoH(task + pid_off); - tc->delVirtPort(vp); return pd; } diff --git a/src/arch/mips/utility.cc b/src/arch/mips/utility.cc index 52c52f8e7..36cf76c67 100644 --- a/src/arch/mips/utility.cc +++ b/src/arch/mips/utility.cc @@ -62,7 +62,6 @@ getArgument(ThreadContext *tc, int number, bool fp) VirtualPort *vp = tc->getVirtPort(); uint64_t arg = vp->read(sp + (number-NumArgumentRegs) * sizeof(uint64_t)); - tc->delVirtPort(vp); return arg; } #else diff --git a/src/arch/sparc/stacktrace.cc b/src/arch/sparc/stacktrace.cc index 2d7991267..8ec1d36c8 100644 --- a/src/arch/sparc/stacktrace.cc +++ b/src/arch/sparc/stacktrace.cc @@ -70,8 +70,6 @@ namespace SparcISA if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr)) panic("thread info not compiled into kernel\n"); name_off = vp->readGtoH(addr); - - tc->delVirtPort(vp); } Addr @@ -87,7 +85,6 @@ namespace SparcISA vp = tc->getVirtPort(); tsk = vp->readGtoH(base + task_off); - tc->delVirtPort(vp); return tsk; } @@ -105,7 +102,6 @@ namespace SparcISA vp = tc->getVirtPort(); pd = vp->readGtoH(task + pid_off); - tc->delVirtPort(vp); return pd; } diff --git a/src/arch/sparc/utility.cc b/src/arch/sparc/utility.cc index 0677823af..8f5c3e036 100644 --- a/src/arch/sparc/utility.cc +++ b/src/arch/sparc/utility.cc @@ -53,7 +53,6 @@ uint64_t getArgument(ThreadContext *tc, int number, bool fp) { VirtualPort *vp = tc->getVirtPort(); uint64_t arg = vp->read(sp + 92 + (number-NumArgumentRegs) * sizeof(uint64_t)); - tc->delVirtPort(vp); return arg; } #else diff --git a/src/arch/x86/stacktrace.cc b/src/arch/x86/stacktrace.cc index 300e8dcd0..87767583b 100644 --- a/src/arch/x86/stacktrace.cc +++ b/src/arch/x86/stacktrace.cc @@ -70,8 +70,6 @@ namespace X86ISA if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr)) panic("thread info not compiled into kernel\n"); name_off = vp->readGtoH(addr); - - tc->delVirtPort(vp); } Addr @@ -87,7 +85,6 @@ namespace X86ISA vp = tc->getVirtPort(); tsk = vp->readGtoH(base + task_off); - tc->delVirtPort(vp); return tsk; } @@ -105,7 +102,6 @@ namespace X86ISA vp = tc->getVirtPort(); pd = vp->readGtoH(task + pid_off); - tc->delVirtPort(vp); return pd; } diff --git a/src/base/remote_gdb.cc b/src/base/remote_gdb.cc index 1a858a3f3..51293e118 100644 --- a/src/base/remote_gdb.cc +++ b/src/base/remote_gdb.cc @@ -459,9 +459,6 @@ BaseRemoteGDB::read(Addr vaddr, size_t size, char *data) TranslatingPort *port = context->getMemPort(); #endif port->readBlob(vaddr, (uint8_t*)data, size); -#if FULL_SYSTEM - context->delVirtPort(port); -#endif #if TRACING_ON if (DTRACE(GDBRead)) { @@ -504,9 +501,7 @@ BaseRemoteGDB::write(Addr vaddr, size_t size, const char *data) TranslatingPort *port = context->getMemPort(); #endif port->writeBlob(vaddr, (uint8_t*)data, size); -#if FULL_SYSTEM - context->delVirtPort(port); -#else +#if !FULL_SYSTEM delete port; #endif diff --git a/src/cpu/checker/thread_context.hh b/src/cpu/checker/thread_context.hh index 15454c3fe..4ede74c64 100644 --- a/src/cpu/checker/thread_context.hh +++ b/src/cpu/checker/thread_context.hh @@ -98,10 +98,8 @@ class CheckerThreadContext : public ThreadContext FunctionalPort *getPhysPort() { return actualTC->getPhysPort(); } - VirtualPort *getVirtPort(ThreadContext *tc = NULL) + VirtualPort *getVirtPort() { return actualTC->getVirtPort(); } - - void delVirtPort(VirtualPort *vp) { actualTC->delVirtPort(vp); } #else TranslatingPort *getMemPort() { return actualTC->getMemPort(); } diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index 44e26729c..66dc47f0b 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -94,9 +94,7 @@ class O3ThreadContext : public ThreadContext virtual FunctionalPort *getPhysPort() { return thread->getPhysPort(); } - virtual VirtualPort *getVirtPort(ThreadContext *src_tc = NULL); - - void delVirtPort(VirtualPort *vp); + virtual VirtualPort *getVirtPort(); virtual void connectMemPorts(ThreadContext *tc) { thread->connectMemPorts(tc); } #else diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index 865d58635..a521c3636 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -36,16 +36,9 @@ #if FULL_SYSTEM template VirtualPort * -O3ThreadContext::getVirtPort(ThreadContext *src_tc) +O3ThreadContext::getVirtPort() { - if (!src_tc) - return thread->getVirtPort(); - - VirtualPort *vp; - - vp = new VirtualPort("tc-vport", src_tc); - thread->connectToMemFunc(vp); - return vp; + return thread->getVirtPort(); } template @@ -97,18 +90,6 @@ O3ThreadContext::takeOverFrom(ThreadContext *old_context) thread->trapPending = false; } -#if FULL_SYSTEM -template -void -O3ThreadContext::delVirtPort(VirtualPort *vp) -{ - if (vp != thread->getVirtPort()) { - vp->removeConn(); - delete vp; - } -} -#endif - template void O3ThreadContext::activate(int delay) diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index b0ea2cba9..c3ea33673 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -134,10 +134,8 @@ class OzoneCPU : public BaseCPU FunctionalPort *getPhysPort() { return thread->getPhysPort(); } - VirtualPort *getVirtPort(ThreadContext *tc = NULL) - { return thread->getVirtPort(tc); } - - void delVirtPort(VirtualPort *vp); + VirtualPort *getVirtPort() + { return thread->getVirtPort(); } #else TranslatingPort *getMemPort() { return thread->getMemPort(); } diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index 0c7105382..ec531d571 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -742,16 +742,6 @@ OzoneCPU::OzoneTC::setCpuId(int id) thread->setCpuId(id); } -#if FULL_SYSTEM -template -void -OzoneCPU::OzoneTC::delVirtPort(VirtualPort *vp) -{ - vp->removeConn(); - delete vp; -} -#endif - template void OzoneCPU::OzoneTC::setStatus(Status new_status) diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index 5a5444de4..8d5c4eafb 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -286,26 +286,3 @@ SimpleThread::copyArchRegs(ThreadContext *src_tc) TheISA::copyRegs(src_tc, tc); } -#if FULL_SYSTEM -VirtualPort* -SimpleThread::getVirtPort(ThreadContext *src_tc) -{ - if (!src_tc) - return virtPort; - - VirtualPort *vp = new VirtualPort("tc-vport", src_tc); - connectToMemFunc(vp); - return vp; -} - -void -SimpleThread::delVirtPort(VirtualPort *vp) -{ - if (vp != virtPort) { - vp->removeConn(); - delete vp; - } -} - -#endif - diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index fa80a283a..37c3221f5 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -208,12 +208,11 @@ class SimpleThread : public ThreadState FunctionalPort *getPhysPort() { return physPort; } - /** Return a virtual port. If no thread context is specified then a static - * port is returned. Otherwise a port is created and returned. It must be - * deleted by deleteVirtPort(). */ - VirtualPort *getVirtPort(ThreadContext *tc); - - void delVirtPort(VirtualPort *vp); + /** 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; } #endif Status status() const { return _status; } diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index b25a67d59..b1687a494 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -130,9 +130,7 @@ class ThreadContext virtual FunctionalPort *getPhysPort() = 0; - virtual VirtualPort *getVirtPort(ThreadContext *tc = NULL) = 0; - - virtual void delVirtPort(VirtualPort *vp) = 0; + virtual VirtualPort *getVirtPort() = 0; virtual void connectMemPorts(ThreadContext *tc) = 0; #else @@ -321,9 +319,7 @@ class ProxyThreadContext : public ThreadContext FunctionalPort *getPhysPort() { return actualTC->getPhysPort(); } - VirtualPort *getVirtPort(ThreadContext *tc = NULL) { return actualTC->getVirtPort(tc); } - - void delVirtPort(VirtualPort *vp) { return actualTC->delVirtPort(vp); } + VirtualPort *getVirtPort() { return actualTC->getVirtPort(); } void connectMemPorts(ThreadContext *tc) { actualTC->connectMemPorts(tc); } #else diff --git a/src/cpu/thread_state.hh b/src/cpu/thread_state.hh index b6a62eebc..1b667f72a 100644 --- a/src/cpu/thread_state.hh +++ b/src/cpu/thread_state.hh @@ -111,9 +111,7 @@ struct ThreadState { void setPhysPort(FunctionalPort *port) { physPort = port; } - VirtualPort *getVirtPort(ThreadContext *tc = NULL) { return virtPort; } - - void setVirtPort(VirtualPort *port) { virtPort = port; } + VirtualPort *getVirtPort() { return virtPort; } #else Process *getProcessPtr() { return process; } diff --git a/src/mem/vport.cc b/src/mem/vport.cc index a2f8b1ecc..15be45c2a 100644 --- a/src/mem/vport.cc +++ b/src/mem/vport.cc @@ -78,9 +78,6 @@ CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen) VirtualPort *vp = tc->getVirtPort(); vp->readBlob(src, dst, cplen); - - tc->delVirtPort(vp); - } void @@ -90,8 +87,6 @@ CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen) VirtualPort *vp = tc->getVirtPort(); vp->writeBlob(dest, src, cplen); - - tc->delVirtPort(vp); } void @@ -105,7 +100,6 @@ CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen) vp->readBlob(vaddr++, (uint8_t*)dst++, 1); } while (len < maxlen && start[len++] != 0 ); - tc->delVirtPort(vp); dst[len] = 0; } @@ -119,5 +113,4 @@ CopyStringIn(ThreadContext *tc, char *src, Addr vaddr) vp->writeBlob(gen.addr(), (uint8_t*)src, gen.size()); src += gen.size(); } - tc->delVirtPort(vp); } diff --git a/src/sim/vptr.hh b/src/sim/vptr.hh index 88b515c13..09aa2d213 100644 --- a/src/sim/vptr.hh +++ b/src/sim/vptr.hh @@ -73,7 +73,6 @@ class VPtr VirtualPort *port = tc->getVirtPort(); port->readBlob(ptr, buffer, sizeof(T)); - tc->delVirtPort(port); } bool -- cgit v1.2.3 From 7a83c50a597f73f302ab5fcf372faa35c56a1b06 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Tue, 1 Jul 2008 10:30:08 -0400 Subject: Fix cases where RADV interrupt timer is used and make ITR interrupt moderation not always delay if no interrupts have been posted for the ITR value. --- src/dev/i8254xGBe.cc | 22 +++++++++++++++------- src/dev/i8254xGBe.hh | 1 + 2 files changed, 16 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/dev/i8254xGBe.cc b/src/dev/i8254xGBe.cc index 3b1970432..76e11b752 100644 --- a/src/dev/i8254xGBe.cc +++ b/src/dev/i8254xGBe.cc @@ -60,7 +60,8 @@ IGbE::IGbE(const Params *p) txTick(false), txFifoTick(false), rxDmaPacket(false), rdtrEvent(this), radvEvent(this), tadvEvent(this), tidvEvent(this), tickEvent(this), interEvent(this), rxDescCache(this, name()+".RxDesc", p->rx_desc_cache_size), - txDescCache(this, name()+".TxDesc", p->tx_desc_cache_size), clock(p->clock) + txDescCache(this, name()+".TxDesc", p->tx_desc_cache_size), + clock(p->clock), lastInterrupt(0) { etherInt = new IGbEInt(name() + ".int", this); @@ -580,17 +581,22 @@ IGbE::postInterrupt(IntTypes t, bool now) return; regs.icr = regs.icr() | t; - if (regs.itr.interval() == 0 || now) { + + Tick itr_interval = Clock::Int::ns * 256 * regs.itr.interval(); + + if (regs.itr.interval() == 0 || now || lastInterrupt + itr_interval <= curTick) { if (interEvent.scheduled()) { interEvent.deschedule(); } postedInterrupts++; cpuPostInt(); } else { - DPRINTF(EthernetIntr, "EINT: Scheduling timer interrupt for %d ticks\n", - Clock::Int::ns * 256 * regs.itr.interval()); + Tick int_time = lastInterrupt + itr_interval; + assert(int_time > 0); + DPRINTF(EthernetIntr, "EINT: Scheduling timer interrupt for tick %d\n", + int_time); if (!interEvent.scheduled()) { - interEvent.schedule(curTick + Clock::Int::ns * 256 * regs.itr.interval()); + interEvent.schedule(int_time); } } } @@ -789,7 +795,7 @@ IGbE::RxDescCache::pktComplete() igbe->intClock(),true); } - if (igbe->regs.radv.idv() && igbe->regs.rdtr.delay()) { + if (igbe->regs.radv.idv()) { DPRINTF(EthernetSM, "RXS: Scheduling ADV for %d\n", igbe->regs.radv.idv() * igbe->intClock()); if (!igbe->radvEvent.scheduled()) { @@ -799,7 +805,7 @@ IGbE::RxDescCache::pktComplete() } // if neither radv or rdtr, maybe itr is set... - if (!igbe->regs.rdtr.delay()) { + if (!igbe->regs.rdtr.delay() && !igbe->regs.radv.idv()) { DPRINTF(EthernetSM, "RXS: Receive interrupt delay disabled, posting IT_RXT\n"); igbe->postInterrupt(IT_RXT); } @@ -1446,6 +1452,7 @@ IGbE::serialize(std::ostream &os) SERIALIZE_SCALAR(eeDataBits); SERIALIZE_SCALAR(eeOpcode); SERIALIZE_SCALAR(eeAddr); + SERIALIZE_SCALAR(lastInterrupt); SERIALIZE_ARRAY(flash,iGbReg::EEPROM_SIZE); rxFifo.serialize("rxfifo", os); @@ -1497,6 +1504,7 @@ IGbE::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(eeDataBits); UNSERIALIZE_SCALAR(eeOpcode); UNSERIALIZE_SCALAR(eeAddr); + UNSERIALIZE_SCALAR(lastInterrupt); UNSERIALIZE_ARRAY(flash,iGbReg::EEPROM_SIZE); rxFifo.unserialize("rxfifo", cp, section); diff --git a/src/dev/i8254xGBe.hh b/src/dev/i8254xGBe.hh index 7957eb515..a69793bd4 100644 --- a/src/dev/i8254xGBe.hh +++ b/src/dev/i8254xGBe.hh @@ -622,6 +622,7 @@ class IGbE : public EtherDevice virtual EtherInt *getEthPort(const std::string &if_name, int idx); Tick clock; + Tick lastInterrupt; inline Tick ticks(int numCycles) const { return numCycles * clock; } virtual Tick read(PacketPtr pkt); -- cgit v1.2.3 From 93517dd90cf232b779beeebb162984d543e7e33c Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 10 Jul 2008 21:35:42 -0700 Subject: eventq: Clean up the Event class so that it uses fewer bytes. This will hopefullly allow it to fit in a cache line. --- src/sim/eventq.cc | 27 ++++----- src/sim/eventq.hh | 157 ++++++++++++++++++++++++++------------------------ src/sim/sim_events.cc | 2 +- 3 files changed, 94 insertions(+), 92 deletions(-) (limited to 'src') diff --git a/src/sim/eventq.cc b/src/sim/eventq.cc index 2c679be1e..ab0ba9385 100644 --- a/src/sim/eventq.cc +++ b/src/sim/eventq.cc @@ -30,18 +30,16 @@ * Steve Raasch */ -#include - +#include #include #include #include -#include "cpu/smt.hh" #include "base/misc.hh" - -#include "sim/eventq.hh" #include "base/trace.hh" +#include "cpu/smt.hh" #include "sim/core.hh" +#include "sim/eventq.hh" using namespace std; @@ -203,7 +201,7 @@ EventQueue::unserialize(Checkpoint *cp, const std::string §ion) } void -EventQueue::dump() +EventQueue::dump() const { cprintf("============================================================\n"); cprintf("EventQueue Dump (cycle %d)\n", curTick); @@ -235,7 +233,6 @@ Event::description() const return "generic"; } -#if TRACING_ON void Event::trace(const char *action) { @@ -250,23 +247,21 @@ Event::trace(const char *action) // needs to be printed. DPRINTFN("%s event %s @ %d\n", description(), action, when()); } -#endif void -Event::dump() +Event::dump() const { - cprintf("Event (%s)\n", description()); + cprintf("Event %s (%s)\n", name(), description()); cprintf("Flags: %#x\n", _flags); -#if TRACING_ON - cprintf("Created: %d\n", when_created); +#ifdef EVENTQ_DEBUG + cprintf("Created: %d\n", whenCreated); #endif if (scheduled()) { -#if TRACING_ON - cprintf("Scheduled at %d\n", when_scheduled); +#ifdef EVENTQ_DEBUG + cprintf("Scheduled at %d\n", whenScheduled); #endif cprintf("Scheduled for %d, priority %d\n", when(), _priority); - } - else { + } else { cprintf("Not Scheduled\n"); } } diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index a454e5d64..ea950e625 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -36,19 +36,17 @@ #ifndef __SIM_EVENTQ_HH__ #define __SIM_EVENTQ_HH__ -#include - #include +#include #include #include #include -#include "sim/host.hh" // for Tick - #include "base/fast_alloc.hh" #include "base/misc.hh" #include "base/trace.hh" #include "sim/serialize.hh" +#include "sim/host.hh" class EventQueue; // forward declaration @@ -64,17 +62,27 @@ class EventQueue; // forward declaration ////////////////////// extern EventQueue mainEventQueue; - /* * An item on an event queue. The action caused by a given * event is specified by deriving a subclass and overriding the * process() member function. + * + * Caution, the order of members is chosen to maximize data packing. */ class Event : public Serializable, public FastAlloc { friend class EventQueue; private: + Event *next; + + /// queue to which this event belongs (though it may or may not be + /// scheduled on this queue yet) + EventQueue *_queue; + + Tick _when; //!< timestamp when event should be processed + short _priority; //!< event priority + short _flags; #ifndef NDEBUG /// Global counter to generate unique IDs for Event instances @@ -84,19 +92,13 @@ class Event : public Serializable, public FastAlloc /// this but they're not consistent across runs making debugging /// more difficult. Thus we use a global counter value when /// debugging. - Counter instanceId; -#endif // NDEBUG - - /// queue to which this event belongs (though it may or may not be - /// scheduled on this queue yet) - EventQueue *queue; - - Event *next; - - Tick _when; //!< timestamp when event should be processed - int _priority; //!< event priority - char _flags; + Counter instance; +#endif +#ifdef DEBUG_EVENTQ + Tick whenCreated; //!< time created + Tick whenScheduled; //!< time scheduled +#endif protected: enum Flags { None = 0x0, @@ -112,26 +114,20 @@ class Event : public Serializable, public FastAlloc void clearFlags(Flags f) { _flags &= ~f; } protected: - EventQueue *theQueue() const { return queue; } - -#if TRACING_ON - Tick when_created; //!< Keep track of creation time For debugging - Tick when_scheduled; //!< Keep track of creation time For debugging + EventQueue *queue() const { return _queue; } + // This function isn't really useful if TRACING_ON is not defined virtual void trace(const char *action); //!< trace event activity -#else - void trace(const char *) {} -#endif - - unsigned annotated_value; public: - /// Event priorities, to provide tie-breakers for events scheduled /// at the same cycle. Most events are scheduled at the default /// priority; these values are used to control events that need to /// be ordered within a cycle. enum Priority { + /// Minimum priority + Minimum_Pri = SHRT_MIN, + /// If we enable tracing on a particular cycle, do that as the /// very first thing so we don't miss any of the events on /// that cycle (even if we enter the debugger). @@ -174,7 +170,10 @@ class Event : public Serializable, public FastAlloc /// If we want to exit on this cycle, it's the very last thing /// we do. - Sim_Exit_Pri = 100 + Sim_Exit_Pri = 100, + + /// Maximum priority + Maximum_Pri = SHRT_MAX }; /* @@ -182,48 +181,41 @@ class Event : public Serializable, public FastAlloc * @param queue that the event gets scheduled on */ Event(EventQueue *q, Priority p = Default_Pri) - : queue(q), next(NULL), _priority(p), _flags(None), -#if TRACING_ON - when_created(curTick), when_scheduled(0), -#endif - annotated_value(0) + : next(NULL), _queue(q), _priority(p), _flags(None) { #ifndef NDEBUG - instanceId = ++instanceCounter; + instance = ++instanceCounter; +#endif +#ifdef EVENTQ_DEBUG + whenCreated = curTick; + whenScheduled = 0; #endif } - ~Event() {} + virtual + ~Event() + { + } - virtual const std::string name() const { + virtual const std::string + name() const + { #ifndef NDEBUG - return csprintf("Event_%d", instanceId); + return csprintf("Event_%d", instance); #else return csprintf("Event_%x", (uintptr_t)this); #endif } - /// Determine if the current event is scheduled - bool scheduled() const { return getFlags(Scheduled); } - - /// Schedule the event with the current priority or default priority - void schedule(Tick t); - - /// Reschedule the event with the current priority - // always parameter means to schedule if not already scheduled - void reschedule(Tick t, bool always = false); - - /// Remove the event from the current schedule - void deschedule(); - /// Return a C string describing the event. This string should /// *not* be dynamically allocated; just a const char array /// describing the event class. virtual const char *description() const; /// Dump the current event data - void dump(); + void dump() const; + public: /* * This member function is invoked when the event is processed * (occurs). There is no default implementation; each subclass @@ -236,17 +228,27 @@ class Event : public Serializable, public FastAlloc */ virtual void process() = 0; - void annotate(unsigned value) { annotated_value = value; }; - unsigned annotation() { return annotated_value; } + /// Determine if the current event is scheduled + bool scheduled() const { return getFlags(Scheduled); } + + /// Schedule the event with the current priority or default priority + void schedule(Tick t); + + /// Reschedule the event with the current priority + // always parameter means to schedule if not already scheduled + void reschedule(Tick t, bool always = false); + + /// Remove the event from the current schedule + void deschedule(); /// Squash the current event void squash() { setFlags(Squashed); } /// Check whether the event is squashed - bool squashed() { return getFlags(Squashed); } + bool squashed() const { return getFlags(Squashed); } /// See if this is a SimExitEvent (without resorting to RTTI) - bool isExitEvent() { return getFlags(IsExitEvent); } + bool isExitEvent() const { return getFlags(IsExitEvent); } /// Get the time that the event is scheduled Tick when() const { return _when; } @@ -254,10 +256,12 @@ class Event : public Serializable, public FastAlloc /// Get the event priority int priority() const { return _priority; } - struct priority_compare : - public std::binary_function + struct priority_compare + : public std::binary_function { - bool operator()(const Event *l, const Event *r) const { + bool + operator()(const Event *l, const Event *r) const + { return l->when() >= r->when() || l->priority() >= r->priority(); } }; @@ -343,13 +347,15 @@ class EventQueue : public Serializable void deschedule(Event *ev); void reschedule(Event *ev); - Tick nextTick() { return head->when(); } + Tick nextTick() const { return head->when(); } Event *serviceOne(); // process all events up to the given timestamp. we inline a // quick test to see if there are any events to process; if so, // call the internal out-of-line version to process them all. - void serviceEvents(Tick when) { + void + serviceEvents(Tick when) + { while (!empty()) { if (nextTick() > when) break; @@ -367,9 +373,9 @@ class EventQueue : public Serializable void serviceEvents() { serviceEvents(curTick); } // return true if no events are queued - bool empty() { return head == NULL; } + bool empty() const { return head == NULL; } - void dump(); + void dump() const; Tick nextEventTime() { return empty() ? curTick : head->when(); } @@ -393,15 +399,14 @@ inline void Event::schedule(Tick t) { assert(!scheduled()); -// if (t < curTick) -// warn("t is less than curTick, ensure you don't want cycles"); + assert(t >= curTick); setFlags(Scheduled); -#if TRACING_ON - when_scheduled = curTick; +#ifdef DEBUG_EVENTQ + whenScheduled = curTick; #endif _when = t; - queue->schedule(this); + _queue->schedule(this); } inline void @@ -411,25 +416,26 @@ Event::deschedule() clearFlags(Squashed); clearFlags(Scheduled); - queue->deschedule(this); + _queue->deschedule(this); } inline void Event::reschedule(Tick t, bool always) { assert(scheduled() || always); + assert(t >= curTick); -#if TRACING_ON - when_scheduled = curTick; +#ifdef DEBUG_EVENTQ + whenScheduled = curTick; #endif _when = t; if (scheduled()) { clearFlags(Squashed); - queue->reschedule(this); + _queue->reschedule(this); } else { setFlags(Scheduled); - queue->schedule(this); + _queue->schedule(this); } } @@ -447,6 +453,9 @@ EventQueue::deschedule(Event *event) remove(event); if (DTRACE(Event)) event->trace("descheduled"); + + if (event->getFlags(Event::AutoDelete)) + delete event; } inline void @@ -458,6 +467,4 @@ EventQueue::reschedule(Event *event) event->trace("rescheduled"); } - - #endif // __SIM_EVENTQ_HH__ diff --git a/src/sim/sim_events.cc b/src/sim/sim_events.cc index 09087ef84..5fe59286c 100644 --- a/src/sim/sim_events.cc +++ b/src/sim/sim_events.cc @@ -49,7 +49,7 @@ SimLoopExitEvent::process() // if this got scheduled on a different queue (e.g. the committed // instruction queue) then make a corresponding event on the main // queue. - if (theQueue() != &mainEventQueue) { + if (queue() != &mainEventQueue) { exitSimLoop(cause, code); delete this; } -- cgit v1.2.3 From 10df68dd727d37876f3d9526739b1c49d195e222 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 11 Jul 2008 08:38:31 -0700 Subject: eventq: new eventq data structure. The new data structure is singly linked list sorted by time and priority. For things of the same time and priority, a second, circularly linked list maintains the data structure. Events of the same time and priority are now inserted in FIFO order instead of LIFO order. This dramatically improves the performance of systems that schedule multiple events at the same time. The FIFO order version is not preferred to LIFO (because it may cause people to rely on it), but I'm going to commit it anyway and immediately commit the preferred LIFO version on top. --- src/sim/eventq.cc | 222 +++++++++++++++++++++++++++++++++++++++++++----------- src/sim/eventq.hh | 132 +++++++++++++++++++++++--------- 2 files changed, 277 insertions(+), 77 deletions(-) (limited to 'src') diff --git a/src/sim/eventq.cc b/src/sim/eventq.cc index ab0ba9385..2b61df26e 100644 --- a/src/sim/eventq.cc +++ b/src/sim/eventq.cc @@ -1,5 +1,6 @@ /* * Copyright (c) 2000-2005 The Regents of The University of Michigan + * Copyright (c) 2008 The Hewlett-Packard Development Company * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,6 +36,7 @@ #include #include +#include "base/hashmap.hh" #include "base/misc.hh" #include "base/trace.hh" #include "cpu/smt.hh" @@ -55,61 +57,140 @@ EventQueue mainEventQueue("MainEventQueue"); Counter Event::instanceCounter = 0; #endif +inline void +insertBefore(Event *event, Event *curr) +{ + // Either way, event will be the last element in the 'in bin' list + // which is the pointer we need in order to look into the list, so + // we need to insert that into the bin list. + if (!curr || *event < *curr) { + // Insert the event before the current list since it is in the future. + event->nextBin = curr; + + // We need to create a new 'in bin' list + event->nextInBin = event; + } else { + // Since we're on the correct list, we need to point to the next list + event->nextBin = curr->nextBin; // curr->nextBin can now become stale + + // Insert event at the end of the 'nextInBin' curr is the last + // element on the 'in bin' list and curr->nextInBin is the first + + event->nextInBin = curr->nextInBin; // event->nextInBin needs to + // point to the first + curr->nextInBin = event; // curr->nextInBin is now second to last + } +} + void EventQueue::insert(Event *event) { - if (head == NULL || event->when() < head->when() || - (event->when() == head->when() && - event->priority() <= head->priority())) { - event->next = head; + // Deal with the head case + if (!head || *event <= *head) { + insertBefore(event, head); head = event; - } else { - Event *prev = head; - Event *curr = head->next; + return; + } - while (curr) { - if (event->when() <= curr->when() && - (event->when() < curr->when() || - event->priority() <= curr->priority())) - break; + // Figure out either which 'in bin' list we are on, or where a new list + // needs to be inserted + Event *curr = head; + Event *next = head->nextBin; + while (next && *next < *event) { + curr = next; + next = next->nextBin; + } - prev = curr; - curr = curr->next; - } + insertBefore(event, next); + curr->nextBin = event; // all nextBin pointers on the curr + // 'in bin' list are now stale +} + +inline Event * +removeItem(Event *event, Event *last) +{ + Event *prev = last; + Event *curr = last->nextInBin; + + while (event != curr) { + if (curr == last) + panic("event not found!"); - event->next = curr; - prev->next = event; + prev = curr; + curr = curr->nextInBin; } + + // If this was the only item in this list, we're done. + if (prev == curr) + return NULL; + + // remove curr from the 'in bin' list since it's what we're looking for + prev->nextInBin = curr->nextInBin; + + // If we didn't remove the last item, we're done + if (curr != last) + return last; + + // if we removed the last item, the new last item is prev + // fix it up since it might be stale and return it + prev->nextBin = last->nextBin; + return prev; } void EventQueue::remove(Event *event) { if (head == NULL) - return; - - if (head == event){ - head = event->next; + panic("event not found!"); + + // deal with an event on the head's 'in bin' list (event has the same + // time as the head) + if (*head == *event) { + head = removeItem(event, head); + if (!head) + head = event->nextBin; return; } + // Find the 'in bin' list that this event belongs on Event *prev = head; - Event *curr = head->next; - while (curr && curr != event) { + Event *curr = head->nextBin; + while (curr && *curr < *event) { prev = curr; - curr = curr->next; + curr = curr->nextBin; } - if (curr == event) - prev->next = curr->next; + if (!curr || *curr != *event) + panic("event not found!"); + + // curr points to the last item of the the correct 'in bin' list, when + // we remove an item, it returns the new last item (which may be + // unchanged) + Event *last = removeItem(event, curr); + if (!last) { + // The current item was removed, so we need to fix the bin list + prev->nextBin = curr->nextBin; + } else if (last != curr) { + // We have a new last item, so we need to update the bin list + prev->nextBin = last; + } } Event * EventQueue::serviceOne() { - Event *event = head; + // grab the first element + Event *event = head->nextInBin; event->clearFlags(Event::Scheduled); - head = event->next; + + if (head == event) { + // this was the only element on the 'in bin' list, so get rid of + // the 'in bin' list and point to the next bin list + head = event->nextBin; + } else { + // maintain head->nextInBin as the first element + head->nextInBin = event->nextInBin; + } // handle action if (!event->squashed()) { @@ -128,7 +209,6 @@ EventQueue::serviceOne() return NULL; } - void Event::serialize(std::ostream &os) { @@ -137,7 +217,6 @@ Event::serialize(std::ostream &os) SERIALIZE_ENUM(_flags); } - void Event::unserialize(Checkpoint *cp, const string §ion) { @@ -166,18 +245,25 @@ EventQueue::serialize(ostream &os) std::list eventPtrs; int numEvents = 0; - Event *event = head; - while (event) { - if (event->getFlags(Event::AutoSerialize)) { - eventPtrs.push_back(event); - paramOut(os, csprintf("event%d", numEvents++), event->name()); - } - event = event->next; + Event *nextBin = head; + while (nextBin) { + Event *nextInBin = nextBin->nextInBin; + + do { + if (nextInBin->getFlags(Event::AutoSerialize)) { + eventPtrs.push_back(nextInBin); + paramOut(os, csprintf("event%d", numEvents++), + nextInBin->name()); + } + nextInBin = nextInBin->nextInBin; + } while (nextInBin != nextBin); + + nextBin = nextBin->nextBin; } SERIALIZE_SCALAR(numEvents); - for (std::list::iterator it=eventPtrs.begin(); + for (std::list::iterator it = eventPtrs.begin(); it != eventPtrs.end(); ++it) { (*it)->nameOut(os); (*it)->serialize(os); @@ -207,19 +293,71 @@ EventQueue::dump() const cprintf("EventQueue Dump (cycle %d)\n", curTick); cprintf("------------------------------------------------------------\n"); + m5::hash_map map; + if (empty()) cprintf("\n"); else { - Event *event = head; - while (event) { - event->dump(); - event = event->next; + Event *nextBin = head; + while (nextBin) { + Event *nextInBin = nextBin; + if (map[reinterpret_cast(nextInBin)]) + break; + map[reinterpret_cast(nextInBin)] = true; + do { + nextInBin = nextInBin->nextInBin; + nextInBin->dump(); + } while (nextInBin != nextBin); + + nextBin = nextBin->nextBin; } } cprintf("============================================================\n"); } +bool +EventQueue::debugVerify() const +{ + m5::hash_map map; + + Tick time = 0; + short priority = 0; + + Event *nextBin = head; + while (nextBin) { + Event *nextInBin = nextBin->nextInBin; + do { + if (nextInBin->when() < time) { + cprintf("time goes backwards!"); + nextInBin->dump(); + return false; + } else if (nextInBin->when() == time && + nextInBin->priority() < priority) { + cprintf("priority inverted!"); + nextInBin->dump(); + return false; + } + + if (map[reinterpret_cast(nextInBin)]) { + cprintf("Node already seen"); + nextInBin->dump(); + return false; + } + map[reinterpret_cast(nextInBin)] = true; + + time = nextInBin->when(); + priority = nextInBin->priority(); + + nextInBin = nextInBin->nextInBin; + } while (nextInBin != nextBin); + + nextBin = nextBin->nextBin; + } + + return true; +} + void dumpMainQueue() { diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index ea950e625..10c0048a8 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -74,7 +74,20 @@ class Event : public Serializable, public FastAlloc friend class EventQueue; private: - Event *next; + // The event queue is now a linked list of linked lists. The + // 'nextBin' pointer is to find the bin, where a bin is defined as + // when+priority. All events in the same bin will be stored in a + // second circularly linked list maintained by the 'nextInBin' + // pointer. The list will be accessed in FIFO order. The end + // result is that the insert/removal in 'nextBin' is + // linear/constant, and the lookup/removal in 'nextInBin' is + // constant/constant. Hopefully this is a significant improvement + // over the current fully linear insertion. + Event *nextBin; + Event *nextInBin; + + friend void insertBefore(Event *event, Event *curr); + friend Event *removeItem(Event *event, Event *last); /// queue to which this event belongs (though it may or may not be /// scheduled on this queue yet) @@ -99,6 +112,17 @@ class Event : public Serializable, public FastAlloc Tick whenCreated; //!< time created Tick whenScheduled; //!< time scheduled #endif + + protected: + void + setWhen(Tick when) + { + _when = when; +#ifdef DEBUG_EVENTQ + whenScheduled = curTick; +#endif + } + protected: enum Flags { None = 0x0, @@ -181,7 +205,7 @@ class Event : public Serializable, public FastAlloc * @param queue that the event gets scheduled on */ Event(EventQueue *q, Priority p = Default_Pri) - : next(NULL), _queue(q), _priority(p), _flags(None) + : nextBin(NULL), nextInBin(NULL), _queue(q), _priority(p), _flags(None) { #ifndef NDEBUG instance = ++instanceCounter; @@ -343,9 +367,9 @@ class EventQueue : public Serializable virtual const std::string name() const { return objName; } // schedule the given event on this queue - void schedule(Event *ev); + void schedule(Event *ev, Tick when); void deschedule(Event *ev); - void reschedule(Event *ev); + void reschedule(Event *ev, Tick when); Tick nextTick() const { return head->when(); } Event *serviceOne(); @@ -379,6 +403,8 @@ class EventQueue : public Serializable Tick nextEventTime() { return empty() ? curTick : head->when(); } + bool debugVerify() const; + virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); }; @@ -396,53 +422,77 @@ class EventQueue : public Serializable // schedule at specified time (place on event queue specified via // constructor) inline void -Event::schedule(Tick t) +Event::schedule(Tick when) { - assert(!scheduled()); - assert(t >= curTick); - - setFlags(Scheduled); -#ifdef DEBUG_EVENTQ - whenScheduled = curTick; -#endif - _when = t; - _queue->schedule(this); + _queue->schedule(this, when); } inline void Event::deschedule() { - assert(scheduled()); - - clearFlags(Squashed); - clearFlags(Scheduled); _queue->deschedule(this); } inline void -Event::reschedule(Tick t, bool always) +Event::reschedule(Tick when, bool always) { - assert(scheduled() || always); - assert(t >= curTick); - -#ifdef DEBUG_EVENTQ - whenScheduled = curTick; -#endif - _when = t; - if (scheduled()) { - clearFlags(Squashed); - _queue->reschedule(this); + _queue->reschedule(this, when); } else { - setFlags(Scheduled); - _queue->schedule(this); + assert(always); + _queue->schedule(this, when); } } +inline bool +operator<(const Event &l, const Event &r) +{ + return l.when() < r.when() || + (l.when() == r.when() && l.priority() < r.priority()); +} + +inline bool +operator>(const Event &l, const Event &r) +{ + return l.when() > r.when() || + (l.when() == r.when() && l.priority() > r.priority()); +} + +inline bool +operator<=(const Event &l, const Event &r) +{ + return l.when() < r.when() || + (l.when() == r.when() && l.priority() <= r.priority()); +} +inline bool +operator>=(const Event &l, const Event &r) +{ + return l.when() > r.when() || + (l.when() == r.when() && l.priority() >= r.priority()); +} + +inline bool +operator==(const Event &l, const Event &r) +{ + return l.when() == r.when() && l.priority() == r.priority(); +} + +inline bool +operator!=(const Event &l, const Event &r) +{ + return l.when() != r.when() || l.priority() != r.priority(); +} + inline void -EventQueue::schedule(Event *event) +EventQueue::schedule(Event *event, Tick when) { + assert(when >= curTick); + assert(!event->scheduled()); + + event->setWhen(when); insert(event); + event->setFlags(Event::Scheduled); + if (DTRACE(Event)) event->trace("scheduled"); } @@ -450,19 +500,31 @@ EventQueue::schedule(Event *event) inline void EventQueue::deschedule(Event *event) { + assert(event->scheduled()); + remove(event); - if (DTRACE(Event)) - event->trace("descheduled"); + + event->clearFlags(Event::Squashed); + event->clearFlags(Event::Scheduled); if (event->getFlags(Event::AutoDelete)) delete event; + + if (DTRACE(Event)) + event->trace("descheduled"); } inline void -EventQueue::reschedule(Event *event) +EventQueue::reschedule(Event *event, Tick when) { + assert(when >= curTick); + assert(event->scheduled()); + remove(event); + event->setWhen(when); insert(event); + event->clearFlags(Event::Squashed); + if (DTRACE(Event)) event->trace("rescheduled"); } -- cgit v1.2.3 From f90b08a5ccd83800e0263e6e13af7d8c87b3cdf4 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 11 Jul 2008 08:48:50 -0700 Subject: eventq: change the event datastructure back to LIFO. The status quo is preferred since it is less likely that people will rely on LIFO than FIFO, and when we move to a parallelized M5, no ordering between events of the same time/priority will be guaranteed. --- src/sim/eventq.cc | 136 ++++++++++++++++++++++++------------------------------ src/sim/eventq.hh | 6 +-- 2 files changed, 63 insertions(+), 79 deletions(-) (limited to 'src') diff --git a/src/sim/eventq.cc b/src/sim/eventq.cc index 2b61df26e..4f0b51e08 100644 --- a/src/sim/eventq.cc +++ b/src/sim/eventq.cc @@ -57,29 +57,25 @@ EventQueue mainEventQueue("MainEventQueue"); Counter Event::instanceCounter = 0; #endif -inline void +inline Event * insertBefore(Event *event, Event *curr) { - // Either way, event will be the last element in the 'in bin' list + // Either way, event will be the top element in the 'in bin' list // which is the pointer we need in order to look into the list, so // we need to insert that into the bin list. if (!curr || *event < *curr) { // Insert the event before the current list since it is in the future. event->nextBin = curr; - - // We need to create a new 'in bin' list - event->nextInBin = event; + event->nextInBin = NULL; } else { // Since we're on the correct list, we need to point to the next list event->nextBin = curr->nextBin; // curr->nextBin can now become stale - // Insert event at the end of the 'nextInBin' curr is the last - // element on the 'in bin' list and curr->nextInBin is the first - - event->nextInBin = curr->nextInBin; // event->nextInBin needs to - // point to the first - curr->nextInBin = event; // curr->nextInBin is now second to last + // Insert event at the top of the stack + event->nextInBin = curr; } + + return event; } void @@ -87,54 +83,53 @@ EventQueue::insert(Event *event) { // Deal with the head case if (!head || *event <= *head) { - insertBefore(event, head); - head = event; + head = insertBefore(event, head); return; } // Figure out either which 'in bin' list we are on, or where a new list // needs to be inserted - Event *curr = head; - Event *next = head->nextBin; - while (next && *next < *event) { - curr = next; - next = next->nextBin; + Event *prev = head; + Event *curr = head->nextBin; + while (curr && *curr < *event) { + prev = curr; + curr = curr->nextBin; } - insertBefore(event, next); - curr->nextBin = event; // all nextBin pointers on the curr - // 'in bin' list are now stale + // Note: this operation may render all nextBin pointers on the + // prev 'in bin' list stale (except for the top one) + prev->nextBin = insertBefore(event, curr); } inline Event * -removeItem(Event *event, Event *last) +removeItem(Event *event, Event *top) { - Event *prev = last; - Event *curr = last->nextInBin; + Event *curr = top; + Event *next = top->nextInBin; + + // if we removed the top item, we need to handle things specially + // and just remove the top item, fixing up the next bin pointer of + // the new top item + if (event == top) { + if (!next) + return top->nextBin; + next->nextBin = top->nextBin; + return next; + } - while (event != curr) { - if (curr == last) + // Since we already checked the current element, we're going to + // keep checking event against the next element. + while (event != next) { + if (!next) panic("event not found!"); - prev = curr; - curr = curr->nextInBin; + curr = next; + next = next->nextInBin; } - // If this was the only item in this list, we're done. - if (prev == curr) - return NULL; - - // remove curr from the 'in bin' list since it's what we're looking for - prev->nextInBin = curr->nextInBin; - - // If we didn't remove the last item, we're done - if (curr != last) - return last; - - // if we removed the last item, the new last item is prev - // fix it up since it might be stale and return it - prev->nextBin = last->nextBin; - return prev; + // remove next from the 'in bin' list since it's what we're looking for + curr->nextInBin = next->nextInBin; + return top; } void @@ -147,8 +142,6 @@ EventQueue::remove(Event *event) // time as the head) if (*head == *event) { head = removeItem(event, head); - if (!head) - head = event->nextBin; return; } @@ -163,33 +156,29 @@ EventQueue::remove(Event *event) if (!curr || *curr != *event) panic("event not found!"); - // curr points to the last item of the the correct 'in bin' list, when - // we remove an item, it returns the new last item (which may be + // curr points to the top item of the the correct 'in bin' list, when + // we remove an item, it returns the new top item (which may be // unchanged) - Event *last = removeItem(event, curr); - if (!last) { - // The current item was removed, so we need to fix the bin list - prev->nextBin = curr->nextBin; - } else if (last != curr) { - // We have a new last item, so we need to update the bin list - prev->nextBin = last; - } + prev->nextBin = removeItem(event, curr); } Event * EventQueue::serviceOne() { - // grab the first element - Event *event = head->nextInBin; + Event *event = head; + Event *next = head->nextInBin; event->clearFlags(Event::Scheduled); - if (head == event) { + if (next) { + // update the next bin pointer since it could be stale + next->nextBin = head->nextBin; + + // pop the stack + head = next; + } else { // this was the only element on the 'in bin' list, so get rid of // the 'in bin' list and point to the next bin list - head = event->nextBin; - } else { - // maintain head->nextInBin as the first element - head->nextInBin = event->nextInBin; + head = head->nextBin; } // handle action @@ -247,16 +236,16 @@ EventQueue::serialize(ostream &os) int numEvents = 0; Event *nextBin = head; while (nextBin) { - Event *nextInBin = nextBin->nextInBin; + Event *nextInBin = nextBin; - do { + while (nextInBin) { if (nextInBin->getFlags(Event::AutoSerialize)) { eventPtrs.push_back(nextInBin); paramOut(os, csprintf("event%d", numEvents++), nextInBin->name()); } nextInBin = nextInBin->nextInBin; - } while (nextInBin != nextBin); + } nextBin = nextBin->nextBin; } @@ -293,21 +282,16 @@ EventQueue::dump() const cprintf("EventQueue Dump (cycle %d)\n", curTick); cprintf("------------------------------------------------------------\n"); - m5::hash_map map; - if (empty()) cprintf("\n"); else { Event *nextBin = head; while (nextBin) { Event *nextInBin = nextBin; - if (map[reinterpret_cast(nextInBin)]) - break; - map[reinterpret_cast(nextInBin)] = true; - do { - nextInBin = nextInBin->nextInBin; + while (nextInBin) { nextInBin->dump(); - } while (nextInBin != nextBin); + nextInBin = nextInBin->nextInBin; + } nextBin = nextBin->nextBin; } @@ -326,8 +310,8 @@ EventQueue::debugVerify() const Event *nextBin = head; while (nextBin) { - Event *nextInBin = nextBin->nextInBin; - do { + Event *nextInBin = nextBin; + while (nextInBin) { if (nextInBin->when() < time) { cprintf("time goes backwards!"); nextInBin->dump(); @@ -350,7 +334,7 @@ EventQueue::debugVerify() const priority = nextInBin->priority(); nextInBin = nextInBin->nextInBin; - } while (nextInBin != nextBin); + } nextBin = nextBin->nextBin; } diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index 10c0048a8..bc9b2353f 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -77,8 +77,8 @@ class Event : public Serializable, public FastAlloc // The event queue is now a linked list of linked lists. The // 'nextBin' pointer is to find the bin, where a bin is defined as // when+priority. All events in the same bin will be stored in a - // second circularly linked list maintained by the 'nextInBin' - // pointer. The list will be accessed in FIFO order. The end + // second linked list (a stack) maintained by the 'nextInBin' + // pointer. The list will be accessed in LIFO order. The end // result is that the insert/removal in 'nextBin' is // linear/constant, and the lookup/removal in 'nextInBin' is // constant/constant. Hopefully this is a significant improvement @@ -86,7 +86,7 @@ class Event : public Serializable, public FastAlloc Event *nextBin; Event *nextInBin; - friend void insertBefore(Event *event, Event *curr); + friend Event *insertBefore(Event *event, Event *curr); friend Event *removeItem(Event *event, Event *last); /// queue to which this event belongs (though it may or may not be -- cgit v1.2.3 From 88766f7c7116d148c5bb47bffa2d76d8c1203b88 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 11 Jul 2008 08:52:50 -0700 Subject: style: fix indentation and formatting of the pseudo insts. --- src/sim/pseudo_inst.cc | 389 +++++++++++++++++++++++++------------------------ src/sim/pseudo_inst.hh | 56 +++---- 2 files changed, 225 insertions(+), 220 deletions(-) (limited to 'src') diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index 157d39e93..ec384a4c5 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -55,255 +55,258 @@ using namespace std; using namespace Stats; using namespace TheISA; -namespace PseudoInst +namespace PseudoInst { + +void +arm(ThreadContext *tc) { - void - arm(ThreadContext *tc) - { - if (tc->getKernelStats()) - tc->getKernelStats()->arm(); - } + if (tc->getKernelStats()) + tc->getKernelStats()->arm(); +} - void - quiesce(ThreadContext *tc) - { - if (!tc->getCpuPtr()->params->do_quiesce) - return; +void +quiesce(ThreadContext *tc) +{ + if (!tc->getCpuPtr()->params->do_quiesce) + return; - DPRINTF(Quiesce, "%s: quiesce()\n", tc->getCpuPtr()->name()); + DPRINTF(Quiesce, "%s: quiesce()\n", tc->getCpuPtr()->name()); - tc->suspend(); - if (tc->getKernelStats()) - tc->getKernelStats()->quiesce(); - } + tc->suspend(); + if (tc->getKernelStats()) + tc->getKernelStats()->quiesce(); +} - void - quiesceNs(ThreadContext *tc, uint64_t ns) - { - if (!tc->getCpuPtr()->params->do_quiesce || ns == 0) - return; +void +quiesceNs(ThreadContext *tc, uint64_t ns) +{ + if (!tc->getCpuPtr()->params->do_quiesce || ns == 0) + return; - EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent(); + EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent(); - Tick resume = curTick + Clock::Int::ns * ns; + Tick resume = curTick + Clock::Int::ns * ns; - quiesceEvent->reschedule(resume, true); + quiesceEvent->reschedule(resume, true); - DPRINTF(Quiesce, "%s: quiesceNs(%d) until %d\n", - tc->getCpuPtr()->name(), ns, resume); + DPRINTF(Quiesce, "%s: quiesceNs(%d) until %d\n", + tc->getCpuPtr()->name(), ns, resume); - tc->suspend(); - if (tc->getKernelStats()) - tc->getKernelStats()->quiesce(); - } + tc->suspend(); + if (tc->getKernelStats()) + tc->getKernelStats()->quiesce(); +} - void - quiesceCycles(ThreadContext *tc, uint64_t cycles) - { - if (!tc->getCpuPtr()->params->do_quiesce || cycles == 0) - return; +void +quiesceCycles(ThreadContext *tc, uint64_t cycles) +{ + if (!tc->getCpuPtr()->params->do_quiesce || cycles == 0) + return; - EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent(); + EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent(); - Tick resume = curTick + tc->getCpuPtr()->ticks(cycles); + Tick resume = curTick + tc->getCpuPtr()->ticks(cycles); - quiesceEvent->reschedule(resume, true); + quiesceEvent->reschedule(resume, true); - DPRINTF(Quiesce, "%s: quiesceCycles(%d) until %d\n", - tc->getCpuPtr()->name(), cycles, resume); + DPRINTF(Quiesce, "%s: quiesceCycles(%d) until %d\n", + tc->getCpuPtr()->name(), cycles, resume); - tc->suspend(); - if (tc->getKernelStats()) - tc->getKernelStats()->quiesce(); - } + tc->suspend(); + if (tc->getKernelStats()) + tc->getKernelStats()->quiesce(); +} - uint64_t - quiesceTime(ThreadContext *tc) - { - return (tc->readLastActivate() - tc->readLastSuspend()) / Clock::Int::ns; - } +uint64_t +quiesceTime(ThreadContext *tc) +{ + return (tc->readLastActivate() - tc->readLastSuspend()) / Clock::Int::ns; +} - void - m5exit_old(ThreadContext *tc) - { - exitSimLoop("m5_exit_old instruction encountered"); - } +void +m5exit_old(ThreadContext *tc) +{ + exitSimLoop("m5_exit_old instruction encountered"); +} - void - m5exit(ThreadContext *tc, Tick delay) - { - Tick when = curTick + delay * Clock::Int::ns; - schedExitSimLoop("m5_exit instruction encountered", when); - } +void +m5exit(ThreadContext *tc, Tick delay) +{ + Tick when = curTick + delay * Clock::Int::ns; + schedExitSimLoop("m5_exit instruction encountered", when); +} - void - loadsymbol(ThreadContext *tc) - { - const string &filename = tc->getCpuPtr()->system->params()->symbolfile; - if (filename.empty()) { - return; - } +void +loadsymbol(ThreadContext *tc) +{ + const string &filename = tc->getCpuPtr()->system->params()->symbolfile; + if (filename.empty()) { + return; + } - std::string buffer; - ifstream file(filename.c_str()); + std::string buffer; + ifstream file(filename.c_str()); - if (!file) - fatal("file error: Can't open symbol table file %s\n", filename); + if (!file) + fatal("file error: Can't open symbol table file %s\n", filename); - while (!file.eof()) { - getline(file, buffer); + while (!file.eof()) { + getline(file, buffer); - if (buffer.empty()) - continue; + if (buffer.empty()) + continue; - int idx = buffer.find(' '); - if (idx == string::npos) - continue; + int idx = buffer.find(' '); + if (idx == string::npos) + continue; - string address = "0x" + buffer.substr(0, idx); - eat_white(address); - if (address.empty()) - continue; + string address = "0x" + buffer.substr(0, idx); + eat_white(address); + if (address.empty()) + continue; - // Skip over letter and space - string symbol = buffer.substr(idx + 3); - eat_white(symbol); - if (symbol.empty()) - continue; + // Skip over letter and space + string symbol = buffer.substr(idx + 3); + eat_white(symbol); + if (symbol.empty()) + continue; - Addr addr; - if (!to_number(address, addr)) - continue; + Addr addr; + if (!to_number(address, addr)) + continue; - if (!tc->getSystemPtr()->kernelSymtab->insert(addr, symbol)) - continue; + if (!tc->getSystemPtr()->kernelSymtab->insert(addr, symbol)) + continue; - DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr); - } - file.close(); + DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr); } + file.close(); +} - void - resetstats(ThreadContext *tc, Tick delay, Tick period) - { - if (!tc->getCpuPtr()->params->do_statistics_insts) - return; +void +resetstats(ThreadContext *tc, Tick delay, Tick period) +{ + if (!tc->getCpuPtr()->params->do_statistics_insts) + return; - Tick when = curTick + delay * Clock::Int::ns; - Tick repeat = period * Clock::Int::ns; + Tick when = curTick + delay * Clock::Int::ns; + Tick repeat = period * Clock::Int::ns; - Stats::StatEvent(false, true, when, repeat); - } + Stats::StatEvent(false, true, when, repeat); +} - void - dumpstats(ThreadContext *tc, Tick delay, Tick period) - { - if (!tc->getCpuPtr()->params->do_statistics_insts) - return; +void +dumpstats(ThreadContext *tc, Tick delay, Tick period) +{ + if (!tc->getCpuPtr()->params->do_statistics_insts) + return; - Tick when = curTick + delay * Clock::Int::ns; - Tick repeat = period * Clock::Int::ns; + Tick when = curTick + delay * Clock::Int::ns; + Tick repeat = period * Clock::Int::ns; - Stats::StatEvent(true, false, when, repeat); - } + Stats::StatEvent(true, false, when, repeat); +} - void - addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr) - { - char symb[100]; - CopyStringOut(tc, symb, symbolAddr, 100); - std::string symbol(symb); +void +addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr) +{ + char symb[100]; + CopyStringOut(tc, symb, symbolAddr, 100); + std::string symbol(symb); - DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr); + DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr); - tc->getSystemPtr()->kernelSymtab->insert(addr,symbol); - } + tc->getSystemPtr()->kernelSymtab->insert(addr,symbol); +} - void - anBegin(ThreadContext *tc, uint64_t cur) - { - Annotate::annotations.add(tc->getSystemPtr(), 0, cur >> 32, cur & - 0xFFFFFFFF, 0,0); - } +void +anBegin(ThreadContext *tc, uint64_t cur) +{ + Annotate::annotations.add(tc->getSystemPtr(), 0, cur >> 32, cur & + 0xFFFFFFFF, 0,0); +} - void - anWait(ThreadContext *tc, uint64_t cur, uint64_t wait) - { - Annotate::annotations.add(tc->getSystemPtr(), 0, cur >> 32, cur & - 0xFFFFFFFF, wait >> 32, wait & 0xFFFFFFFF); - } +void +anWait(ThreadContext *tc, uint64_t cur, uint64_t wait) +{ + Annotate::annotations.add(tc->getSystemPtr(), 0, cur >> 32, cur & + 0xFFFFFFFF, wait >> 32, wait & 0xFFFFFFFF); +} - void - dumpresetstats(ThreadContext *tc, Tick delay, Tick period) - { - if (!tc->getCpuPtr()->params->do_statistics_insts) - return; +void +dumpresetstats(ThreadContext *tc, Tick delay, Tick period) +{ + if (!tc->getCpuPtr()->params->do_statistics_insts) + return; - Tick when = curTick + delay * Clock::Int::ns; - Tick repeat = period * Clock::Int::ns; + Tick when = curTick + delay * Clock::Int::ns; + Tick repeat = period * Clock::Int::ns; - Stats::StatEvent(true, true, when, repeat); - } + Stats::StatEvent(true, true, when, repeat); +} + +void +m5checkpoint(ThreadContext *tc, Tick delay, Tick period) +{ + if (!tc->getCpuPtr()->params->do_checkpoint_insts) + return; - void - m5checkpoint(ThreadContext *tc, Tick delay, Tick period) - { - if (!tc->getCpuPtr()->params->do_checkpoint_insts) - return; + Tick when = curTick + delay * Clock::Int::ns; + Tick repeat = period * Clock::Int::ns; - Tick when = curTick + delay * Clock::Int::ns; - Tick repeat = period * Clock::Int::ns; + schedExitSimLoop("checkpoint", when, repeat); +} - schedExitSimLoop("checkpoint", when, repeat); +uint64_t +readfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset) +{ + const string &file = tc->getSystemPtr()->params()->readfile; + if (file.empty()) { + return ULL(0); } - uint64_t - readfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset) - { - const string &file = tc->getSystemPtr()->params()->readfile; - if (file.empty()) { - return ULL(0); - } - - uint64_t result = 0; - - int fd = ::open(file.c_str(), O_RDONLY, 0); - if (fd < 0) - panic("could not open file %s\n", file); - - if (::lseek(fd, offset, SEEK_SET) < 0) - panic("could not seek: %s", strerror(errno)); - - char *buf = new char[len]; - char *p = buf; - while (len > 0) { - int bytes = ::read(fd, p, len); - if (bytes <= 0) - break; - - p += bytes; - result += bytes; - len -= bytes; - } - - close(fd); - CopyIn(tc, vaddr, buf, result); - delete [] buf; - return result; - } + uint64_t result = 0; - void debugbreak(ThreadContext *tc) - { - debug_break(); - } + int fd = ::open(file.c_str(), O_RDONLY, 0); + if (fd < 0) + panic("could not open file %s\n", file); + + if (::lseek(fd, offset, SEEK_SET) < 0) + panic("could not seek: %s", strerror(errno)); - void switchcpu(ThreadContext *tc) - { - exitSimLoop("switchcpu"); + char *buf = new char[len]; + char *p = buf; + while (len > 0) { + int bytes = ::read(fd, p, len); + if (bytes <= 0) + break; + + p += bytes; + result += bytes; + len -= bytes; } + + close(fd); + CopyIn(tc, vaddr, buf, result); + delete [] buf; + return result; } + +void +debugbreak(ThreadContext *tc) +{ + debug_break(); +} + +void +switchcpu(ThreadContext *tc) +{ + exitSimLoop("switchcpu"); +} + +/* namespace PseudoInst */ } diff --git a/src/sim/pseudo_inst.hh b/src/sim/pseudo_inst.hh index 93021abad..d94b358e5 100644 --- a/src/sim/pseudo_inst.hh +++ b/src/sim/pseudo_inst.hh @@ -33,31 +33,33 @@ class ThreadContext; //We need the "Tick" and "Addr" data types from here #include "sim/host.hh" -namespace PseudoInst -{ - /** - * @todo these externs are only here for a hack in fullCPU::takeOver... - */ - extern bool doStatisticsInsts; - extern bool doCheckpointInsts; - extern bool doQuiesce; +namespace PseudoInst { - void arm(ThreadContext *tc); - void quiesce(ThreadContext *tc); - void quiesceNs(ThreadContext *tc, uint64_t ns); - void quiesceCycles(ThreadContext *tc, uint64_t cycles); - uint64_t quiesceTime(ThreadContext *tc); - void m5exit(ThreadContext *tc, Tick delay); - void m5exit_old(ThreadContext *tc); - void loadsymbol(ThreadContext *xc); - void resetstats(ThreadContext *tc, Tick delay, Tick period); - void dumpstats(ThreadContext *tc, Tick delay, Tick period); - void dumpresetstats(ThreadContext *tc, Tick delay, Tick period); - void m5checkpoint(ThreadContext *tc, Tick delay, Tick period); - uint64_t readfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset); - void debugbreak(ThreadContext *tc); - void switchcpu(ThreadContext *tc); - void addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr); - void anBegin(ThreadContext *tc, uint64_t cur); - void anWait(ThreadContext *tc, uint64_t cur, uint64_t wait); -} +/** + * @todo these externs are only here for a hack in fullCPU::takeOver... + */ +extern bool doStatisticsInsts; +extern bool doCheckpointInsts; +extern bool doQuiesce; + +void arm(ThreadContext *tc); +void quiesce(ThreadContext *tc); +void quiesceNs(ThreadContext *tc, uint64_t ns); +void quiesceCycles(ThreadContext *tc, uint64_t cycles); +uint64_t quiesceTime(ThreadContext *tc); +void m5exit(ThreadContext *tc, Tick delay); +void m5exit_old(ThreadContext *tc); +void loadsymbol(ThreadContext *xc); +void resetstats(ThreadContext *tc, Tick delay, Tick period); +void dumpstats(ThreadContext *tc, Tick delay, Tick period); +void dumpresetstats(ThreadContext *tc, Tick delay, Tick period); +void m5checkpoint(ThreadContext *tc, Tick delay, Tick period); +uint64_t readfile(ThreadContext *tc, Addr vaddr, uint64_t len, + uint64_t offset); +void debugbreak(ThreadContext *tc); +void switchcpu(ThreadContext *tc); +void addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr); +void anBegin(ThreadContext *tc, uint64_t cur); +void anWait(ThreadContext *tc, uint64_t cur, uint64_t wait); + +/* namespace PsuedoInst */ } -- cgit v1.2.3 From f9a597ddf307246b1aee915b59de503d2850ccce Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 11 Jul 2008 08:52:50 -0700 Subject: m5ops: clean up the m5ops stuff. - insert warnings for deprecated m5ops - reserve opcodes for Ali's stuff - remove code for stuff that has been deprecated forever - simplify m5op_alpha --- src/arch/alpha/isa/decoder.isa | 34 +++++++++++++++++++++++----------- src/sim/pseudo_inst.cc | 21 --------------------- src/sim/pseudo_inst.hh | 3 --- 3 files changed, 23 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/isa/decoder.isa b/src/arch/alpha/isa/decoder.isa index 2177e8c4f..dc30039b2 100644 --- a/src/arch/alpha/isa/decoder.isa +++ b/src/arch/alpha/isa/decoder.isa @@ -806,14 +806,15 @@ decode OPCODE default Unknown::unknown() { 0x04: quiesceTime({{ R0 = PseudoInst::quiesceTime(xc->tcBase()); }}, IsNonSpeculative, IsUnverifiable); - 0x10: ivlb({{ - warn_once("Obsolete M5 instruction ivlb encountered.\n"); + 0x10: deprecated_ivlb({{ + warn_once("Obsolete M5 ivlb instruction encountered.\n"); }}); - 0x11: ivle({{ - warn_once("Obsolete M5 instruction ivlb encountered.\n"); + 0x11: deprecated_ivle({{ + warn_once("Obsolete M5 ivlb instruction encountered.\n"); }}); - 0x20: m5exit_old({{ - PseudoInst::m5exit_old(xc->tcBase()); + 0x20: deprecated_exit ({{ + warn_once("deprecated M5 exit instruction encountered.\n"); + PseudoInst::m5exit(xc->tcBase(), 0); }}, No_OpClass, IsNonSpeculative); 0x21: m5exit({{ PseudoInst::m5exit(xc->tcBase(), R16); @@ -821,7 +822,9 @@ decode OPCODE default Unknown::unknown() { 0x31: loadsymbol({{ PseudoInst::loadsymbol(xc->tcBase()); }}, No_OpClass, IsNonSpeculative); - 0x30: initparam({{ Ra = xc->tcBase()->getCpuPtr()->system->init_param; }}); + 0x30: initparam({{ + Ra = xc->tcBase()->getCpuPtr()->system->init_param; + }}); 0x40: resetstats({{ PseudoInst::resetstats(xc->tcBase(), R16, R17); }}, IsNonSpeculative); @@ -849,11 +852,20 @@ decode OPCODE default Unknown::unknown() { 0x54: m5panic({{ panic("M5 panic instruction called at pc=%#x.", xc->readPC()); }}, IsNonSpeculative); - 0x55: m5anBegin({{ - PseudoInst::anBegin(xc->tcBase(), R16); + 0x55: m5reserved1({{ + warn("M5 reserved opcode ignored"); + }}, IsNonSpeculative); + 0x56: m5reserved2({{ + warn("M5 reserved opcode ignored"); + }}, IsNonSpeculative); + 0x57: m5reserved3({{ + warn("M5 reserved opcode ignored"); + }}, IsNonSpeculative); + 0x58: m5reserved4({{ + warn("M5 reserved opcode ignored"); }}, IsNonSpeculative); - 0x56: m5anWait({{ - PseudoInst::anWait(xc->tcBase(), R16, R17); + 0x59: m5reserved5({{ + warn("M5 reserved opcode ignored"); }}, IsNonSpeculative); } } diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index ec384a4c5..60a74b224 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -123,12 +123,6 @@ quiesceTime(ThreadContext *tc) return (tc->readLastActivate() - tc->readLastSuspend()) / Clock::Int::ns; } -void -m5exit_old(ThreadContext *tc) -{ - exitSimLoop("m5_exit_old instruction encountered"); -} - void m5exit(ThreadContext *tc, Tick delay) { @@ -222,21 +216,6 @@ addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr) tc->getSystemPtr()->kernelSymtab->insert(addr,symbol); } -void -anBegin(ThreadContext *tc, uint64_t cur) -{ - Annotate::annotations.add(tc->getSystemPtr(), 0, cur >> 32, cur & - 0xFFFFFFFF, 0,0); -} - -void -anWait(ThreadContext *tc, uint64_t cur, uint64_t wait) -{ - Annotate::annotations.add(tc->getSystemPtr(), 0, cur >> 32, cur & - 0xFFFFFFFF, wait >> 32, wait & 0xFFFFFFFF); -} - - void dumpresetstats(ThreadContext *tc, Tick delay, Tick period) { diff --git a/src/sim/pseudo_inst.hh b/src/sim/pseudo_inst.hh index d94b358e5..40702fced 100644 --- a/src/sim/pseudo_inst.hh +++ b/src/sim/pseudo_inst.hh @@ -48,7 +48,6 @@ void quiesceNs(ThreadContext *tc, uint64_t ns); void quiesceCycles(ThreadContext *tc, uint64_t cycles); uint64_t quiesceTime(ThreadContext *tc); void m5exit(ThreadContext *tc, Tick delay); -void m5exit_old(ThreadContext *tc); void loadsymbol(ThreadContext *xc); void resetstats(ThreadContext *tc, Tick delay, Tick period); void dumpstats(ThreadContext *tc, Tick delay, Tick period); @@ -59,7 +58,5 @@ uint64_t readfile(ThreadContext *tc, Addr vaddr, uint64_t len, void debugbreak(ThreadContext *tc); void switchcpu(ThreadContext *tc); void addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr); -void anBegin(ThreadContext *tc, uint64_t cur); -void anWait(ThreadContext *tc, uint64_t cur, uint64_t wait); /* namespace PsuedoInst */ } -- cgit v1.2.3 From 6262e0d9095215effc8d73297f3eedfddc1c2796 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Tue, 15 Jul 2008 14:38:51 -0400 Subject: Add missing newlines to Bus DPRINTFs. --- src/mem/bus.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/mem/bus.cc b/src/mem/bus.cc index 606402a1e..41e9f0ac9 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -331,10 +331,10 @@ Bus::findPort(Addr addr) if (responderSet) { panic("Unable to find destination for addr (user set default " - "responder): %#llx", addr); + "responder): %#llx\n", addr); } else { DPRINTF(Bus, "Unable to find destination for addr: %#llx, will use " - "default port", addr); + "default port\n", addr); return defaultId; } -- cgit v1.2.3 From 8e7ddce28493c93564aeb20f1856fbe6bff0ece4 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Tue, 15 Jul 2008 14:38:51 -0400 Subject: Use ReadResp instead of LoadLockedResp for LoadLockedReq responses. --- src/cpu/simple/timing.cc | 4 +++- src/mem/packet.cc | 8 +++----- src/mem/packet.hh | 1 - 3 files changed, 6 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index b86d4b2d7..4451dfe81 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -730,7 +730,9 @@ TimingSimpleCPU::completeDataAccess(PacketPtr pkt) traceData = NULL; } - if (pkt->isRead() && pkt->isLocked()) { + // the locked flag may be cleared on the response packet, so check + // pkt->req and not pkt to see if it was a load-locked + if (pkt->isRead() && pkt->req->isLocked()) { TheISA::handleLockedRead(thread, pkt->req); } diff --git a/src/mem/packet.cc b/src/mem/packet.cc index f3bd06f36..35fd44e5b 100644 --- a/src/mem/packet.cc +++ b/src/mem/packet.cc @@ -101,12 +101,10 @@ MemCmd::commandInfo[] = /* ReadExResp */ { SET4(IsRead, NeedsExclusive, IsResponse, HasData), InvalidCmd, "ReadExResp" }, - /* LoadLockedReq */ + /* LoadLockedReq: note that we use plain ReadResp as response, so that + * we can also use ReadRespWithInvalidate when needed */ { SET4(IsRead, IsLocked, IsRequest, NeedsResponse), - LoadLockedResp, "LoadLockedReq" }, - /* LoadLockedResp */ - { SET4(IsRead, IsLocked, IsResponse, HasData), - InvalidCmd, "LoadLockedResp" }, + ReadResp, "LoadLockedReq" }, /* StoreCondReq */ { SET6(IsWrite, NeedsExclusive, IsLocked, IsRequest, NeedsResponse, HasData), diff --git a/src/mem/packet.hh b/src/mem/packet.hh index a278a3945..36aff5b42 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -81,7 +81,6 @@ class MemCmd ReadExReq, ReadExResp, LoadLockedReq, - LoadLockedResp, StoreCondReq, StoreCondResp, SwapReq, -- cgit v1.2.3 From aa2bb4f7b9ec571a4430da25173fbb76d1b0c8bb Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Tue, 15 Jul 2008 14:38:51 -0400 Subject: Get rid of useless m5_assert macro. Its only purpose was to print the cycle number but that already happens in the SIGABRT handler. No one used it anyway. --- src/base/misc.hh | 9 --------- 1 file changed, 9 deletions(-) (limited to 'src') diff --git a/src/base/misc.hh b/src/base/misc.hh index 1509ea2d2..6b0025c34 100644 --- a/src/base/misc.hh +++ b/src/base/misc.hh @@ -113,13 +113,4 @@ __warn(const char *func, const char *file, int line, const std::string &format, } \ } while (0) -// -// assert() that prints out the current cycle -// -#define m5_assert(TEST) do { \ - if (!(TEST)) \ - ccprintf(std::cerr, "Assertion failure, curTick = %d\n", curTick); \ - assert(TEST); \ -} while (0) - #endif // __MISC_HH__ -- cgit v1.2.3 From 8c4f18f6f5e5dd9ccc4ef54590a11d70ba001264 Mon Sep 17 00:00:00 2001 From: Michael Adler Date: Wed, 23 Jul 2008 14:41:33 -0700 Subject: RemoteGDB: add an m5 command line option for setting or disabling remote gdb. --- src/python/m5/main.py | 3 +++ src/python/swig/debug.i | 7 ++----- src/sim/debug.cc | 17 +++++++++++++++++ src/sim/debug.hh | 7 +++++++ src/sim/process.cc | 13 ++++++++----- src/sim/system.cc | 6 ++++-- 6 files changed, 41 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/python/m5/main.py b/src/python/m5/main.py index dbabd9600..2bbd72152 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -102,6 +102,8 @@ add_option("--stats-file", metavar="FILE", default="m5stats.txt", set_group("Debugging Options") add_option("--debug-break", metavar="TIME[,TIME]", action='append', split=',', help="Cycle to create a breakpoint") +add_option("--remote-gdb-port", type='int', default=7000, + help="Remote gdb base port") # Tracing options set_group("Trace Options") @@ -256,6 +258,7 @@ def main(): internal.stats.initText(options.stats_file) # set debugging options + internal.debug.setRemoteGDBPort(options.remote_gdb_port) for when in options.debug_break: internal.debug.schedBreakCycle(int(when)) diff --git a/src/python/swig/debug.i b/src/python/swig/debug.i index b542e9f82..1084d6936 100644 --- a/src/python/swig/debug.i +++ b/src/python/swig/debug.i @@ -31,16 +31,13 @@ %module debug %{ -// include these files when compiling debug_wrap.cc #include "sim/host.hh" +#include "sim/debug.hh" %} %include "stdint.i" %include "sim/host.hh" - -%inline %{ -extern void schedBreakCycle(Tick when); -%} +%include "sim/debug.hh" %wrapper %{ // fix up module name to reflect the fact that it's inside the m5 package diff --git a/src/sim/debug.cc b/src/sim/debug.cc index b4f4cd9dc..36ac4efac 100644 --- a/src/sim/debug.cc +++ b/src/sim/debug.cc @@ -108,3 +108,20 @@ eventqDump() mainEventQueue.dump(); } + +int remote_gdb_base_port = 7000; + +int +getRemoteGDBPort() +{ + return remote_gdb_base_port; +} + +// Set remote GDB base port. 0 means disable remote GDB. +// Callable from python. +void +setRemoteGDBPort(int port) +{ + remote_gdb_base_port = port; +} + diff --git a/src/sim/debug.hh b/src/sim/debug.hh index 79792234b..937864e69 100644 --- a/src/sim/debug.hh +++ b/src/sim/debug.hh @@ -31,6 +31,13 @@ #ifndef __DEBUG_HH__ #define __DEBUG_HH__ +#include "sim/host.hh" + +void schedBreakCycle(Tick when); void debug_break(); +int getRemoteGDBPort(); +// Remote gdb base port. 0 disables remote gdb. +void setRemoteGDBPort(int port); + #endif // __DEBUG_HH__ diff --git a/src/sim/process.cc b/src/sim/process.cc index 16037b2f4..046a6bf9b 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -46,6 +46,7 @@ #include "mem/translating_port.hh" #include "params/Process.hh" #include "params/LiveProcess.hh" +#include "sim/debug.hh" #include "sim/process.hh" #include "sim/process_impl.hh" #include "sim/stats.hh" @@ -201,12 +202,14 @@ Process::registerThreadContext(ThreadContext *tc) int myIndex = threadContexts.size(); threadContexts.push_back(tc); - RemoteGDB *rgdb = new RemoteGDB(system, tc); - GDBListener *gdbl = new GDBListener(rgdb, 7000 + myIndex); - gdbl->listen(); - //gdbl->accept(); + int port = getRemoteGDBPort(); + if (port) { + RemoteGDB *rgdb = new RemoteGDB(system, tc); + GDBListener *gdbl = new GDBListener(rgdb, port + myIndex); + gdbl->listen(); - remoteGDB.push_back(rgdb); + remoteGDB.push_back(rgdb); + } // return CPU number to caller return myIndex; diff --git a/src/sim/system.cc b/src/sim/system.cc index 10b9b1217..803881539 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -42,6 +42,7 @@ #include "mem/physical.hh" #include "sim/byteswap.hh" #include "sim/system.hh" +#include "sim/debug.hh" #if FULL_SYSTEM #include "arch/vtophys.hh" #include "kern/kernel_stats.hh" @@ -183,9 +184,10 @@ System::registerThreadContext(ThreadContext *tc, int id) threadContexts[id] = tc; numcpus++; - if (rgdb_enable) { + int port = getRemoteGDBPort(); + if (rgdb_enable && port) { RemoteGDB *rgdb = new RemoteGDB(this, tc); - GDBListener *gdbl = new GDBListener(rgdb, 7000 + id); + GDBListener *gdbl = new GDBListener(rgdb, port + id); gdbl->listen(); /** * Uncommenting this line waits for a remote debugger to -- cgit v1.2.3 From 2cd04fd6da67d874fd4e563ed05707a42ff0598f Mon Sep 17 00:00:00 2001 From: Michael Adler Date: Wed, 23 Jul 2008 14:41:33 -0700 Subject: syscalls: Add a bunch of missing system calls. readlink, umask, truncate, ftruncate, mkdir, and getcwd. --- src/arch/alpha/linux/process.cc | 12 +++--- src/arch/alpha/tru64/process.cc | 6 +-- src/arch/mips/linux/process.cc | 8 ++-- src/arch/sparc/linux/syscalls.cc | 10 ++--- src/arch/sparc/solaris/process.cc | 4 +- src/sim/process.hh | 2 + src/sim/syscall_emul.cc | 82 +++++++++++++++++++++++++++++++++++++++ src/sim/syscall_emul.hh | 17 ++++++++ 8 files changed, 121 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/linux/process.cc b/src/arch/alpha/linux/process.cc index ec47992bd..0a9d2f1a3 100644 --- a/src/arch/alpha/linux/process.cc +++ b/src/arch/alpha/linux/process.cc @@ -179,9 +179,9 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = { /* 55 */ SyscallDesc("osf_reboot", unimplementedFunc), /* 56 */ SyscallDesc("osf_revoke", unimplementedFunc), /* 57 */ SyscallDesc("symlink", unimplementedFunc), - /* 58 */ SyscallDesc("readlink", unimplementedFunc), + /* 58 */ SyscallDesc("readlink", readlinkFunc), /* 59 */ SyscallDesc("execve", unimplementedFunc), - /* 60 */ SyscallDesc("umask", unimplementedFunc), + /* 60 */ SyscallDesc("umask", umaskFunc), /* 61 */ SyscallDesc("chroot", unimplementedFunc), /* 62 */ SyscallDesc("osf_old_fstat", unimplementedFunc), /* 63 */ SyscallDesc("getpgrp", unimplementedFunc), @@ -250,14 +250,14 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = { /* 126 */ SyscallDesc("setreuid", unimplementedFunc), /* 127 */ SyscallDesc("setregid", unimplementedFunc), /* 128 */ SyscallDesc("rename", renameFunc), - /* 129 */ SyscallDesc("truncate", unimplementedFunc), - /* 130 */ SyscallDesc("ftruncate", unimplementedFunc), + /* 129 */ SyscallDesc("truncate", truncateFunc), + /* 130 */ SyscallDesc("ftruncate", ftruncateFunc), /* 131 */ SyscallDesc("flock", unimplementedFunc), /* 132 */ SyscallDesc("setgid", unimplementedFunc), /* 133 */ SyscallDesc("sendto", unimplementedFunc), /* 134 */ SyscallDesc("shutdown", unimplementedFunc), /* 135 */ SyscallDesc("socketpair", unimplementedFunc), - /* 136 */ SyscallDesc("mkdir", unimplementedFunc), + /* 136 */ SyscallDesc("mkdir", mkdirFunc), /* 137 */ SyscallDesc("rmdir", unimplementedFunc), /* 138 */ SyscallDesc("osf_utimes", unimplementedFunc), /* 139 */ SyscallDesc("osf_old_sigreturn", unimplementedFunc), @@ -491,7 +491,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = { /* 364 */ SyscallDesc("getrusage", getrusageFunc), /* 365 */ SyscallDesc("wait4", unimplementedFunc), /* 366 */ SyscallDesc("adjtimex", unimplementedFunc), - /* 367 */ SyscallDesc("getcwd", unimplementedFunc), + /* 367 */ SyscallDesc("getcwd", getcwdFunc), /* 368 */ SyscallDesc("capget", unimplementedFunc), /* 369 */ SyscallDesc("capset", unimplementedFunc), /* 370 */ SyscallDesc("sendfile", unimplementedFunc), diff --git a/src/arch/alpha/tru64/process.cc b/src/arch/alpha/tru64/process.cc index 6823d820a..e9f7b6be1 100644 --- a/src/arch/alpha/tru64/process.cc +++ b/src/arch/alpha/tru64/process.cc @@ -260,9 +260,9 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = { /* 55 */ SyscallDesc("reboot", unimplementedFunc), /* 56 */ SyscallDesc("revoke", unimplementedFunc), /* 57 */ SyscallDesc("symlink", unimplementedFunc), - /* 58 */ SyscallDesc("readlink", unimplementedFunc), + /* 58 */ SyscallDesc("readlink", readlinkFunc), /* 59 */ SyscallDesc("execve", unimplementedFunc), - /* 60 */ SyscallDesc("umask", unimplementedFunc), + /* 60 */ SyscallDesc("umask", umaskFunc), /* 61 */ SyscallDesc("chroot", unimplementedFunc), /* 62 */ SyscallDesc("old_fstat", unimplementedFunc), /* 63 */ SyscallDesc("getpgrp", unimplementedFunc), @@ -339,7 +339,7 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = { /* 133 */ SyscallDesc("sendto", unimplementedFunc), /* 134 */ SyscallDesc("shutdown", unimplementedFunc), /* 135 */ SyscallDesc("socketpair", unimplementedFunc), - /* 136 */ SyscallDesc("mkdir", unimplementedFunc), + /* 136 */ SyscallDesc("mkdir", mkdirFunc), /* 137 */ SyscallDesc("rmdir", unimplementedFunc), /* 138 */ SyscallDesc("utimes", unimplementedFunc), /* 139 */ SyscallDesc("obsolete 4.2 sigreturn", unimplementedFunc), diff --git a/src/arch/mips/linux/process.cc b/src/arch/mips/linux/process.cc index 06e6e2cf4..8a13d0f18 100644 --- a/src/arch/mips/linux/process.cc +++ b/src/arch/mips/linux/process.cc @@ -160,7 +160,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 36 */ SyscallDesc("sync", unimplementedFunc), /* 37 */ SyscallDesc("kill", unimplementedFunc), /* 38 */ SyscallDesc("rename", unimplementedFunc), - /* 39 */ SyscallDesc("mkdir", unimplementedFunc), + /* 39 */ SyscallDesc("mkdir", mkdirFunc), /* 40 */ SyscallDesc("rmdir", unimplementedFunc), /* 41 */ SyscallDesc("dup", unimplementedFunc), /* 42 */ SyscallDesc("pipe", pipePseudoFunc), @@ -181,7 +181,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 57 */ SyscallDesc("setpgid", unimplementedFunc), /* 58 */ SyscallDesc("ulimit", unimplementedFunc), /* 59 */ SyscallDesc("unused#59", unimplementedFunc), - /* 60 */ SyscallDesc("umask", unimplementedFunc), + /* 60 */ SyscallDesc("umask", umaskFunc), /* 61 */ SyscallDesc("chroot", unimplementedFunc), /* 62 */ SyscallDesc("ustat", unimplementedFunc), /* 63 */ SyscallDesc("dup2", unimplementedFunc), @@ -206,7 +206,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 82 */ SyscallDesc("reserved#82", unimplementedFunc), /* 83 */ SyscallDesc("symlink", unimplementedFunc), /* 84 */ SyscallDesc("unused#84", unimplementedFunc), - /* 85 */ SyscallDesc("readlink", unimplementedFunc), + /* 85 */ SyscallDesc("readlink", readlinkFunc), /* 86 */ SyscallDesc("uselib", unimplementedFunc), /* 87 */ SyscallDesc("swapon", gethostnameFunc), /* 88 */ SyscallDesc("reboot", unimplementedFunc), @@ -324,7 +324,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 200 */ SyscallDesc("pread64", unimplementedFunc), /* 201 */ SyscallDesc("pwrite64", unimplementedFunc), /* 202 */ SyscallDesc("chown", unimplementedFunc), - /* 203 */ SyscallDesc("getcwd", unimplementedFunc), + /* 203 */ SyscallDesc("getcwd", getcwdFunc), /* 204 */ SyscallDesc("capget", unimplementedFunc), /* 205 */ SyscallDesc("capset", unimplementedFunc), /* 206 */ SyscallDesc("sigalstack", unimplementedFunc), diff --git a/src/arch/sparc/linux/syscalls.cc b/src/arch/sparc/linux/syscalls.cc index 03c8bafe2..2964b3c1a 100644 --- a/src/arch/sparc/linux/syscalls.cc +++ b/src/arch/sparc/linux/syscalls.cc @@ -147,7 +147,7 @@ SyscallDesc SparcLinuxProcess::syscall32Descs[] = { /* 55 */ SyscallDesc("reboot", unimplementedFunc), //32 bit /* 56 */ SyscallDesc("mmap2", unimplementedFunc), //32 bit /* 57 */ SyscallDesc("symlink", unimplementedFunc), - /* 58 */ SyscallDesc("readlink", unimplementedFunc), //32 bit + /* 58 */ SyscallDesc("readlink", readlinkFunc), //32 bit /* 59 */ SyscallDesc("execve", unimplementedFunc), //32 bit /* 60 */ SyscallDesc("umask", unimplementedFunc), //32 bit /* 61 */ SyscallDesc("chroot", unimplementedFunc), @@ -208,7 +208,7 @@ SyscallDesc SparcLinuxProcess::syscall32Descs[] = { /* 116 */ SyscallDesc("gettimeofday", unimplementedFunc), //32 bit /* 117 */ SyscallDesc("getrusage", unimplementedFunc), //32 bit /* 118 */ SyscallDesc("getsockopt", unimplementedFunc), - /* 119 */ SyscallDesc("getcwd", unimplementedFunc), + /* 119 */ SyscallDesc("getcwd", getcwdFunc), /* 120 */ SyscallDesc("readv", unimplementedFunc), /* 121 */ SyscallDesc("writev", unimplementedFunc), /* 122 */ SyscallDesc("settimeofday", unimplementedFunc), //32 bit @@ -225,7 +225,7 @@ SyscallDesc SparcLinuxProcess::syscall32Descs[] = { /* 133 */ SyscallDesc("sendto", unimplementedFunc), /* 134 */ SyscallDesc("shutdown", unimplementedFunc), /* 135 */ SyscallDesc("socketpair", unimplementedFunc), - /* 136 */ SyscallDesc("mkdir", unimplementedFunc), //32 bit + /* 136 */ SyscallDesc("mkdir", mkdirFunc), //32 bit /* 137 */ SyscallDesc("rmdir", unimplementedFunc), /* 138 */ SyscallDesc("utimes", unimplementedFunc), //32 bit /* 139 */ SyscallDesc("stat64", unimplementedFunc), @@ -450,7 +450,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = { /* 55 */ SyscallDesc("reboot", unimplementedFunc), /* 56 */ SyscallDesc("mmap2", unimplementedFunc), /* 57 */ SyscallDesc("symlink", unimplementedFunc), - /* 58 */ SyscallDesc("readlink", unimplementedFunc), + /* 58 */ SyscallDesc("readlink", readlinkFunc), /* 59 */ SyscallDesc("execve", unimplementedFunc), /* 60 */ SyscallDesc("umask", unimplementedFunc), /* 61 */ SyscallDesc("chroot", unimplementedFunc), @@ -528,7 +528,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = { /* 133 */ SyscallDesc("sendto", unimplementedFunc), /* 134 */ SyscallDesc("shutdown", unimplementedFunc), /* 135 */ SyscallDesc("socketpair", unimplementedFunc), - /* 136 */ SyscallDesc("mkdir", unimplementedFunc), + /* 136 */ SyscallDesc("mkdir", mkdirFunc), /* 137 */ SyscallDesc("rmdir", unimplementedFunc), /* 138 */ SyscallDesc("utimes", unimplementedFunc), /* 139 */ SyscallDesc("stat64", unimplementedFunc), diff --git a/src/arch/sparc/solaris/process.cc b/src/arch/sparc/solaris/process.cc index 40d172690..e0c3eaa4b 100644 --- a/src/arch/sparc/solaris/process.cc +++ b/src/arch/sparc/solaris/process.cc @@ -123,7 +123,7 @@ SyscallDesc SparcSolarisProcess::syscallDescs[] = { /* 57 */ SyscallDesc("utssys", unimplementedFunc), /* 58 */ SyscallDesc("fdsync", unimplementedFunc), /* 59 */ SyscallDesc("execve", unimplementedFunc), - /* 60 */ SyscallDesc("umask", unimplementedFunc), + /* 60 */ SyscallDesc("umask", umaskFunc), /* 61 */ SyscallDesc("chroot", unimplementedFunc), /* 62 */ SyscallDesc("fcntl", unimplementedFunc), /* 63 */ SyscallDesc("ulimit", unimplementedFunc), @@ -153,7 +153,7 @@ SyscallDesc SparcSolarisProcess::syscallDescs[] = { /* 87 */ SyscallDesc("poll", unimplementedFunc), /* 88 */ SyscallDesc("lstat", unimplementedFunc), /* 89 */ SyscallDesc("symlink", unimplementedFunc), - /* 90 */ SyscallDesc("readlink", unimplementedFunc), + /* 90 */ SyscallDesc("readlink", readlinkFunc), /* 91 */ SyscallDesc("setgroups", unimplementedFunc), /* 92 */ SyscallDesc("getgroups", unimplementedFunc), /* 93 */ SyscallDesc("fchmod", unimplementedFunc), diff --git a/src/sim/process.hh b/src/sim/process.hh index 29d6e5aae..55bae2542 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -303,6 +303,8 @@ class LiveProcess : public Process return full + filename; } + std::string getcwd() const { return cwd; } + virtual void syscall(int64_t callnum, ThreadContext *tc); virtual SyscallDesc* getDesc(int callnum) = 0; diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index f4b9b7ae3..3a0db1016 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -239,6 +239,59 @@ gethostnameFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) return 0; } +SyscallReturn +getcwdFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) +{ + int result = 0; + unsigned long size = tc->getSyscallArg(1); + BufferArg buf(tc->getSyscallArg(0), size); + + // Is current working directory defined? + string cwd = p->getcwd(); + if (!cwd.empty()) { + if (cwd.length() >= size) { + // Buffer too small + return -ERANGE; + } + strncpy((char *)buf.bufferPtr(), cwd.c_str(), size); + result = cwd.length(); + } + else { + if (getcwd((char *)buf.bufferPtr(), size) != NULL) { + result = strlen((char *)buf.bufferPtr()); + } + else { + result = -1; + } + } + + buf.copyOut(tc->getMemPort()); + + return (result == -1) ? -errno : result; +} + + +SyscallReturn +readlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) +{ + string path; + + if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) + return (TheISA::IntReg)-EFAULT; + + // Adjust path for current working directory + path = p->fullPath(path); + + size_t bufsiz = tc->getSyscallArg(2); + BufferArg buf(tc->getSyscallArg(1), bufsiz); + + int result = readlink(path.c_str(), (char *)buf.bufferPtr(), bufsiz); + + buf.copyOut(tc->getMemPort()); + + return (result == -1) ? -errno : result; +} + SyscallReturn unlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { @@ -254,6 +307,24 @@ unlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) return (result == -1) ? -errno : result; } + +SyscallReturn +mkdirFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) +{ + string path; + + if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) + return (TheISA::IntReg)-EFAULT; + + // Adjust path for current working directory + path = p->fullPath(path); + + mode_t mode = tc->getSyscallArg(1); + + int result = mkdir(path.c_str(), mode); + return (result == -1) ? -errno : result; +} + SyscallReturn renameFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { @@ -306,6 +377,17 @@ ftruncateFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *t return (result == -1) ? -errno : result; } +SyscallReturn +umaskFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) +{ + // Letting the simulated program change the simulator's umask seems like + // a bad idea. Compromise by just returning the current umask but not + // changing anything. + mode_t oldMask = umask(0); + umask(oldMask); + return oldMask; +} + SyscallReturn chownFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index e35b0a75b..6dafee34c 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -223,10 +223,22 @@ SyscallReturn munmapFunc(SyscallDesc *desc, int num, SyscallReturn gethostnameFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc); +/// Target getcwd() handler. +SyscallReturn getcwdFunc(SyscallDesc *desc, int num, + LiveProcess *p, ThreadContext *tc); + +/// Target unlink() handler. +SyscallReturn readlinkFunc(SyscallDesc *desc, int num, + LiveProcess *p, ThreadContext *tc); + /// Target unlink() handler. SyscallReturn unlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc); +/// Target mkdir() handler. +SyscallReturn mkdirFunc(SyscallDesc *desc, int num, + LiveProcess *p, ThreadContext *tc); + /// Target rename() handler. SyscallReturn renameFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc); @@ -242,6 +254,11 @@ SyscallReturn ftruncateFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc); +/// Target umask() handler. +SyscallReturn umaskFunc(SyscallDesc *desc, int num, + LiveProcess *p, ThreadContext *tc); + + /// Target chown() handler. SyscallReturn chownFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc); -- cgit v1.2.3 From 5f42bfcd56c84f6fe938b88411265359fc702110 Mon Sep 17 00:00:00 2001 From: Michael Adler Date: Wed, 23 Jul 2008 14:41:34 -0700 Subject: process: separate stderr from stdout - Add the option of redirecting stderr to a file. With the old behaviour, stderr would follow stdout if stdout was to a file, but stderr went to the host stderr if stdout went to the host stdout. The new default maintains stdout and stderr going to the host. Now the two can specify different files, but they will share a file descriptor if the name of the files is the same. - Add --output and --errout options to se.py to go with --input. --- src/sim/Process.py | 3 ++- src/sim/process.cc | 35 +++++++++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/sim/Process.py b/src/sim/Process.py index 37a27bf3b..81108dd70 100644 --- a/src/sim/Process.py +++ b/src/sim/Process.py @@ -34,7 +34,8 @@ class Process(SimObject): type = 'Process' abstract = True input = Param.String('cin', "filename for stdin") - output = Param.String('cout', 'filename for stdout/stderr') + output = Param.String('cout', 'filename for stdout') + errout = Param.String('cerr', 'filename for stderr') system = Param.System(Parent.any, "system process will run on") max_stack_size = Param.MemorySize('64MB', 'maximum size of the stack') diff --git a/src/sim/process.cc b/src/sim/process.cc index 046a6bf9b..23e890b06 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -92,6 +92,7 @@ Process::Process(ProcessParams * params) { string in = params->input; string out = params->output; + string err = params->errout; // initialize file descriptors to default: same as simulator int stdin_fd, stdout_fd, stderr_fd; @@ -112,7 +113,16 @@ Process::Process(ProcessParams * params) else stdout_fd = Process::openOutputFile(out); - stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO; + if (err == "stdout" || err == "cout") + stderr_fd = STDOUT_FILENO; + else if (err == "stderr" || err == "cerr") + stderr_fd = STDERR_FILENO; + else if (err == "None") + stderr_fd = -1; + else if (err == out) + stderr_fd = stdout_fd; + else + stderr_fd = Process::openOutputFile(err); M5_pid = system->allocatePID(); // initialize first 3 fds (stdin, stdout, stderr) @@ -132,7 +142,7 @@ Process::Process(ProcessParams * params) fdo = &fd_map[STDERR_FILENO]; fdo->fd = stderr_fd; - fdo->filename = "STDERR"; + fdo->filename = err; fdo->flags = O_WRONLY; fdo->mode = -1; fdo->fileOffset = 0; @@ -183,7 +193,7 @@ Process::openInputFile(const string &filename) int Process::openOutputFile(const string &filename) { - int fd = open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0774); + int fd = open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0664); if (fd == -1) { perror(NULL); @@ -355,6 +365,7 @@ Process::fix_file_offsets() { Process::FdMap *fdo_stderr = &fd_map[STDERR_FILENO]; string in = fdo_stdin->filename; string out = fdo_stdout->filename; + string err = fdo_stderr->filename; // initialize file descriptors to default: same as simulator int stdin_fd, stdout_fd, stderr_fd; @@ -378,11 +389,23 @@ Process::fix_file_offsets() { stdout_fd = -1; else{ stdout_fd = Process::openOutputFile(out); - if (lseek(stdin_fd, fdo_stdout->fileOffset, SEEK_SET) < 0) - panic("Unable to seek to correct in file: %s", out); + if (lseek(stdout_fd, fdo_stdout->fileOffset, SEEK_SET) < 0) + panic("Unable to seek to correct location in file: %s", out); } - stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO; + if (err == "stdout" || err == "cout") + stderr_fd = STDOUT_FILENO; + else if (err == "stderr" || err == "cerr") + stderr_fd = STDERR_FILENO; + else if (err == "None") + stderr_fd = -1; + else if (err == out) + stderr_fd = stdout_fd; + else { + stderr_fd = Process::openOutputFile(err); + if (lseek(stderr_fd, fdo_stderr->fileOffset, SEEK_SET) < 0) + panic("Unable to seek to correct location in file: %s", err); + } fdo_stdin->fd = stdin_fd; fdo_stdout->fd = stdout_fd; -- cgit v1.2.3 From f3a3ab7f2cfdae687a1dc07dff10c7fa4bde921c Mon Sep 17 00:00:00 2001 From: Michael Adler Date: Thu, 24 Jul 2008 16:31:33 -0700 Subject: syscall: Fix TTY emulation in fstat() user-mode simulation for fd 1 (stdout). The code didn't set S_IFCHR in the st_mode --- src/sim/syscall_emul.hh | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index 6dafee34c..caf269918 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -380,6 +380,11 @@ convertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false) tgt->st_ino = host->st_ino; tgt->st_ino = htog(tgt->st_ino); tgt->st_mode = host->st_mode; + if (fakeTTY) { + // Claim to be a character device + tgt->st_mode &= ~S_IFMT; // Clear S_IFMT + tgt->st_mode |= S_IFCHR; // Set S_IFCHR + } tgt->st_mode = htog(tgt->st_mode); tgt->st_nlink = host->st_nlink; tgt->st_nlink = htog(tgt->st_nlink); -- cgit v1.2.3 From 4b1e0d235df59059a686c992f284278f5bfda2ad Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 31 Jul 2008 08:01:38 -0700 Subject: scons: Get rid of generate.py in the build system. I decided that separating some of the scons code into generate.py was just a bad idea because it caused the dependency system to get all messed up. If separation is the right way to go in the future, we should probably use the sconscript mechanism, not the mechanism that I just removed. --- src/SConscript | 589 +++++++++++++++++++++++++++++++++++++++++++++---- src/python/generate.py | 561 ---------------------------------------------- 2 files changed, 546 insertions(+), 604 deletions(-) delete mode 100644 src/python/generate.py (limited to 'src') diff --git a/src/SConscript b/src/SConscript index 7a6a762fe..6dd647c0d 100644 --- a/src/SConscript +++ b/src/SConscript @@ -30,7 +30,9 @@ import imp import os +import py_compile import sys +import zipfile from os.path import basename, exists, isdir, isfile, join as joinpath @@ -44,6 +46,8 @@ Import('*') # Children need to see the environment Export('env') +build_env = dict([(opt, env[opt]) for opt in env.ExportOptions]) + def sort_list(_list): """return a sorted copy of '_list'""" if isinstance(_list, list): @@ -199,55 +203,171 @@ for opt in env.ExportOptions: # Prevent any SimObjects from being added after this point, they # should all have been added in the SConscripts above # -sim_objects_fixed = True +class DictImporter(object): + '''This importer takes a dictionary of arbitrary module names that + map to arbitrary filenames.''' + def __init__(self, modules): + self.modules = modules + self.installed = set() -######################################################################## -# -# Manually turn python/generate.py into a python module and import it -# -generate_file = File('python/generate.py') -generate_module = imp.new_module('generate') -sys.modules['generate'] = generate_module -exec file(generate_file.srcnode().abspath, 'r') in generate_module.__dict__ + def __del__(self): + self.unload() -######################################################################## -# -# build a generate -# -from generate import Generate -optionDict = dict([(opt, env[opt]) for opt in env.ExportOptions]) -generate = Generate(py_sources, sim_object_modfiles, optionDict) -m5 = generate.m5 + def unload(self): + import sys + for module in self.installed: + del sys.modules[module] + self.installed = set() + + def find_module(self, fullname, path): + if fullname == '__scons': + return self + + if fullname == 'm5.objects': + return self + + if fullname.startswith('m5.internal'): + return None + + if fullname in self.modules and exists(self.modules[fullname]): + return self + + return None + + def load_module(self, fullname): + mod = imp.new_module(fullname) + sys.modules[fullname] = mod + self.installed.add(fullname) + + mod.__loader__ = self + if fullname == 'm5.objects': + mod.__path__ = fullname.split('.') + return mod + + if fullname == '__scons': + mod.__dict__['m5_build_env'] = build_env + return mod + + srcfile = self.modules[fullname] + if basename(srcfile) == '__init__.py': + mod.__path__ = fullname.split('.') + mod.__file__ = srcfile + + exec file(srcfile, 'r') in mod.__dict__ + + return mod + +class ordered_dict(dict): + def keys(self): + keys = super(ordered_dict, self).keys() + keys.sort() + return keys + + def values(self): + return [ self[key] for key in self.keys() ] + + def items(self): + return [ (key,self[key]) for key in self.keys() ] + + def iterkeys(self): + for key in self.keys(): + yield key + + def itervalues(self): + for value in self.values(): + yield value + + def iteritems(self): + for key,value in self.items(): + yield key, value + +py_modules = {} +for source in py_sources: + py_modules[source.modpath] = source.srcpath + +# install the python importer so we can grab stuff from the source +# tree itself. We can't have SimObjects added after this point or +# else we won't know about them for the rest of the stuff. +sim_objects_fixed = True +importer = DictImporter(py_modules) +sys.meta_path[0:0] = [ importer ] + +import m5 + +# import all sim objects so we can populate the all_objects list +# make sure that we're working with a list, then let's sort it +sim_objects = list(sim_object_modfiles) +sim_objects.sort() +for simobj in sim_objects: + exec('from m5.objects import %s' % simobj) + +# we need to unload all of the currently imported modules so that they +# will be re-imported the next time the sconscript is run +importer.unload() +sys.meta_path.remove(importer) + +sim_objects = m5.SimObject.allClasses +all_enums = m5.params.allEnums + +all_params = {} +for name,obj in sim_objects.iteritems(): + for param in obj._params.local.values(): + if not hasattr(param, 'swig_decl'): + continue + pname = param.ptype_str + if pname not in all_params: + all_params[pname] = param ######################################################################## # # calculate extra dependencies # module_depends = ["m5", "m5.SimObject", "m5.params"] -module_depends = [ File(generate.py_modules[dep]) for dep in module_depends ] -file_depends = [ generate_file ] -depends = module_depends + file_depends +depends = [ File(py_modules[dep]) for dep in module_depends ] ######################################################################## # # Commands for the basic automatically generated python files # +# Generate Python file containing a dict specifying the current +# build_env flags. +def makeDefinesPyFile(target, source, env): + f = file(str(target[0]), 'w') + print >>f, "m5_build_env = ", source[0] + f.close() + +# Generate python file containing info about the M5 source code +def makeInfoPyFile(target, source, env): + f = file(str(target[0]), 'w') + for src in source: + data = ''.join(file(src.srcnode().abspath, 'r').xreadlines()) + print >>f, "%s = %s" % (src, repr(data)) + f.close() + +# Generate the __init__.py file for m5.objects +def makeObjectsInitFile(target, source, env): + f = file(str(target[0]), 'w') + print >>f, 'from params import *' + print >>f, 'from m5.SimObject import *' + for module in source: + print >>f, 'from %s import *' % module.get_contents() + f.close() + # Generate a file with all of the compile options in it -env.Command('python/m5/defines.py', Value(optionDict), - generate.makeDefinesPyFile) +env.Command('python/m5/defines.py', Value(build_env), makeDefinesPyFile) PySource('m5', 'python/m5/defines.py') # Generate a file that wraps the basic top level files env.Command('python/m5/info.py', [ '#/AUTHORS', '#/LICENSE', '#/README', '#/RELEASE_NOTES' ], - generate.makeInfoPyFile) + makeInfoPyFile) PySource('m5', 'python/m5/info.py') # Generate an __init__.py file for the objects package env.Command('python/m5/objects/__init__.py', [ Value(o) for o in sort_list(sim_object_modfiles) ], - generate.makeObjectsInitFile) + makeObjectsInitFile) PySource('m5.objects', 'python/m5/objects/__init__.py') ######################################################################## @@ -255,19 +375,57 @@ PySource('m5.objects', 'python/m5/objects/__init__.py') # Create all of the SimObject param headers and enum headers # +def createSimObjectParam(target, source, env): + assert len(target) == 1 and len(source) == 1 + + hh_file = file(target[0].abspath, 'w') + name = str(source[0].get_contents()) + obj = sim_objects[name] + + print >>hh_file, obj.cxx_decl() + +def createSwigParam(target, source, env): + assert len(target) == 1 and len(source) == 1 + + i_file = file(target[0].abspath, 'w') + name = str(source[0].get_contents()) + param = all_params[name] + + for line in param.swig_decl(): + print >>i_file, line + +def createEnumStrings(target, source, env): + assert len(target) == 1 and len(source) == 1 + + cc_file = file(target[0].abspath, 'w') + name = str(source[0].get_contents()) + obj = all_enums[name] + + print >>cc_file, obj.cxx_def() + cc_file.close() + +def createEnumParam(target, source, env): + assert len(target) == 1 and len(source) == 1 + + hh_file = file(target[0].abspath, 'w') + name = str(source[0].get_contents()) + obj = all_enums[name] + + print >>hh_file, obj.cxx_decl() + # Generate all of the SimObject param struct header files params_hh_files = [] -for name,simobj in generate.sim_objects.iteritems(): - extra_deps = [ File(generate.py_modules[simobj.__module__]) ] +for name,simobj in sim_objects.iteritems(): + extra_deps = [ File(py_modules[simobj.__module__]) ] hh_file = File('params/%s.hh' % name) params_hh_files.append(hh_file) - env.Command(hh_file, Value(name), generate.createSimObjectParam) + env.Command(hh_file, Value(name), createSimObjectParam) env.Depends(hh_file, depends + extra_deps) # Generate any parameter header files needed params_i_files = [] -for name,param in generate.params.iteritems(): +for name,param in all_params.iteritems(): if isinstance(param, m5.params.VectorParamDesc): ext = 'vptype' else: @@ -275,28 +433,117 @@ for name,param in generate.params.iteritems(): i_file = File('params/%s_%s.i' % (name, ext)) params_i_files.append(i_file) - env.Command(i_file, Value(name), generate.createSwigParam) + env.Command(i_file, Value(name), createSwigParam) env.Depends(i_file, depends) # Generate all enum header files -for name,enum in generate.enums.iteritems(): - extra_deps = [ File(generate.py_modules[enum.__module__]) ] +for name,enum in all_enums.iteritems(): + extra_deps = [ File(py_modules[enum.__module__]) ] cc_file = File('enums/%s.cc' % name) - env.Command(cc_file, Value(name), generate.createEnumStrings) + env.Command(cc_file, Value(name), createEnumStrings) env.Depends(cc_file, depends + extra_deps) Source(cc_file) hh_file = File('enums/%s.hh' % name) - env.Command(hh_file, Value(name), generate.createEnumParam) + env.Command(hh_file, Value(name), createEnumParam) env.Depends(hh_file, depends + extra_deps) # Build the big monolithic swigged params module (wraps all SimObject # param structs and enum structs) +def buildParams(target, source, env): + names = [ s.get_contents() for s in source ] + objs = [ sim_objects[name] for name in names ] + out = file(target[0].abspath, 'w') + + ordered_objs = [] + obj_seen = set() + def order_obj(obj): + name = str(obj) + if name in obj_seen: + return + + obj_seen.add(name) + if str(obj) != 'SimObject': + order_obj(obj.__bases__[0]) + + ordered_objs.append(obj) + + for obj in objs: + order_obj(obj) + + enums = set() + predecls = [] + pd_seen = set() + + def add_pds(*pds): + for pd in pds: + if pd not in pd_seen: + predecls.append(pd) + pd_seen.add(pd) + + for obj in ordered_objs: + params = obj._params.local.values() + for param in params: + ptype = param.ptype + if issubclass(ptype, m5.params.Enum): + if ptype not in enums: + enums.add(ptype) + pds = param.swig_predecls() + if isinstance(pds, (list, tuple)): + add_pds(*pds) + else: + add_pds(pds) + + print >>out, '%module params' + + print >>out, '%{' + for obj in ordered_objs: + print >>out, '#include "params/%s.hh"' % obj + print >>out, '%}' + + for pd in predecls: + print >>out, pd + + enums = list(enums) + enums.sort() + for enum in enums: + print >>out, '%%include "enums/%s.hh"' % enum.__name__ + print >>out + + for obj in ordered_objs: + if obj.swig_objdecls: + for decl in obj.swig_objdecls: + print >>out, decl + continue + + code = '' + base = obj.get_base() + + code += '// stop swig from creating/wrapping default ctor/dtor\n' + code += '%%nodefault %s;\n' % obj.cxx_class + code += 'class %s ' % obj.cxx_class + if base: + code += ': public %s' % base + code += ' {};\n' + + klass = obj.cxx_class; + if hasattr(obj, 'cxx_namespace'): + new_code = 'namespace %s {\n' % obj.cxx_namespace + new_code += code + new_code += '}\n' + code = new_code + klass = '%s::%s' % (obj.cxx_namespace, klass) + + print >>out, code + + print >>out, '%%include "src/sim/sim_object_params.hh"' % obj + for obj in ordered_objs: + print >>out, '%%include "params/%s.hh"' % obj + params_file = File('params/params.i') -names = sort_list(generate.sim_objects.keys()) -env.Command(params_file, [ Value(v) for v in names ], - generate.buildParams) +names = sort_list(sim_objects.keys()) +env.Command(params_file, [ Value(v) for v in names ], buildParams) env.Depends(params_file, params_hh_files + params_i_files + depends) SwigSource('m5.objects', params_file) @@ -322,28 +569,284 @@ for source,package in swig_sources: PySource(package, py_file) # Generate the main swig init file -env.Command('swig/init.cc', swig_modules, generate.makeSwigInit) +def makeSwigInit(target, source, env): + f = file(str(target[0]), 'w') + print >>f, 'extern "C" {' + for module in source: + print >>f, ' void init_%s();' % module.get_contents() + print >>f, '}' + print >>f, 'void init_swig() {' + for module in source: + print >>f, ' init_%s();' % module.get_contents() + print >>f, '}' + f.close() + +env.Command('swig/init.cc', swig_modules, makeSwigInit) Source('swig/init.cc') # Generate traceflags.py +def traceFlagsPy(target, source, env): + assert(len(target) == 1) + + f = file(str(target[0]), 'w') + + allFlags = [] + for s in source: + val = eval(s.get_contents()) + allFlags.append(val) + + print >>f, 'baseFlags = [' + for flag, compound, desc in allFlags: + if not compound: + print >>f, " '%s'," % flag + print >>f, " ]" + print >>f + + print >>f, 'compoundFlags = [' + print >>f, " 'All'," + for flag, compound, desc in allFlags: + if compound: + print >>f, " '%s'," % flag + print >>f, " ]" + print >>f + + print >>f, "allFlags = frozenset(baseFlags + compoundFlags)" + print >>f + + print >>f, 'compoundFlagMap = {' + all = tuple([flag for flag,compound,desc in allFlags if not compound]) + print >>f, " 'All' : %s," % (all, ) + for flag, compound, desc in allFlags: + if compound: + print >>f, " '%s' : %s," % (flag, compound) + print >>f, " }" + print >>f + + print >>f, 'flagDescriptions = {' + print >>f, " 'All' : 'All flags'," + for flag, compound, desc in allFlags: + print >>f, " '%s' : '%s'," % (flag, desc) + print >>f, " }" + + f.close() + +def traceFlagsCC(target, source, env): + assert(len(target) == 1) + + f = file(str(target[0]), 'w') + + allFlags = [] + for s in source: + val = eval(s.get_contents()) + allFlags.append(val) + + # file header + print >>f, ''' +/* + * DO NOT EDIT THIS FILE! Automatically generated + */ + +#include "base/traceflags.hh" + +using namespace Trace; + +const char *Trace::flagStrings[] = +{''' + + # The string array is used by SimpleEnumParam to map the strings + # provided by the user to enum values. + for flag, compound, desc in allFlags: + if not compound: + print >>f, ' "%s",' % flag + + print >>f, ' "All",' + for flag, compound, desc in allFlags: + if compound: + print >>f, ' "%s",' % flag + + print >>f, '};' + print >>f + print >>f, 'const int Trace::numFlagStrings = %d;' % (len(allFlags) + 1) + print >>f + + # + # Now define the individual compound flag arrays. There is an array + # for each compound flag listing the component base flags. + # + all = tuple([flag for flag,compound,desc in allFlags if not compound]) + print >>f, 'static const Flags AllMap[] = {' + for flag, compound, desc in allFlags: + if not compound: + print >>f, " %s," % flag + print >>f, '};' + print >>f + + for flag, compound, desc in allFlags: + if not compound: + continue + print >>f, 'static const Flags %sMap[] = {' % flag + for flag in compound: + print >>f, " %s," % flag + print >>f, " (Flags)-1" + print >>f, '};' + print >>f + + # + # Finally the compoundFlags[] array maps the compound flags + # to their individual arrays/ + # + print >>f, 'const Flags *Trace::compoundFlags[] =' + print >>f, '{' + print >>f, ' AllMap,' + for flag, compound, desc in allFlags: + if compound: + print >>f, ' %sMap,' % flag + # file trailer + print >>f, '};' + + f.close() + +def traceFlagsHH(target, source, env): + assert(len(target) == 1) + + f = file(str(target[0]), 'w') + + allFlags = [] + for s in source: + val = eval(s.get_contents()) + allFlags.append(val) + + # file header boilerplate + print >>f, ''' +/* + * DO NOT EDIT THIS FILE! + * + * Automatically generated from traceflags.py + */ + +#ifndef __BASE_TRACE_FLAGS_HH__ +#define __BASE_TRACE_FLAGS_HH__ + +namespace Trace { + +enum Flags {''' + + # Generate the enum. Base flags come first, then compound flags. + idx = 0 + for flag, compound, desc in allFlags: + if not compound: + print >>f, ' %s = %d,' % (flag, idx) + idx += 1 + + numBaseFlags = idx + print >>f, ' NumFlags = %d,' % idx + + # put a comment in here to separate base from compound flags + print >>f, ''' +// The remaining enum values are *not* valid indices for Trace::flags. +// They are "compound" flags, which correspond to sets of base +// flags, and are used by changeFlag.''' + + print >>f, ' All = %d,' % idx + idx += 1 + for flag, compound, desc in allFlags: + if compound: + print >>f, ' %s = %d,' % (flag, idx) + idx += 1 + + numCompoundFlags = idx - numBaseFlags + print >>f, ' NumCompoundFlags = %d' % numCompoundFlags + + # trailer boilerplate + print >>f, '''\ +}; // enum Flags + +// Array of strings for SimpleEnumParam +extern const char *flagStrings[]; +extern const int numFlagStrings; + +// Array of arraay pointers: for each compound flag, gives the list of +// base flags to set. Inidividual flag arrays are terminated by -1. +extern const Flags *compoundFlags[]; + +/* namespace Trace */ } + +#endif // __BASE_TRACE_FLAGS_HH__ +''' + + f.close() + flags = [ Value(f) for f in trace_flags ] -env.Command('base/traceflags.py', flags, generate.traceFlagsPy) +env.Command('base/traceflags.py', flags, traceFlagsPy) PySource('m5', 'base/traceflags.py') -env.Command('base/traceflags.hh', flags, generate.traceFlagsHH) -env.Command('base/traceflags.cc', flags, generate.traceFlagsCC) +env.Command('base/traceflags.hh', flags, traceFlagsHH) +env.Command('base/traceflags.cc', flags, traceFlagsCC) Source('base/traceflags.cc') # Generate program_info.cc +def programInfo(target, source, env): + def gen_file(target, rev, node, date): + pi_stats = file(target, 'w') + print >>pi_stats, 'const char *hgRev = "%s:%s";' % (rev, node) + print >>pi_stats, 'const char *hgDate = "%s";' % date + pi_stats.close() + + target = str(target[0]) + scons_dir = str(source[0].get_contents()) + try: + import mercurial.demandimport, mercurial.hg, mercurial.ui + import mercurial.util, mercurial.node + if not exists(scons_dir) or not isdir(scons_dir) or \ + not exists(joinpath(scons_dir, ".hg")): + raise ValueError + repo = mercurial.hg.repository(mercurial.ui.ui(), scons_dir) + rev = mercurial.node.nullrev + repo.changelog.count() + changenode = repo.changelog.node(rev) + changes = repo.changelog.read(changenode) + date = mercurial.util.datestr(changes[2]) + + gen_file(target, rev, mercurial.node.hex(changenode), date) + + mercurial.demandimport.disable() + except ImportError: + gen_file(target, "Unknown", "Unknown", "Unknown") + + except: + print "in except" + gen_file(target, "Unknown", "Unknown", "Unknown") + mercurial.demandimport.disable() + env.Command('base/program_info.cc', Value(str(SCons.Node.FS.default_fs.SConstruct_dir)), - generate.programInfo) + programInfo) # Build the zip file +def compilePyFile(target, source, env): + '''Action function to compile a .py into a .pyc''' + py_compile.compile(str(source[0]), str(target[0])) + +def buildPyZip(target, source, env): + '''Action function to build the zip archive. Uses the + PyZipFile module included in the standard Python library.''' + + py_compiled = {} + for s in py_sources: + compname = str(s.compiled) + assert compname not in py_compiled + py_compiled[compname] = s + + zf = zipfile.ZipFile(str(target[0]), 'w') + for s in source: + zipname = str(s) + arcname = py_compiled[zipname].arcname + zf.write(zipname, arcname) + zf.close() + py_compiled = [] py_zip_depends = [] for source in py_sources: - env.Command(source.compiled, source.source, generate.compilePyFile) + env.Command(source.compiled, source.source, compilePyFile) py_compiled.append(source.compiled) # make the zipfile depend on the archive name so that the archive @@ -352,7 +855,7 @@ for source in py_sources: # Add the zip file target to the environment. m5zip = File('m5py.zip') -env.Command(m5zip, py_compiled, generate.buildPyZip) +env.Command(m5zip, py_compiled, buildPyZip) env.Depends(m5zip, py_zip_depends) ######################################################################## diff --git a/src/python/generate.py b/src/python/generate.py deleted file mode 100644 index 7b69ad876..000000000 --- a/src/python/generate.py +++ /dev/null @@ -1,561 +0,0 @@ -# Copyright (c) 2004-2006 The Regents of The University of Michigan -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer; -# redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution; -# neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Authors: Nathan Binkert - -import imp -import py_compile -import sys -import zipfile - -from os.path import basename, exists, isdir, join - -class DictImporter(object): - '''This importer takes a dictionary of arbitrary module names that - map to arbitrary filenames.''' - def __init__(self, modules, build_env): - self.modules = modules - self.installed = set() - self.build_env = build_env - - def __del__(self): - self.unload() - - def unload(self): - import sys - for module in self.installed: - del sys.modules[module] - self.installed = set() - - def find_module(self, fullname, path): - if fullname == '__scons': - return self - - if fullname == 'm5.objects': - return self - - if fullname.startswith('m5.internal'): - return None - - if fullname in self.modules and exists(self.modules[fullname]): - return self - - return None - - def load_module(self, fullname): - mod = imp.new_module(fullname) - sys.modules[fullname] = mod - self.installed.add(fullname) - - mod.__loader__ = self - if fullname == 'm5.objects': - mod.__path__ = fullname.split('.') - return mod - - if fullname == '__scons': - mod.__dict__['m5_build_env'] = self.build_env - return mod - - srcfile = self.modules[fullname] - if basename(srcfile) == '__init__.py': - mod.__path__ = fullname.split('.') - mod.__file__ = srcfile - - exec file(srcfile, 'r') in mod.__dict__ - - return mod - -class ordered_dict(dict): - def keys(self): - keys = super(ordered_dict, self).keys() - keys.sort() - return keys - - def values(self): - return [ self[key] for key in self.keys() ] - - def items(self): - return [ (key,self[key]) for key in self.keys() ] - - def iterkeys(self): - for key in self.keys(): - yield key - - def itervalues(self): - for value in self.values(): - yield value - - def iteritems(self): - for key,value in self.items(): - yield key, value - -class Generate(object): - def __init__(self, py_sources, sim_objects, build_env): - self.py_sources = py_sources - self.py_modules = {} - for source in py_sources: - self.py_modules[source.modpath] = source.srcpath - - importer = DictImporter(self.py_modules, build_env) - - # install the python importer so we can grab stuff from the source - # tree itself. - sys.meta_path[0:0] = [ importer ] - - import m5 - self.m5 = m5 - - # import all sim objects so we can populate the all_objects list - # make sure that we're working with a list, then let's sort it - sim_objects = list(sim_objects) - sim_objects.sort() - for simobj in sim_objects: - exec('from m5.objects import %s' % simobj) - - # we need to unload all of the currently imported modules so that they - # will be re-imported the next time the sconscript is run - importer.unload() - sys.meta_path.remove(importer) - - self.sim_objects = m5.SimObject.allClasses - self.enums = m5.params.allEnums - - self.params = {} - for name,obj in self.sim_objects.iteritems(): - for param in obj._params.local.values(): - if not hasattr(param, 'swig_decl'): - continue - pname = param.ptype_str - if pname not in self.params: - self.params[pname] = param - - def createSimObjectParam(self, target, source, env): - assert len(target) == 1 and len(source) == 1 - - hh_file = file(target[0].abspath, 'w') - name = str(source[0].get_contents()) - obj = self.sim_objects[name] - - print >>hh_file, obj.cxx_decl() - - # Generate Python file containing a dict specifying the current - # build_env flags. - def makeDefinesPyFile(self, target, source, env): - f = file(str(target[0]), 'w') - print >>f, "m5_build_env = ", source[0] - f.close() - - # Generate python file containing info about the M5 source code - def makeInfoPyFile(self, target, source, env): - f = file(str(target[0]), 'w') - for src in source: - data = ''.join(file(src.srcnode().abspath, 'r').xreadlines()) - print >>f, "%s = %s" % (src, repr(data)) - f.close() - - # Generate the __init__.py file for m5.objects - def makeObjectsInitFile(self, target, source, env): - f = file(str(target[0]), 'w') - print >>f, 'from params import *' - print >>f, 'from m5.SimObject import *' - for module in source: - print >>f, 'from %s import *' % module.get_contents() - f.close() - - def createSwigParam(self, target, source, env): - assert len(target) == 1 and len(source) == 1 - - i_file = file(target[0].abspath, 'w') - name = str(source[0].get_contents()) - param = self.params[name] - - for line in param.swig_decl(): - print >>i_file, line - - def createEnumStrings(self, target, source, env): - assert len(target) == 1 and len(source) == 1 - - cc_file = file(target[0].abspath, 'w') - name = str(source[0].get_contents()) - obj = self.enums[name] - - print >>cc_file, obj.cxx_def() - cc_file.close() - - def createEnumParam(self, target, source, env): - assert len(target) == 1 and len(source) == 1 - - hh_file = file(target[0].abspath, 'w') - name = str(source[0].get_contents()) - obj = self.enums[name] - - print >>hh_file, obj.cxx_decl() - - def buildParams(self, target, source, env): - names = [ s.get_contents() for s in source ] - objs = [ self.sim_objects[name] for name in names ] - out = file(target[0].abspath, 'w') - - ordered_objs = [] - obj_seen = set() - def order_obj(obj): - name = str(obj) - if name in obj_seen: - return - - obj_seen.add(name) - if str(obj) != 'SimObject': - order_obj(obj.__bases__[0]) - - ordered_objs.append(obj) - - for obj in objs: - order_obj(obj) - - enums = set() - predecls = [] - pd_seen = set() - - def add_pds(*pds): - for pd in pds: - if pd not in pd_seen: - predecls.append(pd) - pd_seen.add(pd) - - for obj in ordered_objs: - params = obj._params.local.values() - for param in params: - ptype = param.ptype - if issubclass(ptype, self.m5.params.Enum): - if ptype not in enums: - enums.add(ptype) - pds = param.swig_predecls() - if isinstance(pds, (list, tuple)): - add_pds(*pds) - else: - add_pds(pds) - - print >>out, '%module params' - - print >>out, '%{' - for obj in ordered_objs: - print >>out, '#include "params/%s.hh"' % obj - print >>out, '%}' - - for pd in predecls: - print >>out, pd - - enums = list(enums) - enums.sort() - for enum in enums: - print >>out, '%%include "enums/%s.hh"' % enum.__name__ - print >>out - - for obj in ordered_objs: - if obj.swig_objdecls: - for decl in obj.swig_objdecls: - print >>out, decl - continue - - code = '' - base = obj.get_base() - - code += '// stop swig from creating/wrapping default ctor/dtor\n' - code += '%%nodefault %s;\n' % obj.cxx_class - code += 'class %s ' % obj.cxx_class - if base: - code += ': public %s' % base - code += ' {};\n' - - klass = obj.cxx_class; - if hasattr(obj, 'cxx_namespace'): - new_code = 'namespace %s {\n' % obj.cxx_namespace - new_code += code - new_code += '}\n' - code = new_code - klass = '%s::%s' % (obj.cxx_namespace, klass) - - print >>out, code - - print >>out, '%%include "src/sim/sim_object_params.hh"' % obj - for obj in ordered_objs: - print >>out, '%%include "params/%s.hh"' % obj - - def makeSwigInit(self, target, source, env): - f = file(str(target[0]), 'w') - print >>f, 'extern "C" {' - for module in source: - print >>f, ' void init_%s();' % module.get_contents() - print >>f, '}' - print >>f, 'void init_swig() {' - for module in source: - print >>f, ' init_%s();' % module.get_contents() - print >>f, '}' - f.close() - - def compilePyFile(self, target, source, env): - '''Action function to compile a .py into a .pyc''' - py_compile.compile(str(source[0]), str(target[0])) - - def buildPyZip(self, target, source, env): - '''Action function to build the zip archive. Uses the - PyZipFile module included in the standard Python library.''' - - py_compiled = {} - for s in self.py_sources: - compname = str(s.compiled) - assert compname not in py_compiled - py_compiled[compname] = s - - zf = zipfile.ZipFile(str(target[0]), 'w') - for s in source: - zipname = str(s) - arcname = py_compiled[zipname].arcname - zf.write(zipname, arcname) - zf.close() - - def traceFlagsPy(self, target, source, env): - assert(len(target) == 1) - - f = file(str(target[0]), 'w') - - allFlags = [] - for s in source: - val = eval(s.get_contents()) - allFlags.append(val) - - print >>f, 'baseFlags = [' - for flag, compound, desc in allFlags: - if not compound: - print >>f, " '%s'," % flag - print >>f, " ]" - print >>f - - print >>f, 'compoundFlags = [' - print >>f, " 'All'," - for flag, compound, desc in allFlags: - if compound: - print >>f, " '%s'," % flag - print >>f, " ]" - print >>f - - print >>f, "allFlags = frozenset(baseFlags + compoundFlags)" - print >>f - - print >>f, 'compoundFlagMap = {' - all = tuple([flag for flag,compound,desc in allFlags if not compound]) - print >>f, " 'All' : %s," % (all, ) - for flag, compound, desc in allFlags: - if compound: - print >>f, " '%s' : %s," % (flag, compound) - print >>f, " }" - print >>f - - print >>f, 'flagDescriptions = {' - print >>f, " 'All' : 'All flags'," - for flag, compound, desc in allFlags: - print >>f, " '%s' : '%s'," % (flag, desc) - print >>f, " }" - - f.close() - - def traceFlagsCC(self, target, source, env): - assert(len(target) == 1) - - f = file(str(target[0]), 'w') - - allFlags = [] - for s in source: - val = eval(s.get_contents()) - allFlags.append(val) - - # file header - print >>f, ''' -/* - * DO NOT EDIT THIS FILE! Automatically generated - */ - -#include "base/traceflags.hh" - -using namespace Trace; - -const char *Trace::flagStrings[] = -{''' - - # The string array is used by SimpleEnumParam to map the strings - # provided by the user to enum values. - for flag, compound, desc in allFlags: - if not compound: - print >>f, ' "%s",' % flag - - print >>f, ' "All",' - for flag, compound, desc in allFlags: - if compound: - print >>f, ' "%s",' % flag - - print >>f, '};' - print >>f - print >>f, 'const int Trace::numFlagStrings = %d;' % (len(allFlags) + 1) - print >>f - - # - # Now define the individual compound flag arrays. There is an array - # for each compound flag listing the component base flags. - # - all = tuple([flag for flag,compound,desc in allFlags if not compound]) - print >>f, 'static const Flags AllMap[] = {' - for flag, compound, desc in allFlags: - if not compound: - print >>f, " %s," % flag - print >>f, '};' - print >>f - - for flag, compound, desc in allFlags: - if not compound: - continue - print >>f, 'static const Flags %sMap[] = {' % flag - for flag in compound: - print >>f, " %s," % flag - print >>f, " (Flags)-1" - print >>f, '};' - print >>f - - # - # Finally the compoundFlags[] array maps the compound flags - # to their individual arrays/ - # - print >>f, 'const Flags *Trace::compoundFlags[] =' - print >>f, '{' - print >>f, ' AllMap,' - for flag, compound, desc in allFlags: - if compound: - print >>f, ' %sMap,' % flag - # file trailer - print >>f, '};' - - f.close() - - def traceFlagsHH(self, target, source, env): - assert(len(target) == 1) - - f = file(str(target[0]), 'w') - - allFlags = [] - for s in source: - val = eval(s.get_contents()) - allFlags.append(val) - - # file header boilerplate - print >>f, ''' -/* - * DO NOT EDIT THIS FILE! - * - * Automatically generated from traceflags.py - */ - -#ifndef __BASE_TRACE_FLAGS_HH__ -#define __BASE_TRACE_FLAGS_HH__ - -namespace Trace { - -enum Flags {''' - - # Generate the enum. Base flags come first, then compound flags. - idx = 0 - for flag, compound, desc in allFlags: - if not compound: - print >>f, ' %s = %d,' % (flag, idx) - idx += 1 - - numBaseFlags = idx - print >>f, ' NumFlags = %d,' % idx - - # put a comment in here to separate base from compound flags - print >>f, ''' -// The remaining enum values are *not* valid indices for Trace::flags. -// They are "compound" flags, which correspond to sets of base -// flags, and are used by changeFlag.''' - - print >>f, ' All = %d,' % idx - idx += 1 - for flag, compound, desc in allFlags: - if compound: - print >>f, ' %s = %d,' % (flag, idx) - idx += 1 - - numCompoundFlags = idx - numBaseFlags - print >>f, ' NumCompoundFlags = %d' % numCompoundFlags - - # trailer boilerplate - print >>f, '''\ -}; // enum Flags - -// Array of strings for SimpleEnumParam -extern const char *flagStrings[]; -extern const int numFlagStrings; - -// Array of arraay pointers: for each compound flag, gives the list of -// base flags to set. Inidividual flag arrays are terminated by -1. -extern const Flags *compoundFlags[]; - -/* namespace Trace */ } - -#endif // __BASE_TRACE_FLAGS_HH__ -''' - - f.close() - - def programInfo(self, target, source, env): - def gen_file(target, rev, node, date): - pi_stats = file(target, 'w') - print >>pi_stats, 'const char *hgRev = "%s:%s";' % (rev, node) - print >>pi_stats, 'const char *hgDate = "%s";' % date - pi_stats.close() - - target = str(target[0]) - scons_dir = str(source[0].get_contents()) - try: - import mercurial.demandimport, mercurial.hg, mercurial.ui - import mercurial.util, mercurial.node - if not exists(scons_dir) or not isdir(scons_dir) or \ - not exists(join(scons_dir, ".hg")): - raise ValueError - repo = mercurial.hg.repository(mercurial.ui.ui(), scons_dir) - rev = mercurial.node.nullrev + repo.changelog.count() - changenode = repo.changelog.node(rev) - changes = repo.changelog.read(changenode) - date = mercurial.util.datestr(changes[2]) - - gen_file(target, rev, mercurial.node.hex(changenode), date) - - mercurial.demandimport.disable() - except ImportError: - gen_file(target, "Unknown", "Unknown", "Unknown") - - except: - print "in except" - gen_file(target, "Unknown", "Unknown", "Unknown") - mercurial.demandimport.disable() -- cgit v1.2.3 From e98ccd309bb8eb48153d2400f11a08341e9a2271 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 2 Aug 2008 20:42:15 -0700 Subject: kill unused code --- src/SConscript | 24 ------------------------ 1 file changed, 24 deletions(-) (limited to 'src') diff --git a/src/SConscript b/src/SConscript index 6dd647c0d..ad1fe76a9 100644 --- a/src/SConscript +++ b/src/SConscript @@ -257,30 +257,6 @@ class DictImporter(object): return mod -class ordered_dict(dict): - def keys(self): - keys = super(ordered_dict, self).keys() - keys.sort() - return keys - - def values(self): - return [ self[key] for key in self.keys() ] - - def items(self): - return [ (key,self[key]) for key in self.keys() ] - - def iterkeys(self): - for key in self.keys(): - yield key - - def itervalues(self): - for value in self.values(): - yield value - - def iteritems(self): - for key,value in self.items(): - yield key, value - py_modules = {} for source in py_sources: py_modules[source.modpath] = source.srcpath -- cgit v1.2.3 From b179c3f4cd1e89872de34d70105f703e72377029 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 3 Aug 2008 14:43:24 -0700 Subject: X86: Make hint nops consume their modrm byte. --- src/arch/x86/predecoder_tables.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/predecoder_tables.cc b/src/arch/x86/predecoder_tables.cc index f8aff39f1..bcd5face6 100644 --- a/src/arch/x86/predecoder_tables.cc +++ b/src/arch/x86/predecoder_tables.cc @@ -123,7 +123,7 @@ namespace X86ISA { //LSB // MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F /* 0 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1, -/* 1 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 1 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, /* 2 */ 1 , 1 , 1 , 1 , 1 , 0 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, /* 3 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, /* 4 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, -- cgit v1.2.3 From 62c08a75ad18fda5d06d919db6d8d31a79be9630 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Sun, 3 Aug 2008 18:13:29 -0400 Subject: Make default PhysicalMemory latency slightly more realistic. Also update stats to reflect change. --- src/mem/PhysicalMemory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/mem/PhysicalMemory.py b/src/mem/PhysicalMemory.py index e512cea1c..95cc73daa 100644 --- a/src/mem/PhysicalMemory.py +++ b/src/mem/PhysicalMemory.py @@ -35,7 +35,7 @@ class PhysicalMemory(MemObject): port = VectorPort("the access port") range = Param.AddrRange(AddrRange('128MB'), "Device Address") file = Param.String('', "memory mapped file") - latency = Param.Latency('1t', "latency of an access") + latency = Param.Latency('30ns', "latency of an access") latency_var = Param.Latency('0ns', "access variablity") zero = Param.Bool(False, "zero initialize memory") null = Param.Bool(False, "do not store data, always return zero") -- cgit v1.2.3 From 678abbc3646695f7d9693ce0757abaf7463d0354 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sun, 3 Aug 2008 18:19:53 -0700 Subject: syscall: Avoid a compiler warning which turns into a bug. Simply cast the result to an int and life is good. --- src/sim/syscall_emul.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index 3a0db1016..3f6c56b5f 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -385,7 +385,7 @@ umaskFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) // changing anything. mode_t oldMask = umask(0); umask(oldMask); - return oldMask; + return (int)oldMask; } SyscallReturn -- cgit v1.2.3 From ede89c2d541051c2ed647e2967712e10b3c0fab0 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sun, 3 Aug 2008 18:19:54 -0700 Subject: libm5: Create a libm5 static library for embedding m5. This should allow m5 to be more easily embedded into other simulators. The m5 binary adds a simple main function which then calls into the m5 libarary to start the simulation. In order to make this work correctly, it was necessary embed python code directly into the library instead of the zipfile hack. This is because you can't just append the zipfile to the end of a library the way you can a binary. As a result, Python files that are part of the m5 simulator are now compile, marshalled, compressed, and then inserted into the library's data section with a certain symbol name. Additionally, a new Importer was needed to allow python to get at the embedded python code. Small additional changes include: - Get rid of the PYTHONHOME stuff since I don't think anyone ever used it, and it just confuses things. Easy enough to add back if I'm wrong. - Create a few new functions that are key to initializing and running the simulator: initSignals, initM5Python, m5Main. The original code for creating libm5 was inspired by a patch Michael Adler, though the code here was done by me. --- src/SConscript | 185 ++++++++++++++++++++++++++++++------------ src/python/SConscript | 1 + src/python/importer.py | 80 ++++++++++++++++++ src/python/m5/__init__.py | 2 +- src/python/swig/init.hh | 36 --------- src/sim/SConscript | 3 +- src/sim/init.cc | 202 ++++++++++++++++++++++++++++++++++++++++++++++ src/sim/init.hh | 54 +++++++++++++ src/sim/main.cc | 124 ++++------------------------ 9 files changed, 489 insertions(+), 198 deletions(-) create mode 100644 src/python/importer.py delete mode 100644 src/python/swig/init.hh create mode 100644 src/sim/init.cc create mode 100644 src/sim/init.hh (limited to 'src') diff --git a/src/SConscript b/src/SConscript index ad1fe76a9..36cbbfa78 100644 --- a/src/SConscript +++ b/src/SConscript @@ -28,11 +28,13 @@ # # Authors: Nathan Binkert +import array import imp +import marshal import os -import py_compile +import re import sys -import zipfile +import zlib from os.path import basename, exists, isdir, isfile, join as joinpath @@ -58,39 +60,54 @@ def sort_list(_list): return _list class PySourceFile(object): + invalid_sym_char = re.compile('[^A-z0-9_]') def __init__(self, package, source): filename = str(source) pyname = basename(filename) assert pyname.endswith('.py') name = pyname[:-3] - path = package.split('.') + if package: + path = package.split('.') + else: + path = [] modpath = path if name != '__init__': modpath += [name] modpath = '.'.join(modpath) - arcpath = package.split('.') + [ pyname + 'c' ] + arcpath = path + [ pyname ] arcname = joinpath(*arcpath) - self.source = source + self.tnode = source + self.snode = source.srcnode() self.pyname = pyname - self.srcpath = source.srcnode().abspath self.package = package self.modpath = modpath self.arcname = arcname self.filename = filename self.compiled = File(filename + 'c') + self.assembly = File(filename + '.s') + self.symname = "PyEMB_" + self.invalid_sym_char.sub('_', modpath) + ######################################################################## # Code for adding source files of various types # -cc_sources = [] +cc_lib_sources = [] def Source(source): - '''Add a C/C++ source file to the build''' + '''Add a source file to the libm5 build''' + if not isinstance(source, SCons.Node.FS.File): + source = File(source) + + cc_lib_sources.append(source) + +cc_bin_sources = [] +def BinSource(source): + '''Add a source file to the m5 binary build''' if not isinstance(source, SCons.Node.FS.File): source = File(source) - cc_sources.append(source) + cc_bin_sources.append(source) py_sources = [] def PySource(package, source): @@ -129,6 +146,7 @@ def SwigSource(package, source): # Children should have access Export('Source') +Export('BinSource') Export('PySource') Export('SimObject') Export('SwigSource') @@ -259,7 +277,7 @@ class DictImporter(object): py_modules = {} for source in py_sources: - py_modules[source.modpath] = source.srcpath + py_modules[source.modpath] = source.snode.abspath # install the python importer so we can grab stuff from the source # tree itself. We can't have SimObjects added after this point or @@ -551,14 +569,14 @@ def makeSwigInit(target, source, env): for module in source: print >>f, ' void init_%s();' % module.get_contents() print >>f, '}' - print >>f, 'void init_swig() {' + print >>f, 'void initSwig() {' for module in source: print >>f, ' init_%s();' % module.get_contents() print >>f, '}' f.close() -env.Command('swig/init.cc', swig_modules, makeSwigInit) -Source('swig/init.cc') +env.Command('python/swig/init.cc', swig_modules, makeSwigInit) +Source('python/swig/init.cc') # Generate traceflags.py def traceFlagsPy(target, source, env): @@ -797,42 +815,95 @@ env.Command('base/program_info.cc', Value(str(SCons.Node.FS.default_fs.SConstruct_dir)), programInfo) -# Build the zip file -def compilePyFile(target, source, env): - '''Action function to compile a .py into a .pyc''' - py_compile.compile(str(source[0]), str(target[0])) - -def buildPyZip(target, source, env): - '''Action function to build the zip archive. Uses the - PyZipFile module included in the standard Python library.''' - - py_compiled = {} - for s in py_sources: - compname = str(s.compiled) - assert compname not in py_compiled - py_compiled[compname] = s - - zf = zipfile.ZipFile(str(target[0]), 'w') - for s in source: - zipname = str(s) - arcname = py_compiled[zipname].arcname - zf.write(zipname, arcname) - zf.close() +# embed python files. All .py files that have been indicated by a +# PySource() call in a SConscript need to be embedded into the M5 +# library. To do that, we compile the file to byte code, marshal the +# byte code, compress it, and then generate an assembly file that +# inserts the result into the data section with symbols indicating the +# beginning, and end (and with the size at the end) +py_sources_tnodes = {} +for pysource in py_sources: + py_sources_tnodes[pysource.tnode] = pysource + +def objectifyPyFile(target, source, env): + '''Action function to compile a .py into a code object, marshal + it, compress it, and stick it into an asm file so the code appears + as just bytes with a label in the data section''' + + src = file(str(source[0]), 'r').read() + dst = file(str(target[0]), 'w') + + pysource = py_sources_tnodes[source[0]] + compiled = compile(src, pysource.snode.path, 'exec') + marshalled = marshal.dumps(compiled) + compressed = zlib.compress(marshalled) + data = compressed + + # Some C/C++ compilers prepend an underscore to global symbol + # names, so if they're going to do that, we need to prepend that + # leading underscore to globals in the assembly file. + if env['LEADING_UNDERSCORE']: + sym = '_' + pysource.symname + else: + sym = pysource.symname + + step = 16 + print >>dst, ".data" + print >>dst, ".globl %s_beg" % sym + print >>dst, ".globl %s_end" % sym + print >>dst, "%s_beg:" % sym + for i in xrange(0, len(data), step): + x = array.array('B', data[i:i+step]) + print >>dst, ".byte", ','.join([str(d) for d in x]) + print >>dst, "%s_end:" % sym + print >>dst, ".long %d" % len(marshalled) -py_compiled = [] -py_zip_depends = [] for source in py_sources: - env.Command(source.compiled, source.source, compilePyFile) - py_compiled.append(source.compiled) - - # make the zipfile depend on the archive name so that the archive - # is rebuilt if the name changes - py_zip_depends.append(Value(source.arcname)) + env.Command(source.assembly, source.tnode, objectifyPyFile) + Source(source.assembly) + +# Generate init_python.cc which creates a bunch of EmbeddedPyModule +# structs that describe the embedded python code. One such struct +# contains information about the importer that python uses to get at +# the embedded files, and then there's a list of all of the rest that +# the importer uses to load the rest on demand. +py_sources_symbols = {} +for pysource in py_sources: + py_sources_symbols[pysource.symname] = pysource +def pythonInit(target, source, env): + dst = file(str(target[0]), 'w') + + def dump_mod(sym, endchar=','): + pysource = py_sources_symbols[sym] + print >>dst, ' { "%s",' % pysource.arcname + print >>dst, ' "%s",' % pysource.modpath + print >>dst, ' %s_beg, %s_end,' % (sym, sym) + print >>dst, ' %s_end - %s_beg,' % (sym, sym) + print >>dst, ' *(int *)%s_end }%s' % (sym, endchar) + + print >>dst, '#include "sim/init.hh"' + + for sym in source: + sym = sym.get_contents() + print >>dst, "extern const char %s_beg[], %s_end[];" % (sym, sym) + + print >>dst, "const EmbeddedPyModule embeddedPyImporter = " + dump_mod("PyEMB_importer", endchar=';'); + print >>dst + + print >>dst, "const EmbeddedPyModule embeddedPyModules[] = {" + for i,sym in enumerate(source): + sym = sym.get_contents() + if sym == "PyEMB_importer": + # Skip the importer since we've already exported it + continue + dump_mod(sym) + print >>dst, " { 0, 0, 0, 0, 0, 0 }" + print >>dst, "};" -# Add the zip file target to the environment. -m5zip = File('m5py.zip') -env.Command(m5zip, py_compiled, buildPyZip) -env.Depends(m5zip, py_zip_depends) +symbols = [Value(s.symname) for s in py_sources] +env.Command('sim/init_python.cc', symbols, pythonInit) +Source('sim/init_python.cc') ######################################################################## # @@ -873,18 +944,28 @@ def makeEnv(label, objsfx, strip = False, **kwargs): newEnv = env.Copy(OBJSUFFIX=objsfx) newEnv.Label = label newEnv.Append(**kwargs) + + # First make a library of everything but main() so other programs can + # link against m5. + # + # SCons doesn't know to append a library suffix when there is a '.' in the + # name. Use '_' instead. + m5lib = newEnv.Library('m5_' + label, make_objs(cc_lib_sources, newEnv)) + + # Now link a stub with main() and the library. exe = 'm5.' + label # final executable - bin = exe + '.bin' # executable w/o appended Python zip archive - newEnv.Program(bin, make_objs(cc_sources, newEnv)) + objects = [newEnv.Object(s) for s in cc_bin_sources] + m5lib if strip: - stripped_bin = bin + '.stripped' + unstripped_exe = exe + '.unstripped' + newEnv.Program(unstripped_exe, objects) if sys.platform == 'sunos5': cmd = 'cp $SOURCE $TARGET; strip $TARGET' else: cmd = 'strip $SOURCE -o $TARGET' - newEnv.Command(stripped_bin, bin, cmd) - bin = stripped_bin - targets = newEnv.Concat(exe, [bin, 'm5py.zip']) + targets = newEnv.Command(exe, unstripped_exe, cmd) + else: + targets = newEnv.Program(exe, objects) + newEnv.M5Binary = targets[0] envList.append(newEnv) diff --git a/src/python/SConscript b/src/python/SConscript index 32bab4526..94119c77d 100644 --- a/src/python/SConscript +++ b/src/python/SConscript @@ -34,6 +34,7 @@ Import('*') Source('swig/pyevent.cc') Source('swig/pyobject.cc') +PySource('', 'importer.py') PySource('m5', 'm5/__init__.py') PySource('m5', 'm5/SimObject.py') PySource('m5', 'm5/config.py') diff --git a/src/python/importer.py b/src/python/importer.py new file mode 100644 index 000000000..fe099fdb8 --- /dev/null +++ b/src/python/importer.py @@ -0,0 +1,80 @@ +# Copyright (c) 2008 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +# Simple importer that allows python to import data from a dict of +# code objects. The keys are the module path, and the items are the +# filename and bytecode of the file. +class CodeImporter(object): + def __init__(self): + self.modules = {} + + def add_module(self, filename, modpath, code): + if modpath in self.modules: + raise AttributeError, "%s already found in importer" + + self.modules[modpath] = (filename, code) + + def find_module(self, fullname, path): + if fullname in self.modules: + return self + + return None + + def load_module(self, fullname): + # Because the importer is created and initialized in its own + # little sandbox (in init.cc), the globals that were available + # when the importer module was loaded and CodeImporter was + # defined are not available when load_module is actually + # called. Soooo, the imports must live here. + import imp + import os + import sys + mod = imp.new_module(fullname) + sys.modules[fullname] = mod + + try: + mod.__loader__ = self + srcfile,code = self.modules[fullname] + if os.path.basename(srcfile) == '__init__.py': + mod.__path__ = fullname.split('.') + mod.__file__ = srcfile + + exec code in mod.__dict__ + except Exception: + del sys.modules[fullname] + raise + + return mod + +# Create an importer and add it to the meta_path so future imports can +# use it. There's currently nothing in the importer, but calls to +# add_module can be used to add code. +import sys +importer = CodeImporter() +add_module = importer.add_module +sys.meta_path.append(importer) diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py index f21bb362e..7b071bccd 100644 --- a/src/python/m5/__init__.py +++ b/src/python/m5/__init__.py @@ -91,7 +91,7 @@ else: if running_m5: from event import * from simulate import * - from main import options + from main import options, main import stats import SimObject diff --git a/src/python/swig/init.hh b/src/python/swig/init.hh deleted file mode 100644 index 23d2c19a9..000000000 --- a/src/python/swig/init.hh +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Nathan Binkert - */ - -#ifndef __PYTHON_SWIG_INIT_HH__ -#define __PYTHON_SWIG_INIT_HH__ - -void init_swig(); - -#endif // __PYTHON_SWIG_INIT_HH__ diff --git a/src/sim/SConscript b/src/sim/SConscript index c9e4415f5..3e6adb85a 100644 --- a/src/sim/SConscript +++ b/src/sim/SConscript @@ -40,7 +40,8 @@ Source('core.cc') Source('debug.cc') Source('eventq.cc') Source('faults.cc') -Source('main.cc') +Source('init.cc') +BinSource('main.cc') Source('root.cc') Source('serialize.cc') Source('sim_events.cc') diff --git a/src/sim/init.cc b/src/sim/init.cc new file mode 100644 index 000000000..804389dae --- /dev/null +++ b/src/sim/init.cc @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2000-2005 The Regents of The University of Michigan + * Copyright (c) 2008 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +#include +#include +#include + +#include +#include +#include + +#include "base/cprintf.hh" +#include "base/misc.hh" +#include "sim/async.hh" +#include "sim/core.hh" +#include "sim/host.hh" +#include "sim/init.hh" + +using namespace std; + +/// Stats signal handler. +void +dumpStatsHandler(int sigtype) +{ + async_event = true; + async_statdump = true; +} + +void +dumprstStatsHandler(int sigtype) +{ + async_event = true; + async_statdump = true; + async_statreset = true; +} + +/// Exit signal handler. +void +exitNowHandler(int sigtype) +{ + async_event = true; + async_exit = true; +} + +/// Abort signal handler. +void +abortHandler(int sigtype) +{ + ccprintf(cerr, "Program aborted at cycle %d\n", curTick); +} + +/* + * M5 can do several special things when various signals are sent. + * None are mandatory. + */ +void +initSignals() +{ + // Floating point exceptions may happen on misspeculated paths, so + // ignore them + signal(SIGFPE, SIG_IGN); + + // We use SIGTRAP sometimes for debugging + signal(SIGTRAP, SIG_IGN); + + // Dump intermediate stats + signal(SIGUSR1, dumpStatsHandler); + + // Dump intermediate stats and reset them + signal(SIGUSR2, dumprstStatsHandler); + + // Exit cleanly on Interrupt (Ctrl-C) + signal(SIGINT, exitNowHandler); + + // Print out cycle number on abort + signal(SIGABRT, abortHandler); +} + +/* + * Uncompress and unmarshal the code object stored in the + * EmbeddedPyModule + */ +PyObject * +getCode(const EmbeddedPyModule *pymod) +{ + assert(pymod->zlen == pymod->code_end - pymod->code); + Bytef *marshalled = new Bytef[pymod->mlen]; + uLongf unzlen = pymod->mlen; + int ret = uncompress(marshalled, &unzlen, (const Bytef *)pymod->code, + pymod->zlen); + if (ret != Z_OK) + panic("Could not uncompress code: %s\n", zError(ret)); + assert(unzlen == pymod->mlen); + + return PyMarshal_ReadObjectFromString((char *)marshalled, pymod->mlen); +} + +// The python library is totally messed up with respect to constness, +// so make a simple macro to make life a little easier +#define PyCC(x) (const_cast(x)) + +/* + * Load and initialize all of the python parts of M5, including Swig + * and the embedded module importer. + */ +int +initM5Python() +{ + extern void initSwig(); + + // initialize SWIG modules. initSwig() is autogenerated and calls + // all of the individual swig initialization functions. + initSwig(); + + // Load the importer module + PyObject *code = getCode(&embeddedPyImporter); + PyObject *module = PyImport_ExecCodeModule(PyCC("importer"), code); + if (!module) { + PyErr_Print(); + return 1; + } + + // Load the rest of the embedded python files into the embedded + // python importer + const EmbeddedPyModule *pymod = &embeddedPyModules[0]; + while (pymod->filename) { + PyObject *code = getCode(pymod); + PyObject *result = PyObject_CallMethod(module, PyCC("add_module"), + PyCC("ssO"), pymod->filename, pymod->modpath, code); + if (!result) { + PyErr_Print(); + return 1; + } + Py_DECREF(result); + ++pymod; + } + + return 0; +} + +/* + * Start up the M5 simulator. This mostly vectors into the python + * main function. + */ +int +m5Main(int argc, char **argv) +{ + PySys_SetArgv(argc, argv); + + // We have to set things up in the special __main__ module + PyObject *module = PyImport_AddModule(PyCC("__main__")); + if (module == NULL) + panic("Could not import __main__"); + PyObject *dict = PyModule_GetDict(module); + + // import the main m5 module + PyObject *result; + result = PyRun_String("import m5", Py_file_input, dict, dict); + if (!result) { + PyErr_Print(); + return 1; + } + Py_DECREF(result); + + // Start m5 + result = PyRun_String("m5.main()", Py_file_input, dict, dict); + if (!result) { + PyErr_Print(); + return 1; + } + Py_DECREF(result); + + return 0; +} diff --git a/src/sim/init.hh b/src/sim/init.hh new file mode 100644 index 000000000..b0f29bf30 --- /dev/null +++ b/src/sim/init.hh @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2008 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +#ifndef __SIM_INIT_HH__ +#define __SIM_INIT_HH__ + +/* + * Data structure describing an embedded python file. + */ +struct EmbeddedPyModule +{ + const char *filename; + const char *modpath; + const char *code; + const char *code_end; + int zlen; + int mlen; +}; + +extern const EmbeddedPyModule embeddedPyImporter; +extern const EmbeddedPyModule embeddedPyModules[]; + +void initSignals(); +int initM5Python(); +int m5Main(int argc, char **argv); + +#endif // __SIM_INIT_HH__ diff --git a/src/sim/main.cc b/src/sim/main.cc index baca556a0..d674e0cff 100644 --- a/src/sim/main.cc +++ b/src/sim/main.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2005 The Regents of The University of Michigan + * Copyright (c) 2008 The Hewlett-Packard Development Company * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,125 +29,33 @@ */ #include -#include -#include -#include - -#include "base/cprintf.hh" -#include "base/misc.hh" -#include "config/pythonhome.hh" -#include "python/swig/init.hh" -#include "sim/async.hh" -#include "sim/host.hh" -#include "sim/core.hh" - -using namespace std; - -/// Stats signal handler. -void -dumpStatsHandler(int sigtype) -{ - async_event = true; - async_statdump = true; -} - -void -dumprstStatsHandler(int sigtype) -{ - async_event = true; - async_statdump = true; - async_statreset = true; -} - -/// Exit signal handler. -void -exitNowHandler(int sigtype) -{ - async_event = true; - async_exit = true; -} - -/// Abort signal handler. -void -abortHandler(int sigtype) -{ - ccprintf(cerr, "Program aborted at cycle %d\n", curTick); -} - -int -python_main() -{ - PyObject *module; - PyObject *dict; - PyObject *result; - - module = PyImport_AddModule(const_cast("__main__")); - if (module == NULL) - fatal("Could not import __main__"); - - dict = PyModule_GetDict(module); - - result = PyRun_String("import m5.main", Py_file_input, dict, dict); - if (!result) { - PyErr_Print(); - return 1; - } - Py_DECREF(result); - - result = PyRun_String("m5.main.main()", Py_file_input, dict, dict); - if (!result) { - PyErr_Print(); - return 1; - } - Py_DECREF(result); - - if (Py_FlushLine()) - PyErr_Clear(); - - return 0; -} +#include "sim/init.hh" +// main() is now pretty stripped down and just sets up python and then +// calls initM5Python which loads the various embedded python modules +// into the python environment and then starts things running by +// calling m5Main. int main(int argc, char **argv) { - signal(SIGFPE, SIG_IGN); // may occur on misspeculated paths - signal(SIGTRAP, SIG_IGN); - signal(SIGUSR1, dumpStatsHandler); // dump intermediate stats - signal(SIGUSR2, dumprstStatsHandler); // dump and reset stats - signal(SIGINT, exitNowHandler); // dump final stats and exit - signal(SIGABRT, abortHandler); - - Py_SetProgramName(argv[0]); - - // default path to m5 python code is the currently executing - // file... Python ZipImporter will find embedded zip archive. - // The M5_ARCHIVE environment variable can be used to override this. - char *m5_archive = getenv("M5_ARCHIVE"); - string pythonpath = m5_archive ? m5_archive : argv[0]; + int ret; - char *oldpath = getenv("PYTHONPATH"); - if (oldpath != NULL) { - pythonpath += ":"; - pythonpath += oldpath; - } - - if (setenv("PYTHONPATH", pythonpath.c_str(), true) == -1) - fatal("setenv: %s\n", strerror(errno)); + // Initialize m5 special signal handling. + initSignals(); - const char *python_home = getenv("PYTHONHOME"); - if (!python_home) - python_home = PYTHONHOME; - Py_SetPythonHome(const_cast(python_home)); + Py_SetProgramName(argv[0]); // initialize embedded Python interpreter Py_Initialize(); - PySys_SetArgv(argc, argv); - // initialize SWIG modules - init_swig(); + // Initialize the embedded m5 python library + ret = initM5Python(); - int ret = python_main(); + if (ret == 0) { + // start m5 + ret = m5Main(argc, argv); + } // clean up Python intepreter. Py_Finalize(); -- cgit v1.2.3 From 50ef39af82413ef463609f24173b22af13fad268 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sun, 3 Aug 2008 18:19:55 -0700 Subject: sockets: Add a function to disable all listening sockets. When invoking several copies of m5 on the same machine at the same time, there can be a race for TCP ports for the terminal connections or remote gdb. Expose a function to disable those ports, and have the regression scripts disable them. There are some SimObjects that have no other function than to be used with ports (NativeTrace and EtherTap), so they will panic if the ports are disabled. --- src/base/remote_gdb.cc | 5 +++++ src/base/socket.cc | 18 ++++++++++++++++++ src/base/socket.hh | 8 ++++++++ src/cpu/nativetrace.cc | 6 +++++- src/dev/ethertap.cc | 3 +++ src/dev/terminal.cc | 5 +++++ src/python/m5/simulate.py | 2 ++ src/python/swig/core.i | 3 +++ 8 files changed, 49 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/base/remote_gdb.cc b/src/base/remote_gdb.cc index 51293e118..06e04e19e 100644 --- a/src/base/remote_gdb.cc +++ b/src/base/remote_gdb.cc @@ -195,6 +195,11 @@ GDBListener::name() void GDBListener::listen() { + if (ListenSocket::allDisabled()) { + warn_once("Sockets disabled, not accepting gdb connections"); + return; + } + while (!listener.listen(port, true)) { DPRINTF(GDBMisc, "Can't bind port %d\n", port); port++; diff --git a/src/base/socket.cc b/src/base/socket.cc index adcc48735..bcc5236b0 100644 --- a/src/base/socket.cc +++ b/src/base/socket.cc @@ -43,6 +43,23 @@ using namespace std; +bool ListenSocket::listeningDisabled = false; +bool ListenSocket::anyListening = false; + +void +ListenSocket::disableAll() +{ + if (anyListening) + panic("Too late to disable all listeners, already have a listener"); + listeningDisabled = true; +} + +bool +ListenSocket::allDisabled() +{ + return listeningDisabled; +} + //////////////////////////////////////////////////////////////////////// // // @@ -92,6 +109,7 @@ ListenSocket::listen(int port, bool reuse) listening = true; + anyListening = true; return true; } diff --git a/src/base/socket.hh b/src/base/socket.hh index 8e55eae72..942318e45 100644 --- a/src/base/socket.hh +++ b/src/base/socket.hh @@ -33,6 +33,14 @@ class ListenSocket { + protected: + static bool listeningDisabled; + static bool anyListening; + + public: + static void disableAll(); + static bool allDisabled(); + protected: bool listening; int fd; diff --git a/src/cpu/nativetrace.cc b/src/cpu/nativetrace.cc index 7152602fe..c23a9e4ad 100644 --- a/src/cpu/nativetrace.cc +++ b/src/cpu/nativetrace.cc @@ -50,8 +50,12 @@ using namespace TheISA; namespace Trace { -NativeTrace::NativeTrace(const Params *p) : InstTracer(p) +NativeTrace::NativeTrace(const Params *p) + : InstTracer(p) { + if (ListenSocket::allDisabled()) + fatal("All listeners are disabled!"); + int port = 8000; while(!native_listener.listen(port, true)) { diff --git a/src/dev/ethertap.cc b/src/dev/ethertap.cc index 81b84d179..c7b292c8a 100644 --- a/src/dev/ethertap.cc +++ b/src/dev/ethertap.cc @@ -130,6 +130,9 @@ EtherTap::EtherTap(const Params *p) : EtherObject(p), event(NULL), socket(-1), buflen(p->bufsz), dump(p->dump), interface(NULL), txEvent(this) { + if (ListenSocket::allDisabled()) + fatal("All listeners are disabled! EtherTap can't work!"); + buffer = new char[buflen]; listener = new TapListener(this, p->port); listener->listen(); diff --git a/src/dev/terminal.cc b/src/dev/terminal.cc index 47f280ad3..58371a2bd 100644 --- a/src/dev/terminal.cc +++ b/src/dev/terminal.cc @@ -125,6 +125,11 @@ Terminal::~Terminal() void Terminal::listen(int port) { + if (ListenSocket::allDisabled()) { + warn_once("Sockets disabled, not accepting terminal connections"); + return; + } + while (!listener.listen(port, true)) { DPRINTF(Terminal, ": can't bind address terminal port %d inuse PID %d\n", diff --git a/src/python/m5/simulate.py b/src/python/m5/simulate.py index 3d91da368..e4dbd5784 100644 --- a/src/python/m5/simulate.py +++ b/src/python/m5/simulate.py @@ -182,3 +182,5 @@ def switchCpus(cpuList): for old_cpu, new_cpu in cpuList: new_cpu.takeOverFrom(old_cpu) + +from internal.core import disableAllListeners diff --git a/src/python/swig/core.i b/src/python/swig/core.i index 53d992ac6..3d360c017 100644 --- a/src/python/swig/core.i +++ b/src/python/swig/core.i @@ -34,6 +34,7 @@ %{ #include "python/swig/pyobject.hh" +#include "base/socket.hh" #include "sim/core.hh" #include "sim/host.hh" #include "sim/startup.hh" @@ -42,6 +43,7 @@ extern const char *compileDate; std::vector compileFlags(); extern const char *hgRev; extern const char *hgDate; +inline void disableAllListeners() { ListenSocket::disableAll(); } %} %include "stdint.i" @@ -53,6 +55,7 @@ void setOutputDir(const std::string &dir); void setOutputFile(const std::string &file); void SimStartup(); void doExitCleanup(); +void disableAllListeners(); %immutable compileDate; char *compileDate; -- cgit v1.2.3 From fe8aeff362844838c60ff31e444573fb7e9a7793 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Mon, 4 Aug 2008 00:40:31 -0400 Subject: Add -r/-e options to redirect stdout/stderr. Better than using shell since it automatically uses -d directory for output files (creating it as needed). --- src/base/output.cc | 6 ------ src/python/m5/main.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/base/output.cc b/src/base/output.cc index 5a1768a76..5a0f2ea70 100644 --- a/src/base/output.cc +++ b/src/base/output.cc @@ -60,12 +60,6 @@ OutputDirectory::setDirectory(const string &d) dir = d; - if (dir != ".") { - if (mkdir(dir.c_str(), 0777) < 0 && errno != EEXIST) - panic("couldn't make output dir %s: %s\n", - dir, strerror(errno)); - } - // guarantee that directory ends with a '/' if (dir[dir.size() - 1] != '/') dir += "/"; diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 2bbd72152..c9b1940dc 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -82,6 +82,14 @@ add_option('-N', "--release-notes", action="store_true", default=False, # Options for configuring the base simulator add_option('-d', "--outdir", metavar="DIR", default=".", help="Set the output directory to DIR [Default: %default]") +add_option('-r', "--redirect-stdout", action="store_true", default=False, + help="Redirect stdout (& stderr, without -e) to file") +add_option('-e', "--redirect-stderr", action="store_true", default=False, + help="Redirect stderr to file") +add_option("--stdout-file", metavar="FILE", default="simout", + help="Filename for -r redirection [Default: %default]") +add_option("--stderr-file", metavar="FILE", default="simerr", + help="Filename for -e redirection [Default: %default]") add_option('-i', "--interactive", action="store_true", default=False, help="Invoke the interactive interpreter after running the script") add_option("--pdb", action="store_true", default=False, @@ -138,6 +146,33 @@ def main(): arguments = options.parse_args() + if not os.path.isdir(options.outdir): + os.makedirs(options.outdir) + + # These filenames are used only if the redirect_std* options are set + stdout_file = os.path.join(options.outdir, options.stdout_file) + stderr_file = os.path.join(options.outdir, options.stderr_file) + + # Print redirection notices here before doing any redirection + if options.redirect_stdout and not options.redirect_stderr: + print "Redirecting stdout and stderr to", stdout_file + else: + if options.redirect_stdout: + print "Redirecting stdout to", stdout_file + if options.redirect_stderr: + print "Redirecting stderr to", stderr_file + + # Now redirect stdout/stderr as desired + if options.redirect_stdout: + redir_fd = os.open(stdout_file, os. O_WRONLY | os.O_CREAT | os.O_TRUNC) + os.dup2(redir_fd, sys.stdout.fileno()) + if not options.redirect_stderr: + os.dup2(redir_fd, sys.stderr.fileno()) + + if options.redirect_stderr: + redir_fd = os.open(stderr_file, os. O_WRONLY | os.O_CREAT | os.O_TRUNC) + os.dup2(redir_fd, sys.stderr.fileno()) + done = False if options.build_info: -- cgit v1.2.3 From 58c63ea8b1f56dd0c33ef3d36f5c6a58ce3f28fe Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Mon, 4 Aug 2008 01:45:12 -0400 Subject: Get rid of outputStream... wasn't really being used (except for warn()) and new -r/-e options make it not worth fixing. --- src/base/misc.cc | 2 -- src/python/swig/core.i | 1 - src/sim/core.cc | 8 -------- src/sim/core.hh | 5 ----- 4 files changed, 16 deletions(-) (limited to 'src') diff --git a/src/base/misc.cc b/src/base/misc.cc index afb48ca80..0ab1d6041 100644 --- a/src/base/misc.cc +++ b/src/base/misc.cc @@ -129,6 +129,4 @@ __warn(const char *func, const char *file, int line, const char *fmt, #endif ccprintf(cerr, format.c_str(), args); - if (simout.isFile(*outputStream)) - ccprintf(*outputStream, format.c_str(), args); } diff --git a/src/python/swig/core.i b/src/python/swig/core.i index 3d360c017..b0773ca68 100644 --- a/src/python/swig/core.i +++ b/src/python/swig/core.i @@ -52,7 +52,6 @@ inline void disableAllListeners() { ListenSocket::disableAll(); } %include "sim/host.hh" void setOutputDir(const std::string &dir); -void setOutputFile(const std::string &file); void SimStartup(); void doExitCleanup(); void disableAllListeners(); diff --git a/src/sim/core.cc b/src/sim/core.cc index 75f1f384c..8342b6740 100644 --- a/src/sim/core.cc +++ b/src/sim/core.cc @@ -97,14 +97,6 @@ setOutputDir(const string &dir) simout.setDirectory(dir); } -ostream *outputStream; - -void -setOutputFile(const string &file) -{ - outputStream = simout.find(file); -} - /** * Queue of C++ callbacks to invoke on simulator exit. */ diff --git a/src/sim/core.hh b/src/sim/core.hh index fb7f921f4..50cb2ef59 100644 --- a/src/sim/core.hh +++ b/src/sim/core.hh @@ -68,11 +68,6 @@ extern Tick ps; void setClockFrequency(Tick ticksPerSecond); -/// Output stream for simulator messages (e.g., cprintf()). Also used -/// as default stream for tracing and DPRINTF() messages (unless -/// overridden with trace:file option). -extern std::ostream *outputStream; -void setOutputFile(const std::string &file); void setOutputDir(const std::string &dir); struct Callback; -- cgit v1.2.3 From 3448a122085797a902e776f47bfe69a078bfca5e Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Mon, 4 Aug 2008 01:46:46 -0400 Subject: Make time format in 'started' line same as 'compiled'. Also make -B output consistent with normal header, and only include actual build options. --- src/python/m5/main.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/python/m5/main.py b/src/python/m5/main.py index c9b1940dc..1e217715c 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -180,8 +180,8 @@ def main(): print 'Build information:' print print 'compiled %s' % internal.core.cvar.compileDate; - print 'started %s' % datetime.datetime.now().ctime() - print 'executing on %s' % socket.gethostname() + print "revision %s" % internal.core.cvar.hgRev + print "commit date %s" % internal.core.cvar.hgDate print 'build options:' keys = defines.m5_build_env.keys() keys.sort() @@ -263,12 +263,12 @@ def main(): print brief_copyright print print "M5 compiled %s" % internal.core.cvar.compileDate; - print "M5 started %s" % datetime.datetime.now().ctime() - print "M5 executing on %s" % socket.gethostname() - print "M5 revision %s" % internal.core.cvar.hgRev print "M5 commit date %s" % internal.core.cvar.hgDate + print "M5 started %s" % datetime.datetime.now().strftime("%b %e %Y %X") + print "M5 executing on %s" % socket.gethostname() + print "command line:", for argv in sys.argv: print argv, -- cgit v1.2.3 From ee62a0fec8e63f45f816c61ab9fb28aba7414185 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 11 Aug 2008 12:22:16 -0700 Subject: params: Convert the CPU objects to use the auto generated param structs. A whole bunch of stuff has been converted to use the new params stuff, but the CPU wasn't one of them. While we're at it, make some things a bit more stylish. Most of the work was done by Gabe, I just cleaned stuff up a bit more at the end. --- src/arch/mips/regfile/misc_regfile.cc | 103 +++++++++---------- src/cpu/BaseCPU.py | 11 ++- src/cpu/CheckerCPU.py | 44 +++++++++ src/cpu/SConscript | 1 + src/cpu/base.cc | 49 ++++----- src/cpu/base.hh | 40 ++------ src/cpu/checker/cpu.hh | 17 +--- src/cpu/o3/O3CPU.py | 6 -- src/cpu/o3/alpha/cpu.hh | 4 +- src/cpu/o3/alpha/cpu_builder.cc | 132 ++----------------------- src/cpu/o3/alpha/cpu_impl.hh | 6 +- src/cpu/o3/alpha/impl.hh | 4 - src/cpu/o3/alpha/params.hh | 61 ------------ src/cpu/o3/bpred_unit.hh | 5 +- src/cpu/o3/bpred_unit_impl.hh | 4 +- src/cpu/o3/commit.hh | 5 +- src/cpu/o3/commit_impl.hh | 6 +- src/cpu/o3/cpu.cc | 14 +-- src/cpu/o3/cpu.hh | 11 ++- src/cpu/o3/decode.hh | 5 +- src/cpu/o3/decode_impl.hh | 6 +- src/cpu/o3/fetch.hh | 5 +- src/cpu/o3/fetch_impl.hh | 6 +- src/cpu/o3/iew.hh | 4 +- src/cpu/o3/iew_impl.hh | 5 +- src/cpu/o3/inst_queue.hh | 5 +- src/cpu/o3/inst_queue_impl.hh | 6 +- src/cpu/o3/isa_specific.hh | 3 - src/cpu/o3/lsq.hh | 5 +- src/cpu/o3/lsq_impl.hh | 6 +- src/cpu/o3/lsq_unit.hh | 8 +- src/cpu/o3/lsq_unit_impl.hh | 5 +- src/cpu/o3/mem_dep_unit.hh | 7 +- src/cpu/o3/mem_dep_unit_impl.hh | 6 +- src/cpu/o3/mips/cpu.hh | 4 +- src/cpu/o3/mips/cpu_builder.cc | 122 ++--------------------- src/cpu/o3/mips/cpu_impl.hh | 5 +- src/cpu/o3/mips/impl.hh | 4 - src/cpu/o3/mips/params.hh | 64 ------------ src/cpu/o3/params.hh | 180 ---------------------------------- src/cpu/o3/regfile.hh | 1 + src/cpu/o3/rename.hh | 5 +- src/cpu/o3/rename_impl.hh | 5 +- src/cpu/o3/sparc/cpu.hh | 4 +- src/cpu/o3/sparc/cpu_builder.cc | 132 ++----------------------- src/cpu/o3/sparc/cpu_impl.hh | 6 +- src/cpu/o3/sparc/impl.hh | 4 - src/cpu/o3/sparc/params.hh | 61 ------------ src/cpu/o3/thread_state.hh | 4 +- src/cpu/simple/AtomicSimpleCPU.py | 6 +- src/cpu/simple/BaseSimpleCPU.py | 34 +++++++ src/cpu/simple/SConscript | 1 + src/cpu/simple/TimingSimpleCPU.py | 6 +- src/cpu/simple/atomic.cc | 37 +------ src/cpu/simple/atomic.hh | 9 +- src/cpu/simple/base.cc | 6 +- src/cpu/simple/base.hh | 12 +-- src/cpu/simple/timing.cc | 34 +------ src/cpu/simple/timing.hh | 7 +- src/cpu/simple_thread.cc | 7 +- src/sim/pseudo_inst.cc | 17 ++-- 61 files changed, 335 insertions(+), 1047 deletions(-) create mode 100644 src/cpu/CheckerCPU.py delete mode 100644 src/cpu/o3/alpha/params.hh delete mode 100644 src/cpu/o3/mips/params.hh delete mode 100755 src/cpu/o3/params.hh delete mode 100644 src/cpu/o3/sparc/params.hh create mode 100644 src/cpu/simple/BaseSimpleCPU.py (limited to 'src') diff --git a/src/arch/mips/regfile/misc_regfile.cc b/src/arch/mips/regfile/misc_regfile.cc index dc6ae0baf..407851007 100755 --- a/src/arch/mips/regfile/misc_regfile.cc +++ b/src/arch/mips/regfile/misc_regfile.cc @@ -40,6 +40,8 @@ #include "cpu/base.hh" #include "cpu/exetrace.hh" +#include "params/DerivO3CPU.hh" + using namespace std; std::string MiscRegFile::miscRegNames[NumMiscRegs] = @@ -170,11 +172,12 @@ void MiscRegFile::reset(std::string core_name, unsigned num_threads, unsigned num_vpes, BaseCPU *_cpu) { - DPRINTF(MipsPRA, "Resetting CP0 State with %i TCs and %i VPEs\n", num_threads, num_vpes); cpu = _cpu; - const BaseCPU::Params *p = _cpu->params; + + TheISA::CoreSpecific &cp = cpu->coreParams; + // Do Default CP0 initialization HERE // Do Initialization for MT cores here (eventually use @@ -183,10 +186,10 @@ MiscRegFile::reset(std::string core_name, unsigned num_threads, DPRINTF(MipsPRA, "Initializing CP0 State.... "); MiscReg ProcID = readRegNoEffect(PRId); - replaceBits(ProcID,PRIdCoOp_HI,PRIdCoOp_LO,p->coreParams.CP0_PRId_CompanyOptions); - replaceBits(ProcID,PRIdCoID_HI,PRIdCoID_LO,p->coreParams.CP0_PRId_CompanyID); - replaceBits(ProcID,PRIdProc_ID_HI,PRIdProc_ID_LO,p->coreParams.CP0_PRId_ProcessorID); - replaceBits(ProcID,PRIdRev_HI,PRIdRev_LO,p->coreParams.CP0_PRId_Revision); + replaceBits(ProcID,PRIdCoOp_HI,PRIdCoOp_LO,cp.CP0_PRId_CompanyOptions); + replaceBits(ProcID,PRIdCoID_HI,PRIdCoID_LO,cp.CP0_PRId_CompanyID); + replaceBits(ProcID,PRIdProc_ID_HI,PRIdProc_ID_LO,cp.CP0_PRId_ProcessorID); + replaceBits(ProcID,PRIdRev_HI,PRIdRev_LO,cp.CP0_PRId_Revision); setRegNoEffect(PRId,ProcID); // Now, create Write Mask for ProcID register MiscReg ProcID_Mask = 0; // Read-Only register @@ -195,11 +198,11 @@ MiscRegFile::reset(std::string core_name, unsigned num_threads, // Config MiscReg cfg = readRegNoEffect(Config); - replaceBits(cfg, Config_BE_HI, Config_BE_LO, p->coreParams.CP0_Config_BE); - replaceBits(cfg, Config_AT_HI, Config_AT_LO, p->coreParams.CP0_Config_AT); - replaceBits(cfg, Config_AR_HI, Config_AR_LO, p->coreParams.CP0_Config_AR); - replaceBits(cfg, Config_MT_HI, Config_MT_LO, p->coreParams.CP0_Config_MT); - replaceBits(cfg, Config_VI_HI, Config_VI_LO, p->coreParams.CP0_Config_VI); + replaceBits(cfg, Config_BE_HI, Config_BE_LO, cp.CP0_Config_BE); + replaceBits(cfg, Config_AT_HI, Config_AT_LO, cp.CP0_Config_AT); + replaceBits(cfg, Config_AR_HI, Config_AR_LO, cp.CP0_Config_AR); + replaceBits(cfg, Config_MT_HI, Config_MT_LO, cp.CP0_Config_MT); + replaceBits(cfg, Config_VI_HI, Config_VI_LO, cp.CP0_Config_VI); replaceBits(cfg, Config_M, 1); setRegNoEffect(Config, cfg); // Now, create Write Mask for Config register @@ -209,20 +212,20 @@ MiscRegFile::reset(std::string core_name, unsigned num_threads, // Config1 MiscReg cfg1 = readRegNoEffect(Config1); - replaceBits(cfg1, Config1_MMUSize_HI, Config1_MMUSize_LO, p->coreParams.CP0_Config1_MMU); - replaceBits(cfg1, Config1_IS_HI, Config1_IS_LO, p->coreParams.CP0_Config1_IS); - replaceBits(cfg1, Config1_IL_HI, Config1_IL_LO, p->coreParams.CP0_Config1_IL); - replaceBits(cfg1, Config1_IA_HI, Config1_IA_LO, p->coreParams.CP0_Config1_IA); - replaceBits(cfg1, Config1_DS_HI, Config1_DS_LO, p->coreParams.CP0_Config1_DS); - replaceBits(cfg1, Config1_DL_HI, Config1_DL_LO, p->coreParams.CP0_Config1_DL); - replaceBits(cfg1, Config1_DA_HI, Config1_DA_LO, p->coreParams.CP0_Config1_DA); - replaceBits(cfg1, Config1_FP_HI, Config1_FP_LO, p->coreParams.CP0_Config1_FP); - replaceBits(cfg1, Config1_EP_HI, Config1_EP_LO, p->coreParams.CP0_Config1_EP); - replaceBits(cfg1, Config1_WR_HI, Config1_WR_LO, p->coreParams.CP0_Config1_WR); - replaceBits(cfg1, Config1_MD_HI, Config1_MD_LO, p->coreParams.CP0_Config1_MD); - replaceBits(cfg1, Config1_C2_HI, Config1_C2_LO, p->coreParams.CP0_Config1_C2); - replaceBits(cfg1, Config1_PC_HI, Config1_PC_LO, p->coreParams.CP0_Config1_PC); - replaceBits(cfg1, Config1_M, p->coreParams.CP0_Config1_M); + replaceBits(cfg1, Config1_MMUSize_HI, Config1_MMUSize_LO, cp.CP0_Config1_MMU); + replaceBits(cfg1, Config1_IS_HI, Config1_IS_LO, cp.CP0_Config1_IS); + replaceBits(cfg1, Config1_IL_HI, Config1_IL_LO, cp.CP0_Config1_IL); + replaceBits(cfg1, Config1_IA_HI, Config1_IA_LO, cp.CP0_Config1_IA); + replaceBits(cfg1, Config1_DS_HI, Config1_DS_LO, cp.CP0_Config1_DS); + replaceBits(cfg1, Config1_DL_HI, Config1_DL_LO, cp.CP0_Config1_DL); + replaceBits(cfg1, Config1_DA_HI, Config1_DA_LO, cp.CP0_Config1_DA); + replaceBits(cfg1, Config1_FP_HI, Config1_FP_LO, cp.CP0_Config1_FP); + replaceBits(cfg1, Config1_EP_HI, Config1_EP_LO, cp.CP0_Config1_EP); + replaceBits(cfg1, Config1_WR_HI, Config1_WR_LO, cp.CP0_Config1_WR); + replaceBits(cfg1, Config1_MD_HI, Config1_MD_LO, cp.CP0_Config1_MD); + replaceBits(cfg1, Config1_C2_HI, Config1_C2_LO, cp.CP0_Config1_C2); + replaceBits(cfg1, Config1_PC_HI, Config1_PC_LO, cp.CP0_Config1_PC); + replaceBits(cfg1, Config1_M, cp.CP0_Config1_M); setRegNoEffect(Config1, cfg1); // Now, create Write Mask for Config register MiscReg cfg1_Mask = 0; // Read Only Register @@ -231,15 +234,15 @@ MiscRegFile::reset(std::string core_name, unsigned num_threads, // Config2 MiscReg cfg2 = readRegNoEffect(Config2); - replaceBits(cfg2, Config2_TU_HI, Config2_TU_LO, p->coreParams.CP0_Config2_TU); - replaceBits(cfg2, Config2_TS_HI, Config2_TS_LO, p->coreParams.CP0_Config2_TS); - replaceBits(cfg2, Config2_TL_HI, Config2_TL_LO, p->coreParams.CP0_Config2_TL); - replaceBits(cfg2, Config2_TA_HI, Config2_TA_LO, p->coreParams.CP0_Config2_TA); - replaceBits(cfg2, Config2_SU_HI, Config2_SU_LO, p->coreParams.CP0_Config2_SU); - replaceBits(cfg2, Config2_SS_HI, Config2_SS_LO, p->coreParams.CP0_Config2_SS); - replaceBits(cfg2, Config2_SL_HI, Config2_SL_LO, p->coreParams.CP0_Config2_SL); - replaceBits(cfg2, Config2_SA_HI, Config2_SA_LO, p->coreParams.CP0_Config2_SA); - replaceBits(cfg2, Config2_M, p->coreParams.CP0_Config2_M); + replaceBits(cfg2, Config2_TU_HI, Config2_TU_LO, cp.CP0_Config2_TU); + replaceBits(cfg2, Config2_TS_HI, Config2_TS_LO, cp.CP0_Config2_TS); + replaceBits(cfg2, Config2_TL_HI, Config2_TL_LO, cp.CP0_Config2_TL); + replaceBits(cfg2, Config2_TA_HI, Config2_TA_LO, cp.CP0_Config2_TA); + replaceBits(cfg2, Config2_SU_HI, Config2_SU_LO, cp.CP0_Config2_SU); + replaceBits(cfg2, Config2_SS_HI, Config2_SS_LO, cp.CP0_Config2_SS); + replaceBits(cfg2, Config2_SL_HI, Config2_SL_LO, cp.CP0_Config2_SL); + replaceBits(cfg2, Config2_SA_HI, Config2_SA_LO, cp.CP0_Config2_SA); + replaceBits(cfg2, Config2_M, cp.CP0_Config2_M); setRegNoEffect(Config2, cfg2); // Now, create Write Mask for Config register MiscReg cfg2_Mask = 0x7000F000; // Read Only Register @@ -248,14 +251,14 @@ MiscRegFile::reset(std::string core_name, unsigned num_threads, // Config3 MiscReg cfg3 = readRegNoEffect(Config3); - replaceBits(cfg3, Config3_DSPP_HI, Config3_DSPP_LO, p->coreParams.CP0_Config3_DSPP); - replaceBits(cfg3, Config3_LPA_HI, Config3_LPA_LO, p->coreParams.CP0_Config3_LPA); - replaceBits(cfg3, Config3_VEIC_HI, Config3_VEIC_LO, p->coreParams.CP0_Config3_VEIC); - replaceBits(cfg3, Config3_VINT_HI, Config3_VINT_LO, p->coreParams.CP0_Config3_VInt); - replaceBits(cfg3, Config3_SP_HI, Config3_SP_LO, p->coreParams.CP0_Config3_SP); - replaceBits(cfg3, Config3_MT_HI, Config3_MT_LO, p->coreParams.CP0_Config3_MT); - replaceBits(cfg3, Config3_SM_HI, Config3_SM_LO, p->coreParams.CP0_Config3_SM); - replaceBits(cfg3, Config3_TL_HI, Config3_TL_LO, p->coreParams.CP0_Config3_TL); + replaceBits(cfg3, Config3_DSPP_HI, Config3_DSPP_LO, cp.CP0_Config3_DSPP); + replaceBits(cfg3, Config3_LPA_HI, Config3_LPA_LO, cp.CP0_Config3_LPA); + replaceBits(cfg3, Config3_VEIC_HI, Config3_VEIC_LO, cp.CP0_Config3_VEIC); + replaceBits(cfg3, Config3_VINT_HI, Config3_VINT_LO, cp.CP0_Config3_VInt); + replaceBits(cfg3, Config3_SP_HI, Config3_SP_LO, cp.CP0_Config3_SP); + replaceBits(cfg3, Config3_MT_HI, Config3_MT_LO, cp.CP0_Config3_MT); + replaceBits(cfg3, Config3_SM_HI, Config3_SM_LO, cp.CP0_Config3_SM); + replaceBits(cfg3, Config3_TL_HI, Config3_TL_LO, cp.CP0_Config3_TL); setRegNoEffect(Config3, cfg3); // Now, create Write Mask for Config register MiscReg cfg3_Mask = 0; // Read Only Register @@ -264,7 +267,7 @@ MiscRegFile::reset(std::string core_name, unsigned num_threads, // EBase - CPUNum MiscReg EB = readRegNoEffect(EBase); - replaceBits(EB, EBase_CPUNum_HI, EBase_CPUNum_LO, p->coreParams.CP0_EBase_CPUNum); + replaceBits(EB, EBase_CPUNum_HI, EBase_CPUNum_LO, cp.CP0_EBase_CPUNum); replaceBits(EB, 31, 31, 1); setRegNoEffect(EBase, EB); // Now, create Write Mask for Config register @@ -275,7 +278,7 @@ MiscRegFile::reset(std::string core_name, unsigned num_threads, // SRS Control - HSS (Highest Shadow Set) MiscReg SC = readRegNoEffect(SRSCtl); - replaceBits(SC, SRSCtl_HSS_HI,SRSCtl_HSS_LO,p->coreParams.CP0_SrsCtl_HSS); + replaceBits(SC, SRSCtl_HSS_HI,SRSCtl_HSS_LO,cp.CP0_SrsCtl_HSS); setRegNoEffect(SRSCtl, SC); // Now, create Write Mask for the SRS Ctl register MiscReg SC_Mask = 0x0000F3C0; @@ -284,8 +287,8 @@ MiscRegFile::reset(std::string core_name, unsigned num_threads, // IntCtl - IPTI, IPPCI MiscReg IC = readRegNoEffect(IntCtl); - replaceBits(IC, IntCtl_IPTI_HI,IntCtl_IPTI_LO,p->coreParams.CP0_IntCtl_IPTI); - replaceBits(IC, IntCtl_IPPCI_HI,IntCtl_IPPCI_LO,p->coreParams.CP0_IntCtl_IPPCI); + replaceBits(IC, IntCtl_IPTI_HI,IntCtl_IPTI_LO,cp.CP0_IntCtl_IPTI); + replaceBits(IC, IntCtl_IPPCI_HI,IntCtl_IPPCI_LO,cp.CP0_IntCtl_IPPCI); setRegNoEffect(IntCtl, IC); // Now, create Write Mask for the IntCtl register MiscReg IC_Mask = 0x000003E0; @@ -294,7 +297,7 @@ MiscRegFile::reset(std::string core_name, unsigned num_threads, // Watch Hi - M - FIXME (More than 1 Watch register) MiscReg WHi = readRegNoEffect(WatchHi0); - replaceBits(WHi, WatchHi_M, p->coreParams.CP0_WatchHi_M); + replaceBits(WHi, WatchHi_M, cp.CP0_WatchHi_M); setRegNoEffect(WatchHi0, WHi); // Now, create Write Mask for the IntCtl register MiscReg wh_Mask = 0x7FFF0FFF; @@ -303,8 +306,8 @@ MiscRegFile::reset(std::string core_name, unsigned num_threads, // Perf Ctr - M - FIXME (More than 1 PerfCnt Pair) MiscReg PCtr = readRegNoEffect(PerfCnt0); - replaceBits(PCtr, PerfCntCtl_M, p->coreParams.CP0_PerfCtr_M); - replaceBits(PCtr, PerfCntCtl_W, p->coreParams.CP0_PerfCtr_W); + replaceBits(PCtr, PerfCntCtl_M, cp.CP0_PerfCtr_M); + replaceBits(PCtr, PerfCntCtl_W, cp.CP0_PerfCtr_W); setRegNoEffect(PerfCnt0, PCtr); // Now, create Write Mask for the IntCtl register MiscReg pc_Mask = 0x00007FF; @@ -322,7 +325,7 @@ MiscRegFile::reset(std::string core_name, unsigned num_threads, // PageGrain MiscReg pagegrain = readRegNoEffect(PageGrain); - replaceBits(pagegrain,PageGrain_ESP,p->coreParams.CP0_Config3_SP); + replaceBits(pagegrain,PageGrain_ESP,cp.CP0_Config3_SP); setRegNoEffect(PageGrain, pagegrain); // Now, create Write Mask for the IntCtl register MiscReg pg_Mask = 0x10000000; diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py index c2a865113..1e3f0dbbc 100644 --- a/src/cpu/BaseCPU.py +++ b/src/cpu/BaseCPU.py @@ -26,7 +26,7 @@ # # Authors: Nathan Binkert -from m5.SimObject import SimObject +from MemObject import MemObject from m5.params import * from m5.proxy import * from m5 import build_env @@ -48,14 +48,21 @@ elif build_env['TARGET_ISA'] == 'mips': elif build_env['TARGET_ISA'] == 'arm': from ArmTLB import ArmTLB, ArmDTB, ArmITB, ArmUTB -class BaseCPU(SimObject): +class BaseCPU(MemObject): type = 'BaseCPU' abstract = True system = Param.System(Parent.any, "system object") cpu_id = Param.Int("CPU identifier") + numThreads = Param.Unsigned(1, "number of HW thread contexts") + + function_trace = Param.Bool(False, "Enable function trace") + function_trace_start = Param.Tick(0, "Cycle to start function trace") + + checker = Param.BaseCPU("checker CPU") if build_env['FULL_SYSTEM']: + profile = Param.Latency('0ns', "trace the kernel stack") do_quiesce = Param.Bool(True, "enable quiesce instructions") do_checkpoint_insts = Param.Bool(True, "enable checkpoint pseudo instructions") diff --git a/src/cpu/CheckerCPU.py b/src/cpu/CheckerCPU.py new file mode 100644 index 000000000..06df9c1b1 --- /dev/null +++ b/src/cpu/CheckerCPU.py @@ -0,0 +1,44 @@ +# Copyright (c) 2007 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +from m5.params import * +from m5 import build_env +from BaseCPU import BaseCPU + +class CheckerCPU(BaseCPU): + type = 'CheckerCPU' + abstract = True + exitOnError = Param.Bool(False, "Exit on an error") + updateOnError = Param.Bool(False, + "Update the checker with the main CPU's state on an error") + warnOnlyOnLoadError = Param.Bool(False, + "If a load result is incorrect, only print a warning and do not exit") + function_trace = Param.Bool(False, "Enable function trace") + function_trace_start = Param.Tick(0, "Cycle to start function trace") + if build_env['FULL_SYSTEM']: + profile = Param.Latency('0ns', "trace the kernel stack") diff --git a/src/cpu/SConscript b/src/cpu/SConscript index c6a959d9d..750e1ee4c 100644 --- a/src/cpu/SConscript +++ b/src/cpu/SConscript @@ -71,6 +71,7 @@ temp_cpu_list = env['CPU_MODELS'][:] if env['USE_CHECKER']: temp_cpu_list.append('CheckerCPU') + SimObject('CheckerCPU.py') # Generate header. def gen_cpu_exec_signatures(target, source, env): diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 6ce082996..f79b79350 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -37,17 +37,17 @@ #include "base/loader/symtab.hh" #include "base/misc.hh" #include "base/output.hh" +#include "base/trace.hh" #include "cpu/base.hh" #include "cpu/cpuevent.hh" #include "cpu/thread_context.hh" #include "cpu/profile.hh" +#include "params/BaseCPU.hh" #include "sim/sim_exit.hh" #include "sim/process.hh" #include "sim/sim_events.hh" #include "sim/system.hh" -#include "base/trace.hh" - // Hack #include "sim/stat_control.hh" @@ -95,13 +95,13 @@ CPUProgressEvent::description() const #if FULL_SYSTEM BaseCPU::BaseCPU(Params *p) - : MemObject(makeParams(p->name)), clock(p->clock), instCnt(0), - params(p), number_of_threads(p->numberOfThreads), system(p->system), + : MemObject(p), clock(p->clock), instCnt(0), + number_of_threads(p->numThreads), system(p->system), phase(p->phase) #else BaseCPU::BaseCPU(Params *p) - : MemObject(makeParams(p->name)), clock(p->clock), params(p), - number_of_threads(p->numberOfThreads), system(p->system), + : MemObject(p), clock(p->clock), + number_of_threads(p->numThreads), system(p->system), phase(p->phase) #endif { @@ -166,34 +166,25 @@ BaseCPU::BaseCPU(Params *p) } functionTracingEnabled = false; - if (p->functionTrace) { + if (p->function_trace) { functionTraceStream = simout.find(csprintf("ftrace.%s", name())); currentFunctionStart = currentFunctionEnd = 0; - functionEntryTick = p->functionTraceStart; + functionEntryTick = p->function_trace_start; - if (p->functionTraceStart == 0) { + if (p->function_trace_start == 0) { functionTracingEnabled = true; } else { - new EventWrapper(this, - p->functionTraceStart, - true); + new EventWrapper( + this, p->function_trace_start, true); } } #if FULL_SYSTEM profileEvent = NULL; - if (params->profile) - profileEvent = new ProfileEvent(this, params->profile); -#endif - tracer = params->tracer; -} - -BaseCPU::Params::Params() -{ -#if FULL_SYSTEM - profile = false; + if (params()->profile) + profileEvent = new ProfileEvent(this, params()->profile); #endif - checker = NULL; - tracer = NULL; + tracer = params()->tracer; } void @@ -209,7 +200,7 @@ BaseCPU::~BaseCPU() void BaseCPU::init() { - if (!params->deferRegistration) + if (!params()->defer_registration) registerThreadContexts(); } @@ -217,13 +208,13 @@ void BaseCPU::startup() { #if FULL_SYSTEM - if (!params->deferRegistration && profileEvent) + if (!params()->defer_registration && profileEvent) profileEvent->schedule(curTick); #endif - if (params->progress_interval) { + if (params()->progress_interval) { new CPUProgressEvent(&mainEventQueue, - ticks(params->progress_interval), + ticks(params()->progress_interval), this); } } @@ -281,7 +272,7 @@ BaseCPU::registerThreadContexts() ThreadContext *tc = threadContexts[i]; #if FULL_SYSTEM - int id = params->cpu_id; + int id = params()->cpu_id; if (id != -1) id += i; diff --git a/src/cpu/base.hh b/src/cpu/base.hh index bdc7d7c8b..6e9e1dc39 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -45,6 +45,7 @@ #include "arch/interrupts.hh" #endif +class BaseCPUParams; class BranchPred; class CheckerCPU; class ThreadContext; @@ -162,40 +163,9 @@ class BaseCPU : public MemObject ThreadContext *getContext(int tn) { return threadContexts[tn]; } public: - struct Params - { - std::string name; - int numberOfThreads; - bool deferRegistration; - Counter max_insts_any_thread; - Counter max_insts_all_threads; - Counter max_loads_any_thread; - Counter max_loads_all_threads; - Tick clock; - bool functionTrace; - Tick functionTraceStart; - System *system; - int cpu_id; - Trace::InstTracer * tracer; - - Tick phase; -#if FULL_SYSTEM - Tick profile; - - bool do_statistics_insts; - bool do_checkpoint_insts; - bool do_quiesce; -#endif - Tick progress_interval; - BaseCPU *checker; - - TheISA::CoreSpecific coreParams; //ISA-Specific Params That Set Up State in Core - - Params(); - }; - - const Params *params; - + typedef BaseCPUParams Params; + const Params *params() const + { return reinterpret_cast(_params); } BaseCPU(Params *params); virtual ~BaseCPU(); @@ -221,6 +191,8 @@ class BaseCPU : public MemObject */ int number_of_threads; + TheISA::CoreSpecific coreParams; //ISA-Specific Params That Set Up State in Core + /** * Vector of per-thread instruction-based event queues. Used for * scheduling events based on number of instructions committed by diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh index 35dc59ff4..17648d508 100644 --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@ -65,6 +65,7 @@ class Process; #endif // FULL_SYSTEM template class BaseDynInst; +class CheckerCPUParams; class ThreadContext; class MemInterface; class Checkpoint; @@ -96,20 +97,10 @@ class CheckerCPU : public BaseCPU public: virtual void init(); - struct Params : public BaseCPU::Params - { -#if FULL_SYSTEM - TheISA::ITB *itb; - TheISA::DTB *dtb; -#else - Process *process; -#endif - bool exitOnError; - bool updateOnError; - bool warnOnlyOnLoadError; - }; - public: + typedef CheckerCPUParams Params; + const Params *params() const + { return reinterpret_cast(_params); } CheckerCPU(Params *p); virtual ~CheckerCPU(); diff --git a/src/cpu/o3/O3CPU.py b/src/cpu/o3/O3CPU.py index f0284b2cf..56e537ad2 100644 --- a/src/cpu/o3/O3CPU.py +++ b/src/cpu/o3/O3CPU.py @@ -38,10 +38,7 @@ if build_env['USE_CHECKER']: class DerivO3CPU(BaseCPU): type = 'DerivO3CPU' activity = Param.Unsigned(0, "Initial count") - numThreads = Param.Unsigned(1, "number of HW thread contexts") - if build_env['FULL_SYSTEM']: - profile = Param.Latency('0ns', "trace the kernel stack") if build_env['USE_CHECKER']: if not build_env['FULL_SYSTEM']: checker = Param.BaseCPU(O3Checker(workload=Parent.workload, @@ -134,9 +131,6 @@ class DerivO3CPU(BaseCPU): instShiftAmt = Param.Unsigned(2, "Number of bits to shift instructions by") - function_trace = Param.Bool(False, "Enable function trace") - function_trace_start = Param.Tick(0, "Cycle to start function trace") - smtNumFetchingThreads = Param.Unsigned(1, "SMT Number of Fetching Threads") smtFetchPolicy = Param.String('SingleThread', "SMT Fetch policy") smtLSQPolicy = Param.String('Partitioned', "SMT LSQ Sharing Policy") diff --git a/src/cpu/o3/alpha/cpu.hh b/src/cpu/o3/alpha/cpu.hh index ebc4e7b23..f9f0000d4 100644 --- a/src/cpu/o3/alpha/cpu.hh +++ b/src/cpu/o3/alpha/cpu.hh @@ -37,6 +37,7 @@ #include "cpu/o3/cpu.hh" #include "sim/byteswap.hh" +class DerivO3CPUParams; class EndQuiesceEvent; namespace Kernel { class Statistics; @@ -58,10 +59,9 @@ class AlphaO3CPU : public FullO3CPU public: typedef O3ThreadState ImplState; typedef O3ThreadState Thread; - typedef typename Impl::Params Params; /** Constructs an AlphaO3CPU with the given parameters. */ - AlphaO3CPU(Params *params); + AlphaO3CPU(DerivO3CPUParams *params); /** Registers statistics. */ void regStats(); diff --git a/src/cpu/o3/alpha/cpu_builder.cc b/src/cpu/o3/alpha/cpu_builder.cc index f569c048b..0ff0d5d52 100644 --- a/src/cpu/o3/alpha/cpu_builder.cc +++ b/src/cpu/o3/alpha/cpu_builder.cc @@ -34,14 +34,13 @@ #include "cpu/base.hh" #include "cpu/o3/alpha/cpu.hh" #include "cpu/o3/alpha/impl.hh" -#include "cpu/o3/alpha/params.hh" #include "cpu/o3/fu_pool.hh" #include "params/DerivO3CPU.hh" class DerivO3CPU : public AlphaO3CPU { public: - DerivO3CPU(AlphaSimpleParams *p) + DerivO3CPU(DerivO3CPUParams *p) : AlphaO3CPU(p) { } }; @@ -49,8 +48,6 @@ class DerivO3CPU : public AlphaO3CPU DerivO3CPU * DerivO3CPUParams::create() { - DerivO3CPU *cpu; - #if FULL_SYSTEM // Full-system only supports a single thread for the moment. int actual_num_threads = 1; @@ -65,135 +62,18 @@ DerivO3CPUParams::create() } #endif - AlphaSimpleParams *params = new AlphaSimpleParams; - - params->clock = clock; - params->phase = phase; - - params->tracer = tracer; - - params->name = name; - params->numberOfThreads = actual_num_threads; - params->cpu_id = cpu_id; - params->activity = activity; - - params->itb = itb; - params->dtb = dtb; - - params->system = system; -#if FULL_SYSTEM - params->profile = profile; - - params->do_quiesce = do_quiesce; - params->do_checkpoint_insts = do_checkpoint_insts; - params->do_statistics_insts = do_statistics_insts; -#else - params->workload = workload; -#endif // FULL_SYSTEM - -#if USE_CHECKER - params->checker = checker; -#endif - - params->max_insts_any_thread = max_insts_any_thread; - params->max_insts_all_threads = max_insts_all_threads; - params->max_loads_any_thread = max_loads_any_thread; - params->max_loads_all_threads = max_loads_all_threads; - params->progress_interval = progress_interval; - - // - // Caches - // - params->cachePorts = cachePorts; - - params->decodeToFetchDelay = decodeToFetchDelay; - params->renameToFetchDelay = renameToFetchDelay; - params->iewToFetchDelay = iewToFetchDelay; - params->commitToFetchDelay = commitToFetchDelay; - params->fetchWidth = fetchWidth; - - params->renameToDecodeDelay = renameToDecodeDelay; - params->iewToDecodeDelay = iewToDecodeDelay; - params->commitToDecodeDelay = commitToDecodeDelay; - params->fetchToDecodeDelay = fetchToDecodeDelay; - params->decodeWidth = decodeWidth; - - params->iewToRenameDelay = iewToRenameDelay; - params->commitToRenameDelay = commitToRenameDelay; - params->decodeToRenameDelay = decodeToRenameDelay; - params->renameWidth = renameWidth; - - params->commitToIEWDelay = commitToIEWDelay; - params->renameToIEWDelay = renameToIEWDelay; - params->issueToExecuteDelay = issueToExecuteDelay; - params->dispatchWidth = dispatchWidth; - params->issueWidth = issueWidth; - params->wbWidth = wbWidth; - params->wbDepth = wbDepth; - params->fuPool = fuPool; - - params->iewToCommitDelay = iewToCommitDelay; - params->renameToROBDelay = renameToROBDelay; - params->commitWidth = commitWidth; - params->squashWidth = squashWidth; - params->trapLatency = trapLatency; - - params->backComSize = backComSize; - params->forwardComSize = forwardComSize; - - params->predType = predType; - params->localPredictorSize = localPredictorSize; - params->localCtrBits = localCtrBits; - params->localHistoryTableSize = localHistoryTableSize; - params->localHistoryBits = localHistoryBits; - params->globalPredictorSize = globalPredictorSize; - params->globalCtrBits = globalCtrBits; - params->globalHistoryBits = globalHistoryBits; - params->choicePredictorSize = choicePredictorSize; - params->choiceCtrBits = choiceCtrBits; - - params->BTBEntries = BTBEntries; - params->BTBTagSize = BTBTagSize; - - params->RASSize = RASSize; - - params->LQEntries = LQEntries; - params->SQEntries = SQEntries; - - params->SSITSize = SSITSize; - params->LFSTSize = LFSTSize; - - params->numPhysIntRegs = numPhysIntRegs; - params->numPhysFloatRegs = numPhysFloatRegs; - params->numIQEntries = numIQEntries; - params->numROBEntries = numROBEntries; - - params->smtNumFetchingThreads = smtNumFetchingThreads; + numThreads = actual_num_threads; // Default smtFetchPolicy to "RoundRobin", if necessary. std::string round_robin_policy = "RoundRobin"; std::string single_thread = "SingleThread"; if (actual_num_threads > 1 && single_thread.compare(smtFetchPolicy) == 0) - params->smtFetchPolicy = round_robin_policy; + smtFetchPolicy = round_robin_policy; else - params->smtFetchPolicy = smtFetchPolicy; - - params->smtIQPolicy = smtIQPolicy; - params->smtLSQPolicy = smtLSQPolicy; - params->smtLSQThreshold = smtLSQThreshold; - params->smtROBPolicy = smtROBPolicy; - params->smtROBThreshold = smtROBThreshold; - params->smtCommitPolicy = smtCommitPolicy; - - params->instShiftAmt = 2; - - params->deferRegistration = defer_registration; - - params->functionTrace = function_trace; - params->functionTraceStart = function_trace_start; + smtFetchPolicy = smtFetchPolicy; - cpu = new DerivO3CPU(params); + instShiftAmt = 2; - return cpu; + return new DerivO3CPU(this); } diff --git a/src/cpu/o3/alpha/cpu_impl.hh b/src/cpu/o3/alpha/cpu_impl.hh index 7f8f0547b..dc64113e1 100644 --- a/src/cpu/o3/alpha/cpu_impl.hh +++ b/src/cpu/o3/alpha/cpu_impl.hh @@ -40,7 +40,6 @@ #include "sim/stats.hh" #include "cpu/o3/alpha/cpu.hh" -#include "cpu/o3/alpha/params.hh" #include "cpu/o3/alpha/thread_context.hh" #include "cpu/o3/comm.hh" #include "cpu/o3/thread_state.hh" @@ -54,8 +53,11 @@ #include "sim/system.hh" #endif +#include "params/DerivO3CPU.hh" + template -AlphaO3CPU::AlphaO3CPU(Params *params) : FullO3CPU(this, params) +AlphaO3CPU::AlphaO3CPU(DerivO3CPUParams *params) : + FullO3CPU(this, params) { DPRINTF(O3CPU, "Creating AlphaO3CPU object.\n"); diff --git a/src/cpu/o3/alpha/impl.hh b/src/cpu/o3/alpha/impl.hh index b928ae654..d2d04292c 100644 --- a/src/cpu/o3/alpha/impl.hh +++ b/src/cpu/o3/alpha/impl.hh @@ -33,7 +33,6 @@ #include "arch/alpha/isa_traits.hh" -#include "cpu/o3/alpha/params.hh" #include "cpu/o3/cpu_policy.hh" @@ -77,9 +76,6 @@ struct AlphaSimpleImpl */ typedef O3CPU CPUType; - /** The Params to be passed to each stage. */ - typedef AlphaSimpleParams Params; - enum { MaxWidth = 8, MaxThreads = 4 diff --git a/src/cpu/o3/alpha/params.hh b/src/cpu/o3/alpha/params.hh deleted file mode 100644 index 164c25312..000000000 --- a/src/cpu/o3/alpha/params.hh +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2004-2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - */ - -#ifndef __CPU_O3_ALPHA_PARAMS_HH__ -#define __CPU_O3_ALPHA_PARAMS_HH__ - -#include "cpu/o3/cpu.hh" -#include "cpu/o3/params.hh" - -//Forward declarations -namespace AlphaISA -{ - class DTB; - class ITB; -} -class MemObject; -class Process; -class System; - -/** - * This file defines the parameters that will be used for the AlphaO3CPU. - * This must be defined externally so that the Impl can have a params class - * defined that it can pass to all of the individual stages. - */ - -class AlphaSimpleParams : public O3Params -{ - public: - - AlphaISA::ITB *itb; - AlphaISA::DTB *dtb; -}; - -#endif // __CPU_O3_ALPHA_PARAMS_HH__ diff --git a/src/cpu/o3/bpred_unit.hh b/src/cpu/o3/bpred_unit.hh index 3c4c8e478..34fe74178 100644 --- a/src/cpu/o3/bpred_unit.hh +++ b/src/cpu/o3/bpred_unit.hh @@ -43,6 +43,8 @@ #include +class DerivO3CPUParams; + /** * Basically a wrapper class to hold both the branch predictor * and the BTB. @@ -51,7 +53,6 @@ template class BPredUnit { private: - typedef typename Impl::Params Params; typedef typename Impl::DynInstPtr DynInstPtr; enum PredType { @@ -66,7 +67,7 @@ class BPredUnit /** * @param params The params object, that has the size of the BP and BTB. */ - BPredUnit(Params *params); + BPredUnit(DerivO3CPUParams *params); /** * Registers statistics. diff --git a/src/cpu/o3/bpred_unit_impl.hh b/src/cpu/o3/bpred_unit_impl.hh index 84c50b4da..ded72a1b5 100644 --- a/src/cpu/o3/bpred_unit_impl.hh +++ b/src/cpu/o3/bpred_unit_impl.hh @@ -34,8 +34,10 @@ #include "base/traceflags.hh" #include "cpu/o3/bpred_unit.hh" +#include "params/DerivO3CPU.hh" + template -BPredUnit::BPredUnit(Params *params) +BPredUnit::BPredUnit(DerivO3CPUParams *params) : BTB(params->BTBEntries, params->BTBTagSize, params->instShiftAmt) diff --git a/src/cpu/o3/commit.hh b/src/cpu/o3/commit.hh index 80e42fa8b..ff1e517f2 100644 --- a/src/cpu/o3/commit.hh +++ b/src/cpu/o3/commit.hh @@ -37,6 +37,8 @@ #include "cpu/exetrace.hh" #include "cpu/inst_seq.hh" +class DerivO3CPUParams; + template class O3ThreadState; @@ -69,7 +71,6 @@ class DefaultCommit // Typedefs from the Impl. typedef typename Impl::O3CPU O3CPU; typedef typename Impl::DynInstPtr DynInstPtr; - typedef typename Impl::Params Params; typedef typename Impl::CPUPol CPUPol; typedef typename CPUPol::RenameMap RenameMap; @@ -136,7 +137,7 @@ class DefaultCommit public: /** Construct a DefaultCommit with the given parameters. */ - DefaultCommit(O3CPU *_cpu, Params *params); + DefaultCommit(O3CPU *_cpu, DerivO3CPUParams *params); /** Returns the name of the DefaultCommit. */ std::string name() const; diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index ee0f2bb59..86b4da8ce 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -46,6 +46,8 @@ #include "cpu/checker/cpu.hh" #endif +#include "params/DerivO3CPU.hh" + template DefaultCommit::TrapEvent::TrapEvent(DefaultCommit *_commit, unsigned _tid) @@ -71,7 +73,7 @@ DefaultCommit::TrapEvent::description() const } template -DefaultCommit::DefaultCommit(O3CPU *_cpu, Params *params) +DefaultCommit::DefaultCommit(O3CPU *_cpu, DerivO3CPUParams *params) : cpu(_cpu), squashCounter(0), iewToCommitDelay(params->iewToCommitDelay), @@ -80,7 +82,7 @@ DefaultCommit::DefaultCommit(O3CPU *_cpu, Params *params) fetchToCommitDelay(params->commitToFetchDelay), renameWidth(params->renameWidth), commitWidth(params->commitWidth), - numThreads(params->numberOfThreads), + numThreads(params->numThreads), drainPending(false), switchedOut(false), trapLatency(params->trapLatency) diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index fac214174..f06aee634 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -52,9 +52,11 @@ #include "cpu/checker/cpu.hh" #endif +class BaseCPUParams; + using namespace TheISA; -BaseO3CPU::BaseO3CPU(Params *params) +BaseO3CPU::BaseO3CPU(BaseCPUParams *params) : BaseCPU(params), cpu_id(0) { } @@ -147,7 +149,7 @@ FullO3CPU::DeallocateContextEvent::description() const } template -FullO3CPU::FullO3CPU(O3CPU *o3_cpu, Params *params) +FullO3CPU::FullO3CPU(O3CPU *o3_cpu, DerivO3CPUParams *params) : BaseO3CPU(params), itb(params->itb), dtb(params->dtb), @@ -162,16 +164,16 @@ FullO3CPU::FullO3CPU(O3CPU *o3_cpu, Params *params) regFile(o3_cpu, params->numPhysIntRegs, params->numPhysFloatRegs), - freeList(params->numberOfThreads, + freeList(params->numThreads, TheISA::NumIntRegs, params->numPhysIntRegs, TheISA::NumFloatRegs, params->numPhysFloatRegs), rob(o3_cpu, params->numROBEntries, params->squashWidth, params->smtROBPolicy, params->smtROBThreshold, - params->numberOfThreads), + params->numThreads), - scoreboard(params->numberOfThreads, + scoreboard(params->numThreads, TheISA::NumIntRegs, params->numPhysIntRegs, TheISA::NumFloatRegs, params->numPhysFloatRegs, TheISA::NumMiscRegs * number_of_threads, @@ -192,7 +194,7 @@ FullO3CPU::FullO3CPU(O3CPU *o3_cpu, Params *params) physmem(system->physmem), #endif // FULL_SYSTEM drainCount(0), - deferRegistration(params->deferRegistration), + deferRegistration(params->defer_registration), numThreads(number_of_threads) { if (!deferRegistration) { diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 61d7dcf22..611d03bad 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -53,6 +53,8 @@ //#include "cpu/o3/thread_context.hh" #include "sim/process.hh" +#include "params/DerivO3CPU.hh" + template class Checker; class ThreadContext; @@ -63,13 +65,13 @@ class Checkpoint; class MemObject; class Process; +class BaseCPUParams; + class BaseO3CPU : public BaseCPU { //Stuff that's pretty ISA independent will go here. public: - typedef BaseCPU::Params Params; - - BaseO3CPU(Params *params); + BaseO3CPU(BaseCPUParams *params); void regStats(); @@ -96,7 +98,6 @@ class FullO3CPU : public BaseO3CPU typedef typename Impl::CPUPol CPUPolicy; typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::O3CPU O3CPU; - typedef typename Impl::Params Params; typedef O3ThreadState Thread; @@ -256,7 +257,7 @@ class FullO3CPU : public BaseO3CPU public: /** Constructs a CPU with the given parameters. */ - FullO3CPU(O3CPU *o3_cpu, Params *params); + FullO3CPU(O3CPU *o3_cpu, DerivO3CPUParams *params); /** Destructor. */ ~FullO3CPU(); diff --git a/src/cpu/o3/decode.hh b/src/cpu/o3/decode.hh index 3e82033ca..dc8063f29 100644 --- a/src/cpu/o3/decode.hh +++ b/src/cpu/o3/decode.hh @@ -36,6 +36,8 @@ #include "base/statistics.hh" #include "base/timebuf.hh" +class DerivO3CPUParams; + /** * DefaultDecode class handles both single threaded and SMT * decode. Its width is specified by the parameters; each cycles it @@ -50,7 +52,6 @@ class DefaultDecode // Typedefs from the Impl. typedef typename Impl::O3CPU O3CPU; typedef typename Impl::DynInstPtr DynInstPtr; - typedef typename Impl::Params Params; typedef typename Impl::CPUPol CPUPol; // Typedefs from the CPU policy. @@ -86,7 +87,7 @@ class DefaultDecode public: /** DefaultDecode constructor. */ - DefaultDecode(O3CPU *_cpu, Params *params); + DefaultDecode(O3CPU *_cpu, DerivO3CPUParams *params); /** Returns the name of decode. */ std::string name() const; diff --git a/src/cpu/o3/decode_impl.hh b/src/cpu/o3/decode_impl.hh index ce6738456..015bc8d7f 100644 --- a/src/cpu/o3/decode_impl.hh +++ b/src/cpu/o3/decode_impl.hh @@ -30,15 +30,17 @@ #include "cpu/o3/decode.hh" +#include "params/DerivO3CPU.hh" + template -DefaultDecode::DefaultDecode(O3CPU *_cpu, Params *params) +DefaultDecode::DefaultDecode(O3CPU *_cpu, DerivO3CPUParams *params) : cpu(_cpu), renameToDecodeDelay(params->renameToDecodeDelay), iewToDecodeDelay(params->iewToDecodeDelay), commitToDecodeDelay(params->commitToDecodeDelay), fetchToDecodeDelay(params->fetchToDecodeDelay), decodeWidth(params->decodeWidth), - numThreads(params->numberOfThreads) + numThreads(params->numThreads) { _status = Inactive; diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index d954bd1e7..f12228ff9 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -41,6 +41,8 @@ #include "mem/port.hh" #include "sim/eventq.hh" +class DerivO3CPUParams; + /** * DefaultFetch class handles both single threaded and SMT fetch. Its * width is specified by the parameters; each cycle it tries to fetch @@ -58,7 +60,6 @@ class DefaultFetch typedef typename Impl::DynInst DynInst; typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::O3CPU O3CPU; - typedef typename Impl::Params Params; /** Typedefs from the CPU policy. */ typedef typename CPUPol::BPredUnit BPredUnit; @@ -160,7 +161,7 @@ class DefaultFetch public: /** DefaultFetch constructor. */ - DefaultFetch(O3CPU *_cpu, Params *params); + DefaultFetch(O3CPU *_cpu, DerivO3CPUParams *params); /** Returns the name of fetch. */ std::string name() const; diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 7d344fa33..0b5ce9380 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -51,6 +51,8 @@ #include "sim/system.hh" #endif // FULL_SYSTEM +#include "params/DerivO3CPU.hh" + template void DefaultFetch::IcachePort::setPeer(Port *port) @@ -111,7 +113,7 @@ DefaultFetch::IcachePort::recvRetry() } template -DefaultFetch::DefaultFetch(O3CPU *_cpu, Params *params) +DefaultFetch::DefaultFetch(O3CPU *_cpu, DerivO3CPUParams *params) : cpu(_cpu), branchPred(params), predecoder(NULL), @@ -123,7 +125,7 @@ DefaultFetch::DefaultFetch(O3CPU *_cpu, Params *params) cacheBlocked(false), retryPkt(NULL), retryTid(-1), - numThreads(params->numberOfThreads), + numThreads(params->numThreads), numFetchingThreads(params->smtNumFetchingThreads), interruptPending(false), drainPending(false), diff --git a/src/cpu/o3/iew.hh b/src/cpu/o3/iew.hh index 457e2a024..3caf847ed 100644 --- a/src/cpu/o3/iew.hh +++ b/src/cpu/o3/iew.hh @@ -41,6 +41,7 @@ #include "cpu/o3/scoreboard.hh" #include "cpu/o3/lsq.hh" +class DerivO3CPUParams; class FUPool; /** @@ -70,7 +71,6 @@ class DefaultIEW typedef typename Impl::CPUPol CPUPol; typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::O3CPU O3CPU; - typedef typename Impl::Params Params; typedef typename CPUPol::IQ IQ; typedef typename CPUPol::RenameMap RenameMap; @@ -115,7 +115,7 @@ class DefaultIEW public: /** Constructs a DefaultIEW with the given parameters. */ - DefaultIEW(O3CPU *_cpu, Params *params); + DefaultIEW(O3CPU *_cpu, DerivO3CPUParams *params); /** Returns the name of the DefaultIEW stage. */ std::string name() const; diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh index 84d10e966..1daecd669 100644 --- a/src/cpu/o3/iew_impl.hh +++ b/src/cpu/o3/iew_impl.hh @@ -37,9 +37,10 @@ #include "base/timebuf.hh" #include "cpu/o3/fu_pool.hh" #include "cpu/o3/iew.hh" +#include "params/DerivO3CPU.hh" template -DefaultIEW::DefaultIEW(O3CPU *_cpu, Params *params) +DefaultIEW::DefaultIEW(O3CPU *_cpu, DerivO3CPUParams *params) : issueToExecQueue(params->backComSize, params->forwardComSize), cpu(_cpu), instQueue(_cpu, this, params), @@ -52,7 +53,7 @@ DefaultIEW::DefaultIEW(O3CPU *_cpu, Params *params) issueWidth(params->issueWidth), wbOutstanding(0), wbWidth(params->wbWidth), - numThreads(params->numberOfThreads), + numThreads(params->numThreads), switchedOut(false) { _status = Active; diff --git a/src/cpu/o3/inst_queue.hh b/src/cpu/o3/inst_queue.hh index d0f503977..43da1565d 100644 --- a/src/cpu/o3/inst_queue.hh +++ b/src/cpu/o3/inst_queue.hh @@ -41,8 +41,10 @@ #include "cpu/inst_seq.hh" #include "cpu/o3/dep_graph.hh" #include "cpu/op_class.hh" +#include "sim/eventq.hh" #include "sim/host.hh" +class DerivO3CPUParams; class FUPool; class MemInterface; @@ -70,7 +72,6 @@ class InstructionQueue //Typedefs from the Impl. typedef typename Impl::O3CPU O3CPU; typedef typename Impl::DynInstPtr DynInstPtr; - typedef typename Impl::Params Params; typedef typename Impl::CPUPol::IEW IEW; typedef typename Impl::CPUPol::MemDepUnit MemDepUnit; @@ -110,7 +111,7 @@ class InstructionQueue }; /** Constructs an IQ. */ - InstructionQueue(O3CPU *cpu_ptr, IEW *iew_ptr, Params *params); + InstructionQueue(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params); /** Destructs the IQ. */ ~InstructionQueue(); diff --git a/src/cpu/o3/inst_queue_impl.hh b/src/cpu/o3/inst_queue_impl.hh index fb06f20df..f3ce770fa 100644 --- a/src/cpu/o3/inst_queue_impl.hh +++ b/src/cpu/o3/inst_queue_impl.hh @@ -37,6 +37,8 @@ #include "enums/OpClass.hh" #include "sim/core.hh" +#include "params/DerivO3CPU.hh" + template InstructionQueue::FUCompletion::FUCompletion(DynInstPtr &_inst, int fu_idx, @@ -65,7 +67,7 @@ InstructionQueue::FUCompletion::description() const template InstructionQueue::InstructionQueue(O3CPU *cpu_ptr, IEW *iew_ptr, - Params *params) + DerivO3CPUParams *params) : cpu(cpu_ptr), iewStage(iew_ptr), fuPool(params->fuPool), @@ -79,7 +81,7 @@ InstructionQueue::InstructionQueue(O3CPU *cpu_ptr, IEW *iew_ptr, switchedOut = false; - numThreads = params->numberOfThreads; + numThreads = params->numThreads; // Set the number of physical registers as the number of int + float numPhysRegs = numPhysIntRegs + numPhysFloatRegs; diff --git a/src/cpu/o3/isa_specific.hh b/src/cpu/o3/isa_specific.hh index 72a8d4021..9e74f4c8c 100755 --- a/src/cpu/o3/isa_specific.hh +++ b/src/cpu/o3/isa_specific.hh @@ -33,17 +33,14 @@ #if THE_ISA == ALPHA_ISA #include "cpu/o3/alpha/cpu.hh" #include "cpu/o3/alpha/impl.hh" - #include "cpu/o3/alpha/params.hh" #include "cpu/o3/alpha/dyn_inst.hh" #elif THE_ISA == MIPS_ISA #include "cpu/o3/mips/cpu.hh" #include "cpu/o3/mips/impl.hh" - #include "cpu/o3/mips/params.hh" #include "cpu/o3/mips/dyn_inst.hh" #elif THE_ISA == SPARC_ISA #include "cpu/o3/sparc/cpu.hh" #include "cpu/o3/sparc/impl.hh" - #include "cpu/o3/sparc/params.hh" #include "cpu/o3/sparc/dyn_inst.hh" #else #error "ISA-specific header files O3CPU not defined ISA" diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh index 06de608e0..44b69ab40 100644 --- a/src/cpu/o3/lsq.hh +++ b/src/cpu/o3/lsq.hh @@ -40,10 +40,11 @@ #include "mem/port.hh" #include "sim/sim_object.hh" +class DerivO3CPUParams; + template class LSQ { public: - typedef typename Impl::Params Params; typedef typename Impl::O3CPU O3CPU; typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::CPUPol::IEW IEW; @@ -57,7 +58,7 @@ class LSQ { }; /** Constructs an LSQ with the given parameters. */ - LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, Params *params); + LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params); /** Returns the name of the LSQ. */ std::string name() const; diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh index 8ed6f7f54..f8e77b64e 100644 --- a/src/cpu/o3/lsq_impl.hh +++ b/src/cpu/o3/lsq_impl.hh @@ -34,6 +34,8 @@ #include "cpu/o3/lsq.hh" +#include "params/DerivO3CPU.hh" + template void LSQ::DcachePort::setPeer(Port *port) @@ -111,11 +113,11 @@ LSQ::DcachePort::recvRetry() } template -LSQ::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, Params *params) +LSQ::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params) : cpu(cpu_ptr), iewStage(iew_ptr), dcachePort(this), LQEntries(params->LQEntries), SQEntries(params->SQEntries), - numThreads(params->numberOfThreads), + numThreads(params->numThreads), retryTid(-1) { dcachePort.snoopRangeSent = false; diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh index 3ae69723d..a82ba3ad5 100644 --- a/src/cpu/o3/lsq_unit.hh +++ b/src/cpu/o3/lsq_unit.hh @@ -46,6 +46,8 @@ #include "mem/packet.hh" #include "mem/port.hh" +class DerivO3CPUParams; + /** * Class that implements the actual LQ and SQ for each specific * thread. Both are circular queues; load entries are freed upon @@ -63,7 +65,6 @@ class LSQUnit { protected: typedef TheISA::IntReg IntReg; public: - typedef typename Impl::Params Params; typedef typename Impl::O3CPU O3CPU; typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::CPUPol::IEW IEW; @@ -75,8 +76,9 @@ class LSQUnit { LSQUnit(); /** Initializes the LSQ unit with the specified number of entries. */ - void init(O3CPU *cpu_ptr, IEW *iew_ptr, Params *params, LSQ *lsq_ptr, - unsigned maxLQEntries, unsigned maxSQEntries, unsigned id); + void init(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params, + LSQ *lsq_ptr, unsigned maxLQEntries, unsigned maxSQEntries, + unsigned id); /** Returns the name of the LSQ unit. */ std::string name() const; diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh index e6ff5e931..4b8d693a6 100644 --- a/src/cpu/o3/lsq_unit_impl.hh +++ b/src/cpu/o3/lsq_unit_impl.hh @@ -112,8 +112,9 @@ LSQUnit::LSQUnit() template void -LSQUnit::init(O3CPU *cpu_ptr, IEW *iew_ptr, Params *params, LSQ *lsq_ptr, - unsigned maxLQEntries, unsigned maxSQEntries, unsigned id) +LSQUnit::init(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params, + LSQ *lsq_ptr, unsigned maxLQEntries, unsigned maxSQEntries, + unsigned id) { cpu = cpu_ptr; iewStage = iew_ptr; diff --git a/src/cpu/o3/mem_dep_unit.hh b/src/cpu/o3/mem_dep_unit.hh index a12a3001b..4f66b4599 100644 --- a/src/cpu/o3/mem_dep_unit.hh +++ b/src/cpu/o3/mem_dep_unit.hh @@ -48,6 +48,8 @@ struct SNHash { } }; +class DerivO3CPUParams; + template class InstructionQueue; @@ -65,14 +67,13 @@ class InstructionQueue; template class MemDepUnit { public: - typedef typename Impl::Params Params; typedef typename Impl::DynInstPtr DynInstPtr; /** Empty constructor. Must call init() prior to using in this case. */ MemDepUnit(); /** Constructs a MemDepUnit with given parameters. */ - MemDepUnit(Params *params); + MemDepUnit(DerivO3CPUParams *params); /** Frees up any memory allocated. */ ~MemDepUnit(); @@ -81,7 +82,7 @@ class MemDepUnit { std::string name() const; /** Initializes the unit with parameters and a thread id. */ - void init(Params *params, int tid); + void init(DerivO3CPUParams *params, int tid); /** Registers statistics. */ void regStats(); diff --git a/src/cpu/o3/mem_dep_unit_impl.hh b/src/cpu/o3/mem_dep_unit_impl.hh index 64558efaa..124c087f8 100644 --- a/src/cpu/o3/mem_dep_unit_impl.hh +++ b/src/cpu/o3/mem_dep_unit_impl.hh @@ -33,6 +33,8 @@ #include "cpu/o3/inst_queue.hh" #include "cpu/o3/mem_dep_unit.hh" +#include "params/DerivO3CPU.hh" + template MemDepUnit::MemDepUnit() : loadBarrier(false), loadBarrierSN(0), storeBarrier(false), @@ -41,7 +43,7 @@ MemDepUnit::MemDepUnit() } template -MemDepUnit::MemDepUnit(Params *params) +MemDepUnit::MemDepUnit(DerivO3CPUParams *params) : depPred(params->SSITSize, params->LFSTSize), loadBarrier(false), loadBarrierSN(0), storeBarrier(false), storeBarrierSN(0), iqPtr(NULL) { @@ -82,7 +84,7 @@ MemDepUnit::name() const template void -MemDepUnit::init(Params *params, int tid) +MemDepUnit::init(DerivO3CPUParams *params, int tid) { DPRINTF(MemDepUnit, "Creating MemDepUnit %i object.\n",tid); diff --git a/src/cpu/o3/mips/cpu.hh b/src/cpu/o3/mips/cpu.hh index 3724ced46..38eba5aeb 100755 --- a/src/cpu/o3/mips/cpu.hh +++ b/src/cpu/o3/mips/cpu.hh @@ -39,6 +39,7 @@ #include "sim/byteswap.hh" #include "sim/faults.hh" +class DerivO3CPUParams; class EndQuiesceEvent; namespace Kernel { class Statistics; @@ -60,10 +61,9 @@ class MipsO3CPU : public FullO3CPU public: typedef O3ThreadState ImplState; typedef O3ThreadState Thread; - typedef typename Impl::Params Params; /** Constructs an MipsO3CPU with the given parameters. */ - MipsO3CPU(Params *params); + MipsO3CPU(DerivO3CPUParams *params); /** Registers statistics. */ void regStats(); diff --git a/src/cpu/o3/mips/cpu_builder.cc b/src/cpu/o3/mips/cpu_builder.cc index 4690b9804..8fe34afab 100644 --- a/src/cpu/o3/mips/cpu_builder.cc +++ b/src/cpu/o3/mips/cpu_builder.cc @@ -35,14 +35,13 @@ #include "cpu/base.hh" #include "cpu/o3/mips/cpu.hh" #include "cpu/o3/mips/impl.hh" -#include "cpu/o3/mips/params.hh" #include "cpu/o3/fu_pool.hh" #include "params/DerivO3CPU.hh" class DerivO3CPU : public MipsO3CPU { public: - DerivO3CPU(MipsSimpleParams *p) + DerivO3CPU(DerivO3CPUParams *p) : MipsO3CPU(p) { } }; @@ -50,8 +49,10 @@ class DerivO3CPU : public MipsO3CPU DerivO3CPU * DerivO3CPUParams::create() { - DerivO3CPU *cpu; - +#if FULL_SYSTEM + // Full-system only supports a single thread for the moment. + int actual_num_threads = 1; +#else // In non-full-system mode, we infer the number of threads from // the workload if it's not explicitly specified. int actual_num_threads = @@ -60,123 +61,20 @@ DerivO3CPUParams::create() if (workload.size() == 0) { fatal("Must specify at least one workload!"); } - - MipsSimpleParams *params = new MipsSimpleParams; - - params->clock = clock; - params->phase = phase; - - params->tracer = tracer; - - params->name = name; - params->numberOfThreads = actual_num_threads; - params->cpu_id = cpu_id; - params->activity = activity; - - params->workload = workload; - -#if USE_CHECKER - params->checker = checker; #endif - params->max_insts_any_thread = max_insts_any_thread; - params->max_insts_all_threads = max_insts_all_threads; - params->max_loads_any_thread = max_loads_any_thread; - params->max_loads_all_threads = max_loads_all_threads; - - // - // Caches - // - params->cachePorts = cachePorts; - - params->decodeToFetchDelay = decodeToFetchDelay; - params->renameToFetchDelay = renameToFetchDelay; - params->iewToFetchDelay = iewToFetchDelay; - params->commitToFetchDelay = commitToFetchDelay; - params->fetchWidth = fetchWidth; - - params->renameToDecodeDelay = renameToDecodeDelay; - params->iewToDecodeDelay = iewToDecodeDelay; - params->commitToDecodeDelay = commitToDecodeDelay; - params->fetchToDecodeDelay = fetchToDecodeDelay; - params->decodeWidth = decodeWidth; - - params->iewToRenameDelay = iewToRenameDelay; - params->commitToRenameDelay = commitToRenameDelay; - params->decodeToRenameDelay = decodeToRenameDelay; - params->renameWidth = renameWidth; - - params->commitToIEWDelay = commitToIEWDelay; - params->renameToIEWDelay = renameToIEWDelay; - params->issueToExecuteDelay = issueToExecuteDelay; - params->dispatchWidth = dispatchWidth; - params->issueWidth = issueWidth; - params->wbWidth = wbWidth; - params->wbDepth = wbDepth; - params->fuPool = fuPool; - - params->iewToCommitDelay = iewToCommitDelay; - params->renameToROBDelay = renameToROBDelay; - params->commitWidth = commitWidth; - params->squashWidth = squashWidth; - params->trapLatency = trapLatency; - - params->backComSize = backComSize; - params->forwardComSize = forwardComSize; - - params->predType = predType; - params->localPredictorSize = localPredictorSize; - params->localCtrBits = localCtrBits; - params->localHistoryTableSize = localHistoryTableSize; - params->localHistoryBits = localHistoryBits; - params->globalPredictorSize = globalPredictorSize; - params->globalCtrBits = globalCtrBits; - params->globalHistoryBits = globalHistoryBits; - params->choicePredictorSize = choicePredictorSize; - params->choiceCtrBits = choiceCtrBits; - - params->BTBEntries = BTBEntries; - params->BTBTagSize = BTBTagSize; - - params->RASSize = RASSize; - - params->LQEntries = LQEntries; - params->SQEntries = SQEntries; - - params->SSITSize = SSITSize; - params->LFSTSize = LFSTSize; - - params->numPhysIntRegs = numPhysIntRegs; - params->numPhysFloatRegs = numPhysFloatRegs; - params->numIQEntries = numIQEntries; - params->numROBEntries = numROBEntries; - - params->smtNumFetchingThreads = smtNumFetchingThreads; + numThreads = actual_num_threads; // Default smtFetchPolicy to "RoundRobin", if necessary. std::string round_robin_policy = "RoundRobin"; std::string single_thread = "SingleThread"; if (actual_num_threads > 1 && single_thread.compare(smtFetchPolicy) == 0) - params->smtFetchPolicy = round_robin_policy; + smtFetchPolicy = round_robin_policy; else - params->smtFetchPolicy = smtFetchPolicy; - - params->smtIQPolicy = smtIQPolicy; - params->smtLSQPolicy = smtLSQPolicy; - params->smtLSQThreshold = smtLSQThreshold; - params->smtROBPolicy = smtROBPolicy; - params->smtROBThreshold = smtROBThreshold; - params->smtCommitPolicy = smtCommitPolicy; - - params->instShiftAmt = 2; - - params->deferRegistration = defer_registration; - - params->functionTrace = function_trace; - params->functionTraceStart = function_trace_start; + smtFetchPolicy = smtFetchPolicy; - cpu = new DerivO3CPU(params); + instShiftAmt = 2; - return cpu; + return new DerivO3CPU(this); } diff --git a/src/cpu/o3/mips/cpu_impl.hh b/src/cpu/o3/mips/cpu_impl.hh index 09d73b4a2..70dbb4ac4 100644 --- a/src/cpu/o3/mips/cpu_impl.hh +++ b/src/cpu/o3/mips/cpu_impl.hh @@ -40,13 +40,14 @@ #include "sim/stats.hh" #include "cpu/o3/mips/cpu.hh" -#include "cpu/o3/mips/params.hh" #include "cpu/o3/mips/thread_context.hh" #include "cpu/o3/comm.hh" #include "cpu/o3/thread_state.hh" +#include "params/DerivO3CPU.hh" + template -MipsO3CPU::MipsO3CPU(Params *params) +MipsO3CPU::MipsO3CPU(DerivO3CPUParams *params) : FullO3CPU(this, params) { DPRINTF(O3CPU, "Creating MipsO3CPU object.\n"); diff --git a/src/cpu/o3/mips/impl.hh b/src/cpu/o3/mips/impl.hh index ac7181a19..481184006 100644 --- a/src/cpu/o3/mips/impl.hh +++ b/src/cpu/o3/mips/impl.hh @@ -34,7 +34,6 @@ #include "arch/mips/isa_traits.hh" -#include "cpu/o3/mips/params.hh" #include "cpu/o3/cpu_policy.hh" @@ -78,9 +77,6 @@ struct MipsSimpleImpl */ typedef O3CPU CPUType; - /** The Params to be passed to each stage. */ - typedef MipsSimpleParams Params; - enum { MaxWidth = 8, MaxThreads = 4 diff --git a/src/cpu/o3/mips/params.hh b/src/cpu/o3/mips/params.hh deleted file mode 100644 index 2688d3fb3..000000000 --- a/src/cpu/o3/mips/params.hh +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - * Korey Sewell - */ - -#ifndef __CPU_O3_MIPS_PARAMS_HH__ -#define __CPU_O3_MIPS_PARAMS_HH__ - -#include "cpu/o3/cpu.hh" -#include "cpu/o3/params.hh" - -//Forward declarations -namespace MipsISA -{ - class MipsDTB; - class MipsITB; -} -class MemObject; -class Process; -class System; - -/** - * This file defines the parameters that will be used for the MipsO3CPU. - * This must be defined externally so that the Impl can have a params class - * defined that it can pass to all of the individual stages. - */ - -class MipsSimpleParams : public O3Params -{ - public: - MipsSimpleParams() {} - - //Full System Paramater Objects place here - MipsISA::ITB *itb; - MipsISA::DTB *dtb; -}; - -#endif // __CPU_O3_MIPS_PARAMS_HH__ diff --git a/src/cpu/o3/params.hh b/src/cpu/o3/params.hh deleted file mode 100755 index b487778c6..000000000 --- a/src/cpu/o3/params.hh +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2004-2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - */ - -#ifndef __CPU_O3_PARAMS_HH__ -#define __CPU_O3_PARAMS_HH__ - -#include "cpu/o3/cpu.hh" - -//Forward declarations -class FUPool; - -/** - * This file defines the parameters that will be used for the O3CPU. - * This must be defined externally so that the Impl can have a params class - * defined that it can pass to all of the individual stages. - */ -class O3Params : public BaseO3CPU::Params -{ - public: - unsigned activity; - - // - // Pointers to key objects - // -#if !FULL_SYSTEM - std::vector workload; - Process *process; -#endif // FULL_SYSTEM - - BaseCPU *checker; - - // - // Caches - // - // MemInterface *icacheInterface; - // MemInterface *dcacheInterface; - - unsigned cachePorts; - - // - // Fetch - // - unsigned decodeToFetchDelay; - unsigned renameToFetchDelay; - unsigned iewToFetchDelay; - unsigned commitToFetchDelay; - unsigned fetchWidth; - - // - // Decode - // - unsigned renameToDecodeDelay; - unsigned iewToDecodeDelay; - unsigned commitToDecodeDelay; - unsigned fetchToDecodeDelay; - unsigned decodeWidth; - - // - // Rename - // - unsigned iewToRenameDelay; - unsigned commitToRenameDelay; - unsigned decodeToRenameDelay; - unsigned renameWidth; - - // - // IEW - // - unsigned commitToIEWDelay; - unsigned renameToIEWDelay; - unsigned issueToExecuteDelay; - unsigned dispatchWidth; - unsigned issueWidth; - unsigned wbWidth; - unsigned wbDepth; - FUPool *fuPool; - - // - // Commit - // - unsigned iewToCommitDelay; - unsigned renameToROBDelay; - unsigned commitWidth; - unsigned squashWidth; - Tick trapLatency; - Tick fetchTrapLatency; - - // - // Timebuffer sizes - // - unsigned backComSize; - unsigned forwardComSize; - - // - // Branch predictor (BP, BTB, RAS) - // - std::string predType; - unsigned localPredictorSize; - unsigned localCtrBits; - unsigned localHistoryTableSize; - unsigned localHistoryBits; - unsigned globalPredictorSize; - unsigned globalCtrBits; - unsigned globalHistoryBits; - unsigned choicePredictorSize; - unsigned choiceCtrBits; - - unsigned BTBEntries; - unsigned BTBTagSize; - - unsigned RASSize; - - // - // Load store queue - // - unsigned LQEntries; - unsigned SQEntries; - - // - // Memory dependence - // - unsigned SSITSize; - unsigned LFSTSize; - - // - // Miscellaneous - // - unsigned numPhysIntRegs; - unsigned numPhysFloatRegs; - unsigned numIQEntries; - unsigned numROBEntries; - - //SMT Parameters - unsigned smtNumFetchingThreads; - - std::string smtFetchPolicy; - - std::string smtIQPolicy; - unsigned smtIQThreshold; - - std::string smtLSQPolicy; - unsigned smtLSQThreshold; - - std::string smtCommitPolicy; - - std::string smtROBPolicy; - unsigned smtROBThreshold; - - // Probably can get this from somewhere. - unsigned instShiftAmt; -}; - -#endif // __CPU_O3_ALPHA_PARAMS_HH__ diff --git a/src/cpu/o3/regfile.hh b/src/cpu/o3/regfile.hh index 75d3fa6eb..8bd867136 100644 --- a/src/cpu/o3/regfile.hh +++ b/src/cpu/o3/regfile.hh @@ -33,6 +33,7 @@ #define __CPU_O3_REGFILE_HH__ #include "arch/isa_traits.hh" +#include "arch/regfile.hh" #include "arch/types.hh" #include "base/trace.hh" #include "config/full_system.hh" diff --git a/src/cpu/o3/rename.hh b/src/cpu/o3/rename.hh index b2faffe43..c9e0d418d 100644 --- a/src/cpu/o3/rename.hh +++ b/src/cpu/o3/rename.hh @@ -36,6 +36,8 @@ #include "base/statistics.hh" #include "base/timebuf.hh" +class DerivO3CPUParams; + /** * DefaultRename handles both single threaded and SMT rename. Its * width is specified by the parameters; each cycle it tries to rename @@ -56,7 +58,6 @@ class DefaultRename typedef typename Impl::CPUPol CPUPol; typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::O3CPU O3CPU; - typedef typename Impl::Params Params; // Typedefs from the CPUPol typedef typename CPUPol::DecodeStruct DecodeStruct; @@ -107,7 +108,7 @@ class DefaultRename public: /** DefaultRename constructor. */ - DefaultRename(O3CPU *_cpu, Params *params); + DefaultRename(O3CPU *_cpu, DerivO3CPUParams *params); /** Returns the name of rename. */ std::string name() const; diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh index 49c885753..81647b133 100644 --- a/src/cpu/o3/rename_impl.hh +++ b/src/cpu/o3/rename_impl.hh @@ -35,9 +35,10 @@ #include "arch/regfile.hh" #include "config/full_system.hh" #include "cpu/o3/rename.hh" +#include "params/DerivO3CPU.hh" template -DefaultRename::DefaultRename(O3CPU *_cpu, Params *params) +DefaultRename::DefaultRename(O3CPU *_cpu, DerivO3CPUParams *params) : cpu(_cpu), iewToRenameDelay(params->iewToRenameDelay), decodeToRenameDelay(params->decodeToRenameDelay), @@ -46,7 +47,7 @@ DefaultRename::DefaultRename(O3CPU *_cpu, Params *params) commitWidth(params->commitWidth), resumeSerialize(false), resumeUnblocking(false), - numThreads(params->numberOfThreads), + numThreads(params->numThreads), maxPhysicalRegs(params->numPhysIntRegs + params->numPhysFloatRegs) { _status = Inactive; diff --git a/src/cpu/o3/sparc/cpu.hh b/src/cpu/o3/sparc/cpu.hh index 3fd193e0f..cccfd7d52 100644 --- a/src/cpu/o3/sparc/cpu.hh +++ b/src/cpu/o3/sparc/cpu.hh @@ -37,6 +37,7 @@ #include "cpu/o3/cpu.hh" #include "sim/byteswap.hh" +class DerivO3CPUParams; class EndQuiesceEvent; namespace Kernel { class Statistics; @@ -58,10 +59,9 @@ class SparcO3CPU : public FullO3CPU public: typedef O3ThreadState ImplState; typedef O3ThreadState Thread; - typedef typename Impl::Params Params; /** Constructs an AlphaO3CPU with the given parameters. */ - SparcO3CPU(Params *params); + SparcO3CPU(DerivO3CPUParams *params); /** Registers statistics. */ void regStats(); diff --git a/src/cpu/o3/sparc/cpu_builder.cc b/src/cpu/o3/sparc/cpu_builder.cc index b08845b4e..c5ea31210 100644 --- a/src/cpu/o3/sparc/cpu_builder.cc +++ b/src/cpu/o3/sparc/cpu_builder.cc @@ -35,14 +35,13 @@ #include "cpu/base.hh" #include "cpu/o3/sparc/cpu.hh" #include "cpu/o3/sparc/impl.hh" -#include "cpu/o3/sparc/params.hh" #include "cpu/o3/fu_pool.hh" #include "params/DerivO3CPU.hh" class DerivO3CPU : public SparcO3CPU { public: - DerivO3CPU(SparcSimpleParams *p) + DerivO3CPU(DerivO3CPUParams *p) : SparcO3CPU(p) { } }; @@ -50,8 +49,6 @@ class DerivO3CPU : public SparcO3CPU DerivO3CPU * DerivO3CPUParams::create() { - DerivO3CPU *cpu; - #if FULL_SYSTEM // Full-system only supports a single thread for the moment. int actual_num_threads = 1; @@ -66,135 +63,18 @@ DerivO3CPUParams::create() } #endif - SparcSimpleParams *params = new SparcSimpleParams; - - params->clock = clock; - params->phase = phase; - - params->tracer = tracer; - - params->name = name; - params->numberOfThreads = actual_num_threads; - params->cpu_id = cpu_id; - params->activity = activity; - - params->itb = itb; - params->dtb = dtb; - - params->system = system; -#if FULL_SYSTEM - params->profile = profile; - - params->do_quiesce = do_quiesce; - params->do_checkpoint_insts = do_checkpoint_insts; - params->do_statistics_insts = do_statistics_insts; -#else - params->workload = workload; -#endif // FULL_SYSTEM - -#if USE_CHECKER - params->checker = checker; -#endif - - params->max_insts_any_thread = max_insts_any_thread; - params->max_insts_all_threads = max_insts_all_threads; - params->max_loads_any_thread = max_loads_any_thread; - params->max_loads_all_threads = max_loads_all_threads; - params->progress_interval = progress_interval; - - // - // Caches - // - params->cachePorts = cachePorts; - - params->decodeToFetchDelay = decodeToFetchDelay; - params->renameToFetchDelay = renameToFetchDelay; - params->iewToFetchDelay = iewToFetchDelay; - params->commitToFetchDelay = commitToFetchDelay; - params->fetchWidth = fetchWidth; - - params->renameToDecodeDelay = renameToDecodeDelay; - params->iewToDecodeDelay = iewToDecodeDelay; - params->commitToDecodeDelay = commitToDecodeDelay; - params->fetchToDecodeDelay = fetchToDecodeDelay; - params->decodeWidth = decodeWidth; - - params->iewToRenameDelay = iewToRenameDelay; - params->commitToRenameDelay = commitToRenameDelay; - params->decodeToRenameDelay = decodeToRenameDelay; - params->renameWidth = renameWidth; - - params->commitToIEWDelay = commitToIEWDelay; - params->renameToIEWDelay = renameToIEWDelay; - params->issueToExecuteDelay = issueToExecuteDelay; - params->dispatchWidth = dispatchWidth; - params->issueWidth = issueWidth; - params->wbWidth = wbWidth; - params->wbDepth = wbDepth; - params->fuPool = fuPool; - - params->iewToCommitDelay = iewToCommitDelay; - params->renameToROBDelay = renameToROBDelay; - params->commitWidth = commitWidth; - params->squashWidth = squashWidth; - params->trapLatency = trapLatency; - - params->backComSize = backComSize; - params->forwardComSize = forwardComSize; - - params->predType = predType; - params->localPredictorSize = localPredictorSize; - params->localCtrBits = localCtrBits; - params->localHistoryTableSize = localHistoryTableSize; - params->localHistoryBits = localHistoryBits; - params->globalPredictorSize = globalPredictorSize; - params->globalCtrBits = globalCtrBits; - params->globalHistoryBits = globalHistoryBits; - params->choicePredictorSize = choicePredictorSize; - params->choiceCtrBits = choiceCtrBits; - - params->BTBEntries = BTBEntries; - params->BTBTagSize = BTBTagSize; - - params->RASSize = RASSize; - - params->LQEntries = LQEntries; - params->SQEntries = SQEntries; - - params->SSITSize = SSITSize; - params->LFSTSize = LFSTSize; - - params->numPhysIntRegs = numPhysIntRegs; - params->numPhysFloatRegs = numPhysFloatRegs; - params->numIQEntries = numIQEntries; - params->numROBEntries = numROBEntries; - - params->smtNumFetchingThreads = smtNumFetchingThreads; + numThreads = actual_num_threads; // Default smtFetchPolicy to "RoundRobin", if necessary. std::string round_robin_policy = "RoundRobin"; std::string single_thread = "SingleThread"; if (actual_num_threads > 1 && single_thread.compare(smtFetchPolicy) == 0) - params->smtFetchPolicy = round_robin_policy; + smtFetchPolicy = round_robin_policy; else - params->smtFetchPolicy = smtFetchPolicy; - - params->smtIQPolicy = smtIQPolicy; - params->smtLSQPolicy = smtLSQPolicy; - params->smtLSQThreshold = smtLSQThreshold; - params->smtROBPolicy = smtROBPolicy; - params->smtROBThreshold = smtROBThreshold; - params->smtCommitPolicy = smtCommitPolicy; - - params->instShiftAmt = 2; - - params->deferRegistration = defer_registration; - - params->functionTrace = function_trace; - params->functionTraceStart = function_trace_start; + smtFetchPolicy = smtFetchPolicy; - cpu = new DerivO3CPU(params); + instShiftAmt = 2; - return cpu; + return new DerivO3CPU(this); } diff --git a/src/cpu/o3/sparc/cpu_impl.hh b/src/cpu/o3/sparc/cpu_impl.hh index 068057fc0..2dd38845f 100644 --- a/src/cpu/o3/sparc/cpu_impl.hh +++ b/src/cpu/o3/sparc/cpu_impl.hh @@ -41,7 +41,6 @@ #include "sim/stats.hh" #include "cpu/o3/sparc/cpu.hh" -#include "cpu/o3/sparc/params.hh" #include "cpu/o3/sparc/thread_context.hh" #include "cpu/o3/comm.hh" #include "cpu/o3/thread_state.hh" @@ -54,8 +53,11 @@ #include "sim/system.hh" #endif +#include "params/DerivO3CPU.hh" + template -SparcO3CPU::SparcO3CPU(Params *params) : FullO3CPU(this, params) +SparcO3CPU::SparcO3CPU(DerivO3CPUParams *params) : + FullO3CPU(this, params) { DPRINTF(O3CPU, "Creating SparcO3CPU object.\n"); diff --git a/src/cpu/o3/sparc/impl.hh b/src/cpu/o3/sparc/impl.hh index 0a970c2f0..982fe36cc 100644 --- a/src/cpu/o3/sparc/impl.hh +++ b/src/cpu/o3/sparc/impl.hh @@ -33,7 +33,6 @@ #include "arch/sparc/isa_traits.hh" -#include "cpu/o3/sparc/params.hh" #include "cpu/o3/cpu_policy.hh" @@ -77,9 +76,6 @@ struct SparcSimpleImpl */ typedef O3CPU CPUType; - /** The Params to be passed to each stage. */ - typedef SparcSimpleParams Params; - enum { MaxWidth = 8, MaxThreads = 4 diff --git a/src/cpu/o3/sparc/params.hh b/src/cpu/o3/sparc/params.hh deleted file mode 100644 index 09f523818..000000000 --- a/src/cpu/o3/sparc/params.hh +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2004-2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#ifndef __CPU_O3_SPARC_PARAMS_HH__ -#define __CPU_O3_SPARC_PARAMS_HH__ - -#include "cpu/o3/cpu.hh" -#include "cpu/o3/params.hh" - -//Forward declarations -namespace SparcISA -{ - class DTB; - class ITB; -} -class MemObject; -class Process; -class System; - -/** - * This file defines the parameters that will be used for the AlphaO3CPU. - * This must be defined externally so that the Impl can have a params class - * defined that it can pass to all of the individual stages. - */ - -class SparcSimpleParams : public O3Params -{ - public: - - SparcISA::ITB *itb; - SparcISA::DTB *dtb; -}; - -#endif // __CPU_O3_SPARC_PARAMS_HH__ diff --git a/src/cpu/o3/thread_state.hh b/src/cpu/o3/thread_state.hh index d8720b3ab..8c634f67e 100644 --- a/src/cpu/o3/thread_state.hh +++ b/src/cpu/o3/thread_state.hh @@ -80,8 +80,8 @@ struct O3ThreadState : public ThreadState { : ThreadState(_cpu, -1, _thread_num), cpu(_cpu), inSyscall(0), trapPending(0) { - if (cpu->params->profile) { - profile = new FunctionProfile(cpu->params->system->kernelSymtab); + if (cpu->params()->profile) { + profile = new FunctionProfile(cpu->params()->system->kernelSymtab); Callback *cb = new MakeCallback(this); diff --git a/src/cpu/simple/AtomicSimpleCPU.py b/src/cpu/simple/AtomicSimpleCPU.py index a0b358439..e1c1e4cd1 100644 --- a/src/cpu/simple/AtomicSimpleCPU.py +++ b/src/cpu/simple/AtomicSimpleCPU.py @@ -28,9 +28,9 @@ from m5.params import * from m5 import build_env -from BaseCPU import BaseCPU +from BaseSimpleCPU import BaseSimpleCPU -class AtomicSimpleCPU(BaseCPU): +class AtomicSimpleCPU(BaseSimpleCPU): type = 'AtomicSimpleCPU' width = Param.Int(1, "CPU width") simulate_data_stalls = Param.Bool(False, "Simulate dcache stall cycles") @@ -42,5 +42,5 @@ class AtomicSimpleCPU(BaseCPU): icache_port = Port("Instruction Port") dcache_port = Port("Data Port") physmem_port = Port("Physical Memory Port") - _mem_ports = BaseCPU._mem_ports + \ + _mem_ports = BaseSimpleCPU._mem_ports + \ ['icache_port', 'dcache_port', 'physmem_port'] diff --git a/src/cpu/simple/BaseSimpleCPU.py b/src/cpu/simple/BaseSimpleCPU.py new file mode 100644 index 000000000..9f528bc20 --- /dev/null +++ b/src/cpu/simple/BaseSimpleCPU.py @@ -0,0 +1,34 @@ +# Copyright (c) 2008 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +from m5.params import * +from BaseCPU import BaseCPU + +class BaseSimpleCPU(BaseCPU): + type = 'BaseSimpleCPU' + abstract = True diff --git a/src/cpu/simple/SConscript b/src/cpu/simple/SConscript index c090a938c..76598666f 100644 --- a/src/cpu/simple/SConscript +++ b/src/cpu/simple/SConscript @@ -47,3 +47,4 @@ if 'AtomicSimpleCPU' in env['CPU_MODELS'] or \ if need_simple_base: Source('base.cc') + SimObject('BaseSimpleCPU.py') diff --git a/src/cpu/simple/TimingSimpleCPU.py b/src/cpu/simple/TimingSimpleCPU.py index 7e777e813..f2b14a175 100644 --- a/src/cpu/simple/TimingSimpleCPU.py +++ b/src/cpu/simple/TimingSimpleCPU.py @@ -28,9 +28,9 @@ from m5.params import * from m5 import build_env -from BaseCPU import BaseCPU +from BaseSimpleCPU import BaseSimpleCPU -class TimingSimpleCPU(BaseCPU): +class TimingSimpleCPU(BaseSimpleCPU): type = 'TimingSimpleCPU' function_trace = Param.Bool(False, "Enable function trace") function_trace_start = Param.Tick(0, "Cycle to start function trace") @@ -38,4 +38,4 @@ class TimingSimpleCPU(BaseCPU): profile = Param.Latency('0ns', "trace the kernel stack") icache_port = Port("Instruction Port") dcache_port = Port("Data Port") - _mem_ports = BaseCPU._mem_ports + ['icache_port', 'dcache_port'] + _mem_ports = BaseSimpleCPU._mem_ports + ['icache_port', 'dcache_port'] diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 0e04a36b2..7ed1ee0c3 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -152,7 +152,7 @@ AtomicSimpleCPU::DcachePort::setPeer(Port *port) #endif } -AtomicSimpleCPU::AtomicSimpleCPU(Params *p) +AtomicSimpleCPU::AtomicSimpleCPU(AtomicSimpleCPUParams *p) : BaseSimpleCPU(p), tickEvent(this), width(p->width), simulate_data_stalls(p->simulate_data_stalls), simulate_inst_stalls(p->simulate_inst_stalls), @@ -812,39 +812,10 @@ AtomicSimpleCPU::printAddr(Addr a) AtomicSimpleCPU * AtomicSimpleCPUParams::create() { - AtomicSimpleCPU::Params *params = new AtomicSimpleCPU::Params(); - params->name = name; - params->numberOfThreads = 1; - params->max_insts_any_thread = max_insts_any_thread; - params->max_insts_all_threads = max_insts_all_threads; - params->max_loads_any_thread = max_loads_any_thread; - params->max_loads_all_threads = max_loads_all_threads; - params->progress_interval = progress_interval; - params->deferRegistration = defer_registration; - params->phase = phase; - params->clock = clock; - params->functionTrace = function_trace; - params->functionTraceStart = function_trace_start; - params->width = width; - params->simulate_data_stalls = simulate_data_stalls; - params->simulate_inst_stalls = simulate_inst_stalls; - params->system = system; - params->cpu_id = cpu_id; - params->tracer = tracer; - - params->itb = itb; - params->dtb = dtb; -#if FULL_SYSTEM - params->profile = profile; - params->do_quiesce = do_quiesce; - params->do_checkpoint_insts = do_checkpoint_insts; - params->do_statistics_insts = do_statistics_insts; -#else + numThreads = 1; +#if !FULL_SYSTEM if (workload.size() != 1) panic("only one workload allowed"); - params->process = workload[0]; #endif - - AtomicSimpleCPU *cpu = new AtomicSimpleCPU(params); - return cpu; + return new AtomicSimpleCPU(this); } diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh index 008397533..24400df22 100644 --- a/src/cpu/simple/atomic.hh +++ b/src/cpu/simple/atomic.hh @@ -32,18 +32,13 @@ #define __CPU_SIMPLE_ATOMIC_HH__ #include "cpu/simple/base.hh" +#include "params/AtomicSimpleCPU.hh" class AtomicSimpleCPU : public BaseSimpleCPU { public: - struct Params : public BaseSimpleCPU::Params { - int width; - bool simulate_data_stalls; - bool simulate_inst_stalls; - }; - - AtomicSimpleCPU(Params *params); + AtomicSimpleCPU(AtomicSimpleCPUParams *params); virtual ~AtomicSimpleCPU(); virtual void init(); diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index 0c1162032..3fd699868 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -65,16 +65,18 @@ #include "mem/mem_object.hh" #endif // FULL_SYSTEM +#include "params/BaseSimpleCPU.hh" + using namespace std; using namespace TheISA; -BaseSimpleCPU::BaseSimpleCPU(Params *p) +BaseSimpleCPU::BaseSimpleCPU(BaseSimpleCPUParams *p) : BaseCPU(p), traceData(NULL), thread(NULL), predecoder(NULL) { #if FULL_SYSTEM thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb); #else - thread = new SimpleThread(this, /* thread_num */ 0, p->process, + thread = new SimpleThread(this, /* thread_num */ 0, p->workload[0], p->itb, p->dtb, /* asid */ 0); #endif // !FULL_SYSTEM diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index 62bb31de8..aeae1a3d8 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -76,6 +76,8 @@ namespace Trace { class InstRecord; } +class BaseSimpleCPUParams; + class BaseSimpleCPU : public BaseCPU { @@ -107,15 +109,7 @@ class BaseSimpleCPU : public BaseCPU }; public: - struct Params : public BaseCPU::Params - { - TheISA::ITB *itb; - TheISA::DTB *dtb; -#if !FULL_SYSTEM - Process *process; -#endif - }; - BaseSimpleCPU(Params *params); + BaseSimpleCPU(BaseSimpleCPUParams *params); virtual ~BaseSimpleCPU(); public: diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 4451dfe81..ac67341ff 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -104,7 +104,7 @@ TimingSimpleCPU::CpuPort::TickEvent::schedule(PacketPtr _pkt, Tick t) Event::schedule(t); } -TimingSimpleCPU::TimingSimpleCPU(Params *p) +TimingSimpleCPU::TimingSimpleCPU(TimingSimpleCPUParams *p) : BaseSimpleCPU(p), icachePort(this, p->clock), dcachePort(this, p->clock) { _status = Idle; @@ -852,36 +852,10 @@ TimingSimpleCPU::printAddr(Addr a) TimingSimpleCPU * TimingSimpleCPUParams::create() { - TimingSimpleCPU::Params *params = new TimingSimpleCPU::Params(); - params->name = name; - params->numberOfThreads = 1; - params->max_insts_any_thread = max_insts_any_thread; - params->max_insts_all_threads = max_insts_all_threads; - params->max_loads_any_thread = max_loads_any_thread; - params->max_loads_all_threads = max_loads_all_threads; - params->progress_interval = progress_interval; - params->deferRegistration = defer_registration; - params->clock = clock; - params->phase = phase; - params->functionTrace = function_trace; - params->functionTraceStart = function_trace_start; - params->system = system; - params->cpu_id = cpu_id; - params->tracer = tracer; - - params->itb = itb; - params->dtb = dtb; -#if FULL_SYSTEM - params->profile = profile; - params->do_quiesce = do_quiesce; - params->do_checkpoint_insts = do_checkpoint_insts; - params->do_statistics_insts = do_statistics_insts; -#else + numThreads = 1; +#if !FULL_SYSTEM if (workload.size() != 1) panic("only one workload allowed"); - params->process = workload[0]; #endif - - TimingSimpleCPU *cpu = new TimingSimpleCPU(params); - return cpu; + return new TimingSimpleCPU(this); } diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index a748d47b4..e405f6a41 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -33,14 +33,13 @@ #include "cpu/simple/base.hh" +#include "params/TimingSimpleCPU.hh" + class TimingSimpleCPU : public BaseSimpleCPU { public: - struct Params : public BaseSimpleCPU::Params { - }; - - TimingSimpleCPU(Params *params); + TimingSimpleCPU(TimingSimpleCPUParams * params); virtual ~TimingSimpleCPU(); virtual void init(); diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index 8d5c4eafb..ba3312a7a 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -37,9 +37,11 @@ #include "cpu/base.hh" #include "cpu/simple_thread.hh" #include "cpu/thread_context.hh" +#include "params/BaseCPU.hh" #if FULL_SYSTEM #include "arch/kernel_stats.hh" +#include "arch/stacktrace.hh" #include "base/callback.hh" #include "base/cprintf.hh" #include "base/output.hh" @@ -48,11 +50,10 @@ #include "cpu/quiesce_event.hh" #include "sim/serialize.hh" #include "sim/sim_exit.hh" -#include "arch/stacktrace.hh" #else +#include "mem/translating_port.hh" #include "sim/process.hh" #include "sim/system.hh" -#include "mem/translating_port.hh" #endif using namespace std; @@ -72,7 +73,7 @@ SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys, regs.clear(); - if (cpu->params->profile) { + if (cpu->params()->profile) { profile = new FunctionProfile(system->kernelSymtab); Callback *cb = new MakeCallback #include +#include "arch/kernel_stats.hh" #include "arch/vtophys.hh" #include "base/annotate.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" #include "cpu/quiesce_event.hh" -#include "arch/kernel_stats.hh" +#include "params/BaseCPU.hh" #include "sim/pseudo_inst.hh" #include "sim/serialize.hh" #include "sim/sim_exit.hh" @@ -67,7 +68,7 @@ arm(ThreadContext *tc) void quiesce(ThreadContext *tc) { - if (!tc->getCpuPtr()->params->do_quiesce) + if (!tc->getCpuPtr()->params()->do_quiesce) return; DPRINTF(Quiesce, "%s: quiesce()\n", tc->getCpuPtr()->name()); @@ -80,7 +81,7 @@ quiesce(ThreadContext *tc) void quiesceNs(ThreadContext *tc, uint64_t ns) { - if (!tc->getCpuPtr()->params->do_quiesce || ns == 0) + if (!tc->getCpuPtr()->params()->do_quiesce || ns == 0) return; EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent(); @@ -100,7 +101,7 @@ quiesceNs(ThreadContext *tc, uint64_t ns) void quiesceCycles(ThreadContext *tc, uint64_t cycles) { - if (!tc->getCpuPtr()->params->do_quiesce || cycles == 0) + if (!tc->getCpuPtr()->params()->do_quiesce || cycles == 0) return; EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent(); @@ -181,7 +182,7 @@ loadsymbol(ThreadContext *tc) void resetstats(ThreadContext *tc, Tick delay, Tick period) { - if (!tc->getCpuPtr()->params->do_statistics_insts) + if (!tc->getCpuPtr()->params()->do_statistics_insts) return; @@ -194,7 +195,7 @@ resetstats(ThreadContext *tc, Tick delay, Tick period) void dumpstats(ThreadContext *tc, Tick delay, Tick period) { - if (!tc->getCpuPtr()->params->do_statistics_insts) + if (!tc->getCpuPtr()->params()->do_statistics_insts) return; @@ -219,7 +220,7 @@ addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr) void dumpresetstats(ThreadContext *tc, Tick delay, Tick period) { - if (!tc->getCpuPtr()->params->do_statistics_insts) + if (!tc->getCpuPtr()->params()->do_statistics_insts) return; @@ -232,7 +233,7 @@ dumpresetstats(ThreadContext *tc, Tick delay, Tick period) void m5checkpoint(ThreadContext *tc, Tick delay, Tick period) { - if (!tc->getCpuPtr()->params->do_checkpoint_insts) + if (!tc->getCpuPtr()->params()->do_checkpoint_insts) return; Tick when = curTick + delay * Clock::Int::ns; -- cgit v1.2.3 From 9cf8ad3a17894c482968b5055e72f5434740f1f2 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 11 Aug 2008 12:22:17 -0700 Subject: params: Get rid of the remnants of the old style parameter configuration stuff. --- src/mem/mem_object.cc | 8 -------- src/mem/mem_object.hh | 13 +++---------- src/sim/sim_object.cc | 8 -------- src/sim/sim_object.hh | 4 ---- src/sim/system.cc | 6 +----- 5 files changed, 4 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/mem/mem_object.cc b/src/mem/mem_object.cc index ce2a1107e..20a1b4cd8 100644 --- a/src/mem/mem_object.cc +++ b/src/mem/mem_object.cc @@ -35,14 +35,6 @@ MemObject::MemObject(const Params *params) { } -MemObjectParams * -MemObject::makeParams(const std::string &name) -{ - MemObjectParams *params = new MemObjectParams; - params->name = name; - return params; -} - void MemObject::deletePortRefs(Port *p) { diff --git a/src/mem/mem_object.hh b/src/mem/mem_object.hh index 33b56dfd4..b8bf4b939 100644 --- a/src/mem/mem_object.hh +++ b/src/mem/mem_object.hh @@ -48,17 +48,10 @@ class MemObject : public SimObject { public: typedef MemObjectParams Params; - MemObject(const Params *params); - - const Params * - params() const - { - return dynamic_cast(_params); - } + const Params *params() const + { return dynamic_cast(_params); } - protected: - // static: support for old-style constructors (call manually) - static Params *makeParams(const std::string &name); + MemObject(const Params *params); public: /** Additional function to return the Port of a memory object. */ diff --git a/src/sim/sim_object.cc b/src/sim/sim_object.cc index a835aee5b..2c2213987 100644 --- a/src/sim/sim_object.cc +++ b/src/sim/sim_object.cc @@ -69,14 +69,6 @@ SimObject::SimObject(const Params *p) state = Running; } -SimObjectParams * -SimObject::makeParams(const std::string &name) -{ - SimObjectParams *params = new SimObjectParams; - params->name = name; - return params; -} - void SimObject::init() { diff --git a/src/sim/sim_object.hh b/src/sim/sim_object.hh index 00bb3fee6..0141c16cc 100644 --- a/src/sim/sim_object.hh +++ b/src/sim/sim_object.hh @@ -87,10 +87,6 @@ class SimObject : public Serializable, protected StartupCallback SimObject(const Params *_params); virtual ~SimObject() {} - protected: - // static: support for old-style constructors (call manually) - static Params *makeParams(const std::string &name); - public: virtual const std::string name() const { return params()->name; } diff --git a/src/sim/system.cc b/src/sim/system.cc index 803881539..7b830d0f7 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -285,11 +285,7 @@ const char *System::MemoryModeStrings[3] = {"invalid", "atomic", System * SystemParams::create() { - System::Params *p = new System::Params; - p->name = name; - p->physmem = physmem; - p->mem_mode = mem_mode; - return new System(p); + return new System(this); } #endif -- cgit v1.2.3 From 1b1a7e33e730db51f67bc2f124347afaa7b0e0e9 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 11 Aug 2008 14:47:49 -0700 Subject: style --- src/arch/mips/regfile/misc_regfile.cc | 143 +++++++++++++++++++++------------- src/arch/mips/regfile/misc_regfile.hh | 6 +- src/arch/sparc/miscregfile.cc | 13 ++-- src/arch/sparc/ua2005.cc | 64 +++++++-------- 4 files changed, 133 insertions(+), 93 deletions(-) (limited to 'src') diff --git a/src/arch/mips/regfile/misc_regfile.cc b/src/arch/mips/regfile/misc_regfile.cc index 407851007..b82a94103 100755 --- a/src/arch/mips/regfile/misc_regfile.cc +++ b/src/arch/mips/regfile/misc_regfile.cc @@ -45,39 +45,49 @@ using namespace std; std::string MiscRegFile::miscRegNames[NumMiscRegs] = -{"Index", "MVPControl", "MVPConf0", "MVPConf1", "", "", "", "", - "Random", "VPEControl", "VPEConf0", "VPEConf1", "YQMask", "VPESchedule", "VPEScheFBack", "VPEOpt", - "EntryLo0", "TCStatus", "TCBind", "TCRestart", "TCHalt", "TCContext", "TCSchedule", "TCScheFBack", - "EntryLo1", "", "", "", "", "", "", "", - "Context", "ContextConfig", "", "", "", "", "", "", - "PageMask", "PageGrain", "", "", "", "", "", "", - "Wired", "SRSConf0", "SRCConf1", "SRSConf2", "SRSConf3", "SRSConf4", "", "", - "HWREna", "", "", "", "", "", "", "", - "BadVAddr", "", "", "", "", "", "", "", - "Count", "", "", "", "", "", "", "", - "EntryHi", "", "", "", "", "", "", "", - "Compare", "", "", "", "", "", "", "", - "Status", "IntCtl", "SRSCtl", "SRSMap", "", "", "", "", - "Cause", "", "", "", "", "", "", "", - "EPC", "", "", "", "", "", "", "", - "PRId", "EBase", "", "", "", "", "", "", - "Config", "Config1", "Config2", "Config3", "", "", "", "", - "LLAddr", "", "", "", "", "", "", "", - "WatchLo0", "WatchLo1", "WatchLo2", "WatchLo3", "WatchLo4", "WatchLo5", "WatchLo6", "WatchLo7", - "WatchHi0", "WatchHi1", "WatchHi2", "WatchHi3", "WatchHi4", "WatchHi5", "WatchHi6", "WatchHi7", - "XCContext64", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "Debug", "TraceControl1", "TraceControl2", "UserTraceData", "TraceBPC", "", "", "", - "DEPC", "", "", "", "", "", "", "", - "PerfCnt0", "PerfCnt1", "PerfCnt2", "PerfCnt3", "PerfCnt4", "PerfCnt5", "PerfCnt6", "PerfCnt7", - "ErrCtl", "", "", "", "", "", "", "", - "CacheErr0", "CacheErr1", "CacheErr2", "CacheErr3", "", "", "", "", - "TagLo0", "DataLo1", "TagLo2", "DataLo3", "TagLo4", "DataLo5", "TagLo6", "DataLo7", - "TagHi0", "DataHi1", "TagHi2", "DataHi3", "TagHi4", "DataHi5", "TagHi6", "DataHi7", - "ErrorEPC", "", "", "", "", "", "", "", - "DESAVE", "", "", "", "", "", "", "", - "LLFlag" +{ + "Index", "MVPControl", "MVPConf0", "MVPConf1", "", "", "", "", + "Random", "VPEControl", "VPEConf0", "VPEConf1", + "YQMask", "VPESchedule", "VPEScheFBack", "VPEOpt", + "EntryLo0", "TCStatus", "TCBind", "TCRestart", + "TCHalt", "TCContext", "TCSchedule", "TCScheFBack", + "EntryLo1", "", "", "", "", "", "", "", + "Context", "ContextConfig", "", "", "", "", "", "", + "PageMask", "PageGrain", "", "", "", "", "", "", + "Wired", "SRSConf0", "SRCConf1", "SRSConf2", + "SRSConf3", "SRSConf4", "", "", + "HWREna", "", "", "", "", "", "", "", + "BadVAddr", "", "", "", "", "", "", "", + "Count", "", "", "", "", "", "", "", + "EntryHi", "", "", "", "", "", "", "", + "Compare", "", "", "", "", "", "", "", + "Status", "IntCtl", "SRSCtl", "SRSMap", "", "", "", "", + "Cause", "", "", "", "", "", "", "", + "EPC", "", "", "", "", "", "", "", + "PRId", "EBase", "", "", "", "", "", "", + "Config", "Config1", "Config2", "Config3", "", "", "", "", + "LLAddr", "", "", "", "", "", "", "", + "WatchLo0", "WatchLo1", "WatchLo2", "WatchLo3", + "WatchLo4", "WatchLo5", "WatchLo6", "WatchLo7", + "WatchHi0", "WatchHi1", "WatchHi2", "WatchHi3", + "WatchHi4", "WatchHi5", "WatchHi6", "WatchHi7", + "XCContext64", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", + "Debug", "TraceControl1", "TraceControl2", "UserTraceData", + "TraceBPC", "", "", "", + "DEPC", "", "", "", "", "", "", "", + "PerfCnt0", "PerfCnt1", "PerfCnt2", "PerfCnt3", + "PerfCnt4", "PerfCnt5", "PerfCnt6", "PerfCnt7", + "ErrCtl", "", "", "", "", "", "", "", + "CacheErr0", "CacheErr1", "CacheErr2", "CacheErr3", "", "", "", "", + "TagLo0", "DataLo1", "TagLo2", "DataLo3", + "TagLo4", "DataLo5", "TagLo6", "DataLo7", + "TagHi0", "DataHi1", "TagHi2", "DataHi3", + "TagHi4", "DataHi5", "TagHi6", "DataHi7", + "ErrorEPC", "", "", "", "", "", "", "", + "DESAVE", "", "", "", "", "", "", "", + "LLFlag" }; MiscRegFile::MiscRegFile() @@ -212,7 +222,8 @@ MiscRegFile::reset(std::string core_name, unsigned num_threads, // Config1 MiscReg cfg1 = readRegNoEffect(Config1); - replaceBits(cfg1, Config1_MMUSize_HI, Config1_MMUSize_LO, cp.CP0_Config1_MMU); + replaceBits(cfg1, Config1_MMUSize_HI, Config1_MMUSize_LO, + cp.CP0_Config1_MMU); replaceBits(cfg1, Config1_IS_HI, Config1_IS_LO, cp.CP0_Config1_IS); replaceBits(cfg1, Config1_IL_HI, Config1_IL_LO, cp.CP0_Config1_IL); replaceBits(cfg1, Config1_IA_HI, Config1_IA_LO, cp.CP0_Config1_IA); @@ -334,12 +345,18 @@ MiscRegFile::reset(std::string core_name, unsigned num_threads, // Status MiscReg stat = readRegNoEffect(Status); - // Only CU0 and IE are modified on a reset - everything else needs to be controlled - // on a per CPU model basis - // replaceBits(stat, Status_CU0_HI,Status_CU0_LO, 1); // Enable CP0 on reset + // Only CU0 and IE are modified on a reset - everything else needs + // to be controlled on a per CPU model basis + + // Enable CP0 on reset + // replaceBits(stat, Status_CU0_HI,Status_CU0_LO, 1); + + // Enable ERL bit on a reset + replaceBits(stat, Status_ERL_HI, Status_ERL_LO, 1); + + // Enable BEV bit on a reset + replaceBits(stat, Status_BEV_HI, Status_BEV_LO, 1); - replaceBits(stat, Status_ERL_HI, Status_ERL_LO, 1); // Enable ERL bit on a reset - replaceBits(stat, Status_BEV_HI, Status_BEV_LO, 1); // Enable BEV bit on a reset setRegNoEffect(Status, stat); // Now, create Write Mask for the Status register MiscReg stat_Mask = 0xFF78FF17; @@ -440,7 +457,8 @@ MiscRegFile::readRegNoEffect(int reg_idx, unsigned tid) unsigned reg_sel = (bankType[misc_reg] == perThreadContext) ? tid : getVPENum(tid); DPRINTF(MipsPRA, "Reading CP0 Register:%u Select:%u (%s) (%lx).\n", - misc_reg / 8, misc_reg % 8, getMiscRegName(misc_reg),miscRegFile[misc_reg][reg_sel]); + misc_reg / 8, misc_reg % 8, getMiscRegName(misc_reg), + miscRegFile[misc_reg][reg_sel]); return miscRegFile[misc_reg][reg_sel]; } @@ -454,8 +472,10 @@ MiscRegFile::readReg(int reg_idx, int misc_reg = reg_idx - Ctrl_Base_DepTag; unsigned reg_sel = (bankType[misc_reg] == perThreadContext) ? tid : getVPENum(tid); - DPRINTF(MipsPRA, "Reading CP0 Register:%u Select:%u (%s) with effect (%lx).\n", - misc_reg / 8, misc_reg % 8, getMiscRegName(misc_reg),miscRegFile[misc_reg][reg_sel]); + DPRINTF(MipsPRA, + "Reading CP0 Register:%u Select:%u (%s) with effect (%lx).\n", + misc_reg / 8, misc_reg % 8, getMiscRegName(misc_reg), + miscRegFile[misc_reg][reg_sel]); switch (misc_reg) @@ -471,7 +491,9 @@ MiscRegFile::setRegNoEffect(int reg_idx, const MiscReg &val, unsigned tid) int misc_reg = reg_idx - Ctrl_Base_DepTag; unsigned reg_sel = (bankType[misc_reg] == perThreadContext) ? tid : getVPENum(tid); - DPRINTF(MipsPRA, "[tid:%i]: Setting (direct set) CP0 Register:%u Select:%u (%s) to %#x.\n", + DPRINTF(MipsPRA, + "[tid:%i]: Setting (direct set) CP0 Register:%u " + "Select:%u (%s) to %#x.\n", tid, misc_reg / 8, misc_reg % 8, getMiscRegName(misc_reg), val); miscRegFile[misc_reg][reg_sel] = val; @@ -483,7 +505,9 @@ MiscRegFile::setRegMask(int reg_idx, const MiscReg &val, unsigned tid) int misc_reg = reg_idx - Ctrl_Base_DepTag; unsigned reg_sel = (bankType[misc_reg] == perThreadContext) ? tid : getVPENum(tid); - DPRINTF(MipsPRA,"[tid:%i]: Setting CP0 Register: %u Select: %u (%s) to %#x\n",tid, misc_reg / 8, misc_reg % 8, getMiscRegName(misc_reg), val); + DPRINTF(MipsPRA, + "[tid:%i]: Setting CP0 Register: %u Select: %u (%s) to %#x\n", + tid, misc_reg / 8, misc_reg % 8, getMiscRegName(misc_reg), val); miscRegFile_WriteMask[misc_reg][reg_sel] = val; } @@ -500,7 +524,9 @@ MiscRegFile::setReg(int reg_idx, const MiscReg &val, int reg_sel = (bankType[misc_reg] == perThreadContext) ? tid : getVPENum(tid); - DPRINTF(MipsPRA, "[tid:%i]: Setting CP0 Register:%u Select:%u (%s) to %#x, with effect.\n", + DPRINTF(MipsPRA, + "[tid:%i]: Setting CP0 Register:%u " + "Select:%u (%s) to %#x, with effect.\n", tid, misc_reg / 8, misc_reg % 8, getMiscRegName(misc_reg), val); MiscReg cp0_val = filterCP0Write(misc_reg, reg_sel, val); @@ -509,16 +535,28 @@ MiscRegFile::setReg(int reg_idx, const MiscReg &val, scheduleCP0Update(1); } -/** This method doesn't need to adjust the Control Register Offset since - it has already been done in the calling method (setRegWithEffect) */ -MiscReg MiscRegFile::filterCP0Write(int misc_reg, int reg_sel, const MiscReg &val) +/** + * This method doesn't need to adjust the Control Register Offset + * since it has already been done in the calling method + * (setRegWithEffect) +*/ +MiscReg +MiscRegFile::filterCP0Write(int misc_reg, int reg_sel, const MiscReg &val) { MiscReg retVal = val; - retVal &= miscRegFile_WriteMask[misc_reg][reg_sel]; // Mask off read-only regions + + // Mask off read-only regions + retVal &= miscRegFile_WriteMask[misc_reg][reg_sel]; MiscReg curVal = miscRegFile[misc_reg][reg_sel]; - curVal &= (~miscRegFile_WriteMask[misc_reg][reg_sel]); // Mask off current alue with inverse mask (clear writeable bits) + // Mask off current alue with inverse mask (clear writeable bits) + curVal &= (~miscRegFile_WriteMask[misc_reg][reg_sel]); retVal |= curVal; // Combine the two - DPRINTF(MipsPRA,"filterCP0Write: Mask: %lx, Inverse Mask: %lx, write Val: %x, current val: %lx, written val: %x\n",miscRegFile_WriteMask[misc_reg][reg_sel],~miscRegFile_WriteMask[misc_reg][reg_sel],val,miscRegFile[misc_reg][reg_sel],retVal); + DPRINTF(MipsPRA, + "filterCP0Write: Mask: %lx, Inverse Mask: %lx, write Val: %x, " + "current val: %lx, written val: %x\n", + miscRegFile_WriteMask[misc_reg][reg_sel], + ~miscRegFile_WriteMask[misc_reg][reg_sel], + val, miscRegFile[misc_reg][reg_sel], retVal); return retVal; } void @@ -563,7 +601,8 @@ MiscRegFile::updateCPU() } MiscRegFile::CP0Event::CP0Event(CP0 *_cp0, BaseCPU *_cpu, CP0EventType e_type) - : Event(&mainEventQueue, CPU_Tick_Pri), cp0(_cp0), cpu(_cpu), cp0EventType(e_type) + : Event(&mainEventQueue, CPU_Tick_Pri), cp0(_cp0), cpu(_cpu), + cp0EventType(e_type) { } void diff --git a/src/arch/mips/regfile/misc_regfile.hh b/src/arch/mips/regfile/misc_regfile.hh index 5f19579b3..4bec9a49e 100644 --- a/src/arch/mips/regfile/misc_regfile.hh +++ b/src/arch/mips/regfile/misc_regfile.hh @@ -75,7 +75,8 @@ namespace MipsISA void clear(unsigned tid_or_vpn = 0); - void reset(std::string core_name, unsigned num_threads, unsigned num_vpes, BaseCPU *_cpu); + void reset(std::string core_name, unsigned num_threads, + unsigned num_vpes, BaseCPU *_cpu); void expandForMultithreading(unsigned num_threads, unsigned num_vpes); @@ -98,7 +99,8 @@ namespace MipsISA MiscReg filterCP0Write(int misc_reg, int reg_sel, const MiscReg &val); void setRegMask(int misc_reg, const MiscReg &val, unsigned tid = 0); - void setRegNoEffect(int misc_reg, const MiscReg &val, unsigned tid = 0); + void setRegNoEffect(int misc_reg, const MiscReg &val, + unsigned tid = 0); //template void setReg(int misc_reg, const MiscReg &val, diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc index 7b9c73433..195db90a6 100644 --- a/src/arch/sparc/miscregfile.cc +++ b/src/arch/sparc/miscregfile.cc @@ -322,12 +322,14 @@ MiscReg MiscRegFile::readReg(int miscReg, ThreadContext * tc) return readFSReg(miscReg, tc); #else case MISCREG_HPSTATE: - //HPSTATE is special because because sometimes in privilege checks for instructions - //it will read HPSTATE to make sure the priv. level is ok - //So, we'll just have to tell it it isn't, instead of panicing. + //HPSTATE is special because because sometimes in privilege + //checks for instructions it will read HPSTATE to make sure + //the priv. level is ok So, we'll just have to tell it it + //isn't, instead of panicing. return 0; - panic("Accessing Fullsystem register %s in SE mode\n",getMiscRegName(miscReg)); + panic("Accessing Fullsystem register %s in SE mode\n", + getMiscRegName(miscReg)); #endif } @@ -584,7 +586,8 @@ void MiscRegFile::setReg(int miscReg, //HPSTATE is special because normal trap processing saves HPSTATE when //it goes into a trap, and restores it when it returns. return; - panic("Accessing Fullsystem register %s to %#x in SE mode\n", getMiscRegName(miscReg), val); + panic("Accessing Fullsystem register %s to %#x in SE mode\n", + getMiscRegName(miscReg), val); #endif } setRegNoEffect(miscReg, new_val); diff --git a/src/arch/sparc/ua2005.cc b/src/arch/sparc/ua2005.cc index fe733813c..990250159 100644 --- a/src/arch/sparc/ua2005.cc +++ b/src/arch/sparc/ua2005.cc @@ -40,22 +40,24 @@ using namespace SparcISA; void MiscRegFile::checkSoftInt(ThreadContext *tc) { + BaseCPU *cpu = tc->getCpuPtr(); + // If PIL < 14, copy over the tm and sm bits if (pil < 14 && softint & 0x10000) - tc->getCpuPtr()->post_interrupt(IT_SOFT_INT,16); + cpu->post_interrupt(IT_SOFT_INT, 16); else - tc->getCpuPtr()->clear_interrupt(IT_SOFT_INT,16); + cpu->clear_interrupt(IT_SOFT_INT, 16); if (pil < 14 && softint & 0x1) - tc->getCpuPtr()->post_interrupt(IT_SOFT_INT,0); + cpu->post_interrupt(IT_SOFT_INT, 0); else - tc->getCpuPtr()->clear_interrupt(IT_SOFT_INT,0); + cpu->clear_interrupt(IT_SOFT_INT, 0); // Copy over any of the other bits that are set for (int bit = 15; bit > 0; --bit) { if (1 << bit & softint && bit > pil) - tc->getCpuPtr()->post_interrupt(IT_SOFT_INT,bit); + cpu->post_interrupt(IT_SOFT_INT, bit); else - tc->getCpuPtr()->clear_interrupt(IT_SOFT_INT,bit); + cpu->clear_interrupt(IT_SOFT_INT, bit); } } @@ -63,6 +65,8 @@ MiscRegFile::checkSoftInt(ThreadContext *tc) void MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc) { + BaseCPU *cpu = tc->getCpuPtr(); + int64_t time; switch (miscReg) { /* Full system only ASRs */ @@ -85,7 +89,7 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc) if (!(tick_cmpr & ~mask(63)) && time > 0) { if (tickCompare->scheduled()) tickCompare->deschedule(); - tickCompare->schedule(time * tc->getCpuPtr()->ticks(1)); + tickCompare->schedule(time * cpu->ticks(1)); } panic("writing to TICK compare register %#X\n", val); break; @@ -97,11 +101,11 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc) if ((stick_cmpr & ~mask(63)) && sTickCompare->scheduled()) sTickCompare->deschedule(); time = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) - - tc->getCpuPtr()->instCount(); + cpu->instCount(); if (!(stick_cmpr & ~mask(63)) && time > 0) { if (sTickCompare->scheduled()) sTickCompare->deschedule(); - sTickCompare->schedule(time * tc->getCpuPtr()->ticks(1) + curTick); + sTickCompare->schedule(time * cpu->ticks(1) + curTick); } DPRINTF(Timer, "writing to sTICK compare register value %#X\n", val); break; @@ -120,9 +124,9 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc) case MISCREG_HINTP: setRegNoEffect(miscReg, val); if (hintp) - tc->getCpuPtr()->post_interrupt(IT_HINTP,0); + cpu->post_interrupt(IT_HINTP, 0); else - tc->getCpuPtr()->clear_interrupt(IT_HINTP,0); + cpu->clear_interrupt(IT_HINTP, 0); break; case MISCREG_HTBA: @@ -134,25 +138,25 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc) case MISCREG_QUEUE_CPU_MONDO_TAIL: setRegNoEffect(miscReg, val); if (cpu_mondo_head != cpu_mondo_tail) - tc->getCpuPtr()->post_interrupt(IT_CPU_MONDO,0); + cpu->post_interrupt(IT_CPU_MONDO, 0); else - tc->getCpuPtr()->clear_interrupt(IT_CPU_MONDO,0); + cpu->clear_interrupt(IT_CPU_MONDO, 0); break; case MISCREG_QUEUE_DEV_MONDO_HEAD: case MISCREG_QUEUE_DEV_MONDO_TAIL: setRegNoEffect(miscReg, val); if (dev_mondo_head != dev_mondo_tail) - tc->getCpuPtr()->post_interrupt(IT_DEV_MONDO,0); + cpu->post_interrupt(IT_DEV_MONDO, 0); else - tc->getCpuPtr()->clear_interrupt(IT_DEV_MONDO,0); + cpu->clear_interrupt(IT_DEV_MONDO, 0); break; case MISCREG_QUEUE_RES_ERROR_HEAD: case MISCREG_QUEUE_RES_ERROR_TAIL: setRegNoEffect(miscReg, val); if (res_error_head != res_error_tail) - tc->getCpuPtr()->post_interrupt(IT_RES_ERROR,0); + cpu->post_interrupt(IT_RES_ERROR, 0); else - tc->getCpuPtr()->clear_interrupt(IT_RES_ERROR,0); + cpu->clear_interrupt(IT_RES_ERROR, 0); break; case MISCREG_QUEUE_NRES_ERROR_HEAD: case MISCREG_QUEUE_NRES_ERROR_TAIL: @@ -167,11 +171,11 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc) if ((hstick_cmpr & ~mask(63)) && hSTickCompare->scheduled()) hSTickCompare->deschedule(); time = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) - - tc->getCpuPtr()->instCount(); + cpu->instCount(); if (!(hstick_cmpr & ~mask(63)) && time > 0) { if (hSTickCompare->scheduled()) hSTickCompare->deschedule(); - hSTickCompare->schedule(curTick + time * tc->getCpuPtr()->ticks(1)); + hSTickCompare->schedule(curTick + time * cpu->ticks(1)); } DPRINTF(Timer, "writing to hsTICK compare register value %#X\n", val); break; @@ -181,9 +185,9 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc) setRegNoEffect(miscReg, val | HPSTATE::id); #if FULL_SYSTEM if (hpstate & HPSTATE::tlz && tl == 0 && !(hpstate & HPSTATE::hpriv)) - tc->getCpuPtr()->post_interrupt(IT_TRAP_LEVEL_ZERO,0); + cpu->post_interrupt(IT_TRAP_LEVEL_ZERO, 0); else - tc->getCpuPtr()->clear_interrupt(IT_TRAP_LEVEL_ZERO,0); + cpu->clear_interrupt(IT_TRAP_LEVEL_ZERO, 0); #endif break; case MISCREG_HTSTATE: @@ -200,11 +204,12 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc) tc->suspend(); if (tc->getKernelStats()) tc->getKernelStats()->quiesce(); - } + } break; default: - panic("Invalid write to FS misc register %s\n", getMiscRegName(miscReg)); + panic("Invalid write to FS misc register %s\n", + getMiscRegName(miscReg)); } } @@ -250,7 +255,8 @@ MiscRegFile::readFSReg(int miscReg, ThreadContext * tc) sys = tc->getSystemPtr(); temp = readRegNoEffect(miscReg) & (STS::active | STS::speculative); - // Check that the CPU array is fully populated (by calling getNumCPus()) + // Check that the CPU array is fully populated + // (by calling getNumCPus()) assert(sys->getNumCPUs() > tc->readCpuId()); temp |= tc->readCpuId() << STS::shft_id; @@ -280,16 +286,6 @@ MiscRegFile::readFSReg(int miscReg, ThreadContext * tc) panic("Invalid read to FS misc register\n"); } } -/* - In Niagra STICK==TICK so this isn't needed - case MISCREG_STICK: - SparcSystem *sys; - sys = dynamic_cast(tc->getSystemPtr()); - assert(sys != NULL); - return curTick/Clock::Int::ns - sys->sysTick | (stick & ~(mask(63))); -*/ - - void MiscRegFile::processTickCompare(ThreadContext *tc) -- cgit v1.2.3 From 91d968783ecbcbe4bcd44e10964532303b367a05 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Wed, 13 Aug 2008 16:29:59 -0400 Subject: Return an UnimpFault for an ITB translation of an uncachable address. We don't support fetching from uncached addresses in Alpha and it means that a speculative fetch can clobber device registers. --- src/arch/alpha/tlb.cc | 10 ++++++++-- src/arch/alpha/tlb.hh | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc index 77bf5e285..4f960360e 100644 --- a/src/arch/alpha/tlb.cc +++ b/src/arch/alpha/tlb.cc @@ -116,7 +116,7 @@ TLB::lookup(Addr vpn, uint8_t asn) Fault -TLB::checkCacheability(RequestPtr &req) +TLB::checkCacheability(RequestPtr &req, bool itb) { // in Alpha, cacheability is controlled by upper-level bits of the // physical address @@ -148,6 +148,12 @@ TLB::checkCacheability(RequestPtr &req) req->setPaddr(req->getPaddr() & PAddrUncachedMask); #endif } + // We shouldn't be able to read from an uncachable address in Alpha as + // we don't have a ROM and we don't want to try to fetch from a device + // register as we destroy any data that is clear-on-read. + if (req->isUncacheable() && itb) + return new UnimpFault("CPU trying to fetch from uncached I/O"); + } return NoFault; } @@ -390,7 +396,7 @@ ITB::translate(RequestPtr &req, ThreadContext *tc) if (req->getPaddr() & ~PAddrImplMask) return genMachineCheckFault(); - return checkCacheability(req); + return checkCacheability(req, true); } diff --git a/src/arch/alpha/tlb.hh b/src/arch/alpha/tlb.hh index e61ae5c6d..f94d06ccd 100644 --- a/src/arch/alpha/tlb.hh +++ b/src/arch/alpha/tlb.hh @@ -92,7 +92,7 @@ namespace AlphaISA return (unimplBits == 0) || (unimplBits == EV5::VAddrUnImplMask); } - static Fault checkCacheability(RequestPtr &req); + static Fault checkCacheability(RequestPtr &req, bool itb = false); // Checkpointing virtual void serialize(std::ostream &os); -- cgit v1.2.3 From 05954e1ba7bb35674b0d12428788998d699f25cb Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Wed, 13 Aug 2008 16:30:30 -0400 Subject: More subtle fixes to how interrupts are supposed to work in the device. Fix postedInterrupts statistics. --- src/dev/i8254xGBe.cc | 3 ++- src/dev/i8254xGBe.hh | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/dev/i8254xGBe.cc b/src/dev/i8254xGBe.cc index 76e11b752..98040a252 100644 --- a/src/dev/i8254xGBe.cc +++ b/src/dev/i8254xGBe.cc @@ -588,7 +588,6 @@ IGbE::postInterrupt(IntTypes t, bool now) if (interEvent.scheduled()) { interEvent.deschedule(); } - postedInterrupts++; cpuPostInt(); } else { Tick int_time = lastInterrupt + itr_interval; @@ -612,6 +611,8 @@ void IGbE::cpuPostInt() { + postedInterrupts++; + if (!(regs.icr() & regs.imr)) { DPRINTF(Ethernet, "Interrupt Masked. Not Posting\n"); return; diff --git a/src/dev/i8254xGBe.hh b/src/dev/i8254xGBe.hh index a69793bd4..de73eda79 100644 --- a/src/dev/i8254xGBe.hh +++ b/src/dev/i8254xGBe.hh @@ -87,7 +87,7 @@ class IGbE : public EtherDevice void rdtrProcess() { rxDescCache.writeback(0); DPRINTF(EthernetIntr, "Posting RXT interrupt because RDTR timer expired\n"); - postInterrupt(iGbReg::IT_RXT, true); + postInterrupt(iGbReg::IT_RXT); } //friend class EventWrapper; @@ -97,7 +97,7 @@ class IGbE : public EtherDevice void radvProcess() { rxDescCache.writeback(0); DPRINTF(EthernetIntr, "Posting RXT interrupt because RADV timer expired\n"); - postInterrupt(iGbReg::IT_RXT, true); + postInterrupt(iGbReg::IT_RXT); } //friend class EventWrapper; @@ -107,7 +107,7 @@ class IGbE : public EtherDevice void tadvProcess() { txDescCache.writeback(0); DPRINTF(EthernetIntr, "Posting TXDW interrupt because TADV timer expired\n"); - postInterrupt(iGbReg::IT_TXDW, true); + postInterrupt(iGbReg::IT_TXDW); } //friend class EventWrapper; @@ -117,7 +117,7 @@ class IGbE : public EtherDevice void tidvProcess() { txDescCache.writeback(0); DPRINTF(EthernetIntr, "Posting TXDW interrupt because TIDV timer expired\n"); - postInterrupt(iGbReg::IT_TXDW, true); + postInterrupt(iGbReg::IT_TXDW); } //friend class EventWrapper; EventWrapper tidvEvent; -- cgit v1.2.3 From 549c43b2d0cd2411f7c8eda3f89ce1fd695c17e9 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Wed, 13 Aug 2008 17:41:56 -0400 Subject: Add the ability for a DMA to tack on an extra delay after the DMA is actually finished. --- src/dev/io_device.cc | 11 +++++++---- src/dev/io_device.hh | 18 +++++++++++------- 2 files changed, 18 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/dev/io_device.cc b/src/dev/io_device.cc index 527397ed8..b86a2d313 100644 --- a/src/dev/io_device.cc +++ b/src/dev/io_device.cc @@ -138,7 +138,10 @@ DmaPort::recvTiming(PacketPtr pkt) state->numBytes += pkt->req->getSize(); assert(state->totBytes >= state->numBytes); if (state->totBytes == state->numBytes) { - state->completionEvent->process(); + if (state->delay) + state->completionEvent->schedule(state->delay + curTick); + else + state->completionEvent->process(); delete state; } delete pkt->req; @@ -216,13 +219,13 @@ DmaPort::recvRetry() void DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, - uint8_t *data) + uint8_t *data, Tick delay) { assert(event); assert(device->getState() == SimObject::Running); - DmaReqState *reqState = new DmaReqState(event, this, size); + DmaReqState *reqState = new DmaReqState(event, this, size, delay); DPRINTF(DMA, "Starting DMA for addr: %#x size: %d sched: %d\n", addr, size, @@ -314,7 +317,7 @@ DmaPort::sendDma() if (state->totBytes == state->numBytes) { assert(!state->completionEvent->scheduled()); - state->completionEvent->schedule(curTick + lat); + state->completionEvent->schedule(curTick + lat + state->delay); delete state; delete pkt->req; } diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh index 44aa01798..1e2e623f1 100644 --- a/src/dev/io_device.hh +++ b/src/dev/io_device.hh @@ -89,8 +89,12 @@ class DmaPort : public Port /** Number of bytes that have been acked for this transaction. */ Addr numBytes; - DmaReqState(Event *ce, Port *p, Addr tb) - : completionEvent(ce), outPort(p), totBytes(tb), numBytes(0) + /** Amount to delay completion of dma by */ + Tick delay; + + DmaReqState(Event *ce, Port *p, Addr tb, Tick _delay) + : completionEvent(ce), outPort(p), totBytes(tb), numBytes(0), + delay(_delay) {} }; @@ -144,7 +148,7 @@ class DmaPort : public Port DmaPort(DmaDevice *dev, System *s); void dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, - uint8_t *data = NULL); + uint8_t *data, Tick delay); bool dmaPending() { return pendingCount > 0; } @@ -265,14 +269,14 @@ class DmaDevice : public PioDevice return dynamic_cast(_params); } - void dmaWrite(Addr addr, int size, Event *event, uint8_t *data) + void dmaWrite(Addr addr, int size, Event *event, uint8_t *data, Tick delay = 0) { - dmaPort->dmaAction(MemCmd::WriteReq, addr, size, event, data); + dmaPort->dmaAction(MemCmd::WriteReq, addr, size, event, data, delay); } - void dmaRead(Addr addr, int size, Event *event, uint8_t *data) + void dmaRead(Addr addr, int size, Event *event, uint8_t *data, Tick delay = 0) { - dmaPort->dmaAction(MemCmd::ReadReq, addr, size, event, data); + dmaPort->dmaAction(MemCmd::ReadReq, addr, size, event, data, delay); } bool dmaPending() { return dmaPort->dmaPending(); } -- cgit v1.2.3 From 6248e12704275bf4cc88f1743bb3a4bff7adcf9f Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Wed, 13 Aug 2008 17:41:58 -0400 Subject: Add the ability to specify a think time before descriptor fetch/writeback starts/ends as well as after read/write dmas --- src/dev/Ethernet.py | 7 +++++ src/dev/i8254xGBe.cc | 10 ++++--- src/dev/i8254xGBe.hh | 75 +++++++++++++++++++++++++++++++++++++++------------- 3 files changed, 71 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/dev/Ethernet.py b/src/dev/Ethernet.py index 2beb0d537..01384b32b 100644 --- a/src/dev/Ethernet.py +++ b/src/dev/Ethernet.py @@ -98,6 +98,13 @@ class IGbE(EtherDevice): InterruptLine = 0x1e InterruptPin = 0x01 BAR0Size = '128kB' + wb_delay = Param.Latency('10ns', "delay before desc writeback occurs") + fetch_delay = Param.Latency('10ns', "delay before desc fetch occurs") + fetch_comp_delay = Param.Latency('10ns', "delay after desc fetch occurs") + wb_comp_delay = Param.Latency('10ns', "delay after desc wb occurs") + tx_read_delay = Param.Latency('0ns', "delay after tx dma read") + rx_write_delay = Param.Latency('0ns', "delay after rx dma read") + class EtherDevBase(EtherDevice): type = 'EtherDevBase' diff --git a/src/dev/i8254xGBe.cc b/src/dev/i8254xGBe.cc index 98040a252..ca60d2e7d 100644 --- a/src/dev/i8254xGBe.cc +++ b/src/dev/i8254xGBe.cc @@ -57,7 +57,11 @@ using namespace Net; IGbE::IGbE(const Params *p) : EtherDevice(p), etherInt(NULL), drainEvent(NULL), useFlowControl(p->use_flow_control), rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size), rxTick(false), - txTick(false), txFifoTick(false), rxDmaPacket(false), rdtrEvent(this), radvEvent(this), + txTick(false), txFifoTick(false), rxDmaPacket(false), + fetchDelay(p->fetch_delay), wbDelay(p->wb_delay), + fetchCompDelay(p->fetch_comp_delay), wbCompDelay(p->wb_comp_delay), + rxWriteDelay(p->rx_write_delay), txReadDelay(p->tx_read_delay), + rdtrEvent(this), radvEvent(this), tadvEvent(this), tidvEvent(this), tickEvent(this), interEvent(this), rxDescCache(this, name()+".RxDesc", p->rx_desc_cache_size), txDescCache(this, name()+".TxDesc", p->tx_desc_cache_size), @@ -714,7 +718,7 @@ IGbE::RxDescCache::writePacket(EthPacketPtr packet) pktPtr = packet; pktDone = false; igbe->dmaWrite(igbe->platform->pciToDma(unusedCache.front()->buf), - packet->length, &pktEvent, packet->data); + packet->length, &pktEvent, packet->data, igbe->rxWriteDelay); } void @@ -932,7 +936,7 @@ IGbE::TxDescCache::getPacketData(EthPacketPtr p) DPRINTF(EthernetDesc, "Starting DMA of packet at offset %d\n", p->length); igbe->dmaRead(igbe->platform->pciToDma(TxdOp::getBuf(desc)), - TxdOp::getLen(desc), &pktEvent, p->data + p->length); + TxdOp::getLen(desc), &pktEvent, p->data + p->length, igbe->txReadDelay); } diff --git a/src/dev/i8254xGBe.hh b/src/dev/i8254xGBe.hh index de73eda79..66a93a509 100644 --- a/src/dev/i8254xGBe.hh +++ b/src/dev/i8254xGBe.hh @@ -83,6 +83,11 @@ class IGbE : public EtherDevice bool rxDmaPacket; + // Delays in managaging descriptors + Tick fetchDelay, wbDelay; + Tick fetchCompDelay, wbCompDelay; + Tick rxWriteDelay, txReadDelay; + // Event and function to deal with RDTR timer expiring void rdtrProcess() { rxDescCache.writeback(0); @@ -217,7 +222,8 @@ class IGbE : public EtherDevice public: DescCache(IGbE *i, const std::string n, int s) : igbe(i), _name(n), cachePnt(0), size(s), curFetching(0), wbOut(0), - pktPtr(NULL), fetchEvent(this), wbEvent(this) + pktPtr(NULL), wbDelayEvent(this), fetchDelayEvent(this), + fetchEvent(this), wbEvent(this) { fetchBuf = new T[size]; wbBuf = new T[size]; @@ -243,6 +249,21 @@ class IGbE : public EtherDevice } void writeback(Addr aMask) + { + if (wbOut) { + if (aMask < wbAlignment) { + moreToWb = true; + wbAlignment = aMask; + } + return; + } + + wbAlignment = aMask; + if (!wbDelayEvent.scheduled()) + wbDelayEvent.schedule(igbe->wbDelay + curTick); + } + + void writeback1() { int curHead = descHead(); int max_to_wb = usedCache.size(); @@ -252,26 +273,13 @@ class IGbE : public EtherDevice curHead, descTail(), descLen(), cachePnt, max_to_wb, descLeft()); - // Check if this writeback is less restrictive that the previous - // and if so setup another one immediately following it - if (wbOut && (aMask < wbAlignment)) { - moreToWb = true; - wbAlignment = aMask; - DPRINTF(EthernetDesc, "Writing back already in process, returning\n"); - return; - } - - - moreToWb = false; - wbAlignment = aMask; - if (max_to_wb + curHead >= descLen()) { max_to_wb = descLen() - curHead; moreToWb = true; // this is by definition aligned correctly - } else if (aMask != 0) { + } else if (wbAlignment != 0) { // align the wb point to the mask - max_to_wb = max_to_wb & ~aMask; + max_to_wb = max_to_wb & ~wbAlignment; } DPRINTF(EthernetDesc, "Writing back %d descriptors\n", max_to_wb); @@ -291,13 +299,22 @@ class IGbE : public EtherDevice assert(wbOut); igbe->dmaWrite(igbe->platform->pciToDma(descBase() + curHead * sizeof(T)), - wbOut * sizeof(T), &wbEvent, (uint8_t*)wbBuf); + wbOut * sizeof(T), &wbEvent, (uint8_t*)wbBuf, + igbe->wbCompDelay); } + EventWrapper wbDelayEvent; /** Fetch a chunk of descriptors into the descriptor cache. * Calls fetchComplete when the memory system returns the data */ + void fetchDescriptors() + { + if (!fetchDelayEvent.scheduled()) + fetchDelayEvent.schedule(igbe->fetchDelay + curTick); + } + + void fetchDescriptors1() { size_t max_to_fetch; @@ -331,9 +348,11 @@ class IGbE : public EtherDevice curFetching * sizeof(T)); assert(curFetching); igbe->dmaRead(igbe->platform->pciToDma(descBase() + cachePnt * sizeof(T)), - curFetching * sizeof(T), &fetchEvent, (uint8_t*)fetchBuf); + curFetching * sizeof(T), &fetchEvent, (uint8_t*)fetchBuf, + igbe->fetchCompDelay); } + EventWrapper fetchDelayEvent; /** Called by event when dma to read descriptors is completed */ @@ -391,6 +410,7 @@ class IGbE : public EtherDevice // If we still have more to wb, call wb now intAfterWb(); if (moreToWb) { + moreToWb = false; DPRINTF(EthernetDesc, "Writeback has more todo\n"); writeback(wbAlignment); } @@ -463,6 +483,16 @@ class IGbE : public EtherDevice arrayParamOut(os, csprintf("unusedCache_%d", x), (uint8_t*)unusedCache[x],sizeof(T)); } + + Tick fetch_delay = 0, wb_delay = 0; + if (fetchDelayEvent.scheduled()) + fetch_delay = fetchDelayEvent.when(); + SERIALIZE_SCALAR(fetch_delay); + if (wbDelayEvent.scheduled()) + wb_delay = wbDelayEvent.when(); + SERIALIZE_SCALAR(wb_delay); + + } virtual void unserialize(Checkpoint *cp, const std::string §ion) @@ -491,6 +521,15 @@ class IGbE : public EtherDevice (uint8_t*)temp,sizeof(T)); unusedCache.push_back(temp); } + Tick fetch_delay = 0, wb_delay = 0; + UNSERIALIZE_SCALAR(fetch_delay); + UNSERIALIZE_SCALAR(wb_delay); + if (fetch_delay) + fetchDelayEvent.schedule(fetch_delay); + if (wb_delay) + wbDelayEvent.schedule(wb_delay); + + } virtual bool hasOutstandingEvents() { return wbEvent.scheduled() || fetchEvent.scheduled(); -- cgit v1.2.3 From 8d018aef0f9de7129a77172a4164f36b2b093be6 Mon Sep 17 00:00:00 2001 From: Richard Strong Date: Mon, 18 Aug 2008 10:50:58 -0700 Subject: Changed BaseCPU::ProfileEvent's interval member to be of type Tick. This was done to be consistent with its python type of a latency. In addition, the multiple definitions of profile in the different cpu models caused problems for intialization of the interval value. If a child class's profile value was defined, the parent BaseCPU::ProfileEvent interval field would be initialized with a garbage value. The fix was to remove the multiple redifitions of profile in the child CPU classes. --- src/cpu/CheckerCPU.py | 2 -- src/cpu/base.cc | 2 +- src/cpu/base.hh | 4 ++-- src/cpu/o3/O3Checker.py | 2 -- src/cpu/ozone/OzoneCPU.py | 2 -- src/cpu/ozone/OzoneChecker.py | 2 -- src/cpu/simple/AtomicSimpleCPU.py | 2 -- src/cpu/simple/TimingSimpleCPU.py | 2 -- 8 files changed, 3 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/cpu/CheckerCPU.py b/src/cpu/CheckerCPU.py index 06df9c1b1..bff9af62d 100644 --- a/src/cpu/CheckerCPU.py +++ b/src/cpu/CheckerCPU.py @@ -40,5 +40,3 @@ class CheckerCPU(BaseCPU): "If a load result is incorrect, only print a warning and do not exit") function_trace = Param.Bool(False, "Enable function trace") function_trace_start = Param.Tick(0, "Cycle to start function trace") - if build_env['FULL_SYSTEM']: - profile = Param.Latency('0ns', "trace the kernel stack") diff --git a/src/cpu/base.cc b/src/cpu/base.cc index f79b79350..7b6404419 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -357,7 +357,7 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc) #if FULL_SYSTEM -BaseCPU::ProfileEvent::ProfileEvent(BaseCPU *_cpu, int _interval) +BaseCPU::ProfileEvent::ProfileEvent(BaseCPU *_cpu, Tick _interval) : Event(&mainEventQueue), cpu(_cpu), interval(_interval) { } diff --git a/src/cpu/base.hh b/src/cpu/base.hh index 6e9e1dc39..251adc1b7 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -122,10 +122,10 @@ class BaseCPU : public MemObject { private: BaseCPU *cpu; - int interval; + Tick interval; public: - ProfileEvent(BaseCPU *cpu, int interval); + ProfileEvent(BaseCPU *cpu, Tick interval); void process(); }; ProfileEvent *profileEvent; diff --git a/src/cpu/o3/O3Checker.py b/src/cpu/o3/O3Checker.py index 43a71d67b..edc6dc9b6 100644 --- a/src/cpu/o3/O3Checker.py +++ b/src/cpu/o3/O3Checker.py @@ -39,5 +39,3 @@ class O3Checker(BaseCPU): "If a load result is incorrect, only print a warning and do not exit") function_trace = Param.Bool(False, "Enable function trace") function_trace_start = Param.Tick(0, "Cycle to start function trace") - if build_env['FULL_SYSTEM']: - profile = Param.Latency('0ns', "trace the kernel stack") diff --git a/src/cpu/ozone/OzoneCPU.py b/src/cpu/ozone/OzoneCPU.py index b9cfb448f..37386898d 100644 --- a/src/cpu/ozone/OzoneCPU.py +++ b/src/cpu/ozone/OzoneCPU.py @@ -40,8 +40,6 @@ class DerivOzoneCPU(BaseCPU): if build_env['USE_CHECKER']: checker = Param.BaseCPU("Checker CPU") - if build_env['FULL_SYSTEM']: - profile = Param.Latency('0ns', "trace the kernel stack") icache_port = Port("Instruction Port") dcache_port = Port("Data Port") diff --git a/src/cpu/ozone/OzoneChecker.py b/src/cpu/ozone/OzoneChecker.py index f20b8770e..bfa39ead9 100644 --- a/src/cpu/ozone/OzoneChecker.py +++ b/src/cpu/ozone/OzoneChecker.py @@ -39,5 +39,3 @@ class OzoneChecker(BaseCPU): "If a load result is incorrect, only print a warning and do not exit") function_trace = Param.Bool(False, "Enable function trace") function_trace_start = Param.Tick(0, "Cycle to start function trace") - if build_env['FULL_SYSTEM']: - profile = Param.Latency('0ns', "trace the kernel stack") diff --git a/src/cpu/simple/AtomicSimpleCPU.py b/src/cpu/simple/AtomicSimpleCPU.py index e1c1e4cd1..87e8b5509 100644 --- a/src/cpu/simple/AtomicSimpleCPU.py +++ b/src/cpu/simple/AtomicSimpleCPU.py @@ -37,8 +37,6 @@ class AtomicSimpleCPU(BaseSimpleCPU): simulate_inst_stalls = Param.Bool(False, "Simulate icache stall cycles") function_trace = Param.Bool(False, "Enable function trace") function_trace_start = Param.Tick(0, "Cycle to start function trace") - if build_env['FULL_SYSTEM']: - profile = Param.Latency('0ns', "trace the kernel stack") icache_port = Port("Instruction Port") dcache_port = Port("Data Port") physmem_port = Port("Physical Memory Port") diff --git a/src/cpu/simple/TimingSimpleCPU.py b/src/cpu/simple/TimingSimpleCPU.py index f2b14a175..b7f044bfa 100644 --- a/src/cpu/simple/TimingSimpleCPU.py +++ b/src/cpu/simple/TimingSimpleCPU.py @@ -34,8 +34,6 @@ class TimingSimpleCPU(BaseSimpleCPU): type = 'TimingSimpleCPU' function_trace = Param.Bool(False, "Enable function trace") function_trace_start = Param.Tick(0, "Cycle to start function trace") - if build_env['FULL_SYSTEM']: - profile = Param.Latency('0ns', "trace the kernel stack") icache_port = Port("Instruction Port") dcache_port = Port("Data Port") _mem_ports = BaseSimpleCPU._mem_ports + ['icache_port', 'dcache_port'] -- cgit v1.2.3 From 3633a916c299a1f5df9f6d34a0215cdae68a3e93 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 19 Aug 2008 21:59:09 -0700 Subject: CPU: Get rid of two more duplicated CPU params. --- src/cpu/simple/AtomicSimpleCPU.py | 2 -- src/cpu/simple/TimingSimpleCPU.py | 2 -- 2 files changed, 4 deletions(-) (limited to 'src') diff --git a/src/cpu/simple/AtomicSimpleCPU.py b/src/cpu/simple/AtomicSimpleCPU.py index 87e8b5509..b7174bb43 100644 --- a/src/cpu/simple/AtomicSimpleCPU.py +++ b/src/cpu/simple/AtomicSimpleCPU.py @@ -35,8 +35,6 @@ 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") - function_trace = Param.Bool(False, "Enable function trace") - function_trace_start = Param.Tick(0, "Cycle to start function trace") icache_port = Port("Instruction Port") dcache_port = Port("Data Port") physmem_port = Port("Physical Memory Port") diff --git a/src/cpu/simple/TimingSimpleCPU.py b/src/cpu/simple/TimingSimpleCPU.py index b7f044bfa..ce6839241 100644 --- a/src/cpu/simple/TimingSimpleCPU.py +++ b/src/cpu/simple/TimingSimpleCPU.py @@ -32,8 +32,6 @@ from BaseSimpleCPU import BaseSimpleCPU class TimingSimpleCPU(BaseSimpleCPU): type = 'TimingSimpleCPU' - function_trace = Param.Bool(False, "Enable function trace") - function_trace_start = Param.Tick(0, "Cycle to start function trace") icache_port = Port("Instruction Port") dcache_port = Port("Data Port") _mem_ports = BaseSimpleCPU._mem_ports + ['icache_port', 'dcache_port'] -- cgit v1.2.3 From 3d5fe0c372a16f9178b348080c1c1bb24dd1d834 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Sun, 24 Aug 2008 15:27:49 -0400 Subject: IGbE: Patches I neglected to apply before pushing the previous igbe changeset --- src/dev/i8254xGBe.cc | 4 +++ src/dev/i8254xGBe.hh | 76 +++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 58 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/dev/i8254xGBe.cc b/src/dev/i8254xGBe.cc index ca60d2e7d..f362a7a0a 100644 --- a/src/dev/i8254xGBe.cc +++ b/src/dev/i8254xGBe.cc @@ -587,6 +587,8 @@ IGbE::postInterrupt(IntTypes t, bool now) regs.icr = regs.icr() | t; Tick itr_interval = Clock::Int::ns * 256 * regs.itr.interval(); + DPRINTF(EthernetIntr, "EINT: postInterrupt() curTick: %d itr: %d interval: %d\n", + curTick, regs.itr.interval(), itr_interval); if (regs.itr.interval() == 0 || now || lastInterrupt + itr_interval <= curTick) { if (interEvent.scheduled()) { @@ -652,6 +654,7 @@ IGbE::cpuPostInt() intrPost(); + lastInterrupt = curTick; } void @@ -1404,6 +1407,7 @@ IGbE::txWire() txBytes += txFifo.front()->length; txPackets++; + txFifoTick = false; txFifo.pop(); } else { diff --git a/src/dev/i8254xGBe.hh b/src/dev/i8254xGBe.hh index 66a93a509..4c3896e36 100644 --- a/src/dev/i8254xGBe.hh +++ b/src/dev/i8254xGBe.hh @@ -133,6 +133,8 @@ class IGbE : public EtherDevice EventWrapper tickEvent; + uint64_t macAddr; + void rxStateMachine(); void txStateMachine(); void txWire(); @@ -250,23 +252,23 @@ class IGbE : public EtherDevice void writeback(Addr aMask) { + int curHead = descHead(); + int max_to_wb = usedCache.size(); + + // Check if this writeback is less restrictive that the previous + // and if so setup another one immediately following it if (wbOut) { if (aMask < wbAlignment) { moreToWb = true; wbAlignment = aMask; } + DPRINTF(EthernetDesc, "Writing back already in process, returning\n"); return; } + moreToWb = false; wbAlignment = aMask; - if (!wbDelayEvent.scheduled()) - wbDelayEvent.schedule(igbe->wbDelay + curTick); - } - - void writeback1() - { - int curHead = descHead(); - int max_to_wb = usedCache.size(); + DPRINTF(EthernetDesc, "Writing back descriptors head: %d tail: " "%d len: %d cachePnt: %d max_to_wb: %d descleft: %d\n", @@ -284,21 +286,35 @@ class IGbE : public EtherDevice DPRINTF(EthernetDesc, "Writing back %d descriptors\n", max_to_wb); - if (max_to_wb <= 0 || wbOut) + if (max_to_wb <= 0) { return; + } wbOut = max_to_wb; + assert(!wbDelayEvent.scheduled()); + wbDelayEvent.schedule(igbe->wbDelay + curTick); + } + + void writeback1() + { + // If we're draining delay issuing this DMA + if (igbe->drainEvent) { + wbDelayEvent.schedule(igbe->wbDelay + curTick); + return; + } + + DPRINTF(EthernetDesc, "Beining DMA of %d descriptors\n", wbOut); + for (int x = 0; x < wbOut; x++) { assert(usedCache.size()); - memcpy(&wbBuf[x], usedCache[0], sizeof(T)); - delete usedCache[0]; - usedCache.pop_front(); + memcpy(&wbBuf[x], usedCache[x], sizeof(T)); + //delete usedCache[0]; + //usedCache.pop_front(); } - assert(wbOut); - igbe->dmaWrite(igbe->platform->pciToDma(descBase() + curHead * sizeof(T)), + igbe->dmaWrite(igbe->platform->pciToDma(descBase() + descHead() * sizeof(T)), wbOut * sizeof(T), &wbEvent, (uint8_t*)wbBuf, igbe->wbCompDelay); } @@ -309,17 +325,13 @@ class IGbE : public EtherDevice */ void fetchDescriptors() - { - if (!fetchDelayEvent.scheduled()) - fetchDelayEvent.schedule(igbe->fetchDelay + curTick); - } - - void fetchDescriptors1() { size_t max_to_fetch; - if (curFetching) + if (curFetching) { + DPRINTF(EthernetDesc, "Currently fetching %d descriptors, returning\n", curFetching); return; + } if (descTail() >= cachePnt) max_to_fetch = descTail() - cachePnt; @@ -329,6 +341,7 @@ class IGbE : public EtherDevice size_t free_cache = size - usedCache.size() - unusedCache.size(); max_to_fetch = std::min(max_to_fetch, free_cache); + DPRINTF(EthernetDesc, "Fetching descriptors head: %d tail: " "%d len: %d cachePnt: %d max_to_fetch: %d descleft: %d\n", @@ -338,10 +351,22 @@ class IGbE : public EtherDevice // Nothing to do if (max_to_fetch == 0) return; - + // So we don't have two descriptor fetches going on at once curFetching = max_to_fetch; + assert(!fetchDelayEvent.scheduled()); + fetchDelayEvent.schedule(igbe->fetchDelay + curTick); + } + + void fetchDescriptors1() + { + // If we're draining delay issuing this DMA + if (igbe->drainEvent) { + fetchDelayEvent.schedule(igbe->fetchDelay + curTick); + return; + } + DPRINTF(EthernetDesc, "Fetching descriptors at %#x (%#x), size: %#x\n", descBase() + cachePnt * sizeof(T), igbe->platform->pciToDma(descBase() + cachePnt * sizeof(T)), @@ -365,6 +390,7 @@ class IGbE : public EtherDevice unusedCache.push_back(newDesc); } + #ifndef NDEBUG int oldCp = cachePnt; #endif @@ -394,6 +420,12 @@ class IGbE : public EtherDevice #ifndef NDEBUG long oldHead = curHead; #endif + + for (int x = 0; x < wbOut; x++) { + assert(usedCache.size()); + delete usedCache[0]; + usedCache.pop_front(); + } curHead += wbOut; wbOut = 0; -- cgit v1.2.3 From 4aa017affc53b3b730219d3b617f0e237c57debc Mon Sep 17 00:00:00 2001 From: Clint Smullen Date: Tue, 26 Aug 2008 02:37:26 -0400 Subject: Device: Fix bug in DmaPort::recvRetry. The interface attempts to send the same packet again. It doesn't cause a problem currently, however with a different Memory Object it could cause problems --- src/dev/io_device.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/dev/io_device.cc b/src/dev/io_device.cc index b86a2d313..41fcec8ac 100644 --- a/src/dev/io_device.cc +++ b/src/dev/io_device.cc @@ -190,9 +190,9 @@ void DmaPort::recvRetry() { assert(transmitList.size()); - PacketPtr pkt = transmitList.front(); bool result = true; do { + PacketPtr pkt = transmitList.front(); DPRINTF(DMA, "Retry on %s addr %#x\n", pkt->cmdString(), pkt->getAddr()); result = sendTiming(pkt); -- cgit v1.2.3 From 30bc897613a1ee36ed887eb9da1579bd9828186e Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 3 Sep 2008 00:52:54 -0400 Subject: X86: Fix the microcode for sign/zero extending moves that use high byte registers. --- src/arch/x86/isa/insts/general_purpose/data_transfer/move.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py index d9a83dfde..35f0436f5 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py +++ b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py @@ -126,7 +126,8 @@ def macroop MOVSXD_R_P { }; def macroop MOVSX_B_R_R { - sexti reg, regm, 7 + mov t1, t1, regm, dataSize=1 + sexti reg, t1, 7 }; def macroop MOVSX_B_R_M { @@ -160,7 +161,8 @@ def macroop MOVSX_W_R_P { # def macroop MOVZX_B_R_R { - zexti reg, regm, 7 + mov t1, t1, regm, dataSize=1 + zexti reg, t1, 7 }; def macroop MOVZX_B_R_M { -- cgit v1.2.3 From 496d3f2789e53a0a394095f741e593491db0453d Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 8 Sep 2008 18:03:52 -0700 Subject: style: This file hugely violated the M5 style. Remove a bunch of unused cruft from the interface while we're at it --- src/base/loader/hex_file.cc | 161 +++++++++++++++++++------------------------- src/base/loader/hex_file.hh | 35 +++------- 2 files changed, 76 insertions(+), 120 deletions(-) (limited to 'src') diff --git a/src/base/loader/hex_file.cc b/src/base/loader/hex_file.cc index 1855ebe0c..17347531e 100755 --- a/src/base/loader/hex_file.cc +++ b/src/base/loader/hex_file.cc @@ -28,134 +28,109 @@ * Authors: Jaidev Patwardhan */ +#include +#include #include #include -#include -#include -#include -#include -#include - #include "base/cprintf.hh" #include "base/loader/hex_file.hh" #include "base/loader/symtab.hh" - - #include "mem/translating_port.hh" using namespace std; -/* Load a Hex File into memory. - Currently only used with MIPS BARE_IRON mode. - A hex file consists of [Address Data] tuples that get directly loaded into - physical memory. The address specified is a word address (i.e., to get the byte address, shift left by 2) - The data is a full 32-bit hex value. +/* + * Load a Hex File into memory. Currently only used with MIPS + * BARE_IRON mode. A hex file consists of [Address Data] tuples that + * get directly loaded into physical memory. The address specified is + * a word address (i.e., to get the byte address, shift left by 2) The + * data is a full 32-bit hex value. */ HexFile::HexFile(const string _filename) : filename(_filename) { - fp = fopen(filename.c_str(),"r"); - if(fp == NULL) - { - panic("Unable to open %s\n",filename.c_str()); - } - + fp = fopen(filename.c_str(), "r"); + if (fp == NULL) + panic("Unable to open %s\n", filename.c_str()); } HexFile::~HexFile() { } - bool -HexFile::loadSections(Port *memPort, Addr addrMask) +HexFile::loadSections(Port *memPort) { - char Line[64]; - Addr MemAddr; - uint32_t Data; - while(!feof(fp)) - { - fgets(Line,64,fp); - parseLine(Line,&MemAddr,&Data); - // printf("Hex:%u\n",Data); - - if(MemAddr != 0) - { - // Now, write to memory - memPort->writeBlob(MemAddr<<2,(uint8_t *)&Data,sizeof(Data)); + char Line[64]; + Addr MemAddr; + uint32_t Data; + while (!feof(fp)) { + fgets(Line, 64, fp); + parseLine(Line, &MemAddr, &Data); + if (MemAddr != 0) { + // Now, write to memory + memPort->writeBlob(MemAddr << 2, (uint8_t *)&Data, sizeof(Data)); } } return true; } -void HexFile::parseLine(char *Str,Addr *A, uint32_t *D) -{ - int i=0; - bool Flag = false; - *A = 0; - *D = 0; - int Digit = 0; - unsigned Number = 0; - /* Skip white spaces */ - while(Str[i] != '\0' && Str[i]==' ') - i++; - /* Ok, we're at some character...process things */ - while(Str[i] != '\0') - { - if(Str[i]>='0' && Str[i]<='9') - { - Digit=Str[i]-'0'; - } - else if(Str[i]>='a' && Str[i]<='f') - { - Digit=Str[i]-'a'+10; - } - else if(Str[i]>='A' && Str[i]<='F') - { +void +HexFile::parseLine(char *Str, Addr *A, uint32_t *D) +{ + int i = 0; + bool Flag = false; + *A = 0; + *D = 0; + int Digit = 0; + unsigned Number = 0; + + /* Skip white spaces */ + while (Str[i] != '\0' && Str[i]==' ') + i++; + + /* Ok, we're at some character...process things */ + while (Str[i] != '\0') { + if (Str[i] >= '0' && Str[i] <= '9') { + Digit = Str[i] - '0'; + } else if (Str[i] >= 'a' && Str[i] <= 'f') { + Digit = Str[i] - 'a' + 10; + } else if (Str[i] >= 'A' && Str[i] <= 'F') { Digit=Str[i]-'A'+10; - } - else if(Str[i] == ' ' || Str[i]=='\n') - { - if(Number == 0) - return; - if(Flag == false) - { - *A = Number; - Number = 0; - Flag = true; - } - else - { - *D = Number; - return; + } else if (Str[i] == ' ' || Str[i] == '\n') { + if (Number == 0) + return; + if (Flag == false) { + *A = Number; + Number = 0; + Flag = true; + } else { + *D = Number; + return; } + } else { + // Ok, we've encountered a non-hex character, cannot be a + // valid line, skip and return 0's + *A = 0; + *D = 0; + return; } - else - { - // Ok, we've encountered a non-hex character, cannot be a valid line, skip and return 0's - *A = 0; - *D = 0; - return; - } - Number<<=4; - Number+=Digit; - i++; + Number <<= 4; + Number += Digit; + i++; } - if(Flag != true) - { - *A = 0; - *D = 0; - } - else - *D = Number; + if (Flag != true) { + *A = 0; + *D = 0; + } else { + *D = Number; + } } - - void HexFile::close() { - fclose(fp); + fclose(fp); } diff --git a/src/base/loader/hex_file.hh b/src/base/loader/hex_file.hh index 1dbfd034f..3c0a2d1b8 100755 --- a/src/base/loader/hex_file.hh +++ b/src/base/loader/hex_file.hh @@ -28,50 +28,31 @@ * Authors: Jaidev Patwardhan */ -#ifndef __HEX_FILE_HH__ -#define __HEX_FILE_HH__ +#ifndef __BASE_LOADER_HEX_FILE_HH__ +#define __BASE_LOADER_HEX_FILE_HH__ +#include #include #include #include "sim/host.hh" // for Addr -#include class Port; class HexFile { - public: - - protected: const std::string filename; FILE *fp; + void parseLine(char *, Addr *, uint32_t *); + public: - virtual ~HexFile(); HexFile(const std::string _filename); + virtual ~HexFile(); void close(); - - bool loadSections(Port *memPort, Addr addrMask = - std::numeric_limits::max()); - - protected: - - typedef struct { - Addr MemAddr; - uint32_t Data; - } HexLine; - - Addr entry; - Addr globalPtr; - - public: - void parseLine(char *,Addr *,uint32_t *); - Addr entryPoint() const { return entry; } - Addr globalPointer() const { return globalPtr; } - + bool loadSections(Port *memPort); }; -#endif // __HEX_FILE_HH__ +#endif // __BASE_LOADER_HEX_FILE_HH__ -- cgit v1.2.3 From 09a8fb0b5263d4b41b8206ce075a3f6923907d65 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Tue, 9 Sep 2008 16:27:17 -0700 Subject: style: this file did not conform to style --- src/arch/mips/regfile/int_regfile.cc | 44 ++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/arch/mips/regfile/int_regfile.cc b/src/arch/mips/regfile/int_regfile.cc index c46ecf0b3..4ffbcdfb8 100644 --- a/src/arch/mips/regfile/int_regfile.cc +++ b/src/arch/mips/regfile/int_regfile.cc @@ -37,7 +37,6 @@ using namespace MipsISA; using namespace std; - void IntRegFile::clear() { @@ -48,25 +47,27 @@ IntRegFile::clear() void IntRegFile::setShadowSet(int css) { - DPRINTF(MipsPRA,"Setting Shadow Set to :%d (%s)\n",css,currShadowSet); + DPRINTF(MipsPRA, "Setting Shadow Set to :%d (%s)\n", css, currShadowSet); currShadowSet = css; } IntReg IntRegFile::readReg(int intReg) { - if(intReg < NumIntRegs) - { // Regular GPR Read - DPRINTF(MipsPRA,"Reading Reg: %d, CurrShadowSet: %d\n",intReg,currShadowSet); - if(intReg >= NumIntArchRegs*NumShadowRegSets){ - return regs[intReg+NumIntRegs*currShadowSet]; - } - else { - return regs[(intReg + NumIntArchRegs*currShadowSet) % NumIntArchRegs]; + if (intReg < NumIntRegs) { + // Regular GPR Read + DPRINTF(MipsPRA, "Reading Reg: %d, CurrShadowSet: %d\n", intReg, + currShadowSet); + + if (intReg >= NumIntArchRegs * NumShadowRegSets) { + return regs[intReg + NumIntRegs * currShadowSet]; + } else { + int index = intReg + NumIntArchRegs * currShadowSet; + index = index % NumIntArchRegs; + return regs[index]; } - } - else - { // Read from shadow GPR .. probably called by RDPGPR + } else { + // Read from shadow GPR .. probably called by RDPGPR return regs[intReg]; } } @@ -75,20 +76,16 @@ Fault IntRegFile::setReg(int intReg, const IntReg &val) { if (intReg != ZeroReg) { - - if(intReg < NumIntRegs) - { - if(intReg >= NumIntArchRegs*NumShadowRegSets){ + if (intReg < NumIntRegs) { + if (intReg >= NumIntArchRegs * NumShadowRegSets) regs[intReg] = val; - } - else{ - regs[intReg+NumIntRegs*currShadowSet] = val; - } - } - else{ + else + regs[intReg + NumIntRegs * currShadowSet] = val; + } else { regs[intReg] = val; } } + return NoFault; } @@ -103,4 +100,3 @@ IntRegFile::unserialize(Checkpoint *cp, const std::string §ion) { UNSERIALIZE_ARRAY(regs, NumIntRegs); } - -- cgit v1.2.3 From 3a3e356f4e61e86f6f1427dd85cf1e41fa9125c0 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Wed, 10 Sep 2008 14:26:15 -0400 Subject: style: Remove non-leading tabs everywhere they shouldn't be. Developers should configure their editors to not insert tabs --- src/arch/alpha/aout_machdep.h | 42 +- src/arch/alpha/ev5.cc | 2 +- src/arch/alpha/floatregfile.hh | 4 +- src/arch/alpha/ipr.cc | 144 ++-- src/arch/alpha/ipr.hh | 152 ++-- src/arch/alpha/isa_traits.hh | 14 +- src/arch/alpha/linux/linux.cc | 40 +- src/arch/alpha/linux/linux.hh | 30 +- src/arch/alpha/miscregfile.hh | 10 +- src/arch/alpha/osfpal.cc | 512 +++++++------- src/arch/alpha/pagetable.hh | 18 +- src/arch/alpha/regfile.hh | 12 +- src/arch/alpha/remote_gdb.cc | 26 +- src/arch/alpha/system.cc | 6 +- src/arch/alpha/tlb.cc | 2 +- src/arch/alpha/tru64/process.cc | 10 +- src/arch/alpha/tru64/tru64.cc | 40 +- src/arch/alpha/tru64/tru64.hh | 40 +- src/arch/isa_parser.py | 10 +- src/arch/isa_specific.hh | 2 +- src/arch/mips/isa_traits.hh | 10 +- src/arch/mips/linux/linux.cc | 40 +- src/arch/mips/linux/linux.hh | 40 +- src/arch/mips/regfile/regfile.hh | 12 +- src/arch/mips/system.cc | 6 +- src/arch/mips/tlb.cc | 32 +- src/arch/mips/tlb.hh | 8 +- src/arch/sparc/isa_traits.hh | 2 +- src/arch/sparc/linux/linux.cc | 40 +- src/arch/sparc/linux/linux.hh | 30 +- src/arch/sparc/miscregfile.hh | 56 +- src/arch/sparc/regfile.hh | 10 +- src/arch/sparc/remote_gdb.cc | 26 +- src/arch/sparc/solaris/solaris.cc | 52 +- src/arch/sparc/solaris/solaris.hh | 20 +- src/arch/sparc/sparc_traits.hh | 4 +- .../general_purpose/cache_and_memory_management.py | 14 +- .../insts/general_purpose/control_transfer/call.py | 2 +- .../control_transfer/interrupts_and_exceptions.py | 4 +- .../data_conversion/ascii_adjust.py | 8 +- .../general_purpose/data_conversion/bcd_adjust.py | 4 +- .../data_conversion/endian_conversion.py | 2 +- .../data_conversion/extract_sign_mask.py | 4 +- .../insts/general_purpose/data_transfer/move.py | 4 +- .../general_purpose/load_segment_registers.py | 14 +- .../x86/isa/insts/general_purpose/semaphores.py | 4 +- .../x86/isa/insts/general_purpose/system_calls.py | 8 +- src/arch/x86/linux/linux.hh | 30 +- src/arch/x86/remote_gdb.cc | 16 +- src/base/bitunion.hh | 2 +- src/base/crc.cc | 6 +- src/base/fast_alloc.cc | 2 +- src/base/fast_alloc.hh | 10 +- src/base/inifile.hh | 8 +- src/base/loader/aout_object.cc | 2 +- src/base/loader/coff_sym.h | 354 +++++----- src/base/loader/coff_symconst.h | 220 +++--- src/base/loader/ecoff_object.cc | 2 +- src/base/loader/elf_object.cc | 2 +- src/base/loader/hex_file.hh | 2 +- src/base/loader/object_file.hh | 2 +- src/base/loader/symtab.hh | 2 +- src/base/remote_gdb.cc | 16 +- src/base/res_list.hh | 2 +- src/base/stats/flags.hh | 22 +- src/base/stats/mysql.cc | 6 +- src/base/time.hh | 4 +- src/base/trace.hh | 2 +- src/cpu/base_dyn_inst.hh | 30 +- src/cpu/checker/cpu.hh | 2 +- src/cpu/checker/cpu_impl.hh | 4 +- src/cpu/memtest/memtest.hh | 14 +- src/cpu/o3/alpha/dyn_inst.hh | 4 +- src/cpu/o3/mips/dyn_inst.hh | 4 +- src/cpu/o3/regfile.hh | 2 +- src/cpu/ozone/back_end.hh | 10 +- src/cpu/ozone/cpu_impl.hh | 2 +- src/cpu/ozone/front_end.hh | 2 +- src/cpu/ozone/inorder_back_end.hh | 10 +- src/cpu/ozone/lsq_unit_impl.hh | 2 +- src/cpu/ozone/lw_back_end.hh | 2 +- src/cpu/simple/base.hh | 2 +- src/cpu/simple_thread.cc | 4 +- src/cpu/simple_thread.hh | 2 +- src/cpu/static_inst.hh | 78 +-- src/dev/alpha/access.h | 34 +- src/dev/etherdump.cc | 20 +- src/dev/mips/access.h | 34 +- src/dev/ns_gige.hh | 8 +- src/dev/pcidev.cc | 2 +- src/dev/pcireg.h | 120 ++-- src/dev/sinicreg.hh | 2 +- src/kern/linux/linux.hh | 122 ++-- src/kern/operatingsystem.hh | 54 +- src/kern/solaris/solaris.hh | 62 +- src/kern/tru64/mbuf.hh | 78 +-- src/kern/tru64/tru64.hh | 274 ++++---- src/kern/tru64/tru64_syscalls.cc | 768 ++++++++++----------- src/mem/cache/blk.hh | 20 +- src/mem/cache/builder.cc | 74 +- src/mem/cache/prefetch/stride.cc | 4 +- src/mem/cache/prefetch/stride.hh | 2 +- src/mem/cache/tags/iic.cc | 2 +- src/mem/cache/tags/lru.cc | 4 +- src/mem/cache/tags/lru.hh | 2 +- src/mem/cache/tags/split_lru.cc | 4 +- src/mem/dram.cc | 20 +- src/mem/physical.hh | 6 +- src/mem/request.hh | 14 +- src/python/m5/SimObject.py | 4 +- src/sim/async.hh | 12 +- src/sim/debug.cc | 2 +- src/sim/eventq.hh | 28 +- src/sim/host.hh | 4 +- src/sim/insttracer.hh | 4 +- src/sim/process.hh | 14 +- src/sim/serialize.cc | 32 +- src/sim/serialize.hh | 36 +- src/sim/sim_events.hh | 16 +- src/sim/syscall_emul.cc | 6 +- src/sim/syscall_emul.hh | 24 +- 121 files changed, 2185 insertions(+), 2185 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/aout_machdep.h b/src/arch/alpha/aout_machdep.h index 58991256a..bcf004d05 100644 --- a/src/arch/alpha/aout_machdep.h +++ b/src/arch/alpha/aout_machdep.h @@ -36,35 +36,35 @@ /// Funky Alpha 64-bit a.out header used for PAL code. /// struct aout_exechdr { - uint16_t magic; ///< magic number - uint16_t vstamp; ///< version stamp? - uint16_t bldrev; ///< ??? - uint16_t padcell; ///< padding - uint64_t tsize; ///< text segment size - uint64_t dsize; ///< data segment size - uint64_t bsize; ///< bss segment size - uint64_t entry; ///< entry point - uint64_t text_start; ///< text base address - uint64_t data_start; ///< data base address - uint64_t bss_start; ///< bss base address - uint32_t gprmask; ///< GPR mask (unused, AFAIK) - uint32_t fprmask; ///< FPR mask (unused, AFAIK) - uint64_t gp_value; ///< global pointer reg value + uint16_t magic; ///< magic number + uint16_t vstamp; ///< version stamp? + uint16_t bldrev; ///< ??? + uint16_t padcell; ///< padding + uint64_t tsize; ///< text segment size + uint64_t dsize; ///< data segment size + uint64_t bsize; ///< bss segment size + uint64_t entry; ///< entry point + uint64_t text_start; ///< text base address + uint64_t data_start; ///< data base address + uint64_t bss_start; ///< bss base address + uint32_t gprmask; ///< GPR mask (unused, AFAIK) + uint32_t fprmask; ///< FPR mask (unused, AFAIK) + uint64_t gp_value; ///< global pointer reg value }; -#define AOUT_LDPGSZ 8192 +#define AOUT_LDPGSZ 8192 -#define N_GETMAGIC(ex) ((ex).magic) +#define N_GETMAGIC(ex) ((ex).magic) #define N_BADMAX -#define N_TXTADDR(ex) ((ex).text_start) -#define N_DATADDR(ex) ((ex).data_start) -#define N_BSSADDR(ex) ((ex).bss_start) +#define N_TXTADDR(ex) ((ex).text_start) +#define N_DATADDR(ex) ((ex).data_start) +#define N_BSSADDR(ex) ((ex).bss_start) -#define N_TXTOFF(ex) \ +#define N_TXTOFF(ex) \ (N_GETMAGIC(ex) == ZMAGIC ? 0 : sizeof(struct aout_exechdr)) -#define N_DATOFF(ex) N_ALIGN(ex, N_TXTOFF(ex) + (ex).tsize) +#define N_DATOFF(ex) N_ALIGN(ex, N_TXTOFF(ex) + (ex).tsize) #endif /* !__AOUT_MACHDEP_H__*/ diff --git a/src/arch/alpha/ev5.cc b/src/arch/alpha/ev5.cc index 5dc49623e..33306d6af 100644 --- a/src/arch/alpha/ev5.cc +++ b/src/arch/alpha/ev5.cc @@ -176,7 +176,7 @@ AlphaISA::initIPRs(ThreadContext *tc, int cpuId) AlphaISA::MiscReg AlphaISA::MiscRegFile::readIpr(int idx, ThreadContext *tc) { - uint64_t retval = 0; // return value, default 0 + uint64_t retval = 0; // return value, default 0 switch (idx) { case AlphaISA::IPR_PALtemp0: diff --git a/src/arch/alpha/floatregfile.hh b/src/arch/alpha/floatregfile.hh index 0c5fe17a7..e69e8d186 100644 --- a/src/arch/alpha/floatregfile.hh +++ b/src/arch/alpha/floatregfile.hh @@ -52,8 +52,8 @@ namespace AlphaISA public: union { - uint64_t q[NumFloatRegs]; // integer qword view - double d[NumFloatRegs]; // double-precision floating point view + uint64_t q[NumFloatRegs]; // integer qword view + double d[NumFloatRegs]; // double-precision floating point view }; void serialize(std::ostream &os); diff --git a/src/arch/alpha/ipr.cc b/src/arch/alpha/ipr.cc index 8e83102eb..a76fcc2bc 100644 --- a/src/arch/alpha/ipr.cc +++ b/src/arch/alpha/ipr.cc @@ -38,89 +38,89 @@ namespace AlphaISA md_ipr_names MiscRegIndexToIpr[NumInternalProcRegs] = { //Write only - RAW_IPR_HWINT_CLR, // H/W interrupt clear register - RAW_IPR_SL_XMIT, // serial line transmit register + RAW_IPR_HWINT_CLR, // H/W interrupt clear register + RAW_IPR_SL_XMIT, // serial line transmit register RAW_IPR_DC_FLUSH, - RAW_IPR_IC_FLUSH, // instruction cache flush control - RAW_IPR_ALT_MODE, // alternate mode register - RAW_IPR_DTB_IA, // DTLB invalidate all register - RAW_IPR_DTB_IAP, // DTLB invalidate all process register - RAW_IPR_ITB_IA, // ITLB invalidate all register - RAW_IPR_ITB_IAP, // ITLB invalidate all process register + RAW_IPR_IC_FLUSH, // instruction cache flush control + RAW_IPR_ALT_MODE, // alternate mode register + RAW_IPR_DTB_IA, // DTLB invalidate all register + RAW_IPR_DTB_IAP, // DTLB invalidate all process register + RAW_IPR_ITB_IA, // ITLB invalidate all register + RAW_IPR_ITB_IAP, // ITLB invalidate all process register //Read only - RAW_IPR_INTID, // interrupt ID register - RAW_IPR_SL_RCV, // serial line receive register - RAW_IPR_MM_STAT, // data MMU fault status register - RAW_IPR_ITB_PTE_TEMP, // ITLB page table entry temp register - RAW_IPR_DTB_PTE_TEMP, // DTLB page table entry temporary register + RAW_IPR_INTID, // interrupt ID register + RAW_IPR_SL_RCV, // serial line receive register + RAW_IPR_MM_STAT, // data MMU fault status register + RAW_IPR_ITB_PTE_TEMP, // ITLB page table entry temp register + RAW_IPR_DTB_PTE_TEMP, // DTLB page table entry temporary register - RAW_IPR_ISR, // interrupt summary register - RAW_IPR_ITB_TAG, // ITLB tag register - RAW_IPR_ITB_PTE, // ITLB page table entry register - RAW_IPR_ITB_ASN, // ITLB address space register - RAW_IPR_ITB_IS, // ITLB invalidate select register - RAW_IPR_SIRR, // software interrupt request register - RAW_IPR_ASTRR, // asynchronous system trap request register - RAW_IPR_ASTER, // asynchronous system trap enable register - RAW_IPR_EXC_ADDR, // exception address register - RAW_IPR_EXC_SUM, // exception summary register - RAW_IPR_EXC_MASK, // exception mask register - RAW_IPR_PAL_BASE, // PAL base address register - RAW_IPR_ICM, // instruction current mode - RAW_IPR_IPLR, // interrupt priority level register - RAW_IPR_IFAULT_VA_FORM, // formatted faulting virtual addr register - RAW_IPR_IVPTBR, // virtual page table base register - RAW_IPR_ICSR, // instruction control and status register - RAW_IPR_IC_PERR_STAT, // inst cache parity error status register - RAW_IPR_PMCTR, // performance counter register + RAW_IPR_ISR, // interrupt summary register + RAW_IPR_ITB_TAG, // ITLB tag register + RAW_IPR_ITB_PTE, // ITLB page table entry register + RAW_IPR_ITB_ASN, // ITLB address space register + RAW_IPR_ITB_IS, // ITLB invalidate select register + RAW_IPR_SIRR, // software interrupt request register + RAW_IPR_ASTRR, // asynchronous system trap request register + RAW_IPR_ASTER, // asynchronous system trap enable register + RAW_IPR_EXC_ADDR, // exception address register + RAW_IPR_EXC_SUM, // exception summary register + RAW_IPR_EXC_MASK, // exception mask register + RAW_IPR_PAL_BASE, // PAL base address register + RAW_IPR_ICM, // instruction current mode + RAW_IPR_IPLR, // interrupt priority level register + RAW_IPR_IFAULT_VA_FORM, // formatted faulting virtual addr register + RAW_IPR_IVPTBR, // virtual page table base register + RAW_IPR_ICSR, // instruction control and status register + RAW_IPR_IC_PERR_STAT, // inst cache parity error status register + RAW_IPR_PMCTR, // performance counter register // PAL temporary registers... // register meanings gleaned from osfpal.s source code - RAW_IPR_PALtemp0, // local scratch - RAW_IPR_PALtemp1, // local scratch - RAW_IPR_PALtemp2, // entUna - RAW_IPR_PALtemp3, // CPU specific impure area pointer - RAW_IPR_PALtemp4, // memory management temp - RAW_IPR_PALtemp5, // memory management temp - RAW_IPR_PALtemp6, // memory management temp - RAW_IPR_PALtemp7, // entIF - RAW_IPR_PALtemp8, // intmask - RAW_IPR_PALtemp9, // entSys - RAW_IPR_PALtemp10, // ?? - RAW_IPR_PALtemp11, // entInt - RAW_IPR_PALtemp12, // entArith - RAW_IPR_PALtemp13, // reserved for platform specific PAL - RAW_IPR_PALtemp14, // reserved for platform specific PAL - RAW_IPR_PALtemp15, // reserved for platform specific PAL - RAW_IPR_PALtemp16, // scratch / whami<7:0> / mces<4:0> - RAW_IPR_PALtemp17, // sysval - RAW_IPR_PALtemp18, // usp - RAW_IPR_PALtemp19, // ksp - RAW_IPR_PALtemp20, // PTBR - RAW_IPR_PALtemp21, // entMM - RAW_IPR_PALtemp22, // kgp - RAW_IPR_PALtemp23, // PCBB + RAW_IPR_PALtemp0, // local scratch + RAW_IPR_PALtemp1, // local scratch + RAW_IPR_PALtemp2, // entUna + RAW_IPR_PALtemp3, // CPU specific impure area pointer + RAW_IPR_PALtemp4, // memory management temp + RAW_IPR_PALtemp5, // memory management temp + RAW_IPR_PALtemp6, // memory management temp + RAW_IPR_PALtemp7, // entIF + RAW_IPR_PALtemp8, // intmask + RAW_IPR_PALtemp9, // entSys + RAW_IPR_PALtemp10, // ?? + RAW_IPR_PALtemp11, // entInt + RAW_IPR_PALtemp12, // entArith + RAW_IPR_PALtemp13, // reserved for platform specific PAL + RAW_IPR_PALtemp14, // reserved for platform specific PAL + RAW_IPR_PALtemp15, // reserved for platform specific PAL + RAW_IPR_PALtemp16, // scratch / whami<7:0> / mces<4:0> + RAW_IPR_PALtemp17, // sysval + RAW_IPR_PALtemp18, // usp + RAW_IPR_PALtemp19, // ksp + RAW_IPR_PALtemp20, // PTBR + RAW_IPR_PALtemp21, // entMM + RAW_IPR_PALtemp22, // kgp + RAW_IPR_PALtemp23, // PCBB - RAW_IPR_DTB_ASN, // DTLB address space number register - RAW_IPR_DTB_CM, // DTLB current mode register - RAW_IPR_DTB_TAG, // DTLB tag register - RAW_IPR_DTB_PTE, // DTLB page table entry register + RAW_IPR_DTB_ASN, // DTLB address space number register + RAW_IPR_DTB_CM, // DTLB current mode register + RAW_IPR_DTB_TAG, // DTLB tag register + RAW_IPR_DTB_PTE, // DTLB page table entry register - RAW_IPR_VA, // fault virtual address register - RAW_IPR_VA_FORM, // formatted virtual address register - RAW_IPR_MVPTBR, // MTU virtual page table base register - RAW_IPR_DTB_IS, // DTLB invalidate single register - RAW_IPR_CC, // cycle counter register - RAW_IPR_CC_CTL, // cycle counter control register - RAW_IPR_MCSR, // MTU control register + RAW_IPR_VA, // fault virtual address register + RAW_IPR_VA_FORM, // formatted virtual address register + RAW_IPR_MVPTBR, // MTU virtual page table base register + RAW_IPR_DTB_IS, // DTLB invalidate single register + RAW_IPR_CC, // cycle counter register + RAW_IPR_CC_CTL, // cycle counter control register + RAW_IPR_MCSR, // MTU control register - RAW_IPR_DC_PERR_STAT, // Dcache parity error status register - RAW_IPR_DC_TEST_CTL, // Dcache test tag control register - RAW_IPR_DC_TEST_TAG, // Dcache test tag register + RAW_IPR_DC_PERR_STAT, // Dcache parity error status register + RAW_IPR_DC_TEST_CTL, // Dcache test tag control register + RAW_IPR_DC_TEST_TAG, // Dcache test tag register RAW_IPR_DC_TEST_TAG_TEMP, // Dcache test tag temporary register - RAW_IPR_DC_MODE, // Dcache mode register - RAW_IPR_MAF_MODE // miss address file mode register + RAW_IPR_DC_MODE, // Dcache mode register + RAW_IPR_MAF_MODE // miss address file mode register }; int IprToMiscRegIndex[MaxInternalProcRegs]; diff --git a/src/arch/alpha/ipr.hh b/src/arch/alpha/ipr.hh index b55154764..6296cdb9a 100644 --- a/src/arch/alpha/ipr.hh +++ b/src/arch/alpha/ipr.hh @@ -40,88 +40,88 @@ namespace AlphaISA // enum md_ipr_names { - RAW_IPR_ISR = 0x100, // interrupt summary register - RAW_IPR_ITB_TAG = 0x101, // ITLB tag register - RAW_IPR_ITB_PTE = 0x102, // ITLB page table entry register - RAW_IPR_ITB_ASN = 0x103, // ITLB address space register - RAW_IPR_ITB_PTE_TEMP = 0x104, // ITLB page table entry temp register - RAW_IPR_ITB_IA = 0x105, // ITLB invalidate all register - RAW_IPR_ITB_IAP = 0x106, // ITLB invalidate all process register - RAW_IPR_ITB_IS = 0x107, // ITLB invalidate select register - RAW_IPR_SIRR = 0x108, // software interrupt request register - RAW_IPR_ASTRR = 0x109, // asynchronous system trap request register - RAW_IPR_ASTER = 0x10a, // asynchronous system trap enable register - RAW_IPR_EXC_ADDR = 0x10b, // exception address register - RAW_IPR_EXC_SUM = 0x10c, // exception summary register - RAW_IPR_EXC_MASK = 0x10d, // exception mask register - RAW_IPR_PAL_BASE = 0x10e, // PAL base address register - RAW_IPR_ICM = 0x10f, // instruction current mode - RAW_IPR_IPLR = 0x110, // interrupt priority level register - RAW_IPR_INTID = 0x111, // interrupt ID register - RAW_IPR_IFAULT_VA_FORM = 0x112, // formatted faulting virtual addr register - RAW_IPR_IVPTBR = 0x113, // virtual page table base register - RAW_IPR_HWINT_CLR = 0x115, // H/W interrupt clear register - RAW_IPR_SL_XMIT = 0x116, // serial line transmit register - RAW_IPR_SL_RCV = 0x117, // serial line receive register - RAW_IPR_ICSR = 0x118, // instruction control and status register - RAW_IPR_IC_FLUSH = 0x119, // instruction cache flush control - RAW_IPR_IC_PERR_STAT = 0x11a, // inst cache parity error status register - RAW_IPR_PMCTR = 0x11c, // performance counter register + RAW_IPR_ISR = 0x100, // interrupt summary register + RAW_IPR_ITB_TAG = 0x101, // ITLB tag register + RAW_IPR_ITB_PTE = 0x102, // ITLB page table entry register + RAW_IPR_ITB_ASN = 0x103, // ITLB address space register + RAW_IPR_ITB_PTE_TEMP = 0x104, // ITLB page table entry temp register + RAW_IPR_ITB_IA = 0x105, // ITLB invalidate all register + RAW_IPR_ITB_IAP = 0x106, // ITLB invalidate all process register + RAW_IPR_ITB_IS = 0x107, // ITLB invalidate select register + RAW_IPR_SIRR = 0x108, // software interrupt request register + RAW_IPR_ASTRR = 0x109, // asynchronous system trap request register + RAW_IPR_ASTER = 0x10a, // asynchronous system trap enable register + RAW_IPR_EXC_ADDR = 0x10b, // exception address register + RAW_IPR_EXC_SUM = 0x10c, // exception summary register + RAW_IPR_EXC_MASK = 0x10d, // exception mask register + RAW_IPR_PAL_BASE = 0x10e, // PAL base address register + RAW_IPR_ICM = 0x10f, // instruction current mode + RAW_IPR_IPLR = 0x110, // interrupt priority level register + RAW_IPR_INTID = 0x111, // interrupt ID register + RAW_IPR_IFAULT_VA_FORM = 0x112, // formatted faulting virtual addr register + RAW_IPR_IVPTBR = 0x113, // virtual page table base register + RAW_IPR_HWINT_CLR = 0x115, // H/W interrupt clear register + RAW_IPR_SL_XMIT = 0x116, // serial line transmit register + RAW_IPR_SL_RCV = 0x117, // serial line receive register + RAW_IPR_ICSR = 0x118, // instruction control and status register + RAW_IPR_IC_FLUSH = 0x119, // instruction cache flush control + RAW_IPR_IC_PERR_STAT = 0x11a, // inst cache parity error status register + RAW_IPR_PMCTR = 0x11c, // performance counter register // PAL temporary registers... // register meanings gleaned from osfpal.s source code - RAW_IPR_PALtemp0 = 0x140, // local scratch - RAW_IPR_PALtemp1 = 0x141, // local scratch - RAW_IPR_PALtemp2 = 0x142, // entUna - RAW_IPR_PALtemp3 = 0x143, // CPU specific impure area pointer - RAW_IPR_PALtemp4 = 0x144, // memory management temp - RAW_IPR_PALtemp5 = 0x145, // memory management temp - RAW_IPR_PALtemp6 = 0x146, // memory management temp - RAW_IPR_PALtemp7 = 0x147, // entIF - RAW_IPR_PALtemp8 = 0x148, // intmask - RAW_IPR_PALtemp9 = 0x149, // entSys - RAW_IPR_PALtemp10 = 0x14a, // ?? - RAW_IPR_PALtemp11 = 0x14b, // entInt - RAW_IPR_PALtemp12 = 0x14c, // entArith - RAW_IPR_PALtemp13 = 0x14d, // reserved for platform specific PAL - RAW_IPR_PALtemp14 = 0x14e, // reserved for platform specific PAL - RAW_IPR_PALtemp15 = 0x14f, // reserved for platform specific PAL - RAW_IPR_PALtemp16 = 0x150, // scratch / whami<7:0> / mces<4:0> - RAW_IPR_PALtemp17 = 0x151, // sysval - RAW_IPR_PALtemp18 = 0x152, // usp - RAW_IPR_PALtemp19 = 0x153, // ksp - RAW_IPR_PALtemp20 = 0x154, // PTBR - RAW_IPR_PALtemp21 = 0x155, // entMM - RAW_IPR_PALtemp22 = 0x156, // kgp - RAW_IPR_PALtemp23 = 0x157, // PCBB - - RAW_IPR_DTB_ASN = 0x200, // DTLB address space number register - RAW_IPR_DTB_CM = 0x201, // DTLB current mode register - RAW_IPR_DTB_TAG = 0x202, // DTLB tag register - RAW_IPR_DTB_PTE = 0x203, // DTLB page table entry register - RAW_IPR_DTB_PTE_TEMP = 0x204, // DTLB page table entry temporary register - - RAW_IPR_MM_STAT = 0x205, // data MMU fault status register - RAW_IPR_VA = 0x206, // fault virtual address register - RAW_IPR_VA_FORM = 0x207, // formatted virtual address register - RAW_IPR_MVPTBR = 0x208, // MTU virtual page table base register - RAW_IPR_DTB_IAP = 0x209, // DTLB invalidate all process register - RAW_IPR_DTB_IA = 0x20a, // DTLB invalidate all register - RAW_IPR_DTB_IS = 0x20b, // DTLB invalidate single register - RAW_IPR_ALT_MODE = 0x20c, // alternate mode register - RAW_IPR_CC = 0x20d, // cycle counter register - RAW_IPR_CC_CTL = 0x20e, // cycle counter control register - RAW_IPR_MCSR = 0x20f, // MTU control register + RAW_IPR_PALtemp0 = 0x140, // local scratch + RAW_IPR_PALtemp1 = 0x141, // local scratch + RAW_IPR_PALtemp2 = 0x142, // entUna + RAW_IPR_PALtemp3 = 0x143, // CPU specific impure area pointer + RAW_IPR_PALtemp4 = 0x144, // memory management temp + RAW_IPR_PALtemp5 = 0x145, // memory management temp + RAW_IPR_PALtemp6 = 0x146, // memory management temp + RAW_IPR_PALtemp7 = 0x147, // entIF + RAW_IPR_PALtemp8 = 0x148, // intmask + RAW_IPR_PALtemp9 = 0x149, // entSys + RAW_IPR_PALtemp10 = 0x14a, // ?? + RAW_IPR_PALtemp11 = 0x14b, // entInt + RAW_IPR_PALtemp12 = 0x14c, // entArith + RAW_IPR_PALtemp13 = 0x14d, // reserved for platform specific PAL + RAW_IPR_PALtemp14 = 0x14e, // reserved for platform specific PAL + RAW_IPR_PALtemp15 = 0x14f, // reserved for platform specific PAL + RAW_IPR_PALtemp16 = 0x150, // scratch / whami<7:0> / mces<4:0> + RAW_IPR_PALtemp17 = 0x151, // sysval + RAW_IPR_PALtemp18 = 0x152, // usp + RAW_IPR_PALtemp19 = 0x153, // ksp + RAW_IPR_PALtemp20 = 0x154, // PTBR + RAW_IPR_PALtemp21 = 0x155, // entMM + RAW_IPR_PALtemp22 = 0x156, // kgp + RAW_IPR_PALtemp23 = 0x157, // PCBB + + RAW_IPR_DTB_ASN = 0x200, // DTLB address space number register + RAW_IPR_DTB_CM = 0x201, // DTLB current mode register + RAW_IPR_DTB_TAG = 0x202, // DTLB tag register + RAW_IPR_DTB_PTE = 0x203, // DTLB page table entry register + RAW_IPR_DTB_PTE_TEMP = 0x204, // DTLB page table entry temporary register + + RAW_IPR_MM_STAT = 0x205, // data MMU fault status register + RAW_IPR_VA = 0x206, // fault virtual address register + RAW_IPR_VA_FORM = 0x207, // formatted virtual address register + RAW_IPR_MVPTBR = 0x208, // MTU virtual page table base register + RAW_IPR_DTB_IAP = 0x209, // DTLB invalidate all process register + RAW_IPR_DTB_IA = 0x20a, // DTLB invalidate all register + RAW_IPR_DTB_IS = 0x20b, // DTLB invalidate single register + RAW_IPR_ALT_MODE = 0x20c, // alternate mode register + RAW_IPR_CC = 0x20d, // cycle counter register + RAW_IPR_CC_CTL = 0x20e, // cycle counter control register + RAW_IPR_MCSR = 0x20f, // MTU control register RAW_IPR_DC_FLUSH = 0x210, - RAW_IPR_DC_PERR_STAT = 0x212, // Dcache parity error status register - RAW_IPR_DC_TEST_CTL = 0x213, // Dcache test tag control register - RAW_IPR_DC_TEST_TAG = 0x214, // Dcache test tag register + RAW_IPR_DC_PERR_STAT = 0x212, // Dcache parity error status register + RAW_IPR_DC_TEST_CTL = 0x213, // Dcache test tag control register + RAW_IPR_DC_TEST_TAG = 0x214, // Dcache test tag register RAW_IPR_DC_TEST_TAG_TEMP = 0x215, // Dcache test tag temporary register - RAW_IPR_DC_MODE = 0x216, // Dcache mode register - RAW_IPR_MAF_MODE = 0x217, // miss address file mode register + RAW_IPR_DC_MODE = 0x216, // Dcache mode register + RAW_IPR_MAF_MODE = 0x217, // miss address file mode register - MaxInternalProcRegs // number of IPR registers + MaxInternalProcRegs // number of IPR registers }; enum MiscRegIpr @@ -215,7 +215,7 @@ namespace AlphaISA IPR_DC_MODE, IPR_MAF_MODE, - NumInternalProcRegs // number of IPR registers + NumInternalProcRegs // number of IPR registers }; inline bool IprIsWritable(int index) diff --git a/src/arch/alpha/isa_traits.hh b/src/arch/alpha/isa_traits.hh index be1d1b8bb..4837d4a34 100644 --- a/src/arch/alpha/isa_traits.hh +++ b/src/arch/alpha/isa_traits.hh @@ -123,11 +123,11 @@ namespace AlphaISA // EV5 modes enum mode_type { - mode_kernel = 0, // kernel - mode_executive = 1, // executive (unused by unix) - mode_supervisor = 2, // supervisor (unused by unix) - mode_user = 3, // user mode - mode_number // number of modes + mode_kernel = 0, // kernel + mode_executive = 1, // executive (unused by unix) + mode_supervisor = 2, // supervisor (unused by unix) + mode_user = 3, // user mode + mode_number // number of modes }; // Constants Related to the number of registers @@ -148,7 +148,7 @@ namespace AlphaISA const int TotalDataRegs = NumIntRegs + NumFloatRegs; // semantically meaningful register indices - const int ZeroReg = 31; // architecturally meaningful + const int ZeroReg = 31; // architecturally meaningful // the rest of these depend on the ABI const int StackPointerReg = 30; const int GlobalPointerReg = 29; @@ -164,7 +164,7 @@ namespace AlphaISA const int SyscallPseudoReturnReg = ArgumentReg[4]; const int SyscallSuccessReg = 19; - const int LogVMPageSize = 13; // 8K bytes + const int LogVMPageSize = 13; // 8K bytes const int VMPageSize = (1 << LogVMPageSize); const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned diff --git a/src/arch/alpha/linux/linux.cc b/src/arch/alpha/linux/linux.cc index e6908a572..3e80f62a7 100644 --- a/src/arch/alpha/linux/linux.cc +++ b/src/arch/alpha/linux/linux.cc @@ -35,34 +35,34 @@ // open(2) flags translation table OpenFlagTransTable AlphaLinux::openFlagTable[] = { #ifdef _MSC_VER - { AlphaLinux::TGT_O_RDONLY, _O_RDONLY }, - { AlphaLinux::TGT_O_WRONLY, _O_WRONLY }, - { AlphaLinux::TGT_O_RDWR, _O_RDWR }, - { AlphaLinux::TGT_O_APPEND, _O_APPEND }, - { AlphaLinux::TGT_O_CREAT, _O_CREAT }, - { AlphaLinux::TGT_O_TRUNC, _O_TRUNC }, - { AlphaLinux::TGT_O_EXCL, _O_EXCL }, + { AlphaLinux::TGT_O_RDONLY, _O_RDONLY }, + { AlphaLinux::TGT_O_WRONLY, _O_WRONLY }, + { AlphaLinux::TGT_O_RDWR, _O_RDWR }, + { AlphaLinux::TGT_O_APPEND, _O_APPEND }, + { AlphaLinux::TGT_O_CREAT, _O_CREAT }, + { AlphaLinux::TGT_O_TRUNC, _O_TRUNC }, + { AlphaLinux::TGT_O_EXCL, _O_EXCL }, #ifdef _O_NONBLOCK - { AlphaLinux::TGT_O_NONBLOCK, _O_NONBLOCK }, + { AlphaLinux::TGT_O_NONBLOCK, _O_NONBLOCK }, #endif #ifdef _O_NOCTTY - { AlphaLinux::TGT_O_NOCTTY, _O_NOCTTY }, + { AlphaLinux::TGT_O_NOCTTY, _O_NOCTTY }, #endif #ifdef _O_SYNC - { AlphaLinux::TGT_O_SYNC, _O_SYNC }, + { AlphaLinux::TGT_O_SYNC, _O_SYNC }, #endif #else /* !_MSC_VER */ - { AlphaLinux::TGT_O_RDONLY, O_RDONLY }, - { AlphaLinux::TGT_O_WRONLY, O_WRONLY }, - { AlphaLinux::TGT_O_RDWR, O_RDWR }, - { AlphaLinux::TGT_O_APPEND, O_APPEND }, - { AlphaLinux::TGT_O_CREAT, O_CREAT }, - { AlphaLinux::TGT_O_TRUNC, O_TRUNC }, - { AlphaLinux::TGT_O_EXCL, O_EXCL }, - { AlphaLinux::TGT_O_NONBLOCK, O_NONBLOCK }, - { AlphaLinux::TGT_O_NOCTTY, O_NOCTTY }, + { AlphaLinux::TGT_O_RDONLY, O_RDONLY }, + { AlphaLinux::TGT_O_WRONLY, O_WRONLY }, + { AlphaLinux::TGT_O_RDWR, O_RDWR }, + { AlphaLinux::TGT_O_APPEND, O_APPEND }, + { AlphaLinux::TGT_O_CREAT, O_CREAT }, + { AlphaLinux::TGT_O_TRUNC, O_TRUNC }, + { AlphaLinux::TGT_O_EXCL, O_EXCL }, + { AlphaLinux::TGT_O_NONBLOCK, O_NONBLOCK }, + { AlphaLinux::TGT_O_NOCTTY, O_NOCTTY }, #ifdef O_SYNC - { AlphaLinux::TGT_O_SYNC, O_SYNC }, + { AlphaLinux::TGT_O_SYNC, O_SYNC }, #endif #endif /* _MSC_VER */ }; diff --git a/src/arch/alpha/linux/linux.hh b/src/arch/alpha/linux/linux.hh index 84c04ebc3..803970aa9 100644 --- a/src/arch/alpha/linux/linux.hh +++ b/src/arch/alpha/linux/linux.hh @@ -50,21 +50,21 @@ class AlphaLinux : public Linux //@{ /// open(2) flag values. - static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY - static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY - static const int TGT_O_RDWR = 00000002; //!< O_RDWR - static const int TGT_O_NONBLOCK = 00000004; //!< O_NONBLOCK - static const int TGT_O_APPEND = 00000010; //!< O_APPEND - static const int TGT_O_CREAT = 00001000; //!< O_CREAT - static const int TGT_O_TRUNC = 00002000; //!< O_TRUNC - static const int TGT_O_EXCL = 00004000; //!< O_EXCL - static const int TGT_O_NOCTTY = 00010000; //!< O_NOCTTY - static const int TGT_O_SYNC = 00040000; //!< O_SYNC - static const int TGT_O_DRD = 00100000; //!< O_DRD - static const int TGT_O_DIRECTIO = 00200000; //!< O_DIRECTIO - static const int TGT_O_CACHE = 00400000; //!< O_CACHE - static const int TGT_O_DSYNC = 02000000; //!< O_DSYNC - static const int TGT_O_RSYNC = 04000000; //!< O_RSYNC + static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY + static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY + static const int TGT_O_RDWR = 00000002; //!< O_RDWR + static const int TGT_O_NONBLOCK = 00000004; //!< O_NONBLOCK + static const int TGT_O_APPEND = 00000010; //!< O_APPEND + static const int TGT_O_CREAT = 00001000; //!< O_CREAT + static const int TGT_O_TRUNC = 00002000; //!< O_TRUNC + static const int TGT_O_EXCL = 00004000; //!< O_EXCL + static const int TGT_O_NOCTTY = 00010000; //!< O_NOCTTY + static const int TGT_O_SYNC = 00040000; //!< O_SYNC + static const int TGT_O_DRD = 00100000; //!< O_DRD + static const int TGT_O_DIRECTIO = 00200000; //!< O_DIRECTIO + static const int TGT_O_CACHE = 00400000; //!< O_CACHE + static const int TGT_O_DSYNC = 02000000; //!< O_DSYNC + static const int TGT_O_RSYNC = 04000000; //!< O_RSYNC //@} /// For mmap(). diff --git a/src/arch/alpha/miscregfile.hh b/src/arch/alpha/miscregfile.hh index 022b6404a..f07b998e6 100644 --- a/src/arch/alpha/miscregfile.hh +++ b/src/arch/alpha/miscregfile.hh @@ -60,11 +60,11 @@ namespace AlphaISA class MiscRegFile { protected: - uint64_t fpcr; // floating point condition codes - uint64_t uniq; // process-unique register - bool lock_flag; // lock flag for LL/SC - Addr lock_addr; // lock address for LL/SC - int intr_flag; + uint64_t fpcr; // floating point condition codes + uint64_t uniq; // process-unique register + bool lock_flag; // lock flag for LL/SC + Addr lock_addr; // lock address for LL/SC + int intr_flag; public: MiscRegFile() diff --git a/src/arch/alpha/osfpal.cc b/src/arch/alpha/osfpal.cc index ed1d255a6..0edbadb06 100644 --- a/src/arch/alpha/osfpal.cc +++ b/src/arch/alpha/osfpal.cc @@ -33,265 +33,265 @@ namespace { const char *strings[PAL::NumCodes] = { // Priviledged PAL instructions - "halt", // 0x00 - "cflush", // 0x01 - "draina", // 0x02 - 0, // 0x03 - 0, // 0x04 - 0, // 0x05 - 0, // 0x06 - 0, // 0x07 - 0, // 0x08 - "cserve", // 0x09 - "swppal", // 0x0a - 0, // 0x0b - 0, // 0x0c - "wripir", // 0x0d - 0, // 0x0e - 0, // 0x0f - "rdmces", // 0x10 - "wrmces", // 0x11 - 0, // 0x12 - 0, // 0x13 - 0, // 0x14 - 0, // 0x15 - 0, // 0x16 - 0, // 0x17 - 0, // 0x18 - 0, // 0x19 - 0, // 0x1a - 0, // 0x1b - 0, // 0x1c - 0, // 0x1d - 0, // 0x1e - 0, // 0x1f - 0, // 0x20 - 0, // 0x21 - 0, // 0x22 - 0, // 0x23 - 0, // 0x24 - 0, // 0x25 - 0, // 0x26 - 0, // 0x27 - 0, // 0x28 - 0, // 0x29 - 0, // 0x2a - "wrfen", // 0x2b - 0, // 0x2c - "wrvptptr", // 0x2d - 0, // 0x2e - 0, // 0x2f - "swpctx", // 0x30 - "wrval", // 0x31 - "rdval", // 0x32 - "tbi", // 0x33 - "wrent", // 0x34 - "swpipl", // 0x35 - "rdps", // 0x36 - "wrkgp", // 0x37 - "wrusp", // 0x38 - "wrperfmon", // 0x39 - "rdusp", // 0x3a - 0, // 0x3b - "whami", // 0x3c - "retsys", // 0x3d - "wtint", // 0x3e - "rti", // 0x3f - 0, // 0x40 - 0, // 0x41 - 0, // 0x42 - 0, // 0x43 - 0, // 0x44 - 0, // 0x45 - 0, // 0x46 - 0, // 0x47 - 0, // 0x48 - 0, // 0x49 - 0, // 0x4a - 0, // 0x4b - 0, // 0x4c - 0, // 0x4d - 0, // 0x4e - 0, // 0x4f - 0, // 0x50 - 0, // 0x51 - 0, // 0x52 - 0, // 0x53 - 0, // 0x54 - 0, // 0x55 - 0, // 0x56 - 0, // 0x57 - 0, // 0x58 - 0, // 0x59 - 0, // 0x5a - 0, // 0x5b - 0, // 0x5c - 0, // 0x5d - 0, // 0x5e - 0, // 0x5f - 0, // 0x60 - 0, // 0x61 - 0, // 0x62 - 0, // 0x63 - 0, // 0x64 - 0, // 0x65 - 0, // 0x66 - 0, // 0x67 - 0, // 0x68 - 0, // 0x69 - 0, // 0x6a - 0, // 0x6b - 0, // 0x6c - 0, // 0x6d - 0, // 0x6e - 0, // 0x6f - 0, // 0x70 - 0, // 0x71 - 0, // 0x72 - 0, // 0x73 - 0, // 0x74 - 0, // 0x75 - 0, // 0x76 - 0, // 0x77 - 0, // 0x78 - 0, // 0x79 - 0, // 0x7a - 0, // 0x7b - 0, // 0x7c - 0, // 0x7d - 0, // 0x7e - 0, // 0x7f + "halt", // 0x00 + "cflush", // 0x01 + "draina", // 0x02 + 0, // 0x03 + 0, // 0x04 + 0, // 0x05 + 0, // 0x06 + 0, // 0x07 + 0, // 0x08 + "cserve", // 0x09 + "swppal", // 0x0a + 0, // 0x0b + 0, // 0x0c + "wripir", // 0x0d + 0, // 0x0e + 0, // 0x0f + "rdmces", // 0x10 + "wrmces", // 0x11 + 0, // 0x12 + 0, // 0x13 + 0, // 0x14 + 0, // 0x15 + 0, // 0x16 + 0, // 0x17 + 0, // 0x18 + 0, // 0x19 + 0, // 0x1a + 0, // 0x1b + 0, // 0x1c + 0, // 0x1d + 0, // 0x1e + 0, // 0x1f + 0, // 0x20 + 0, // 0x21 + 0, // 0x22 + 0, // 0x23 + 0, // 0x24 + 0, // 0x25 + 0, // 0x26 + 0, // 0x27 + 0, // 0x28 + 0, // 0x29 + 0, // 0x2a + "wrfen", // 0x2b + 0, // 0x2c + "wrvptptr", // 0x2d + 0, // 0x2e + 0, // 0x2f + "swpctx", // 0x30 + "wrval", // 0x31 + "rdval", // 0x32 + "tbi", // 0x33 + "wrent", // 0x34 + "swpipl", // 0x35 + "rdps", // 0x36 + "wrkgp", // 0x37 + "wrusp", // 0x38 + "wrperfmon", // 0x39 + "rdusp", // 0x3a + 0, // 0x3b + "whami", // 0x3c + "retsys", // 0x3d + "wtint", // 0x3e + "rti", // 0x3f + 0, // 0x40 + 0, // 0x41 + 0, // 0x42 + 0, // 0x43 + 0, // 0x44 + 0, // 0x45 + 0, // 0x46 + 0, // 0x47 + 0, // 0x48 + 0, // 0x49 + 0, // 0x4a + 0, // 0x4b + 0, // 0x4c + 0, // 0x4d + 0, // 0x4e + 0, // 0x4f + 0, // 0x50 + 0, // 0x51 + 0, // 0x52 + 0, // 0x53 + 0, // 0x54 + 0, // 0x55 + 0, // 0x56 + 0, // 0x57 + 0, // 0x58 + 0, // 0x59 + 0, // 0x5a + 0, // 0x5b + 0, // 0x5c + 0, // 0x5d + 0, // 0x5e + 0, // 0x5f + 0, // 0x60 + 0, // 0x61 + 0, // 0x62 + 0, // 0x63 + 0, // 0x64 + 0, // 0x65 + 0, // 0x66 + 0, // 0x67 + 0, // 0x68 + 0, // 0x69 + 0, // 0x6a + 0, // 0x6b + 0, // 0x6c + 0, // 0x6d + 0, // 0x6e + 0, // 0x6f + 0, // 0x70 + 0, // 0x71 + 0, // 0x72 + 0, // 0x73 + 0, // 0x74 + 0, // 0x75 + 0, // 0x76 + 0, // 0x77 + 0, // 0x78 + 0, // 0x79 + 0, // 0x7a + 0, // 0x7b + 0, // 0x7c + 0, // 0x7d + 0, // 0x7e + 0, // 0x7f // Unpriviledged PAL instructions - "bpt", // 0x80 - "bugchk", // 0x81 - 0, // 0x82 - "callsys", // 0x83 - 0, // 0x84 - 0, // 0x85 - "imb", // 0x86 - 0, // 0x87 - 0, // 0x88 - 0, // 0x89 - 0, // 0x8a - 0, // 0x8b - 0, // 0x8c - 0, // 0x8d - 0, // 0x8e - 0, // 0x8f - 0, // 0x90 - 0, // 0x91 - "urti", // 0x92 - 0, // 0x93 - 0, // 0x94 - 0, // 0x95 - 0, // 0x96 - 0, // 0x97 - 0, // 0x98 - 0, // 0x99 - 0, // 0x9a - 0, // 0x9b - 0, // 0x9c - 0, // 0x9d - "rdunique", // 0x9e - "wrunique", // 0x9f - 0, // 0xa0 - 0, // 0xa1 - 0, // 0xa2 - 0, // 0xa3 - 0, // 0xa4 - 0, // 0xa5 - 0, // 0xa6 - 0, // 0xa7 - 0, // 0xa8 - 0, // 0xa9 - "gentrap", // 0xaa - 0, // 0xab - 0, // 0xac - 0, // 0xad - "clrfen", // 0xae - 0, // 0xaf - 0, // 0xb0 - 0, // 0xb1 - 0, // 0xb2 - 0, // 0xb3 - 0, // 0xb4 - 0, // 0xb5 - 0, // 0xb6 - 0, // 0xb7 - 0, // 0xb8 - 0, // 0xb9 - 0, // 0xba - 0, // 0xbb - 0, // 0xbc - 0, // 0xbd - "nphalt", // 0xbe - "copypal", // 0xbf + "bpt", // 0x80 + "bugchk", // 0x81 + 0, // 0x82 + "callsys", // 0x83 + 0, // 0x84 + 0, // 0x85 + "imb", // 0x86 + 0, // 0x87 + 0, // 0x88 + 0, // 0x89 + 0, // 0x8a + 0, // 0x8b + 0, // 0x8c + 0, // 0x8d + 0, // 0x8e + 0, // 0x8f + 0, // 0x90 + 0, // 0x91 + "urti", // 0x92 + 0, // 0x93 + 0, // 0x94 + 0, // 0x95 + 0, // 0x96 + 0, // 0x97 + 0, // 0x98 + 0, // 0x99 + 0, // 0x9a + 0, // 0x9b + 0, // 0x9c + 0, // 0x9d + "rdunique", // 0x9e + "wrunique", // 0x9f + 0, // 0xa0 + 0, // 0xa1 + 0, // 0xa2 + 0, // 0xa3 + 0, // 0xa4 + 0, // 0xa5 + 0, // 0xa6 + 0, // 0xa7 + 0, // 0xa8 + 0, // 0xa9 + "gentrap", // 0xaa + 0, // 0xab + 0, // 0xac + 0, // 0xad + "clrfen", // 0xae + 0, // 0xaf + 0, // 0xb0 + 0, // 0xb1 + 0, // 0xb2 + 0, // 0xb3 + 0, // 0xb4 + 0, // 0xb5 + 0, // 0xb6 + 0, // 0xb7 + 0, // 0xb8 + 0, // 0xb9 + 0, // 0xba + 0, // 0xbb + 0, // 0xbc + 0, // 0xbd + "nphalt", // 0xbe + "copypal", // 0xbf #if 0 - 0, // 0xc0 - 0, // 0xc1 - 0, // 0xc2 - 0, // 0xc3 - 0, // 0xc4 - 0, // 0xc5 - 0, // 0xc6 - 0, // 0xc7 - 0, // 0xc8 - 0, // 0xc9 - 0, // 0xca - 0, // 0xcb - 0, // 0xcc - 0, // 0xcd - 0, // 0xce - 0, // 0xcf - 0, // 0xd0 - 0, // 0xd1 - 0, // 0xd2 - 0, // 0xd3 - 0, // 0xd4 - 0, // 0xd5 - 0, // 0xd6 - 0, // 0xd7 - 0, // 0xd8 - 0, // 0xd9 - 0, // 0xda - 0, // 0xdb - 0, // 0xdc - 0, // 0xdd - 0, // 0xde - 0, // 0xdf - 0, // 0xe0 - 0, // 0xe1 - 0, // 0xe2 - 0, // 0xe3 - 0, // 0xe4 - 0, // 0xe5 - 0, // 0xe6 - 0, // 0xe7 - 0, // 0xe8 - 0, // 0xe9 - 0, // 0xea - 0, // 0xeb - 0, // 0xec - 0, // 0xed - 0, // 0xee - 0, // 0xef - 0, // 0xf0 - 0, // 0xf1 - 0, // 0xf2 - 0, // 0xf3 - 0, // 0xf4 - 0, // 0xf5 - 0, // 0xf6 - 0, // 0xf7 - 0, // 0xf8 - 0, // 0xf9 - 0, // 0xfa - 0, // 0xfb - 0, // 0xfc - 0, // 0xfd - 0, // 0xfe - 0 // 0xff + 0, // 0xc0 + 0, // 0xc1 + 0, // 0xc2 + 0, // 0xc3 + 0, // 0xc4 + 0, // 0xc5 + 0, // 0xc6 + 0, // 0xc7 + 0, // 0xc8 + 0, // 0xc9 + 0, // 0xca + 0, // 0xcb + 0, // 0xcc + 0, // 0xcd + 0, // 0xce + 0, // 0xcf + 0, // 0xd0 + 0, // 0xd1 + 0, // 0xd2 + 0, // 0xd3 + 0, // 0xd4 + 0, // 0xd5 + 0, // 0xd6 + 0, // 0xd7 + 0, // 0xd8 + 0, // 0xd9 + 0, // 0xda + 0, // 0xdb + 0, // 0xdc + 0, // 0xdd + 0, // 0xde + 0, // 0xdf + 0, // 0xe0 + 0, // 0xe1 + 0, // 0xe2 + 0, // 0xe3 + 0, // 0xe4 + 0, // 0xe5 + 0, // 0xe6 + 0, // 0xe7 + 0, // 0xe8 + 0, // 0xe9 + 0, // 0xea + 0, // 0xeb + 0, // 0xec + 0, // 0xed + 0, // 0xee + 0, // 0xef + 0, // 0xf0 + 0, // 0xf1 + 0, // 0xf2 + 0, // 0xf3 + 0, // 0xf4 + 0, // 0xf5 + 0, // 0xf6 + 0, // 0xf7 + 0, // 0xf8 + 0, // 0xf9 + 0, // 0xfa + 0, // 0xfb + 0, // 0xfc + 0, // 0xfd + 0, // 0xfe + 0 // 0xff #endif }; } diff --git a/src/arch/alpha/pagetable.hh b/src/arch/alpha/pagetable.hh index 8ce5b4e5d..f28c1b195 100644 --- a/src/arch/alpha/pagetable.hh +++ b/src/arch/alpha/pagetable.hh @@ -110,15 +110,15 @@ namespace AlphaISA { TlbEntry() {} - Addr tag; // virtual page number tag - Addr ppn; // physical page number - uint8_t xre; // read permissions - VMEM_PERM_* mask - uint8_t xwe; // write permissions - VMEM_PERM_* mask - uint8_t asn; // address space number - bool asma; // address space match - bool fonr; // fault on read - bool fonw; // fault on write - bool valid; // valid page table entry + Addr tag; // virtual page number tag + Addr ppn; // physical page number + uint8_t xre; // read permissions - VMEM_PERM_* mask + uint8_t xwe; // write permissions - VMEM_PERM_* mask + uint8_t asn; // address space number + bool asma; // address space match + bool fonr; // fault on read + bool fonw; // fault on write + bool valid; // valid page table entry Addr pageStart() { diff --git a/src/arch/alpha/regfile.hh b/src/arch/alpha/regfile.hh index 792a518fb..0c1f07bdd 100644 --- a/src/arch/alpha/regfile.hh +++ b/src/arch/alpha/regfile.hh @@ -51,8 +51,8 @@ namespace AlphaISA class RegFile { protected: - Addr pc; // program counter - Addr npc; // next-cycle program counter + Addr pc; // program counter + Addr npc; // next-cycle program counter Addr nnpc; public: @@ -85,14 +85,14 @@ namespace AlphaISA { } protected: - IntRegFile intRegFile; // (signed) integer register file - FloatRegFile floatRegFile; // floating point register file - MiscRegFile miscRegFile; // control register file + IntRegFile intRegFile; // (signed) integer register file + FloatRegFile floatRegFile; // floating point register file + MiscRegFile miscRegFile; // control register file public: #if FULL_SYSTEM - int intrflag; // interrupt flag + int intrflag; // interrupt flag inline int instAsid() { return miscRegFile.getInstAsid(); } inline int dataAsid() diff --git a/src/arch/alpha/remote_gdb.cc b/src/arch/alpha/remote_gdb.cc index ea5db36f4..8d70ebfa2 100644 --- a/src/arch/alpha/remote_gdb.cc +++ b/src/arch/alpha/remote_gdb.cc @@ -30,7 +30,7 @@ /* * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. + * The Regents of the University of California. All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and @@ -38,8 +38,8 @@ * * All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Lawrence Berkeley Laboratories. + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -51,8 +51,8 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. + * This product includes software developed by the University of + * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -69,7 +69,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94 + * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94 */ /*- @@ -89,8 +89,8 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. @@ -151,7 +151,7 @@ RemoteGDB::RemoteGDB(System *_system, ThreadContext *c) /////////////////////////////////////////////////////////// // RemoteGDB::acc // -// Determine if the mapping at va..(va+len) is valid. +// Determine if the mapping at va..(va+len) is valid. // bool RemoteGDB::acc(Addr va, size_t len) @@ -204,8 +204,8 @@ RemoteGDB::acc(Addr va, size_t len) /////////////////////////////////////////////////////////// // RemoteGDB::getregs // -// Translate the kernel debugger register format into -// the GDB register format. +// Translate the kernel debugger register format into +// the GDB register format. void RemoteGDB::getregs() { @@ -234,8 +234,8 @@ RemoteGDB::getregs() /////////////////////////////////////////////////////////// // RemoteGDB::setregs // -// Translate the GDB register format into the kernel -// debugger register format. +// Translate the GDB register format into the kernel +// debugger register format. // void RemoteGDB::setregs() diff --git a/src/arch/alpha/system.cc b/src/arch/alpha/system.cc index 2af62ceea..f8fea4fee 100644 --- a/src/arch/alpha/system.cc +++ b/src/arch/alpha/system.cc @@ -142,9 +142,9 @@ AlphaSystem::~AlphaSystem() * in the procedure value register (pv aka t12 == r27). This sequence * looks like the following: * - * opcode Ra Rb offset - * ldah gp,X(pv) 09 29 27 X - * lda gp,Y(gp) 08 29 29 Y + * opcode Ra Rb offset + * ldah gp,X(pv) 09 29 27 X + * lda gp,Y(gp) 08 29 29 Y * * for some constant offsets X and Y. The catch is that the linker * (or maybe even the compiler, I'm not sure) may recognize that the diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc index 4f960360e..60502ebdb 100644 --- a/src/arch/alpha/tlb.cc +++ b/src/arch/alpha/tlb.cc @@ -55,7 +55,7 @@ bool uncacheBit39 = false; bool uncacheBit40 = false; #endif -#define MODE2MASK(X) (1 << (X)) +#define MODE2MASK(X) (1 << (X)) TLB::TLB(const Params *p) : BaseTLB(p), size(p->size), nlu(0) diff --git a/src/arch/alpha/tru64/process.cc b/src/arch/alpha/tru64/process.cc index e9f7b6be1..5f448489e 100644 --- a/src/arch/alpha/tru64/process.cc +++ b/src/arch/alpha/tru64/process.cc @@ -85,7 +85,7 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, case AlphaTru64::GSI_PHYSMEM: { TypedBufferArg physmem(tc->getSyscallArg(1)); - *physmem = htog((uint64_t)1024 * 1024); // physical memory in KB + *physmem = htog((uint64_t)1024 * 1024); // physical memory in KB physmem.copyOut(tc->getMemPort()); return 1; } @@ -168,11 +168,11 @@ SyscallReturn tableFunc(SyscallDesc *desc, int callnum, LiveProcess *process, using namespace std; using namespace TheISA; - int id = tc->getSyscallArg(0); // table ID - int index = tc->getSyscallArg(1); // index into table + int id = tc->getSyscallArg(0); // table ID + int index = tc->getSyscallArg(1); // index into table // arg 2 is buffer pointer; type depends on table ID - int nel = tc->getSyscallArg(3); // number of elements - int lel = tc->getSyscallArg(4); // expected element size + int nel = tc->getSyscallArg(3); // number of elements + int lel = tc->getSyscallArg(4); // expected element size switch (id) { case AlphaTru64::TBL_SYSINFO: { diff --git a/src/arch/alpha/tru64/tru64.cc b/src/arch/alpha/tru64/tru64.cc index 56b04846f..c72e975f0 100644 --- a/src/arch/alpha/tru64/tru64.cc +++ b/src/arch/alpha/tru64/tru64.cc @@ -33,34 +33,34 @@ // open(2) flags translation table OpenFlagTransTable AlphaTru64::openFlagTable[] = { #ifdef _MSC_VER - { AlphaTru64::TGT_O_RDONLY, _O_RDONLY }, - { AlphaTru64::TGT_O_WRONLY, _O_WRONLY }, - { AlphaTru64::TGT_O_RDWR, _O_RDWR }, - { AlphaTru64::TGT_O_APPEND, _O_APPEND }, - { AlphaTru64::TGT_O_CREAT, _O_CREAT }, - { AlphaTru64::TGT_O_TRUNC, _O_TRUNC }, - { AlphaTru64::TGT_O_EXCL, _O_EXCL }, + { AlphaTru64::TGT_O_RDONLY, _O_RDONLY }, + { AlphaTru64::TGT_O_WRONLY, _O_WRONLY }, + { AlphaTru64::TGT_O_RDWR, _O_RDWR }, + { AlphaTru64::TGT_O_APPEND, _O_APPEND }, + { AlphaTru64::TGT_O_CREAT, _O_CREAT }, + { AlphaTru64::TGT_O_TRUNC, _O_TRUNC }, + { AlphaTru64::TGT_O_EXCL, _O_EXCL }, #ifdef _O_NONBLOCK - { AlphaTru64::TGT_O_NONBLOCK, _O_NONBLOCK }, + { AlphaTru64::TGT_O_NONBLOCK, _O_NONBLOCK }, #endif #ifdef _O_NOCTTY - { AlphaTru64::TGT_O_NOCTTY, _O_NOCTTY }, + { AlphaTru64::TGT_O_NOCTTY, _O_NOCTTY }, #endif #ifdef _O_SYNC - { AlphaTru64::TGT_O_SYNC, _O_SYNC }, + { AlphaTru64::TGT_O_SYNC, _O_SYNC }, #endif #else /* !_MSC_VER */ - { AlphaTru64::TGT_O_RDONLY, O_RDONLY }, - { AlphaTru64::TGT_O_WRONLY, O_WRONLY }, - { AlphaTru64::TGT_O_RDWR, O_RDWR }, - { AlphaTru64::TGT_O_APPEND, O_APPEND }, - { AlphaTru64::TGT_O_CREAT, O_CREAT }, - { AlphaTru64::TGT_O_TRUNC, O_TRUNC }, - { AlphaTru64::TGT_O_EXCL, O_EXCL }, - { AlphaTru64::TGT_O_NONBLOCK, O_NONBLOCK }, - { AlphaTru64::TGT_O_NOCTTY, O_NOCTTY }, + { AlphaTru64::TGT_O_RDONLY, O_RDONLY }, + { AlphaTru64::TGT_O_WRONLY, O_WRONLY }, + { AlphaTru64::TGT_O_RDWR, O_RDWR }, + { AlphaTru64::TGT_O_APPEND, O_APPEND }, + { AlphaTru64::TGT_O_CREAT, O_CREAT }, + { AlphaTru64::TGT_O_TRUNC, O_TRUNC }, + { AlphaTru64::TGT_O_EXCL, O_EXCL }, + { AlphaTru64::TGT_O_NONBLOCK, O_NONBLOCK }, + { AlphaTru64::TGT_O_NOCTTY, O_NOCTTY }, #ifdef O_SYNC - { AlphaTru64::TGT_O_SYNC, O_SYNC }, + { AlphaTru64::TGT_O_SYNC, O_SYNC }, #endif #endif /* _MSC_VER */ }; diff --git a/src/arch/alpha/tru64/tru64.hh b/src/arch/alpha/tru64/tru64.hh index 90e5f12dc..8aa959553 100644 --- a/src/arch/alpha/tru64/tru64.hh +++ b/src/arch/alpha/tru64/tru64.hh @@ -46,21 +46,21 @@ class AlphaTru64 : public Tru64 //@{ /// open(2) flag values. - static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY - static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY - static const int TGT_O_RDWR = 00000002; //!< O_RDWR - static const int TGT_O_NONBLOCK = 00000004; //!< O_NONBLOCK - static const int TGT_O_APPEND = 00000010; //!< O_APPEND - static const int TGT_O_CREAT = 00001000; //!< O_CREAT - static const int TGT_O_TRUNC = 00002000; //!< O_TRUNC - static const int TGT_O_EXCL = 00004000; //!< O_EXCL - static const int TGT_O_NOCTTY = 00010000; //!< O_NOCTTY - static const int TGT_O_SYNC = 00040000; //!< O_SYNC - static const int TGT_O_DRD = 00100000; //!< O_DRD - static const int TGT_O_DIRECTIO = 00200000; //!< O_DIRECTIO - static const int TGT_O_CACHE = 00400000; //!< O_CACHE - static const int TGT_O_DSYNC = 02000000; //!< O_DSYNC - static const int TGT_O_RSYNC = 04000000; //!< O_RSYNC + static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY + static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY + static const int TGT_O_RDWR = 00000002; //!< O_RDWR + static const int TGT_O_NONBLOCK = 00000004; //!< O_NONBLOCK + static const int TGT_O_APPEND = 00000010; //!< O_APPEND + static const int TGT_O_CREAT = 00001000; //!< O_CREAT + static const int TGT_O_TRUNC = 00002000; //!< O_TRUNC + static const int TGT_O_EXCL = 00004000; //!< O_EXCL + static const int TGT_O_NOCTTY = 00010000; //!< O_NOCTTY + static const int TGT_O_SYNC = 00040000; //!< O_SYNC + static const int TGT_O_DRD = 00100000; //!< O_DRD + static const int TGT_O_DIRECTIO = 00200000; //!< O_DIRECTIO + static const int TGT_O_CACHE = 00400000; //!< O_CACHE + static const int TGT_O_DSYNC = 02000000; //!< O_DSYNC + static const int TGT_O_RSYNC = 04000000; //!< O_RSYNC //@} /// For mmap(). @@ -69,12 +69,12 @@ class AlphaTru64 : public Tru64 //@{ /// For getsysinfo(). static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string - static const unsigned GSI_CPU_INFO = 59; //!< CPU information - static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type + static const unsigned GSI_CPU_INFO = 59; //!< CPU information + static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine - static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system - static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB - static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz + static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system + static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB + static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz //@} //@{ diff --git a/src/arch/isa_parser.py b/src/arch/isa_parser.py index bbdd95bb0..25cf84b30 100755 --- a/src/arch/isa_parser.py +++ b/src/arch/isa_parser.py @@ -116,7 +116,7 @@ t_SEMI = r';' t_DOT = r'\.' t_COLON = r':' t_DBLCOLON = r'::' -t_ASTERISK = r'\*' +t_ASTERISK = r'\*' # Identifiers and reserved words reserved_map = { } @@ -480,7 +480,7 @@ def p_excess_args_param(t): # # A decode block looks like: -# decode [, ]* [default ] { ... } +# decode [, ]* [default ] { ... } # def p_decode_block(t): 'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE' @@ -1149,7 +1149,7 @@ def buildOperandTypeMap(userDict, lineno): ctype = 'uint%d_t' % size is_signed = 0 elif desc == 'float': - is_signed = 1 # shouldn't really matter + is_signed = 1 # shouldn't really matter if size == 32: ctype = 'float' elif size == 64: @@ -1595,9 +1595,9 @@ def buildOperandNameMap(userDict, lineno): operands = userDict.keys() operandsREString = (r''' - (?size), nlu(0) @@ -91,7 +91,7 @@ TLB::lookup(Addr vpn, uint8_t asn) const Addr Mask = pte->Mask; Addr InvMask = ~Mask; Addr VPN = pte->VPN; - // warn("Valid: %d - %d\n",pte->V0,pte->V1); + // warn("Valid: %d - %d\n",pte->V0,pte->V1); if(((vpn & InvMask) == (VPN & InvMask)) && (pte->G || (asn == pte->asid))) { // We have a VPN + ASID Match retval = pte; @@ -389,7 +389,7 @@ ITB::translate(RequestPtr &req, ThreadContext *tc) } else {// Ok, this is really a match, set paddr - // hits++; + // hits++; Addr PAddr; if(EvenOdd == 0){ PAddr = pte->PFN0; @@ -406,7 +406,7 @@ ITB::translate(RequestPtr &req, ThreadContext *tc) } else { // Didn't find any match, return a TLB Refill Exception - // misses++; + // misses++; ItbRefillFault *Flt=new ItbRefillFault(); /* EntryHi VPN, ASID fields must be set */ Flt->EntryHi_Asid = Asid; @@ -494,7 +494,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) if(Valid == false) {//Invalid entry - // invalids++; + // invalids++; DtbInvalidFault *Flt = new DtbInvalidFault(); /* EntryHi VPN, ASID fields must be set */ Flt->EntryHi_Asid = Asid; @@ -512,7 +512,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) } else {// Ok, this is really a match, set paddr - // hits++; + // hits++; if(!Dirty) { TLBModifiedFault *Flt = new TLBModifiedFault(); @@ -544,7 +544,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) } else { // Didn't find any match, return a TLB Refill Exception - // misses++; + // misses++; DtbRefillFault *Flt=new DtbRefillFault(); /* EntryHi VPN, ASID fields must be set */ Flt->EntryHi_Asid = Asid; @@ -577,19 +577,19 @@ ITB::ITB(const Params *p) // ITB::regStats() // { // /* hits - causes failure for some reason -// .name(name() + ".hits") -// .desc("ITB hits"); +// .name(name() + ".hits") +// .desc("ITB hits"); // misses -// .name(name() + ".misses") -// .desc("ITB misses"); +// .name(name() + ".misses") +// .desc("ITB misses"); // acv -// .name(name() + ".acv") -// .desc("ITB acv"); +// .name(name() + ".acv") +// .desc("ITB acv"); // accesses -// .name(name() + ".accesses") -// .desc("ITB accesses"); +// .name(name() + ".accesses") +// .desc("ITB accesses"); -// accesses = hits + misses + invalids; */ +// accesses = hits + misses + invalids; */ // } diff --git a/src/arch/mips/tlb.hh b/src/arch/mips/tlb.hh index 4333777ff..feb2509c5 100644 --- a/src/arch/mips/tlb.hh +++ b/src/arch/mips/tlb.hh @@ -84,11 +84,11 @@ class TLB : public BaseTLB { protected: typedef std::multimap PageTable; - PageTable lookupTable; // Quick lookup into page table + PageTable lookupTable; // Quick lookup into page table - MipsISA::PTE *table; // the Page Table - int size; // TLB Size - int nlu; // not last used entry (for replacement) + MipsISA::PTE *table; // the Page Table + int size; // TLB Size + int nlu; // not last used entry (for replacement) void nextnlu() { if (++nlu >= size) nlu = 0; } MipsISA::PTE *lookup(Addr vpn, uint8_t asn) const; diff --git a/src/arch/sparc/isa_traits.hh b/src/arch/sparc/isa_traits.hh index 133817eb5..30455792f 100644 --- a/src/arch/sparc/isa_traits.hh +++ b/src/arch/sparc/isa_traits.hh @@ -66,7 +66,7 @@ namespace SparcISA }; // semantically meaningful register indices - const int ZeroReg = 0; // architecturally meaningful + const int ZeroReg = 0; // architecturally meaningful // the rest of these depend on the ABI const int StackPointerReg = 14; const int ReturnAddressReg = 31; // post call, precall is 15 diff --git a/src/arch/sparc/linux/linux.cc b/src/arch/sparc/linux/linux.cc index 1211d5f65..102e5af3b 100644 --- a/src/arch/sparc/linux/linux.cc +++ b/src/arch/sparc/linux/linux.cc @@ -34,34 +34,34 @@ // open(2) flags translation table OpenFlagTransTable SparcLinux::openFlagTable[] = { #ifdef _MSC_VER - { SparcLinux::TGT_O_RDONLY, _O_RDONLY }, - { SparcLinux::TGT_O_WRONLY, _O_WRONLY }, - { SparcLinux::TGT_O_RDWR, _O_RDWR }, - { SparcLinux::TGT_O_APPEND, _O_APPEND }, - { SparcLinux::TGT_O_CREAT, _O_CREAT }, - { SparcLinux::TGT_O_TRUNC, _O_TRUNC }, - { SparcLinux::TGT_O_EXCL, _O_EXCL }, + { SparcLinux::TGT_O_RDONLY, _O_RDONLY }, + { SparcLinux::TGT_O_WRONLY, _O_WRONLY }, + { SparcLinux::TGT_O_RDWR, _O_RDWR }, + { SparcLinux::TGT_O_APPEND, _O_APPEND }, + { SparcLinux::TGT_O_CREAT, _O_CREAT }, + { SparcLinux::TGT_O_TRUNC, _O_TRUNC }, + { SparcLinux::TGT_O_EXCL, _O_EXCL }, #ifdef _O_NONBLOCK - { SparcLinux::TGT_O_NONBLOCK, _O_NONBLOCK }, + { SparcLinux::TGT_O_NONBLOCK, _O_NONBLOCK }, #endif #ifdef _O_NOCTTY - { SparcLinux::TGT_O_NOCTTY, _O_NOCTTY }, + { SparcLinux::TGT_O_NOCTTY, _O_NOCTTY }, #endif #ifdef _O_SYNC - { SparcLinux::TGT_O_SYNC, _O_SYNC }, + { SparcLinux::TGT_O_SYNC, _O_SYNC }, #endif #else /* !_MSC_VER */ - { SparcLinux::TGT_O_RDONLY, O_RDONLY }, - { SparcLinux::TGT_O_WRONLY, O_WRONLY }, - { SparcLinux::TGT_O_RDWR, O_RDWR }, - { SparcLinux::TGT_O_APPEND, O_APPEND }, - { SparcLinux::TGT_O_CREAT, O_CREAT }, - { SparcLinux::TGT_O_TRUNC, O_TRUNC }, - { SparcLinux::TGT_O_EXCL, O_EXCL }, - { SparcLinux::TGT_O_NONBLOCK, O_NONBLOCK }, - { SparcLinux::TGT_O_NOCTTY, O_NOCTTY }, + { SparcLinux::TGT_O_RDONLY, O_RDONLY }, + { SparcLinux::TGT_O_WRONLY, O_WRONLY }, + { SparcLinux::TGT_O_RDWR, O_RDWR }, + { SparcLinux::TGT_O_APPEND, O_APPEND }, + { SparcLinux::TGT_O_CREAT, O_CREAT }, + { SparcLinux::TGT_O_TRUNC, O_TRUNC }, + { SparcLinux::TGT_O_EXCL, O_EXCL }, + { SparcLinux::TGT_O_NONBLOCK, O_NONBLOCK }, + { SparcLinux::TGT_O_NOCTTY, O_NOCTTY }, #ifdef O_SYNC - { SparcLinux::TGT_O_SYNC, O_SYNC }, + { SparcLinux::TGT_O_SYNC, O_SYNC }, #endif #endif /* _MSC_VER */ }; diff --git a/src/arch/sparc/linux/linux.hh b/src/arch/sparc/linux/linux.hh index f396eb5cd..b1dc691ce 100644 --- a/src/arch/sparc/linux/linux.hh +++ b/src/arch/sparc/linux/linux.hh @@ -58,21 +58,21 @@ class SparcLinux : public Linux static OpenFlagTransTable openFlagTable[]; - static const int TGT_O_RDONLY = 0x00000000; //!< O_RDONLY - static const int TGT_O_WRONLY = 0x00000001; //!< O_WRONLY - static const int TGT_O_RDWR = 0x00000002; //!< O_RDWR - static const int TGT_O_NONBLOCK = 0x00004000; //!< O_NONBLOCK - static const int TGT_O_APPEND = 0x00000008; //!< O_APPEND - static const int TGT_O_CREAT = 0x00000200; //!< O_CREAT - static const int TGT_O_TRUNC = 0x00000400; //!< O_TRUNC - static const int TGT_O_EXCL = 0x00000800; //!< O_EXCL - static const int TGT_O_NOCTTY = 0x00008000; //!< O_NOCTTY - static const int TGT_O_SYNC = 0x00002000; //!< O_SYNC -// static const int TGT_O_DRD = 0x00010000; //!< O_DRD -// static const int TGT_O_DIRECTIO = 0x00020000; //!< O_DIRECTIO -// static const int TGT_O_CACHE = 0x00002000; //!< O_CACHE -// static const int TGT_O_DSYNC = 0x00008000; //!< O_DSYNC -// static const int TGT_O_RSYNC = 0x00040000; //!< O_RSYNC + static const int TGT_O_RDONLY = 0x00000000; //!< O_RDONLY + static const int TGT_O_WRONLY = 0x00000001; //!< O_WRONLY + static const int TGT_O_RDWR = 0x00000002; //!< O_RDWR + static const int TGT_O_NONBLOCK = 0x00004000; //!< O_NONBLOCK + static const int TGT_O_APPEND = 0x00000008; //!< O_APPEND + static const int TGT_O_CREAT = 0x00000200; //!< O_CREAT + static const int TGT_O_TRUNC = 0x00000400; //!< O_TRUNC + static const int TGT_O_EXCL = 0x00000800; //!< O_EXCL + static const int TGT_O_NOCTTY = 0x00008000; //!< O_NOCTTY + static const int TGT_O_SYNC = 0x00002000; //!< O_SYNC +// static const int TGT_O_DRD = 0x00010000; //!< O_DRD +// static const int TGT_O_DIRECTIO = 0x00020000; //!< O_DIRECTIO +// static const int TGT_O_CACHE = 0x00002000; //!< O_CACHE +// static const int TGT_O_DSYNC = 0x00008000; //!< O_DSYNC +// static const int TGT_O_RSYNC = 0x00040000; //!< O_RSYNC static const int NUM_OPEN_FLAGS; diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh index 3e17779a9..bf9c880fa 100644 --- a/src/arch/sparc/miscregfile.hh +++ b/src/arch/sparc/miscregfile.hh @@ -171,50 +171,50 @@ namespace SparcISA private: /* ASR Registers */ - //uint64_t y; // Y (used in obsolete multiplication) - //uint8_t ccr; // Condition Code Register - uint8_t asi; // Address Space Identifier - uint64_t tick; // Hardware clock-tick counter - uint8_t fprs; // Floating-Point Register State - uint64_t gsr; // General Status Register + //uint64_t y; // Y (used in obsolete multiplication) + //uint8_t ccr; // Condition Code Register + uint8_t asi; // Address Space Identifier + uint64_t tick; // Hardware clock-tick counter + uint8_t fprs; // Floating-Point Register State + uint64_t gsr; // General Status Register uint64_t softint; - uint64_t tick_cmpr; // Hardware tick compare registers - uint64_t stick; // Hardware clock-tick counter - uint64_t stick_cmpr; // Hardware tick compare registers + uint64_t tick_cmpr; // Hardware tick compare registers + uint64_t stick; // Hardware clock-tick counter + uint64_t stick_cmpr; // Hardware tick compare registers /* Privileged Registers */ - uint64_t tpc[MaxTL]; // Trap Program Counter (value from + uint64_t tpc[MaxTL]; // Trap Program Counter (value from // previous trap level) - uint64_t tnpc[MaxTL]; // Trap Next Program Counter (value from + uint64_t tnpc[MaxTL]; // Trap Next Program Counter (value from // previous trap level) - uint64_t tstate[MaxTL]; // Trap State - uint16_t tt[MaxTL]; // Trap Type (Type of trap which occured + uint64_t tstate[MaxTL]; // Trap State + uint16_t tt[MaxTL]; // Trap Type (Type of trap which occured // on the previous level) - uint64_t tba; // Trap Base Address - - uint16_t pstate; // Process State Register - uint8_t tl; // Trap Level - uint8_t pil; // Process Interrupt Register - uint8_t cwp; // Current Window Pointer - //uint8_t cansave; // Savable windows - //uint8_t canrestore; // Restorable windows - //uint8_t cleanwin; // Clean windows - //uint8_t otherwin; // Other windows - //uint8_t wstate; // Window State + uint64_t tba; // Trap Base Address + + uint16_t pstate; // Process State Register + uint8_t tl; // Trap Level + uint8_t pil; // Process Interrupt Register + uint8_t cwp; // Current Window Pointer + //uint8_t cansave; // Savable windows + //uint8_t canrestore; // Restorable windows + //uint8_t cleanwin; // Clean windows + //uint8_t otherwin; // Other windows + //uint8_t wstate; // Window State uint8_t gl; // Global level register /** Hyperprivileged Registers */ - uint64_t hpstate; // Hyperprivileged State Register + uint64_t hpstate; // Hyperprivileged State Register uint64_t htstate[MaxTL];// Hyperprivileged Trap State Register uint64_t hintp; - uint64_t htba; // Hyperprivileged Trap Base Address register - uint64_t hstick_cmpr; // Hardware tick compare registers + uint64_t htba; // Hyperprivileged Trap Base Address register + uint64_t hstick_cmpr; // Hardware tick compare registers uint64_t strandStatusReg;// Per strand status register /** Floating point misc registers. */ - uint64_t fsr; // Floating-Point State Register + uint64_t fsr; // Floating-Point State Register /** MMU Internal Registers */ uint16_t priContext; diff --git a/src/arch/sparc/regfile.hh b/src/arch/sparc/regfile.hh index c03f69fc5..581785714 100644 --- a/src/arch/sparc/regfile.hh +++ b/src/arch/sparc/regfile.hh @@ -48,8 +48,8 @@ namespace SparcISA class RegFile { protected: - Addr pc; // Program Counter - Addr npc; // Next Program Counter + Addr pc; // Program Counter + Addr npc; // Next Program Counter Addr nnpc; public: @@ -63,9 +63,9 @@ namespace SparcISA void setNextNPC(Addr val); protected: - IntRegFile intRegFile; // integer register file - FloatRegFile floatRegFile; // floating point register file - MiscRegFile miscRegFile; // control register file + IntRegFile intRegFile; // integer register file + FloatRegFile floatRegFile; // floating point register file + MiscRegFile miscRegFile; // control register file public: diff --git a/src/arch/sparc/remote_gdb.cc b/src/arch/sparc/remote_gdb.cc index 67cc5b0d1..ef30bd808 100644 --- a/src/arch/sparc/remote_gdb.cc +++ b/src/arch/sparc/remote_gdb.cc @@ -30,7 +30,7 @@ /* * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. + * The Regents of the University of California. All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and @@ -38,8 +38,8 @@ * * All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Lawrence Berkeley Laboratories. + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -51,8 +51,8 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. + * This product includes software developed by the University of + * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -69,7 +69,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94 + * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94 */ /*- @@ -89,8 +89,8 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. @@ -146,7 +146,7 @@ RemoteGDB::RemoteGDB(System *_system, ThreadContext *c) /////////////////////////////////////////////////////////// // RemoteGDB::acc // -// Determine if the mapping at va..(va+len) is valid. +// Determine if the mapping at va..(va+len) is valid. // bool RemoteGDB::acc(Addr va, size_t len) @@ -171,8 +171,8 @@ RemoteGDB::acc(Addr va, size_t len) /////////////////////////////////////////////////////////// // RemoteGDB::getregs // -// Translate the kernel debugger register format into -// the GDB register format. +// Translate the kernel debugger register format into +// the GDB register format. void RemoteGDB::getregs() { @@ -217,8 +217,8 @@ RemoteGDB::getregs() /////////////////////////////////////////////////////////// // RemoteGDB::setregs // -// Translate the GDB register format into the kernel -// debugger register format. +// Translate the GDB register format into the kernel +// debugger register format. // void RemoteGDB::setregs() diff --git a/src/arch/sparc/solaris/solaris.cc b/src/arch/sparc/solaris/solaris.cc index c53caa72a..3cc910005 100644 --- a/src/arch/sparc/solaris/solaris.cc +++ b/src/arch/sparc/solaris/solaris.cc @@ -35,40 +35,40 @@ // open(2) flags translation table OpenFlagTransTable SparcSolaris::openFlagTable[] = { #ifdef _MSC_VER - { SparcSolaris::TGT_O_RDONLY, _O_RDONLY }, - { SparcSolaris::TGT_O_WRONLY, _O_WRONLY }, - { SparcSolaris::TGT_O_RDWR, _O_RDWR }, - { SparcSolaris::TGT_O_APPEND, _O_APPEND }, - { SparcSolaris::TGT_O_CREAT, _O_CREAT }, - { SparcSolaris::TGT_O_TRUNC, _O_TRUNC }, - { SparcSolaris::TGT_O_EXCL, _O_EXCL }, + { SparcSolaris::TGT_O_RDONLY, _O_RDONLY }, + { SparcSolaris::TGT_O_WRONLY, _O_WRONLY }, + { SparcSolaris::TGT_O_RDWR, _O_RDWR }, + { SparcSolaris::TGT_O_APPEND, _O_APPEND }, + { SparcSolaris::TGT_O_CREAT, _O_CREAT }, + { SparcSolaris::TGT_O_TRUNC, _O_TRUNC }, + { SparcSolaris::TGT_O_EXCL, _O_EXCL }, #ifdef _O_NONBLOCK - { SparcSolaris::TGT_O_NONBLOCK, _O_NONBLOCK }, - { SparcSolaris::TGT_O_NDELAY , _O_NONBLOCK }, + { SparcSolaris::TGT_O_NONBLOCK, _O_NONBLOCK }, + { SparcSolaris::TGT_O_NDELAY , _O_NONBLOCK }, #endif #ifdef _O_NOCTTY - { SparcSolaris::TGT_O_NOCTTY, _O_NOCTTY }, + { SparcSolaris::TGT_O_NOCTTY, _O_NOCTTY }, #endif #ifdef _O_SYNC - { SparcSolaris::TGT_O_SYNC, _O_SYNC }, - { SparcSolaris::TGT_O_DSYNC, _O_SYNC }, - { SparcSolaris::TGT_O_RSYNC, _O_SYNC }, + { SparcSolaris::TGT_O_SYNC, _O_SYNC }, + { SparcSolaris::TGT_O_DSYNC, _O_SYNC }, + { SparcSolaris::TGT_O_RSYNC, _O_SYNC }, #endif #else /* !_MSC_VER */ - { SparcSolaris::TGT_O_RDONLY, O_RDONLY }, - { SparcSolaris::TGT_O_WRONLY, O_WRONLY }, - { SparcSolaris::TGT_O_RDWR, O_RDWR }, - { SparcSolaris::TGT_O_APPEND, O_APPEND }, - { SparcSolaris::TGT_O_CREAT, O_CREAT }, - { SparcSolaris::TGT_O_TRUNC, O_TRUNC }, - { SparcSolaris::TGT_O_EXCL, O_EXCL }, - { SparcSolaris::TGT_O_NONBLOCK, O_NONBLOCK }, - { SparcSolaris::TGT_O_NDELAY , O_NONBLOCK }, - { SparcSolaris::TGT_O_NOCTTY, O_NOCTTY }, + { SparcSolaris::TGT_O_RDONLY, O_RDONLY }, + { SparcSolaris::TGT_O_WRONLY, O_WRONLY }, + { SparcSolaris::TGT_O_RDWR, O_RDWR }, + { SparcSolaris::TGT_O_APPEND, O_APPEND }, + { SparcSolaris::TGT_O_CREAT, O_CREAT }, + { SparcSolaris::TGT_O_TRUNC, O_TRUNC }, + { SparcSolaris::TGT_O_EXCL, O_EXCL }, + { SparcSolaris::TGT_O_NONBLOCK, O_NONBLOCK }, + { SparcSolaris::TGT_O_NDELAY , O_NONBLOCK }, + { SparcSolaris::TGT_O_NOCTTY, O_NOCTTY }, #ifdef O_SYNC - { SparcSolaris::TGT_O_SYNC, O_SYNC }, - { SparcSolaris::TGT_O_DSYNC, O_SYNC }, - { SparcSolaris::TGT_O_RSYNC, O_SYNC }, + { SparcSolaris::TGT_O_SYNC, O_SYNC }, + { SparcSolaris::TGT_O_DSYNC, O_SYNC }, + { SparcSolaris::TGT_O_RSYNC, O_SYNC }, #endif #endif /* _MSC_VER */ }; diff --git a/src/arch/sparc/solaris/solaris.hh b/src/arch/sparc/solaris/solaris.hh index 0564faba4..df2565027 100644 --- a/src/arch/sparc/solaris/solaris.hh +++ b/src/arch/sparc/solaris/solaris.hh @@ -39,22 +39,22 @@ class SparcSolaris : public Solaris static OpenFlagTransTable openFlagTable[]; - static const int TGT_O_RDONLY = 0x00000000; //!< O_RDONLY - static const int TGT_O_WRONLY = 0x00000001; //!< O_WRONLY - static const int TGT_O_RDWR = 0x00000002; //!< O_RDWR - static const int TGT_O_NDELAY = 0x00000004; //!< O_NONBLOCK - static const int TGT_O_APPEND = 0x00000008; //!< O_APPEND + static const int TGT_O_RDONLY = 0x00000000; //!< O_RDONLY + static const int TGT_O_WRONLY = 0x00000001; //!< O_WRONLY + static const int TGT_O_RDWR = 0x00000002; //!< O_RDWR + static const int TGT_O_NDELAY = 0x00000004; //!< O_NONBLOCK + static const int TGT_O_APPEND = 0x00000008; //!< O_APPEND static const int TGT_O_SYNC = 0x00000010; //!< O_SYNC static const int TGT_O_DSYNC = 0x00000040; //!< O_SYNC static const int TGT_O_RSYNC = 0x00008000; //!< O_SYNC static const int TGT_O_NONBLOCK = 0x00000080; //!< O_NONBLOCK static const int TGT_O_PRIV = 0x00001000; //?? static const int TGT_O_LARGEFILE = 0x00002000; //?? - static const int TGT_O_CREAT = 0x00000100; //!< O_CREAT - static const int TGT_O_TRUNC = 0x00000200; //!< O_TRUNC - static const int TGT_O_EXCL = 0x00000400; //!< O_EXCL - static const int TGT_O_NOCTTY = 0x00000800; //!< O_NOCTTY - static const int TGT_O_XATTR = 0x00004000; //?? + static const int TGT_O_CREAT = 0x00000100; //!< O_CREAT + static const int TGT_O_TRUNC = 0x00000200; //!< O_TRUNC + static const int TGT_O_EXCL = 0x00000400; //!< O_EXCL + static const int TGT_O_NOCTTY = 0x00000800; //!< O_NOCTTY + static const int TGT_O_XATTR = 0x00004000; //?? static const int NUM_OPEN_FLAGS; diff --git a/src/arch/sparc/sparc_traits.hh b/src/arch/sparc/sparc_traits.hh index 715c08c03..e154ba274 100644 --- a/src/arch/sparc/sparc_traits.hh +++ b/src/arch/sparc/sparc_traits.hh @@ -47,8 +47,8 @@ namespace SparcISA // const int NumRegularIntRegs = MaxGL * 8 + NWindows * 16; // const int NumMicroIntRegs = 1; // const int NumIntRegs = -// NumRegularIntRegs + -// NumMicroIntRegs; +// NumRegularIntRegs + +// NumMicroIntRegs; // const int NumFloatRegs = 64; // const int NumMiscRegs = 40; } diff --git a/src/arch/x86/isa/insts/general_purpose/cache_and_memory_management.py b/src/arch/x86/isa/insts/general_purpose/cache_and_memory_management.py index b5fc43fcd..08b842825 100644 --- a/src/arch/x86/isa/insts/general_purpose/cache_and_memory_management.py +++ b/src/arch/x86/isa/insts/general_purpose/cache_and_memory_management.py @@ -56,17 +56,17 @@ microcode = "" #let {{ # class LFENCE(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class SFENCE(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class MFENCE(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class PREFETCHlevel(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class PREFETCH(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class PREFETCHW(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class CLFLUSH(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" #}}; diff --git a/src/arch/x86/isa/insts/general_purpose/control_transfer/call.py b/src/arch/x86/isa/insts/general_purpose/control_transfer/call.py index 45a7822fb..7abafe253 100644 --- a/src/arch/x86/isa/insts/general_purpose/control_transfer/call.py +++ b/src/arch/x86/isa/insts/general_purpose/control_transfer/call.py @@ -103,5 +103,5 @@ def macroop CALL_NEAR_P ''' #let {{ # class CALL(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" #}}; diff --git a/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py b/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py index 327361746..be562b424 100644 --- a/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py +++ b/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py @@ -239,7 +239,7 @@ def macroop IRET_VIRT { ''' #let {{ # class INT(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class INTO(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" #}}; diff --git a/src/arch/x86/isa/insts/general_purpose/data_conversion/ascii_adjust.py b/src/arch/x86/isa/insts/general_purpose/data_conversion/ascii_adjust.py index a1e322e56..2cbdd1ad8 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_conversion/ascii_adjust.py +++ b/src/arch/x86/isa/insts/general_purpose/data_conversion/ascii_adjust.py @@ -56,11 +56,11 @@ microcode = "" #let {{ # class AAA(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class AAD(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class AAM(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class AAS(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" #}}; diff --git a/src/arch/x86/isa/insts/general_purpose/data_conversion/bcd_adjust.py b/src/arch/x86/isa/insts/general_purpose/data_conversion/bcd_adjust.py index 213724768..d220fdeb6 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_conversion/bcd_adjust.py +++ b/src/arch/x86/isa/insts/general_purpose/data_conversion/bcd_adjust.py @@ -56,7 +56,7 @@ microcode = "" #let {{ # class DAA(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class DAS(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" #}}; diff --git a/src/arch/x86/isa/insts/general_purpose/data_conversion/endian_conversion.py b/src/arch/x86/isa/insts/general_purpose/data_conversion/endian_conversion.py index b98d09816..b375ac27e 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_conversion/endian_conversion.py +++ b/src/arch/x86/isa/insts/general_purpose/data_conversion/endian_conversion.py @@ -56,5 +56,5 @@ microcode = "" #let {{ # class BSWAP(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" #}}; diff --git a/src/arch/x86/isa/insts/general_purpose/data_conversion/extract_sign_mask.py b/src/arch/x86/isa/insts/general_purpose/data_conversion/extract_sign_mask.py index 1e0810594..01fa280fc 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_conversion/extract_sign_mask.py +++ b/src/arch/x86/isa/insts/general_purpose/data_conversion/extract_sign_mask.py @@ -56,7 +56,7 @@ microcode = "" #let {{ # class MOVMSKPS(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class MOVMSKPD(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" #}}; diff --git a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py index 35f0436f5..d965735f5 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py +++ b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py @@ -342,7 +342,7 @@ processDescriptor: ''' #let {{ # class MOVD(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class MOVNTI(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" #}}; diff --git a/src/arch/x86/isa/insts/general_purpose/load_segment_registers.py b/src/arch/x86/isa/insts/general_purpose/load_segment_registers.py index 8aec4b99e..e6633ee1a 100644 --- a/src/arch/x86/isa/insts/general_purpose/load_segment_registers.py +++ b/src/arch/x86/isa/insts/general_purpose/load_segment_registers.py @@ -56,17 +56,17 @@ microcode = "" #let {{ # class LDS(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class LES(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class LFS(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class LGS(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class LSS(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class MOV_SEG(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class POP(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" #}}; diff --git a/src/arch/x86/isa/insts/general_purpose/semaphores.py b/src/arch/x86/isa/insts/general_purpose/semaphores.py index 27a31dbd9..da16477fc 100644 --- a/src/arch/x86/isa/insts/general_purpose/semaphores.py +++ b/src/arch/x86/isa/insts/general_purpose/semaphores.py @@ -81,7 +81,7 @@ def macroop CMPXCHG_P_R { ''' #let {{ # class XADD(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class XCHG(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" #}}; diff --git a/src/arch/x86/isa/insts/general_purpose/system_calls.py b/src/arch/x86/isa/insts/general_purpose/system_calls.py index e056bea84..b3a57eca9 100644 --- a/src/arch/x86/isa/insts/general_purpose/system_calls.py +++ b/src/arch/x86/isa/insts/general_purpose/system_calls.py @@ -56,11 +56,11 @@ microcode = "" #let {{ # class SYSENTER(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class SYSEXIT(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class SYSCALL(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" # class SYSRET(Inst): -# "GenFault ${new UnimpInstFault}" +# "GenFault ${new UnimpInstFault}" #}}; diff --git a/src/arch/x86/linux/linux.hh b/src/arch/x86/linux/linux.hh index 8d6468f06..dbc336da1 100644 --- a/src/arch/x86/linux/linux.hh +++ b/src/arch/x86/linux/linux.hh @@ -87,21 +87,21 @@ class X86Linux64 : public Linux static OpenFlagTransTable openFlagTable[]; - static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY - static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY - static const int TGT_O_RDWR = 00000002; //!< O_RDWR - static const int TGT_O_NONBLOCK = 00004000; //!< O_NONBLOCK - static const int TGT_O_APPEND = 00002000; //!< O_APPEND - static const int TGT_O_CREAT = 00000100; //!< O_CREAT - static const int TGT_O_TRUNC = 00001000; //!< O_TRUNC - static const int TGT_O_EXCL = 00000200; //!< O_EXCL - static const int TGT_O_NOCTTY = 00000400; //!< O_NOCTTY - static const int TGT_O_SYNC = 00010000; //!< O_SYNC -// static const int TGT_O_DRD = 0x00010000; //!< O_DRD -// static const int TGT_O_DIRECTIO = 0x00020000; //!< O_DIRECTIO -// static const int TGT_O_CACHE = 0x00002000; //!< O_CACHE -// static const int TGT_O_DSYNC = 0x00008000; //!< O_DSYNC -// static const int TGT_O_RSYNC = 0x00040000; //!< O_RSYNC + static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY + static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY + static const int TGT_O_RDWR = 00000002; //!< O_RDWR + static const int TGT_O_NONBLOCK = 00004000; //!< O_NONBLOCK + static const int TGT_O_APPEND = 00002000; //!< O_APPEND + static const int TGT_O_CREAT = 00000100; //!< O_CREAT + static const int TGT_O_TRUNC = 00001000; //!< O_TRUNC + static const int TGT_O_EXCL = 00000200; //!< O_EXCL + static const int TGT_O_NOCTTY = 00000400; //!< O_NOCTTY + static const int TGT_O_SYNC = 00010000; //!< O_SYNC +// static const int TGT_O_DRD = 0x00010000; //!< O_DRD +// static const int TGT_O_DIRECTIO = 0x00020000; //!< O_DIRECTIO +// static const int TGT_O_CACHE = 0x00002000; //!< O_CACHE +// static const int TGT_O_DSYNC = 0x00008000; //!< O_DSYNC +// static const int TGT_O_RSYNC = 0x00040000; //!< O_RSYNC static const int NUM_OPEN_FLAGS; diff --git a/src/arch/x86/remote_gdb.cc b/src/arch/x86/remote_gdb.cc index 5ab0ec3fb..3a024e087 100644 --- a/src/arch/x86/remote_gdb.cc +++ b/src/arch/x86/remote_gdb.cc @@ -57,7 +57,7 @@ /* * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. + * The Regents of the University of California. All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and @@ -65,8 +65,8 @@ * * All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Lawrence Berkeley Laboratories. + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -78,8 +78,8 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. + * This product includes software developed by the University of + * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -96,7 +96,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94 + * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94 */ /*- @@ -116,8 +116,8 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. diff --git a/src/base/bitunion.hh b/src/base/bitunion.hh index 507fafecd..8ba28f3ba 100644 --- a/src/base/bitunion.hh +++ b/src/base/bitunion.hh @@ -34,7 +34,7 @@ #include #include "base/bitfield.hh" -// The following implements the BitUnion system of defining bitfields +// The following implements the BitUnion system of defining bitfields //on top of an underlying class. This is done through the pervasive use of //both named and unnamed unions which all contain the same actual storage. //Since they're unioned with each other, all of these storage locations diff --git a/src/base/crc.cc b/src/base/crc.cc index 08f039577..ce837a408 100644 --- a/src/base/crc.cc +++ b/src/base/crc.cc @@ -1,6 +1,6 @@ /* * Copyright (c) 1988, 1992, 1993 - * The Regents of the University of California. All rights reserved. + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -12,8 +12,8 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. + * This product includes software developed by the University of + * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. diff --git a/src/base/fast_alloc.cc b/src/base/fast_alloc.cc index e263df893..3e43ad94c 100644 --- a/src/base/fast_alloc.cc +++ b/src/base/fast_alloc.cc @@ -56,7 +56,7 @@ void *FastAlloc::moreStructs(int bucket) assert(bucket > 0 && bucket < Num_Buckets); int sz = bucket * Alloc_Quantum; - const int nstructs = Num_Structs_Per_New; // how many to allocate? + const int nstructs = Num_Structs_Per_New; // how many to allocate? char *p = ::new char[nstructs * sz]; #if FAST_ALLOC_STATS diff --git a/src/base/fast_alloc.hh b/src/base/fast_alloc.hh index 50b761c9c..794a4afcc 100644 --- a/src/base/fast_alloc.hh +++ b/src/base/fast_alloc.hh @@ -84,7 +84,7 @@ class FastAlloc { #if FAST_ALLOC_DEBUG FastAlloc(); - FastAlloc(FastAlloc*,FastAlloc*); // for inUseHead, see below + FastAlloc(FastAlloc*,FastAlloc*); // for inUseHead, see below virtual ~FastAlloc(); #else virtual ~FastAlloc() {} @@ -123,13 +123,13 @@ class FastAlloc { #if FAST_ALLOC_DEBUG // per-object debugging fields - bool inUse; // in-use flag - FastAlloc *inUsePrev; // ptrs to build list of in-use objects + bool inUse; // in-use flag + FastAlloc *inUsePrev; // ptrs to build list of in-use objects FastAlloc *inUseNext; // static (global) debugging vars - static int numInUse; // count in-use objects - static FastAlloc inUseHead; // dummy head for list of in-use objects + static int numInUse; // count in-use objects + static FastAlloc inUseHead; // dummy head for list of in-use objects public: // functions to dump debugging info (see fast_alloc.cc for C diff --git a/src/base/inifile.hh b/src/base/inifile.hh index 631b29b87..a2692919f 100644 --- a/src/base/inifile.hh +++ b/src/base/inifile.hh @@ -61,8 +61,8 @@ class IniFile /// class Entry { - std::string value; ///< The entry value. - mutable bool referenced; ///< Has this entry been used? + std::string value; ///< The entry value. + mutable bool referenced; ///< Has this entry been used? public: /// Constructor. @@ -96,8 +96,8 @@ class IniFile /// EntryTable type. Map of strings to Entry object pointers. typedef m5::hash_map EntryTable; - EntryTable table; ///< Table of entries. - mutable bool referenced; ///< Has this section been used? + EntryTable table; ///< Table of entries. + mutable bool referenced; ///< Has this section been used? public: /// Constructor. diff --git a/src/base/loader/aout_object.cc b/src/base/loader/aout_object.cc index 8fbad8030..1412adfc3 100644 --- a/src/base/loader/aout_object.cc +++ b/src/base/loader/aout_object.cc @@ -34,7 +34,7 @@ #include "base/loader/symtab.hh" -#include "base/trace.hh" // for DPRINTF +#include "base/trace.hh" // for DPRINTF #include "base/loader/exec_aout.h" diff --git a/src/base/loader/coff_sym.h b/src/base/loader/coff_sym.h index 4c6540395..be0631141 100644 --- a/src/base/loader/coff_sym.h +++ b/src/base/loader/coff_sym.h @@ -65,7 +65,7 @@ * * Symbols are assumed to be in 'encounter order' - i.e. the order that * the things they represent were encountered by the compiler/assembler/loader. - * EXCEPT for globals! These are assumed to be bunched together, + * EXCEPT for globals! These are assumed to be bunched together, * probably right after the last 'normal' symbol. Globals ARE sorted * in ascending order. * @@ -76,13 +76,13 @@ * All "ifooMax" values are the highest legal value PLUS ONE. This makes * them good for allocating arrays, etc. All checks are "ifoo < ifooMax". * - * "isym" Index into the SYMbol table. - * "ipd" Index into the Procedure Descriptor array. - * "ifd" Index into the File Descriptor array. - * "iss" Index into String Space. - * "cb" Count of Bytes. - * "rgPd" array whose domain is "0..ipdMax-1" and RanGe is PDR. - * "rgFd" array whose domain is "0..ifdMax-1" and RanGe is FDR. + * "isym" Index into the SYMbol table. + * "ipd" Index into the Procedure Descriptor array. + * "ifd" Index into the File Descriptor array. + * "iss" Index into String Space. + * "cb" Count of Bytes. + * "rgPd" array whose domain is "0..ipdMax-1" and RanGe is PDR. + * "rgFd" array whose domain is "0..ifdMax-1" and RanGe is FDR. */ @@ -97,31 +97,31 @@ */ typedef struct ecoff_symhdr { - coff_short magic; /* to verify validity of the table */ - coff_short vstamp; /* version stamp */ - coff_int ilineMax; /* number of line number entries */ - coff_int idnMax; /* max index into dense number table */ - coff_int ipdMax; /* number of procedures */ - coff_int isymMax; /* number of local symbols */ - coff_int ioptMax; /* max index into optimization symbol entries */ - coff_int iauxMax; /* number of auxillary symbol entries */ - coff_int issMax; /* max index into local strings */ - coff_int issExtMax; /* max index into external strings */ - coff_int ifdMax; /* number of file descriptor entries */ - coff_int crfd; /* number of relative file descriptor entries */ - coff_int iextMax; /* max index into external symbols */ - coff_addr cbLine; /* number of bytes for line number entries */ - coff_addr cbLineOffset; /* offset to start of line number entries*/ - coff_addr cbDnOffset; /* offset to start dense number table */ - coff_addr cbPdOffset; /* offset to procedure descriptor table */ - coff_addr cbSymOffset; /* offset to start of local symbols*/ - coff_addr cbOptOffset; /* offset to optimization symbol entries */ - coff_addr cbAuxOffset; /* offset to start of auxillary symbol entries*/ - coff_addr cbSsOffset; /* offset to start of local strings */ - coff_addr cbSsExtOffset; /* offset to start of external strings */ - coff_addr cbFdOffset; /* offset to file descriptor table */ - coff_addr cbRfdOffset; /* offset to relative file descriptor table */ - coff_addr cbExtOffset; /* offset to start of external symbol entries*/ + coff_short magic; /* to verify validity of the table */ + coff_short vstamp; /* version stamp */ + coff_int ilineMax; /* number of line number entries */ + coff_int idnMax; /* max index into dense number table */ + coff_int ipdMax; /* number of procedures */ + coff_int isymMax; /* number of local symbols */ + coff_int ioptMax; /* max index into optimization symbol entries */ + coff_int iauxMax; /* number of auxillary symbol entries */ + coff_int issMax; /* max index into local strings */ + coff_int issExtMax; /* max index into external strings */ + coff_int ifdMax; /* number of file descriptor entries */ + coff_int crfd; /* number of relative file descriptor entries */ + coff_int iextMax; /* max index into external symbols */ + coff_addr cbLine; /* number of bytes for line number entries */ + coff_addr cbLineOffset; /* offset to start of line number entries*/ + coff_addr cbDnOffset; /* offset to start dense number table */ + coff_addr cbPdOffset; /* offset to procedure descriptor table */ + coff_addr cbSymOffset; /* offset to start of local symbols*/ + coff_addr cbOptOffset; /* offset to optimization symbol entries */ + coff_addr cbAuxOffset; /* offset to start of auxillary symbol entries*/ + coff_addr cbSsOffset; /* offset to start of local strings */ + coff_addr cbSsExtOffset; /* offset to start of external strings */ + coff_addr cbFdOffset; /* offset to file descriptor table */ + coff_addr cbRfdOffset; /* offset to relative file descriptor table */ + coff_addr cbExtOffset; /* offset to start of external symbol entries*/ /* If you add machine dependent fields, add them here */ } HDRR, *pHDRR; #define cbHDRR sizeof(HDRR) @@ -138,39 +138,39 @@ typedef struct ecoff_symhdr { * * There is one of these for EVERY FILE, whether compiled with * full debugging symbols or not. The name of a file should be - * the path name given to the compiler. This allows the user + * the path name given to the compiler. This allows the user * to simply specify the names of the directories where the COMPILES * were done, and we will be able to find their files. * A field whose comment starts with "R - " indicates that it will be * setup at runtime. */ typedef struct ecoff_fdr { - coff_addr adr; /* memory address of beginning of file */ - coff_addr cbLineOffset; /* byte offset from header for this file ln's */ - coff_addr cbLine; /* size of lines for this file */ - coff_addr cbSs; /* number of bytes in the ss */ - coff_int rss; /* file name (of source, if known) */ - coff_int issBase; /* file's string space */ - coff_int isymBase; /* beginning of symbols */ - coff_int csym; /* count file's of symbols */ - coff_int ilineBase; /* file's line symbols */ - coff_int cline; /* count of file's line symbols */ - coff_int ioptBase; /* file's optimization entries */ - coff_int copt; /* count of file's optimization entries */ - coff_int ipdFirst; /* start of procedures for this file */ - coff_int cpd; /* count of procedures for this file */ - coff_int iauxBase; /* file's auxiliary entries */ - coff_int caux; /* count of file's auxiliary entries */ - coff_int rfdBase; /* index into the file indirect table */ - coff_int crfd; /* count file indirect entries */ - unsigned lang: 5; /* language for this file */ - unsigned fMerge : 1; /* whether this file can be merged */ - unsigned fReadin : 1; /* true if it was read in (not just created) */ + coff_addr adr; /* memory address of beginning of file */ + coff_addr cbLineOffset; /* byte offset from header for this file ln's */ + coff_addr cbLine; /* size of lines for this file */ + coff_addr cbSs; /* number of bytes in the ss */ + coff_int rss; /* file name (of source, if known) */ + coff_int issBase; /* file's string space */ + coff_int isymBase; /* beginning of symbols */ + coff_int csym; /* count file's of symbols */ + coff_int ilineBase; /* file's line symbols */ + coff_int cline; /* count of file's line symbols */ + coff_int ioptBase; /* file's optimization entries */ + coff_int copt; /* count of file's optimization entries */ + coff_int ipdFirst; /* start of procedures for this file */ + coff_int cpd; /* count of procedures for this file */ + coff_int iauxBase; /* file's auxiliary entries */ + coff_int caux; /* count of file's auxiliary entries */ + coff_int rfdBase; /* index into the file indirect table */ + coff_int crfd; /* count file indirect entries */ + unsigned lang: 5; /* language for this file */ + unsigned fMerge : 1; /* whether this file can be merged */ + unsigned fReadin : 1; /* true if it was read in (not just created) */ unsigned fBigendian : 1;/* if set, was compiled on big endian machine */ - /* aux's will be in compile host's sex */ - unsigned glevel : 2; /* level this file was compiled with */ + /* aux's will be in compile host's sex */ + unsigned glevel : 2; /* level this file was compiled with */ unsigned reserved : 22; /* reserved for future use */ - coff_uint reserved2; + coff_uint reserved2; } FDR, *pFDR; #define cbFDR sizeof(FDR) #define fdNil ((pFDR)0) @@ -189,31 +189,31 @@ typedef struct ecoff_fdr { */ typedef struct pdr { - coff_addr adr; /* memory address of start of procedure */ - coff_addr cbLineOffset; /* byte offset for this procedure from the fd base */ - coff_int isym; /* start of local symbol entries */ - coff_int iline; /* start of line number entries*/ - coff_uint regmask; /* save register mask */ - coff_int regoffset; /* save register offset */ - coff_int iopt; /* start of optimization symbol entries*/ - coff_uint fregmask; /* save floating point register mask */ - coff_int fregoffset; /* save floating point register offset */ - coff_int frameoffset; /* frame size */ - coff_int lnLow; /* lowest line in the procedure */ - coff_int lnHigh; /* highest line in the procedure */ + coff_addr adr; /* memory address of start of procedure */ + coff_addr cbLineOffset; /* byte offset for this procedure from the fd base */ + coff_int isym; /* start of local symbol entries */ + coff_int iline; /* start of line number entries*/ + coff_uint regmask; /* save register mask */ + coff_int regoffset; /* save register offset */ + coff_int iopt; /* start of optimization symbol entries*/ + coff_uint fregmask; /* save floating point register mask */ + coff_int fregoffset; /* save floating point register offset */ + coff_int frameoffset; /* frame size */ + coff_int lnLow; /* lowest line in the procedure */ + coff_int lnHigh; /* highest line in the procedure */ /* These fields are new for 64 bit ECOFF. */ unsigned gp_prologue : 8; /* byte size of GP prologue */ - unsigned gp_used : 1; /* true if the procedure uses GP */ - unsigned reg_frame : 1; /* true if register frame procedure */ - unsigned prof : 1; /* true if compiled with -pg */ - unsigned reserved : 13; /* reserved: must be zero */ - unsigned localoff : 8; /* offset of local variables from vfp */ - coff_short framereg; /* frame pointer register */ - coff_short pcreg; /* offset or reg of return pc */ + unsigned gp_used : 1; /* true if the procedure uses GP */ + unsigned reg_frame : 1; /* true if register frame procedure */ + unsigned prof : 1; /* true if compiled with -pg */ + unsigned reserved : 13; /* reserved: must be zero */ + unsigned localoff : 8; /* offset of local variables from vfp */ + coff_short framereg; /* frame pointer register */ + coff_short pcreg; /* offset or reg of return pc */ } PDR, *pPDR; #define cbPDR sizeof(PDR) #define pdNil ((pPDR) 0) -#define ipdNil -1 +#define ipdNil -1 /* * The structure of the runtime procedure descriptor created by the loader @@ -225,16 +225,16 @@ typedef struct pdr { */ #if 0 typedef struct runtime_pdr { - coff_addr adr; /* memory address of start of procedure */ - coff_uint regmask; /* save register mask */ - coff_int regoffset; /* save register offset */ - coff_uint fregmask; /* save floating point register mask */ - coff_int fregoffset; /* save floating point register offset */ - coff_int frameoffset; /* frame size */ - coff_ushort framereg; /* frame pointer register */ - coff_ushort pcreg; /* offset or reg of return pc */ - coff_int irpss; /* index into the runtime string table */ - coff_uint reserved; + coff_addr adr; /* memory address of start of procedure */ + coff_uint regmask; /* save register mask */ + coff_int regoffset; /* save register offset */ + coff_uint fregmask; /* save floating point register mask */ + coff_int fregoffset; /* save floating point register offset */ + coff_int frameoffset; /* frame size */ + coff_ushort framereg; /* frame pointer register */ + coff_ushort pcreg; /* offset or reg of return pc */ + coff_int irpss; /* index into the runtime string table */ + coff_uint reserved; struct exception_info *exception_info;/* pointer to exception array */ } RPDR, *pRPDR; #define cbRPDR sizeof(RPDR) @@ -253,24 +253,24 @@ typedef struct runtime_pdr { * the first line of a procedure and represent the first address. */ -typedef coff_int LINER, *pLINER; +typedef coff_int LINER, *pLINER; #define lineNil ((pLINER)0) #define cbLINER sizeof(LINER) -#define ilineNil -1 +#define ilineNil -1 /* - * The Symbol Structure (GFW, to those who Know!) + * The Symbol Structure (GFW, to those who Know!) */ typedef struct ecoff_sym { - coff_long value; /* value of symbol */ - coff_int iss; /* index into String Space of name */ - unsigned st : 6; /* symbol type */ - unsigned sc : 5; /* storage class - text, data, etc */ - unsigned reserved : 1; /* reserved */ - unsigned index : 20; /* index into sym/aux table */ + coff_long value; /* value of symbol */ + coff_int iss; /* index into String Space of name */ + unsigned st : 6; /* symbol type */ + unsigned sc : 5; /* storage class - text, data, etc */ + unsigned reserved : 1; /* reserved */ + unsigned index : 20; /* index into sym/aux table */ } SYMR, *pSYMR; #define symNil ((pSYMR)0) #define cbSYMR sizeof(SYMR) @@ -287,22 +287,22 @@ typedef struct ecoff_sym { /* E X T E R N A L S Y M B O L R E C O R D * - * Same as the SYMR except it contains file context to determine where - * the index is. + * Same as the SYMR except it contains file context to determine where + * the index is. */ typedef struct ecoff_extsym { - SYMR asym; /* symbol for the external */ - unsigned jmptbl:1; /* symbol is a jump table entry for shlibs */ - unsigned cobol_main:1; /* symbol is a cobol main procedure */ - unsigned weakext:1; /* symbol is weak external */ - unsigned reserved:29; /* reserved for future use */ - coff_int ifd; /* where the iss and index fields point into */ + SYMR asym; /* symbol for the external */ + unsigned jmptbl:1; /* symbol is a jump table entry for shlibs */ + unsigned cobol_main:1; /* symbol is a cobol main procedure */ + unsigned weakext:1; /* symbol is weak external */ + unsigned reserved:29; /* reserved for future use */ + coff_int ifd; /* where the iss and index fields point into */ } EXTR, *pEXTR; #define extNil ((pEXTR)0) #define cbEXTR sizeof(EXTR) -/* A U X I L L A R Y T Y P E I N F O R M A T I O N */ +/* A U X I L L A R Y T Y P E I N F O R M A T I O N */ /* * Type Information Record @@ -310,12 +310,12 @@ typedef struct ecoff_extsym { typedef struct { unsigned fBitfield : 1; /* set if bit width is specified */ unsigned continued : 1; /* indicates additional TQ info in next AUX */ - unsigned bt : 6; /* basic type */ + unsigned bt : 6; /* basic type */ unsigned tq4 : 4; unsigned tq5 : 4; /* ---- 16 bit boundary ---- */ unsigned tq0 : 4; - unsigned tq1 : 4; /* 6 type qualifiers - tqPtr, etc. */ + unsigned tq1 : 4; /* 6 type qualifiers - tqPtr, etc. */ unsigned tq2 : 4; unsigned tq3 : 4; } TIR, *pTIR; @@ -327,22 +327,22 @@ typedef struct { * Relative symbol record * * If the rfd field is 4095, the index field indexes into the global symbol - * table. + * table. */ typedef struct { - unsigned rfd : 12; /* index into the file indirect table */ - unsigned index : 20; /* index int sym/aux/iss tables */ + unsigned rfd : 12; /* index into the file indirect table */ + unsigned index : 20; /* index int sym/aux/iss tables */ } RNDXR, *pRNDXR; #define cbRNDXR sizeof(RNDXR) #define rndxNil ((pRNDXR)0) /* dense numbers or sometimes called block numbers are stored in this type, - * a rfd of 0xffffffff is an index into the global table. + * a rfd of 0xffffffff is an index into the global table. */ typedef struct { - coff_uint rfd; /* index into the file table */ - coff_uint index; /* index int sym/aux/iss tables */ + coff_uint rfd; /* index into the file table */ + coff_uint index; /* index int sym/aux/iss tables */ } DNR, *pDNR; #define cbDNR sizeof(DNR) #define dnNil ((pDNR)0) @@ -353,36 +353,36 @@ typedef struct { * Auxillary information occurs only if needed. * It ALWAYS occurs in this order when present. - isymMac used by stProc only - TIR type info - TIR additional TQ info (if first TIR was not enough) - rndx if (bt == btStruct,btUnion,btEnum,btSet,btRange, + isymMac used by stProc only + TIR type info + TIR additional TQ info (if first TIR was not enough) + rndx if (bt == btStruct,btUnion,btEnum,btSet,btRange, btTypedef): rsym.index == iaux for btSet or btRange else rsym.index == isym - dimLow btRange, btSet - dimMac btRange, btSet - rndx0 As many as there are tq arrays + dimLow btRange, btSet + dimMac btRange, btSet + rndx0 As many as there are tq arrays dimLow0 dimHigh0 ... rndxMax-1 dimLowMax-1 dimHighMax-1 - width in bits if (bit field), width in bits. + width in bits if (bit field), width in bits. */ #define cAuxMax (6 + (idimMax*3)) /* a union of all possible info in the AUX universe */ typedef union { - TIR ti; /* type information record */ - RNDXR rndx; /* relative index into symbol table */ - coff_int dnLow; /* low dimension */ - coff_int dnHigh; /* high dimension */ - coff_int isym; /* symbol table index (end of proc) */ - coff_int iss; /* index into string space (not used) */ - coff_int width; /* width for non-default sized struc fields */ - coff_int count; /* count of ranges for variant arm */ + TIR ti; /* type information record */ + RNDXR rndx; /* relative index into symbol table */ + coff_int dnLow; /* low dimension */ + coff_int dnHigh; /* high dimension */ + coff_int isym; /* symbol table index (end of proc) */ + coff_int iss; /* index into string space (not used) */ + coff_int width; /* width for non-default sized struc fields */ + coff_int count; /* count of ranges for variant arm */ } AUXU, *pAUXU; #define cbAUXU sizeof(AUXU) #define auxNil ((pAUXU)0) @@ -401,12 +401,12 @@ typedef union { */ typedef struct { - unsigned ot: 8; /* optimization type */ - unsigned value: 24; /* address where we are moving it to */ - RNDXR rndx; /* points to a symbol or opt entry */ - coff_ulong offset; /* relative offset this occured */ + unsigned ot: 8; /* optimization type */ + unsigned value: 24; /* address where we are moving it to */ + RNDXR rndx; /* points to a symbol or opt entry */ + coff_ulong offset; /* relative offset this occured */ } OPTR, *pOPTR; -#define optNil ((pOPTR) 0) +#define optNil ((pOPTR) 0) #define cbOPTR sizeof(OPTR) #define ioptNil -1 @@ -414,15 +414,15 @@ typedef struct { * File Indirect * * When a symbol is referenced across files the following procedure is used: - * 1) use the file index to get the File indirect entry. - * 2) use the file indirect entry to get the File descriptor. - * 3) add the sym index to the base of that file's sym table + * 1) use the file index to get the File indirect entry. + * 2) use the file indirect entry to get the File descriptor. + * 3) add the sym index to the base of that file's sym table * */ typedef coff_long RFDT, *pRFDT; #define cbRFDT sizeof(RFDT) -#define rfdNil -1 +#define rfdNil -1 /* * The file indirect table in the mips loader is known as an array of FITs. @@ -430,9 +430,9 @@ typedef coff_long RFDT, *pRFDT; * these tables are merged. Note this is only a name change. */ typedef coff_int FIT, *pFIT; -#define cbFIT sizeof(FIT) -#define ifiNil -1 -#define fiNil ((pFIT) 0) +#define cbFIT sizeof(FIT) +#define ifiNil -1 +#define fiNil ((pFIT) 0) #ifdef _LANGUAGE_PASCAL #define ifdNil -1 @@ -448,18 +448,18 @@ typedef coff_int FIT, *pFIT; #define ioptNil -1 #define rfdNil -1 #define ifiNil -1 -#endif /* _LANGUAGE_PASCAL */ +#endif /* _LANGUAGE_PASCAL */ /* Dense numbers * * Rather than use file index, symbol index pairs to represent symbols - * and globals, we use dense number so that they can be easily embeded - * in intermediate code and the programs that process them can - * use direct access tabls instead of hash table (which would be - * necesary otherwise because of the sparse name space caused by - * file index, symbol index pairs. Dense number are represented - * by RNDXRs. + * and globals, we use dense number so that they can be easily embeded + * in intermediate code and the programs that process them can + * use direct access tabls instead of hash table (which would be + * necesary otherwise because of the sparse name space caused by + * file index, symbol index pairs. Dense number are represented + * by RNDXRs. */ /* @@ -467,7 +467,7 @@ typedef coff_int FIT, *pFIT; * a function of the "st". (scD/B == scData OR scBss) * * Note: the value "isymMac" is used by symbols that have the concept - * of enclosing a block of related information. This value is the + * of enclosing a block of related information. This value is the * isym of the first symbol AFTER the end associated with the primary * symbol. For example if a procedure was at isym==90 and had an * isymMac==155, the associated end would be at isym==154, and the @@ -477,42 +477,42 @@ typedef coff_int FIT, *pFIT; * isym of the primary symbol that started the block. * -ST SC VALUE INDEX --------- ------ -------- ------ -stFile scText address isymMac -stLabel scText address --- -stGlobal scD/B address iaux -stStatic scD/B address iaux -stParam scAbs offset iaux -stLocal scAbs offset iaux -stProc scText address iaux (isymMac is first AUX) -stStaticProc scText address iaux (isymMac is first AUX) - -stMember scNil ordinal --- (if member of enum) +ST SC VALUE INDEX +-------- ------ -------- ------ +stFile scText address isymMac +stLabel scText address --- +stGlobal scD/B address iaux +stStatic scD/B address iaux +stParam scAbs offset iaux +stLocal scAbs offset iaux +stProc scText address iaux (isymMac is first AUX) +stStaticProc scText address iaux (isymMac is first AUX) + +stMember scNil ordinal --- (if member of enum) (mipsread thinks the case below has a bit, not byte, offset.) -stMember scNil byte offset iaux (if member of struct/union) -stMember scBits bit offset iaux (bit field spec) +stMember scNil byte offset iaux (if member of struct/union) +stMember scBits bit offset iaux (bit field spec) -stBlock scText address isymMac (text block) +stBlock scText address isymMac (text block) (the code seems to think that rather than scNil, we see scInfo for the two cases below.) -stBlock scNil cb isymMac (struct/union member define) -stBlock scNil cMembers isymMac (enum member define) +stBlock scNil cb isymMac (struct/union member define) +stBlock scNil cMembers isymMac (enum member define) (New types added by SGI to simplify things:) -stStruct scInfo cb isymMac (struct type define) -stUnion scInfo cb isymMac (union type define) -stEnum scInfo cMembers isymMac (enum type define) +stStruct scInfo cb isymMac (struct type define) +stUnion scInfo cb isymMac (union type define) +stEnum scInfo cMembers isymMac (enum type define) -stEnd scText address isymStart -stEnd scNil ------- isymStart (struct/union/enum) +stEnd scText address isymStart +stEnd scNil ------- isymStart (struct/union/enum) -stTypedef scNil ------- iaux -stRegReloc sc??? value old register number -stForward sc??? new address isym to original symbol +stTypedef scNil ------- iaux +stRegReloc sc??? value old register number +stForward sc??? new address isym to original symbol -stConstant scInfo value --- (scalar) -stConstant scInfo iss --- (complex, e.g. string) +stConstant scInfo value --- (scalar) +stConstant scInfo iss --- (complex, e.g. string) * */ diff --git a/src/base/loader/coff_symconst.h b/src/base/loader/coff_symconst.h index f383c19e6..18529113f 100644 --- a/src/base/loader/coff_symconst.h +++ b/src/base/loader/coff_symconst.h @@ -59,30 +59,30 @@ */ /* glevels for field in FDR */ -#define GLEVEL_0 2 -#define GLEVEL_1 1 -#define GLEVEL_2 0 /* for upward compat reasons. */ -#define GLEVEL_3 3 +#define GLEVEL_0 2 +#define GLEVEL_1 1 +#define GLEVEL_2 0 /* for upward compat reasons. */ +#define GLEVEL_3 3 /* magic number fo symheader */ -#define magicSym 0x7009 +#define magicSym 0x7009 /* The Alpha uses this value instead, for some reason. */ -#define magicSym2 0x1992 +#define magicSym2 0x1992 /* Language codes */ -#define langC 0 -#define langPascal 1 -#define langFortran 2 -#define langAssembler 3 /* one Assembley inst might map to many mach */ -#define langMachine 4 -#define langNil 5 -#define langAda 6 -#define langPl1 7 -#define langCobol 8 -#define langStdc 9 /* FIXME: Collides with SGI langCplusplus */ -#define langCplusplus 9 /* FIXME: Collides with langStdc */ -#define langCplusplusV2 10 /* SGI addition */ -#define langMax 11 /* maximun allowed 32 -- 5 bits */ +#define langC 0 +#define langPascal 1 +#define langFortran 2 +#define langAssembler 3 /* one Assembley inst might map to many mach */ +#define langMachine 4 +#define langNil 5 +#define langAda 6 +#define langPl1 7 +#define langCobol 8 +#define langStdc 9 /* FIXME: Collides with SGI langCplusplus */ +#define langCplusplus 9 /* FIXME: Collides with langStdc */ +#define langCplusplusV2 10 /* SGI addition */ +#define langMax 11 /* maximun allowed 32 -- 5 bits */ /* The following are value definitions for the fields in the SYMR */ @@ -90,111 +90,111 @@ * Storage Classes */ -#define scNil 0 -#define scText 1 /* text symbol */ -#define scData 2 /* initialized data symbol */ -#define scBss 3 /* un-initialized data symbol */ -#define scRegister 4 /* value of symbol is register number */ -#define scAbs 5 /* value of symbol is absolute */ -#define scUndefined 6 /* who knows? */ -#define scCdbLocal 7 /* variable's value is IN se->va.?? */ -#define scBits 8 /* this is a bit field */ -#define scCdbSystem 9 /* variable's value is IN CDB's address space */ -#define scDbx 9 /* overlap dbx internal use */ -#define scRegImage 10 /* register value saved on stack */ -#define scInfo 11 /* symbol contains debugger information */ -#define scUserStruct 12 /* address in struct user for current process */ -#define scSData 13 /* load time only small data */ -#define scSBss 14 /* load time only small common */ -#define scRData 15 /* load time only read only data */ -#define scVar 16 /* Var parameter (fortran,pascal) */ -#define scCommon 17 /* common variable */ -#define scSCommon 18 /* small common */ -#define scVarRegister 19 /* Var parameter in a register */ -#define scVariant 20 /* Variant record */ -#define scSUndefined 21 /* small undefined(external) data */ -#define scInit 22 /* .init section symbol */ -#define scBasedVar 23 /* Fortran or PL/1 ptr based var */ +#define scNil 0 +#define scText 1 /* text symbol */ +#define scData 2 /* initialized data symbol */ +#define scBss 3 /* un-initialized data symbol */ +#define scRegister 4 /* value of symbol is register number */ +#define scAbs 5 /* value of symbol is absolute */ +#define scUndefined 6 /* who knows? */ +#define scCdbLocal 7 /* variable's value is IN se->va.?? */ +#define scBits 8 /* this is a bit field */ +#define scCdbSystem 9 /* variable's value is IN CDB's address space */ +#define scDbx 9 /* overlap dbx internal use */ +#define scRegImage 10 /* register value saved on stack */ +#define scInfo 11 /* symbol contains debugger information */ +#define scUserStruct 12 /* address in struct user for current process */ +#define scSData 13 /* load time only small data */ +#define scSBss 14 /* load time only small common */ +#define scRData 15 /* load time only read only data */ +#define scVar 16 /* Var parameter (fortran,pascal) */ +#define scCommon 17 /* common variable */ +#define scSCommon 18 /* small common */ +#define scVarRegister 19 /* Var parameter in a register */ +#define scVariant 20 /* Variant record */ +#define scSUndefined 21 /* small undefined(external) data */ +#define scInit 22 /* .init section symbol */ +#define scBasedVar 23 /* Fortran or PL/1 ptr based var */ #define scXData 24 /* exception handling data */ #define scPData 25 /* Procedure section */ #define scFini 26 /* .fini section */ -#define scRConst 27 /* .rconst section */ -#define scMax 32 +#define scRConst 27 /* .rconst section */ +#define scMax 32 /* * Symbol Types */ -#define stNil 0 /* Nuthin' special */ -#define stGlobal 1 /* external symbol */ -#define stStatic 2 /* static */ -#define stParam 3 /* procedure argument */ -#define stLocal 4 /* local variable */ -#define stLabel 5 /* label */ -#define stProc 6 /* " " Procedure */ -#define stBlock 7 /* beginnning of block */ -#define stEnd 8 /* end (of anything) */ -#define stMember 9 /* member (of anything - struct/union/enum */ -#define stTypedef 10 /* type definition */ -#define stFile 11 /* file name */ -#define stRegReloc 12 /* register relocation */ -#define stForward 13 /* forwarding address */ -#define stStaticProc 14 /* load time only static procs */ -#define stConstant 15 /* const */ -#define stStaParam 16 /* Fortran static parameters */ +#define stNil 0 /* Nuthin' special */ +#define stGlobal 1 /* external symbol */ +#define stStatic 2 /* static */ +#define stParam 3 /* procedure argument */ +#define stLocal 4 /* local variable */ +#define stLabel 5 /* label */ +#define stProc 6 /* " " Procedure */ +#define stBlock 7 /* beginnning of block */ +#define stEnd 8 /* end (of anything) */ +#define stMember 9 /* member (of anything - struct/union/enum */ +#define stTypedef 10 /* type definition */ +#define stFile 11 /* file name */ +#define stRegReloc 12 /* register relocation */ +#define stForward 13 /* forwarding address */ +#define stStaticProc 14 /* load time only static procs */ +#define stConstant 15 /* const */ +#define stStaParam 16 /* Fortran static parameters */ /* These new symbol types have been recently added to SGI machines. */ -#define stStruct 26 /* Beginning of block defining a struct type */ -#define stUnion 27 /* Beginning of block defining a union type */ -#define stEnum 28 /* Beginning of block defining an enum type */ -#define stIndirect 34 /* Indirect type specification */ +#define stStruct 26 /* Beginning of block defining a struct type */ +#define stUnion 27 /* Beginning of block defining a union type */ +#define stEnum 28 /* Beginning of block defining an enum type */ +#define stIndirect 34 /* Indirect type specification */ /* Pseudo-symbols - internal to debugger */ -#define stStr 60 /* string */ -#define stNumber 61 /* pure number (ie. 4 NOR 2+2) */ -#define stExpr 62 /* 2+2 vs. 4 */ -#define stType 63 /* post-coersion SER */ -#define stMax 64 +#define stStr 60 /* string */ +#define stNumber 61 /* pure number (ie. 4 NOR 2+2) */ +#define stExpr 62 /* 2+2 vs. 4 */ +#define stType 63 /* post-coersion SER */ +#define stMax 64 /* definitions for fields in TIR */ /* type qualifiers for ti.tq0 -> ti.(itqMax-1) */ -#define tqNil 0 /* bt is what you see */ -#define tqPtr 1 /* pointer */ -#define tqProc 2 /* procedure */ -#define tqArray 3 /* duh */ -#define tqFar 4 /* longer addressing - 8086/8 land */ -#define tqVol 5 /* volatile */ -#define tqConst 6 /* const */ -#define tqMax 8 +#define tqNil 0 /* bt is what you see */ +#define tqPtr 1 /* pointer */ +#define tqProc 2 /* procedure */ +#define tqArray 3 /* duh */ +#define tqFar 4 /* longer addressing - 8086/8 land */ +#define tqVol 5 /* volatile */ +#define tqConst 6 /* const */ +#define tqMax 8 /* basic types as seen in ti.bt */ -#define btNil 0 /* undefined (also, enum members) */ -#define btAdr 1 /* address - integer same size as pointer */ -#define btChar 2 /* character */ -#define btUChar 3 /* unsigned character */ -#define btShort 4 /* short */ -#define btUShort 5 /* unsigned short */ -#define btInt 6 /* int */ -#define btUInt 7 /* unsigned int */ -#define btLong 8 /* long */ -#define btULong 9 /* unsigned long */ -#define btFloat 10 /* float (real) */ -#define btDouble 11 /* Double (real) */ -#define btStruct 12 /* Structure (Record) */ -#define btUnion 13 /* Union (variant) */ -#define btEnum 14 /* Enumerated */ -#define btTypedef 15 /* defined via a typedef, isymRef points */ -#define btRange 16 /* subrange of int */ -#define btSet 17 /* pascal sets */ -#define btComplex 18 /* fortran complex */ -#define btDComplex 19 /* fortran double complex */ -#define btIndirect 20 /* forward or unnamed typedef */ -#define btFixedDec 21 /* Fixed Decimal */ -#define btFloatDec 22 /* Float Decimal */ -#define btString 23 /* Varying Length Character String */ -#define btBit 24 /* Aligned Bit String */ -#define btPicture 25 /* Picture */ -#define btVoid 26 /* void */ -#define btLongLong 27 /* long long */ -#define btULongLong 28 /* unsigned long long */ -#define btMax 64 +#define btNil 0 /* undefined (also, enum members) */ +#define btAdr 1 /* address - integer same size as pointer */ +#define btChar 2 /* character */ +#define btUChar 3 /* unsigned character */ +#define btShort 4 /* short */ +#define btUShort 5 /* unsigned short */ +#define btInt 6 /* int */ +#define btUInt 7 /* unsigned int */ +#define btLong 8 /* long */ +#define btULong 9 /* unsigned long */ +#define btFloat 10 /* float (real) */ +#define btDouble 11 /* Double (real) */ +#define btStruct 12 /* Structure (Record) */ +#define btUnion 13 /* Union (variant) */ +#define btEnum 14 /* Enumerated */ +#define btTypedef 15 /* defined via a typedef, isymRef points */ +#define btRange 16 /* subrange of int */ +#define btSet 17 /* pascal sets */ +#define btComplex 18 /* fortran complex */ +#define btDComplex 19 /* fortran double complex */ +#define btIndirect 20 /* forward or unnamed typedef */ +#define btFixedDec 21 /* Fixed Decimal */ +#define btFloatDec 22 /* Float Decimal */ +#define btString 23 /* Varying Length Character String */ +#define btBit 24 /* Aligned Bit String */ +#define btPicture 25 /* Picture */ +#define btVoid 26 /* void */ +#define btLongLong 27 /* long long */ +#define btULongLong 28 /* unsigned long long */ +#define btMax 64 diff --git a/src/base/loader/ecoff_object.cc b/src/base/loader/ecoff_object.cc index a5a0ad9a4..d1719f1c6 100644 --- a/src/base/loader/ecoff_object.cc +++ b/src/base/loader/ecoff_object.cc @@ -34,7 +34,7 @@ #include "base/misc.hh" #include "base/loader/symtab.hh" -#include "base/trace.hh" // for DPRINTF +#include "base/trace.hh" // for DPRINTF #include "base/loader/exec_ecoff.h" #include "base/loader/coff_sym.h" diff --git a/src/base/loader/elf_object.cc b/src/base/loader/elf_object.cc index 4c3f694e5..ad46a7de5 100644 --- a/src/base/loader/elf_object.cc +++ b/src/base/loader/elf_object.cc @@ -36,7 +36,7 @@ #include "base/loader/elf_object.hh" #include "base/loader/symtab.hh" #include "base/misc.hh" -#include "base/trace.hh" // for DPRINTF +#include "base/trace.hh" // for DPRINTF #include "sim/byteswap.hh" using namespace std; diff --git a/src/base/loader/hex_file.hh b/src/base/loader/hex_file.hh index 3c0a2d1b8..40483e684 100755 --- a/src/base/loader/hex_file.hh +++ b/src/base/loader/hex_file.hh @@ -35,7 +35,7 @@ #include #include -#include "sim/host.hh" // for Addr +#include "sim/host.hh" // for Addr class Port; diff --git a/src/base/loader/object_file.hh b/src/base/loader/object_file.hh index 7f2bef0bf..cc806ca81 100644 --- a/src/base/loader/object_file.hh +++ b/src/base/loader/object_file.hh @@ -35,7 +35,7 @@ #include #include -#include "sim/host.hh" // for Addr +#include "sim/host.hh" // for Addr class Port; class SymbolTable; diff --git a/src/base/loader/symtab.hh b/src/base/loader/symtab.hh index 184c0a996..97a675140 100644 --- a/src/base/loader/symtab.hh +++ b/src/base/loader/symtab.hh @@ -35,7 +35,7 @@ #include #include -#include "sim/host.hh" // for Addr +#include "sim/host.hh" // for Addr class Checkpoint; class SymbolTable diff --git a/src/base/remote_gdb.cc b/src/base/remote_gdb.cc index 06e04e19e..fe4bdad5a 100644 --- a/src/base/remote_gdb.cc +++ b/src/base/remote_gdb.cc @@ -30,7 +30,7 @@ /* * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. + * The Regents of the University of California. All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and @@ -38,8 +38,8 @@ * * All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Lawrence Berkeley Laboratories. + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -51,8 +51,8 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. + * This product includes software developed by the University of + * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -69,7 +69,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94 + * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94 */ /*- @@ -89,8 +89,8 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. diff --git a/src/base/res_list.hh b/src/base/res_list.hh index 442280e15..024b56982 100644 --- a/src/base/res_list.hh +++ b/src/base/res_list.hh @@ -635,7 +635,7 @@ res_list::remove(iterator q) // A little "garbage collection" if (++remove_count > 10) { - // free_extras(); + // free_extras(); remove_count = 0; } diff --git a/src/base/stats/flags.hh b/src/base/stats/flags.hh index 69f73f66a..b8b0171ed 100644 --- a/src/base/stats/flags.hh +++ b/src/base/stats/flags.hh @@ -39,28 +39,28 @@ namespace Stats { typedef uint32_t StatFlags; /** Nothing extra to print. */ -const StatFlags none = 0x00000000; +const StatFlags none = 0x00000000; /** This Stat is Initialized */ -const StatFlags init = 0x00000001; +const StatFlags init = 0x00000001; /** Print this stat. */ -const StatFlags print = 0x00000002; +const StatFlags print = 0x00000002; /** Print the total. */ -const StatFlags total = 0x00000010; +const StatFlags total = 0x00000010; /** Print the percent of the total that this entry represents. */ -const StatFlags pdf = 0x00000020; +const StatFlags pdf = 0x00000020; /** Print the cumulative percentage of total upto this entry. */ -const StatFlags cdf = 0x00000040; +const StatFlags cdf = 0x00000040; /** Print the distribution. */ -const StatFlags dist = 0x00000080; +const StatFlags dist = 0x00000080; /** Don't print if this is zero. */ -const StatFlags nozero = 0x00000100; +const StatFlags nozero = 0x00000100; /** Don't print if this is NAN */ -const StatFlags nonan = 0x00000200; +const StatFlags nonan = 0x00000200; /** Used for SS compatability. */ -const StatFlags __substat = 0x80000000; +const StatFlags __substat = 0x80000000; /** Mask of flags that can't be set directly */ -const StatFlags __reserved = init | print | __substat; +const StatFlags __reserved = init | print | __substat; enum DisplayMode { diff --git a/src/base/stats/mysql.cc b/src/base/stats/mysql.cc index 39a687fff..ee15d4231 100644 --- a/src/base/stats/mysql.cc +++ b/src/base/stats/mysql.cc @@ -458,7 +458,7 @@ InsertSubData::setup(MySqlRun *run) mysql.query(insert); // if (mysql.error) -// panic("could not insert subdata\n%s\n", mysql.error); +// panic("could not insert subdata\n%s\n", mysql.error); if (mysql.commit()) panic("could not commit transaction\n%s\n", mysql.error); @@ -683,7 +683,7 @@ MySql::configure(const FormulaData &data) mysql.query(insert_formula); // if (mysql.error) -// panic("could not insert formula\n%s\n", mysql.error); +// panic("could not insert formula\n%s\n", mysql.error); stringstream insert_ref; ccprintf(insert_ref, @@ -692,7 +692,7 @@ MySql::configure(const FormulaData &data) mysql.query(insert_ref); // if (mysql.error) -// panic("could not insert formula reference\n%s\n", mysql.error); +// panic("could not insert formula reference\n%s\n", mysql.error); if (mysql.commit()) panic("could not commit transaction\n%s\n", mysql.error); diff --git a/src/base/time.hh b/src/base/time.hh index f10cc5d6c..565ea0aac 100644 --- a/src/base/time.hh +++ b/src/base/time.hh @@ -68,7 +68,7 @@ std::ostream &operator<<(std::ostream &out, const Time &time); /* * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -94,7 +94,7 @@ std::ostream &operator<<(std::ostream &out, const Time &time); * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)time.h 8.2 (Berkeley) 7/10/94 + * @(#)time.h 8.2 (Berkeley) 7/10/94 */ #if defined(__sun) diff --git a/src/base/trace.hh b/src/base/trace.hh index c1b506187..72d7ba605 100644 --- a/src/base/trace.hh +++ b/src/base/trace.hh @@ -124,6 +124,6 @@ inline const std::string &name() { return Trace::DefaultName; } #define DPRINTFN(...) do {} while (0) #define DPRINTFNR(...) do {} while (0) -#endif // TRACING_ON +#endif // TRACING_ON #endif // __BASE_TRACE_HH__ diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index bea680fac..b03a2f63e 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -77,8 +77,8 @@ class BaseDynInst : public FastAlloc, public RefCounted typedef typename std::list::iterator ListIt; enum { - MaxInstSrcRegs = TheISA::MaxInstSrcRegs, /// Max source regs - MaxInstDestRegs = TheISA::MaxInstDestRegs, /// Max dest regs + MaxInstSrcRegs = TheISA::MaxInstSrcRegs, /// Max source regs + MaxInstDestRegs = TheISA::MaxInstDestRegs, /// Max dest regs }; /** The StaticInst used by this BaseDynInst. */ @@ -486,24 +486,24 @@ class BaseDynInst : public FastAlloc, public RefCounted // // Instruction types. Forward checks to StaticInst object. // - bool isNop() const { return staticInst->isNop(); } - bool isMemRef() const { return staticInst->isMemRef(); } - bool isLoad() const { return staticInst->isLoad(); } - bool isStore() const { return staticInst->isStore(); } + bool isNop() const { return staticInst->isNop(); } + bool isMemRef() const { return staticInst->isMemRef(); } + bool isLoad() const { return staticInst->isLoad(); } + bool isStore() const { return staticInst->isStore(); } bool isStoreConditional() const { return staticInst->isStoreConditional(); } bool isInstPrefetch() const { return staticInst->isInstPrefetch(); } bool isDataPrefetch() const { return staticInst->isDataPrefetch(); } bool isCopy() const { return staticInst->isCopy(); } - bool isInteger() const { return staticInst->isInteger(); } - bool isFloating() const { return staticInst->isFloating(); } - bool isControl() const { return staticInst->isControl(); } - bool isCall() const { return staticInst->isCall(); } - bool isReturn() const { return staticInst->isReturn(); } - bool isDirectCtrl() const { return staticInst->isDirectCtrl(); } + bool isInteger() const { return staticInst->isInteger(); } + bool isFloating() const { return staticInst->isFloating(); } + bool isControl() const { return staticInst->isControl(); } + bool isCall() const { return staticInst->isCall(); } + bool isReturn() const { return staticInst->isReturn(); } + bool isDirectCtrl() const { return staticInst->isDirectCtrl(); } bool isIndirectCtrl() const { return staticInst->isIndirectCtrl(); } - bool isCondCtrl() const { return staticInst->isCondCtrl(); } - bool isUncondCtrl() const { return staticInst->isUncondCtrl(); } + bool isCondCtrl() const { return staticInst->isCondCtrl(); } + bool isUncondCtrl() const { return staticInst->isUncondCtrl(); } bool isCondDelaySlot() const { return staticInst->isCondDelaySlot(); } bool isThreadSync() const { return staticInst->isThreadSync(); } bool isSerializing() const { return staticInst->isSerializing(); } @@ -560,7 +560,7 @@ class BaseDynInst : public FastAlloc, public RefCounted Addr branchTarget() const { return staticInst->branchTarget(PC); } /** Returns the number of source registers. */ - int8_t numSrcRegs() const { return staticInst->numSrcRegs(); } + int8_t numSrcRegs() const { return staticInst->numSrcRegs(); } /** Returns the number of destination registers. */ int8_t numDestRegs() const { return staticInst->numDestRegs(); } diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh index 17648d508..5b3c4582c 100644 --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@ -180,7 +180,7 @@ class CheckerCPU : public BaseCPU // These functions are only used in CPU models that split // effective address computation from the actual memory access. void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); } - Addr getEA() { panic("SimpleCPU::getEA() not implemented\n"); } + Addr getEA() { panic("SimpleCPU::getEA() not implemented\n"); } void prefetch(Addr addr, unsigned flags) { diff --git a/src/cpu/checker/cpu_impl.hh b/src/cpu/checker/cpu_impl.hh index f3f8a0bb3..33c70569a 100644 --- a/src/cpu/checker/cpu_impl.hh +++ b/src/cpu/checker/cpu_impl.hh @@ -141,9 +141,9 @@ Checker::verify(DynInstPtr &completed_inst) // Try to fetch the instruction #if FULL_SYSTEM -#define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0 +#define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0 #else -#define IFETCH_FLAGS(pc) 0 +#define IFETCH_FLAGS(pc) 0 #endif uint64_t fetch_PC = thread->readPC() & ~3; diff --git a/src/cpu/memtest/memtest.hh b/src/cpu/memtest/memtest.hh index 43f141af6..5a7e0b9ae 100644 --- a/src/cpu/memtest/memtest.hh +++ b/src/cpu/memtest/memtest.hh @@ -133,10 +133,10 @@ class MemTest : public MemObject bool accessRetry; - unsigned size; // size of testing memory region + unsigned size; // size of testing memory region - unsigned percentReads; // target percentage of read accesses - unsigned percentFunctional; // target percentage of functional accesses + unsigned percentReads; // target percentage of read accesses + unsigned percentFunctional; // target percentage of functional accesses unsigned percentUncacheable; int id; @@ -154,12 +154,12 @@ class MemTest : public MemObject Addr traceBlockAddr; - Addr baseAddr1; // fix this to option - Addr baseAddr2; // fix this to option + Addr baseAddr1; // fix this to option + Addr baseAddr2; // fix this to option Addr uncacheAddr; - unsigned progressInterval; // frequency of progress reports - Tick nextProgressMessage; // access # for next progress report + unsigned progressInterval; // frequency of progress reports + Tick nextProgressMessage; // access # for next progress report unsigned percentSourceUnaligned; unsigned percentDestUnaligned; diff --git a/src/cpu/o3/alpha/dyn_inst.hh b/src/cpu/o3/alpha/dyn_inst.hh index a6fb7b885..180545c3d 100644 --- a/src/cpu/o3/alpha/dyn_inst.hh +++ b/src/cpu/o3/alpha/dyn_inst.hh @@ -67,8 +67,8 @@ class AlphaDynInst : public BaseDynInst typedef TheISA::MiscReg MiscReg; enum { - MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs - MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs + MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs + MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs }; public: diff --git a/src/cpu/o3/mips/dyn_inst.hh b/src/cpu/o3/mips/dyn_inst.hh index b1a29ccf9..861577966 100755 --- a/src/cpu/o3/mips/dyn_inst.hh +++ b/src/cpu/o3/mips/dyn_inst.hh @@ -64,8 +64,8 @@ class MipsDynInst : public BaseDynInst typedef TheISA::MiscReg MiscReg; enum { - MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs - MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs + MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs + MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs }; public: diff --git a/src/cpu/o3/regfile.hh b/src/cpu/o3/regfile.hh index 8bd867136..53ac2d683 100644 --- a/src/cpu/o3/regfile.hh +++ b/src/cpu/o3/regfile.hh @@ -265,7 +265,7 @@ class PhysRegFile #if FULL_SYSTEM private: - int intrflag; // interrupt flag + int intrflag; // interrupt flag #endif private: diff --git a/src/cpu/ozone/back_end.hh b/src/cpu/ozone/back_end.hh index 4cdc86c3c..84429f3c1 100644 --- a/src/cpu/ozone/back_end.hh +++ b/src/cpu/ozone/back_end.hh @@ -447,7 +447,7 @@ class BackEnd Stats::Scalar<> ROB_fcount; Stats::Formula ROB_full_rate; - Stats::Vector<> ROB_count; // cumulative ROB occupancy + Stats::Vector<> ROB_count; // cumulative ROB occupancy Stats::Formula ROB_occ_rate; Stats::VectorDistribution<> ROB_occ_dist; public: @@ -482,8 +482,8 @@ BackEnd::read(RequestPtr req, T &data, int load_idx) memReq->completionEvent = &cacheCompletionEvent; lastDcacheStall = curTick; -// unscheduleTickEvent(); -// status = DcacheMissStall; +// unscheduleTickEvent(); +// status = DcacheMissStall; DPRINTF(OzoneCPU, "Dcache miss stall!\n"); } else { // do functional access @@ -524,8 +524,8 @@ BackEnd::write(RequestPtr req, T &data, int store_idx) if (result != MA_HIT && dcacheInterface->doEvents()) { memReq->completionEvent = &cacheCompletionEvent; lastDcacheStall = curTick; -// unscheduleTickEvent(); -// status = DcacheMissStall; +// unscheduleTickEvent(); +// status = DcacheMissStall; DPRINTF(OzoneCPU, "Dcache miss stall!\n"); } } diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index ec531d571..ceb980d4c 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -585,7 +585,7 @@ OzoneCPU::post_interrupt(int int_num, int index) if (_status == Idle) { DPRINTF(IPI,"Suspended Processor awoke\n"); -// thread.activate(); +// thread.activate(); // Hack for now. Otherwise might have to go through the tc, or // I need to figure out what's the right thing to call. activateContext(thread.readTid(), 1); diff --git a/src/cpu/ozone/front_end.hh b/src/cpu/ozone/front_end.hh index 667392c06..fac243449 100644 --- a/src/cpu/ozone/front_end.hh +++ b/src/cpu/ozone/front_end.hh @@ -307,7 +307,7 @@ class FrontEnd Stats::Formula idleRate; Stats::Formula branchRate; Stats::Formula fetchRate; - Stats::Scalar<> IFQCount; // cumulative IFQ occupancy + Stats::Scalar<> IFQCount; // cumulative IFQ occupancy Stats::Formula IFQOccupancy; Stats::Formula IFQLatency; Stats::Scalar<> IFQFcount; // cumulative IFQ full count diff --git a/src/cpu/ozone/inorder_back_end.hh b/src/cpu/ozone/inorder_back_end.hh index aef29b1e2..c23d801ba 100644 --- a/src/cpu/ozone/inorder_back_end.hh +++ b/src/cpu/ozone/inorder_back_end.hh @@ -222,7 +222,7 @@ InorderBackEnd::read(Addr addr, T &data, unsigned flags) // are executed twice. memReq->completionEvent = &cacheCompletionEvent; lastDcacheStall = curTick; -// unscheduleTickEvent(); +// unscheduleTickEvent(); status = DcacheMissLoadStall; DPRINTF(IBE, "Dcache miss stall!\n"); } else { @@ -249,7 +249,7 @@ InorderBackEnd::write(T data, Addr addr, unsigned flags, uint64_t *res) if (fault == NoFault && dcacheInterface) { memReq->cmd = Write; -// memcpy(memReq->data,(uint8_t *)&data,memReq->size); +// memcpy(memReq->data,(uint8_t *)&data,memReq->size); memReq->completionEvent = NULL; memReq->time = curTick; memReq->flags &= ~INST_READ; @@ -261,7 +261,7 @@ InorderBackEnd::write(T data, Addr addr, unsigned flags, uint64_t *res) if (result != MA_HIT) { memReq->completionEvent = &cacheCompletionEvent; lastDcacheStall = curTick; -// unscheduleTickEvent(); +// unscheduleTickEvent(); status = DcacheMissStoreStall; DPRINTF(IBE, "Dcache miss stall!\n"); } else { @@ -307,7 +307,7 @@ InorderBackEnd::read(MemReqPtr &req, T &data, int load_idx) if (result != MA_HIT) { req->completionEvent = &cacheCompletionEvent; lastDcacheStall = curTick; -// unscheduleTickEvent(); +// unscheduleTickEvent(); status = DcacheMissLoadStall; DPRINTF(IBE, "Dcache miss load stall!\n"); } else { @@ -372,7 +372,7 @@ InorderBackEnd::write(MemReqPtr &req, T &data, int store_idx) if (result != MA_HIT) { req->completionEvent = &cacheCompletionEvent; lastDcacheStall = curTick; -// unscheduleTickEvent(); +// unscheduleTickEvent(); status = DcacheMissStoreStall; DPRINTF(IBE, "Dcache miss store stall!\n"); } else { diff --git a/src/cpu/ozone/lsq_unit_impl.hh b/src/cpu/ozone/lsq_unit_impl.hh index 84a90eede..c24410520 100644 --- a/src/cpu/ozone/lsq_unit_impl.hh +++ b/src/cpu/ozone/lsq_unit_impl.hh @@ -553,7 +553,7 @@ OzoneLSQ::writebackStores() MemReqPtr req = storeQueue[storeWBIdx].req; storeQueue[storeWBIdx].committed = true; -// Fault fault = cpu->translateDataReadReq(req); +// Fault fault = cpu->translateDataReadReq(req); req->cmd = Write; req->completionEvent = NULL; req->time = curTick; diff --git a/src/cpu/ozone/lw_back_end.hh b/src/cpu/ozone/lw_back_end.hh index a335ab7dc..8ab50d5c9 100644 --- a/src/cpu/ozone/lw_back_end.hh +++ b/src/cpu/ozone/lw_back_end.hh @@ -407,7 +407,7 @@ class LWBackEnd Stats::Scalar<> ROBFcount; Stats::Formula ROBFullRate; - Stats::Vector<> ROBCount; // cumulative ROB occupancy + Stats::Vector<> ROBCount; // cumulative ROB occupancy Stats::Formula ROBOccRate; // Stats::VectorDistribution<> ROBOccDist; public: diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index aeae1a3d8..b7fcf1708 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -227,7 +227,7 @@ class BaseSimpleCPU : public BaseCPU // These functions are only used in CPU models that split // effective address computation from the actual memory access. void setEA(Addr EA) { panic("BaseSimpleCPU::setEA() not implemented\n"); } - Addr getEA() { panic("BaseSimpleCPU::getEA() not implemented\n"); + Addr getEA() { panic("BaseSimpleCPU::getEA() not implemented\n"); M5_DUMMY_RETURN} void prefetch(Addr addr, unsigned flags) diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index ba3312a7a..0124184e0 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -220,8 +220,8 @@ SimpleThread::activate(int delay) lastActivate = curTick; // if (status() == ThreadContext::Unallocated) { -// cpu->activateWhenReady(tid); -// return; +// cpu->activateWhenReady(tid); +// return; // } _status = ThreadContext::Active; diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index 37c3221f5..377bfcd79 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -99,7 +99,7 @@ class SimpleThread : public ThreadState typedef ThreadContext::Status Status; protected: - RegFile regs; // correct-path register context + RegFile regs; // correct-path register context public: // pointer to CPU associated with this SimpleThread diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index ceda78d90..cd4009e76 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -105,38 +105,38 @@ class StaticInstBase : public RefCounted /// implement this behavior via the execute() methods. /// enum Flags { - IsNop, ///< Is a no-op (no effect at all). + IsNop, ///< Is a no-op (no effect at all). - IsInteger, ///< References integer regs. - IsFloating, ///< References FP regs. + IsInteger, ///< References integer regs. + IsFloating, ///< References FP regs. - IsMemRef, ///< References memory (load, store, or prefetch). - IsLoad, ///< Reads from memory (load or prefetch). - IsStore, ///< Writes to memory. + IsMemRef, ///< References memory (load, store, or prefetch). + IsLoad, ///< Reads from memory (load or prefetch). + IsStore, ///< Writes to memory. IsStoreConditional, ///< Store conditional instruction. IsIndexed, ///< Accesses memory with an indexed address computation - IsInstPrefetch, ///< Instruction-cache prefetch. - IsDataPrefetch, ///< Data-cache prefetch. + IsInstPrefetch, ///< Instruction-cache prefetch. + IsDataPrefetch, ///< Data-cache prefetch. IsCopy, ///< Fast Cache block copy - IsControl, ///< Control transfer instruction. - IsDirectControl, ///< PC relative control transfer. - IsIndirectControl, ///< Register indirect control transfer. - IsCondControl, ///< Conditional control transfer. - IsUncondControl, ///< Unconditional control transfer. - IsCall, ///< Subroutine call. - IsReturn, ///< Subroutine return. + IsControl, ///< Control transfer instruction. + IsDirectControl, ///< PC relative control transfer. + IsIndirectControl, ///< Register indirect control transfer. + IsCondControl, ///< Conditional control transfer. + IsUncondControl, ///< Unconditional control transfer. + IsCall, ///< Subroutine call. + IsReturn, ///< Subroutine return. IsCondDelaySlot,///< Conditional Delay-Slot Instruction - IsThreadSync, ///< Thread synchronization operation. + IsThreadSync, ///< Thread synchronization operation. - IsSerializing, ///< Serializes pipeline: won't execute until all + IsSerializing, ///< Serializes pipeline: won't execute until all /// older instructions have committed. IsSerializeBefore, IsSerializeAfter, - IsMemBarrier, ///< Is a memory barrier - IsWriteBarrier, ///< Is a write barrier + IsMemBarrier, ///< Is a memory barrier + IsWriteBarrier, ///< Is a write barrier IsERET, /// <- Causes the IFU to stall (MIPS ISA) IsNonSpeculative, ///< Should not be executed speculatively @@ -150,12 +150,12 @@ class StaticInstBase : public RefCounted //Flags for microcode IsMacroop, ///< Is a macroop containing microops - IsMicroop, ///< Is a microop - IsDelayedCommit, ///< This microop doesn't commit right away - IsLastMicroop, ///< This microop ends a microop sequence - IsFirstMicroop, ///< This microop begins a microop sequence + IsMicroop, ///< Is a microop + IsDelayedCommit, ///< This microop doesn't commit right away + IsLastMicroop, ///< This microop ends a microop sequence + IsFirstMicroop, ///< This microop begins a microop sequence //This flag doesn't do anything yet - IsMicroBranch, ///< This microop branches within the microcode for a macroop + IsMicroBranch, ///< This microop branches within the microcode for a macroop IsDspOp, NumFlags @@ -215,26 +215,26 @@ class StaticInstBase : public RefCounted /// of the individual flags. //@{ - bool isNop() const { return flags[IsNop]; } + bool isNop() const { return flags[IsNop]; } - bool isMemRef() const { return flags[IsMemRef]; } - bool isLoad() const { return flags[IsLoad]; } - bool isStore() const { return flags[IsStore]; } - bool isStoreConditional() const { return flags[IsStoreConditional]; } + bool isMemRef() const { return flags[IsMemRef]; } + bool isLoad() const { return flags[IsLoad]; } + bool isStore() const { return flags[IsStore]; } + bool isStoreConditional() const { return flags[IsStoreConditional]; } bool isInstPrefetch() const { return flags[IsInstPrefetch]; } bool isDataPrefetch() const { return flags[IsDataPrefetch]; } bool isCopy() const { return flags[IsCopy];} - bool isInteger() const { return flags[IsInteger]; } - bool isFloating() const { return flags[IsFloating]; } + bool isInteger() const { return flags[IsInteger]; } + bool isFloating() const { return flags[IsFloating]; } - bool isControl() const { return flags[IsControl]; } - bool isCall() const { return flags[IsCall]; } - bool isReturn() const { return flags[IsReturn]; } - bool isDirectCtrl() const { return flags[IsDirectControl]; } + bool isControl() const { return flags[IsControl]; } + bool isCall() const { return flags[IsCall]; } + bool isReturn() const { return flags[IsReturn]; } + bool isDirectCtrl() const { return flags[IsDirectControl]; } bool isIndirectCtrl() const { return flags[IsIndirectControl]; } - bool isCondCtrl() const { return flags[IsCondControl]; } - bool isUncondCtrl() const { return flags[IsUncondControl]; } + bool isCondCtrl() const { return flags[IsCondControl]; } + bool isUncondCtrl() const { return flags[IsUncondControl]; } bool isCondDelaySlot() const { return flags[IsCondDelaySlot]; } bool isThreadSync() const { return flags[IsThreadSync]; } @@ -287,8 +287,8 @@ class StaticInst : public StaticInstBase typedef TheISA::RegIndex RegIndex; enum { - MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs - MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs + MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs + MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs }; diff --git a/src/dev/alpha/access.h b/src/dev/alpha/access.h index 4adeaf84b..72eb4950a 100644 --- a/src/dev/alpha/access.h +++ b/src/dev/alpha/access.h @@ -45,31 +45,31 @@ typedef unsigned long uint64_t; // This structure hacked up from simos struct AlphaAccess { - uint32_t last_offset; // 00: must be first field - uint32_t version; // 04: - uint32_t numCPUs; // 08: - uint32_t intrClockFrequency; // 0C: Hz - uint64_t cpuClock; // 10: MHz - uint64_t mem_size; // 18: + uint32_t last_offset; // 00: must be first field + uint32_t version; // 04: + uint32_t numCPUs; // 08: + uint32_t intrClockFrequency; // 0C: Hz + uint64_t cpuClock; // 10: MHz + uint64_t mem_size; // 18: // Loaded kernel - uint64_t kernStart; // 20: - uint64_t kernEnd; // 28: - uint64_t entryPoint; // 30: + uint64_t kernStart; // 20: + uint64_t kernEnd; // 28: + uint64_t entryPoint; // 30: // console disk stuff - uint64_t diskUnit; // 38: - uint64_t diskCount; // 40: - uint64_t diskPAddr; // 48: - uint64_t diskBlock; // 50: - uint64_t diskOperation; // 58: + uint64_t diskUnit; // 38: + uint64_t diskCount; // 40: + uint64_t diskPAddr; // 48: + uint64_t diskBlock; // 50: + uint64_t diskOperation; // 58: // console simple output stuff - uint64_t outputChar; // 60: Placeholder for output - uint64_t inputChar; // 68: Placeholder for input + uint64_t outputChar; // 60: Placeholder for output + uint64_t inputChar; // 68: Placeholder for input // MP boot - uint64_t cpuStack[64]; // 70: + uint64_t cpuStack[64]; // 70: }; #endif // __ALPHA_ACCESS_H__ diff --git a/src/dev/etherdump.cc b/src/dev/etherdump.cc index 07e52f36d..57da8a7f0 100644 --- a/src/dev/etherdump.cc +++ b/src/dev/etherdump.cc @@ -50,26 +50,26 @@ EtherDump::EtherDump(const Params *p) { } -#define DLT_EN10MB 1 // Ethernet (10Mb) -#define TCPDUMP_MAGIC 0xa1b2c3d4 -#define PCAP_VERSION_MAJOR 2 -#define PCAP_VERSION_MINOR 4 +#define DLT_EN10MB 1 // Ethernet (10Mb) +#define TCPDUMP_MAGIC 0xa1b2c3d4 +#define PCAP_VERSION_MAJOR 2 +#define PCAP_VERSION_MINOR 4 struct pcap_file_header { uint32_t magic; uint16_t version_major; uint16_t version_minor; - int32_t thiszone; // gmt to local correction - uint32_t sigfigs; // accuracy of timestamps - uint32_t snaplen; // max length saved portion of each pkt - uint32_t linktype; // data link type (DLT_*) + int32_t thiszone; // gmt to local correction + uint32_t sigfigs; // accuracy of timestamps + uint32_t snaplen; // max length saved portion of each pkt + uint32_t linktype; // data link type (DLT_*) }; struct pcap_pkthdr { uint32_t seconds; uint32_t microseconds; - uint32_t caplen; // length of portion present - uint32_t len; // length this packet (off wire) + uint32_t caplen; // length of portion present + uint32_t len; // length this packet (off wire) }; void diff --git a/src/dev/mips/access.h b/src/dev/mips/access.h index dbf3661b3..416b80590 100755 --- a/src/dev/mips/access.h +++ b/src/dev/mips/access.h @@ -48,37 +48,37 @@ typedef unsigned long uint64_t; // This structure hacked up from simos struct MipsAccess { - uint32_t inputChar; // 00: Placeholder for input - uint32_t last_offset; // 04: must be first field - uint32_t version; // 08: - uint32_t numCPUs; // 0C: - uint32_t intrClockFrequency; // 10: Hz + uint32_t inputChar; // 00: Placeholder for input + uint32_t last_offset; // 04: must be first field + uint32_t version; // 08: + uint32_t numCPUs; // 0C: + uint32_t intrClockFrequency; // 10: Hz // Loaded kernel - uint32_t kernStart; // 14: - uint32_t kernEnd; // 18: - uint32_t entryPoint; // 1c: + uint32_t kernStart; // 14: + uint32_t kernEnd; // 18: + uint32_t entryPoint; // 1c: // console simple output stuff - uint32_t outputChar; // 20: Placeholder for output + uint32_t outputChar; // 20: Placeholder for output // console disk stuff - uint32_t diskUnit; // 24: - uint32_t diskCount; // 28: - uint32_t diskPAddr; // 2c: - uint32_t diskBlock; // 30: - uint32_t diskOperation; // 34: + uint32_t diskUnit; // 24: + uint32_t diskCount; // 28: + uint32_t diskPAddr; // 2c: + uint32_t diskBlock; // 30: + uint32_t diskOperation; // 34: // MP boot - uint32_t cpuStack[64]; // 70: + uint32_t cpuStack[64]; // 70: /* XXX There appears to be a problem in accessing * unit64_t in the console.c file. They are treated * like uint32_int and result in the wrong address for * everything below. This problem should be investigated. */ - uint64_t cpuClock; // 38: MHz - uint64_t mem_size; // 40: + uint64_t cpuClock; // 38: MHz + uint64_t mem_size; // 40: }; #endif // __MIPS_ACCESS_H__ diff --git a/src/dev/ns_gige.hh b/src/dev/ns_gige.hh index a55a1c75e..87cf56962 100644 --- a/src/dev/ns_gige.hh +++ b/src/dev/ns_gige.hh @@ -62,10 +62,10 @@ const uint8_t EEPROM_PMATCH0_ADDR = 0xC; // EEPROM Address of PMATCH word 0 * Ethernet device registers */ struct dp_regs { - uint32_t command; - uint32_t config; - uint32_t mear; - uint32_t ptscr; + uint32_t command; + uint32_t config; + uint32_t mear; + uint32_t ptscr; uint32_t isr; uint32_t imr; uint32_t ier; diff --git a/src/dev/pcidev.cc b/src/dev/pcidev.cc index aa532414c..63b4a806e 100644 --- a/src/dev/pcidev.cc +++ b/src/dev/pcidev.cc @@ -41,7 +41,7 @@ #include "base/inifile.hh" #include "base/intmath.hh" // for isPowerOf2( #include "base/misc.hh" -#include "base/str.hh" // for to_number +#include "base/str.hh" // for to_number #include "base/trace.hh" #include "dev/pciconfigall.hh" #include "dev/pcidev.hh" diff --git a/src/dev/pcireg.h b/src/dev/pcireg.h index df57acdb0..5639d8e29 100644 --- a/src/dev/pcireg.h +++ b/src/dev/pcireg.h @@ -69,18 +69,18 @@ union PCIConfig { }; // Common PCI offsets -#define PCI_VENDOR_ID 0x00 // Vendor ID ro -#define PCI_DEVICE_ID 0x02 // Device ID ro -#define PCI_COMMAND 0x04 // Command rw -#define PCI_STATUS 0x06 // Status rw -#define PCI_REVISION_ID 0x08 // Revision ID ro -#define PCI_CLASS_CODE 0x09 // Class Code ro -#define PCI_SUB_CLASS_CODE 0x0A // Sub Class Code ro -#define PCI_BASE_CLASS_CODE 0x0B // Base Class Code ro -#define PCI_CACHE_LINE_SIZE 0x0C // Cache Line Size ro+ -#define PCI_LATENCY_TIMER 0x0D // Latency Timer ro+ -#define PCI_HEADER_TYPE 0x0E // Header Type ro -#define PCI_BIST 0x0F // Built in self test rw +#define PCI_VENDOR_ID 0x00 // Vendor ID ro +#define PCI_DEVICE_ID 0x02 // Device ID ro +#define PCI_COMMAND 0x04 // Command rw +#define PCI_STATUS 0x06 // Status rw +#define PCI_REVISION_ID 0x08 // Revision ID ro +#define PCI_CLASS_CODE 0x09 // Class Code ro +#define PCI_SUB_CLASS_CODE 0x0A // Sub Class Code ro +#define PCI_BASE_CLASS_CODE 0x0B // Base Class Code ro +#define PCI_CACHE_LINE_SIZE 0x0C // Cache Line Size ro+ +#define PCI_LATENCY_TIMER 0x0D // Latency Timer ro+ +#define PCI_HEADER_TYPE 0x0E // Header Type ro +#define PCI_BIST 0x0F // Built in self test rw // some pci command reg bitfields #define PCI_CMD_BME 0x04 // Bus master function enable @@ -88,62 +88,62 @@ union PCIConfig { #define PCI_CMD_IOSE 0x01 // I/O space enable // Type 0 PCI offsets -#define PCI0_BASE_ADDR0 0x10 // Base Address 0 rw -#define PCI0_BASE_ADDR1 0x14 // Base Address 1 rw -#define PCI0_BASE_ADDR2 0x18 // Base Address 2 rw -#define PCI0_BASE_ADDR3 0x1C // Base Address 3 rw -#define PCI0_BASE_ADDR4 0x20 // Base Address 4 rw -#define PCI0_BASE_ADDR5 0x24 // Base Address 5 rw -#define PCI0_CIS 0x28 // CardBus CIS Pointer ro -#define PCI0_SUB_VENDOR_ID 0x2C // Sub-Vendor ID ro -#define PCI0_SUB_SYSTEM_ID 0x2E // Sub-System ID ro -#define PCI0_ROM_BASE_ADDR 0x30 // Expansion ROM Base Address rw -#define PCI0_RESERVED0 0x34 -#define PCI0_RESERVED1 0x38 -#define PCI0_INTERRUPT_LINE 0x3C // Interrupt Line rw -#define PCI0_INTERRUPT_PIN 0x3D // Interrupt Pin ro -#define PCI0_MINIMUM_GRANT 0x3E // Maximum Grant ro -#define PCI0_MAXIMUM_LATENCY 0x3F // Maximum Latency ro +#define PCI0_BASE_ADDR0 0x10 // Base Address 0 rw +#define PCI0_BASE_ADDR1 0x14 // Base Address 1 rw +#define PCI0_BASE_ADDR2 0x18 // Base Address 2 rw +#define PCI0_BASE_ADDR3 0x1C // Base Address 3 rw +#define PCI0_BASE_ADDR4 0x20 // Base Address 4 rw +#define PCI0_BASE_ADDR5 0x24 // Base Address 5 rw +#define PCI0_CIS 0x28 // CardBus CIS Pointer ro +#define PCI0_SUB_VENDOR_ID 0x2C // Sub-Vendor ID ro +#define PCI0_SUB_SYSTEM_ID 0x2E // Sub-System ID ro +#define PCI0_ROM_BASE_ADDR 0x30 // Expansion ROM Base Address rw +#define PCI0_RESERVED0 0x34 +#define PCI0_RESERVED1 0x38 +#define PCI0_INTERRUPT_LINE 0x3C // Interrupt Line rw +#define PCI0_INTERRUPT_PIN 0x3D // Interrupt Pin ro +#define PCI0_MINIMUM_GRANT 0x3E // Maximum Grant ro +#define PCI0_MAXIMUM_LATENCY 0x3F // Maximum Latency ro // Type 1 PCI offsets -#define PCI1_BASE_ADDR0 0x10 // Base Address 0 rw -#define PCI1_BASE_ADDR1 0x14 // Base Address 1 rw -#define PCI1_PRI_BUS_NUM 0x18 // Primary Bus Number rw -#define PCI1_SEC_BUS_NUM 0x19 // Secondary Bus Number rw -#define PCI1_SUB_BUS_NUM 0x1A // Subordinate Bus Number rw -#define PCI1_SEC_LAT_TIMER 0x1B // Secondary Latency Timer ro+ -#define PCI1_IO_BASE 0x1C // I/O Base rw -#define PCI1_IO_LIMIT 0x1D // I/O Limit rw -#define PCI1_SECONDARY_STATUS 0x1E // Secondary Status rw -#define PCI1_MEM_BASE 0x20 // Memory Base rw -#define PCI1_MEM_LIMIT 0x22 // Memory Limit rw -#define PCI1_PRF_MEM_BASE 0x24 // Prefetchable Memory Base rw -#define PCI1_PRF_MEM_LIMIT 0x26 // Prefetchable Memory Limit rw -#define PCI1_PRF_BASE_UPPER 0x28 // Prefetchable Base Upper 32 rw -#define PCI1_PRF_LIMIT_UPPER 0x2C // Prefetchable Limit Upper 32 rw -#define PCI1_IO_BASE_UPPER 0x30 // I/O Base Upper 16 bits rw -#define PCI1_IO_LIMIT_UPPER 0x32 // I/O Limit Upper 16 bits rw -#define PCI1_RESERVED 0x34 // Reserved ro -#define PCI1_ROM_BASE_ADDR 0x38 // Expansion ROM Base Address rw -#define PCI1_INTR_LINE 0x3C // Interrupt Line rw -#define PCI1_INTR_PIN 0x3D // Interrupt Pin ro -#define PCI1_BRIDGE_CTRL 0x3E // Bridge Control rw +#define PCI1_BASE_ADDR0 0x10 // Base Address 0 rw +#define PCI1_BASE_ADDR1 0x14 // Base Address 1 rw +#define PCI1_PRI_BUS_NUM 0x18 // Primary Bus Number rw +#define PCI1_SEC_BUS_NUM 0x19 // Secondary Bus Number rw +#define PCI1_SUB_BUS_NUM 0x1A // Subordinate Bus Number rw +#define PCI1_SEC_LAT_TIMER 0x1B // Secondary Latency Timer ro+ +#define PCI1_IO_BASE 0x1C // I/O Base rw +#define PCI1_IO_LIMIT 0x1D // I/O Limit rw +#define PCI1_SECONDARY_STATUS 0x1E // Secondary Status rw +#define PCI1_MEM_BASE 0x20 // Memory Base rw +#define PCI1_MEM_LIMIT 0x22 // Memory Limit rw +#define PCI1_PRF_MEM_BASE 0x24 // Prefetchable Memory Base rw +#define PCI1_PRF_MEM_LIMIT 0x26 // Prefetchable Memory Limit rw +#define PCI1_PRF_BASE_UPPER 0x28 // Prefetchable Base Upper 32 rw +#define PCI1_PRF_LIMIT_UPPER 0x2C // Prefetchable Limit Upper 32 rw +#define PCI1_IO_BASE_UPPER 0x30 // I/O Base Upper 16 bits rw +#define PCI1_IO_LIMIT_UPPER 0x32 // I/O Limit Upper 16 bits rw +#define PCI1_RESERVED 0x34 // Reserved ro +#define PCI1_ROM_BASE_ADDR 0x38 // Expansion ROM Base Address rw +#define PCI1_INTR_LINE 0x3C // Interrupt Line rw +#define PCI1_INTR_PIN 0x3D // Interrupt Pin ro +#define PCI1_BRIDGE_CTRL 0x3E // Bridge Control rw // Device specific offsets -#define PCI_DEVICE_SPECIFIC 0x40 // 192 bytes +#define PCI_DEVICE_SPECIFIC 0x40 // 192 bytes #define PCI_CONFIG_SIZE 0xFF // Some Vendor IDs -#define PCI_VENDOR_DEC 0x1011 -#define PCI_VENDOR_NCR 0x101A -#define PCI_VENDOR_QLOGIC 0x1077 -#define PCI_VENDOR_SIMOS 0x1291 +#define PCI_VENDOR_DEC 0x1011 +#define PCI_VENDOR_NCR 0x101A +#define PCI_VENDOR_QLOGIC 0x1077 +#define PCI_VENDOR_SIMOS 0x1291 // Some Product IDs -#define PCI_PRODUCT_DEC_PZA 0x0008 -#define PCI_PRODUCT_NCR_810 0x0001 -#define PCI_PRODUCT_QLOGIC_ISP1020 0x1020 -#define PCI_PRODUCT_SIMOS_SIMOS 0x1291 -#define PCI_PRODUCT_SIMOS_ETHER 0x1292 +#define PCI_PRODUCT_DEC_PZA 0x0008 +#define PCI_PRODUCT_NCR_810 0x0001 +#define PCI_PRODUCT_QLOGIC_ISP1020 0x1020 +#define PCI_PRODUCT_SIMOS_SIMOS 0x1291 +#define PCI_PRODUCT_SIMOS_ETHER 0x1292 #endif // __PCIREG_H__ diff --git a/src/dev/sinicreg.hh b/src/dev/sinicreg.hh index de4188145..791aabf6b 100644 --- a/src/dev/sinicreg.hh +++ b/src/dev/sinicreg.hh @@ -48,7 +48,7 @@ static const uint64_t NAME##_width = WIDTH; \ static const uint64_t NAME##_offset = OFFSET; \ static const uint64_t NAME##_mask = (ULL(1) << WIDTH) - 1; \ - static const uint64_t NAME = ((ULL(1) << WIDTH) - 1) << OFFSET; \ + static const uint64_t NAME = ((ULL(1) << WIDTH) - 1) << OFFSET; \ static inline uint64_t get_##NAME(uint64_t reg) \ { return (reg & NAME) >> OFFSET; } \ static inline uint64_t set_##NAME(uint64_t reg, uint64_t val) \ diff --git a/src/kern/linux/linux.hh b/src/kern/linux/linux.hh index 6e0b37d91..a41fac9a7 100644 --- a/src/kern/linux/linux.hh +++ b/src/kern/linux/linux.hh @@ -65,46 +65,46 @@ class Linux : public OperatingSystem /// gets #defined to something else on some systems. This type /// can be specialized by architecture specific "Linux" classes typedef struct { - uint32_t st_dev; //!< device - uint32_t st_ino; //!< inode - uint32_t st_mode; //!< mode - uint32_t st_nlink; //!< link count - uint32_t st_uid; //!< owner's user ID - uint32_t st_gid; //!< owner's group ID - uint32_t st_rdev; //!< device number - int32_t _pad1; //!< for alignment - int64_t st_size; //!< file size in bytes - uint64_t st_atimeX; //!< time of last access - uint64_t st_mtimeX; //!< time of last modification - uint64_t st_ctimeX; //!< time of last status change - uint32_t st_blksize; //!< optimal I/O block size - int32_t st_blocks; //!< number of blocks allocated - uint32_t st_flags; //!< flags - uint32_t st_gen; //!< unknown + uint32_t st_dev; //!< device + uint32_t st_ino; //!< inode + uint32_t st_mode; //!< mode + uint32_t st_nlink; //!< link count + uint32_t st_uid; //!< owner's user ID + uint32_t st_gid; //!< owner's group ID + uint32_t st_rdev; //!< device number + int32_t _pad1; //!< for alignment + int64_t st_size; //!< file size in bytes + uint64_t st_atimeX; //!< time of last access + uint64_t st_mtimeX; //!< time of last modification + uint64_t st_ctimeX; //!< time of last status change + uint32_t st_blksize; //!< optimal I/O block size + int32_t st_blocks; //!< number of blocks allocated + uint32_t st_flags; //!< flags + uint32_t st_gen; //!< unknown } tgt_stat; // same for stat64 typedef struct { - uint64_t st_dev; - uint64_t st_ino; - uint64_t st_rdev; - int64_t st_size; - uint64_t st_blocks; - - uint32_t st_mode; - uint32_t st_uid; - uint32_t st_gid; - uint32_t st_blksize; - uint32_t st_nlink; - uint32_t __pad0; - - uint64_t st_atimeX; - uint64_t st_atime_nsec; - uint64_t st_mtimeX; - uint64_t st_mtime_nsec; - uint64_t st_ctimeX; - uint64_t st_ctime_nsec; - int64_t ___unused[3]; + uint64_t st_dev; + uint64_t st_ino; + uint64_t st_rdev; + int64_t st_size; + uint64_t st_blocks; + + uint32_t st_mode; + uint32_t st_uid; + uint32_t st_gid; + uint32_t st_blksize; + uint32_t st_nlink; + uint32_t __pad0; + + uint64_t st_atimeX; + uint64_t st_atime_nsec; + uint64_t st_mtimeX; + uint64_t st_mtime_nsec; + uint64_t st_ctimeX; + uint64_t st_ctime_nsec; + int64_t ___unused[3]; } tgt_stat64; /// Length of strings in struct utsname (plus 1 for null char). @@ -112,23 +112,23 @@ class Linux : public OperatingSystem /// Interface struct for uname(). struct utsname { - char sysname[_SYS_NMLN]; //!< System name. - char nodename[_SYS_NMLN]; //!< Node name. - char release[_SYS_NMLN]; //!< OS release. - char version[_SYS_NMLN]; //!< OS version. - char machine[_SYS_NMLN]; //!< Machine type. + char sysname[_SYS_NMLN]; //!< System name. + char nodename[_SYS_NMLN]; //!< Node name. + char release[_SYS_NMLN]; //!< OS release. + char version[_SYS_NMLN]; //!< OS version. + char machine[_SYS_NMLN]; //!< Machine type. }; /// Limit struct for getrlimit/setrlimit. struct rlimit { - uint64_t rlim_cur; //!< soft limit - uint64_t rlim_max; //!< hard limit + uint64_t rlim_cur; //!< soft limit + uint64_t rlim_max; //!< hard limit }; /// For gettimeofday(). struct timeval { - int64_t tv_sec; //!< seconds - int64_t tv_usec; //!< microseconds + int64_t tv_sec; //!< seconds + int64_t tv_usec; //!< microseconds }; // For writev/readv @@ -140,22 +140,22 @@ class Linux : public OperatingSystem /// For getrusage(). struct rusage { - struct timeval ru_utime; //!< user time used - struct timeval ru_stime; //!< system time used - int64_t ru_maxrss; //!< max rss - int64_t ru_ixrss; //!< integral shared memory size - int64_t ru_idrss; //!< integral unshared data " - int64_t ru_isrss; //!< integral unshared stack " - int64_t ru_minflt; //!< page reclaims - total vmfaults - int64_t ru_majflt; //!< page faults - int64_t ru_nswap; //!< swaps - int64_t ru_inblock; //!< block input operations - int64_t ru_oublock; //!< block output operations - int64_t ru_msgsnd; //!< messages sent - int64_t ru_msgrcv; //!< messages received - int64_t ru_nsignals; //!< signals received - int64_t ru_nvcsw; //!< voluntary context switches - int64_t ru_nivcsw; //!< involuntary " + struct timeval ru_utime; //!< user time used + struct timeval ru_stime; //!< system time used + int64_t ru_maxrss; //!< max rss + int64_t ru_ixrss; //!< integral shared memory size + int64_t ru_idrss; //!< integral unshared data " + int64_t ru_isrss; //!< integral unshared stack " + int64_t ru_minflt; //!< page reclaims - total vmfaults + int64_t ru_majflt; //!< page faults + int64_t ru_nswap; //!< swaps + int64_t ru_inblock; //!< block input operations + int64_t ru_oublock; //!< block output operations + int64_t ru_msgsnd; //!< messages sent + int64_t ru_msgrcv; //!< messages received + int64_t ru_nsignals; //!< signals received + int64_t ru_nvcsw; //!< voluntary context switches + int64_t ru_nivcsw; //!< involuntary " }; }; // class Linux diff --git a/src/kern/operatingsystem.hh b/src/kern/operatingsystem.hh index 99358ae03..10daae3d7 100644 --- a/src/kern/operatingsystem.hh +++ b/src/kern/operatingsystem.hh @@ -44,8 +44,8 @@ class OperatingSystem {}; /// This struct is used to build an target-OS-dependent table that /// maps the target's open() flags to the host open() flags. struct OpenFlagTransTable { - int tgtFlag; //!< Target system flag value. - int hostFlag; //!< Corresponding host system flag value. + int tgtFlag; //!< Target system flag value. + int hostFlag; //!< Corresponding host system flag value. }; @@ -71,23 +71,23 @@ class OperatingSystem { /// Interface struct for uname(). typedef struct { - char sysname[_SYS_NMLN]; //!< System name. - char nodename[_SYS_NMLN]; //!< Node name. - char release[_SYS_NMLN]; //!< OS release. - char version[_SYS_NMLN]; //!< OS version. - char machine[_SYS_NMLN]; //!< Machine type. + char sysname[_SYS_NMLN]; //!< System name. + char nodename[_SYS_NMLN]; //!< Node name. + char release[_SYS_NMLN]; //!< OS release. + char version[_SYS_NMLN]; //!< OS version. + char machine[_SYS_NMLN]; //!< Machine type. } utsname; /// Limit struct for getrlimit/setrlimit. typedef struct { - uint64_t rlim_cur; //!< soft limit - uint64_t rlim_max; //!< hard limit + uint64_t rlim_cur; //!< soft limit + uint64_t rlim_max; //!< hard limit } rlimit; /// For gettimeofday(). typedef struct { - int64_t tv_sec; //!< seconds - int64_t tv_usec; //!< microseconds + int64_t tv_sec; //!< seconds + int64_t tv_usec; //!< microseconds } timeval; // For writev/readv @@ -99,22 +99,22 @@ class OperatingSystem { /// For getrusage(). typedef struct { - timeval ru_utime; //!< user time used - timeval ru_stime; //!< system time used - int64_t ru_maxrss; //!< max rss - int64_t ru_ixrss; //!< integral shared memory size - int64_t ru_idrss; //!< integral unshared data " - int64_t ru_isrss; //!< integral unshared stack " - int64_t ru_minflt; //!< page reclaims - total vmfaults - int64_t ru_majflt; //!< page faults - int64_t ru_nswap; //!< swaps - int64_t ru_inblock; //!< block input operations - int64_t ru_oublock; //!< block output operations - int64_t ru_msgsnd; //!< messages sent - int64_t ru_msgrcv; //!< messages received - int64_t ru_nsignals; //!< signals received - int64_t ru_nvcsw; //!< voluntary context switches - int64_t ru_nivcsw; //!< involuntary " + timeval ru_utime; //!< user time used + timeval ru_stime; //!< system time used + int64_t ru_maxrss; //!< max rss + int64_t ru_ixrss; //!< integral shared memory size + int64_t ru_idrss; //!< integral unshared data " + int64_t ru_isrss; //!< integral unshared stack " + int64_t ru_minflt; //!< page reclaims - total vmfaults + int64_t ru_majflt; //!< page faults + int64_t ru_nswap; //!< swaps + int64_t ru_inblock; //!< block input operations + int64_t ru_oublock; //!< block output operations + int64_t ru_msgsnd; //!< messages sent + int64_t ru_msgrcv; //!< messages received + int64_t ru_nsignals; //!< signals received + int64_t ru_nvcsw; //!< voluntary context switches + int64_t ru_nivcsw; //!< involuntary " } rusage; }; // class OperatingSystem diff --git a/src/kern/solaris/solaris.hh b/src/kern/solaris/solaris.hh index ed574fdbf..a55ce2c80 100644 --- a/src/kern/solaris/solaris.hh +++ b/src/kern/solaris/solaris.hh @@ -76,39 +76,39 @@ class Solaris : public OperatingSystem /// Stat buffer. Note that we can't call it 'stat' since that /// gets #defined to something else on some systems. typedef struct { - uint64_t st_dev; //!< device - uint64_t st_ino; //!< inode - uint32_t st_mode; //!< mode - uint32_t st_nlink; //!< link count - int32_t st_uid; //!< owner's user ID - int32_t st_gid; //!< owner's group ID - uint64_t st_rdev; //!< device number - int64_t st_size; //!< file size in bytes - //struct tgt_timespec st_atimeX; //!< time of last access - //struct tgt_timespec st_mtimeX; //!< time of last modification - //struct tgt_timespec st_ctimeX; //!< time of last status change + uint64_t st_dev; //!< device + uint64_t st_ino; //!< inode + uint32_t st_mode; //!< mode + uint32_t st_nlink; //!< link count + int32_t st_uid; //!< owner's user ID + int32_t st_gid; //!< owner's group ID + uint64_t st_rdev; //!< device number + int64_t st_size; //!< file size in bytes + //struct tgt_timespec st_atimeX; //!< time of last access + //struct tgt_timespec st_mtimeX; //!< time of last modification + //struct tgt_timespec st_ctimeX; //!< time of last status change int64_t st_atimeX, st_mtimeX, st_ctimeX; - int32_t st_blksize; //!< optimal I/O block size - int64_t st_blocks; //!< number of blocks allocated + int32_t st_blksize; //!< optimal I/O block size + int64_t st_blocks; //!< number of blocks allocated char st_fstype[16]; } tgt_stat; // same for stat64 typedef struct { - uint64_t st_dev; //!< device - uint64_t st_ino; //!< inode - uint32_t st_mode; //!< mode - uint32_t st_nlink; //!< link count - int32_t st_uid; //!< owner's user ID - int32_t st_gid; //!< owner's group ID - uint64_t st_rdev; //!< device number - int64_t st_size; //!< file size in bytes - //struct tgt_timespec st_atimeX; //!< time of last access - //struct tgt_timespec st_mtimeX; //!< time of last modification - //struct tgt_timespec st_ctimeX; //!< time of last status change + uint64_t st_dev; //!< device + uint64_t st_ino; //!< inode + uint32_t st_mode; //!< mode + uint32_t st_nlink; //!< link count + int32_t st_uid; //!< owner's user ID + int32_t st_gid; //!< owner's group ID + uint64_t st_rdev; //!< device number + int64_t st_size; //!< file size in bytes + //struct tgt_timespec st_atimeX; //!< time of last access + //struct tgt_timespec st_mtimeX; //!< time of last modification + //struct tgt_timespec st_ctimeX; //!< time of last status change int64_t st_atimeX, st_mtimeX, st_ctimeX; - int32_t st_blksize; //!< optimal I/O block size - int64_t st_blocks; //!< number of blocks allocated + int32_t st_blksize; //!< optimal I/O block size + int64_t st_blocks; //!< number of blocks allocated char st_fstype[16]; } tgt_stat64; @@ -117,11 +117,11 @@ class Solaris : public OperatingSystem /// Interface struct for uname(). typedef struct utsname { - char sysname[_SYS_NMLN]; //!< System name. - char nodename[_SYS_NMLN]; //!< Node name. - char release[_SYS_NMLN]; //!< OS release. - char version[_SYS_NMLN]; //!< OS version. - char machine[_SYS_NMLN]; //!< Machine type. + char sysname[_SYS_NMLN]; //!< System name. + char nodename[_SYS_NMLN]; //!< Node name. + char release[_SYS_NMLN]; //!< OS release. + char version[_SYS_NMLN]; //!< OS version. + char machine[_SYS_NMLN]; //!< Machine type. } utsname; }; // class Solaris diff --git a/src/kern/tru64/mbuf.hh b/src/kern/tru64/mbuf.hh index cb5a84a7e..78b5ead7a 100644 --- a/src/kern/tru64/mbuf.hh +++ b/src/kern/tru64/mbuf.hh @@ -37,63 +37,63 @@ namespace tru64 { struct m_hdr { - Addr mh_next; // 0x00 - Addr mh_nextpkt; // 0x08 - Addr mh_data; // 0x10 - int32_t mh_len; // 0x18 - int32_t mh_type; // 0x1C - int32_t mh_flags; // 0x20 - int32_t mh_pad0; // 0x24 - Addr mh_foo[4]; // 0x28, 0x30, 0x38, 0x40 + Addr mh_next; // 0x00 + Addr mh_nextpkt; // 0x08 + Addr mh_data; // 0x10 + int32_t mh_len; // 0x18 + int32_t mh_type; // 0x1C + int32_t mh_flags; // 0x20 + int32_t mh_pad0; // 0x24 + Addr mh_foo[4]; // 0x28, 0x30, 0x38, 0x40 }; -struct pkthdr { - int32_t len; - int32_t protocolSum; - Addr rcvif; +struct pkthdr { + int32_t len; + int32_t protocolSum; + Addr rcvif; }; struct m_ext { - Addr ext_buf; // 0x00 - Addr ext_free; // 0x08 - uint32_t ext_size; // 0x10 - uint32_t ext_pad0; // 0x14 - Addr ext_arg; // 0x18 - struct ext_refq { - Addr forw, back; // 0x20, 0x28 + Addr ext_buf; // 0x00 + Addr ext_free; // 0x08 + uint32_t ext_size; // 0x10 + uint32_t ext_pad0; // 0x14 + Addr ext_arg; // 0x18 + struct ext_refq { + Addr forw, back; // 0x20, 0x28 } ext_ref; - Addr uiomove_f; // 0x30 - int32_t protocolSum; // 0x38 - int32_t bytesSummed; // 0x3C - Addr checksum; // 0x40 + Addr uiomove_f; // 0x30 + int32_t protocolSum; // 0x38 + int32_t bytesSummed; // 0x3C + Addr checksum; // 0x40 }; struct mbuf { - struct m_hdr m_hdr; + struct m_hdr m_hdr; union { struct { - struct pkthdr MH_pkthdr; + struct pkthdr MH_pkthdr; union { - struct m_ext MH_ext; - char MH_databuf[1]; + struct m_ext MH_ext; + char MH_databuf[1]; } MH_dat; } MH; - char M_databuf[1]; + char M_databuf[1]; } M_dat; }; #define m_attr m_hdr.mh_attr -#define m_next m_hdr.mh_next -#define m_len m_hdr.mh_len -#define m_data m_hdr.mh_data -#define m_type m_hdr.mh_type -#define m_flags m_hdr.mh_flags -#define m_nextpkt m_hdr.mh_nextpkt -#define m_act m_nextpkt -#define m_pkthdr M_dat.MH.MH_pkthdr -#define m_ext M_dat.MH.MH_dat.MH_ext -#define m_pktdat M_dat.MH.MH_dat.MH_databuf -#define m_dat M_dat.M_databuf +#define m_next m_hdr.mh_next +#define m_len m_hdr.mh_len +#define m_data m_hdr.mh_data +#define m_type m_hdr.mh_type +#define m_flags m_hdr.mh_flags +#define m_nextpkt m_hdr.mh_nextpkt +#define m_act m_nextpkt +#define m_pkthdr M_dat.MH.MH_pkthdr +#define m_ext M_dat.MH.MH_dat.MH_ext +#define m_pktdat M_dat.MH.MH_dat.MH_databuf +#define m_dat M_dat.M_databuf } diff --git a/src/kern/tru64/tru64.hh b/src/kern/tru64/tru64.hh index 70fb4d688..d0c359a1f 100644 --- a/src/kern/tru64/tru64.hh +++ b/src/kern/tru64/tru64.hh @@ -52,7 +52,7 @@ class Tru64 {}; #include #include #include -#include // for memset() +#include // for memset() #include #include "cpu/base.hh" @@ -102,7 +102,7 @@ class Tru64 : public OperatingSystem int32_t f_retired5; int32_t f_retired6; int32_t f_retired7; - fsid_t f_fsid; + fsid_t f_fsid; int32_t f_spare[9]; char f_retired8[90]; char f_retired9[90]; @@ -141,10 +141,10 @@ class Tru64 : public OperatingSystem /// For getdirentries(). struct dirent { - ino_t d_ino; //!< file number of entry - uint16_t d_reclen; //!< length of this record - uint16_t d_namlen; //!< length of string in d_name - char d_name[256]; //!< dummy name length + ino_t d_ino; //!< file number of entry + uint16_t d_reclen; //!< length of this record + uint16_t d_namlen; //!< length of string in d_name + char d_name[256]; //!< dummy name length }; @@ -162,106 +162,106 @@ class Tru64 : public OperatingSystem /// Limit struct for getrlimit/setrlimit. struct rlimit { - uint64_t rlim_cur; //!< soft limit - uint64_t rlim_max; //!< hard limit + uint64_t rlim_cur; //!< soft limit + uint64_t rlim_max; //!< hard limit }; /// For getsysinfo() GSI_CPU_INFO option. struct cpu_info { - uint32_t current_cpu; //!< current_cpu - uint32_t cpus_in_box; //!< cpus_in_box - uint32_t cpu_type; //!< cpu_type - uint32_t ncpus; //!< ncpus - uint64_t cpus_present; //!< cpus_present - uint64_t cpus_running; //!< cpus_running - uint64_t cpu_binding; //!< cpu_binding - uint64_t cpu_ex_binding; //!< cpu_ex_binding - uint32_t mhz; //!< mhz - uint32_t unused[3]; //!< future expansion + uint32_t current_cpu; //!< current_cpu + uint32_t cpus_in_box; //!< cpus_in_box + uint32_t cpu_type; //!< cpu_type + uint32_t ncpus; //!< ncpus + uint64_t cpus_present; //!< cpus_present + uint64_t cpus_running; //!< cpus_running + uint64_t cpu_binding; //!< cpu_binding + uint64_t cpu_ex_binding; //!< cpu_ex_binding + uint32_t mhz; //!< mhz + uint32_t unused[3]; //!< future expansion }; /// For gettimeofday. struct timeval { - uint32_t tv_sec; //!< seconds - uint32_t tv_usec; //!< microseconds + uint32_t tv_sec; //!< seconds + uint32_t tv_usec; //!< microseconds }; /// For getrusage(). struct rusage { - struct timeval ru_utime; //!< user time used - struct timeval ru_stime; //!< system time used - uint64_t ru_maxrss; //!< ru_maxrss - uint64_t ru_ixrss; //!< integral shared memory size - uint64_t ru_idrss; //!< integral unshared data " - uint64_t ru_isrss; //!< integral unshared stack " - uint64_t ru_minflt; //!< page reclaims - total vmfaults - uint64_t ru_majflt; //!< page faults - uint64_t ru_nswap; //!< swaps - uint64_t ru_inblock; //!< block input operations - uint64_t ru_oublock; //!< block output operations - uint64_t ru_msgsnd; //!< messages sent - uint64_t ru_msgrcv; //!< messages received - uint64_t ru_nsignals; //!< signals received - uint64_t ru_nvcsw; //!< voluntary context switches - uint64_t ru_nivcsw; //!< involuntary " + struct timeval ru_utime; //!< user time used + struct timeval ru_stime; //!< system time used + uint64_t ru_maxrss; //!< ru_maxrss + uint64_t ru_ixrss; //!< integral shared memory size + uint64_t ru_idrss; //!< integral unshared data " + uint64_t ru_isrss; //!< integral unshared stack " + uint64_t ru_minflt; //!< page reclaims - total vmfaults + uint64_t ru_majflt; //!< page faults + uint64_t ru_nswap; //!< swaps + uint64_t ru_inblock; //!< block input operations + uint64_t ru_oublock; //!< block output operations + uint64_t ru_msgsnd; //!< messages sent + uint64_t ru_msgrcv; //!< messages received + uint64_t ru_nsignals; //!< signals received + uint64_t ru_nvcsw; //!< voluntary context switches + uint64_t ru_nivcsw; //!< involuntary " }; /// For sigreturn(). struct sigcontext { - int64_t sc_onstack; //!< sigstack state to restore - int64_t sc_mask; //!< signal mask to restore - int64_t sc_pc; //!< pc at time of signal - int64_t sc_ps; //!< psl to retore - int64_t sc_regs[32]; //!< processor regs 0 to 31 - int64_t sc_ownedfp; //!< fp has been used - int64_t sc_fpregs[32]; //!< fp regs 0 to 31 - uint64_t sc_fpcr; //!< floating point control reg - uint64_t sc_fp_control; //!< software fpcr - int64_t sc_reserved1; //!< reserved for kernel - uint32_t sc_kreserved1; //!< reserved for kernel - uint32_t sc_kreserved2; //!< reserved for kernel - size_t sc_ssize; //!< stack size - caddr_t sc_sbase; //!< stack start - uint64_t sc_traparg_a0; //!< a0 argument to trap on exc - uint64_t sc_traparg_a1; //!< a1 argument to trap on exc - uint64_t sc_traparg_a2; //!< a2 argument to trap on exc - uint64_t sc_fp_trap_pc; //!< imprecise pc - uint64_t sc_fp_trigger_sum; //!< Exception summary at trigg - uint64_t sc_fp_trigger_inst; //!< Instruction at trigger pc + int64_t sc_onstack; //!< sigstack state to restore + int64_t sc_mask; //!< signal mask to restore + int64_t sc_pc; //!< pc at time of signal + int64_t sc_ps; //!< psl to retore + int64_t sc_regs[32]; //!< processor regs 0 to 31 + int64_t sc_ownedfp; //!< fp has been used + int64_t sc_fpregs[32]; //!< fp regs 0 to 31 + uint64_t sc_fpcr; //!< floating point control reg + uint64_t sc_fp_control; //!< software fpcr + int64_t sc_reserved1; //!< reserved for kernel + uint32_t sc_kreserved1; //!< reserved for kernel + uint32_t sc_kreserved2; //!< reserved for kernel + size_t sc_ssize; //!< stack size + caddr_t sc_sbase; //!< stack start + uint64_t sc_traparg_a0; //!< a0 argument to trap on exc + uint64_t sc_traparg_a1; //!< a1 argument to trap on exc + uint64_t sc_traparg_a2; //!< a2 argument to trap on exc + uint64_t sc_fp_trap_pc; //!< imprecise pc + uint64_t sc_fp_trigger_sum; //!< Exception summary at trigg + uint64_t sc_fp_trigger_inst; //!< Instruction at trigger pc }; /// For table(). struct tbl_sysinfo { - uint64_t si_user; //!< User time - uint64_t si_nice; //!< Nice time - uint64_t si_sys; //!< System time - uint64_t si_idle; //!< Idle time - uint64_t si_hz; //!< hz - uint64_t si_phz; //!< phz - uint64_t si_boottime; //!< Boot time in seconds - uint64_t wait; //!< Wait time - uint32_t si_max_procs; //!< rpb->rpb_numprocs - uint32_t pad; //!< padding + uint64_t si_user; //!< User time + uint64_t si_nice; //!< Nice time + uint64_t si_sys; //!< System time + uint64_t si_idle; //!< Idle time + uint64_t si_hz; //!< hz + uint64_t si_phz; //!< phz + uint64_t si_boottime; //!< Boot time in seconds + uint64_t wait; //!< Wait time + uint32_t si_max_procs; //!< rpb->rpb_numprocs + uint32_t pad; //!< padding }; /// For stack_create. struct vm_stack { // was void * - Addr address; //!< address hint - size_t rsize; //!< red zone size - size_t ysize; //!< yellow zone size - size_t gsize; //!< green zone size - size_t swap; //!< amount of swap to reserve - size_t incr; //!< growth increment - uint64_t align; //!< address alignment - uint64_t flags; //!< MAP_FIXED etc. + Addr address; //!< address hint + size_t rsize; //!< red zone size + size_t ysize; //!< yellow zone size + size_t gsize; //!< green zone size + size_t swap; //!< amount of swap to reserve + size_t incr; //!< growth increment + uint64_t align; //!< address alignment + uint64_t flags; //!< MAP_FIXED etc. // was struct memalloc_attr * - Addr attr; //!< allocation policy - uint64_t reserved; //!< reserved + Addr attr; //!< allocation policy + uint64_t reserved; //!< reserved }; /// Return values for nxm calls. @@ -271,17 +271,17 @@ class Tru64 : public OperatingSystem }; /// For nxm_task_init. - static const int NXM_TASK_INIT_VP = 2; //!< initial thread is VP + static const int NXM_TASK_INIT_VP = 2; //!< initial thread is VP /// Task attribute structure. struct nxm_task_attr { - int64_t nxm_callback; //!< nxm_callback - unsigned int nxm_version; //!< nxm_version - unsigned short nxm_uniq_offset; //!< nxm_uniq_offset - unsigned short flags; //!< flags - int nxm_quantum; //!< nxm_quantum - int pad1; //!< pad1 - int64_t pad2; //!< pad2 + int64_t nxm_callback; //!< nxm_callback + unsigned int nxm_version; //!< nxm_version + unsigned short nxm_uniq_offset; //!< nxm_uniq_offset + unsigned short flags; //!< flags + int nxm_quantum; //!< nxm_quantum + int pad1; //!< pad1 + int64_t pad2; //!< pad2 }; /// Signal set. @@ -316,9 +316,9 @@ class Tru64 : public OperatingSystem // the kernel but are never context-switched by the library. int nxm_ssig; //!< scheduler's synchronous signals - int reserved1; //!< reserved1 + int reserved1; //!< reserved1 int64_t nxm_active; //!< scheduler active - int64_t reserved2; //!< reserved2 + int64_t reserved2; //!< reserved2 }; struct nxm_sched_state { @@ -328,14 +328,14 @@ class Tru64 : public OperatingSystem int nxm_set_quantum; //!< quantum reset value int nxm_sysevent; //!< syscall state // struct nxm_upcall * - Addr nxm_uc_ret; //!< stack ptr of null thread + Addr nxm_uc_ret; //!< stack ptr of null thread // void * Addr nxm_tid; //!< scheduler's thread id int64_t nxm_va; //!< page fault address // struct nxm_pth_state * Addr nxm_pthid; //!< id of null thread uint64_t nxm_bound_pcs_count; //!< bound PCS thread count - int64_t pad[2]; //!< pad + int64_t pad[2]; //!< pad }; /// nxm_shared. @@ -343,7 +343,7 @@ class Tru64 : public OperatingSystem int64_t nxm_callback; //!< address of upcall routine unsigned int nxm_version; //!< version number unsigned short nxm_uniq_offset; //!< correction factor for TEB - unsigned short pad1; //!< pad1 + unsigned short pad1; //!< pad1 int64_t space[2]; //!< future growth struct nxm_sched_state nxm_ss[1]; //!< array of shared areas }; @@ -368,29 +368,29 @@ class Tru64 : public OperatingSystem /// For nxm_thread_create. enum nxm_thread_type { - NXM_TYPE_SCS = 0, - NXM_TYPE_VP = 1, - NXM_TYPE_MANAGER = 2 + NXM_TYPE_SCS = 0, + NXM_TYPE_VP = 1, + NXM_TYPE_MANAGER = 2 }; /// Thread attributes. struct nxm_thread_attr { - int version; //!< version - int type; //!< type - int cancel_flags; //!< cancel_flags - int priority; //!< priority - int policy; //!< policy - int signal_type; //!< signal_type + int version; //!< version + int type; //!< type + int cancel_flags; //!< cancel_flags + int priority; //!< priority + int policy; //!< policy + int signal_type; //!< signal_type // void * - Addr pthid; //!< pthid - sigset_t sigmask; //!< sigmask + Addr pthid; //!< pthid + sigset_t sigmask; //!< sigmask /// Initial register values. struct { - uint64_t pc; //!< pc - uint64_t sp; //!< sp - uint64_t a0; //!< a0 + uint64_t pc; //!< pc + uint64_t sp; //!< sp + uint64_t a0; //!< a0 } registers; - uint64_t pad2[2]; //!< pad2 + uint64_t pad2[2]; //!< pad2 }; /// Helper function to convert a host statfs buffer to a target statfs @@ -605,7 +605,7 @@ class Tru64 : public OperatingSystem process->numCpus() * sizeof(Tru64::nxm_slot_state_t); cur_addr += slot_state_size; // now the per-RAD state struct (we only support one RAD) - cur_addr = 0x14000; // bump up addr for alignment + cur_addr = 0x14000; // bump up addr for alignment Addr rad_state_addr = cur_addr; int rad_state_size = (sizeof(Tru64::nxm_shared) @@ -616,7 +616,7 @@ class Tru64 : public OperatingSystem TypedBufferArg config(config_addr); config->nxm_nslots_per_rad = htog(process->numCpus()); - config->nxm_nrads = htog(1); // only one RAD in our system! + config->nxm_nrads = htog(1); // only one RAD in our system! config->nxm_slot_state = htog(slot_state_addr); config->nxm_rad[0] = htog(rad_state_addr); @@ -1111,37 +1111,37 @@ class Tru64_F64 : public Tru64 /// On some hosts (notably Linux) define st_atime, st_mtime, and /// st_ctime as macros, so we append an X to get around this. struct F64_stat { - dev_t st_dev; //!< st_dev - int32_t st_retired1; //!< st_retired1 - mode_t st_mode; //!< st_mode - nlink_t st_nlink; //!< st_nlink - uint16_t st_nlink_reserved; //!< st_nlink_reserved - uid_t st_uid; //!< st_uid - gid_t st_gid; //!< st_gid - dev_t st_rdev; //!< st_rdev - dev_t st_ldev; //!< st_ldev - off_t st_size; //!< st_size - time_t st_retired2; //!< st_retired2 - int32_t st_uatime; //!< st_uatime - time_t st_retired3; //!< st_retired3 - int32_t st_umtime; //!< st_umtime - time_t st_retired4; //!< st_retired4 - int32_t st_uctime; //!< st_uctime - int32_t st_retired5; //!< st_retired5 - int32_t st_retired6; //!< st_retired6 - uint32_t st_flags; //!< st_flags - uint32_t st_gen; //!< st_gen - uint64_t st_spare[4]; //!< st_spare[4] - ino_t st_ino; //!< st_ino - int32_t st_ino_reserved; //!< st_ino_reserved - time_t st_atimeX; //!< st_atime - int32_t st_atime_reserved; //!< st_atime_reserved - time_t st_mtimeX; //!< st_mtime - int32_t st_mtime_reserved; //!< st_mtime_reserved - time_t st_ctimeX; //!< st_ctime - int32_t st_ctime_reserved; //!< st_ctime_reserved - uint64_t st_blksize; //!< st_blksize - uint64_t st_blocks; //!< st_blocks + dev_t st_dev; //!< st_dev + int32_t st_retired1; //!< st_retired1 + mode_t st_mode; //!< st_mode + nlink_t st_nlink; //!< st_nlink + uint16_t st_nlink_reserved; //!< st_nlink_reserved + uid_t st_uid; //!< st_uid + gid_t st_gid; //!< st_gid + dev_t st_rdev; //!< st_rdev + dev_t st_ldev; //!< st_ldev + off_t st_size; //!< st_size + time_t st_retired2; //!< st_retired2 + int32_t st_uatime; //!< st_uatime + time_t st_retired3; //!< st_retired3 + int32_t st_umtime; //!< st_umtime + time_t st_retired4; //!< st_retired4 + int32_t st_uctime; //!< st_uctime + int32_t st_retired5; //!< st_retired5 + int32_t st_retired6; //!< st_retired6 + uint32_t st_flags; //!< st_flags + uint32_t st_gen; //!< st_gen + uint64_t st_spare[4]; //!< st_spare[4] + ino_t st_ino; //!< st_ino + int32_t st_ino_reserved; //!< st_ino_reserved + time_t st_atimeX; //!< st_atime + int32_t st_atime_reserved; //!< st_atime_reserved + time_t st_mtimeX; //!< st_mtime + int32_t st_mtime_reserved; //!< st_mtime_reserved + time_t st_ctimeX; //!< st_ctime + int32_t st_ctime_reserved; //!< st_ctime_reserved + uint64_t st_blksize; //!< st_blksize + uint64_t st_blocks; //!< st_blocks }; typedef F64_stat tgt_stat; diff --git a/src/kern/tru64/tru64_syscalls.cc b/src/kern/tru64/tru64_syscalls.cc index 8051b9efb..602271b36 100644 --- a/src/kern/tru64/tru64_syscalls.cc +++ b/src/kern/tru64/tru64_syscalls.cc @@ -33,394 +33,394 @@ namespace { const char * standard_strings[SystemCalls::StandardNumber] = { - "syscall", // 0 - "exit", // 1 - "fork", // 2 - "read", // 3 - "write", // 4 - "old_open", // 5 - "close", // 6 - "wait4", // 7 - "old_creat", // 8 - "link", // 9 - - "unlink", // 10 - "execv", // 11 - "chdir", // 12 - "fchdir", // 13 - "mknod", // 14 - "chmod", // 15 - "chown", // 16 - "obreak", // 17 - "pre_F64_getfsstat", // 18 - "lseek", // 19 - - "getpid", // 20 - "mount", // 21 - "unmount", // 22 - "setuid", // 23 - "getuid", // 24 - "exec_with_loader", // 25 - "ptrace", // 26 - "recvmsg", // 27 - "sendmsg", // 28 - "recvfrom", // 29 - - "accept", // 30 - "getpeername", // 31 - "getsockname", // 32 - "access", // 33 - "chflags", // 34 - "fchflags", // 35 - "sync", // 36 - "kill", // 37 - "old_stat", // 38 - "setpgid", // 39 - - "old_lstat", // 40 - "dup", // 41 - "pipe", // 42 - "set_program_attributes", // 43 - "profil", // 44 - "open", // 45 - "obsolete_osigaction", // 46 - "getgid", // 47 - "sigprocmask", // 48 - "getlogin", // 49 - - "setlogin", // 50 - "acct", // 51 - "sigpending", // 52 - "classcntl", // 53 - "ioctl", // 54 - "reboot", // 55 - "revoke", // 56 - "symlink", // 57 - "readlink", // 58 - "execve", // 59 - - "umask", // 60 - "chroot", // 61 - "old_fstat", // 62 - "getpgrp", // 63 - "getpagesize", // 64 - "mremap", // 65 - "vfork", // 66 - "pre_F64_stat", // 67 - "pre_F64_lstat", // 68 - "sbrk", // 69 - - "sstk", // 70 - "mmap", // 71 - "ovadvise", // 72 - "munmap", // 73 - "mprotect", // 74 - "madvise", // 75 - "old_vhangup", // 76 - "kmodcall", // 77 - "mincore", // 78 - "getgroups", // 79 - - "setgroups", // 80 - "old_getpgrp", // 81 - "setpgrp", // 82 - "setitimer", // 83 - "old_wait", // 84 - "table", // 85 - "getitimer", // 86 - "gethostname", // 87 - "sethostname", // 88 - "getdtablesize", // 89 - - "dup2", // 90 - "pre_F64_fstat", // 91 - "fcntl", // 92 - "select", // 93 - "poll", // 94 - "fsync", // 95 - "setpriority", // 96 - "socket", // 97 - "connect", // 98 - "old_accept", // 99 - - "getpriority", // 100 - "old_send", // 101 - "old_recv", // 102 - "sigreturn", // 103 - "bind", // 104 - "setsockopt", // 105 - "listen", // 106 - "plock", // 107 - "old_sigvec", // 108 - "old_sigblock", // 109 - - "old_sigsetmask", // 110 - "sigsuspend", // 111 - "sigstack", // 112 - "old_recvmsg", // 113 - "old_sendmsg", // 114 - "obsolete_vtrcae", // 115 - "gettimeofday", // 116 - "getrusage", // 117 - "getsockopt", // 118 - "numa_syscalls", // 119 - - "readv", // 120 - "writev", // 121 - "settimeofday", // 122 - "fchown", // 123 - "fchmod", // 124 - "old_recvfrom", // 125 - "setreuid", // 126 - "setregid", // 127 - "rename", // 128 - "truncate", // 129 - - "ftruncate", // 130 - "flock", // 131 - "setgid", // 132 - "sendto", // 133 - "shutdown", // 134 - "socketpair", // 135 - "mkdir", // 136 - "rmdir", // 137 - "utimes", // 138 - "obsolete_42_sigreturn", // 139 - - "adjtime", // 140 - "old_getpeername", // 141 - "gethostid", // 142 - "sethostid", // 143 - "getrlimit", // 144 - "setrlimit", // 145 - "old_killpg", // 146 - "setsid", // 147 - "quotactl", // 148 - "oldquota", // 149 - - "old_getsockname", // 150 - "pread", // 151 - "pwrite", // 152 - "pid_block", // 153 - "pid_unblock", // 154 - "signal_urti", // 155 - "sigaction", // 156 - "sigwaitprim", // 157 - "nfssvc", // 158 - "getdirentries", // 159 - - "pre_F64_statfs", // 160 - "pre_F64_fstatfs", // 161 - 0, // 162 - "async_daemon", // 163 - "getfh", // 164 - "getdomainname", // 165 - "setdomainname", // 166 - 0, // 167 - 0, // 168 - "exportfs", // 169 - - 0, // 170 - 0, // 171 - 0, // 172 - 0, // 173 - 0, // 174 - 0, // 175 - 0, // 176 - 0, // 177 - 0, // 178 - 0, // 179 - - 0, // 180 - "alt_plock", // 181 - 0, // 182 - 0, // 183 - "getmnt", // 184 - 0, // 185 - 0, // 186 - "alt_sigpending", // 187 - "alt_setsid", // 188 - 0, // 189 - - 0, // 190 - 0, // 191 - 0, // 192 - 0, // 193 - 0, // 194 - 0, // 195 - 0, // 196 - 0, // 197 - 0, // 198 - "swapon", // 199 - - "msgctl", // 200 - "msgget", // 201 - "msgrcv", // 202 - "msgsnd", // 203 - "semctl", // 204 - "semget", // 205 - "semop", // 206 - "uname", // 207 - "lchown", // 208 - "shmat", // 209 - - "shmctl", // 210 - "shmdt", // 211 - "shmget", // 212 - "mvalid", // 213 - "getaddressconf", // 214 - "msleep", // 215 - "mwakeup", // 216 - "msync", // 217 - "signal", // 218 - "utc_gettime", // 219 - - "utc_adjtime", // 220 - 0, // 221 - "security", // 222 - "kloadcall", // 223 - "stat", // 224 - "lstat", // 225 - "fstat", // 226 - "statfs", // 227 - "fstatfs", // 228 - "getfsstat", // 229 - - "gettimeofday64", // 230 - "settimeofday64", // 231 - 0, // 232 - "getpgid", // 233 - "getsid", // 234 - "sigaltstack", // 235 - "waitid", // 236 - "priocntlset", // 237 - "sigsendset", // 238 - "set_speculative", // 239 - - "msfs_syscall", // 240 - "sysinfo", // 241 - "uadmin", // 242 - "fuser", // 243 - "proplist_syscall", // 244 - "ntp_adjtime", // 245 - "ntp_gettime", // 246 - "pathconf", // 247 - "fpathconf", // 248 - "sync2", // 249 - - "uswitch", // 250 - "usleep_thread", // 251 - "audcntl", // 252 - "audgen", // 253 - "sysfs", // 254 - "subsys_info", // 255 - "getsysinfo", // 256 - "setsysinfo", // 257 - "afs_syscall", // 258 - "swapctl", // 259 - - "memcntl", // 260 - "fdatasync", // 261 - "oflock", // 262 - "_F64_readv", // 263 - "_F64_writev", // 264 - "cdslxlate", // 265 - "sendfile", // 266 + "syscall", // 0 + "exit", // 1 + "fork", // 2 + "read", // 3 + "write", // 4 + "old_open", // 5 + "close", // 6 + "wait4", // 7 + "old_creat", // 8 + "link", // 9 + + "unlink", // 10 + "execv", // 11 + "chdir", // 12 + "fchdir", // 13 + "mknod", // 14 + "chmod", // 15 + "chown", // 16 + "obreak", // 17 + "pre_F64_getfsstat", // 18 + "lseek", // 19 + + "getpid", // 20 + "mount", // 21 + "unmount", // 22 + "setuid", // 23 + "getuid", // 24 + "exec_with_loader", // 25 + "ptrace", // 26 + "recvmsg", // 27 + "sendmsg", // 28 + "recvfrom", // 29 + + "accept", // 30 + "getpeername", // 31 + "getsockname", // 32 + "access", // 33 + "chflags", // 34 + "fchflags", // 35 + "sync", // 36 + "kill", // 37 + "old_stat", // 38 + "setpgid", // 39 + + "old_lstat", // 40 + "dup", // 41 + "pipe", // 42 + "set_program_attributes", // 43 + "profil", // 44 + "open", // 45 + "obsolete_osigaction", // 46 + "getgid", // 47 + "sigprocmask", // 48 + "getlogin", // 49 + + "setlogin", // 50 + "acct", // 51 + "sigpending", // 52 + "classcntl", // 53 + "ioctl", // 54 + "reboot", // 55 + "revoke", // 56 + "symlink", // 57 + "readlink", // 58 + "execve", // 59 + + "umask", // 60 + "chroot", // 61 + "old_fstat", // 62 + "getpgrp", // 63 + "getpagesize", // 64 + "mremap", // 65 + "vfork", // 66 + "pre_F64_stat", // 67 + "pre_F64_lstat", // 68 + "sbrk", // 69 + + "sstk", // 70 + "mmap", // 71 + "ovadvise", // 72 + "munmap", // 73 + "mprotect", // 74 + "madvise", // 75 + "old_vhangup", // 76 + "kmodcall", // 77 + "mincore", // 78 + "getgroups", // 79 + + "setgroups", // 80 + "old_getpgrp", // 81 + "setpgrp", // 82 + "setitimer", // 83 + "old_wait", // 84 + "table", // 85 + "getitimer", // 86 + "gethostname", // 87 + "sethostname", // 88 + "getdtablesize", // 89 + + "dup2", // 90 + "pre_F64_fstat", // 91 + "fcntl", // 92 + "select", // 93 + "poll", // 94 + "fsync", // 95 + "setpriority", // 96 + "socket", // 97 + "connect", // 98 + "old_accept", // 99 + + "getpriority", // 100 + "old_send", // 101 + "old_recv", // 102 + "sigreturn", // 103 + "bind", // 104 + "setsockopt", // 105 + "listen", // 106 + "plock", // 107 + "old_sigvec", // 108 + "old_sigblock", // 109 + + "old_sigsetmask", // 110 + "sigsuspend", // 111 + "sigstack", // 112 + "old_recvmsg", // 113 + "old_sendmsg", // 114 + "obsolete_vtrcae", // 115 + "gettimeofday", // 116 + "getrusage", // 117 + "getsockopt", // 118 + "numa_syscalls", // 119 + + "readv", // 120 + "writev", // 121 + "settimeofday", // 122 + "fchown", // 123 + "fchmod", // 124 + "old_recvfrom", // 125 + "setreuid", // 126 + "setregid", // 127 + "rename", // 128 + "truncate", // 129 + + "ftruncate", // 130 + "flock", // 131 + "setgid", // 132 + "sendto", // 133 + "shutdown", // 134 + "socketpair", // 135 + "mkdir", // 136 + "rmdir", // 137 + "utimes", // 138 + "obsolete_42_sigreturn", // 139 + + "adjtime", // 140 + "old_getpeername", // 141 + "gethostid", // 142 + "sethostid", // 143 + "getrlimit", // 144 + "setrlimit", // 145 + "old_killpg", // 146 + "setsid", // 147 + "quotactl", // 148 + "oldquota", // 149 + + "old_getsockname", // 150 + "pread", // 151 + "pwrite", // 152 + "pid_block", // 153 + "pid_unblock", // 154 + "signal_urti", // 155 + "sigaction", // 156 + "sigwaitprim", // 157 + "nfssvc", // 158 + "getdirentries", // 159 + + "pre_F64_statfs", // 160 + "pre_F64_fstatfs", // 161 + 0, // 162 + "async_daemon", // 163 + "getfh", // 164 + "getdomainname", // 165 + "setdomainname", // 166 + 0, // 167 + 0, // 168 + "exportfs", // 169 + + 0, // 170 + 0, // 171 + 0, // 172 + 0, // 173 + 0, // 174 + 0, // 175 + 0, // 176 + 0, // 177 + 0, // 178 + 0, // 179 + + 0, // 180 + "alt_plock", // 181 + 0, // 182 + 0, // 183 + "getmnt", // 184 + 0, // 185 + 0, // 186 + "alt_sigpending", // 187 + "alt_setsid", // 188 + 0, // 189 + + 0, // 190 + 0, // 191 + 0, // 192 + 0, // 193 + 0, // 194 + 0, // 195 + 0, // 196 + 0, // 197 + 0, // 198 + "swapon", // 199 + + "msgctl", // 200 + "msgget", // 201 + "msgrcv", // 202 + "msgsnd", // 203 + "semctl", // 204 + "semget", // 205 + "semop", // 206 + "uname", // 207 + "lchown", // 208 + "shmat", // 209 + + "shmctl", // 210 + "shmdt", // 211 + "shmget", // 212 + "mvalid", // 213 + "getaddressconf", // 214 + "msleep", // 215 + "mwakeup", // 216 + "msync", // 217 + "signal", // 218 + "utc_gettime", // 219 + + "utc_adjtime", // 220 + 0, // 221 + "security", // 222 + "kloadcall", // 223 + "stat", // 224 + "lstat", // 225 + "fstat", // 226 + "statfs", // 227 + "fstatfs", // 228 + "getfsstat", // 229 + + "gettimeofday64", // 230 + "settimeofday64", // 231 + 0, // 232 + "getpgid", // 233 + "getsid", // 234 + "sigaltstack", // 235 + "waitid", // 236 + "priocntlset", // 237 + "sigsendset", // 238 + "set_speculative", // 239 + + "msfs_syscall", // 240 + "sysinfo", // 241 + "uadmin", // 242 + "fuser", // 243 + "proplist_syscall", // 244 + "ntp_adjtime", // 245 + "ntp_gettime", // 246 + "pathconf", // 247 + "fpathconf", // 248 + "sync2", // 249 + + "uswitch", // 250 + "usleep_thread", // 251 + "audcntl", // 252 + "audgen", // 253 + "sysfs", // 254 + "subsys_info", // 255 + "getsysinfo", // 256 + "setsysinfo", // 257 + "afs_syscall", // 258 + "swapctl", // 259 + + "memcntl", // 260 + "fdatasync", // 261 + "oflock", // 262 + "_F64_readv", // 263 + "_F64_writev", // 264 + "cdslxlate", // 265 + "sendfile", // 266 }; const char * mach_strings[SystemCalls::MachNumber] = { - 0, // 0 - 0, // 1 - 0, // 2 - 0, // 3 - 0, // 4 - 0, // 5 - 0, // 6 - 0, // 7 - 0, // 8 - 0, // 9 - - "task_self", // 10 - "thread_reply", // 11 - "task_notify", // 12 - "thread_self", // 13 - 0, // 14 - 0, // 15 - 0, // 16 - 0, // 17 - 0, // 18 - 0, // 19 - - "msg_send_trap", // 20 - "msg_receive_trap", // 21 - "msg_rpc_trap", // 22 - 0, // 23 - "nxm_block", // 24 - "nxm_unblock", // 25 - 0, // 26 - 0, // 27 - 0, // 28 - "nxm_thread_destroy", // 29 - - "lw_wire", // 30 - "lw_unwire", // 31 - "nxm_thread_create", // 32 - "nxm_task_init", // 33 - 0, // 34 - "nxm_idle", // 35 - "nxm_wakeup_idle", // 36 - "nxm_set_pthid", // 37 - "nxm_thread_kill", // 38 - "nxm_thread_block", // 39 - - "nxm_thread_wakeup", // 40 - "init_process", // 41 - "nxm_get_binding", // 42 - "map_fd", // 43 - "nxm_resched", // 44 - "nxm_set_cancel", // 45 - "nxm_set_binding", // 46 - "stack_create", // 47 - "nxm_get_state", // 48 - "nxm_thread_suspend", // 49 - - "nxm_thread_resume", // 50 - "nxm_signal_check", // 51 - "htg_unix_syscall", // 52 - 0, // 53 - 0, // 54 - "host_self", // 55 - "host_priv_self", // 56 - 0, // 57 - 0, // 58 - "swtch_pri", // 59 - - "swtch", // 60 - "thread_switch", // 61 - "semop_fast", // 62 - "nxm_pshared_init", // 63 - "nxm_pshared_block", // 64 - "nxm_pshared_unblock", // 65 - "nxm_pshared_destroy", // 66 - "nxm_swtch_pri", // 67 - "lw_syscall", // 68 - 0, // 69 - - "mach_sctimes_0", // 70 - "mach_sctimes_1", // 71 - "mach_sctimes_2", // 72 - "mach_sctimes_3", // 73 - "mach_sctimes_4", // 74 - "mach_sctimes_5", // 75 - "mach_sctimes_6", // 76 - "mach_sctimes_7", // 77 - "mach_sctimes_8", // 78 - "mach_sctimes_9", // 79 - - "mach_sctimes_10", // 80 - "mach_sctimes_11", // 81 - "mach_sctimes_port_alloc_dealloc", // 82 + 0, // 0 + 0, // 1 + 0, // 2 + 0, // 3 + 0, // 4 + 0, // 5 + 0, // 6 + 0, // 7 + 0, // 8 + 0, // 9 + + "task_self", // 10 + "thread_reply", // 11 + "task_notify", // 12 + "thread_self", // 13 + 0, // 14 + 0, // 15 + 0, // 16 + 0, // 17 + 0, // 18 + 0, // 19 + + "msg_send_trap", // 20 + "msg_receive_trap", // 21 + "msg_rpc_trap", // 22 + 0, // 23 + "nxm_block", // 24 + "nxm_unblock", // 25 + 0, // 26 + 0, // 27 + 0, // 28 + "nxm_thread_destroy", // 29 + + "lw_wire", // 30 + "lw_unwire", // 31 + "nxm_thread_create", // 32 + "nxm_task_init", // 33 + 0, // 34 + "nxm_idle", // 35 + "nxm_wakeup_idle", // 36 + "nxm_set_pthid", // 37 + "nxm_thread_kill", // 38 + "nxm_thread_block", // 39 + + "nxm_thread_wakeup", // 40 + "init_process", // 41 + "nxm_get_binding", // 42 + "map_fd", // 43 + "nxm_resched", // 44 + "nxm_set_cancel", // 45 + "nxm_set_binding", // 46 + "stack_create", // 47 + "nxm_get_state", // 48 + "nxm_thread_suspend", // 49 + + "nxm_thread_resume", // 50 + "nxm_signal_check", // 51 + "htg_unix_syscall", // 52 + 0, // 53 + 0, // 54 + "host_self", // 55 + "host_priv_self", // 56 + 0, // 57 + 0, // 58 + "swtch_pri", // 59 + + "swtch", // 60 + "thread_switch", // 61 + "semop_fast", // 62 + "nxm_pshared_init", // 63 + "nxm_pshared_block", // 64 + "nxm_pshared_unblock", // 65 + "nxm_pshared_destroy", // 66 + "nxm_swtch_pri", // 67 + "lw_syscall", // 68 + 0, // 69 + + "mach_sctimes_0", // 70 + "mach_sctimes_1", // 71 + "mach_sctimes_2", // 72 + "mach_sctimes_3", // 73 + "mach_sctimes_4", // 74 + "mach_sctimes_5", // 75 + "mach_sctimes_6", // 76 + "mach_sctimes_7", // 77 + "mach_sctimes_8", // 78 + "mach_sctimes_9", // 79 + + "mach_sctimes_10", // 80 + "mach_sctimes_11", // 81 + "mach_sctimes_port_alloc_dealloc", // 82 }; } diff --git a/src/mem/cache/blk.hh b/src/mem/cache/blk.hh index 127c547ac..9bfbd646d 100644 --- a/src/mem/cache/blk.hh +++ b/src/mem/cache/blk.hh @@ -38,8 +38,8 @@ #include #include "base/printable.hh" -#include "sim/core.hh" // for Tick -#include "arch/isa_traits.hh" // for Addr +#include "sim/core.hh" // for Tick +#include "arch/isa_traits.hh" // for Addr #include "mem/packet.hh" #include "mem/request.hh" @@ -48,17 +48,17 @@ */ enum CacheBlkStatusBits { /** valid, readable */ - BlkValid = 0x01, + BlkValid = 0x01, /** write permission */ - BlkWritable = 0x02, + BlkWritable = 0x02, /** read permission (yes, block can be valid but not readable) */ - BlkReadable = 0x04, + BlkReadable = 0x04, /** dirty (modified) */ - BlkDirty = 0x08, + BlkDirty = 0x08, /** block was referenced */ - BlkReferenced = 0x10, + BlkReferenced = 0x10, /** block was a hardware prefetch yet unaccessed*/ - BlkHWPrefetched = 0x20 + BlkHWPrefetched = 0x20 }; /** @@ -108,8 +108,8 @@ class CacheBlk */ class Lock { public: - int cpuNum; // locking CPU - int threadNum; // locking thread ID within CPU + int cpuNum; // locking CPU + int threadNum; // locking thread ID within CPU // check for matching execution context bool matchesContext(Request *req) diff --git a/src/mem/cache/builder.cc b/src/mem/cache/builder.cc index db900c64c..97930fe60 100644 --- a/src/mem/cache/builder.cc +++ b/src/mem/cache/builder.cc @@ -100,101 +100,101 @@ using namespace TheISA; return retval; \ } while (0) -#define BUILD_CACHE_PANIC(x) do { \ - panic("%s not compiled into M5", x); \ +#define BUILD_CACHE_PANIC(x) do { \ + panic("%s not compiled into M5", x); \ } while (0) #if defined(USE_CACHE_FALRU) -#define BUILD_FALRU_CACHE do { \ +#define BUILD_FALRU_CACHE do { \ FALRU *tags = new FALRU(block_size, size, latency); \ - BUILD_CACHE(FALRU, tags); \ + BUILD_CACHE(FALRU, tags); \ } while (0) #else #define BUILD_FALRU_CACHE BUILD_CACHE_PANIC("falru cache") #endif #if defined(USE_CACHE_LRU) -#define BUILD_LRU_CACHE do { \ - LRU *tags = new LRU(numSets, block_size, assoc, latency); \ - BUILD_CACHE(LRU, tags); \ +#define BUILD_LRU_CACHE do { \ + LRU *tags = new LRU(numSets, block_size, assoc, latency); \ + BUILD_CACHE(LRU, tags); \ } while (0) #else #define BUILD_LRU_CACHE BUILD_CACHE_PANIC("lru cache") #endif #if defined(USE_CACHE_SPLIT) -#define BUILD_SPLIT_CACHE do { \ +#define BUILD_SPLIT_CACHE do { \ Split *tags = new Split(numSets, block_size, assoc, split_size, lifo, \ - two_queue, latency); \ - BUILD_CACHE(Split, tags); \ + two_queue, latency); \ + BUILD_CACHE(Split, tags); \ } while (0) #else #define BUILD_SPLIT_CACHE BUILD_CACHE_PANIC("split cache") #endif #if defined(USE_CACHE_SPLIT_LIFO) -#define BUILD_SPLIT_LIFO_CACHE do { \ +#define BUILD_SPLIT_LIFO_CACHE do { \ SplitLIFO *tags = new SplitLIFO(block_size, size, assoc, \ - latency, two_queue, -1); \ - BUILD_CACHE(SplitLIFO, tags); \ + latency, two_queue, -1); \ + BUILD_CACHE(SplitLIFO, tags); \ } while (0) #else #define BUILD_SPLIT_LIFO_CACHE BUILD_CACHE_PANIC("lifo cache") #endif #if defined(USE_CACHE_IIC) -#define BUILD_IIC_CACHE do { \ - IIC *tags = new IIC(iic_params); \ - BUILD_CACHE(IIC, tags); \ +#define BUILD_IIC_CACHE do { \ + IIC *tags = new IIC(iic_params); \ + BUILD_CACHE(IIC, tags); \ } while (0) #else #define BUILD_IIC_CACHE BUILD_CACHE_PANIC("iic") #endif -#define BUILD_CACHES do { \ - if (repl == NULL) { \ - if (numSets == 1) { \ - BUILD_FALRU_CACHE; \ - } else { \ - if (split == true) { \ - BUILD_SPLIT_CACHE; \ - } else if (lifo == true) { \ - BUILD_SPLIT_LIFO_CACHE; \ - } else { \ - BUILD_LRU_CACHE; \ - } \ - } \ - } else { \ - BUILD_IIC_CACHE; \ - } \ +#define BUILD_CACHES do { \ + if (repl == NULL) { \ + if (numSets == 1) { \ + BUILD_FALRU_CACHE; \ + } else { \ + if (split == true) { \ + BUILD_SPLIT_CACHE; \ + } else if (lifo == true) { \ + BUILD_SPLIT_LIFO_CACHE; \ + } else { \ + BUILD_LRU_CACHE; \ + } \ + } \ + } else { \ + BUILD_IIC_CACHE; \ + } \ } while (0) -#define BUILD_COHERENCE(b) do { \ +#define BUILD_COHERENCE(b) do { \ } while (0) #if defined(USE_TAGGED) -#define BUILD_TAGGED_PREFETCHER(t) \ +#define BUILD_TAGGED_PREFETCHER(t) \ pf = new TaggedPrefetcher(this) #else #define BUILD_TAGGED_PREFETCHER(t) BUILD_CACHE_PANIC("Tagged Prefetcher") #endif #if defined(USE_STRIDED) -#define BUILD_STRIDED_PREFETCHER(t) \ +#define BUILD_STRIDED_PREFETCHER(t) \ pf = new StridePrefetcher(this) #else #define BUILD_STRIDED_PREFETCHER(t) BUILD_CACHE_PANIC("Stride Prefetcher") #endif #if defined(USE_GHB) -#define BUILD_GHB_PREFETCHER(t) \ +#define BUILD_GHB_PREFETCHER(t) \ pf = new GHBPrefetcher(this) #else #define BUILD_GHB_PREFETCHER(t) BUILD_CACHE_PANIC("GHB Prefetcher") #endif #if defined(USE_TAGGED) -#define BUILD_NULL_PREFETCHER(t) \ +#define BUILD_NULL_PREFETCHER(t) \ pf = new TaggedPrefetcher(this) #else #define BUILD_NULL_PREFETCHER(t) BUILD_CACHE_PANIC("NULL Prefetcher (uses Tagged)") diff --git a/src/mem/cache/prefetch/stride.cc b/src/mem/cache/prefetch/stride.cc index b116b66c7..e93058d6e 100644 --- a/src/mem/cache/prefetch/stride.cc +++ b/src/mem/cache/prefetch/stride.cc @@ -40,12 +40,12 @@ void StridePrefetcher::calculatePrefetch(PacketPtr &pkt, std::list &addresses, std::list &delays) { -// Addr blkAddr = pkt->paddr & ~(Addr)(this->blkSize-1); +// Addr blkAddr = pkt->paddr & ~(Addr)(this->blkSize-1); int cpuID = pkt->req->getCpuNum(); if (!useCPUId) cpuID = 0; /* Scan Table for IAddr Match */ -/* std::list::iterator iter; +/* std::list::iterator iter; for (iter=table[cpuID].begin(); iter !=table[cpuID].end(); iter++) { diff --git a/src/mem/cache/prefetch/stride.hh b/src/mem/cache/prefetch/stride.hh index f6bdbc424..ca173277c 100644 --- a/src/mem/cache/prefetch/stride.hh +++ b/src/mem/cache/prefetch/stride.hh @@ -50,7 +50,7 @@ class StridePrefetcher : public BasePrefetcher int stride; int64_t confidence; -/* bool operator < (strideEntry a,strideEntry b) +/* bool operator < (strideEntry a,strideEntry b) { if (a.confidence == b.confidence) { return true; //?????? diff --git a/src/mem/cache/tags/iic.cc b/src/mem/cache/tags/iic.cc index 2825599f6..af9a75d43 100644 --- a/src/mem/cache/tags/iic.cc +++ b/src/mem/cache/tags/iic.cc @@ -365,7 +365,7 @@ IIC::freeReplacementBlock(PacketList & writebacks) tag_ptr->refCount = 0; if (tag_ptr->isDirty()) { -/* PacketPtr writeback = +/* PacketPtr writeback = buildWritebackReq(regenerateBlkAddr(tag_ptr->tag, 0), tag_ptr->req->asid, tag_ptr->xc, blkSize, tag_ptr->data, diff --git a/src/mem/cache/tags/lru.cc b/src/mem/cache/tags/lru.cc index 7f352e9c4..7fb5318a0 100644 --- a/src/mem/cache/tags/lru.cc +++ b/src/mem/cache/tags/lru.cc @@ -113,7 +113,7 @@ LRU::LRU(int _numSets, int _blkSize, int _assoc, int _hit_latency) : // allocate data storage in one big chunk dataBlks = new uint8_t[numSets*assoc*blkSize]; - blkIndex = 0; // index into blks array + blkIndex = 0; // index into blks array for (i = 0; i < numSets; ++i) { sets[i].assoc = assoc; @@ -160,7 +160,7 @@ LRU::probe(Addr addr) const LRUBlk *blk = sets[myset].findBlk(tag); - return (blk != NULL); // true if in cache + return (blk != NULL); // true if in cache } LRUBlk* diff --git a/src/mem/cache/tags/lru.hh b/src/mem/cache/tags/lru.hh index ea5606cde..65be492de 100644 --- a/src/mem/cache/tags/lru.hh +++ b/src/mem/cache/tags/lru.hh @@ -127,7 +127,7 @@ public: * @param _assoc The associativity of the cache. * @param _hit_latency The latency in cycles for a hit. */ - LRU(int _numSets, int _blkSize, int _assoc, int _hit_latency); + LRU(int _numSets, int _blkSize, int _assoc, int _hit_latency); /** * Destructor diff --git a/src/mem/cache/tags/split_lru.cc b/src/mem/cache/tags/split_lru.cc index bcccdcb30..2b01b07cd 100644 --- a/src/mem/cache/tags/split_lru.cc +++ b/src/mem/cache/tags/split_lru.cc @@ -113,7 +113,7 @@ SplitLRU::SplitLRU(int _numSets, int _blkSize, int _assoc, int _hit_latency, int // allocate data storage in one big chunk dataBlks = new uint8_t[numSets*assoc*blkSize]; - blkIndex = 0; // index into blks array + blkIndex = 0; // index into blks array for (i = 0; i < numSets; ++i) { sets[i].assoc = assoc; @@ -179,7 +179,7 @@ SplitLRU::probe(Addr addr) const SplitBlk *blk = sets[myset].findBlk(tag); - return (blk != NULL); // true if in cache + return (blk != NULL); // true if in cache } SplitBlk* diff --git a/src/mem/dram.cc b/src/mem/dram.cc index 75146f9ed..ff01ab1dc 100644 --- a/src/mem/dram.cc +++ b/src/mem/dram.cc @@ -366,7 +366,7 @@ DRAMMemory::calculateLatency(PacketPtr pkt) int lat=0, temp=0, current_bank=0; int current_row=0, current_device=0; - int was_miss = 0; // determines if there was an active row miss this access + int was_miss = 0; // determines if there was an active row miss this access //md_addr_t physic_address; /* linear memory address to be accessed */ Addr physic_address; /* linear memory address to be accessed */ @@ -415,7 +415,7 @@ DRAMMemory::calculateLatency(PacketPtr pkt) int SD_BEST_T_WRITE_WRITE_OBANK = 0; /* WAW, row miss/hit, another bank */ Tick time_since_last_access = curTick-time_last_access; - Tick time_last_miss = 0; // used for keeping track of times between activations (page misses) + Tick time_last_miss = 0; // used for keeping track of times between activations (page misses) //int was_idle = (curTick > busy_until); bool srow_flag = false; int timing_correction = 0; @@ -433,7 +433,7 @@ DRAMMemory::calculateLatency(PacketPtr pkt) // SDRAM does not use the active_row array in closed_page mode // TODO: handle closed page operation - } else { // DRDRAM uses the active_row array + } else { // DRDRAM uses the active_row array for( int i = 0; i < bank_max; i++ ) { if( (active_row[current_bank] != row_max)) all_precharged = 0; } @@ -923,7 +923,7 @@ DRAMMemory::calculateLatency(PacketPtr pkt) } // cout <<"cpu id = " << _cpu_num << "current_bank = " << current_bank << endl; // if((_cpu_num < num_cpus) && (_cpu_num >= 0)) - // bank_access_profile[_cpu_num][current_bank]++; + // bank_access_profile[_cpu_num][current_bank]++; return lat; } @@ -2034,7 +2034,7 @@ DRAMMemory::calculateLatency(PacketPtr pkt) // if((_cpu_num < num_cpus) && (_cpu_num >= 0)) // cout <<"cpu id = " << _cpu_num << "current_bank = " << current_bank << endl; - // bank_access_profile[_cpu_num][current_bank]++; + // bank_access_profile[_cpu_num][current_bank]++; return lat; } @@ -2226,7 +2226,7 @@ DRAMMemory::calculateLatency(PacketPtr pkt) /*fprintf(stderr,"%10.0f %10.0f %4d %4d \n",(double)busy_until, (double)curTick, overlap, lat);debug*/ // if((_cpu_num < num_cpus) && (_cpu_num >= 0)) // cout <<"cpu id = " << _cpu_num << "current_bank = " << current_bank << endl; - // bank_access_profile[_cpu_num][current_bank]++; + // bank_access_profile[_cpu_num][current_bank]++; return lat; } @@ -2468,7 +2468,7 @@ DRAMMemory::calculateLatency(PacketPtr pkt) // if((_cpu_num < num_cpus) && (_cpu_num >= 0)) // cout <<"cpu id = " << _cpu_num << "current_bank = " << current_bank << endl; - // bank_access_profile[_cpu_num][current_bank]++; + // bank_access_profile[_cpu_num][current_bank]++; return lat; } @@ -2525,7 +2525,7 @@ DRAMMemory::calculateLatency(PacketPtr pkt) // if((_cpu_num < num_cpus) && (_cpu_num >= 0)) // cout <<"cpu id = " << _cpu_num << "current_bank = " << current_bank << endl; - // bank_access_profile[_cpu_num][current_bank]++; + // bank_access_profile[_cpu_num][current_bank]++; return lat; } @@ -2593,7 +2593,7 @@ DRAMMemory::calculateLatency(PacketPtr pkt) } // if((_cpu_num < num_cpus) && (_cpu_num >= 0)) // cout <<"cpu id = " << _cpu_num << "current_bank = " << current_bank << endl; - // bank_access_profile[_cpu_num][current_bank]++; + // bank_access_profile[_cpu_num][current_bank]++; return lat; } @@ -2608,7 +2608,7 @@ DRAMMemory::calculateLatency(PacketPtr pkt) assert(chunks >0); // if((_cpu_num < num_cpus) && (_cpu_num >= 0)) // cout <<"cpu id = " << _cpu_num << "current_bank = " << current_bank << endl; - // bank_access_profile[_cpu_num][current_bank]++; + // bank_access_profile[_cpu_num][current_bank]++; return(/* first chunk latency */act_lat + (/* remainder chunk latency */cas_lat * (chunks - 1))); } diff --git a/src/mem/physical.hh b/src/mem/physical.hh index ceb36b5c0..2a0086ba9 100644 --- a/src/mem/physical.hh +++ b/src/mem/physical.hh @@ -89,9 +89,9 @@ class PhysicalMemory : public MemObject static Addr mask(Addr paddr) { return (paddr & ~Addr_Mask); } - Addr addr; // locked address - int cpuNum; // locking CPU - int threadNum; // locking thread ID within CPU + Addr addr; // locked address + int cpuNum; // locking CPU + int threadNum; // locking thread ID within CPU // check for matching execution context bool matchesContext(Request *req) diff --git a/src/mem/request.hh b/src/mem/request.hh index 85ff8a445..ab8f9d596 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -53,21 +53,21 @@ typedef Request* RequestPtr; /** ASI information for this request if it exsits. */ const uint32_t ASI_BITS = 0x000FF; /** The request is a Load locked/store conditional. */ -const uint32_t LOCKED = 0x00100; +const uint32_t LOCKED = 0x00100; /** The virtual address is also the physical address. */ -const uint32_t PHYSICAL = 0x00200; +const uint32_t PHYSICAL = 0x00200; /** The request is an ALPHA VPTE pal access (hw_ld). */ -const uint32_t VPTE = 0x00400; +const uint32_t VPTE = 0x00400; /** Use the alternate mode bits in ALPHA. */ -const uint32_t ALTMODE = 0x00800; +const uint32_t ALTMODE = 0x00800; /** The request is to an uncacheable address. */ -const uint32_t UNCACHEABLE = 0x01000; +const uint32_t UNCACHEABLE = 0x01000; /** The request should not cause a page fault. */ const uint32_t NO_FAULT = 0x02000; /** The request should be prefetched into the exclusive state. */ -const uint32_t PF_EXCLUSIVE = 0x10000; +const uint32_t PF_EXCLUSIVE = 0x10000; /** The request should be marked as LRU. */ -const uint32_t EVICT_NEXT = 0x20000; +const uint32_t EVICT_NEXT = 0x20000; /** The request should ignore unaligned access faults */ const uint32_t NO_ALIGN_FAULT = 0x40000; /** The request was an instruction read. */ diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index 4cf0f7a3d..64f4ec5af 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -729,7 +729,7 @@ class SimObject(object): self._children[child].unproxy_all() def print_ini(self, ini_file): - print >>ini_file, '[' + self.path() + ']' # .ini section header + print >>ini_file, '[' + self.path() + ']' # .ini section header instanceDict[self.path()] = self @@ -756,7 +756,7 @@ class SimObject(object): if port != None: print >>ini_file, '%s=%s' % (port_name, port.ini_str()) - print >>ini_file # blank line between objects + print >>ini_file # blank line between objects for child in child_names: self._children[child].print_ini(ini_file) diff --git a/src/sim/async.hh b/src/sim/async.hh index 932f975d2..6dd5b8a0d 100644 --- a/src/sim/async.hh +++ b/src/sim/async.hh @@ -42,12 +42,12 @@ /// then checked in the main event loop. Defined in main.cc. /// @note See the PollQueue object (in pollevent.hh) for the use of async_io and async_alarm. //@{ -extern volatile bool async_event; ///< Some asynchronous event has happened. -extern volatile bool async_statdump; ///< Async request to dump stats. -extern volatile bool async_statreset; ///< Async request to reset stats. -extern volatile bool async_exit; ///< Async request to exit simulator. -extern volatile bool async_io; ///< Async I/O request (SIGIO). -extern volatile bool async_alarm; ///< Async alarm event (SIGALRM). +extern volatile bool async_event; ///< Some asynchronous event has happened. +extern volatile bool async_statdump; ///< Async request to dump stats. +extern volatile bool async_statreset; ///< Async request to reset stats. +extern volatile bool async_exit; ///< Async request to exit simulator. +extern volatile bool async_io; ///< Async I/O request (SIGIO). +extern volatile bool async_alarm; ///< Async alarm event (SIGALRM). extern volatile bool async_exception; ///< Python exception. //@} diff --git a/src/sim/debug.cc b/src/sim/debug.cc index 36ac4efac..5a65f096a 100644 --- a/src/sim/debug.cc +++ b/src/sim/debug.cc @@ -62,7 +62,7 @@ class DebugBreakEvent : public Event DebugBreakEvent(EventQueue *q, Tick _when); - void process(); // process event + void process(); // process event virtual const char *description() const; }; diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index bc9b2353f..2003c64ee 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -48,7 +48,7 @@ #include "sim/serialize.hh" #include "sim/host.hh" -class EventQueue; // forward declaration +class EventQueue; // forward declaration ////////////////////// // @@ -93,8 +93,8 @@ class Event : public Serializable, public FastAlloc /// scheduled on this queue yet) EventQueue *_queue; - Tick _when; //!< timestamp when event should be processed - short _priority; //!< event priority + Tick _when; //!< timestamp when event should be processed + short _priority; //!< event priority short _flags; #ifndef NDEBUG @@ -141,7 +141,7 @@ class Event : public Serializable, public FastAlloc EventQueue *queue() const { return _queue; } // This function isn't really useful if TRACING_ON is not defined - virtual void trace(const char *action); //!< trace event activity + virtual void trace(const char *action); //!< trace event activity public: /// Event priorities, to provide tie-breakers for events scheduled @@ -150,7 +150,7 @@ class Event : public Serializable, public FastAlloc /// be ordered within a cycle. enum Priority { /// Minimum priority - Minimum_Pri = SHRT_MIN, + Minimum_Pri = SHRT_MIN, /// If we enable tracing on a particular cycle, do that as the /// very first thing so we don't miss any of the events on @@ -160,44 +160,44 @@ class Event : public Serializable, public FastAlloc /// Breakpoints should happen before anything else (except /// enabling trace output), so we don't miss any action when /// debugging. - Debug_Break_Pri = -100, + Debug_Break_Pri = -100, /// CPU switches schedule the new CPU's tick event for the /// same cycle (after unscheduling the old CPU's tick event). /// The switch needs to come before any tick events to make /// sure we don't tick both CPUs in the same cycle. - CPU_Switch_Pri = -31, + CPU_Switch_Pri = -31, /// For some reason "delayed" inter-cluster writebacks are /// scheduled before regular writebacks (which have default /// priority). Steve? - Delayed_Writeback_Pri = -1, + Delayed_Writeback_Pri = -1, /// Default is zero for historical reasons. - Default_Pri = 0, + Default_Pri = 0, /// Serailization needs to occur before tick events also, so /// that a serialize/unserialize is identical to an on-line /// CPU switch. - Serialize_Pri = 32, + Serialize_Pri = 32, /// CPU ticks must come after other associated CPU events /// (such as writebacks). - CPU_Tick_Pri = 50, + CPU_Tick_Pri = 50, /// Statistics events (dump, reset, etc.) come after /// everything else, but before exit. - Stat_Event_Pri = 90, + Stat_Event_Pri = 90, /// Progress events come at the end. Progress_Event_Pri = 95, /// If we want to exit on this cycle, it's the very last thing /// we do. - Sim_Exit_Pri = 100, + Sim_Exit_Pri = 100, /// Maximum priority - Maximum_Pri = SHRT_MAX + Maximum_Pri = SHRT_MAX }; /* diff --git a/src/sim/host.hh b/src/sim/host.hh index 93a5fe7f2..518873ab3 100644 --- a/src/sim/host.hh +++ b/src/sim/host.hh @@ -42,9 +42,9 @@ /** uint64_t constant */ -#define ULL(N) ((uint64_t)N##ULL) +#define ULL(N) ((uint64_t)N##ULL) /** int64_t constant */ -#define LL(N) ((int64_t)N##LL) +#define LL(N) ((int64_t)N##LL) /** Statistics counter type. Not much excuse for not using a 64-bit * integer here, but if you're desperate and only run short diff --git a/src/sim/insttracer.hh b/src/sim/insttracer.hh index 9a20c7c56..39a5536b0 100644 --- a/src/sim/insttracer.hh +++ b/src/sim/insttracer.hh @@ -34,7 +34,7 @@ #include "base/bigint.hh" #include "base/trace.hh" -#include "cpu/inst_seq.hh" // for InstSeqNum +#include "cpu/inst_seq.hh" // for InstSeqNum #include "cpu/static_inst.hh" #include "sim/host.hh" #include "sim/sim_object.hh" @@ -71,7 +71,7 @@ class InstRecord } data; enum { DataInvalid = 0, - DataInt8 = 1, // set to equal number of bytes + DataInt8 = 1, // set to equal number of bytes DataInt16 = 2, DataInt32 = 4, DataInt64 = 8, diff --git a/src/sim/process.hh b/src/sim/process.hh index 55bae2542..cb59fed64 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -95,17 +95,17 @@ class Process : public SimObject WaitRec(Addr chan, ThreadContext *ctx) : waitChan(chan), waitingContext(ctx) - { } + { } }; // list of all blocked contexts std::list waitList; - Addr brk_point; // top of the data segment + Addr brk_point; // top of the data segment - Addr stack_base; // stack segment base (highest address) - unsigned stack_size; // initial stack size - Addr stack_min; // lowest address accessed on the stack + Addr stack_base; // stack segment base (highest address) + unsigned stack_size; // initial stack size + Addr stack_min; // lowest address accessed on the stack // The maximum size allowed for the stack. Addr max_stack_size; @@ -121,9 +121,9 @@ class Process : public SimObject Addr nxm_start; Addr nxm_end; - std::string prog_fname; // file name + std::string prog_fname; // file name - Stats::Scalar<> num_syscalls; // number of syscalls executed + Stats::Scalar<> num_syscalls; // number of syscalls executed protected: diff --git a/src/sim/serialize.cc b/src/sim/serialize.cc index a0d17f489..7050779b2 100644 --- a/src/sim/serialize.cc +++ b/src/sim/serialize.cc @@ -321,23 +321,23 @@ objParamIn(Checkpoint *cp, const std::string §ion, } -#define INSTANTIATE_PARAM_TEMPLATES(type) \ -template void \ -paramOut(ostream &os, const std::string &name, type const ¶m); \ -template void \ -paramIn(Checkpoint *cp, const std::string §ion, \ - const std::string &name, type & param); \ -template void \ -arrayParamOut(ostream &os, const std::string &name, \ - type const *param, int size); \ -template void \ -arrayParamIn(Checkpoint *cp, const std::string §ion, \ +#define INSTANTIATE_PARAM_TEMPLATES(type) \ +template void \ +paramOut(ostream &os, const std::string &name, type const ¶m); \ +template void \ +paramIn(Checkpoint *cp, const std::string §ion, \ + const std::string &name, type & param); \ +template void \ +arrayParamOut(ostream &os, const std::string &name, \ + type const *param, int size); \ +template void \ +arrayParamIn(Checkpoint *cp, const std::string §ion, \ const std::string &name, type *param, int size); \ -template void \ -arrayParamOut(ostream &os, const std::string &name, \ - const std::vector ¶m); \ -template void \ -arrayParamIn(Checkpoint *cp, const std::string §ion, \ +template void \ +arrayParamOut(ostream &os, const std::string &name, \ + const std::vector ¶m); \ +template void \ +arrayParamIn(Checkpoint *cp, const std::string §ion, \ const std::string &name, std::vector ¶m); INSTANTIATE_PARAM_TEMPLATES(signed char) diff --git a/src/sim/serialize.hh b/src/sim/serialize.hh index e72eedb30..4c5f399e6 100644 --- a/src/sim/serialize.hh +++ b/src/sim/serialize.hh @@ -82,33 +82,33 @@ objParamIn(Checkpoint *cp, const std::string §ion, // These macros are streamlined to use in serialize/unserialize // functions. It's assumed that serialize() has a parameter 'os' for // the ostream, and unserialize() has parameters 'cp' and 'section'. -#define SERIALIZE_SCALAR(scalar) paramOut(os, #scalar, scalar) +#define SERIALIZE_SCALAR(scalar) paramOut(os, #scalar, scalar) -#define UNSERIALIZE_SCALAR(scalar) paramIn(cp, section, #scalar, scalar) +#define UNSERIALIZE_SCALAR(scalar) paramIn(cp, section, #scalar, scalar) // ENUMs are like SCALARs, but we cast them to ints on the way out -#define SERIALIZE_ENUM(scalar) paramOut(os, #scalar, (int)scalar) +#define SERIALIZE_ENUM(scalar) paramOut(os, #scalar, (int)scalar) -#define UNSERIALIZE_ENUM(scalar) \ - do { \ - int tmp; \ - paramIn(cp, section, #scalar, tmp); \ - scalar = (typeof(scalar))tmp; \ +#define UNSERIALIZE_ENUM(scalar) \ + do { \ + int tmp; \ + paramIn(cp, section, #scalar, tmp); \ + scalar = (typeof(scalar))tmp; \ } while (0) -#define SERIALIZE_ARRAY(member, size) \ +#define SERIALIZE_ARRAY(member, size) \ arrayParamOut(os, #member, member, size) -#define UNSERIALIZE_ARRAY(member, size) \ +#define UNSERIALIZE_ARRAY(member, size) \ arrayParamIn(cp, section, #member, member, size) -#define SERIALIZE_OBJPTR(objptr) paramOut(os, #objptr, (objptr)->name()) +#define SERIALIZE_OBJPTR(objptr) paramOut(os, #objptr, (objptr)->name()) -#define UNSERIALIZE_OBJPTR(objptr) \ - do { \ - SimObject *sptr; \ - objParamIn(cp, section, #objptr, sptr); \ - objptr = dynamic_cast(sptr); \ +#define UNSERIALIZE_OBJPTR(objptr) \ + do { \ + SimObject *sptr; \ + objParamIn(cp, section, #objptr, sptr); \ + objptr = dynamic_cast(sptr); \ } while (0) /* @@ -211,8 +211,8 @@ class SerializableClass // SerializableBuilder and SerializableClass objects // -#define REGISTER_SERIALIZEABLE(CLASS_NAME, OBJ_CLASS) \ -SerializableClass the##OBJ_CLASS##Class(CLASS_NAME, \ +#define REGISTER_SERIALIZEABLE(CLASS_NAME, OBJ_CLASS) \ +SerializableClass the##OBJ_CLASS##Class(CLASS_NAME, \ OBJ_CLASS::createForUnserialize); void diff --git a/src/sim/sim_events.hh b/src/sim/sim_events.hh index 58ec963c0..6f9b7f612 100644 --- a/src/sim/sim_events.hh +++ b/src/sim/sim_events.hh @@ -58,15 +58,15 @@ class SimLoopExitEvent : public Event { setFlags(IsExitEvent); schedule(_when); } // SimLoopExitEvent(EventQueue *q, -// Tick _when, const std::string &_cause, -// Tick _repeat = 0, int c = 0) -// : Event(q, Sim_Exit_Pri), cause(_cause), code(c), repeat(_repeat) +// Tick _when, const std::string &_cause, +// Tick _repeat = 0, int c = 0) +// : Event(q, Sim_Exit_Pri), cause(_cause), code(c), repeat(_repeat) // { setFlags(IsExitEvent); schedule(_when); } std::string getCause() { return cause; } int getCode() { return code; } - void process(); // process event + void process(); // process event virtual const char *description() const; }; @@ -95,14 +95,14 @@ class CountedDrainEvent : public SimLoopExitEvent class CountedExitEvent : public Event { private: - std::string cause; // string explaining why we're terminating - int &downCounter; // decrement & terminate if zero + std::string cause; // string explaining why we're terminating + int &downCounter; // decrement & terminate if zero public: CountedExitEvent(EventQueue *q, const std::string &_cause, Tick _when, int &_downCounter); - void process(); // process event + void process(); // process event virtual const char *description() const; }; @@ -120,7 +120,7 @@ class CheckSwapEvent : public Event : Event(q), interval(ival) { schedule(curTick + interval); } - void process(); // process event + void process(); // process event virtual const char *description() const; }; diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index 3f6c56b5f..e0e703815 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -558,7 +558,7 @@ getuidPseudoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, // EUID goes in r20. tc->setIntReg(SyscallPseudoReturnReg, process->euid()); //EUID - return process->uid(); // UID + return process->uid(); // UID } @@ -604,14 +604,14 @@ SyscallReturn getuidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - return process->uid(); // UID + return process->uid(); // UID } SyscallReturn geteuidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - return process->euid(); // UID + return process->euid(); // UID } SyscallReturn diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index caf269918..2e8071196 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -44,15 +44,15 @@ #include #include #ifdef __CYGWIN32__ -#include // for O_BINARY +#include // for O_BINARY #endif #include #include #include -#include "sim/host.hh" // for Addr +#include "sim/host.hh" // for Addr #include "base/chunk_generator.hh" -#include "base/intmath.hh" // for RoundUp +#include "base/intmath.hh" // for RoundUp #include "base/misc.hh" #include "base/trace.hh" #include "cpu/base.hh" @@ -72,9 +72,9 @@ class SyscallDesc { typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num, LiveProcess *, ThreadContext *); - const char *name; //!< Syscall name (e.g., "open"). - FuncPtr funcPtr; //!< Pointer to emulation function. - int flags; //!< Flags (see Flags enum). + const char *name; //!< Syscall name (e.g., "open"). + FuncPtr funcPtr; //!< Pointer to emulation function. + int flags; //!< Flags (see Flags enum). /// Flag values for controlling syscall behavior. enum Flags { @@ -117,7 +117,7 @@ class BaseBufferArg { virtual bool copyIn(TranslatingPort *memport) { memport->readBlob(addr, bufPtr, size); - return true; // no EFAULT detection for now + return true; // no EFAULT detection for now } // @@ -126,7 +126,7 @@ class BaseBufferArg { virtual bool copyOut(TranslatingPort *memport) { memport->writeBlob(addr, bufPtr, size); - return true; // no EFAULT detection for now + return true; // no EFAULT detection for now } protected: @@ -140,7 +140,7 @@ class BufferArg : public BaseBufferArg { public: BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { } - void *bufferPtr() { return bufPtr; } + void *bufferPtr() { return bufPtr; } }; template @@ -158,8 +158,8 @@ class TypedBufferArg : public BaseBufferArg operator T*() { return (T *)bufPtr; } // dereference operators - T &operator*() { return *((T *)bufPtr); } - T* operator->() { return (T *)bufPtr; } + T &operator*() { return *((T *)bufPtr); } + T* operator->() { return (T *)bufPtr; } T &operator[](int i) { return ((T *)bufPtr)[i]; } }; @@ -994,7 +994,7 @@ SyscallReturn getrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - int who = tc->getSyscallArg(0); // THREAD, SELF, or CHILDREN + int who = tc->getSyscallArg(0); // THREAD, SELF, or CHILDREN TypedBufferArg rup(tc->getSyscallArg(1)); rup->ru_utime.tv_sec = 0; -- cgit v1.2.3 From f066db7fcd49d2234178e5d80db9278c798d9ba8 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 19 Sep 2008 09:11:40 -0700 Subject: inifile: Whack preprocessor access. We haven't used the preprocessor feature of the inifile stuff in a very long time, so let's get rid of it since it would otherwise take effort to maintain. --- src/base/inifile.cc | 111 ---------------------------------------------------- src/base/inifile.hh | 8 ---- 2 files changed, 119 deletions(-) (limited to 'src') diff --git a/src/base/inifile.cc b/src/base/inifile.cc index 809cbe172..24d0013c4 100644 --- a/src/base/inifile.cc +++ b/src/base/inifile.cc @@ -29,22 +29,8 @@ * Steve Reinhardt */ -#define USE_CPP - -#ifdef USE_CPP -#include -#include -#include - -#include -#include -#include -#include -#endif - #include #include - #include #include @@ -67,103 +53,6 @@ IniFile::~IniFile() } } - -#ifdef USE_CPP -bool -IniFile::loadCPP(const string &file, vector &cppArgs) -{ - // Open the file just to verify that we can. Otherwise if the - // file doesn't exist or has bad permissions the user will get - // confusing errors from cpp/g++. - ifstream tmpf(file.c_str()); - - if (!tmpf.is_open()) - return false; - - tmpf.close(); - - char *cfile = strncpy(new char[file.size() + 1], file.c_str(), - file.size()); - char *dir = dirname(cfile); - char *dir_arg = NULL; - if (*dir != '.') { - string arg = "-I"; - arg += dir; - - dir_arg = new char[arg.size() + 1]; - strncpy(dir_arg, arg.c_str(), arg.size()); - } - - delete [] cfile; - - char tempfile[] = "/tmp/configXXXXXX"; - int tmp_fd = mkstemp(tempfile); - - int pid = fork(); - - if (pid == -1) - return false; - - if (pid == 0) { - char filename[FILENAME_MAX]; - string::size_type i = file.copy(filename, sizeof(filename) - 1); - filename[i] = '\0'; - - int arg_count = cppArgs.size(); - - const char **args = new const char *[arg_count + 20]; - - int nextArg = 0; - args[nextArg++] = "g++"; - args[nextArg++] = "-E"; - args[nextArg++] = "-P"; - args[nextArg++] = "-nostdinc"; - args[nextArg++] = "-nostdinc++"; - args[nextArg++] = "-x"; - args[nextArg++] = "c++"; - args[nextArg++] = "-undef"; - - for (int i = 0; i < arg_count; i++) - args[nextArg++] = cppArgs[i]; - - if (dir_arg) - args[nextArg++] = dir_arg; - - args[nextArg++] = filename; - args[nextArg++] = NULL; - - close(STDOUT_FILENO); - if (dup2(tmp_fd, STDOUT_FILENO) == -1) - exit(1); - - // execvp signature is intentionally broken wrt const-ness for - // backwards compatibility... see man page - execvp("g++", const_cast(args)); - - exit(0); - } - - int retval; - waitpid(pid, &retval, 0); - - delete [] dir_arg; - - // check for normal completion of CPP - if (!WIFEXITED(retval) || WEXITSTATUS(retval) != 0) - return false; - - close(tmp_fd); - - bool status = false; - - status = load(tempfile); - - unlink(tempfile); - - return status; -} -#endif - bool IniFile::load(const string &file) { diff --git a/src/base/inifile.hh b/src/base/inifile.hh index a2692919f..83cf80cf0 100644 --- a/src/base/inifile.hh +++ b/src/base/inifile.hh @@ -167,14 +167,6 @@ class IniFile /// @retval True if successful, false if errors were encountered. bool load(std::istream &f); - /// Load the specified file, passing it through the C preprocessor. - /// Parameter settings found in the file will be merged with any - /// already defined in this object. - /// @param file The path of the file to load. - /// @param cppFlags Vector of extra flags to pass to cpp. - /// @retval True if successful, false if errors were encountered. - bool loadCPP(const std::string &file, std::vector &cppFlags); - /// Load the specified file. /// Parameter settings found in the file will be merged with any /// already defined in this object. -- cgit v1.2.3 From ea83cedcf625c35ddc6fe6b9390cdd1cca6b2039 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 19 Sep 2008 09:11:42 -0700 Subject: Check the return value of I/O operations for failure --- src/base/loader/hex_file.cc | 4 +++- src/base/remote_gdb.cc | 6 ++++-- src/dev/ethertap.cc | 8 ++++++-- 3 files changed, 13 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/base/loader/hex_file.cc b/src/base/loader/hex_file.cc index 17347531e..61d6c8009 100755 --- a/src/base/loader/hex_file.cc +++ b/src/base/loader/hex_file.cc @@ -65,7 +65,9 @@ HexFile::loadSections(Port *memPort) Addr MemAddr; uint32_t Data; while (!feof(fp)) { - fgets(Line, 64, fp); + char *ret = fgets(Line, sizeof(Line), fp); + if (!ret) + panic("malformed file"); parseLine(Line, &MemAddr, &Data); if (MemAddr != 0) { // Now, write to memory diff --git a/src/base/remote_gdb.cc b/src/base/remote_gdb.cc index fe4bdad5a..93d86447e 100644 --- a/src/base/remote_gdb.cc +++ b/src/base/remote_gdb.cc @@ -346,14 +346,16 @@ uint8_t BaseRemoteGDB::getbyte() { uint8_t b; - ::read(fd, &b, 1); + if (::read(fd, &b, 1) != 1) + warn("could not read byte from debugger"); return b; } void BaseRemoteGDB::putbyte(uint8_t b) { - ::write(fd, &b, 1); + if (::write(fd, &b, 1) != 1) + warn("could not write byte to debugger"); } // Send a packet to gdb diff --git a/src/dev/ethertap.cc b/src/dev/ethertap.cc index c7b292c8a..f1fd1800b 100644 --- a/src/dev/ethertap.cc +++ b/src/dev/ethertap.cc @@ -182,8 +182,12 @@ EtherTap::recvPacket(EthPacketPtr packet) DPRINTF(Ethernet, "EtherTap output len=%d\n", packet->length); DDUMP(EthernetData, packet->data, packet->length); uint32_t len = htonl(packet->length); - write(socket, &len, sizeof(len)); - write(socket, packet->data, packet->length); + ssize_t ret = write(socket, &len, sizeof(len)); + if (ret != sizeof(len)) + return false; + ret = write(socket, packet->data, packet->length); + if (ret != packet->length) + return false; interface->recvDone(); -- cgit v1.2.3 From befae3c0b025593657e52ba24c872184d17be132 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 19 Sep 2008 09:11:43 -0700 Subject: Use the proper version of C++ headers --- src/base/cprintf_formats.hh | 3 ++- src/base/misc.cc | 1 + src/base/time.cc | 6 +++--- src/sim/eventq.hh | 1 + 4 files changed, 7 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/base/cprintf_formats.hh b/src/base/cprintf_formats.hh index 4e8b2b09e..75157a540 100644 --- a/src/base/cprintf_formats.hh +++ b/src/base/cprintf_formats.hh @@ -31,8 +31,9 @@ #ifndef __BASE_CPRINTF_FORMATS_HH__ #define __BASE_CPRINTF_FORMATS_HH__ -#include +#include #include +#include namespace cp { diff --git a/src/base/misc.cc b/src/base/misc.cc index 0ab1d6041..7d284a378 100644 --- a/src/base/misc.cc +++ b/src/base/misc.cc @@ -28,6 +28,7 @@ * Authors: Nathan Binkert */ +#include #include #include diff --git a/src/base/time.cc b/src/base/time.cc index 76ba355b7..a1732773e 100644 --- a/src/base/time.cc +++ b/src/base/time.cc @@ -28,9 +28,9 @@ * Authors: Nathan Binkert */ -#include -#include -#include +#include +#include +#include #include #include diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index 2003c64ee..d172c73da 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -38,6 +38,7 @@ #include #include +#include #include #include #include -- cgit v1.2.3 From af9c5e05f73f6899a405230e66dfa75a5b39822a Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 19 Sep 2008 09:11:43 -0700 Subject: Use C++ limits where applicable for portability --- src/base/statistics.hh | 11 +++++++---- src/base/str.cc | 15 +++++++-------- 2 files changed, 14 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/base/statistics.hh b/src/base/statistics.hh index 3a859d364..17aef14b9 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -56,6 +56,7 @@ #include #include #include +#include #include #include @@ -76,6 +77,8 @@ extern Tick curTick; /* A namespace for all of the Statistics */ namespace Stats { +typedef std::numeric_limits CounterLimits; + /* Contains the statistic implementation details */ ////////////////////////////////////////////////////////////////////// // @@ -1454,8 +1457,8 @@ struct DistStor data->bucket_size = params.bucket_size; data->size = params.size; - data->min_val = (min_val == INT_MAX) ? 0 : min_val; - data->max_val = (max_val == INT_MIN) ? 0 : max_val; + data->min_val = (min_val == CounterLimits::max()) ? 0 : min_val; + data->max_val = (max_val == CounterLimits::min()) ? 0 : max_val; data->underflow = underflow; data->overflow = overflow; data->cvec.resize(params.size); @@ -1472,8 +1475,8 @@ struct DistStor */ void reset() { - min_val = INT_MAX; - max_val = INT_MIN; + min_val = CounterLimits::max(); + max_val = CounterLimits::min(); underflow = 0; overflow = 0; diff --git a/src/base/str.cc b/src/base/str.cc index 0a517dff5..2df1c103c 100644 --- a/src/base/str.cc +++ b/src/base/str.cc @@ -28,10 +28,10 @@ * Authors: Nathan Binkert */ -#include - +#include #include #include +#include #include #include @@ -117,12 +117,11 @@ inline bool __to_number(string value, T &retval) { static const T maxnum = ((T)-1); - static const bool sign = maxnum < 0; - static const int bits = sizeof(T) * 8; - static const T hexmax = maxnum & (((T)1 << (bits - 4 - sign)) - 1); - static const T octmax = maxnum & (((T)1 << (bits - 3 - sign)) - 1); - static const T signmax = - (sign) ? maxnum & (((T)1 << (bits - 1)) - 1) : maxnum; + static const bool sign = numeric_limits::is_signed; + static const int bits = numeric_limits::digits; + static const T hexmax = maxnum & (((T)1 << (bits - 4)) - 1); + static const T octmax = maxnum & (((T)1 << (bits - 3)) - 1); + static const T signmax = numeric_limits::max(); static const T decmax = signmax / 10; #if 0 -- cgit v1.2.3 From ce3d8c2b038605fa5ceb6d1ad8e27b51c1aca980 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 19 Sep 2008 09:42:31 -0700 Subject: atomicio: provide atomic read and write functions. These functions keep trying to read and write until all data has been transferred, or an error occurrs. In the case where an end of file hasn't been reached, but all of the bytes have not been read/written, try again. On EINTR, try again. --- src/base/SConscript | 1 + src/base/atomicio.cc | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/base/atomicio.hh | 44 ++++++++++++++++++++++++ src/base/circlebuf.cc | 29 ++++++++-------- src/dev/terminal.cc | 18 ++++------ 5 files changed, 157 insertions(+), 27 deletions(-) create mode 100644 src/base/atomicio.cc create mode 100644 src/base/atomicio.hh (limited to 'src') diff --git a/src/base/SConscript b/src/base/SConscript index f9d936d84..c09fdc976 100644 --- a/src/base/SConscript +++ b/src/base/SConscript @@ -31,6 +31,7 @@ Import('*') Source('annotate.cc') +Source('atomicio.cc') Source('bigint.cc') Source('circlebuf.cc') Source('cprintf.cc') diff --git a/src/base/atomicio.cc b/src/base/atomicio.cc new file mode 100644 index 000000000..3f3e6d6f0 --- /dev/null +++ b/src/base/atomicio.cc @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2008 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +#include +#include + +#include "base/atomicio.hh" + +ssize_t +atomic_read(int fd, void *s, size_t n) +{ + char *p = reinterpret_cast(s); + ssize_t pos = 0; + + // Keep reading until we've gotten all of the data. + while (n > pos) { + ssize_t result = read(fd, p + pos, n - pos); + + // We didn't get any more data, so we should probably punt, + // otherwise we'd just keep spinning + if (result == 0) + break; + + // If there was an error, try again on EINTR/EAGAIN, pass the + // error up otherwise. + if (result == -1) { + if (errno == EINTR || errno == EAGAIN) + continue; + return result; + } + + pos += result; + } + + return pos; +} + +ssize_t +atomic_write(int fd, const void *s, size_t n) +{ + const char *p = reinterpret_cast(s); + ssize_t pos = 0; + + // Keep writing until we've written all of the data + while (n > pos) { + ssize_t result = write(fd, p + pos, n - pos); + + // We didn't manage to write anything this time, so we should + // probably punt, otherwise we'd just keep spinning + if (result == 0) + break; + + // If there was an error, try again on EINTR/EAGAIN, pass the + // error up otherwise. + if (result == -1) { + if (errno == EINTR || errno == EAGAIN) + continue; + return result; + } + + pos += result; + } + + return pos; +} diff --git a/src/base/atomicio.hh b/src/base/atomicio.hh new file mode 100644 index 000000000..5e703f315 --- /dev/null +++ b/src/base/atomicio.hh @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2008 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +#ifndef __BASE_ATOMICIO_HH__ +#define __BASE_ATOMICIO_HH__ + +#include + +// These functions keep reading/writing, if possible, until all data +// has been transferred. Basically, try again when there's no error, +// but there is data left also retry on EINTR. +// This function blocks until it is done. + +ssize_t atomic_read(int fd, void *s, size_t n); +ssize_t atomic_write(int fd, const void *s, size_t n); + +#endif // __BASE_ATOMICIO_HH__ diff --git a/src/base/circlebuf.cc b/src/base/circlebuf.cc index a0c015671..d42bb11c3 100644 --- a/src/base/circlebuf.cc +++ b/src/base/circlebuf.cc @@ -29,12 +29,11 @@ */ #include +#include +#include #include -#include -#include -#include - +#include "base/atomicio.hh" #include "base/circlebuf.hh" #include "base/cprintf.hh" #include "base/intmath.hh" @@ -59,8 +58,8 @@ CircleBuf::dump() cprintf("start = %10d, stop = %10d, buflen = %10d\n", _start, _stop, _buflen); fflush(stdout); - ::write(STDOUT_FILENO, _buf, _buflen); - ::write(STDOUT_FILENO, "<\n", 2); + atomic_write(STDOUT_FILENO, _buf, _buflen); + atomic_write(STDOUT_FILENO, "<\n", 2); } void @@ -106,19 +105,19 @@ CircleBuf::read(int fd, int len) if (_stop > _start) { len = min(len, _stop - _start); - ::write(fd, _buf + _start, len); + atomic_write(fd, _buf + _start, len); _start += len; } else { int endlen = _buflen - _start; if (endlen > len) { - ::write(fd, _buf + _start, len); + atomic_write(fd, _buf + _start, len); _start += len; } else { - ::write(fd, _buf + _start, endlen); + atomic_write(fd, _buf + _start, endlen); _start = min(len - endlen, _stop); - ::write(fd, _buf, _start); + atomic_write(fd, _buf, _start); } } } @@ -129,11 +128,11 @@ CircleBuf::read(int fd) _size = 0; if (_stop > _start) { - ::write(fd, _buf + _start, _stop - _start); + atomic_write(fd, _buf + _start, _stop - _start); } else { - ::write(fd, _buf + _start, _buflen - _start); - ::write(fd, _buf, _stop); + atomic_write(fd, _buf + _start, _buflen - _start); + atomic_write(fd, _buf, _stop); } _start = _stop; @@ -159,9 +158,9 @@ void CircleBuf::readall(int fd) { if (_rollover) - ::write(fd, _buf + _stop, _buflen - _stop); + atomic_write(fd, _buf + _stop, _buflen - _stop); - ::write(fd, _buf, _stop); + atomic_write(fd, _buf, _stop); _start = _stop; } diff --git a/src/dev/terminal.cc b/src/dev/terminal.cc index 58371a2bd..8c18e3bbc 100644 --- a/src/dev/terminal.cc +++ b/src/dev/terminal.cc @@ -35,16 +35,17 @@ #include #include -#include #include #include #include +#include #include #include #include #include +#include "base/atomicio.hh" #include "base/misc.hh" #include "base/output.hh" #include "base/socket.hh" @@ -156,7 +157,7 @@ Terminal::accept() int fd = listener.accept(true); if (data_fd != -1) { char message[] = "terminal already attached!\n"; - ::write(fd, message, sizeof(message)); + atomic_write(fd, message, sizeof(message)); ::close(fd); return; } @@ -238,16 +239,9 @@ Terminal::write(const uint8_t *buf, size_t len) if (data_fd < 0) panic("Terminal not properly attached.\n"); - size_t ret; - for (;;) { - ret = ::write(data_fd, buf, len); - - if (ret >= 0) - break; - - if (errno != EINTR) - detach(); - } + ssize_t ret = atomic_write(data_fd, buf, len); + if (ret < len) + detach(); return ret; } -- cgit v1.2.3 From 4826610d8604e8ce828ebefd9d25f5ef637c3630 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 19 Sep 2008 09:42:54 -0700 Subject: We're using the static keyword improperly in some cases. --- src/arch/alpha/utility.hh | 2 +- src/sim/byteswap.hh | 56 +++++++++++++++++++++++------------------------ 2 files changed, 29 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh index 11357bc44..ddbf88e95 100644 --- a/src/arch/alpha/utility.hh +++ b/src/arch/alpha/utility.hh @@ -44,7 +44,7 @@ namespace AlphaISA uint64_t getArgument(ThreadContext *tc, int number, bool fp); - static inline bool + inline bool inUserMode(ThreadContext *tc) { return (tc->readMiscRegNoEffect(AlphaISA::IPR_DTB_CM) & 0x18) != 0; diff --git a/src/sim/byteswap.hh b/src/sim/byteswap.hh index 062fc4513..2519e552b 100644 --- a/src/sim/byteswap.hh +++ b/src/sim/byteswap.hh @@ -62,7 +62,7 @@ enum ByteOrder {BigEndianByteOrder, LittleEndianByteOrder}; //These functions actually perform the swapping for parameters //of various bit lengths -static inline uint64_t +inline uint64_t swap_byte64(uint64_t x) { #if defined(linux) @@ -81,7 +81,7 @@ swap_byte64(uint64_t x) #endif } -static inline uint32_t +inline uint32_t swap_byte32(uint32_t x) { #if defined(linux) @@ -95,7 +95,7 @@ swap_byte32(uint32_t x) #endif } -static inline uint16_t +inline uint16_t swap_byte16(uint16_t x) { #if defined(linux) @@ -113,7 +113,7 @@ swap_byte16(uint16_t x) // sizeof() values are known at compile time, it should inline to a // direct call to the right swap_byteNN() function. template -static inline T swap_byte(T x) { +inline T swap_byte(T x) { if (sizeof(T) == 8) return swap_byte64((uint64_t)x); else if (sizeof(T) == 4) @@ -127,7 +127,7 @@ static inline T swap_byte(T x) { } template<> -static inline Twin64_t swap_byte(Twin64_t x) +inline Twin64_t swap_byte(Twin64_t x) { x.a = swap_byte(x.a); x.b = swap_byte(x.b); @@ -135,7 +135,7 @@ static inline Twin64_t swap_byte(Twin64_t x) } template<> -static inline Twin32_t swap_byte(Twin32_t x) +inline Twin32_t swap_byte(Twin32_t x) { x.a = swap_byte(x.a); x.b = swap_byte(x.b); @@ -144,23 +144,23 @@ static inline Twin32_t swap_byte(Twin32_t x) //The conversion functions with fixed endianness on both ends don't need to //be in a namespace -template static inline T betole(T value) {return swap_byte(value);} -template static inline T letobe(T value) {return swap_byte(value);} +template inline T betole(T value) {return swap_byte(value);} +template inline T letobe(T value) {return swap_byte(value);} //For conversions not involving the guest system, we can define the functions //conditionally based on the BYTE_ORDER macro and outside of the namespaces #if defined(_BIG_ENDIAN) || !defined(_LITTLE_ENDIAN) && BYTE_ORDER == BIG_ENDIAN const ByteOrder HostByteOrder = BigEndianByteOrder; -template static inline T htole(T value) {return swap_byte(value);} -template static inline T letoh(T value) {return swap_byte(value);} -template static inline T htobe(T value) {return value;} -template static inline T betoh(T value) {return value;} +template inline T htole(T value) {return swap_byte(value);} +template inline T letoh(T value) {return swap_byte(value);} +template inline T htobe(T value) {return value;} +template inline T betoh(T value) {return value;} #elif defined(_LITTLE_ENDIAN) || BYTE_ORDER == LITTLE_ENDIAN const ByteOrder HostByteOrder = LittleEndianByteOrder; -template static inline T htole(T value) {return value;} -template static inline T letoh(T value) {return value;} -template static inline T htobe(T value) {return swap_byte(value);} -template static inline T betoh(T value) {return swap_byte(value);} +template inline T htole(T value) {return value;} +template inline T letoh(T value) {return value;} +template inline T htobe(T value) {return swap_byte(value);} +template inline T betoh(T value) {return swap_byte(value);} #else #error Invalid Endianess #endif @@ -169,33 +169,33 @@ namespace BigEndianGuest { const bool ByteOrderDiffers = (HostByteOrder != BigEndianByteOrder); template - static inline T gtole(T value) {return betole(value);} + inline T gtole(T value) {return betole(value);} template - static inline T letog(T value) {return letobe(value);} + inline T letog(T value) {return letobe(value);} template - static inline T gtobe(T value) {return value;} + inline T gtobe(T value) {return value;} template - static inline T betog(T value) {return value;} + inline T betog(T value) {return value;} template - static inline T htog(T value) {return htobe(value);} + inline T htog(T value) {return htobe(value);} template - static inline T gtoh(T value) {return betoh(value);} + inline T gtoh(T value) {return betoh(value);} } namespace LittleEndianGuest { const bool ByteOrderDiffers = (HostByteOrder != LittleEndianByteOrder); template - static inline T gtole(T value) {return value;} + inline T gtole(T value) {return value;} template - static inline T letog(T value) {return value;} + inline T letog(T value) {return value;} template - static inline T gtobe(T value) {return letobe(value);} + inline T gtobe(T value) {return letobe(value);} template - static inline T betog(T value) {return betole(value);} + inline T betog(T value) {return betole(value);} template - static inline T htog(T value) {return htole(value);} + inline T htog(T value) {return htole(value);} template - static inline T gtoh(T value) {return letoh(value);} + inline T gtoh(T value) {return letoh(value);} } #endif // __SIM_BYTE_SWAP_HH__ -- cgit v1.2.3 From f3f4b17c5b6f594524d54176c15c23d6338c60a4 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 22 Sep 2008 08:21:47 -0700 Subject: style --- src/arch/alpha/utility.hh | 50 ++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh index ddbf88e95..43d4908b4 100644 --- a/src/arch/alpha/utility.hh +++ b/src/arch/alpha/utility.hh @@ -41,7 +41,6 @@ namespace AlphaISA { - uint64_t getArgument(ThreadContext *tc, int number, bool fp); inline bool @@ -50,58 +49,71 @@ namespace AlphaISA return (tc->readMiscRegNoEffect(AlphaISA::IPR_DTB_CM) & 0x18) != 0; } - inline bool isCallerSaveIntegerRegister(unsigned int reg) { + inline bool + isCallerSaveIntegerRegister(unsigned int reg) + { panic("register classification not implemented"); return (reg >= 1 && reg <= 8 || reg >= 22 && reg <= 25 || reg == 27); } - inline bool isCalleeSaveIntegerRegister(unsigned int reg) { + inline bool + isCalleeSaveIntegerRegister(unsigned int reg) + { panic("register classification not implemented"); return (reg >= 9 && reg <= 15); } - inline bool isCallerSaveFloatRegister(unsigned int reg) { + inline bool + isCallerSaveFloatRegister(unsigned int reg) + { panic("register classification not implemented"); return false; } - inline bool isCalleeSaveFloatRegister(unsigned int reg) { + inline bool + isCalleeSaveFloatRegister(unsigned int reg) + { panic("register classification not implemented"); return false; } - inline Addr alignAddress(const Addr &addr, - unsigned int nbytes) { + inline Addr + alignAddress(const Addr &addr, unsigned int nbytes) + { return (addr & ~(nbytes - 1)); } // Instruction address compression hooks - inline Addr realPCToFetchPC(const Addr &addr) { + inline Addr + realPCToFetchPC(const Addr &addr) + { return addr; } - inline Addr fetchPCToRealPC(const Addr &addr) { + inline Addr + fetchPCToRealPC(const Addr &addr) + { return addr; } // the size of "fetched" instructions (not necessarily the size // of real instructions for PISA) - inline size_t fetchInstSize() { + inline size_t + fetchInstSize() + { return sizeof(MachInst); } - inline MachInst makeRegisterCopy(int dest, int src) { + inline MachInst + makeRegisterCopy(int dest, int src) + { panic("makeRegisterCopy not implemented"); return 0; } // Machine operations - - void saveMachineReg(AnyReg &savereg, const RegFile ®_file, - int regnum); - - void restoreMachineReg(RegFile ®s, const AnyReg ®, - int regnum); + void saveMachineReg(AnyReg &savereg, const RegFile ®_file, int regnum); + void restoreMachineReg(RegFile ®s, const AnyReg ®, int regnum); /** * Function to insure ISA semantics about 0 registers. @@ -112,9 +124,7 @@ namespace AlphaISA // Alpha IPR register accessors inline bool PcPAL(Addr addr) { return addr & 0x3; } - inline void startupCPU(ThreadContext *tc, int cpuId) { - tc->activate(0); - } + inline void startupCPU(ThreadContext *tc, int cpuId) { tc->activate(0); } //////////////////////////////////////////////////////////////////////// // -- cgit v1.2.3 From 6efb930e19056e3421f3bb1996bf370883873b32 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 22 Sep 2008 08:25:57 -0700 Subject: gcc: Version 4.3 is pretty anal about shadowing types, placate it. In the future, it would be nice to put the O3CPU into its own namespace so that we don't end up hardcoding pointers to the global namespace. --- src/base/varargs.hh | 4 ++-- src/cpu/o3/cpu_policy.hh | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/base/varargs.hh b/src/base/varargs.hh index 2ba8c240a..f307e58d1 100644 --- a/src/base/varargs.hh +++ b/src/base/varargs.hh @@ -150,7 +150,7 @@ struct Any : public Base template struct Argument : public RefCountingPtr > { - typedef RefCountingPtr > Base; + typedef RefCountingPtr > Base; Argument() { } Argument(const Null &null) { } @@ -169,7 +169,7 @@ template class List { public: - typedef Argument Argument; + typedef VarArgs::Argument Argument; typedef std::list list; typedef typename list::iterator iterator; typedef typename list::const_iterator const_iterator; diff --git a/src/cpu/o3/cpu_policy.hh b/src/cpu/o3/cpu_policy.hh index 32a0adcf1..c06c9a201 100644 --- a/src/cpu/o3/cpu_policy.hh +++ b/src/cpu/o3/cpu_policy.hh @@ -65,7 +65,7 @@ struct SimpleCPUPolicy /** Typedef for the branch prediction unit (which includes the BP, * RAS, and BTB). */ - typedef BPredUnit BPredUnit; + typedef ::BPredUnit BPredUnit; /** Typedef for the register file. Most classes assume a unified * physical register file. */ @@ -75,15 +75,15 @@ struct SimpleCPUPolicy /** Typedef for the rename map. */ typedef SimpleRenameMap RenameMap; /** Typedef for the ROB. */ - typedef ROB ROB; + typedef ::ROB ROB; /** Typedef for the instruction queue/scheduler. */ typedef InstructionQueue IQ; /** Typedef for the memory dependence unit. */ - typedef MemDepUnit MemDepUnit; + typedef ::MemDepUnit MemDepUnit; /** Typedef for the LSQ. */ - typedef LSQ LSQ; + typedef ::LSQ LSQ; /** Typedef for the thread-specific LSQ units. */ - typedef LSQUnit LSQUnit; + typedef ::LSQUnit LSQUnit; /** Typedef for fetch. */ typedef DefaultFetch Fetch; @@ -109,7 +109,7 @@ struct SimpleCPUPolicy typedef DefaultIEWDefaultCommit IEWStruct; /** The struct for communication within the IEW stage. */ - typedef IssueStruct IssueStruct; + typedef ::IssueStruct IssueStruct; /** The struct for all backwards communication. */ typedef TimeBufStruct TimeStruct; -- cgit v1.2.3 From 38dd9687ce7f852126161b38430b301376642b51 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 22 Sep 2008 08:25:58 -0700 Subject: scons: Separate swig environment so we can have different flags. Swig code isn't quite perfect, so let's not turn on all of the warnings. --- src/SConscript | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/SConscript b/src/SConscript index 36cbbfa78..9734a3618 100644 --- a/src/SConscript +++ b/src/SConscript @@ -543,6 +543,7 @@ SwigSource('m5.objects', params_file) # Build all swig modules swig_modules = [] +cc_swig_sources = [] for source,package in swig_sources: filename = str(source) assert filename.endswith('.i') @@ -559,7 +560,7 @@ for source,package in swig_sources: env.Depends(cc_file, source) swig_modules.append(Value(module)) - Source(cc_file) + cc_swig_sources.append(File(cc_file)) PySource(package, py_file) # Generate the main swig init file @@ -945,12 +946,18 @@ def makeEnv(label, objsfx, strip = False, **kwargs): newEnv.Label = label newEnv.Append(**kwargs) + swig_env = newEnv.Copy() + swig_env.Append(CCFLAGS='-Wno-uninitialized') + swig_objs = [ swig_env.Object(s) for s in cc_swig_sources ] + # First make a library of everything but main() so other programs can # link against m5. # # SCons doesn't know to append a library suffix when there is a '.' in the # name. Use '_' instead. - m5lib = newEnv.Library('m5_' + label, make_objs(cc_lib_sources, newEnv)) + + m5lib = newEnv.Library('m5_' + label, + make_objs(cc_lib_sources, newEnv) + swig_objs) # Now link a stub with main() and the library. exe = 'm5.' + label # final executable -- cgit v1.2.3 From 70ec46de1736ef218ee0f554358c0558d56169ac Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Tue, 23 Sep 2008 20:38:02 -0700 Subject: sparc: Fix style, create a helper function for translation. The translate function simplifies code and removes some compiler warnings in gcc 3.4 --- src/arch/sparc/pagetable.hh | 119 ++++++++++++++++++++++++++++---------------- src/arch/sparc/tlb.cc | 100 ++++++++++++++++--------------------- src/arch/sparc/tlb.hh | 6 +-- 3 files changed, 123 insertions(+), 102 deletions(-) (limited to 'src') diff --git a/src/arch/sparc/pagetable.hh b/src/arch/sparc/pagetable.hh index bf7f34b60..d787f30e4 100644 --- a/src/arch/sparc/pagetable.hh +++ b/src/arch/sparc/pagetable.hh @@ -38,8 +38,8 @@ class Checkpoint; -namespace SparcISA -{ +namespace SparcISA { + struct VAddr { VAddr(Addr a) { panic("not implemented yet."); } @@ -54,8 +54,15 @@ class TteTag public: TteTag() : entry(0), populated(false) {} TteTag(uint64_t e) : entry(e), populated(true) {} - const TteTag &operator=(uint64_t e) { populated = true; - entry = e; return *this; } + + const TteTag & + operator=(uint64_t e) + { + populated = true; + entry = e; + return *this; + } + bool valid() const {assert(populated); return !bits(entry,62,62); } Addr va() const {assert(populated); return bits(entry,41,0); } }; @@ -76,13 +83,13 @@ class PageTableEntry uint64_t entry4u; bool populated; - public: - PageTableEntry() : entry(0), type(invalid), populated(false) {} + PageTableEntry() + : entry(0), type(invalid), populated(false) + {} PageTableEntry(uint64_t e, EntryType t = sun4u) : entry(e), type(t), populated(true) - { populate(entry, type); } @@ -113,49 +120,74 @@ class PageTableEntry } } - void clear() + void + clear() { populated = false; } static int pageSizes[6]; - uint64_t operator()() const { assert(populated); return entry4u; } - const PageTableEntry &operator=(uint64_t e) { populated = true; - entry4u = e; return *this; } - - const PageTableEntry &operator=(const PageTableEntry &e) - { populated = true; entry4u = e.entry4u; type = e.type; return *this; } - - bool valid() const { return bits(entry4u,63,63) && populated; } - uint8_t _size() const { assert(populated); - return bits(entry4u, 62,61) | - bits(entry4u, 48,48) << 2; } - Addr size() const { assert(_size() < 6); return pageSizes[_size()]; } - Addr sizeMask() const { assert(_size() < 6); return pageSizes[_size()]-1;} - bool ie() const { return bits(entry4u, 59,59); } - Addr pfn() const { assert(populated); return bits(entry4u,39,13); } - Addr paddr() const { assert(populated); return mbits(entry4u, 39,13);} - bool locked() const { assert(populated); return bits(entry4u,6,6); } - bool cv() const { assert(populated); return bits(entry4u,4,4); } - bool cp() const { assert(populated); return bits(entry4u,5,5); } - bool priv() const { assert(populated); return bits(entry4u,2,2); } - bool writable() const { assert(populated); return bits(entry4u,1,1); } - bool nofault() const { assert(populated); return bits(entry4u,60,60); } - bool sideffect() const { assert(populated); return bits(entry4u,3,3); } - Addr paddrMask() const { assert(populated); - return mbits(entry4u, 39,13) & ~sizeMask(); } + const PageTableEntry & + operator=(uint64_t e) + { + populated = true; + entry4u = e; + return *this; + } + + const PageTableEntry & + operator=(const PageTableEntry &e) + { + populated = true; + entry4u = e.entry4u; + type = e.type; + return *this; + } + + bool valid() const { return bits(entry4u,63,63) && populated; } + + uint8_t + _size() const + { + assert(populated); + return bits(entry4u, 62,61) | bits(entry4u, 48,48) << 2; + } + + Addr size() const { assert(_size() < 6); return pageSizes[_size()]; } + Addr sizeMask() const { return size() - 1; } + bool ie() const { return bits(entry4u, 59,59); } + Addr pfn() const { assert(populated); return bits(entry4u,39,13); } + Addr paddr() const { assert(populated); return mbits(entry4u, 39,13);} + bool locked() const { assert(populated); return bits(entry4u,6,6); } + bool cv() const { assert(populated); return bits(entry4u,4,4); } + bool cp() const { assert(populated); return bits(entry4u,5,5); } + bool priv() const { assert(populated); return bits(entry4u,2,2); } + bool writable() const { assert(populated); return bits(entry4u,1,1); } + bool nofault() const { assert(populated); return bits(entry4u,60,60); } + bool sideffect() const { assert(populated); return bits(entry4u,3,3); } + Addr paddrMask() const { assert(populated); return paddr() & ~sizeMask(); } + + Addr + translate(Addr vaddr) const + { + assert(populated); + Addr mask = sizeMask(); + return (paddr() & ~mask) | (vaddr & mask); + } }; -struct TlbRange { +struct TlbRange +{ Addr va; Addr size; int contextId; int partitionId; bool real; - inline bool operator<(const TlbRange &r2) const + inline bool + operator<(const TlbRange &r2) const { if (real && !r2.real) return true; @@ -178,7 +210,9 @@ struct TlbRange { return true; return false; } - inline bool operator==(const TlbRange &r2) const + + inline bool + operator==(const TlbRange &r2) const { return va == r2.va && size == r2.size && @@ -189,7 +223,11 @@ struct TlbRange { }; -struct TlbEntry { +struct TlbEntry +{ + TlbEntry() + {} + TlbEntry(Addr asn, Addr vaddr, Addr paddr) { uint64_t entry = 0; @@ -215,8 +253,7 @@ struct TlbEntry { valid = true; } - TlbEntry() - {} + TlbRange range; PageTableEntry pte; bool used; @@ -229,11 +266,9 @@ struct TlbEntry { void serialize(std::ostream &os); void unserialize(Checkpoint *cp, const std::string §ion); - }; - -}; // namespace SparcISA +} // namespace SparcISA #endif // __ARCH_SPARC_PAGE_TABLE_HH__ diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc index 22df44908..defa33c51 100644 --- a/src/arch/sparc/tlb.cc +++ b/src/arch/sparc/tlb.cc @@ -51,7 +51,7 @@ TLB::TLB(const Params *p) { // To make this work you'll have to change the hypervisor and OS if (size > 64) - fatal("SPARC T1 TLB registers don't support more than 64 TLB entries."); + fatal("SPARC T1 TLB registers don't support more than 64 TLB entries"); tlb = new TlbEntry[size]; std::memset(tlb, 0, sizeof(TlbEntry) * size); @@ -87,8 +87,6 @@ void TLB::insert(Addr va, int partition_id, int context_id, bool real, const PageTableEntry& PTE, int entry) { - - MapIter i; TlbEntry *new_entry = NULL; // TlbRange tr; @@ -103,8 +101,9 @@ TLB::insert(Addr va, int partition_id, int context_id, bool real, tr.real = real; */ - DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x pa=%#x pid=%d cid=%d r=%d entryid=%d\n", - va, PTE.paddr(), partition_id, context_id, (int)real, entry); + DPRINTF(TLB, + "TLB: Inserting Entry; va=%#x pa=%#x pid=%d cid=%d r=%d entryid=%d\n", + va, PTE.paddr(), partition_id, context_id, (int)real, entry); // Demap any entry that conflicts for (x = 0; x < size; x++) { @@ -128,7 +127,6 @@ TLB::insert(Addr va, int partition_id, int context_id, bool real, } } - /* i = lookupTable.find(tr); if (i != lookupTable.end()) { @@ -195,25 +193,22 @@ insertAllLocked: new_entry->valid = true; usedEntries++; - - i = lookupTable.insert(new_entry->range, new_entry); assert(i != lookupTable.end()); - // If all entries have there used bit set, clear it on them all, but the - // one we just inserted + // If all entries have their used bit set, clear it on them all, + // but the one we just inserted if (usedEntries == size) { clearUsedBits(); new_entry->used = true; usedEntries++; } - } TlbEntry* -TLB::lookup(Addr va, int partition_id, bool real, int context_id, bool - update_used) +TLB::lookup(Addr va, int partition_id, bool real, int context_id, + bool update_used) { MapIter i; TlbRange tr; @@ -240,8 +235,8 @@ TLB::lookup(Addr va, int partition_id, bool real, int context_id, bool DPRINTF(TLB, "TLB: Valid entry found pa: %#x size: %#x\n", t->pte.paddr(), t->pte.size()); - // Update the used bits only if this is a real access (not a fake one from - // virttophys() + // Update the used bits only if this is a real access (not a fake + // one from virttophys() if (!t->used && update_used) { t->used = true; usedEntries++; @@ -304,11 +299,10 @@ TLB::demapPage(Addr va, int partition_id, bool real, int context_id) void TLB::demapContext(int partition_id, int context_id) { - int x; DPRINTF(IPR, "TLB: Demapping Context pid=%#d cid=%d\n", partition_id, context_id); cacheValid = false; - for (x = 0; x < size; x++) { + for (int x = 0; x < size; x++) { if (tlb[x].range.contextId == context_id && tlb[x].range.partitionId == partition_id) { if (tlb[x].valid == true) { @@ -327,10 +321,9 @@ TLB::demapContext(int partition_id, int context_id) void TLB::demapAll(int partition_id) { - int x; DPRINTF(TLB, "TLB: Demapping All pid=%#d\n", partition_id); cacheValid = false; - for (x = 0; x < size; x++) { + for (int x = 0; x < size; x++) { if (tlb[x].valid && !tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) { freeList.push_front(&tlb[x]); @@ -347,11 +340,10 @@ TLB::demapAll(int partition_id) void TLB::invalidateAll() { - int x; cacheValid = false; - lookupTable.clear(); - for (x = 0; x < size; x++) { + + for (int x = 0; x < size; x++) { if (tlb[x].valid == true) freeList.push_back(&tlb[x]); tlb[x].valid = false; @@ -361,7 +353,8 @@ TLB::invalidateAll() } uint64_t -TLB::TteRead(int entry) { +TLB::TteRead(int entry) +{ if (entry >= size) panic("entry: %d\n", entry); @@ -373,7 +366,8 @@ TLB::TteRead(int entry) { } uint64_t -TLB::TagRead(int entry) { +TLB::TagRead(int entry) +{ assert(entry < size); uint64_t tag; if (!tlb[entry].valid) @@ -459,9 +453,8 @@ ITB::translate(RequestPtr &req, ThreadContext *tc) if (cacheEntry) { if (cacheEntry->range.va < vaddr + sizeof(MachInst) && cacheEntry->range.va + cacheEntry->range.size >= vaddr) { - req->setPaddr(cacheEntry->pte.paddr() & ~(cacheEntry->pte.size()-1) | - vaddr & cacheEntry->pte.size()-1 ); - return NoFault; + req->setPaddr(cacheEntry->pte.translate(vaddr)); + return NoFault; } } else { req->setPaddr(vaddr & PAddrImplMask); @@ -550,18 +543,18 @@ ITB::translate(RequestPtr &req, ThreadContext *tc) cacheState = tlbdata; cacheEntry = e; - req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) | - vaddr & e->pte.size()-1 ); + req->setPaddr(e->pte.translate(vaddr)); DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); return NoFault; } - - Fault DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) { - /* @todo this could really use some profiling and fixing to make it faster! */ + /* + * @todo this could really use some profiling and fixing to make + * it faster! + */ uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA); Addr vaddr = req->getVaddr(); Addr size = req->getSize(); @@ -599,11 +592,11 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) if (cacheAsi[0] == asi && ce_va < vaddr + size && ce_va + ce->range.size > vaddr && (!write || ce->pte.writable())) { - req->setPaddr(ce->pte.paddrMask() | vaddr & ce->pte.sizeMask()); - if (ce->pte.sideffect() || (ce->pte.paddr() >> 39) & 1) - req->setFlags(req->getFlags() | UNCACHEABLE); - DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); - return NoFault; + req->setPaddr(ce->pte.translate(vaddr)); + if (ce->pte.sideffect() || (ce->pte.paddr() >> 39) & 1) + req->setFlags(req->getFlags() | UNCACHEABLE); + DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); + return NoFault; } // if matched } // if cache entry valid if (cacheEntry[1]) { @@ -612,11 +605,11 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) if (cacheAsi[1] == asi && ce_va < vaddr + size && ce_va + ce->range.size > vaddr && (!write || ce->pte.writable())) { - req->setPaddr(ce->pte.paddrMask() | vaddr & ce->pte.sizeMask()); - if (ce->pte.sideffect() || (ce->pte.paddr() >> 39) & 1) - req->setFlags(req->getFlags() | UNCACHEABLE); - DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); - return NoFault; + req->setPaddr(ce->pte.translate(vaddr)); + if (ce->pte.sideffect() || (ce->pte.paddr() >> 39) & 1) + req->setFlags(req->getFlags() | UNCACHEABLE); + DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); + return NoFault; } // if matched } // if cache entry valid } @@ -639,7 +632,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) TlbEntry *e; DPRINTF(TLB, "TLB: priv:%d hpriv:%d red:%d lsudm:%d part_id: %#X\n", - priv, hpriv, red, lsu_dm, part_id); + priv, hpriv, red, lsu_dm, part_id); if (implicit) { if (tl > 0) { @@ -725,11 +718,10 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) return new DataAccessException; } - if ((!lsu_dm && !hpriv && !red) || AsiIsReal(asi)) { real = true; context = 0; - }; + } if (hpriv && (implicit || (!AsiIsAsIfUser(asi) && !AsiIsReal(asi)))) { req->setPaddr(vaddr & PAddrImplMask); @@ -776,7 +768,6 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) return new DataAccessException; } - if (e->pte.sideffect() || (e->pte.paddr() >> 39) & 1) req->setFlags(req->getFlags() | UNCACHEABLE); @@ -796,8 +787,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) cacheAsi[0] = (ASI)0; } cacheValid = true; - req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) | - vaddr & e->pte.size()-1); + req->setPaddr(e->pte.translate(vaddr)); DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); return NoFault; @@ -869,7 +859,7 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) DPRINTF(IPR, "Memory Mapped IPR Read: asi=%#X a=%#x\n", (uint32_t)pkt->req->getAsi(), pkt->getAddr()); - ITB * itb = tc->getITBPtr(); + ITB *itb = tc->getITBPtr(); switch (asi) { case ASI_LSU_CONTROL_REG: @@ -1055,7 +1045,7 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) DPRINTF(IPR, "Memory Mapped IPR Write: asi=%#X a=%#x d=%#X\n", (uint32_t)asi, va, data); - ITB * itb = tc->getITBPtr(); + ITB *itb = tc->getITBPtr(); switch (asi) { case ASI_LSU_CONTROL_REG: @@ -1173,7 +1163,8 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) real_insert = bits(va, 9,9); pte.populate(data, bits(va,10,10) ? PageTableEntry::sun4v : PageTableEntry::sun4u); - insert(va_insert, part_insert, ct_insert, real_insert, pte, entry_insert); + insert(va_insert, part_insert, ct_insert, real_insert, pte, + entry_insert); break; case ASI_IMMU_DEMAP: ignore = false; @@ -1272,7 +1263,7 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) tc->getSystemPtr()->threadContexts[bits(data,12,8)]->getCpuPtr()-> post_interrupt(bits(data,5,0),0); break; - default: + default: doMmuWriteError: panic("need to impl DTB::doMmuRegWrite() got asi=%#x, va=%#x d=%#x\n", (uint32_t)pkt->req->getAsi(), pkt->getAddr(), data); @@ -1310,10 +1301,6 @@ DTB::GetTsbPtr(ThreadContext *tc, Addr addr, int ctx, Addr *ptrs) itb->cx_config); } - - - - uint64_t DTB::MakeTsbPtr(TsbPageSize ps, uint64_t tag_access, uint64_t c0_tsb, uint64_t c0_config, uint64_t cX_tsb, uint64_t cX_config) @@ -1341,7 +1328,6 @@ DTB::MakeTsbPtr(TsbPageSize ps, uint64_t tag_access, uint64_t c0_tsb, return ptr; } - void TLB::serialize(std::ostream &os) { diff --git a/src/arch/sparc/tlb.hh b/src/arch/sparc/tlb.hh index 2f7d08320..504a40cbb 100644 --- a/src/arch/sparc/tlb.hh +++ b/src/arch/sparc/tlb.hh @@ -109,9 +109,9 @@ class TLB : public BaseTLB * @param paritition_id partition this entry is for * @param real is this a real->phys or virt->phys translation * @param context_id if this is virt->phys what context - * @param update_used should ew update the used bits in the entries on not - * useful if we are trying to do a va->pa without mucking with any state for - * a debug read for example. + * @param update_used should ew update the used bits in the + * entries on not useful if we are trying to do a va->pa without + * mucking with any state for a debug read for example. * @return A pointer to a tlb entry */ TlbEntry *lookup(Addr va, int partition_id, bool real, int context_id = 0, -- cgit v1.2.3 From 712a8ee70090abc8c8c0fdb4a907e3ec419ae56e Mon Sep 17 00:00:00 2001 From: Kevin Lim Date: Fri, 26 Sep 2008 07:44:06 -0700 Subject: O3CPU: Add a hack to ensure that nextPC is set correctly after syscalls. Just check CPU's nextPC before and after syscall and if it changes, update this instruction's nextPC because the syscall must have changed the nextPC. --- src/cpu/o3/alpha/dyn_inst_impl.hh | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/cpu/o3/alpha/dyn_inst_impl.hh b/src/cpu/o3/alpha/dyn_inst_impl.hh index 6dfe0ccdd..610a313cf 100644 --- a/src/cpu/o3/alpha/dyn_inst_impl.hh +++ b/src/cpu/o3/alpha/dyn_inst_impl.hh @@ -161,7 +161,15 @@ template void AlphaDynInst::syscall(int64_t callnum) { + // HACK: check CPU's nextPC before and after syscall. If it + // changes, update this instruction's nextPC because the syscall + // must have changed the nextPC. + Addr cpu_next_pc = this->cpu->readNextPC(this->threadNumber); this->cpu->syscall(callnum, this->threadNumber); + Addr new_next_pc = this->cpu->readNextPC(this->threadNumber); + if (cpu_next_pc != new_next_pc) { + this->setNextPC(new_next_pc); + } } #endif -- cgit v1.2.3 From b7849032072ed7e93979d625cade3b384aa19948 Mon Sep 17 00:00:00 2001 From: Kevin Lim Date: Fri, 26 Sep 2008 07:44:07 -0700 Subject: O3CPU: Fix thread writeback logic. Fix the logic in the LSQ that determines if there are any stores to write back. In the commit stage, check for thread specific writebacks instead of just any writeback. --- src/cpu/o3/commit_impl.hh | 8 ++++---- src/cpu/o3/iew.hh | 3 +++ src/cpu/o3/lsq_impl.hh | 15 ++++++--------- 3 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index 86b4da8ce..b16955691 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -814,7 +814,7 @@ DefaultCommit::commit() // @todo: Make this handle multi-cycle communication between // commit and IEW. if (checkEmptyROB[tid] && rob->isEmpty(tid) && - !iewStage->hasStoresToWB() && !committedStores[tid]) { + !iewStage->hasStoresToWB(tid) && !committedStores[tid]) { checkEmptyROB[tid] = false; toIEW->commitInfo[tid].usedROB = true; toIEW->commitInfo[tid].emptyROB = true; @@ -968,7 +968,7 @@ DefaultCommit::commitHead(DynInstPtr &head_inst, unsigned inst_num) "instruction [sn:%lli] at the head of the ROB, PC %#x.\n", head_inst->seqNum, head_inst->readPC()); - if (inst_num > 0 || iewStage->hasStoresToWB()) { + if (inst_num > 0 || iewStage->hasStoresToWB(tid)) { DPRINTF(Commit, "Waiting for all stores to writeback.\n"); return false; } @@ -983,7 +983,7 @@ DefaultCommit::commitHead(DynInstPtr &head_inst, unsigned inst_num) return false; } else if (head_inst->isLoad()) { - if (inst_num > 0 || iewStage->hasStoresToWB()) { + if (inst_num > 0 || iewStage->hasStoresToWB(tid)) { DPRINTF(Commit, "Waiting for all stores to writeback.\n"); return false; } @@ -1038,7 +1038,7 @@ DefaultCommit::commitHead(DynInstPtr &head_inst, unsigned inst_num) DPRINTF(Commit, "Inst [sn:%lli] PC %#x has a fault\n", head_inst->seqNum, head_inst->readPC()); - if (iewStage->hasStoresToWB() || inst_num > 0) { + if (iewStage->hasStoresToWB(tid) || inst_num > 0) { DPRINTF(Commit, "Stores outstanding, fault must wait.\n"); return false; } diff --git a/src/cpu/o3/iew.hh b/src/cpu/o3/iew.hh index 3caf847ed..bc60f401b 100644 --- a/src/cpu/o3/iew.hh +++ b/src/cpu/o3/iew.hh @@ -208,6 +208,9 @@ class DefaultIEW /** Returns if the LSQ has any stores to writeback. */ bool hasStoresToWB() { return ldstQueue.hasStoresToWB(); } + /** Returns if the LSQ has any stores to writeback. */ + bool hasStoresToWB(unsigned tid) { return ldstQueue.hasStoresToWB(tid); } + void incrWb(InstSeqNum &sn) { if (++wbOutstanding == wbMax) diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh index f8e77b64e..5aea020a9 100644 --- a/src/cpu/o3/lsq_impl.hh +++ b/src/cpu/o3/lsq_impl.hh @@ -584,17 +584,14 @@ LSQ::hasStoresToWB() std::list::iterator threads = activeThreads->begin(); std::list::iterator end = activeThreads->end(); - if (threads == end) - return false; - while (threads != end) { unsigned tid = *threads++; - if (!hasStoresToWB(tid)) - return false; + if (hasStoresToWB(tid)) + return true; } - return true; + return false; } template @@ -607,11 +604,11 @@ LSQ::willWB() while (threads != end) { unsigned tid = *threads++; - if (!willWB(tid)) - return false; + if (willWB(tid)) + return true; } - return true; + return false; } template -- cgit v1.2.3 From 0309c877f32d415122cfb59960ec41dba54ba3e3 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 26 Sep 2008 08:18:53 -0700 Subject: style: These files didn't even come close to following the M5 style guide. --- src/arch/mips/dsp.cc | 989 +++++++++++++++++++++++++-------------------------- src/arch/mips/dsp.hh | 285 ++++++++------- 2 files changed, 635 insertions(+), 639 deletions(-) (limited to 'src') diff --git a/src/arch/mips/dsp.cc b/src/arch/mips/dsp.cc index 8e2db3f0b..183016ee7 100755 --- a/src/arch/mips/dsp.cc +++ b/src/arch/mips/dsp.cc @@ -40,92 +40,84 @@ using namespace MipsISA; using namespace std; int32_t -MipsISA::bitrev( int32_t value ) +MipsISA::bitrev(int32_t value) { int32_t result = 0; - int i, shift; + int shift; - for( i=0; i<16; i++ ) - { - shift = 2*i - 15; + for (int i = 0; i < 16; i++) { + shift = 2 * i - 15; - if( shift < 0 ) - result |= (value & 1L<> shift; + result |= (value & 1 << i) >> shift; } return result; } uint64_t -MipsISA::dspSaturate( uint64_t value, int32_t fmt, int32_t sign, uint32_t *overflow ) +MipsISA::dspSaturate(uint64_t value, int32_t fmt, int32_t sign, + uint32_t *overflow) { - int64_t svalue; + int64_t svalue = (int64_t)value; - svalue = (int64_t)value; - - switch( sign ) - { + switch(sign) { case SIGNED: - if( svalue > (int64_t)FIXED_SMAX[fmt] ) - { + if (svalue > (int64_t)FIXED_SMAX[fmt]) { *overflow = 1; svalue = (int64_t)FIXED_SMAX[fmt]; - } - else if( svalue < (int64_t)FIXED_SMIN[fmt] ) - { + } else if (svalue < (int64_t)FIXED_SMIN[fmt]) { *overflow = 1; svalue = (int64_t)FIXED_SMIN[fmt]; } break; case UNSIGNED: - if( svalue > (int64_t)FIXED_UMAX[fmt] ) - { + if (svalue > (int64_t)FIXED_UMAX[fmt]) { *overflow = 1; svalue = FIXED_UMAX[fmt]; - } - else if( svalue < (int64_t)FIXED_UMIN[fmt] ) - { + } else if (svalue < (int64_t)FIXED_UMIN[fmt]) { *overflow = 1; svalue = FIXED_UMIN[fmt]; } break; } - return( (uint64_t)svalue ); + return (uint64_t)svalue; } uint64_t -MipsISA::checkOverflow( uint64_t value, int32_t fmt, int32_t sign, uint32_t *overflow ) +MipsISA::checkOverflow(uint64_t value, int32_t fmt, int32_t sign, + uint32_t *overflow) { - int64_t svalue; - - svalue = (int64_t)value; + int64_t svalue = (int64_t)value; - switch( sign ) + switch(sign) { case SIGNED: - if( svalue > (int64_t)FIXED_SMAX[fmt] || svalue < (int64_t)FIXED_SMIN[fmt] ) + if (svalue > (int64_t)FIXED_SMAX[fmt] || + svalue < (int64_t)FIXED_SMIN[fmt]) *overflow = 1; break; case UNSIGNED: - if( svalue > (int64_t)FIXED_UMAX[fmt] || svalue < (int64_t)FIXED_UMIN[fmt] ) + if (svalue > (int64_t)FIXED_UMAX[fmt] || + svalue < (int64_t)FIXED_UMIN[fmt]) *overflow = 1; break; } - return( (uint64_t)svalue ); + return (uint64_t)svalue; } uint64_t -MipsISA::signExtend( uint64_t value, int32_t fmt ) +MipsISA::signExtend(uint64_t value, int32_t fmt) { int32_t signpos = SIMD_NBITS[fmt]; - uint64_t sign = uint64_t(1)<<(signpos-1); + uint64_t sign = uint64_t(1) << (signpos - 1); uint64_t ones = ~(0ULL); - if( value & sign ) + if (value & sign) value |= (ones << signpos); // extend with ones else value &= (ones >> (64 - signpos)); // extend with zeros @@ -134,231 +126,230 @@ MipsISA::signExtend( uint64_t value, int32_t fmt ) } uint64_t -MipsISA::addHalfLsb( uint64_t value, int32_t lsbpos ) +MipsISA::addHalfLsb(uint64_t value, int32_t lsbpos) { - return( value += ULL(1) << (lsbpos-1) ); + return value += ULL(1) << (lsbpos - 1); } int32_t -MipsISA::dspAbs( int32_t a, int32_t fmt, uint32_t *dspctl ) +MipsISA::dspAbs(int32_t a, int32_t fmt, uint32_t *dspctl) { - int i = 0; int nvals = SIMD_NVALS[fmt]; int32_t result; int64_t svalue; uint32_t ouflag = 0; uint64_t a_values[SIMD_MAX_VALS]; - simdUnpack( a, a_values, fmt, SIGNED ); + simdUnpack(a, a_values, fmt, SIGNED); - for( i=0; i> 1; + for (int i = 0; i < nvals; i++) { + if (round) + a_values[i] = addHalfLsb(a_values[i] + b_values[i], 1) >> 1; else - a_values[i] = ( a_values[i] + b_values[i] ) >> 1; + a_values[i] = (a_values[i] + b_values[i]) >> 1; } - simdPack( a_values, &result, fmt ); + simdPack(a_values, &result, fmt); - return( result ); + return result; } int32_t -MipsISA::dspSub( int32_t a, int32_t b, int32_t fmt, int32_t saturate, int32_t sign, uint32_t *dspctl ) +MipsISA::dspSub(int32_t a, int32_t b, int32_t fmt, int32_t saturate, + int32_t sign, uint32_t *dspctl) { - int i = 0; int nvals = SIMD_NVALS[fmt]; int32_t result; uint32_t ouflag = 0; uint64_t a_values[SIMD_MAX_VALS]; uint64_t b_values[SIMD_MAX_VALS]; - simdUnpack( a, a_values, fmt, sign ); - simdUnpack( b, b_values, fmt, sign ); + simdUnpack(a, a_values, fmt, sign); + simdUnpack(b, b_values, fmt, sign); - for( i=0; i> 1; + if (round) + a_values[i] = addHalfLsb(a_values[i] - b_values[i], 1) >> 1; else - a_values[i] = ( a_values[i] - b_values[i] ) >> 1; + a_values[i] = (a_values[i] - b_values[i]) >> 1; } - simdPack( a_values, &result, fmt ); + simdPack(a_values, &result, fmt); - return( result ); + return result; } int32_t -MipsISA::dspShll( int32_t a, uint32_t sa, int32_t fmt, int32_t saturate, int32_t sign, uint32_t *dspctl ) +MipsISA::dspShll(int32_t a, uint32_t sa, int32_t fmt, int32_t saturate, + int32_t sign, uint32_t *dspctl) { - int i = 0; int nvals = SIMD_NVALS[fmt]; int32_t result; uint32_t ouflag = 0; uint64_t a_values[SIMD_MAX_VALS]; - sa = bits( sa, SIMD_LOG2N[fmt]-1, 0 ); - simdUnpack( a, a_values, fmt, sign ); + sa = bits(sa, SIMD_LOG2N[fmt] - 1, 0); + simdUnpack(a, a_values, fmt, sign); - for( i=0; i> sa; - simdPack( a_values, &result, fmt ); + simdPack(a_values, &result, fmt); - return( result ); + return result; } int32_t -MipsISA::dspShra( int32_t a, uint32_t sa, int32_t fmt, int32_t round, int32_t sign, uint32_t *dspctl ) +MipsISA::dspShra(int32_t a, uint32_t sa, int32_t fmt, int32_t round, + int32_t sign, uint32_t *dspctl) { - int i = 0; int nvals = SIMD_NVALS[fmt]; int32_t result; uint64_t a_values[SIMD_MAX_VALS]; - sa = bits( sa, SIMD_LOG2N[fmt]-1, 0 ); + sa = bits(sa, SIMD_LOG2N[fmt] - 1, 0); - simdUnpack( a, a_values, fmt, SIGNED ); + simdUnpack(a, a_values, fmt, SIGNED); - for( i=0; i> sa; + for (int i = 0; i < nvals; i++) { + if (round) + a_values[i] = addHalfLsb(a_values[i], sa) >> sa; else a_values[i] = a_values[i] >> sa; } - simdPack( a_values, &result, fmt ); + simdPack(a_values, &result, fmt); - return( result ); + return result; } int32_t -MipsISA::dspMulq( int32_t a, int32_t b, int32_t fmt, int32_t saturate, int32_t round, uint32_t *dspctl ) +MipsISA::dspMulq(int32_t a, int32_t b, int32_t fmt, int32_t saturate, + int32_t round, uint32_t *dspctl) { - int i = 0; int nvals = SIMD_NVALS[fmt]; int sa = SIMD_NBITS[fmt]; int32_t result; @@ -367,102 +358,104 @@ MipsISA::dspMulq( int32_t a, int32_t b, int32_t fmt, int32_t saturate, int32_t r uint64_t b_values[SIMD_MAX_VALS]; int64_t temp; - simdUnpack( a, a_values, fmt, SIGNED ); - simdUnpack( b, b_values, fmt, SIGNED ); + simdUnpack(a, a_values, fmt, SIGNED); + simdUnpack(b, b_values, fmt, SIGNED); - for( i=0; i> sa; + for (int i = 0; i < nvals; i++) { + if (round) + temp = + (int64_t)addHalfLsb(a_values[i] * b_values[i] << 1, sa) >> sa; else temp = (int64_t)(a_values[i] * b_values[i]) >> (sa - 1); - if( a_values[i] == FIXED_SMIN[fmt] && - b_values[i] == FIXED_SMIN[fmt] ) - { + if (a_values[i] == FIXED_SMIN[fmt] && b_values[i] == FIXED_SMIN[fmt]) { ouflag = 1; - if( saturate ) + if (saturate) temp = FIXED_SMAX[fmt]; } a_values[i] = temp; } - simdPack( a_values, &result, fmt ); + simdPack(a_values, &result, fmt); - if( ouflag ) - writeDSPControl( dspctl, (ouflag<<5)<-1; i-- ) - { + for (int i = nvals - 1; i > -1; i--) { temp[i] = a_values[i] * b_values[i] << 1; - if( a_values[i] == FIXED_SMIN[fmt] && - b_values[i] == FIXED_SMIN[fmt] ) - { - temp[i] = FIXED_SMAX[fmt-1]; + if (a_values[i] == FIXED_SMIN[fmt] && b_values[i] == FIXED_SMIN[fmt]) { + temp[i] = FIXED_SMAX[fmt - 1]; ouflag = 1; } } dspac += temp[1] - temp[0]; - if( ouflag ) - *dspctl = insertBits( *dspctl, 16+ac, 16+ac, 1 ); + if (ouflag) + *dspctl = insertBits(*dspctl, 16 + ac, 16 + ac, 1); return dspac; } void -MipsISA::dspCmp( int32_t a, int32_t b, int32_t fmt, int32_t sign, int32_t op, uint32_t *dspctl ) +MipsISA::dspCmp(int32_t a, int32_t b, int32_t fmt, int32_t sign, int32_t op, + uint32_t *dspctl) { - int i = 0; int nvals = SIMD_NVALS[fmt]; int ccond = 0; uint64_t a_values[SIMD_MAX_VALS]; uint64_t b_values[SIMD_MAX_VALS]; - simdUnpack( a, a_values, fmt, sign ); - simdUnpack( b, b_values, fmt, sign ); + simdUnpack(a, a_values, fmt, sign); + simdUnpack(b, b_values, fmt, sign); - for( i=0; i>1)] << sa; break; - case MODE_R: out_values[i] = in_values[i] << sa; break; - case MODE_LA: out_values[i] = in_values[(i<<1)+1] << sa; break; - case MODE_RA: out_values[i] = in_values[i<<1] << sa; break; + for (int i = 0; i> 1)] << sa; + break; + case MODE_R: + out_values[i] = in_values[i] << sa; + break; + case MODE_LA: + out_values[i] = in_values[(i << 1) + 1] << sa; + break; + case MODE_RA: + out_values[i] = in_values[i << 1] << sa; + break; } } - simdPack( out_values, &result, outfmt ); + simdPack(out_values, &result, outfmt); - return( result ); + return result; } int32_t -MipsISA::dspPrecrqu( int32_t a, int32_t b, uint32_t *dspctl ) +MipsISA::dspPrecrqu(int32_t a, int32_t b, uint32_t *dspctl) { - int i = 0; uint64_t a_values[SIMD_MAX_VALS]; uint64_t b_values[SIMD_MAX_VALS]; uint64_t r_values[SIMD_MAX_VALS]; uint32_t ouflag = 0; int32_t result = 0; - simdUnpack( a, a_values, SIMD_FMT_PH, SIGNED ); - simdUnpack( b, b_values, SIMD_FMT_PH, SIGNED ); + simdUnpack(a, a_values, SIMD_FMT_PH, SIGNED); + simdUnpack(b, b_values, SIMD_FMT_PH, SIGNED); - for( i=0; i<2; i++ ) - { - r_values[i] = dspSaturate( (int64_t)b_values[i] >> SIMD_NBITS[SIMD_FMT_QB] - 1, - SIMD_FMT_QB, UNSIGNED, &ouflag ); - r_values[i+2] = dspSaturate( (int64_t)a_values[i] >> SIMD_NBITS[SIMD_FMT_QB] - 1, - SIMD_FMT_QB, UNSIGNED, &ouflag ); + for (int i = 0; i<2; i++) { + r_values[i] = + dspSaturate((int64_t)b_values[i] >> SIMD_NBITS[SIMD_FMT_QB] - 1, + SIMD_FMT_QB, UNSIGNED, &ouflag); + r_values[i + 2] = + dspSaturate((int64_t)a_values[i] >> SIMD_NBITS[SIMD_FMT_QB] - 1, + SIMD_FMT_QB, UNSIGNED, &ouflag); } - simdPack( r_values, &result, SIMD_FMT_QB ); + simdPack(r_values, &result, SIMD_FMT_QB); - if( ouflag ) - *dspctl = insertBits( *dspctl, 22, 22, 1 ); + if (ouflag) + *dspctl = insertBits(*dspctl, 22, 22, 1); return result; } int32_t -MipsISA::dspPrecrq( int32_t a, int32_t b, int32_t fmt, uint32_t *dspctl ) +MipsISA::dspPrecrq(int32_t a, int32_t b, int32_t fmt, uint32_t *dspctl) { uint64_t a_values[SIMD_MAX_VALS]; uint64_t b_values[SIMD_MAX_VALS]; @@ -965,245 +947,226 @@ MipsISA::dspPrecrq( int32_t a, int32_t b, int32_t fmt, uint32_t *dspctl ) uint32_t ouflag = 0; int32_t result; - simdUnpack( a, a_values, fmt, SIGNED ); - simdUnpack( b, b_values, fmt, SIGNED ); + simdUnpack(a, a_values, fmt, SIGNED); + simdUnpack(b, b_values, fmt, SIGNED); - r_values[1] = dspSaturate( (int64_t)addHalfLsb( a_values[0], 16 ) >> 16, - fmt+1, SIGNED, &ouflag ); - r_values[0] = dspSaturate( (int64_t)addHalfLsb( b_values[0], 16 ) >> 16, - fmt+1, SIGNED, &ouflag ); + r_values[1] = dspSaturate((int64_t)addHalfLsb(a_values[0], 16) >> 16, + fmt + 1, SIGNED, &ouflag); + r_values[0] = dspSaturate((int64_t)addHalfLsb(b_values[0], 16) >> 16, + fmt + 1, SIGNED, &ouflag); - simdPack( r_values, &result, fmt+1 ); + simdPack(r_values, &result, fmt + 1); - if( ouflag ) - *dspctl = insertBits( *dspctl, 22, 22, 1 ); + if (ouflag) + *dspctl = insertBits(*dspctl, 22, 22, 1); return result; } int32_t -MipsISA::dspPrecrSra( int32_t a, int32_t b, int32_t sa, int32_t fmt, int32_t round ) +MipsISA::dspPrecrSra(int32_t a, int32_t b, int32_t sa, int32_t fmt, + int32_t round) { - int i = 0; int nvals = SIMD_NVALS[fmt]; uint64_t a_values[SIMD_MAX_VALS]; uint64_t b_values[SIMD_MAX_VALS]; uint64_t c_values[SIMD_MAX_VALS]; int32_t result = 0; - simdUnpack( a, a_values, fmt, SIGNED ); - simdUnpack( b, b_values, fmt, SIGNED ); + simdUnpack(a, a_values, fmt, SIGNED); + simdUnpack(b, b_values, fmt, SIGNED); - for( i=0; i> sa; - c_values[i+1] = addHalfLsb( a_values[i], sa ) >> sa; - } - else - { + for (int i = 0; i < nvals; i++) { + if (round) { + c_values[i] = addHalfLsb(b_values[i], sa) >> sa; + c_values[i + 1] = addHalfLsb(a_values[i], sa) >> sa; + } else { c_values[i] = b_values[i] >> sa; - c_values[i+1] = a_values[i] >> sa; + c_values[i + 1] = a_values[i] >> sa; } } - simdPack( c_values, &result, fmt+1 ); + simdPack(c_values, &result, fmt + 1); return result; } int32_t -MipsISA::dspPick( int32_t a, int32_t b, int32_t fmt, uint32_t *dspctl ) +MipsISA::dspPick(int32_t a, int32_t b, int32_t fmt, uint32_t *dspctl) { - int i = 0; int nvals = SIMD_NVALS[fmt]; int32_t result; uint64_t a_values[SIMD_MAX_VALS]; uint64_t b_values[SIMD_MAX_VALS]; uint64_t c_values[SIMD_MAX_VALS]; - simdUnpack( a, a_values, fmt, UNSIGNED ); - simdUnpack( b, b_values, fmt, UNSIGNED ); + simdUnpack(a, a_values, fmt, UNSIGNED); + simdUnpack(b, b_values, fmt, UNSIGNED); - for( i=0; i 0 ) - { - if( round ) - { - temp = (int64_t)addHalfLsb( dspac, sa ); + if (sa > 0) { + if (round) { + temp = (int64_t)addHalfLsb(dspac, sa); - if( dspac > 0 && temp < 0 ) - { + if (dspac > 0 && temp < 0) { ouflag = 1; - if( saturate ) + if (saturate) temp = FIXED_SMAX[SIMD_FMT_L]; } temp = temp >> sa; - } - else + } else { temp = dspac >> sa; - } - else + } + } else { temp = dspac; + } - dspac = checkOverflow( dspac, fmt, SIGNED, &ouflag ); + dspac = checkOverflow(dspac, fmt, SIGNED, &ouflag); - if( ouflag ) - { - *dspctl = insertBits( *dspctl, 23, 23, ouflag ); + if (ouflag) { + *dspctl = insertBits(*dspctl, 23, 23, ouflag); - if( saturate ) - result = (int32_t)dspSaturate( temp, fmt, SIGNED, &ouflag ); + if (saturate) + result = (int32_t)dspSaturate(temp, fmt, SIGNED, &ouflag); else result = (int32_t)temp; - } - else + } else { result = (int32_t)temp; + } - return( result ); + return result; } int32_t -MipsISA::dspExtp( int64_t dspac, int32_t size, uint32_t *dspctl ) +MipsISA::dspExtp(int64_t dspac, int32_t size, uint32_t *dspctl) { int32_t pos = 0; int32_t result = 0; - pos = bits( *dspctl, 5, 0 ); - size = bits( size, 4, 0 ); + pos = bits(*dspctl, 5, 0); + size = bits(size, 4, 0); - if( pos - (size+1) >= -1 ) - { - result = bits( dspac, pos, pos-size ); - *dspctl = insertBits( *dspctl, 14, 14, 0 ); - } - else - { + if (pos - (size + 1) >= -1) { + result = bits(dspac, pos, pos - size); + *dspctl = insertBits(*dspctl, 14, 14, 0); + } else { result = 0; - *dspctl = insertBits( *dspctl, 14, 14, 1 ); + *dspctl = insertBits(*dspctl, 14, 14, 1); } - return( result ); + return result; } int32_t -MipsISA::dspExtpd( int64_t dspac, int32_t size, uint32_t *dspctl ) +MipsISA::dspExtpd(int64_t dspac, int32_t size, uint32_t *dspctl) { int32_t pos = 0; int32_t result = 0; - pos = bits( *dspctl, 5, 0 ); - size = bits( size, 4, 0 ); - - if( pos - (size+1) >= -1 ) - { - result = bits( dspac, pos, pos-size ); - *dspctl = insertBits( *dspctl, 14, 14, 0 ); - if( pos - (size+1) >= 0 ) - *dspctl = insertBits( *dspctl, 5, 0, pos - (size+1) ); - else if( (pos - (size+1)) == -1 ) - *dspctl = insertBits( *dspctl, 5, 0, 63 ); - } - else - { + pos = bits(*dspctl, 5, 0); + size = bits(size, 4, 0); + + if (pos - (size + 1) >= -1) { + result = bits(dspac, pos, pos - size); + *dspctl = insertBits(*dspctl, 14, 14, 0); + if (pos - (size + 1) >= 0) + *dspctl = insertBits(*dspctl, 5, 0, pos - (size + 1)); + else if ((pos - (size + 1)) == -1) + *dspctl = insertBits(*dspctl, 5, 0, 63); + } else { result = 0; - *dspctl = insertBits( *dspctl, 14, 14, 1 ); + *dspctl = insertBits(*dspctl, 14, 14, 1); } - return( result ); + return result; } void -MipsISA::simdPack( uint64_t *values_ptr, int32_t *reg, int32_t fmt ) +MipsISA::simdPack(uint64_t *values_ptr, int32_t *reg, int32_t fmt) { - int i = 0; int nvals = SIMD_NVALS[fmt]; int nbits = SIMD_NBITS[fmt]; *reg = 0; - for( i=0; i Date: Fri, 26 Sep 2008 08:18:54 -0700 Subject: scons: disable several gcc warnings for swig autogenerated wrapper code. --- src/SConscript | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/SConscript b/src/SConscript index 9734a3618..14988bbbe 100644 --- a/src/SConscript +++ b/src/SConscript @@ -947,7 +947,10 @@ def makeEnv(label, objsfx, strip = False, **kwargs): newEnv.Append(**kwargs) swig_env = newEnv.Copy() - swig_env.Append(CCFLAGS='-Wno-uninitialized') + if env['GCC']: + swig_env.Append(CCFLAGS='-Wno-uninitialized') + swig_env.Append(CCFLAGS='-Wno-sign-compare') + swig_env.Append(CCFLAGS='-Wno-parentheses') swig_objs = [ swig_env.Object(s) for s in cc_swig_sources ] # First make a library of everything but main() so other programs can -- cgit v1.2.3 From 6798aa14ed68b2c7a7ad7f09e6223d5d28f0e56e Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 26 Sep 2008 08:18:55 -0700 Subject: style: bring this file into M5 style, use the new pte translate function. --- src/arch/sparc/vtophys.cc | 162 ++++++++++++++++++++++++---------------------- 1 file changed, 85 insertions(+), 77 deletions(-) (limited to 'src') diff --git a/src/arch/sparc/vtophys.cc b/src/arch/sparc/vtophys.cc index 9a93950d2..f23fb8304 100644 --- a/src/arch/sparc/vtophys.cc +++ b/src/arch/sparc/vtophys.cc @@ -40,85 +40,93 @@ using namespace std; -namespace SparcISA +namespace SparcISA { + +Addr +vtophys(Addr vaddr) { - Addr vtophys(Addr vaddr) - { - // In SPARC it's almost always impossible to turn a VA->PA w/o a context - // The only times we can kinda do it are if we have a SegKPM mapping - // and can find the real address in the tlb or we have a physical - // adddress already (beacuse we are looking at the hypervisor) - // Either case is rare, so we'll just panic. - - panic("vtophys() without context on SPARC largly worthless\n"); - M5_DUMMY_RETURN - } + // In SPARC it's almost always impossible to turn a VA->PA w/o a + // context The only times we can kinda do it are if we have a + // SegKPM mapping and can find the real address in the tlb or we + // have a physical adddress already (beacuse we are looking at the + // hypervisor) Either case is rare, so we'll just panic. + + panic("vtophys() without context on SPARC largly worthless\n"); + M5_DUMMY_RETURN; +} + +Addr +vtophys(ThreadContext *tc, Addr addr) +{ + // Here we have many options and are really implementing something like + // a fill handler to find the address since there isn't a multilevel + // table for us to walk around. + // + // 1. We are currently hyperpriv, return the address unmodified + // 2. The mmu is off return(ra->pa) + // 3. We are currently priv, use ctx0* tsbs to find the page + // 4. We are not priv, use ctxN0* tsbs to find the page + // For all accesses we check the tlbs first since it's possible that + // long standing pages (e.g. locked kernel mappings) won't be in the tsb + uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA); + + bool hpriv = bits(tlbdata,0,0); + //bool priv = bits(tlbdata,2,2); + bool addr_mask = bits(tlbdata,3,3); + bool data_real = !bits(tlbdata,5,5); + bool inst_real = !bits(tlbdata,4,4); + bool ctx_zero = bits(tlbdata,18,16) > 0; + int part_id = bits(tlbdata,15,8); + int pri_context = bits(tlbdata,47,32); + //int sec_context = bits(tlbdata,63,48); - Addr vtophys(ThreadContext *tc, Addr addr) - { - // Here we have many options and are really implementing something like - // a fill handler to find the address since there isn't a multilevel - // table for us to walk around. - // - // 1. We are currently hyperpriv, return the address unmodified - // 2. The mmu is off return(ra->pa) - // 3. We are currently priv, use ctx0* tsbs to find the page - // 4. We are not priv, use ctxN0* tsbs to find the page - // For all accesses we check the tlbs first since it's possible that - // long standing pages (e.g. locked kernel mappings) won't be in the tsb - uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA); - - bool hpriv = bits(tlbdata,0,0); - //bool priv = bits(tlbdata,2,2); - bool addr_mask = bits(tlbdata,3,3); - bool data_real = !bits(tlbdata,5,5); - bool inst_real = !bits(tlbdata,4,4); - bool ctx_zero = bits(tlbdata,18,16) > 0; - int part_id = bits(tlbdata,15,8); - int pri_context = bits(tlbdata,47,32); - //int sec_context = bits(tlbdata,63,48); - - FunctionalPort *mem = tc->getPhysPort(); - ITB* itb = tc->getITBPtr(); - DTB* dtb = tc->getDTBPtr(); - TlbEntry* tbe; - PageTableEntry pte; - Addr tsbs[4]; - Addr va_tag; - TteTag ttetag; - - if (hpriv) - return addr; - - if (addr_mask) - addr = addr & VAddrAMask; - - tbe = dtb->lookup(addr, part_id, data_real, ctx_zero ? 0 : pri_context , false); - if (tbe) goto foundtbe; - - tbe = itb->lookup(addr, part_id, inst_real, ctx_zero ? 0 : pri_context, false); - if (tbe) goto foundtbe; - - // We didn't find it in the tlbs, so lets look at the TSBs - dtb->GetTsbPtr(tc, addr, ctx_zero ? 0 : pri_context, tsbs); - va_tag = bits(addr, 63, 22); - for (int x = 0; x < 4; x++) { - ttetag = betoh(mem->read(tsbs[x])); - if (ttetag.valid() && ttetag.va() == va_tag) { - pte.populate(betoh(mem->read(tsbs[x]) + sizeof(uint64_t)), - PageTableEntry::sun4v); // I think it's sun4v at least! - DPRINTF(VtoPhys, "Virtual(%#x)->Physical(%#x) found in TTE\n", addr, - pte.paddrMask() | addr & pte.sizeMask()); - goto foundpte; - } + FunctionalPort *mem = tc->getPhysPort(); + ITB* itb = tc->getITBPtr(); + DTB* dtb = tc->getDTBPtr(); + TlbEntry* tbe; + PageTableEntry pte; + Addr tsbs[4]; + Addr va_tag; + TteTag ttetag; + + if (hpriv) + return addr; + + if (addr_mask) + addr = addr & VAddrAMask; + + tbe = dtb->lookup(addr, part_id, data_real, ctx_zero ? 0 : pri_context , + false); + if (tbe) + goto foundtbe; + + tbe = itb->lookup(addr, part_id, inst_real, ctx_zero ? 0 : pri_context, + false); + if (tbe) + goto foundtbe; + + // We didn't find it in the tlbs, so lets look at the TSBs + dtb->GetTsbPtr(tc, addr, ctx_zero ? 0 : pri_context, tsbs); + va_tag = bits(addr, 63, 22); + for (int x = 0; x < 4; x++) { + ttetag = betoh(mem->read(tsbs[x])); + if (ttetag.valid() && ttetag.va() == va_tag) { + uint64_t entry = mem->read(tsbs[x]) + sizeof(uint64_t); + // I think it's sun4v at least! + pte.populate(betoh(entry), PageTableEntry::sun4v); + DPRINTF(VtoPhys, "Virtual(%#x)->Physical(%#x) found in TTE\n", + addr, pte.translate(addr)); + goto foundpte; } - panic("couldn't translate %#x\n", addr); - -foundtbe: - pte = tbe->pte; - DPRINTF(VtoPhys, "Virtual(%#x)->Physical(%#x) found in TLB\n", addr, - pte.paddrMask() | addr & pte.sizeMask()); -foundpte: - return pte.paddrMask() | addr & pte.sizeMask(); } + panic("couldn't translate %#x\n", addr); + + foundtbe: + pte = tbe->pte; + DPRINTF(VtoPhys, "Virtual(%#x)->Physical(%#x) found in TLB\n", addr, + pte.translate(addr)); + foundpte: + return pte.translate(addr); } + +} /* namespace SparcISA */ -- cgit v1.2.3 From abca171e244b27d1c44a9bcdedbe231bdc342cbb Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 26 Sep 2008 08:18:56 -0700 Subject: Use logical operator instead of bitwise operator for correctness. --- src/arch/mips/mt.hh | 2 +- src/kern/tru64/tru64.hh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/arch/mips/mt.hh b/src/arch/mips/mt.hh index 6765c27a9..20658df28 100755 --- a/src/arch/mips/mt.hh +++ b/src/arch/mips/mt.hh @@ -220,7 +220,7 @@ yieldThread(TC *tc, Fault &fault, int src_reg, uint32_t yield_mask) warn("%i: Deactivating Hardware Thread Context #%i", curTick, tc->getThreadNum()); } } else if (src_reg > 0) { - if (src_reg & !yield_mask != 0) { + if (src_reg && !yield_mask != 0) { unsigned vpe_control = tc->readMiscReg(VPEControl); tc->setMiscReg(VPEControl, insertBits(vpe_control, VPEC_EXCPT_HI, VPEC_EXCPT_LO, 2)); fault = new ThreadFault(); diff --git a/src/kern/tru64/tru64.hh b/src/kern/tru64/tru64.hh index d0c359a1f..dfdb8524d 100644 --- a/src/kern/tru64/tru64.hh +++ b/src/kern/tru64/tru64.hh @@ -723,7 +723,7 @@ class Tru64 : public OperatingSystem abort(); } - if (thread_index < 0 | thread_index > process->numCpus()) { + if (thread_index < 0 || thread_index > process->numCpus()) { cerr << "nxm_thread_create: bad thread index " << thread_index << endl; abort(); -- cgit v1.2.3 From 9838be252114cf044735ca07007d23ee03d8da2c Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 26 Sep 2008 08:18:57 -0700 Subject: When nesting if statements, use braces to avoid ambiguous else clauses. --- src/arch/sparc/tlb_map.hh | 3 ++- src/mem/bridge.cc | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/arch/sparc/tlb_map.hh b/src/arch/sparc/tlb_map.hh index 8285db939..fa49584ba 100644 --- a/src/arch/sparc/tlb_map.hh +++ b/src/arch/sparc/tlb_map.hh @@ -52,7 +52,7 @@ class TlbMap i = tree.upper_bound(r); - if (i == tree.begin()) + if (i == tree.begin()) { if (r.real == i->first.real && r.partitionId == i->first.partitionId && i->first.va < r.va + r.size && @@ -62,6 +62,7 @@ class TlbMap else // Nothing could match, so return end() return tree.end(); + } i--; diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc index c09cacc00..2e668ec32 100644 --- a/src/mem/bridge.cc +++ b/src/mem/bridge.cc @@ -130,7 +130,7 @@ Bridge::BridgePort::recvTiming(PacketPtr pkt) return true; } - if (pkt->needsResponse()) + 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", @@ -141,6 +141,7 @@ Bridge::BridgePort::recvTiming(PacketPtr pkt) DPRINTF(BusBridge, "Request Needs response, reserving space\n"); ++outstandingResponses; } + } otherPort->queueForSendTiming(pkt); -- cgit v1.2.3 From ca4baf387134f75b5e78a22c4c18d63fb5f48201 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 26 Sep 2008 09:37:21 -0700 Subject: style: missed space after switch --- src/arch/mips/dsp.cc | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/arch/mips/dsp.cc b/src/arch/mips/dsp.cc index 183016ee7..fc3ae65d6 100755 --- a/src/arch/mips/dsp.cc +++ b/src/arch/mips/dsp.cc @@ -63,7 +63,7 @@ MipsISA::dspSaturate(uint64_t value, int32_t fmt, int32_t sign, { int64_t svalue = (int64_t)value; - switch(sign) { + switch (sign) { case SIGNED: if (svalue > (int64_t)FIXED_SMAX[fmt]) { *overflow = 1; @@ -93,7 +93,7 @@ MipsISA::checkOverflow(uint64_t value, int32_t fmt, int32_t sign, { int64_t svalue = (int64_t)value; - switch(sign) + switch (sign) { case SIGNED: if (svalue > (int64_t)FIXED_SMAX[fmt] || @@ -431,7 +431,7 @@ MipsISA::dspMuleu(int32_t a, int32_t b, int32_t mode, uint32_t *dspctl) simdUnpack(a, a_values, SIMD_FMT_QB, UNSIGNED); simdUnpack(b, b_values, SIMD_FMT_PH, UNSIGNED); - switch(mode) { + switch (mode) { case MODE_L: for (int i = 0; i < nvals; i++) b_values[i] = dspSaturate(a_values[i + 2] * b_values[i], @@ -466,7 +466,7 @@ MipsISA::dspMuleq(int32_t a, int32_t b, int32_t mode, uint32_t *dspctl) simdUnpack(a, a_values, SIMD_FMT_PH, SIGNED); simdUnpack(b, b_values, SIMD_FMT_PH, SIGNED); - switch(mode) { + switch (mode) { case MODE_L: for (int i = 0; i < nvals; i++) c_values[i] = dspSaturate(a_values[i + 1] * b_values[i + 1] << 1, @@ -504,7 +504,7 @@ MipsISA::dspDpaq(int64_t dspac, int32_t a, int32_t b, int32_t ac, simdUnpack(b, b_values, infmt, SIGNED); for (int i = 0; i < nvals; i++) { - switch(mode) { + switch (mode) { case MODE_X: if (a_values[nvals - 1 - i] == FIXED_SMIN[infmt] && b_values[i] == FIXED_SMIN[infmt]) { @@ -571,7 +571,7 @@ MipsISA::dspDpsq(int64_t dspac, int32_t a, int32_t b, int32_t ac, simdUnpack(b, b_values, infmt, SIGNED); for (int i = 0; i < nvals; i++) { - switch(mode) { + switch (mode) { case MODE_X: if (a_values[nvals - 1 - i] == FIXED_SMIN[infmt] && b_values[i] == FIXED_SMIN[infmt]) { @@ -634,7 +634,7 @@ MipsISA::dspDpa(int64_t dspac, int32_t a, int32_t b, int32_t ac, simdUnpack(b, b_values, fmt, sign); for (int i = 0; i < 2; i++) { - switch(mode) { + switch (mode) { case MODE_L: dspac += a_values[nvals - 1 - i] * b_values[nvals - 1 - i]; break; @@ -662,7 +662,7 @@ MipsISA::dspDps(int64_t dspac, int32_t a, int32_t b, int32_t ac, simdUnpack(b, b_values, fmt, sign); for (int i = 0; i < 2; i++) { - switch(mode) { + switch (mode) { case MODE_L: dspac -= a_values[nvals - 1 - i] * b_values[nvals - 1 - i]; break; @@ -692,7 +692,7 @@ MipsISA::dspMaq(int64_t dspac, int32_t a, int32_t b, int32_t ac, simdUnpack(b, b_values, fmt, SIGNED); for (int i = 0; i < nvals; i++) { - switch(mode) { + switch (mode) { case MODE_L: temp = a_values[i + 1] * b_values[i + 1] << 1; if (a_values[i + 1] == FIXED_SMIN[fmt] && @@ -780,7 +780,7 @@ MipsISA::dspCmp(int32_t a, int32_t b, int32_t fmt, int32_t sign, int32_t op, for (int i = 0; i < nvals; i++) { int cc = 0; - switch(op) { + switch (op) { case CMP_EQ: cc = (a_values[i] == b_values[i]); break; @@ -812,7 +812,7 @@ MipsISA::dspCmpg(int32_t a, int32_t b, int32_t fmt, int32_t sign, int32_t op) for (int i = 0; i < nvals; i++) { int cc = 0; - switch(op) { + switch (op) { case CMP_EQ: cc = (a_values[i] == b_values[i]); break; @@ -846,7 +846,7 @@ MipsISA::dspCmpgd(int32_t a, int32_t b, int32_t fmt, int32_t sign, int32_t op, for (int i = 0; i < nvals; i++) { int cc = 0; - switch(op) { + switch (op) { case CMP_EQ: cc = (a_values[i] == b_values[i]); break; @@ -888,7 +888,7 @@ MipsISA::dspPrece(int32_t a, int32_t infmt, int32_t insign, int32_t outfmt, simdUnpack(a, in_values, infmt, insign); for (int i = 0; i> 1)] << sa; break; @@ -1140,7 +1140,7 @@ MipsISA::simdUnpack(int32_t reg, uint64_t *values_ptr, int32_t fmt, int32_t sign int nvals = SIMD_NVALS[fmt]; int nbits = SIMD_NBITS[fmt]; - switch(sign) { + switch (sign) { case SIGNED: for (int i = 0; i < nvals; i++) { uint64_t tmp = (uint64_t)bits(reg, nbits * (i + 1) - 1, nbits * i); -- cgit v1.2.3 From 83f3bff6431a7fbf0a06cc382117af52c4c1ad3b Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 27 Sep 2008 00:15:45 -0700 Subject: add a bit of style --- src/base/fast_alloc.cc | 24 ++++++++---------------- src/base/fast_alloc.hh | 45 ++++++++++++++++++++------------------------- 2 files changed, 28 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/base/fast_alloc.cc b/src/base/fast_alloc.cc index 3e43ad94c..a91a99d20 100644 --- a/src/base/fast_alloc.cc +++ b/src/base/fast_alloc.cc @@ -34,7 +34,8 @@ * by permission. */ -#include +#include + #include "base/fast_alloc.hh" #if !NO_FAST_ALLOC @@ -51,7 +52,8 @@ unsigned FastAlloc::deleteCount[Num_Buckets]; unsigned FastAlloc::allocCount[Num_Buckets]; #endif -void *FastAlloc::moreStructs(int bucket) +void * +FastAlloc::moreStructs(int bucket) { assert(bucket > 0 && bucket < Num_Buckets); @@ -71,14 +73,13 @@ void *FastAlloc::moreStructs(int bucket) return (p + sz); } - #if FAST_ALLOC_DEBUG -#include -#include #include +#include #include #include +#include using namespace std; @@ -97,7 +98,6 @@ FastAlloc::FastAlloc(FastAlloc *prev, FastAlloc *next) inUseNext = next; } - // constructor: marks as in use, add to in-use list FastAlloc::FastAlloc() { @@ -131,7 +131,6 @@ FastAlloc::~FastAlloc() inUseNext->inUsePrev = inUsePrev; } - // summarize in-use list void FastAlloc::dump_summary() @@ -148,20 +147,16 @@ FastAlloc::dump_summary() cout << " count type\n" << " ----- ----\n"; for (mapiter = typemap.begin(); mapiter != typemap.end(); ++mapiter) - { cout << setw(6) << mapiter->second << " " << mapiter->first << endl; - } } - // show oldest n items on in-use list void FastAlloc::dump_oldest(int n) { // sanity check: don't want to crash the debugger if you forget to // pass in a parameter - if (n < 0 || n > numInUse) - { + if (n < 0 || n > numInUse) { cout << "FastAlloc::dump_oldest: bad arg " << n << " (" << numInUse << " objects in use" << endl; return; @@ -170,12 +165,9 @@ FastAlloc::dump_oldest(int n) for (FastAlloc *p = inUseHead.inUseNext; p != &inUseHead && n > 0; p = p->inUseNext, --n) - { cout << p << " " << typeid(*p).name() << endl; - } } - // // C interfaces to FastAlloc::dump_summary() and FastAlloc::dump_oldest(). // gdb seems to have trouble with calling C++ functions directly. @@ -192,6 +184,6 @@ fast_alloc_oldest(int n) FastAlloc::dump_oldest(n); } -#endif +#endif // FAST_ALLOC_DEBUG #endif // NO_FAST_ALLOC diff --git a/src/base/fast_alloc.hh b/src/base/fast_alloc.hh index 794a4afcc..775c93d50 100644 --- a/src/base/fast_alloc.hh +++ b/src/base/fast_alloc.hh @@ -34,10 +34,10 @@ * by permission. */ -#ifndef __FAST_ALLOC_H__ -#define __FAST_ALLOC_H__ +#ifndef __BASE_FAST_ALLOC_HH__ +#define __BASE_FAST_ALLOC_HH__ -#include +#include // Fast structure allocator. Designed for small objects that are // frequently allocated and deallocated. This code is derived from the @@ -68,14 +68,15 @@ #if NO_FAST_ALLOC -class FastAlloc { +class FastAlloc +{ }; #else -class FastAlloc { +class FastAlloc +{ public: - static void *allocate(size_t); static void deallocate(void *, size_t); @@ -84,7 +85,7 @@ class FastAlloc { #if FAST_ALLOC_DEBUG FastAlloc(); - FastAlloc(FastAlloc*,FastAlloc*); // for inUseHead, see below + FastAlloc(FastAlloc *, FastAlloc *); // for inUseHead, see below virtual ~FastAlloc(); #else virtual ~FastAlloc() {} @@ -139,16 +140,14 @@ class FastAlloc { #endif }; - -inline -int FastAlloc::bucketFor(size_t sz) +inline int +FastAlloc::bucketFor(size_t sz) { return (sz + Alloc_Quantum - 1) >> Log2_Alloc_Quantum; } - -inline -void *FastAlloc::allocate(size_t sz) +inline void * +FastAlloc::allocate(size_t sz) { int b; void *p; @@ -171,14 +170,12 @@ void *FastAlloc::allocate(size_t sz) return p; } - -inline -void FastAlloc::deallocate(void *p, size_t sz) +inline void +FastAlloc::deallocate(void *p, size_t sz) { int b; - if (sz > Max_Alloc_Size) - { + if (sz > Max_Alloc_Size) { ::delete [] (char *)p; return; } @@ -191,20 +188,18 @@ void FastAlloc::deallocate(void *p, size_t sz) #endif } - -inline -void *FastAlloc::operator new(size_t sz) +inline void * +FastAlloc::operator new(size_t sz) { return allocate(sz); } - -inline -void FastAlloc::operator delete(void *p, size_t sz) +inline void +FastAlloc::operator delete(void *p, size_t sz) { deallocate(p, sz); } #endif // NO_FAST_ALLOC -#endif // __FAST_ALLOC_H__ +#endif // __BASE_FAST_ALLOC_HH__ -- cgit v1.2.3 From 819023b8e2be98479a391cec1b24dbe159479737 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 27 Sep 2008 07:25:04 -0700 Subject: style --- src/arch/alpha/interrupts.hh | 228 ++++++++++++++++++++++--------------------- 1 file changed, 119 insertions(+), 109 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/interrupts.hh b/src/arch/alpha/interrupts.hh index 6453edf97..009b41637 100644 --- a/src/arch/alpha/interrupts.hh +++ b/src/arch/alpha/interrupts.hh @@ -37,140 +37,150 @@ #include "base/compiler.hh" #include "cpu/thread_context.hh" -namespace AlphaISA +namespace AlphaISA { + +class Interrupts { - class Interrupts + private: + bool newInfoSet; + int newIpl; + int newSummary; + + protected: + uint64_t interrupts[NumInterruptLevels]; + uint64_t intstatus; + + public: + Interrupts() { - protected: - uint64_t interrupts[NumInterruptLevels]; - uint64_t intstatus; - - public: - Interrupts() - { - memset(interrupts, 0, sizeof(interrupts)); - intstatus = 0; - newInfoSet = false; - } + memset(interrupts, 0, sizeof(interrupts)); + intstatus = 0; + newInfoSet = false; + } - void post(int int_num, int index) - { - DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); + void + post(int int_num, int index) + { + DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); - if (int_num < 0 || int_num >= NumInterruptLevels) - panic("int_num out of bounds\n"); + if (int_num < 0 || int_num >= NumInterruptLevels) + panic("int_num out of bounds\n"); - if (index < 0 || index >= sizeof(uint64_t) * 8) - panic("int_num out of bounds\n"); + if (index < 0 || index >= (int)sizeof(uint64_t) * 8) + panic("int_num out of bounds\n"); - interrupts[int_num] |= 1 << index; - intstatus |= (ULL(1) << int_num); - } + interrupts[int_num] |= 1 << index; + intstatus |= (ULL(1) << int_num); + } - void clear(int int_num, int index) - { - DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); + void + clear(int int_num, int index) + { + DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); - if (int_num < 0 || int_num >= TheISA::NumInterruptLevels) - panic("int_num out of bounds\n"); + if (int_num < 0 || int_num >= TheISA::NumInterruptLevels) + panic("int_num out of bounds\n"); - if (index < 0 || index >= sizeof(uint64_t) * 8) - panic("int_num out of bounds\n"); + if (index < 0 || index >= (int)sizeof(uint64_t) * 8) + panic("int_num out of bounds\n"); - interrupts[int_num] &= ~(1 << index); - if (interrupts[int_num] == 0) - intstatus &= ~(ULL(1) << int_num); - } + interrupts[int_num] &= ~(1 << index); + if (interrupts[int_num] == 0) + intstatus &= ~(ULL(1) << int_num); + } - void clear_all() - { - DPRINTF(Interrupt, "Interrupts all cleared\n"); + void + clear_all() + { + DPRINTF(Interrupt, "Interrupts all cleared\n"); - memset(interrupts, 0, sizeof(interrupts)); - intstatus = 0; - } + memset(interrupts, 0, sizeof(interrupts)); + intstatus = 0; + } - void serialize(std::ostream &os) - { - SERIALIZE_ARRAY(interrupts, NumInterruptLevels); - SERIALIZE_SCALAR(intstatus); - } + void + serialize(std::ostream &os) + { + SERIALIZE_ARRAY(interrupts, NumInterruptLevels); + SERIALIZE_SCALAR(intstatus); + } - void unserialize(Checkpoint *cp, const std::string §ion) - { - UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels); - UNSERIALIZE_SCALAR(intstatus); - } + void + unserialize(Checkpoint *cp, const std::string §ion) + { + UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels); + UNSERIALIZE_SCALAR(intstatus); + } - bool check_interrupts(ThreadContext * tc) const - { - return (intstatus != 0) && !(tc->readPC() & 0x3); - } + bool + check_interrupts(ThreadContext *tc) const + { + return (intstatus != 0) && !(tc->readPC() & 0x3); + } - Fault getInterrupt(ThreadContext * tc) - { - int ipl = 0; - int summary = 0; - - if (tc->readMiscRegNoEffect(IPR_ASTRR)) - panic("asynchronous traps not implemented\n"); - - if (tc->readMiscRegNoEffect(IPR_SIRR)) { - for (int i = INTLEVEL_SOFTWARE_MIN; - i < INTLEVEL_SOFTWARE_MAX; i++) { - if (tc->readMiscRegNoEffect(IPR_SIRR) & (ULL(1) << i)) { - // See table 4-19 of 21164 hardware reference - ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1; - summary |= (ULL(1) << i); - } + Fault + getInterrupt(ThreadContext *tc) + { + int ipl = 0; + int summary = 0; + + if (tc->readMiscRegNoEffect(IPR_ASTRR)) + panic("asynchronous traps not implemented\n"); + + if (tc->readMiscRegNoEffect(IPR_SIRR)) { + for (int i = INTLEVEL_SOFTWARE_MIN; + i < INTLEVEL_SOFTWARE_MAX; i++) { + if (tc->readMiscRegNoEffect(IPR_SIRR) & (ULL(1) << i)) { + // See table 4-19 of 21164 hardware reference + ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1; + summary |= (ULL(1) << i); } } + } - uint64_t interrupts = intstatus; - if (interrupts) { - for (int i = INTLEVEL_EXTERNAL_MIN; - i < INTLEVEL_EXTERNAL_MAX; i++) { - if (interrupts & (ULL(1) << i)) { - // See table 4-19 of 21164 hardware reference - ipl = i; - summary |= (ULL(1) << i); - } + uint64_t interrupts = intstatus; + if (interrupts) { + for (int i = INTLEVEL_EXTERNAL_MIN; + i < INTLEVEL_EXTERNAL_MAX; i++) { + if (interrupts & (ULL(1) << i)) { + // See table 4-19 of 21164 hardware reference + ipl = i; + summary |= (ULL(1) << i); } } - - if (ipl && ipl > tc->readMiscRegNoEffect(IPR_IPLR)) { - newIpl = ipl; - newSummary = summary; - newInfoSet = true; - DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", - tc->readMiscRegNoEffect(IPR_IPLR), ipl, summary); - - return new InterruptFault; - } else { - return NoFault; - } } - void updateIntrInfo(ThreadContext *tc) - { - assert(newInfoSet); - tc->setMiscRegNoEffect(IPR_ISR, newSummary); - tc->setMiscRegNoEffect(IPR_INTID, newIpl); - newInfoSet = false; - } + if (ipl && ipl > tc->readMiscRegNoEffect(IPR_IPLR)) { + newIpl = ipl; + newSummary = summary; + newInfoSet = true; + DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", + tc->readMiscRegNoEffect(IPR_IPLR), ipl, summary); - uint64_t get_vec(int int_num) - { - panic("Shouldn't be called for Alpha\n"); - M5_DUMMY_RETURN + return new InterruptFault; + } else { + return NoFault; } + } + + void + updateIntrInfo(ThreadContext *tc) + { + assert(newInfoSet); + tc->setMiscRegNoEffect(IPR_ISR, newSummary); + tc->setMiscRegNoEffect(IPR_INTID, newIpl); + newInfoSet = false; + } + + uint64_t + get_vec(int int_num) + { + panic("Shouldn't be called for Alpha\n"); + M5_DUMMY_RETURN; + } +}; - private: - bool newInfoSet; - int newIpl; - int newSummary; - }; -} +} // namespace AlphaISA -#endif +#endif // __ARCH_ALPHA_INTERRUPT_HH__ -- cgit v1.2.3 From 0b30c345f17f928c99660d633147f24f4f0035bd Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 27 Sep 2008 21:03:45 -0700 Subject: alpha: Get rid fo the namespace called EV5. We're never going to do an alpha platform other than the one we've got. --- src/arch/alpha/ev5.cc | 44 ++++++++++++++++++------------------- src/arch/alpha/ev5.hh | 7 ++---- src/arch/alpha/faults.cc | 4 ++-- src/arch/alpha/isa/fp.isa | 2 +- src/arch/alpha/system.cc | 2 +- src/arch/alpha/tlb.cc | 1 - src/arch/alpha/tlb.hh | 4 ++-- src/arch/alpha/vtophys.cc | 2 +- src/arch/mips/mips_core_specific.cc | 4 ++-- src/arch/mips/system.cc | 2 +- src/kern/tru64/tru64_events.cc | 2 +- 11 files changed, 35 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/ev5.cc b/src/arch/alpha/ev5.cc index 33306d6af..83900349e 100644 --- a/src/arch/alpha/ev5.cc +++ b/src/arch/alpha/ev5.cc @@ -44,9 +44,9 @@ #include "sim/debug.hh" #include "sim/sim_exit.hh" -#if FULL_SYSTEM +using namespace AlphaISA; -using namespace EV5; +#if FULL_SYSTEM //////////////////////////////////////////////////////////////////////// // @@ -146,13 +146,13 @@ SimpleThread::hwrei() int AlphaISA::MiscRegFile::getInstAsid() { - return EV5::ITB_ASN_ASN(ipr[IPR_ITB_ASN]); + return AlphaISA::ITB_ASN_ASN(ipr[IPR_ITB_ASN]); } int AlphaISA::MiscRegFile::getDataAsid() { - return EV5::DTB_ASN_ASN(ipr[IPR_DTB_ASN]); + return AlphaISA::DTB_ASN_ASN(ipr[IPR_DTB_ASN]); } #endif @@ -168,7 +168,7 @@ AlphaISA::initIPRs(ThreadContext *tc, int cpuId) tc->setMiscRegNoEffect(i, 0); } - tc->setMiscRegNoEffect(IPR_PAL_BASE, EV5::PalBase); + tc->setMiscRegNoEffect(IPR_PAL_BASE, AlphaISA::PalBase); tc->setMiscRegNoEffect(IPR_MCSR, 0x6); tc->setMiscRegNoEffect(IPR_PALtemp16, cpuId); } @@ -477,27 +477,27 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc) ipr[idx] = val; tc->getDTBPtr()->flushAddr(val, - EV5::DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN])); + AlphaISA::DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN])); break; case AlphaISA::IPR_DTB_TAG: { struct AlphaISA::TlbEntry entry; // FIXME: granularity hints NYI... - if (EV5::DTB_PTE_GH(ipr[AlphaISA::IPR_DTB_PTE]) != 0) + if (AlphaISA::DTB_PTE_GH(ipr[AlphaISA::IPR_DTB_PTE]) != 0) panic("PTE GH field != 0"); // write entire quad ipr[idx] = val; // construct PTE for new entry - entry.ppn = EV5::DTB_PTE_PPN(ipr[AlphaISA::IPR_DTB_PTE]); - entry.xre = EV5::DTB_PTE_XRE(ipr[AlphaISA::IPR_DTB_PTE]); - entry.xwe = EV5::DTB_PTE_XWE(ipr[AlphaISA::IPR_DTB_PTE]); - entry.fonr = EV5::DTB_PTE_FONR(ipr[AlphaISA::IPR_DTB_PTE]); - entry.fonw = EV5::DTB_PTE_FONW(ipr[AlphaISA::IPR_DTB_PTE]); - entry.asma = EV5::DTB_PTE_ASMA(ipr[AlphaISA::IPR_DTB_PTE]); - entry.asn = EV5::DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]); + entry.ppn = AlphaISA::DTB_PTE_PPN(ipr[AlphaISA::IPR_DTB_PTE]); + entry.xre = AlphaISA::DTB_PTE_XRE(ipr[AlphaISA::IPR_DTB_PTE]); + entry.xwe = AlphaISA::DTB_PTE_XWE(ipr[AlphaISA::IPR_DTB_PTE]); + entry.fonr = AlphaISA::DTB_PTE_FONR(ipr[AlphaISA::IPR_DTB_PTE]); + entry.fonw = AlphaISA::DTB_PTE_FONW(ipr[AlphaISA::IPR_DTB_PTE]); + entry.asma = AlphaISA::DTB_PTE_ASMA(ipr[AlphaISA::IPR_DTB_PTE]); + entry.asn = AlphaISA::DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]); // insert new TAG/PTE value into data TLB tc->getDTBPtr()->insert(val, entry); @@ -508,20 +508,20 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc) struct AlphaISA::TlbEntry entry; // FIXME: granularity hints NYI... - if (EV5::ITB_PTE_GH(val) != 0) + if (AlphaISA::ITB_PTE_GH(val) != 0) panic("PTE GH field != 0"); // write entire quad ipr[idx] = val; // construct PTE for new entry - entry.ppn = EV5::ITB_PTE_PPN(val); - entry.xre = EV5::ITB_PTE_XRE(val); + entry.ppn = AlphaISA::ITB_PTE_PPN(val); + entry.xre = AlphaISA::ITB_PTE_XRE(val); entry.xwe = 0; - entry.fonr = EV5::ITB_PTE_FONR(val); - entry.fonw = EV5::ITB_PTE_FONW(val); - entry.asma = EV5::ITB_PTE_ASMA(val); - entry.asn = EV5::ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]); + entry.fonr = AlphaISA::ITB_PTE_FONR(val); + entry.fonw = AlphaISA::ITB_PTE_FONW(val); + entry.asma = AlphaISA::ITB_PTE_ASMA(val); + entry.asn = AlphaISA::ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]); // insert new TAG/PTE value into data TLB tc->getITBPtr()->insert(ipr[AlphaISA::IPR_ITB_TAG], entry); @@ -547,7 +547,7 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc) ipr[idx] = val; tc->getITBPtr()->flushAddr(val, - EV5::ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN])); + AlphaISA::ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN])); break; default: diff --git a/src/arch/alpha/ev5.hh b/src/arch/alpha/ev5.hh index 4dd225786..4fe5f1b71 100644 --- a/src/arch/alpha/ev5.hh +++ b/src/arch/alpha/ev5.hh @@ -36,10 +36,7 @@ #include "config/alpha_tlaser.hh" #include "arch/alpha/isa_traits.hh" -namespace EV5 { - -//It seems like a safe assumption EV5 only applies to alpha -using namespace AlphaISA; +namespace AlphaISA { #if ALPHA_TLASER const uint64_t AsnMask = ULL(0x7f); @@ -120,6 +117,6 @@ inline int Ra(AlphaISA::MachInst inst) { return inst >> 21 & 0x1f; } const Addr PalBase = 0x4000; const Addr PalMax = 0x10000; -/* namespace EV5 */ } +} // namespace AlphaISA #endif // __ARCH_ALPHA_EV5_HH__ diff --git a/src/arch/alpha/faults.cc b/src/arch/alpha/faults.cc index 20591b357..7417ada5f 100644 --- a/src/arch/alpha/faults.cc +++ b/src/arch/alpha/faults.cc @@ -148,8 +148,8 @@ void DtbFault::invoke(ThreadContext * tc) // set MM_STAT register flags tc->setMiscRegNoEffect(AlphaISA::IPR_MM_STAT, - (((EV5::Opcode(tc->getInst()) & 0x3f) << 11) - | ((EV5::Ra(tc->getInst()) & 0x1f) << 6) + (((AlphaISA::Opcode(tc->getInst()) & 0x3f) << 11) + | ((AlphaISA::Ra(tc->getInst()) & 0x1f) << 6) | (flags & 0x3f))); // set VA_FORM register with faulting formatted address diff --git a/src/arch/alpha/isa/fp.isa b/src/arch/alpha/isa/fp.isa index 773e7d10c..8b13f8dd7 100644 --- a/src/arch/alpha/isa/fp.isa +++ b/src/arch/alpha/isa/fp.isa @@ -46,7 +46,7 @@ output exec {{ inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) { Fault fault = NoFault; // dummy... this ipr access should not fault - if (!EV5::ICSR_FPE(xc->readMiscReg(AlphaISA::IPR_ICSR))) { + if (!AlphaISA::ICSR_FPE(xc->readMiscReg(AlphaISA::IPR_ICSR))) { fault = new FloatEnableFault; } return fault; diff --git a/src/arch/alpha/system.cc b/src/arch/alpha/system.cc index f8fea4fee..63efef4a0 100644 --- a/src/arch/alpha/system.cc +++ b/src/arch/alpha/system.cc @@ -190,7 +190,7 @@ AlphaSystem::setAlphaAccess(Addr access) { Addr addr = 0; if (consoleSymtab->findAddress("m5AlphaAccess", addr)) { - virtPort.write(addr, htog(EV5::Phys2K0Seg(access))); + virtPort.write(addr, htog(AlphaISA::Phys2K0Seg(access))); } else panic("could not find m5AlphaAccess\n"); } diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc index 60502ebdb..2694cf38f 100644 --- a/src/arch/alpha/tlb.cc +++ b/src/arch/alpha/tlb.cc @@ -43,7 +43,6 @@ #include "cpu/thread_context.hh" using namespace std; -using namespace EV5; namespace AlphaISA { /////////////////////////////////////////////////////////////////////// diff --git a/src/arch/alpha/tlb.hh b/src/arch/alpha/tlb.hh index f94d06ccd..98f845e21 100644 --- a/src/arch/alpha/tlb.hh +++ b/src/arch/alpha/tlb.hh @@ -88,8 +88,8 @@ namespace AlphaISA // static helper functions... really EV5 VM traits static bool validVirtualAddress(Addr vaddr) { // unimplemented bits must be all 0 or all 1 - Addr unimplBits = vaddr & EV5::VAddrUnImplMask; - return (unimplBits == 0) || (unimplBits == EV5::VAddrUnImplMask); + Addr unimplBits = vaddr & AlphaISA::VAddrUnImplMask; + return (unimplBits == 0) || (unimplBits == AlphaISA::VAddrUnImplMask); } static Fault checkCacheability(RequestPtr &req, bool itb = false); diff --git a/src/arch/alpha/vtophys.cc b/src/arch/alpha/vtophys.cc index 6ffbea181..439af3bd7 100644 --- a/src/arch/alpha/vtophys.cc +++ b/src/arch/alpha/vtophys.cc @@ -92,7 +92,7 @@ AlphaISA::vtophys(ThreadContext *tc, Addr addr) Addr paddr = 0; //@todo Andrew couldn't remember why he commented some of this code //so I put it back in. Perhaps something to do with gdb debugging? - if (AlphaISA::PcPAL(vaddr) && (vaddr < EV5::PalMax)) { + if (AlphaISA::PcPAL(vaddr) && (vaddr < AlphaISA::PalMax)) { paddr = vaddr & ~ULL(1); } else { if (AlphaISA::IsK0Seg(vaddr)) { diff --git a/src/arch/mips/mips_core_specific.cc b/src/arch/mips/mips_core_specific.cc index a17ebcdf3..80d856b0c 100755 --- a/src/arch/mips/mips_core_specific.cc +++ b/src/arch/mips/mips_core_specific.cc @@ -113,13 +113,13 @@ MipsISA::processInterrupts(CPU *cpu) /*int MipsISA::MiscRegFile::getInstAsid() { - return EV5::ITB_ASN_ASN(ipr[IPR_ITB_ASN]); + return AlphaISA::ITB_ASN_ASN(ipr[IPR_ITB_ASN]); } int MipsISA::MiscRegFile::getDataAsid() { - return EV5::DTB_ASN_ASN(ipr[IPR_DTB_ASN]); + return AlphaISA::DTB_ASN_ASN(ipr[IPR_DTB_ASN]); }*/ diff --git a/src/arch/mips/system.cc b/src/arch/mips/system.cc index bf86bb030..73bc33161 100755 --- a/src/arch/mips/system.cc +++ b/src/arch/mips/system.cc @@ -185,7 +185,7 @@ MipsSystem::setMipsAccess(Addr access) { Addr addr = 0; if (consoleSymtab->findAddress("m5MipsAccess", addr)) { - // virtPort.write(addr, htog(EV5::Phys2K0Seg(access))); + // virtPort.write(addr, htog(AlphaISA::Phys2K0Seg(access))); } else panic("could not find m5MipsAccess\n"); } diff --git a/src/kern/tru64/tru64_events.cc b/src/kern/tru64/tru64_events.cc index c798c3ced..9fa770c4d 100644 --- a/src/kern/tru64/tru64_events.cc +++ b/src/kern/tru64/tru64_events.cc @@ -61,7 +61,7 @@ BadAddrEvent::process(ThreadContext *tc) tc->getPhysPort()->getPeerAddressRanges(resp, snoop); for(iter = resp.begin(); iter != resp.end(); iter++) { - if (*iter == (TheISA::K0Seg2Phys(a0) & EV5::PAddrImplMask)) + if (*iter == (TheISA::K0Seg2Phys(a0) & AlphaISA::PAddrImplMask)) found = true; } -- cgit v1.2.3 From 8ea5176b7f4eac09d152dd63d0ba07962be9c865 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 27 Sep 2008 21:03:46 -0700 Subject: arch: TheISA shouldn't really ever be used in the arch directory. We should always refer to the specific ISA in that arch directory. This is especially necessary if we're ever going to make it to the point where we actually have heterogeneous systems. --- src/arch/alpha/ev5.cc | 4 ++-- src/arch/alpha/idle_event.cc | 2 +- src/arch/alpha/interrupts.hh | 2 +- src/arch/alpha/linux/threadinfo.hh | 4 ++-- src/arch/alpha/regfile.cc | 2 +- src/arch/alpha/remote_gdb.cc | 26 +++++++++++++------------- src/arch/alpha/stacktrace.cc | 2 +- src/arch/alpha/stacktrace.hh | 2 +- src/arch/alpha/tru64/process.cc | 2 +- src/arch/mips/idle_event.cc | 2 +- src/arch/mips/linux/threadinfo.hh | 4 ++-- src/arch/mips/regfile/misc_regfile.cc | 2 +- src/arch/mips/stacktrace.cc | 2 +- src/arch/mips/stacktrace.hh | 2 +- src/arch/sparc/process.cc | 2 +- src/arch/sparc/regfile.cc | 4 ++-- src/arch/sparc/remote_gdb.cc | 2 +- src/arch/sparc/stacktrace.cc | 2 +- src/arch/sparc/stacktrace.hh | 2 +- src/arch/x86/process.cc | 6 +++--- src/arch/x86/remote_gdb.cc | 2 +- 21 files changed, 39 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/ev5.cc b/src/arch/alpha/ev5.cc index 83900349e..45d2ff5a5 100644 --- a/src/arch/alpha/ev5.cc +++ b/src/arch/alpha/ev5.cc @@ -383,10 +383,10 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc) #if FULL_SYSTEM if (val & 0x18) { if (tc->getKernelStats()) - tc->getKernelStats()->mode(TheISA::Kernel::user, tc); + tc->getKernelStats()->mode(AlphaISA::Kernel::user, tc); } else { if (tc->getKernelStats()) - tc->getKernelStats()->mode(TheISA::Kernel::kernel, tc); + tc->getKernelStats()->mode(AlphaISA::Kernel::kernel, tc); } #endif diff --git a/src/arch/alpha/idle_event.cc b/src/arch/alpha/idle_event.cc index f0f1eab7a..d3807a48d 100644 --- a/src/arch/alpha/idle_event.cc +++ b/src/arch/alpha/idle_event.cc @@ -33,7 +33,7 @@ #include "arch/alpha/kernel_stats.hh" #include "cpu/thread_context.hh" -using namespace TheISA; +using namespace AlphaISA; void IdleStartEvent::process(ThreadContext *tc) diff --git a/src/arch/alpha/interrupts.hh b/src/arch/alpha/interrupts.hh index 009b41637..1d8ba736f 100644 --- a/src/arch/alpha/interrupts.hh +++ b/src/arch/alpha/interrupts.hh @@ -78,7 +78,7 @@ class Interrupts { DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); - if (int_num < 0 || int_num >= TheISA::NumInterruptLevels) + if (int_num < 0 || int_num >= AlphaISA::NumInterruptLevels) panic("int_num out of bounds\n"); if (index < 0 || index >= (int)sizeof(uint64_t) * 8) diff --git a/src/arch/alpha/linux/threadinfo.hh b/src/arch/alpha/linux/threadinfo.hh index b0c8284be..3ec1aa098 100644 --- a/src/arch/alpha/linux/threadinfo.hh +++ b/src/arch/alpha/linux/threadinfo.hh @@ -55,7 +55,7 @@ class ThreadInfo CopyOut(tc, &data, addr, sizeof(T)); - data = TheISA::gtoh(data); + data = AlphaISA::gtoh(data); return true; } @@ -76,7 +76,7 @@ class ThreadInfo Addr sp; if (!addr) - addr = tc->readMiscRegNoEffect(TheISA::IPR_PALtemp23); + addr = tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp23); FunctionalPort *p = tc->getPhysPort(); p->readBlob(addr, (uint8_t *)&sp, sizeof(Addr)); diff --git a/src/arch/alpha/regfile.cc b/src/arch/alpha/regfile.cc index 2653310d7..3faa189ca 100644 --- a/src/arch/alpha/regfile.cc +++ b/src/arch/alpha/regfile.cc @@ -70,7 +70,7 @@ namespace AlphaISA } // Then loop through the floating point registers. - for (int i = 0; i < TheISA::NumFloatRegs; ++i) { + for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) { dest->setFloatRegBits(i, src->readFloatRegBits(i)); } diff --git a/src/arch/alpha/remote_gdb.cc b/src/arch/alpha/remote_gdb.cc index 8d70ebfa2..a40d06f18 100644 --- a/src/arch/alpha/remote_gdb.cc +++ b/src/arch/alpha/remote_gdb.cc @@ -140,7 +140,7 @@ #include "sim/system.hh" using namespace std; -using namespace TheISA; +using namespace AlphaISA; RemoteGDB::RemoteGDB(System *_system, ThreadContext *c) : BaseRemoteGDB(_system, c, KGDB_NUMREGS) @@ -161,12 +161,12 @@ RemoteGDB::acc(Addr va, size_t len) #else Addr last_va; - va = TheISA::TruncPage(va); - last_va = TheISA::RoundPage(va + len); + va = AlphaISA::TruncPage(va); + last_va = AlphaISA::RoundPage(va + len); do { - if (TheISA::IsK0Seg(va)) { - if (va < (TheISA::K0SegBase + pmem->size())) { + if (AlphaISA::IsK0Seg(va)) { + if (va < (AlphaISA::K0SegBase + pmem->size())) { DPRINTF(GDBAcc, "acc: Mapping is valid K0SEG <= " "%#x < K0SEG + size\n", va); return true; @@ -188,12 +188,12 @@ RemoteGDB::acc(Addr va, size_t len) return true; Addr ptbr = context->readMiscRegNoEffect(AlphaISA::IPR_PALtemp20); - TheISA::PageTableEntry pte = TheISA::kernel_pte_lookup(context->getPhysPort(), ptbr, va); + AlphaISA::PageTableEntry pte = AlphaISA::kernel_pte_lookup(context->getPhysPort(), ptbr, va); if (!pte.valid()) { DPRINTF(GDBAcc, "acc: %#x pte is invalid\n", va); return false; } - va += TheISA::PageBytes; + va += AlphaISA::PageBytes; } while (va < last_va); DPRINTF(GDBAcc, "acc: %#x mapping is valid\n", va); @@ -215,17 +215,17 @@ RemoteGDB::getregs() // @todo: Currently this is very Alpha specific. if (AlphaISA::PcPAL(gdbregs.regs[KGDB_REG_PC])) { - for (int i = 0; i < TheISA::NumIntArchRegs; ++i) { + for (int i = 0; i < AlphaISA::NumIntArchRegs; ++i) { gdbregs.regs[i] = context->readIntReg(AlphaISA::reg_redir[i]); } } else { - for (int i = 0; i < TheISA::NumIntArchRegs; ++i) { + for (int i = 0; i < AlphaISA::NumIntArchRegs; ++i) { gdbregs.regs[i] = context->readIntReg(i); } } #ifdef KGDB_FP_REGS - for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) { + for (int i = 0; i < AlphaISA::NumFloatArchRegs; ++i) { gdbregs.regs[i + KGDB_REG_F0] = context->readFloatRegBits(i); } #endif @@ -242,17 +242,17 @@ RemoteGDB::setregs() { // @todo: Currently this is very Alpha specific. if (AlphaISA::PcPAL(gdbregs.regs[KGDB_REG_PC])) { - for (int i = 0; i < TheISA::NumIntArchRegs; ++i) { + for (int i = 0; i < AlphaISA::NumIntArchRegs; ++i) { context->setIntReg(AlphaISA::reg_redir[i], gdbregs.regs[i]); } } else { - for (int i = 0; i < TheISA::NumIntArchRegs; ++i) { + for (int i = 0; i < AlphaISA::NumIntArchRegs; ++i) { context->setIntReg(i, gdbregs.regs[i]); } } #ifdef KGDB_FP_REGS - for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) { + for (int i = 0; i < AlphaISA::NumFloatArchRegs; ++i) { context->setFloatRegBits(i, gdbregs.regs[i + KGDB_REG_F0]); } #endif diff --git a/src/arch/alpha/stacktrace.cc b/src/arch/alpha/stacktrace.cc index 124949781..b2fa89cb8 100644 --- a/src/arch/alpha/stacktrace.cc +++ b/src/arch/alpha/stacktrace.cc @@ -159,7 +159,7 @@ namespace AlphaISA } SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; - Addr ksp = tc->readIntReg(TheISA::StackPointerReg); + Addr ksp = tc->readIntReg(AlphaISA::StackPointerReg); Addr bottom = ksp & ~0x3fff; Addr addr; diff --git a/src/arch/alpha/stacktrace.hh b/src/arch/alpha/stacktrace.hh index 834abbc2f..c028afe2b 100644 --- a/src/arch/alpha/stacktrace.hh +++ b/src/arch/alpha/stacktrace.hh @@ -62,7 +62,7 @@ namespace AlphaISA class StackTrace { protected: - typedef TheISA::MachInst MachInst; + typedef AlphaISA::MachInst MachInst; private: ThreadContext *tc; std::vector stack; diff --git a/src/arch/alpha/tru64/process.cc b/src/arch/alpha/tru64/process.cc index 5f448489e..455a24584 100644 --- a/src/arch/alpha/tru64/process.cc +++ b/src/arch/alpha/tru64/process.cc @@ -166,7 +166,7 @@ SyscallReturn tableFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { using namespace std; - using namespace TheISA; + using namespace AlphaISA; int id = tc->getSyscallArg(0); // table ID int index = tc->getSyscallArg(1); // index into table diff --git a/src/arch/mips/idle_event.cc b/src/arch/mips/idle_event.cc index d1d4f7c63..0aea08834 100644 --- a/src/arch/mips/idle_event.cc +++ b/src/arch/mips/idle_event.cc @@ -34,7 +34,7 @@ #include "arch/mips/kernel_stats.hh" #include "cpu/thread_context.hh" -using namespace TheISA; +using namespace MipsISA; void IdleStartEvent::process(ThreadContext *tc) diff --git a/src/arch/mips/linux/threadinfo.hh b/src/arch/mips/linux/threadinfo.hh index 25ee74dd3..b0d0cd811 100644 --- a/src/arch/mips/linux/threadinfo.hh +++ b/src/arch/mips/linux/threadinfo.hh @@ -55,7 +55,7 @@ class ThreadInfo CopyOut(tc, &data, addr, sizeof(T)); - data = TheISA::gtoh(data); + data = MipsISA::gtoh(data); return true; } @@ -77,7 +77,7 @@ class ThreadInfo Addr sp; if (!addr) - addr = tc->readMiscRegNoEffect(0/*TheISA::IPR_PALtemp23*/); + addr = tc->readMiscRegNoEffect(0/*MipsISA::IPR_PALtemp23*/); FunctionalPort *p = tc->getPhysPort(); p->readBlob(addr, (uint8_t *)&sp, sizeof(Addr)); diff --git a/src/arch/mips/regfile/misc_regfile.cc b/src/arch/mips/regfile/misc_regfile.cc index b82a94103..e81f940f5 100755 --- a/src/arch/mips/regfile/misc_regfile.cc +++ b/src/arch/mips/regfile/misc_regfile.cc @@ -186,7 +186,7 @@ MiscRegFile::reset(std::string core_name, unsigned num_threads, num_threads, num_vpes); cpu = _cpu; - TheISA::CoreSpecific &cp = cpu->coreParams; + MipsISA::CoreSpecific &cp = cpu->coreParams; // Do Default CP0 initialization HERE diff --git a/src/arch/mips/stacktrace.cc b/src/arch/mips/stacktrace.cc index 482d264e8..04a9a0f18 100644 --- a/src/arch/mips/stacktrace.cc +++ b/src/arch/mips/stacktrace.cc @@ -159,7 +159,7 @@ StackTrace::trace(ThreadContext *_tc, bool is_call) // } // SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; -// Addr ksp = tc->readIntReg(TheISA::StackPointerReg); +// Addr ksp = tc->readIntReg(MipsISA::StackPointerReg); // Addr bottom = ksp & ~0x3fff; // Addr addr; diff --git a/src/arch/mips/stacktrace.hh b/src/arch/mips/stacktrace.hh index e2424523f..4c02cc86c 100644 --- a/src/arch/mips/stacktrace.hh +++ b/src/arch/mips/stacktrace.hh @@ -61,7 +61,7 @@ class ProcessInfo class StackTrace { protected: - typedef TheISA::MachInst MachInst; + typedef MipsISA::MachInst MachInst; private: ThreadContext *tc; std::vector stack; diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index 6e490e05e..a8fda04eb 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -354,7 +354,7 @@ SparcLiveProcess::argsInit(int pageSize) // figure out argc IntType argc = argv.size(); - IntType guestArgc = TheISA::htog(argc); + IntType guestArgc = SparcISA::htog(argc); //Write out the sentry void * uint64_t sentry_NULL = 0; diff --git a/src/arch/sparc/regfile.cc b/src/arch/sparc/regfile.cc index d6be52424..76516daca 100644 --- a/src/arch/sparc/regfile.cc +++ b/src/arch/sparc/regfile.cc @@ -366,12 +366,12 @@ void SparcISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest) void SparcISA::copyRegs(ThreadContext *src, ThreadContext *dest) { // First loop through the integer registers. - for (int i = 0; i < TheISA::NumIntRegs; ++i) { + for (int i = 0; i < SparcISA::NumIntRegs; ++i) { dest->setIntReg(i, src->readIntReg(i)); } // Then loop through the floating point registers. - for (int i = 0; i < TheISA::NumFloatRegs; ++i) { + for (int i = 0; i < SparcISA::NumFloatRegs; ++i) { dest->setFloatRegBits(i, src->readFloatRegBits(i)); } diff --git a/src/arch/sparc/remote_gdb.cc b/src/arch/sparc/remote_gdb.cc index ef30bd808..615c5b551 100644 --- a/src/arch/sparc/remote_gdb.cc +++ b/src/arch/sparc/remote_gdb.cc @@ -137,7 +137,7 @@ #include "sim/system.hh" using namespace std; -using namespace TheISA; +using namespace SparcISA; RemoteGDB::RemoteGDB(System *_system, ThreadContext *c) : BaseRemoteGDB(_system, c, NumGDBRegs), nextBkpt(0) diff --git a/src/arch/sparc/stacktrace.cc b/src/arch/sparc/stacktrace.cc index 8ec1d36c8..3ab0edb57 100644 --- a/src/arch/sparc/stacktrace.cc +++ b/src/arch/sparc/stacktrace.cc @@ -159,7 +159,7 @@ namespace SparcISA } SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; - Addr ksp = tc->readIntReg(TheISA::StackPointerReg); + Addr ksp = tc->readIntReg(SparcISA::StackPointerReg); Addr bottom = ksp & ~0x3fff; Addr addr; diff --git a/src/arch/sparc/stacktrace.hh b/src/arch/sparc/stacktrace.hh index 4bc5d779b..929990fcb 100644 --- a/src/arch/sparc/stacktrace.hh +++ b/src/arch/sparc/stacktrace.hh @@ -61,7 +61,7 @@ namespace SparcISA class StackTrace { protected: - typedef TheISA::MachInst MachInst; + typedef SparcISA::MachInst MachInst; private: ThreadContext *tc; std::vector stack; diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index 76f0b5d04..b62efd3cd 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -105,8 +105,8 @@ using namespace X86ISA; M5_64_auxv_t::M5_64_auxv_t(int64_t type, int64_t val) { - a_type = TheISA::htog(type); - a_val = TheISA::htog(val); + a_type = X86ISA::htog(type); + a_val = X86ISA::htog(val); } X86LiveProcess::X86LiveProcess(LiveProcessParams * params, @@ -424,7 +424,7 @@ X86LiveProcess::argsInit(int intSize, int pageSize) // figure out argc uint64_t argc = argv.size(); - uint64_t guestArgc = TheISA::htog(argc); + uint64_t guestArgc = X86ISA::htog(argc); //Write out the sentry void * uint64_t sentry_NULL = 0; diff --git a/src/arch/x86/remote_gdb.cc b/src/arch/x86/remote_gdb.cc index 3a024e087..c416042c8 100644 --- a/src/arch/x86/remote_gdb.cc +++ b/src/arch/x86/remote_gdb.cc @@ -157,7 +157,7 @@ #include "cpu/thread_context.hh" using namespace std; -using namespace TheISA; +using namespace X86ISA; RemoteGDB::RemoteGDB(System *_system, ThreadContext *c) : BaseRemoteGDB(_system, c, NumGDBRegs) -- cgit v1.2.3 From 82f5723c7a8b245e1f60190a78b7fe383c2caf9b Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 27 Sep 2008 21:03:47 -0700 Subject: alpha: Clean up namespace usage. --- src/arch/alpha/ev5.cc | 367 +++++++++++++++++++++-------------------- src/arch/alpha/ev5.hh | 14 +- src/arch/alpha/faults.cc | 28 ++-- src/arch/alpha/faults.hh | 14 +- src/arch/alpha/idle_event.cc | 2 +- src/arch/alpha/interrupts.hh | 2 +- src/arch/alpha/intregfile.cc | 4 +- src/arch/alpha/isa/decoder.isa | 8 +- src/arch/alpha/isa/fp.isa | 4 +- src/arch/alpha/isa/main.isa | 6 +- src/arch/alpha/kernel_stats.cc | 6 +- src/arch/alpha/kernel_stats.hh | 4 +- src/arch/alpha/pagetable.hh | 6 +- src/arch/alpha/regfile.cc | 18 +- src/arch/alpha/remote_gdb.cc | 36 ++-- src/arch/alpha/stacktrace.cc | 16 +- src/arch/alpha/stacktrace.hh | 2 - src/arch/alpha/system.cc | 13 +- src/arch/alpha/tlb.cc | 2 +- src/arch/alpha/tlb.hh | 4 +- src/arch/alpha/utility.hh | 2 +- src/arch/alpha/vtophys.cc | 37 +++-- src/arch/alpha/vtophys.hh | 2 +- 23 files changed, 300 insertions(+), 297 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/ev5.cc b/src/arch/alpha/ev5.cc index 45d2ff5a5..166d42bc6 100644 --- a/src/arch/alpha/ev5.cc +++ b/src/arch/alpha/ev5.cc @@ -44,7 +44,7 @@ #include "sim/debug.hh" #include "sim/sim_exit.hh" -using namespace AlphaISA; +namespace AlphaISA { #if FULL_SYSTEM @@ -53,14 +53,14 @@ using namespace AlphaISA; // Machine dependent functions // void -AlphaISA::initCPU(ThreadContext *tc, int cpuId) +initCPU(ThreadContext *tc, int cpuId) { initIPRs(tc, cpuId); tc->setIntReg(16, cpuId); tc->setIntReg(0, cpuId); - AlphaISA::AlphaFault *reset = new AlphaISA::ResetFault; + AlphaFault *reset = new ResetFault; tc->setPC(tc->readMiscRegNoEffect(IPR_PAL_BASE) + reset->vect()); tc->setNextPC(tc->readPC() + sizeof(MachInst)); @@ -71,7 +71,7 @@ AlphaISA::initCPU(ThreadContext *tc, int cpuId) template void -AlphaISA::processInterrupts(CPU *cpu) +processInterrupts(CPU *cpu) { //Check if there are any outstanding interrupts //Handle the interrupts @@ -117,7 +117,7 @@ AlphaISA::processInterrupts(CPU *cpu) template void -AlphaISA::zeroRegisters(CPU *cpu) +zeroRegisters(CPU *cpu) { // Insure ISA semantics // (no longer very clean due to the change in setIntReg() in the @@ -126,33 +126,16 @@ AlphaISA::zeroRegisters(CPU *cpu) cpu->thread->setFloatReg(ZeroReg, 0.0); } -Fault -SimpleThread::hwrei() -{ - if (!(readPC() & 0x3)) - return new UnimplementedOpcodeFault; - - setNextPC(readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR)); - - if (!misspeculating()) { - if (kernelStats) - kernelStats->hwrei(); - } - - // FIXME: XXX check for interrupts? XXX - return NoFault; -} - int -AlphaISA::MiscRegFile::getInstAsid() +MiscRegFile::getInstAsid() { - return AlphaISA::ITB_ASN_ASN(ipr[IPR_ITB_ASN]); + return ITB_ASN_ASN(ipr[IPR_ITB_ASN]); } int -AlphaISA::MiscRegFile::getDataAsid() +MiscRegFile::getDataAsid() { - return AlphaISA::DTB_ASN_ASN(ipr[IPR_DTB_ASN]); + return DTB_ASN_ASN(ipr[IPR_DTB_ASN]); } #endif @@ -162,90 +145,90 @@ AlphaISA::MiscRegFile::getDataAsid() // // void -AlphaISA::initIPRs(ThreadContext *tc, int cpuId) +initIPRs(ThreadContext *tc, int cpuId) { for (int i = 0; i < NumInternalProcRegs; ++i) { tc->setMiscRegNoEffect(i, 0); } - tc->setMiscRegNoEffect(IPR_PAL_BASE, AlphaISA::PalBase); + tc->setMiscRegNoEffect(IPR_PAL_BASE, PalBase); tc->setMiscRegNoEffect(IPR_MCSR, 0x6); tc->setMiscRegNoEffect(IPR_PALtemp16, cpuId); } -AlphaISA::MiscReg -AlphaISA::MiscRegFile::readIpr(int idx, ThreadContext *tc) +MiscReg +MiscRegFile::readIpr(int idx, ThreadContext *tc) { uint64_t retval = 0; // return value, default 0 switch (idx) { - case AlphaISA::IPR_PALtemp0: - case AlphaISA::IPR_PALtemp1: - case AlphaISA::IPR_PALtemp2: - case AlphaISA::IPR_PALtemp3: - case AlphaISA::IPR_PALtemp4: - case AlphaISA::IPR_PALtemp5: - case AlphaISA::IPR_PALtemp6: - case AlphaISA::IPR_PALtemp7: - case AlphaISA::IPR_PALtemp8: - case AlphaISA::IPR_PALtemp9: - case AlphaISA::IPR_PALtemp10: - case AlphaISA::IPR_PALtemp11: - case AlphaISA::IPR_PALtemp12: - case AlphaISA::IPR_PALtemp13: - case AlphaISA::IPR_PALtemp14: - case AlphaISA::IPR_PALtemp15: - case AlphaISA::IPR_PALtemp16: - case AlphaISA::IPR_PALtemp17: - case AlphaISA::IPR_PALtemp18: - case AlphaISA::IPR_PALtemp19: - case AlphaISA::IPR_PALtemp20: - case AlphaISA::IPR_PALtemp21: - case AlphaISA::IPR_PALtemp22: - case AlphaISA::IPR_PALtemp23: - case AlphaISA::IPR_PAL_BASE: - - case AlphaISA::IPR_IVPTBR: - case AlphaISA::IPR_DC_MODE: - case AlphaISA::IPR_MAF_MODE: - case AlphaISA::IPR_ISR: - case AlphaISA::IPR_EXC_ADDR: - case AlphaISA::IPR_IC_PERR_STAT: - case AlphaISA::IPR_DC_PERR_STAT: - case AlphaISA::IPR_MCSR: - case AlphaISA::IPR_ASTRR: - case AlphaISA::IPR_ASTER: - case AlphaISA::IPR_SIRR: - case AlphaISA::IPR_ICSR: - case AlphaISA::IPR_ICM: - case AlphaISA::IPR_DTB_CM: - case AlphaISA::IPR_IPLR: - case AlphaISA::IPR_INTID: - case AlphaISA::IPR_PMCTR: + case IPR_PALtemp0: + case IPR_PALtemp1: + case IPR_PALtemp2: + case IPR_PALtemp3: + case IPR_PALtemp4: + case IPR_PALtemp5: + case IPR_PALtemp6: + case IPR_PALtemp7: + case IPR_PALtemp8: + case IPR_PALtemp9: + case IPR_PALtemp10: + case IPR_PALtemp11: + case IPR_PALtemp12: + case IPR_PALtemp13: + case IPR_PALtemp14: + case IPR_PALtemp15: + case IPR_PALtemp16: + case IPR_PALtemp17: + case IPR_PALtemp18: + case IPR_PALtemp19: + case IPR_PALtemp20: + case IPR_PALtemp21: + case IPR_PALtemp22: + case IPR_PALtemp23: + case IPR_PAL_BASE: + + case IPR_IVPTBR: + case IPR_DC_MODE: + case IPR_MAF_MODE: + case IPR_ISR: + case IPR_EXC_ADDR: + case IPR_IC_PERR_STAT: + case IPR_DC_PERR_STAT: + case IPR_MCSR: + case IPR_ASTRR: + case IPR_ASTER: + case IPR_SIRR: + case IPR_ICSR: + case IPR_ICM: + case IPR_DTB_CM: + case IPR_IPLR: + case IPR_INTID: + case IPR_PMCTR: // no side-effect retval = ipr[idx]; break; - case AlphaISA::IPR_CC: + case IPR_CC: retval |= ipr[idx] & ULL(0xffffffff00000000); retval |= tc->getCpuPtr()->curCycle() & ULL(0x00000000ffffffff); break; - case AlphaISA::IPR_VA: + case IPR_VA: retval = ipr[idx]; break; - case AlphaISA::IPR_VA_FORM: - case AlphaISA::IPR_MM_STAT: - case AlphaISA::IPR_IFAULT_VA_FORM: - case AlphaISA::IPR_EXC_MASK: - case AlphaISA::IPR_EXC_SUM: + case IPR_VA_FORM: + case IPR_MM_STAT: + case IPR_IFAULT_VA_FORM: + case IPR_EXC_MASK: + case IPR_EXC_SUM: retval = ipr[idx]; break; - case AlphaISA::IPR_DTB_PTE: + case IPR_DTB_PTE: { - AlphaISA::TlbEntry &entry + TlbEntry &entry = tc->getDTBPtr()->index(!tc->misspeculating()); retval |= ((uint64_t)entry.ppn & ULL(0x7ffffff)) << 32; @@ -259,15 +242,15 @@ AlphaISA::MiscRegFile::readIpr(int idx, ThreadContext *tc) break; // write only registers - case AlphaISA::IPR_HWINT_CLR: - case AlphaISA::IPR_SL_XMIT: - case AlphaISA::IPR_DC_FLUSH: - case AlphaISA::IPR_IC_FLUSH: - case AlphaISA::IPR_ALT_MODE: - case AlphaISA::IPR_DTB_IA: - case AlphaISA::IPR_DTB_IAP: - case AlphaISA::IPR_ITB_IA: - case AlphaISA::IPR_ITB_IAP: + case IPR_HWINT_CLR: + case IPR_SL_XMIT: + case IPR_DC_FLUSH: + case IPR_IC_FLUSH: + case IPR_ALT_MODE: + case IPR_DTB_IA: + case IPR_DTB_IAP: + case IPR_ITB_IA: + case IPR_ITB_IAP: panic("Tried to read write only register %d\n", idx); break; @@ -286,7 +269,7 @@ int break_ipl = -1; #endif void -AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc) +MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc) { uint64_t old; @@ -294,52 +277,52 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc) return; switch (idx) { - case AlphaISA::IPR_PALtemp0: - case AlphaISA::IPR_PALtemp1: - case AlphaISA::IPR_PALtemp2: - case AlphaISA::IPR_PALtemp3: - case AlphaISA::IPR_PALtemp4: - case AlphaISA::IPR_PALtemp5: - case AlphaISA::IPR_PALtemp6: - case AlphaISA::IPR_PALtemp7: - case AlphaISA::IPR_PALtemp8: - case AlphaISA::IPR_PALtemp9: - case AlphaISA::IPR_PALtemp10: - case AlphaISA::IPR_PALtemp11: - case AlphaISA::IPR_PALtemp12: - case AlphaISA::IPR_PALtemp13: - case AlphaISA::IPR_PALtemp14: - case AlphaISA::IPR_PALtemp15: - case AlphaISA::IPR_PALtemp16: - case AlphaISA::IPR_PALtemp17: - case AlphaISA::IPR_PALtemp18: - case AlphaISA::IPR_PALtemp19: - case AlphaISA::IPR_PALtemp20: - case AlphaISA::IPR_PALtemp21: - case AlphaISA::IPR_PALtemp22: - case AlphaISA::IPR_PAL_BASE: - case AlphaISA::IPR_IC_PERR_STAT: - case AlphaISA::IPR_DC_PERR_STAT: - case AlphaISA::IPR_PMCTR: + case IPR_PALtemp0: + case IPR_PALtemp1: + case IPR_PALtemp2: + case IPR_PALtemp3: + case IPR_PALtemp4: + case IPR_PALtemp5: + case IPR_PALtemp6: + case IPR_PALtemp7: + case IPR_PALtemp8: + case IPR_PALtemp9: + case IPR_PALtemp10: + case IPR_PALtemp11: + case IPR_PALtemp12: + case IPR_PALtemp13: + case IPR_PALtemp14: + case IPR_PALtemp15: + case IPR_PALtemp16: + case IPR_PALtemp17: + case IPR_PALtemp18: + case IPR_PALtemp19: + case IPR_PALtemp20: + case IPR_PALtemp21: + case IPR_PALtemp22: + case IPR_PAL_BASE: + case IPR_IC_PERR_STAT: + case IPR_DC_PERR_STAT: + case IPR_PMCTR: // write entire quad w/ no side-effect ipr[idx] = val; break; - case AlphaISA::IPR_CC_CTL: + case IPR_CC_CTL: // This IPR resets the cycle counter. We assume this only // happens once... let's verify that. assert(ipr[idx] == 0); ipr[idx] = 1; break; - case AlphaISA::IPR_CC: + case IPR_CC: // This IPR only writes the upper 64 bits. It's ok to write // all 64 here since we mask out the lower 32 in rpcc (see // isa_desc). ipr[idx] = val; break; - case AlphaISA::IPR_PALtemp23: + case IPR_PALtemp23: // write entire quad w/ no side-effect old = ipr[idx]; ipr[idx] = val; @@ -349,23 +332,23 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc) #endif break; - case AlphaISA::IPR_DTB_PTE: + case IPR_DTB_PTE: // write entire quad w/ no side-effect, tag is forthcoming ipr[idx] = val; break; - case AlphaISA::IPR_EXC_ADDR: + case IPR_EXC_ADDR: // second least significant bit in PC is always zero ipr[idx] = val & ~2; break; - case AlphaISA::IPR_ASTRR: - case AlphaISA::IPR_ASTER: + case IPR_ASTRR: + case IPR_ASTER: // only write least significant four bits - privilege mask ipr[idx] = val & 0xf; break; - case AlphaISA::IPR_IPLR: + case IPR_IPLR: #ifdef DEBUG if (break_ipl != -1 && break_ipl == (val & 0x1f)) debug_break(); @@ -379,175 +362,175 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc) #endif break; - case AlphaISA::IPR_DTB_CM: + case IPR_DTB_CM: #if FULL_SYSTEM if (val & 0x18) { if (tc->getKernelStats()) - tc->getKernelStats()->mode(AlphaISA::Kernel::user, tc); + tc->getKernelStats()->mode(Kernel::user, tc); } else { if (tc->getKernelStats()) - tc->getKernelStats()->mode(AlphaISA::Kernel::kernel, tc); + tc->getKernelStats()->mode(Kernel::kernel, tc); } #endif - case AlphaISA::IPR_ICM: + case IPR_ICM: // only write two mode bits - processor mode ipr[idx] = val & 0x18; break; - case AlphaISA::IPR_ALT_MODE: + case IPR_ALT_MODE: // only write two mode bits - processor mode ipr[idx] = val & 0x18; break; - case AlphaISA::IPR_MCSR: + case IPR_MCSR: // more here after optimization... ipr[idx] = val; break; - case AlphaISA::IPR_SIRR: + case IPR_SIRR: // only write software interrupt mask ipr[idx] = val & 0x7fff0; break; - case AlphaISA::IPR_ICSR: + case IPR_ICSR: ipr[idx] = val & ULL(0xffffff0300); break; - case AlphaISA::IPR_IVPTBR: - case AlphaISA::IPR_MVPTBR: + case IPR_IVPTBR: + case IPR_MVPTBR: ipr[idx] = val & ULL(0xffffffffc0000000); break; - case AlphaISA::IPR_DC_TEST_CTL: + case IPR_DC_TEST_CTL: ipr[idx] = val & 0x1ffb; break; - case AlphaISA::IPR_DC_MODE: - case AlphaISA::IPR_MAF_MODE: + case IPR_DC_MODE: + case IPR_MAF_MODE: ipr[idx] = val & 0x3f; break; - case AlphaISA::IPR_ITB_ASN: + case IPR_ITB_ASN: ipr[idx] = val & 0x7f0; break; - case AlphaISA::IPR_DTB_ASN: + case IPR_DTB_ASN: ipr[idx] = val & ULL(0xfe00000000000000); break; - case AlphaISA::IPR_EXC_SUM: - case AlphaISA::IPR_EXC_MASK: + case IPR_EXC_SUM: + case IPR_EXC_MASK: // any write to this register clears it ipr[idx] = 0; break; - case AlphaISA::IPR_INTID: - case AlphaISA::IPR_SL_RCV: - case AlphaISA::IPR_MM_STAT: - case AlphaISA::IPR_ITB_PTE_TEMP: - case AlphaISA::IPR_DTB_PTE_TEMP: + case IPR_INTID: + case IPR_SL_RCV: + case IPR_MM_STAT: + case IPR_ITB_PTE_TEMP: + case IPR_DTB_PTE_TEMP: // read-only registers panic("Tried to write read only ipr %d\n", idx); - case AlphaISA::IPR_HWINT_CLR: - case AlphaISA::IPR_SL_XMIT: - case AlphaISA::IPR_DC_FLUSH: - case AlphaISA::IPR_IC_FLUSH: + case IPR_HWINT_CLR: + case IPR_SL_XMIT: + case IPR_DC_FLUSH: + case IPR_IC_FLUSH: // the following are write only ipr[idx] = val; break; - case AlphaISA::IPR_DTB_IA: + case IPR_DTB_IA: // really a control write ipr[idx] = 0; tc->getDTBPtr()->flushAll(); break; - case AlphaISA::IPR_DTB_IAP: + case IPR_DTB_IAP: // really a control write ipr[idx] = 0; tc->getDTBPtr()->flushProcesses(); break; - case AlphaISA::IPR_DTB_IS: + case IPR_DTB_IS: // really a control write ipr[idx] = val; tc->getDTBPtr()->flushAddr(val, - AlphaISA::DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN])); + DTB_ASN_ASN(ipr[IPR_DTB_ASN])); break; - case AlphaISA::IPR_DTB_TAG: { - struct AlphaISA::TlbEntry entry; + case IPR_DTB_TAG: { + struct TlbEntry entry; // FIXME: granularity hints NYI... - if (AlphaISA::DTB_PTE_GH(ipr[AlphaISA::IPR_DTB_PTE]) != 0) + if (DTB_PTE_GH(ipr[IPR_DTB_PTE]) != 0) panic("PTE GH field != 0"); // write entire quad ipr[idx] = val; // construct PTE for new entry - entry.ppn = AlphaISA::DTB_PTE_PPN(ipr[AlphaISA::IPR_DTB_PTE]); - entry.xre = AlphaISA::DTB_PTE_XRE(ipr[AlphaISA::IPR_DTB_PTE]); - entry.xwe = AlphaISA::DTB_PTE_XWE(ipr[AlphaISA::IPR_DTB_PTE]); - entry.fonr = AlphaISA::DTB_PTE_FONR(ipr[AlphaISA::IPR_DTB_PTE]); - entry.fonw = AlphaISA::DTB_PTE_FONW(ipr[AlphaISA::IPR_DTB_PTE]); - entry.asma = AlphaISA::DTB_PTE_ASMA(ipr[AlphaISA::IPR_DTB_PTE]); - entry.asn = AlphaISA::DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]); + entry.ppn = DTB_PTE_PPN(ipr[IPR_DTB_PTE]); + entry.xre = DTB_PTE_XRE(ipr[IPR_DTB_PTE]); + entry.xwe = DTB_PTE_XWE(ipr[IPR_DTB_PTE]); + entry.fonr = DTB_PTE_FONR(ipr[IPR_DTB_PTE]); + entry.fonw = DTB_PTE_FONW(ipr[IPR_DTB_PTE]); + entry.asma = DTB_PTE_ASMA(ipr[IPR_DTB_PTE]); + entry.asn = DTB_ASN_ASN(ipr[IPR_DTB_ASN]); // insert new TAG/PTE value into data TLB tc->getDTBPtr()->insert(val, entry); } break; - case AlphaISA::IPR_ITB_PTE: { - struct AlphaISA::TlbEntry entry; + case IPR_ITB_PTE: { + struct TlbEntry entry; // FIXME: granularity hints NYI... - if (AlphaISA::ITB_PTE_GH(val) != 0) + if (ITB_PTE_GH(val) != 0) panic("PTE GH field != 0"); // write entire quad ipr[idx] = val; // construct PTE for new entry - entry.ppn = AlphaISA::ITB_PTE_PPN(val); - entry.xre = AlphaISA::ITB_PTE_XRE(val); + entry.ppn = ITB_PTE_PPN(val); + entry.xre = ITB_PTE_XRE(val); entry.xwe = 0; - entry.fonr = AlphaISA::ITB_PTE_FONR(val); - entry.fonw = AlphaISA::ITB_PTE_FONW(val); - entry.asma = AlphaISA::ITB_PTE_ASMA(val); - entry.asn = AlphaISA::ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]); + entry.fonr = ITB_PTE_FONR(val); + entry.fonw = ITB_PTE_FONW(val); + entry.asma = ITB_PTE_ASMA(val); + entry.asn = ITB_ASN_ASN(ipr[IPR_ITB_ASN]); // insert new TAG/PTE value into data TLB - tc->getITBPtr()->insert(ipr[AlphaISA::IPR_ITB_TAG], entry); + tc->getITBPtr()->insert(ipr[IPR_ITB_TAG], entry); } break; - case AlphaISA::IPR_ITB_IA: + case IPR_ITB_IA: // really a control write ipr[idx] = 0; tc->getITBPtr()->flushAll(); break; - case AlphaISA::IPR_ITB_IAP: + case IPR_ITB_IAP: // really a control write ipr[idx] = 0; tc->getITBPtr()->flushProcesses(); break; - case AlphaISA::IPR_ITB_IS: + case IPR_ITB_IS: // really a control write ipr[idx] = val; tc->getITBPtr()->flushAddr(val, - AlphaISA::ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN])); + ITB_ASN_ASN(ipr[IPR_ITB_ASN])); break; default: @@ -560,14 +543,34 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc) void -AlphaISA::copyIprs(ThreadContext *src, ThreadContext *dest) +copyIprs(ThreadContext *src, ThreadContext *dest) { for (int i = 0; i < NumInternalProcRegs; ++i) { dest->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i)); } } +} // namespace AlphaISA + #if FULL_SYSTEM +using namespace AlphaISA; + +Fault +SimpleThread::hwrei() +{ + if (!(readPC() & 0x3)) + return new UnimplementedOpcodeFault; + + setNextPC(readMiscRegNoEffect(IPR_EXC_ADDR)); + + if (!misspeculating()) { + if (kernelStats) + kernelStats->hwrei(); + } + + // FIXME: XXX check for interrupts? XXX + return NoFault; +} /** * Check for special simulator handling of specific PAL calls. diff --git a/src/arch/alpha/ev5.hh b/src/arch/alpha/ev5.hh index 4fe5f1b71..a40ca6749 100644 --- a/src/arch/alpha/ev5.hh +++ b/src/arch/alpha/ev5.hh @@ -48,8 +48,8 @@ const int VAddrImplBits = 43; const Addr VAddrImplMask = (ULL(1) << VAddrImplBits) - 1; const Addr VAddrUnImplMask = ~VAddrImplMask; inline Addr VAddrImpl(Addr a) { return a & VAddrImplMask; } -inline Addr VAddrVPN(Addr a) { return a >> AlphaISA::PageShift; } -inline Addr VAddrOffset(Addr a) { return a & AlphaISA::PageOffset; } +inline Addr VAddrVPN(Addr a) { return a >> PageShift; } +inline Addr VAddrOffset(Addr a) { return a & PageOffset; } inline Addr VAddrSpaceEV5(Addr a) { return a >> 41 & 0x3; } inline Addr VAddrSpaceEV6(Addr a) { return a >> 41 & 0x7f; } @@ -73,12 +73,12 @@ inline Addr Phys2K0Seg(Addr addr) addr |= PAddrUncachedBit40; } #endif - return addr | AlphaISA::K0SegBase; + return addr | K0SegBase; } inline int DTB_ASN_ASN(uint64_t reg) { return reg >> 57 & AsnMask; } inline Addr DTB_PTE_PPN(uint64_t reg) -{ return reg >> 32 & (ULL(1) << PAddrImplBits - AlphaISA::PageShift) - 1; } +{ return reg >> 32 & (ULL(1) << PAddrImplBits - PageShift) - 1; } inline int DTB_PTE_XRE(uint64_t reg) { return reg >> 8 & 0xf; } inline int DTB_PTE_XWE(uint64_t reg) { return reg >> 12 & 0xf; } inline int DTB_PTE_FONR(uint64_t reg) { return reg >> 1 & 0x1; } @@ -88,7 +88,7 @@ inline int DTB_PTE_ASMA(uint64_t reg) { return reg >> 4 & 0x1; } inline int ITB_ASN_ASN(uint64_t reg) { return reg >> 4 & AsnMask; } inline Addr ITB_PTE_PPN(uint64_t reg) -{ return reg >> 32 & (ULL(1) << PAddrImplBits - AlphaISA::PageShift) - 1; } +{ return reg >> 32 & (ULL(1) << PAddrImplBits - PageShift) - 1; } inline int ITB_PTE_XRE(uint64_t reg) { return reg >> 8 & 0xf; } inline bool ITB_PTE_FONR(uint64_t reg) { return reg >> 1 & 0x1; } inline bool ITB_PTE_FONW(uint64_t reg) { return reg >> 2 & 0x1; } @@ -111,8 +111,8 @@ const uint64_t MM_STAT_FONW_MASK = ULL(0x0008); const uint64_t MM_STAT_FONR_MASK = ULL(0x0004); const uint64_t MM_STAT_ACV_MASK = ULL(0x0002); const uint64_t MM_STAT_WR_MASK = ULL(0x0001); -inline int Opcode(AlphaISA::MachInst inst) { return inst >> 26 & 0x3f; } -inline int Ra(AlphaISA::MachInst inst) { return inst >> 21 & 0x1f; } +inline int Opcode(MachInst inst) { return inst >> 26 & 0x3f; } +inline int Ra(MachInst inst) { return inst >> 21 & 0x1f; } const Addr PalBase = 0x4000; const Addr PalMax = 0x10000; diff --git a/src/arch/alpha/faults.cc b/src/arch/alpha/faults.cc index 7417ada5f..845ac0288 100644 --- a/src/arch/alpha/faults.cc +++ b/src/arch/alpha/faults.cc @@ -116,15 +116,15 @@ void AlphaFault::invoke(ThreadContext * tc) // exception restart address if (setRestartAddress() || !(tc->readPC() & 0x3)) - tc->setMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR, tc->readPC()); + tc->setMiscRegNoEffect(IPR_EXC_ADDR, tc->readPC()); if (skipFaultingInstruction()) { // traps... skip faulting instruction. - tc->setMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR, - tc->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR) + 4); + tc->setMiscRegNoEffect(IPR_EXC_ADDR, + tc->readMiscRegNoEffect(IPR_EXC_ADDR) + 4); } - tc->setPC(tc->readMiscRegNoEffect(AlphaISA::IPR_PAL_BASE) + vect()); + tc->setPC(tc->readMiscRegNoEffect(IPR_PAL_BASE) + vect()); tc->setNextPC(tc->readPC() + sizeof(MachInst)); } @@ -144,17 +144,17 @@ void DtbFault::invoke(ThreadContext * tc) if (!tc->misspeculating() && !(reqFlags & VPTE) && !(reqFlags & NO_FAULT)) { // set VA register with faulting address - tc->setMiscRegNoEffect(AlphaISA::IPR_VA, vaddr); + tc->setMiscRegNoEffect(IPR_VA, vaddr); // set MM_STAT register flags - tc->setMiscRegNoEffect(AlphaISA::IPR_MM_STAT, - (((AlphaISA::Opcode(tc->getInst()) & 0x3f) << 11) - | ((AlphaISA::Ra(tc->getInst()) & 0x1f) << 6) + tc->setMiscRegNoEffect(IPR_MM_STAT, + (((Opcode(tc->getInst()) & 0x3f) << 11) + | ((Ra(tc->getInst()) & 0x1f) << 6) | (flags & 0x3f))); // set VA_FORM register with faulting formatted address - tc->setMiscRegNoEffect(AlphaISA::IPR_VA_FORM, - tc->readMiscRegNoEffect(AlphaISA::IPR_MVPTBR) | (vaddr.vpn() << 3)); + tc->setMiscRegNoEffect(IPR_VA_FORM, + tc->readMiscRegNoEffect(IPR_MVPTBR) | (vaddr.vpn() << 3)); } AlphaFault::invoke(tc); @@ -163,10 +163,10 @@ void DtbFault::invoke(ThreadContext * tc) void ItbFault::invoke(ThreadContext * tc) { if (!tc->misspeculating()) { - tc->setMiscRegNoEffect(AlphaISA::IPR_ITB_TAG, pc); - tc->setMiscRegNoEffect(AlphaISA::IPR_IFAULT_VA_FORM, - tc->readMiscRegNoEffect(AlphaISA::IPR_IVPTBR) | - (AlphaISA::VAddr(pc).vpn() << 3)); + tc->setMiscRegNoEffect(IPR_ITB_TAG, pc); + tc->setMiscRegNoEffect(IPR_IFAULT_VA_FORM, + tc->readMiscRegNoEffect(IPR_IVPTBR) | + (VAddr(pc).vpn() << 3)); } AlphaFault::invoke(tc); diff --git a/src/arch/alpha/faults.hh b/src/arch/alpha/faults.hh index 74699b2b5..1d2ac593a 100644 --- a/src/arch/alpha/faults.hh +++ b/src/arch/alpha/faults.hh @@ -134,11 +134,11 @@ class InterruptFault : public AlphaFault class DtbFault : public AlphaFault { protected: - AlphaISA::VAddr vaddr; + VAddr vaddr; uint32_t reqFlags; uint64_t flags; public: - DtbFault(AlphaISA::VAddr _vaddr, uint32_t _reqFlags, uint64_t _flags) + DtbFault(VAddr _vaddr, uint32_t _reqFlags, uint64_t _flags) : vaddr(_vaddr), reqFlags(_reqFlags), flags(_flags) { } FaultName name() const = 0; @@ -156,7 +156,7 @@ class NDtbMissFault : public DtbFault static FaultVect _vect; static FaultStat _count; public: - NDtbMissFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags) + NDtbMissFault(VAddr vaddr, uint32_t reqFlags, uint64_t flags) : DtbFault(vaddr, reqFlags, flags) { } FaultName name() const {return _name;} @@ -174,7 +174,7 @@ class PDtbMissFault : public DtbFault static FaultVect _vect; static FaultStat _count; public: - PDtbMissFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags) + PDtbMissFault(VAddr vaddr, uint32_t reqFlags, uint64_t flags) : DtbFault(vaddr, reqFlags, flags) { } FaultName name() const {return _name;} @@ -189,7 +189,7 @@ class DtbPageFault : public DtbFault static FaultVect _vect; static FaultStat _count; public: - DtbPageFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags) + DtbPageFault(VAddr vaddr, uint32_t reqFlags, uint64_t flags) : DtbFault(vaddr, reqFlags, flags) { } FaultName name() const {return _name;} @@ -204,7 +204,7 @@ class DtbAcvFault : public DtbFault static FaultVect _vect; static FaultStat _count; public: - DtbAcvFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags) + DtbAcvFault(VAddr vaddr, uint32_t reqFlags, uint64_t flags) : DtbFault(vaddr, reqFlags, flags) { } FaultName name() const {return _name;} @@ -219,7 +219,7 @@ class DtbAlignmentFault : public DtbFault static FaultVect _vect; static FaultStat _count; public: - DtbAlignmentFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags) + DtbAlignmentFault(VAddr vaddr, uint32_t reqFlags, uint64_t flags) : DtbFault(vaddr, reqFlags, flags) { } FaultName name() const {return _name;} diff --git a/src/arch/alpha/idle_event.cc b/src/arch/alpha/idle_event.cc index d3807a48d..337166aec 100644 --- a/src/arch/alpha/idle_event.cc +++ b/src/arch/alpha/idle_event.cc @@ -40,6 +40,6 @@ IdleStartEvent::process(ThreadContext *tc) { if (tc->getKernelStats()) tc->getKernelStats()->setIdleProcess( - tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp23), tc); + tc->readMiscRegNoEffect(IPR_PALtemp23), tc); remove(); } diff --git a/src/arch/alpha/interrupts.hh b/src/arch/alpha/interrupts.hh index 1d8ba736f..abfecfb5b 100644 --- a/src/arch/alpha/interrupts.hh +++ b/src/arch/alpha/interrupts.hh @@ -78,7 +78,7 @@ class Interrupts { DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); - if (int_num < 0 || int_num >= AlphaISA::NumInterruptLevels) + if (int_num < 0 || int_num >= NumInterruptLevels) panic("int_num out of bounds\n"); if (index < 0 || index >= (int)sizeof(uint64_t) * 8) diff --git a/src/arch/alpha/intregfile.cc b/src/arch/alpha/intregfile.cc index 0188cb2cd..d1dfc5168 100644 --- a/src/arch/alpha/intregfile.cc +++ b/src/arch/alpha/intregfile.cc @@ -37,13 +37,13 @@ namespace AlphaISA { #if FULL_SYSTEM - const int reg_redir[AlphaISA::NumIntRegs] = { + const int reg_redir[NumIntRegs] = { /* 0 */ 0, 1, 2, 3, 4, 5, 6, 7, /* 8 */ 32, 33, 34, 35, 36, 37, 38, 15, /* 16 */ 16, 17, 18, 19, 20, 21, 22, 23, /* 24 */ 24, 39, 26, 27, 28, 29, 30, 31 }; #else - const int reg_redir[AlphaISA::NumIntRegs] = { + const int reg_redir[NumIntRegs] = { /* 0 */ 0, 1, 2, 3, 4, 5, 6, 7, /* 8 */ 8, 9, 10, 11, 12, 13, 14, 15, /* 16 */ 16, 17, 18, 19, 20, 21, 22, 23, diff --git a/src/arch/alpha/isa/decoder.isa b/src/arch/alpha/isa/decoder.isa index dc30039b2..270940df2 100644 --- a/src/arch/alpha/isa/decoder.isa +++ b/src/arch/alpha/isa/decoder.isa @@ -638,7 +638,7 @@ decode OPCODE default Unknown::unknown() { /* Rb is a fake dependency so here is a fun way to get * the parser to understand that. */ - Ra = xc->readMiscReg(AlphaISA::IPR_CC) + (Rb & 0); + Ra = xc->readMiscReg(IPR_CC) + (Rb & 0); #else Ra = curTick; @@ -690,7 +690,7 @@ decode OPCODE default Unknown::unknown() { 0x00: CallPal::call_pal({{ if (!palValid || (palPriv - && xc->readMiscReg(AlphaISA::IPR_ICM) != AlphaISA::mode_kernel)) { + && xc->readMiscReg(IPR_ICM) != mode_kernel)) { // invalid pal function code, or attempt to do privileged // PAL call in non-kernel mode fault = new UnimplementedOpcodeFault; @@ -701,8 +701,8 @@ decode OPCODE default Unknown::unknown() { bool dopal = xc->simPalCheck(palFunc); if (dopal) { - xc->setMiscReg(AlphaISA::IPR_EXC_ADDR, NPC); - NPC = xc->readMiscReg(AlphaISA::IPR_PAL_BASE) + palOffset; + xc->setMiscReg(IPR_EXC_ADDR, NPC); + NPC = xc->readMiscReg(IPR_PAL_BASE) + palOffset; } } }}, IsNonSpeculative); diff --git a/src/arch/alpha/isa/fp.isa b/src/arch/alpha/isa/fp.isa index 8b13f8dd7..ed04d2a50 100644 --- a/src/arch/alpha/isa/fp.isa +++ b/src/arch/alpha/isa/fp.isa @@ -46,7 +46,7 @@ output exec {{ inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) { Fault fault = NoFault; // dummy... this ipr access should not fault - if (!AlphaISA::ICSR_FPE(xc->readMiscReg(AlphaISA::IPR_ICSR))) { + if (!ICSR_FPE(xc->readMiscReg(IPR_ICSR))) { fault = new FloatEnableFault; } return fault; @@ -229,7 +229,7 @@ def template FloatingPointExecute {{ %(code)s; } else { m5_fesetround(getC99RoundingMode( - xc->readMiscRegNoEffect(AlphaISA::MISCREG_FPCR))); + xc->readMiscRegNoEffect(MISCREG_FPCR))); %(code)s; m5_fesetround(M5_FE_TONEAREST); } diff --git a/src/arch/alpha/isa/main.isa b/src/arch/alpha/isa/main.isa index d72dfe34a..5231712c8 100644 --- a/src/arch/alpha/isa/main.isa +++ b/src/arch/alpha/isa/main.isa @@ -173,11 +173,11 @@ def operands {{ # Int regs default to unsigned, but code should not count on this. # For clarity, descriptions that depend on unsigned behavior should # explicitly specify '.uq'. - 'Ra': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RA] : RA', + 'Ra': ('IntReg', 'uq', 'PALMODE ? reg_redir[RA] : RA', 'IsInteger', 1), - 'Rb': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RB] : RB', + 'Rb': ('IntReg', 'uq', 'PALMODE ? reg_redir[RB] : RB', 'IsInteger', 2), - 'Rc': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RC] : RC', + 'Rc': ('IntReg', 'uq', 'PALMODE ? reg_redir[RC] : RC', 'IsInteger', 3), 'Fa': ('FloatReg', 'df', 'FA', 'IsFloating', 1), 'Fb': ('FloatReg', 'df', 'FB', 'IsFloating', 2), diff --git a/src/arch/alpha/kernel_stats.cc b/src/arch/alpha/kernel_stats.cc index a004d5f25..6e9dc1611 100644 --- a/src/arch/alpha/kernel_stats.cc +++ b/src/arch/alpha/kernel_stats.cc @@ -152,7 +152,7 @@ Statistics::changeMode(cpu_mode newmode, ThreadContext *tc) void Statistics::mode(cpu_mode newmode, ThreadContext *tc) { - Addr pcbb = tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp23); + Addr pcbb = tc->readMiscRegNoEffect(IPR_PALtemp23); if (newmode == kernel && pcbb == idleProcess) newmode = idle; @@ -213,5 +213,5 @@ Statistics::unserialize(Checkpoint *cp, const string §ion) themode = (cpu_mode)exemode; } -} /* end namespace AlphaISA::Kernel */ -} /* end namespace AlphaISA */ +} // namespace Kernel +} // namespace AlphaISA diff --git a/src/arch/alpha/kernel_stats.hh b/src/arch/alpha/kernel_stats.hh index 7b8640ad7..aab96b150 100644 --- a/src/arch/alpha/kernel_stats.hh +++ b/src/arch/alpha/kernel_stats.hh @@ -90,7 +90,7 @@ class Statistics : public ::Kernel::Statistics void unserialize(Checkpoint *cp, const std::string §ion); }; -} /* end namespace AlphaISA::Kernel */ -} /* end namespace AlphaISA */ +} // namespace Kernel +} // namespace AlphaISA #endif // __ARCH_ALPHA_KERNEL_STATS_HH__ diff --git a/src/arch/alpha/pagetable.hh b/src/arch/alpha/pagetable.hh index f28c1b195..b0689dce0 100644 --- a/src/arch/alpha/pagetable.hh +++ b/src/arch/alpha/pagetable.hh @@ -54,11 +54,11 @@ namespace AlphaISA { Addr offset() const { return addr & PageOffset; } Addr level3() const - { return AlphaISA::PteAddr(addr >> PageShift); } + { return PteAddr(addr >> PageShift); } Addr level2() const - { return AlphaISA::PteAddr(addr >> NPtePageShift + PageShift); } + { return PteAddr(addr >> NPtePageShift + PageShift); } Addr level1() const - { return AlphaISA::PteAddr(addr >> 2 * NPtePageShift + PageShift); } + { return PteAddr(addr >> 2 * NPtePageShift + PageShift); } }; struct PageTableEntry diff --git a/src/arch/alpha/regfile.cc b/src/arch/alpha/regfile.cc index 3faa189ca..e617b00ae 100644 --- a/src/arch/alpha/regfile.cc +++ b/src/arch/alpha/regfile.cc @@ -70,7 +70,7 @@ namespace AlphaISA } // Then loop through the floating point registers. - for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) { + for (int i = 0; i < NumFloatRegs; ++i) { dest->setFloatRegBits(i, src->readFloatRegBits(i)); } @@ -85,14 +85,14 @@ namespace AlphaISA void copyMiscRegs(ThreadContext *src, ThreadContext *dest) { - dest->setMiscRegNoEffect(AlphaISA::MISCREG_FPCR, - src->readMiscRegNoEffect(AlphaISA::MISCREG_FPCR)); - dest->setMiscRegNoEffect(AlphaISA::MISCREG_UNIQ, - src->readMiscRegNoEffect(AlphaISA::MISCREG_UNIQ)); - dest->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, - src->readMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG)); - dest->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKADDR, - src->readMiscRegNoEffect(AlphaISA::MISCREG_LOCKADDR)); + dest->setMiscRegNoEffect(MISCREG_FPCR, + src->readMiscRegNoEffect(MISCREG_FPCR)); + dest->setMiscRegNoEffect(MISCREG_UNIQ, + src->readMiscRegNoEffect(MISCREG_UNIQ)); + dest->setMiscRegNoEffect(MISCREG_LOCKFLAG, + src->readMiscRegNoEffect(MISCREG_LOCKFLAG)); + dest->setMiscRegNoEffect(MISCREG_LOCKADDR, + src->readMiscRegNoEffect(MISCREG_LOCKADDR)); copyIprs(src, dest); } diff --git a/src/arch/alpha/remote_gdb.cc b/src/arch/alpha/remote_gdb.cc index a40d06f18..22a1f5224 100644 --- a/src/arch/alpha/remote_gdb.cc +++ b/src/arch/alpha/remote_gdb.cc @@ -161,12 +161,12 @@ RemoteGDB::acc(Addr va, size_t len) #else Addr last_va; - va = AlphaISA::TruncPage(va); - last_va = AlphaISA::RoundPage(va + len); + va = TruncPage(va); + last_va = RoundPage(va + len); do { - if (AlphaISA::IsK0Seg(va)) { - if (va < (AlphaISA::K0SegBase + pmem->size())) { + if (IsK0Seg(va)) { + if (va < (K0SegBase + pmem->size())) { DPRINTF(GDBAcc, "acc: Mapping is valid K0SEG <= " "%#x < K0SEG + size\n", va); return true; @@ -184,16 +184,16 @@ RemoteGDB::acc(Addr va, size_t len) * but there is no easy way to do it. */ - if (AlphaISA::PcPAL(va) || va < 0x10000) + if (PcPAL(va) || va < 0x10000) return true; - Addr ptbr = context->readMiscRegNoEffect(AlphaISA::IPR_PALtemp20); - AlphaISA::PageTableEntry pte = AlphaISA::kernel_pte_lookup(context->getPhysPort(), ptbr, va); + Addr ptbr = context->readMiscRegNoEffect(IPR_PALtemp20); + PageTableEntry pte = kernel_pte_lookup(context->getPhysPort(), ptbr, va); if (!pte.valid()) { DPRINTF(GDBAcc, "acc: %#x pte is invalid\n", va); return false; } - va += AlphaISA::PageBytes; + va += PageBytes; } while (va < last_va); DPRINTF(GDBAcc, "acc: %#x mapping is valid\n", va); @@ -214,18 +214,18 @@ RemoteGDB::getregs() gdbregs.regs[KGDB_REG_PC] = context->readPC(); // @todo: Currently this is very Alpha specific. - if (AlphaISA::PcPAL(gdbregs.regs[KGDB_REG_PC])) { - for (int i = 0; i < AlphaISA::NumIntArchRegs; ++i) { - gdbregs.regs[i] = context->readIntReg(AlphaISA::reg_redir[i]); + if (PcPAL(gdbregs.regs[KGDB_REG_PC])) { + for (int i = 0; i < NumIntArchRegs; ++i) { + gdbregs.regs[i] = context->readIntReg(reg_redir[i]); } } else { - for (int i = 0; i < AlphaISA::NumIntArchRegs; ++i) { + for (int i = 0; i < NumIntArchRegs; ++i) { gdbregs.regs[i] = context->readIntReg(i); } } #ifdef KGDB_FP_REGS - for (int i = 0; i < AlphaISA::NumFloatArchRegs; ++i) { + for (int i = 0; i < NumFloatArchRegs; ++i) { gdbregs.regs[i + KGDB_REG_F0] = context->readFloatRegBits(i); } #endif @@ -241,18 +241,18 @@ void RemoteGDB::setregs() { // @todo: Currently this is very Alpha specific. - if (AlphaISA::PcPAL(gdbregs.regs[KGDB_REG_PC])) { - for (int i = 0; i < AlphaISA::NumIntArchRegs; ++i) { - context->setIntReg(AlphaISA::reg_redir[i], gdbregs.regs[i]); + if (PcPAL(gdbregs.regs[KGDB_REG_PC])) { + for (int i = 0; i < NumIntArchRegs; ++i) { + context->setIntReg(reg_redir[i], gdbregs.regs[i]); } } else { - for (int i = 0; i < AlphaISA::NumIntArchRegs; ++i) { + for (int i = 0; i < NumIntArchRegs; ++i) { context->setIntReg(i, gdbregs.regs[i]); } } #ifdef KGDB_FP_REGS - for (int i = 0; i < AlphaISA::NumFloatArchRegs; ++i) { + for (int i = 0; i < NumFloatArchRegs; ++i) { context->setFloatRegBits(i, gdbregs.regs[i + KGDB_REG_F0]); } #endif diff --git a/src/arch/alpha/stacktrace.cc b/src/arch/alpha/stacktrace.cc index b2fa89cb8..a29a4eb4d 100644 --- a/src/arch/alpha/stacktrace.cc +++ b/src/arch/alpha/stacktrace.cc @@ -142,7 +142,7 @@ namespace AlphaISA { tc = _tc; - bool usermode = (tc->readMiscRegNoEffect(AlphaISA::IPR_DTB_CM) & 0x18) != 0; + bool usermode = (tc->readMiscRegNoEffect(IPR_DTB_CM) & 0x18) != 0; Addr pc = tc->readNextPC(); bool kernel = tc->getSystemPtr()->kernelStart <= pc && @@ -159,7 +159,7 @@ namespace AlphaISA } SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; - Addr ksp = tc->readIntReg(AlphaISA::StackPointerReg); + Addr ksp = tc->readIntReg(StackPointerReg); Addr bottom = ksp & ~0x3fff; Addr addr; @@ -215,22 +215,22 @@ namespace AlphaISA bool StackTrace::isEntry(Addr addr) { - if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp12)) + if (addr == tc->readMiscRegNoEffect(IPR_PALtemp12)) return true; - if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp7)) + if (addr == tc->readMiscRegNoEffect(IPR_PALtemp7)) return true; - if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp11)) + if (addr == tc->readMiscRegNoEffect(IPR_PALtemp11)) return true; - if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp21)) + if (addr == tc->readMiscRegNoEffect(IPR_PALtemp21)) return true; - if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp9)) + if (addr == tc->readMiscRegNoEffect(IPR_PALtemp9)) return true; - if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp2)) + if (addr == tc->readMiscRegNoEffect(IPR_PALtemp2)) return true; return false; diff --git a/src/arch/alpha/stacktrace.hh b/src/arch/alpha/stacktrace.hh index c028afe2b..39fd3d286 100644 --- a/src/arch/alpha/stacktrace.hh +++ b/src/arch/alpha/stacktrace.hh @@ -61,8 +61,6 @@ namespace AlphaISA class StackTrace { - protected: - typedef AlphaISA::MachInst MachInst; private: ThreadContext *tc; std::vector stack; diff --git a/src/arch/alpha/system.cc b/src/arch/alpha/system.cc index 63efef4a0..6bff3d798 100644 --- a/src/arch/alpha/system.cc +++ b/src/arch/alpha/system.cc @@ -42,8 +42,7 @@ #include "params/AlphaSystem.hh" #include "sim/byteswap.hh" - -using namespace LittleEndianGuest; +using namespace AlphaISA; AlphaSystem::AlphaSystem(Params *p) : System(p) @@ -67,8 +66,8 @@ AlphaSystem::AlphaSystem(Params *p) // Load program sections into memory - pal->loadSections(&functionalPort, AlphaISA::LoadAddrMask); - console->loadSections(&functionalPort, AlphaISA::LoadAddrMask); + pal->loadSections(&functionalPort, LoadAddrMask); + console->loadSections(&functionalPort, LoadAddrMask); // load symbols if (!console->loadGlobalSymbols(consoleSymtab)) @@ -172,11 +171,11 @@ AlphaSystem::fixFuncEventAddr(Addr addr) const uint32_t gp_lda_pattern = (8 << 26) | (29 << 21) | (29 << 16); uint32_t i1 = virtPort.read(addr); - uint32_t i2 = virtPort.read(addr + sizeof(AlphaISA::MachInst)); + uint32_t i2 = virtPort.read(addr + sizeof(MachInst)); if ((i1 & inst_mask) == gp_ldah_pattern && (i2 & inst_mask) == gp_lda_pattern) { - Addr new_addr = addr + 2* sizeof(AlphaISA::MachInst); + Addr new_addr = addr + 2* sizeof(MachInst); DPRINTF(Loader, "fixFuncEventAddr: %p -> %p", addr, new_addr); return new_addr; } else { @@ -190,7 +189,7 @@ AlphaSystem::setAlphaAccess(Addr access) { Addr addr = 0; if (consoleSymtab->findAddress("m5AlphaAccess", addr)) { - virtPort.write(addr, htog(AlphaISA::Phys2K0Seg(access))); + virtPort.write(addr, htog(Phys2K0Seg(access))); } else panic("could not find m5AlphaAccess\n"); } diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc index 2694cf38f..5e231d4d8 100644 --- a/src/arch/alpha/tlb.cc +++ b/src/arch/alpha/tlb.cc @@ -622,7 +622,7 @@ TLB::index(bool advance) return *entry; } -/* end namespace AlphaISA */ } +} // namespace AlphaISA AlphaISA::ITB * AlphaITBParams::create() diff --git a/src/arch/alpha/tlb.hh b/src/arch/alpha/tlb.hh index 98f845e21..f127d09a7 100644 --- a/src/arch/alpha/tlb.hh +++ b/src/arch/alpha/tlb.hh @@ -88,8 +88,8 @@ namespace AlphaISA // static helper functions... really EV5 VM traits static bool validVirtualAddress(Addr vaddr) { // unimplemented bits must be all 0 or all 1 - Addr unimplBits = vaddr & AlphaISA::VAddrUnImplMask; - return (unimplBits == 0) || (unimplBits == AlphaISA::VAddrUnImplMask); + Addr unimplBits = vaddr & VAddrUnImplMask; + return (unimplBits == 0) || (unimplBits == VAddrUnImplMask); } static Fault checkCacheability(RequestPtr &req, bool itb = false); diff --git a/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh index 43d4908b4..220aa6695 100644 --- a/src/arch/alpha/utility.hh +++ b/src/arch/alpha/utility.hh @@ -46,7 +46,7 @@ namespace AlphaISA inline bool inUserMode(ThreadContext *tc) { - return (tc->readMiscRegNoEffect(AlphaISA::IPR_DTB_CM) & 0x18) != 0; + return (tc->readMiscRegNoEffect(IPR_DTB_CM) & 0x18) != 0; } inline bool diff --git a/src/arch/alpha/vtophys.cc b/src/arch/alpha/vtophys.cc index 439af3bd7..88e5a3090 100644 --- a/src/arch/alpha/vtophys.cc +++ b/src/arch/alpha/vtophys.cc @@ -40,27 +40,28 @@ #include "mem/vport.hh" using namespace std; -using namespace AlphaISA; -AlphaISA::PageTableEntry -AlphaISA::kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vaddr) +namespace AlphaISA { + +PageTableEntry +kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, VAddr vaddr) { Addr level1_pte = ptbr + vaddr.level1(); - AlphaISA::PageTableEntry level1 = mem->read(level1_pte); + PageTableEntry level1 = mem->read(level1_pte); if (!level1.valid()) { DPRINTF(VtoPhys, "level 1 PTE not valid, va = %#\n", vaddr); return 0; } Addr level2_pte = level1.paddr() + vaddr.level2(); - AlphaISA::PageTableEntry level2 = mem->read(level2_pte); + PageTableEntry level2 = mem->read(level2_pte); if (!level2.valid()) { DPRINTF(VtoPhys, "level 2 PTE not valid, va = %#x\n", vaddr); return 0; } Addr level3_pte = level2.paddr() + vaddr.level3(); - AlphaISA::PageTableEntry level3 = mem->read(level3_pte); + PageTableEntry level3 = mem->read(level3_pte); if (!level3.valid()) { DPRINTF(VtoPhys, "level 3 PTE not valid, va = %#x\n", vaddr); return 0; @@ -69,13 +70,13 @@ AlphaISA::kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vadd } Addr -AlphaISA::vtophys(Addr vaddr) +vtophys(Addr vaddr) { Addr paddr = 0; - if (AlphaISA::IsUSeg(vaddr)) + if (IsUSeg(vaddr)) DPRINTF(VtoPhys, "vtophys: invalid vaddr %#x", vaddr); - else if (AlphaISA::IsK0Seg(vaddr)) - paddr = AlphaISA::K0Seg2Phys(vaddr); + else if (IsK0Seg(vaddr)) + paddr = K0Seg2Phys(vaddr); else panic("vtophys: ptbr is not set on virtual lookup"); @@ -85,22 +86,22 @@ AlphaISA::vtophys(Addr vaddr) } Addr -AlphaISA::vtophys(ThreadContext *tc, Addr addr) +vtophys(ThreadContext *tc, Addr addr) { - AlphaISA::VAddr vaddr = addr; - Addr ptbr = tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp20); + VAddr vaddr = addr; + Addr ptbr = tc->readMiscRegNoEffect(IPR_PALtemp20); Addr paddr = 0; //@todo Andrew couldn't remember why he commented some of this code //so I put it back in. Perhaps something to do with gdb debugging? - if (AlphaISA::PcPAL(vaddr) && (vaddr < AlphaISA::PalMax)) { + if (PcPAL(vaddr) && (vaddr < PalMax)) { paddr = vaddr & ~ULL(1); } else { - if (AlphaISA::IsK0Seg(vaddr)) { - paddr = AlphaISA::K0Seg2Phys(vaddr); + if (IsK0Seg(vaddr)) { + paddr = K0Seg2Phys(vaddr); } else if (!ptbr) { paddr = vaddr; } else { - AlphaISA::PageTableEntry pte = + PageTableEntry pte = kernel_pte_lookup(tc->getPhysPort(), ptbr, vaddr); if (pte.valid()) paddr = pte.paddr() | vaddr.offset(); @@ -113,3 +114,5 @@ AlphaISA::vtophys(ThreadContext *tc, Addr addr) return paddr; } +} // namespace AlphaISA + diff --git a/src/arch/alpha/vtophys.hh b/src/arch/alpha/vtophys.hh index bd2ee8468..9cce85d6c 100644 --- a/src/arch/alpha/vtophys.hh +++ b/src/arch/alpha/vtophys.hh @@ -42,7 +42,7 @@ class FunctionalPort; namespace AlphaISA { PageTableEntry - kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vaddr); + kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, VAddr vaddr); Addr vtophys(Addr vaddr); Addr vtophys(ThreadContext *tc, Addr vaddr); -- cgit v1.2.3 From cf7ddd8e8ac92cf5b90cd89a028414dd782c645a Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 27 Sep 2008 21:03:48 -0700 Subject: style: Make a style pass over the whole arch/alpha directory. --- src/arch/alpha/ev5.cc | 11 +- src/arch/alpha/ev5.hh | 4 +- src/arch/alpha/faults.cc | 40 +-- src/arch/alpha/faults.hh | 59 +++-- src/arch/alpha/floatregfile.cc | 28 +- src/arch/alpha/floatregfile.hh | 45 ++-- src/arch/alpha/freebsd/system.cc | 3 - src/arch/alpha/freebsd/system.hh | 1 - src/arch/alpha/idle_event.cc | 7 +- src/arch/alpha/intregfile.cc | 53 ++-- src/arch/alpha/intregfile.hh | 63 ++--- src/arch/alpha/ipr.cc | 210 +++++++-------- src/arch/alpha/ipr.hh | 402 ++++++++++++++--------------- src/arch/alpha/isa_traits.hh | 257 +++++++++---------- src/arch/alpha/linux/linux.cc | 9 +- src/arch/alpha/linux/linux.hh | 20 +- src/arch/alpha/linux/process.cc | 2 - src/arch/alpha/linux/process.hh | 1 + src/arch/alpha/linux/system.cc | 2 - src/arch/alpha/linux/system.hh | 7 +- src/arch/alpha/linux/threadinfo.hh | 2 +- src/arch/alpha/locked_mem.hh | 6 +- src/arch/alpha/miscregfile.cc | 206 ++++++++------- src/arch/alpha/miscregfile.hh | 120 ++++----- src/arch/alpha/mmaped_ipr.hh | 5 +- src/arch/alpha/osfpal.cc | 10 +- src/arch/alpha/osfpal.hh | 6 +- src/arch/alpha/pagetable.cc | 55 ++-- src/arch/alpha/pagetable.hh | 181 ++++++------- src/arch/alpha/predecoder.hh | 114 ++++---- src/arch/alpha/process.cc | 6 +- src/arch/alpha/process.hh | 12 +- src/arch/alpha/regfile.cc | 101 ++++---- src/arch/alpha/regfile.hh | 273 +++++++++++--------- src/arch/alpha/remote_gdb.cc | 49 ++-- src/arch/alpha/remote_gdb.hh | 40 ++- src/arch/alpha/stacktrace.cc | 514 ++++++++++++++++++------------------- src/arch/alpha/stacktrace.hh | 126 ++++----- src/arch/alpha/syscallreturn.hh | 35 +-- src/arch/alpha/system.cc | 8 +- src/arch/alpha/system.hh | 16 +- src/arch/alpha/tlb.cc | 61 +++-- src/arch/alpha/tlb.hh | 208 +++++++-------- src/arch/alpha/tru64/process.cc | 25 +- src/arch/alpha/tru64/process.hh | 9 +- src/arch/alpha/tru64/tru64.hh | 23 +- src/arch/alpha/types.hh | 67 ++--- src/arch/alpha/utility.cc | 8 +- src/arch/alpha/utility.hh | 244 +++++++++--------- src/arch/alpha/vtophys.cc | 1 - src/arch/alpha/vtophys.hh | 11 +- src/kern/tru64/tru64_events.cc | 11 +- 52 files changed, 1915 insertions(+), 1862 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/ev5.cc b/src/arch/alpha/ev5.cc index 166d42bc6..7dc02a611 100644 --- a/src/arch/alpha/ev5.cc +++ b/src/arch/alpha/ev5.cc @@ -459,8 +459,7 @@ MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc) // really a control write ipr[idx] = val; - tc->getDTBPtr()->flushAddr(val, - DTB_ASN_ASN(ipr[IPR_DTB_ASN])); + tc->getDTBPtr()->flushAddr(val, DTB_ASN_ASN(ipr[IPR_DTB_ASN])); break; case IPR_DTB_TAG: { @@ -529,8 +528,7 @@ MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc) // really a control write ipr[idx] = val; - tc->getITBPtr()->flushAddr(val, - ITB_ASN_ASN(ipr[IPR_ITB_ASN])); + tc->getITBPtr()->flushAddr(val, ITB_ASN_ASN(ipr[IPR_ITB_ASN])); break; default: @@ -541,18 +539,17 @@ MiscRegFile::setIpr(int idx, uint64_t val, ThreadContext *tc) // no error... } - void copyIprs(ThreadContext *src, ThreadContext *dest) { - for (int i = 0; i < NumInternalProcRegs; ++i) { + for (int i = 0; i < NumInternalProcRegs; ++i) dest->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i)); - } } } // namespace AlphaISA #if FULL_SYSTEM + using namespace AlphaISA; Fault diff --git a/src/arch/alpha/ev5.hh b/src/arch/alpha/ev5.hh index a40ca6749..4c4f282f1 100644 --- a/src/arch/alpha/ev5.hh +++ b/src/arch/alpha/ev5.hh @@ -65,7 +65,9 @@ const Addr PAddrUncachedBit39 = ULL(0x8000000000); const Addr PAddrUncachedBit40 = ULL(0x10000000000); const Addr PAddrUncachedBit43 = ULL(0x80000000000); const Addr PAddrUncachedMask = ULL(0x807ffffffff); // Clear PA<42:35> -inline Addr Phys2K0Seg(Addr addr) + +inline Addr +Phys2K0Seg(Addr addr) { #if !ALPHA_TLASER if (addr & PAddrUncachedBit43) { diff --git a/src/arch/alpha/faults.cc b/src/arch/alpha/faults.cc index 845ac0288..dae188839 100644 --- a/src/arch/alpha/faults.cc +++ b/src/arch/alpha/faults.cc @@ -40,8 +40,7 @@ #include "mem/page_table.hh" #endif -namespace AlphaISA -{ +namespace AlphaISA { FaultName MachineCheckFault::_name = "mchk"; FaultVect MachineCheckFault::_vect = 0x0401; @@ -109,7 +108,8 @@ FaultStat IntegerOverflowFault::_count; #if FULL_SYSTEM -void AlphaFault::invoke(ThreadContext * tc) +void +AlphaFault::invoke(ThreadContext *tc) { FaultBase::invoke(tc); countStat()++; @@ -128,29 +128,31 @@ void AlphaFault::invoke(ThreadContext * tc) tc->setNextPC(tc->readPC() + sizeof(MachInst)); } -void ArithmeticFault::invoke(ThreadContext * tc) +void +ArithmeticFault::invoke(ThreadContext *tc) { FaultBase::invoke(tc); panic("Arithmetic traps are unimplemented!"); } -void DtbFault::invoke(ThreadContext * tc) +void +DtbFault::invoke(ThreadContext *tc) { // Set fault address and flags. Even though we're modeling an // EV5, we use the EV6 technique of not latching fault registers // on VPTE loads (instead of locking the registers until IPR_VA is // read, like the EV5). The EV6 approach is cleaner and seems to // work with EV5 PAL code, but not the other way around. - if (!tc->misspeculating() - && !(reqFlags & VPTE) && !(reqFlags & NO_FAULT)) { + if (!tc->misspeculating() && + !(reqFlags & VPTE) && !(reqFlags & NO_FAULT)) { // set VA register with faulting address tc->setMiscRegNoEffect(IPR_VA, vaddr); // set MM_STAT register flags tc->setMiscRegNoEffect(IPR_MM_STAT, - (((Opcode(tc->getInst()) & 0x3f) << 11) - | ((Ra(tc->getInst()) & 0x1f) << 6) - | (flags & 0x3f))); + (((Opcode(tc->getInst()) & 0x3f) << 11) | + ((Ra(tc->getInst()) & 0x1f) << 6) | + (flags & 0x3f))); // set VA_FORM register with faulting formatted address tc->setMiscRegNoEffect(IPR_VA_FORM, @@ -160,13 +162,13 @@ void DtbFault::invoke(ThreadContext * tc) AlphaFault::invoke(tc); } -void ItbFault::invoke(ThreadContext * tc) +void +ItbFault::invoke(ThreadContext *tc) { if (!tc->misspeculating()) { tc->setMiscRegNoEffect(IPR_ITB_TAG, pc); tc->setMiscRegNoEffect(IPR_IFAULT_VA_FORM, - tc->readMiscRegNoEffect(IPR_IVPTBR) | - (VAddr(pc).vpn() << 3)); + tc->readMiscRegNoEffect(IPR_IVPTBR) | (VAddr(pc).vpn() << 3)); } AlphaFault::invoke(tc); @@ -174,12 +176,13 @@ void ItbFault::invoke(ThreadContext * tc) #else -void ItbPageFault::invoke(ThreadContext * tc) +void +ItbPageFault::invoke(ThreadContext *tc) { Process *p = tc->getProcessPtr(); TlbEntry entry; bool success = p->pTable->lookup(pc, entry); - if(!success) { + if (!success) { panic("Tried to execute unmapped address %#x.\n", pc); } else { VAddr vaddr(pc); @@ -187,16 +190,17 @@ void ItbPageFault::invoke(ThreadContext * tc) } } -void NDtbMissFault::invoke(ThreadContext * tc) +void +NDtbMissFault::invoke(ThreadContext *tc) { Process *p = tc->getProcessPtr(); TlbEntry entry; bool success = p->pTable->lookup(vaddr, entry); - if(!success) { + if (!success) { p->checkAndAllocNextPage(vaddr); success = p->pTable->lookup(vaddr, entry); } - if(!success) { + if (!success) { panic("Tried to access unmapped address %#x.\n", (Addr)vaddr); } else { tc->getDTBPtr()->insert(vaddr.page(), entry); diff --git a/src/arch/alpha/faults.hh b/src/arch/alpha/faults.hh index 1d2ac593a..4b107273b 100644 --- a/src/arch/alpha/faults.hh +++ b/src/arch/alpha/faults.hh @@ -29,18 +29,16 @@ * Kevin Lim */ -#ifndef __ALPHA_FAULTS_HH__ -#define __ALPHA_FAULTS_HH__ +#ifndef __ARCH_ALPHA_FAULTS_HH__ +#define __ARCH_ALPHA_FAULTS_HH__ +#include "arch/alpha/pagetable.hh" #include "config/full_system.hh" #include "sim/faults.hh" -#include "arch/alpha/pagetable.hh" - // The design of the "name" and "vect" functions is in sim/faults.hh -namespace AlphaISA -{ +namespace AlphaISA { typedef const Addr FaultVect; @@ -63,6 +61,7 @@ class MachineCheckFault : public AlphaFault static FaultName _name; static FaultVect _vect; static FaultStat _count; + public: FaultName name() const {return _name;} FaultVect vect() {return _vect;} @@ -76,6 +75,7 @@ class AlignmentFault : public AlphaFault static FaultName _name; static FaultVect _vect; static FaultStat _count; + public: FaultName name() const {return _name;} FaultVect vect() {return _vect;} @@ -94,6 +94,7 @@ class ResetFault : public AlphaFault static FaultName _name; static FaultVect _vect; static FaultStat _count; + public: FaultName name() const {return _name;} FaultVect vect() {return _vect;} @@ -102,12 +103,14 @@ class ResetFault : public AlphaFault class ArithmeticFault : public AlphaFault { - protected: - bool skipFaultingInstruction() {return true;} private: static FaultName _name; static FaultVect _vect; static FaultStat _count; + + protected: + bool skipFaultingInstruction() {return true;} + public: FaultName name() const {return _name;} FaultVect vect() {return _vect;} @@ -119,12 +122,14 @@ class ArithmeticFault : public AlphaFault class InterruptFault : public AlphaFault { - protected: - bool setRestartAddress() {return false;} private: static FaultName _name; static FaultVect _vect; static FaultStat _count; + + protected: + bool setRestartAddress() {return false;} + public: FaultName name() const {return _name;} FaultVect vect() {return _vect;} @@ -137,6 +142,7 @@ class DtbFault : public AlphaFault VAddr vaddr; uint32_t reqFlags; uint64_t flags; + public: DtbFault(VAddr _vaddr, uint32_t _reqFlags, uint64_t _flags) : vaddr(_vaddr), reqFlags(_reqFlags), flags(_flags) @@ -155,6 +161,7 @@ class NDtbMissFault : public DtbFault static FaultName _name; static FaultVect _vect; static FaultStat _count; + public: NDtbMissFault(VAddr vaddr, uint32_t reqFlags, uint64_t flags) : DtbFault(vaddr, reqFlags, flags) @@ -173,6 +180,7 @@ class PDtbMissFault : public DtbFault static FaultName _name; static FaultVect _vect; static FaultStat _count; + public: PDtbMissFault(VAddr vaddr, uint32_t reqFlags, uint64_t flags) : DtbFault(vaddr, reqFlags, flags) @@ -188,6 +196,7 @@ class DtbPageFault : public DtbFault static FaultName _name; static FaultVect _vect; static FaultStat _count; + public: DtbPageFault(VAddr vaddr, uint32_t reqFlags, uint64_t flags) : DtbFault(vaddr, reqFlags, flags) @@ -203,6 +212,7 @@ class DtbAcvFault : public DtbFault static FaultName _name; static FaultVect _vect; static FaultStat _count; + public: DtbAcvFault(VAddr vaddr, uint32_t reqFlags, uint64_t flags) : DtbFault(vaddr, reqFlags, flags) @@ -218,6 +228,7 @@ class DtbAlignmentFault : public DtbFault static FaultName _name; static FaultVect _vect; static FaultStat _count; + public: DtbAlignmentFault(VAddr vaddr, uint32_t reqFlags, uint64_t flags) : DtbFault(vaddr, reqFlags, flags) @@ -231,10 +242,9 @@ class ItbFault : public AlphaFault { protected: Addr pc; + public: - ItbFault(Addr _pc) - : pc(_pc) - { } + ItbFault(Addr _pc) : pc(_pc) { } FaultName name() const = 0; FaultVect vect() = 0; FaultStat & countStat() = 0; @@ -249,10 +259,9 @@ class ItbPageFault : public ItbFault static FaultName _name; static FaultVect _vect; static FaultStat _count; + public: - ItbPageFault(Addr pc) - : ItbFault(pc) - { } + ItbPageFault(Addr pc) : ItbFault(pc) { } FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} @@ -267,10 +276,9 @@ class ItbAcvFault : public ItbFault static FaultName _name; static FaultVect _vect; static FaultStat _count; + public: - ItbAcvFault(Addr pc) - : ItbFault(pc) - { } + ItbAcvFault(Addr pc) : ItbFault(pc) { } FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} @@ -282,6 +290,7 @@ class UnimplementedOpcodeFault : public AlphaFault static FaultName _name; static FaultVect _vect; static FaultStat _count; + public: FaultName name() const {return _name;} FaultVect vect() {return _vect;} @@ -294,6 +303,7 @@ class FloatEnableFault : public AlphaFault static FaultName _name; static FaultVect _vect; static FaultStat _count; + public: FaultName name() const {return _name;} FaultVect vect() {return _vect;} @@ -302,12 +312,14 @@ class FloatEnableFault : public AlphaFault class PalFault : public AlphaFault { - protected: - bool skipFaultingInstruction() {return true;} private: static FaultName _name; static FaultVect _vect; static FaultStat _count; + + protected: + bool skipFaultingInstruction() {return true;} + public: FaultName name() const {return _name;} FaultVect vect() {return _vect;} @@ -320,12 +332,13 @@ class IntegerOverflowFault : public AlphaFault static FaultName _name; static FaultVect _vect; static FaultStat _count; + public: FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; -} // AlphaISA namespace +} // namespace AlphaISA -#endif // __FAULTS_HH__ +#endif // __ARCH_ALPHA_FAULTS_HH__ diff --git a/src/arch/alpha/floatregfile.cc b/src/arch/alpha/floatregfile.cc index 512b0df95..15dc13166 100644 --- a/src/arch/alpha/floatregfile.cc +++ b/src/arch/alpha/floatregfile.cc @@ -33,17 +33,23 @@ #include "arch/alpha/floatregfile.hh" #include "sim/serialize.hh" -namespace AlphaISA +namespace AlphaISA { +void +FloatRegFile::clear() { - void - FloatRegFile::serialize(std::ostream &os) - { - SERIALIZE_ARRAY(q, NumFloatRegs); - } + std::memset(d, 0, sizeof(d)); +} + +void +FloatRegFile::serialize(std::ostream &os) +{ + SERIALIZE_ARRAY(q, NumFloatRegs); +} - void - FloatRegFile::unserialize(Checkpoint *cp, const std::string §ion) - { - UNSERIALIZE_ARRAY(q, NumFloatRegs); - } +void +FloatRegFile::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_ARRAY(q, NumFloatRegs); } + +} // namespace AlphaISA diff --git a/src/arch/alpha/floatregfile.hh b/src/arch/alpha/floatregfile.hh index e69e8d186..82592d80d 100644 --- a/src/arch/alpha/floatregfile.hh +++ b/src/arch/alpha/floatregfile.hh @@ -32,37 +32,36 @@ #ifndef __ARCH_ALPHA_FLOATREGFILE_HH__ #define __ARCH_ALPHA_FLOATREGFILE_HH__ +#include +#include + #include "arch/alpha/isa_traits.hh" #include "arch/alpha/types.hh" -#include -#include - class Checkpoint; -namespace AlphaISA -{ - static inline std::string getFloatRegName(RegIndex) - { - return ""; - } +namespace AlphaISA { - class FloatRegFile - { - public: +static inline std::string +getFloatRegName(RegIndex) +{ + return ""; +} - union { - uint64_t q[NumFloatRegs]; // integer qword view - double d[NumFloatRegs]; // double-precision floating point view - }; +class FloatRegFile +{ + public: + union { + uint64_t q[NumFloatRegs]; // integer qword view + double d[NumFloatRegs]; // double-precision floating point view + }; - void serialize(std::ostream &os); + void clear(); - void unserialize(Checkpoint *cp, const std::string §ion); + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); +}; - void clear() - { std::memset(d, 0, sizeof(d)); } - }; -} +} // namespace AlphaISA -#endif +#endif // __ARCH_ALPHA_FLOATREGFILE_HH__ diff --git a/src/arch/alpha/freebsd/system.cc b/src/arch/alpha/freebsd/system.cc index f666de604..f2ea1b587 100644 --- a/src/arch/alpha/freebsd/system.cc +++ b/src/arch/alpha/freebsd/system.cc @@ -62,14 +62,12 @@ FreebsdAlphaSystem::FreebsdAlphaSystem(Params *p) addKernelFuncEvent("calibrate_clocks"); } - FreebsdAlphaSystem::~FreebsdAlphaSystem() { delete skipDelayEvent; delete skipCalibrateClocks; } - void FreebsdAlphaSystem::doCalibrateClocks(ThreadContext *tc) { @@ -84,7 +82,6 @@ FreebsdAlphaSystem::doCalibrateClocks(ThreadContext *tc) virtPort.write(timer_vaddr, (uint32_t)TIMER_FREQUENCY); } - void FreebsdAlphaSystem::SkipCalibrateClocksEvent::process(ThreadContext *tc) { diff --git a/src/arch/alpha/freebsd/system.hh b/src/arch/alpha/freebsd/system.hh index 8e8493f97..48f6238c0 100644 --- a/src/arch/alpha/freebsd/system.hh +++ b/src/arch/alpha/freebsd/system.hh @@ -57,7 +57,6 @@ class FreebsdAlphaSystem : public AlphaSystem ~FreebsdAlphaSystem(); void doCalibrateClocks(ThreadContext *tc); - }; #endif // __ARCH_ALPHA_FREEBSD_SYSTEM_HH__ diff --git a/src/arch/alpha/idle_event.cc b/src/arch/alpha/idle_event.cc index 337166aec..bb68782e7 100644 --- a/src/arch/alpha/idle_event.cc +++ b/src/arch/alpha/idle_event.cc @@ -38,8 +38,9 @@ using namespace AlphaISA; void IdleStartEvent::process(ThreadContext *tc) { - if (tc->getKernelStats()) - tc->getKernelStats()->setIdleProcess( - tc->readMiscRegNoEffect(IPR_PALtemp23), tc); + if (tc->getKernelStats()) { + MiscReg val = tc->readMiscRegNoEffect(IPR_PALtemp23); + tc->getKernelStats()->setIdleProcess(val, tc); + } remove(); } diff --git a/src/arch/alpha/intregfile.cc b/src/arch/alpha/intregfile.cc index d1dfc5168..8f692f856 100644 --- a/src/arch/alpha/intregfile.cc +++ b/src/arch/alpha/intregfile.cc @@ -30,36 +30,45 @@ * Kevin Lim */ +#include + #include "arch/alpha/isa_traits.hh" #include "arch/alpha/intregfile.hh" #include "sim/serialize.hh" -namespace AlphaISA -{ +namespace AlphaISA { + #if FULL_SYSTEM - const int reg_redir[NumIntRegs] = { - /* 0 */ 0, 1, 2, 3, 4, 5, 6, 7, - /* 8 */ 32, 33, 34, 35, 36, 37, 38, 15, - /* 16 */ 16, 17, 18, 19, 20, 21, 22, 23, - /* 24 */ 24, 39, 26, 27, 28, 29, 30, 31 }; +const int reg_redir[NumIntRegs] = { + /* 0 */ 0, 1, 2, 3, 4, 5, 6, 7, + /* 8 */ 32, 33, 34, 35, 36, 37, 38, 15, + /* 16 */ 16, 17, 18, 19, 20, 21, 22, 23, + /* 24 */ 24, 39, 26, 27, 28, 29, 30, 31 }; #else - const int reg_redir[NumIntRegs] = { - /* 0 */ 0, 1, 2, 3, 4, 5, 6, 7, - /* 8 */ 8, 9, 10, 11, 12, 13, 14, 15, - /* 16 */ 16, 17, 18, 19, 20, 21, 22, 23, - /* 24 */ 24, 25, 26, 27, 28, 29, 30, 31 }; +const int reg_redir[NumIntRegs] = { + /* 0 */ 0, 1, 2, 3, 4, 5, 6, 7, + /* 8 */ 8, 9, 10, 11, 12, 13, 14, 15, + /* 16 */ 16, 17, 18, 19, 20, 21, 22, 23, + /* 24 */ 24, 25, 26, 27, 28, 29, 30, 31 }; #endif - void - IntRegFile::serialize(std::ostream &os) - { - SERIALIZE_ARRAY(regs, NumIntRegs); - } +void +IntRegFile::clear() +{ + std::memset(regs, 0, sizeof(regs)); +} + +void +IntRegFile::serialize(std::ostream &os) +{ + SERIALIZE_ARRAY(regs, NumIntRegs); +} - void - IntRegFile::unserialize(Checkpoint *cp, const std::string §ion) - { - UNSERIALIZE_ARRAY(regs, NumIntRegs); - } +void +IntRegFile::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_ARRAY(regs, NumIntRegs); } +} // namespace AlphaISA + diff --git a/src/arch/alpha/intregfile.hh b/src/arch/alpha/intregfile.hh index dea160992..f6ba72e79 100644 --- a/src/arch/alpha/intregfile.hh +++ b/src/arch/alpha/intregfile.hh @@ -32,47 +32,48 @@ #ifndef __ARCH_ALPHA_INTREGFILE_HH__ #define __ARCH_ALPHA_INTREGFILE_HH__ -#include "arch/alpha/types.hh" +#include +#include -#include -#include +#include "arch/alpha/types.hh" class Checkpoint; -namespace AlphaISA -{ - static inline std::string getIntRegName(RegIndex) - { - return ""; - } +namespace AlphaISA { - // redirected register map, really only used for the full system case. - extern const int reg_redir[NumIntRegs]; +static inline std::string +getIntRegName(RegIndex) +{ + return ""; +} - class IntRegFile - { - protected: - IntReg regs[NumIntRegs]; +// redirected register map, really only used for the full system case. +extern const int reg_redir[NumIntRegs]; - public: +class IntRegFile +{ + protected: + IntReg regs[NumIntRegs]; - IntReg readReg(int intReg) - { - return regs[intReg]; - } + public: + IntReg + readReg(int intReg) + { + return regs[intReg]; + } - void setReg(int intReg, const IntReg &val) - { - regs[intReg] = val; - } + void + setReg(int intReg, const IntReg &val) + { + regs[intReg] = val; + } - void serialize(std::ostream &os); + void clear(); - void unserialize(Checkpoint *cp, const std::string §ion); + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); +}; - void clear() - { std::memset(regs, 0, sizeof(regs)); } - }; -} +} // namespace AlphaISA -#endif +#endif // __ARCH_ALPHA_INTREGFILE_HH__ diff --git a/src/arch/alpha/ipr.cc b/src/arch/alpha/ipr.cc index a76fcc2bc..502ada5eb 100644 --- a/src/arch/alpha/ipr.cc +++ b/src/arch/alpha/ipr.cc @@ -28,113 +28,115 @@ * Authors: Gabe Black */ -#include -#include +#include +#include #include "arch/alpha/ipr.hh" -namespace AlphaISA +namespace AlphaISA { + +md_ipr_names MiscRegIndexToIpr[NumInternalProcRegs] = { + + //Write only + RAW_IPR_HWINT_CLR, // H/W interrupt clear register + RAW_IPR_SL_XMIT, // serial line transmit register + RAW_IPR_DC_FLUSH, + RAW_IPR_IC_FLUSH, // instruction cache flush control + RAW_IPR_ALT_MODE, // alternate mode register + RAW_IPR_DTB_IA, // DTLB invalidate all register + RAW_IPR_DTB_IAP, // DTLB invalidate all process register + RAW_IPR_ITB_IA, // ITLB invalidate all register + RAW_IPR_ITB_IAP, // ITLB invalidate all process register + + //Read only + RAW_IPR_INTID, // interrupt ID register + RAW_IPR_SL_RCV, // serial line receive register + RAW_IPR_MM_STAT, // data MMU fault status register + RAW_IPR_ITB_PTE_TEMP, // ITLB page table entry temp register + RAW_IPR_DTB_PTE_TEMP, // DTLB page table entry temporary register + + RAW_IPR_ISR, // interrupt summary register + RAW_IPR_ITB_TAG, // ITLB tag register + RAW_IPR_ITB_PTE, // ITLB page table entry register + RAW_IPR_ITB_ASN, // ITLB address space register + RAW_IPR_ITB_IS, // ITLB invalidate select register + RAW_IPR_SIRR, // software interrupt request register + RAW_IPR_ASTRR, // asynchronous system trap request register + RAW_IPR_ASTER, // asynchronous system trap enable register + RAW_IPR_EXC_ADDR, // exception address register + RAW_IPR_EXC_SUM, // exception summary register + RAW_IPR_EXC_MASK, // exception mask register + RAW_IPR_PAL_BASE, // PAL base address register + RAW_IPR_ICM, // instruction current mode + RAW_IPR_IPLR, // interrupt priority level register + RAW_IPR_IFAULT_VA_FORM, // formatted faulting virtual addr register + RAW_IPR_IVPTBR, // virtual page table base register + RAW_IPR_ICSR, // instruction control and status register + RAW_IPR_IC_PERR_STAT, // inst cache parity error status register + RAW_IPR_PMCTR, // performance counter register + + // PAL temporary registers... + // register meanings gleaned from osfpal.s source code + RAW_IPR_PALtemp0, // local scratch + RAW_IPR_PALtemp1, // local scratch + RAW_IPR_PALtemp2, // entUna + RAW_IPR_PALtemp3, // CPU specific impure area pointer + RAW_IPR_PALtemp4, // memory management temp + RAW_IPR_PALtemp5, // memory management temp + RAW_IPR_PALtemp6, // memory management temp + RAW_IPR_PALtemp7, // entIF + RAW_IPR_PALtemp8, // intmask + RAW_IPR_PALtemp9, // entSys + RAW_IPR_PALtemp10, // ?? + RAW_IPR_PALtemp11, // entInt + RAW_IPR_PALtemp12, // entArith + RAW_IPR_PALtemp13, // reserved for platform specific PAL + RAW_IPR_PALtemp14, // reserved for platform specific PAL + RAW_IPR_PALtemp15, // reserved for platform specific PAL + RAW_IPR_PALtemp16, // scratch / whami<7:0> / mces<4:0> + RAW_IPR_PALtemp17, // sysval + RAW_IPR_PALtemp18, // usp + RAW_IPR_PALtemp19, // ksp + RAW_IPR_PALtemp20, // PTBR + RAW_IPR_PALtemp21, // entMM + RAW_IPR_PALtemp22, // kgp + RAW_IPR_PALtemp23, // PCBB + + RAW_IPR_DTB_ASN, // DTLB address space number register + RAW_IPR_DTB_CM, // DTLB current mode register + RAW_IPR_DTB_TAG, // DTLB tag register + RAW_IPR_DTB_PTE, // DTLB page table entry register + + RAW_IPR_VA, // fault virtual address register + RAW_IPR_VA_FORM, // formatted virtual address register + RAW_IPR_MVPTBR, // MTU virtual page table base register + RAW_IPR_DTB_IS, // DTLB invalidate single register + RAW_IPR_CC, // cycle counter register + RAW_IPR_CC_CTL, // cycle counter control register + RAW_IPR_MCSR, // MTU control register + + RAW_IPR_DC_PERR_STAT, // Dcache parity error status register + RAW_IPR_DC_TEST_CTL, // Dcache test tag control register + RAW_IPR_DC_TEST_TAG, // Dcache test tag register + RAW_IPR_DC_TEST_TAG_TEMP, // Dcache test tag temporary register + RAW_IPR_DC_MODE, // Dcache mode register + RAW_IPR_MAF_MODE // miss address file mode register +}; + +int IprToMiscRegIndex[MaxInternalProcRegs]; + +void +initializeIprTable() { - md_ipr_names MiscRegIndexToIpr[NumInternalProcRegs] = - { - //Write only - RAW_IPR_HWINT_CLR, // H/W interrupt clear register - RAW_IPR_SL_XMIT, // serial line transmit register - RAW_IPR_DC_FLUSH, - RAW_IPR_IC_FLUSH, // instruction cache flush control - RAW_IPR_ALT_MODE, // alternate mode register - RAW_IPR_DTB_IA, // DTLB invalidate all register - RAW_IPR_DTB_IAP, // DTLB invalidate all process register - RAW_IPR_ITB_IA, // ITLB invalidate all register - RAW_IPR_ITB_IAP, // ITLB invalidate all process register - - //Read only - RAW_IPR_INTID, // interrupt ID register - RAW_IPR_SL_RCV, // serial line receive register - RAW_IPR_MM_STAT, // data MMU fault status register - RAW_IPR_ITB_PTE_TEMP, // ITLB page table entry temp register - RAW_IPR_DTB_PTE_TEMP, // DTLB page table entry temporary register - - RAW_IPR_ISR, // interrupt summary register - RAW_IPR_ITB_TAG, // ITLB tag register - RAW_IPR_ITB_PTE, // ITLB page table entry register - RAW_IPR_ITB_ASN, // ITLB address space register - RAW_IPR_ITB_IS, // ITLB invalidate select register - RAW_IPR_SIRR, // software interrupt request register - RAW_IPR_ASTRR, // asynchronous system trap request register - RAW_IPR_ASTER, // asynchronous system trap enable register - RAW_IPR_EXC_ADDR, // exception address register - RAW_IPR_EXC_SUM, // exception summary register - RAW_IPR_EXC_MASK, // exception mask register - RAW_IPR_PAL_BASE, // PAL base address register - RAW_IPR_ICM, // instruction current mode - RAW_IPR_IPLR, // interrupt priority level register - RAW_IPR_IFAULT_VA_FORM, // formatted faulting virtual addr register - RAW_IPR_IVPTBR, // virtual page table base register - RAW_IPR_ICSR, // instruction control and status register - RAW_IPR_IC_PERR_STAT, // inst cache parity error status register - RAW_IPR_PMCTR, // performance counter register - - // PAL temporary registers... - // register meanings gleaned from osfpal.s source code - RAW_IPR_PALtemp0, // local scratch - RAW_IPR_PALtemp1, // local scratch - RAW_IPR_PALtemp2, // entUna - RAW_IPR_PALtemp3, // CPU specific impure area pointer - RAW_IPR_PALtemp4, // memory management temp - RAW_IPR_PALtemp5, // memory management temp - RAW_IPR_PALtemp6, // memory management temp - RAW_IPR_PALtemp7, // entIF - RAW_IPR_PALtemp8, // intmask - RAW_IPR_PALtemp9, // entSys - RAW_IPR_PALtemp10, // ?? - RAW_IPR_PALtemp11, // entInt - RAW_IPR_PALtemp12, // entArith - RAW_IPR_PALtemp13, // reserved for platform specific PAL - RAW_IPR_PALtemp14, // reserved for platform specific PAL - RAW_IPR_PALtemp15, // reserved for platform specific PAL - RAW_IPR_PALtemp16, // scratch / whami<7:0> / mces<4:0> - RAW_IPR_PALtemp17, // sysval - RAW_IPR_PALtemp18, // usp - RAW_IPR_PALtemp19, // ksp - RAW_IPR_PALtemp20, // PTBR - RAW_IPR_PALtemp21, // entMM - RAW_IPR_PALtemp22, // kgp - RAW_IPR_PALtemp23, // PCBB - - RAW_IPR_DTB_ASN, // DTLB address space number register - RAW_IPR_DTB_CM, // DTLB current mode register - RAW_IPR_DTB_TAG, // DTLB tag register - RAW_IPR_DTB_PTE, // DTLB page table entry register - - RAW_IPR_VA, // fault virtual address register - RAW_IPR_VA_FORM, // formatted virtual address register - RAW_IPR_MVPTBR, // MTU virtual page table base register - RAW_IPR_DTB_IS, // DTLB invalidate single register - RAW_IPR_CC, // cycle counter register - RAW_IPR_CC_CTL, // cycle counter control register - RAW_IPR_MCSR, // MTU control register - - RAW_IPR_DC_PERR_STAT, // Dcache parity error status register - RAW_IPR_DC_TEST_CTL, // Dcache test tag control register - RAW_IPR_DC_TEST_TAG, // Dcache test tag register - RAW_IPR_DC_TEST_TAG_TEMP, // Dcache test tag temporary register - RAW_IPR_DC_MODE, // Dcache mode register - RAW_IPR_MAF_MODE // miss address file mode register - }; - - int IprToMiscRegIndex[MaxInternalProcRegs]; - - void initializeIprTable() - { - static bool initialized = false; - if(initialized) - return; - - memset(IprToMiscRegIndex, -1, MaxInternalProcRegs * sizeof(int)); - - for(int x = 0; x < NumInternalProcRegs; x++) - IprToMiscRegIndex[MiscRegIndexToIpr[x]] = x; - } + static bool initialized = false; + if (initialized) + return; + + memset(IprToMiscRegIndex, -1, MaxInternalProcRegs * sizeof(int)); + + for (int x = 0; x < NumInternalProcRegs; x++) + IprToMiscRegIndex[MiscRegIndexToIpr[x]] = x; } +} // namespace AlphaISA + diff --git a/src/arch/alpha/ipr.hh b/src/arch/alpha/ipr.hh index 6296cdb9a..4e7bf1fa4 100644 --- a/src/arch/alpha/ipr.hh +++ b/src/arch/alpha/ipr.hh @@ -32,206 +32,208 @@ #ifndef __ARCH_ALPHA_IPR_HH__ #define __ARCH_ALPHA_IPR_HH__ -namespace AlphaISA +namespace AlphaISA { + +//////////////////////////////////////////////////////////////////////// +// +// Internal Processor Reigsters +// +enum md_ipr_names { + RAW_IPR_ISR = 0x100, // interrupt summary + RAW_IPR_ITB_TAG = 0x101, // ITLB tag + RAW_IPR_ITB_PTE = 0x102, // ITLB page table entry + RAW_IPR_ITB_ASN = 0x103, // ITLB address space + RAW_IPR_ITB_PTE_TEMP = 0x104, // ITLB page table entry temp + RAW_IPR_ITB_IA = 0x105, // ITLB invalidate all + RAW_IPR_ITB_IAP = 0x106, // ITLB invalidate all process + RAW_IPR_ITB_IS = 0x107, // ITLB invalidate select + RAW_IPR_SIRR = 0x108, // software interrupt request + RAW_IPR_ASTRR = 0x109, // asynchronous system trap request + RAW_IPR_ASTER = 0x10a, // asynchronous system trap enable + RAW_IPR_EXC_ADDR = 0x10b, // exception address + RAW_IPR_EXC_SUM = 0x10c, // exception summary + RAW_IPR_EXC_MASK = 0x10d, // exception mask + RAW_IPR_PAL_BASE = 0x10e, // PAL base address + RAW_IPR_ICM = 0x10f, // instruction current mode + RAW_IPR_IPLR = 0x110, // interrupt priority level + RAW_IPR_INTID = 0x111, // interrupt ID + RAW_IPR_IFAULT_VA_FORM = 0x112, // formatted faulting virtual addr + RAW_IPR_IVPTBR = 0x113, // virtual page table base + RAW_IPR_HWINT_CLR = 0x115, // H/W interrupt clear + RAW_IPR_SL_XMIT = 0x116, // serial line transmit + RAW_IPR_SL_RCV = 0x117, // serial line receive + RAW_IPR_ICSR = 0x118, // instruction control and status + RAW_IPR_IC_FLUSH = 0x119, // instruction cache flush control + RAW_IPR_IC_PERR_STAT = 0x11a, // inst cache parity error status + RAW_IPR_PMCTR = 0x11c, // performance counter + + // PAL temporary registers... + // register meanings gleaned from osfpal.s source code + RAW_IPR_PALtemp0 = 0x140, // local scratch + RAW_IPR_PALtemp1 = 0x141, // local scratch + RAW_IPR_PALtemp2 = 0x142, // entUna + RAW_IPR_PALtemp3 = 0x143, // CPU specific impure area pointer + RAW_IPR_PALtemp4 = 0x144, // memory management temp + RAW_IPR_PALtemp5 = 0x145, // memory management temp + RAW_IPR_PALtemp6 = 0x146, // memory management temp + RAW_IPR_PALtemp7 = 0x147, // entIF + RAW_IPR_PALtemp8 = 0x148, // intmask + RAW_IPR_PALtemp9 = 0x149, // entSys + RAW_IPR_PALtemp10 = 0x14a, // ?? + RAW_IPR_PALtemp11 = 0x14b, // entInt + RAW_IPR_PALtemp12 = 0x14c, // entArith + RAW_IPR_PALtemp13 = 0x14d, // reserved for platform specific PAL + RAW_IPR_PALtemp14 = 0x14e, // reserved for platform specific PAL + RAW_IPR_PALtemp15 = 0x14f, // reserved for platform specific PAL + RAW_IPR_PALtemp16 = 0x150, // scratch / whami<7:0> / mces<4:0> + RAW_IPR_PALtemp17 = 0x151, // sysval + RAW_IPR_PALtemp18 = 0x152, // usp + RAW_IPR_PALtemp19 = 0x153, // ksp + RAW_IPR_PALtemp20 = 0x154, // PTBR + RAW_IPR_PALtemp21 = 0x155, // entMM + RAW_IPR_PALtemp22 = 0x156, // kgp + RAW_IPR_PALtemp23 = 0x157, // PCBB + + RAW_IPR_DTB_ASN = 0x200, // DTLB address space number + RAW_IPR_DTB_CM = 0x201, // DTLB current mode + RAW_IPR_DTB_TAG = 0x202, // DTLB tag + RAW_IPR_DTB_PTE = 0x203, // DTLB page table entry + RAW_IPR_DTB_PTE_TEMP = 0x204, // DTLB page table entry temporary + + RAW_IPR_MM_STAT = 0x205, // data MMU fault status + RAW_IPR_VA = 0x206, // fault virtual address + RAW_IPR_VA_FORM = 0x207, // formatted virtual address + RAW_IPR_MVPTBR = 0x208, // MTU virtual page table base + RAW_IPR_DTB_IAP = 0x209, // DTLB invalidate all process + RAW_IPR_DTB_IA = 0x20a, // DTLB invalidate all + RAW_IPR_DTB_IS = 0x20b, // DTLB invalidate single + RAW_IPR_ALT_MODE = 0x20c, // alternate mode + RAW_IPR_CC = 0x20d, // cycle counter + RAW_IPR_CC_CTL = 0x20e, // cycle counter control + RAW_IPR_MCSR = 0x20f, // MTU control + + RAW_IPR_DC_FLUSH = 0x210, + RAW_IPR_DC_PERR_STAT = 0x212, // Dcache parity error status + RAW_IPR_DC_TEST_CTL = 0x213, // Dcache test tag control + RAW_IPR_DC_TEST_TAG = 0x214, // Dcache test tag + RAW_IPR_DC_TEST_TAG_TEMP = 0x215, // Dcache test tag temporary + RAW_IPR_DC_MODE = 0x216, // Dcache mode + RAW_IPR_MAF_MODE = 0x217, // miss address file mode + + MaxInternalProcRegs // number of IPRs +}; + +enum MiscRegIpr { - //////////////////////////////////////////////////////////////////////// - // - // Internal Processor Reigsters - // - enum md_ipr_names - { - RAW_IPR_ISR = 0x100, // interrupt summary register - RAW_IPR_ITB_TAG = 0x101, // ITLB tag register - RAW_IPR_ITB_PTE = 0x102, // ITLB page table entry register - RAW_IPR_ITB_ASN = 0x103, // ITLB address space register - RAW_IPR_ITB_PTE_TEMP = 0x104, // ITLB page table entry temp register - RAW_IPR_ITB_IA = 0x105, // ITLB invalidate all register - RAW_IPR_ITB_IAP = 0x106, // ITLB invalidate all process register - RAW_IPR_ITB_IS = 0x107, // ITLB invalidate select register - RAW_IPR_SIRR = 0x108, // software interrupt request register - RAW_IPR_ASTRR = 0x109, // asynchronous system trap request register - RAW_IPR_ASTER = 0x10a, // asynchronous system trap enable register - RAW_IPR_EXC_ADDR = 0x10b, // exception address register - RAW_IPR_EXC_SUM = 0x10c, // exception summary register - RAW_IPR_EXC_MASK = 0x10d, // exception mask register - RAW_IPR_PAL_BASE = 0x10e, // PAL base address register - RAW_IPR_ICM = 0x10f, // instruction current mode - RAW_IPR_IPLR = 0x110, // interrupt priority level register - RAW_IPR_INTID = 0x111, // interrupt ID register - RAW_IPR_IFAULT_VA_FORM = 0x112, // formatted faulting virtual addr register - RAW_IPR_IVPTBR = 0x113, // virtual page table base register - RAW_IPR_HWINT_CLR = 0x115, // H/W interrupt clear register - RAW_IPR_SL_XMIT = 0x116, // serial line transmit register - RAW_IPR_SL_RCV = 0x117, // serial line receive register - RAW_IPR_ICSR = 0x118, // instruction control and status register - RAW_IPR_IC_FLUSH = 0x119, // instruction cache flush control - RAW_IPR_IC_PERR_STAT = 0x11a, // inst cache parity error status register - RAW_IPR_PMCTR = 0x11c, // performance counter register - - // PAL temporary registers... - // register meanings gleaned from osfpal.s source code - RAW_IPR_PALtemp0 = 0x140, // local scratch - RAW_IPR_PALtemp1 = 0x141, // local scratch - RAW_IPR_PALtemp2 = 0x142, // entUna - RAW_IPR_PALtemp3 = 0x143, // CPU specific impure area pointer - RAW_IPR_PALtemp4 = 0x144, // memory management temp - RAW_IPR_PALtemp5 = 0x145, // memory management temp - RAW_IPR_PALtemp6 = 0x146, // memory management temp - RAW_IPR_PALtemp7 = 0x147, // entIF - RAW_IPR_PALtemp8 = 0x148, // intmask - RAW_IPR_PALtemp9 = 0x149, // entSys - RAW_IPR_PALtemp10 = 0x14a, // ?? - RAW_IPR_PALtemp11 = 0x14b, // entInt - RAW_IPR_PALtemp12 = 0x14c, // entArith - RAW_IPR_PALtemp13 = 0x14d, // reserved for platform specific PAL - RAW_IPR_PALtemp14 = 0x14e, // reserved for platform specific PAL - RAW_IPR_PALtemp15 = 0x14f, // reserved for platform specific PAL - RAW_IPR_PALtemp16 = 0x150, // scratch / whami<7:0> / mces<4:0> - RAW_IPR_PALtemp17 = 0x151, // sysval - RAW_IPR_PALtemp18 = 0x152, // usp - RAW_IPR_PALtemp19 = 0x153, // ksp - RAW_IPR_PALtemp20 = 0x154, // PTBR - RAW_IPR_PALtemp21 = 0x155, // entMM - RAW_IPR_PALtemp22 = 0x156, // kgp - RAW_IPR_PALtemp23 = 0x157, // PCBB - - RAW_IPR_DTB_ASN = 0x200, // DTLB address space number register - RAW_IPR_DTB_CM = 0x201, // DTLB current mode register - RAW_IPR_DTB_TAG = 0x202, // DTLB tag register - RAW_IPR_DTB_PTE = 0x203, // DTLB page table entry register - RAW_IPR_DTB_PTE_TEMP = 0x204, // DTLB page table entry temporary register - - RAW_IPR_MM_STAT = 0x205, // data MMU fault status register - RAW_IPR_VA = 0x206, // fault virtual address register - RAW_IPR_VA_FORM = 0x207, // formatted virtual address register - RAW_IPR_MVPTBR = 0x208, // MTU virtual page table base register - RAW_IPR_DTB_IAP = 0x209, // DTLB invalidate all process register - RAW_IPR_DTB_IA = 0x20a, // DTLB invalidate all register - RAW_IPR_DTB_IS = 0x20b, // DTLB invalidate single register - RAW_IPR_ALT_MODE = 0x20c, // alternate mode register - RAW_IPR_CC = 0x20d, // cycle counter register - RAW_IPR_CC_CTL = 0x20e, // cycle counter control register - RAW_IPR_MCSR = 0x20f, // MTU control register - - RAW_IPR_DC_FLUSH = 0x210, - RAW_IPR_DC_PERR_STAT = 0x212, // Dcache parity error status register - RAW_IPR_DC_TEST_CTL = 0x213, // Dcache test tag control register - RAW_IPR_DC_TEST_TAG = 0x214, // Dcache test tag register - RAW_IPR_DC_TEST_TAG_TEMP = 0x215, // Dcache test tag temporary register - RAW_IPR_DC_MODE = 0x216, // Dcache mode register - RAW_IPR_MAF_MODE = 0x217, // miss address file mode register - - MaxInternalProcRegs // number of IPR registers - }; - - enum MiscRegIpr - { - //Write only - MinWriteOnlyIpr, - IPR_HWINT_CLR = MinWriteOnlyIpr, - IPR_SL_XMIT, - IPR_DC_FLUSH, - IPR_IC_FLUSH, - IPR_ALT_MODE, - IPR_DTB_IA, - IPR_DTB_IAP, - IPR_ITB_IA, - MaxWriteOnlyIpr, - IPR_ITB_IAP = MaxWriteOnlyIpr, - - //Read only - MinReadOnlyIpr, - IPR_INTID = MinReadOnlyIpr, - IPR_SL_RCV, - IPR_MM_STAT, - IPR_ITB_PTE_TEMP, - MaxReadOnlyIpr, - IPR_DTB_PTE_TEMP = MaxReadOnlyIpr, - - IPR_ISR, - IPR_ITB_TAG, - IPR_ITB_PTE, - IPR_ITB_ASN, - IPR_ITB_IS, - IPR_SIRR, - IPR_ASTRR, - IPR_ASTER, - IPR_EXC_ADDR, - IPR_EXC_SUM, - IPR_EXC_MASK, - IPR_PAL_BASE, - IPR_ICM, - IPR_IPLR, - IPR_IFAULT_VA_FORM, - IPR_IVPTBR, - IPR_ICSR, - IPR_IC_PERR_STAT, - IPR_PMCTR, - - // PAL temporary registers... - // register meanings gleaned from osfpal.s source code - IPR_PALtemp0, - IPR_PALtemp1, - IPR_PALtemp2, - IPR_PALtemp3, - IPR_PALtemp4, - IPR_PALtemp5, - IPR_PALtemp6, - IPR_PALtemp7, - IPR_PALtemp8, - IPR_PALtemp9, - IPR_PALtemp10, - IPR_PALtemp11, - IPR_PALtemp12, - IPR_PALtemp13, - IPR_PALtemp14, - IPR_PALtemp15, - IPR_PALtemp16, - IPR_PALtemp17, - IPR_PALtemp18, - IPR_PALtemp19, - IPR_PALtemp20, - IPR_PALtemp21, - IPR_PALtemp22, - IPR_PALtemp23, - - IPR_DTB_ASN, - IPR_DTB_CM, - IPR_DTB_TAG, - IPR_DTB_PTE, - - IPR_VA, - IPR_VA_FORM, - IPR_MVPTBR, - IPR_DTB_IS, - IPR_CC, - IPR_CC_CTL, - IPR_MCSR, - - IPR_DC_PERR_STAT, - IPR_DC_TEST_CTL, - IPR_DC_TEST_TAG, - IPR_DC_TEST_TAG_TEMP, - IPR_DC_MODE, - IPR_MAF_MODE, - - NumInternalProcRegs // number of IPR registers - }; - - inline bool IprIsWritable(int index) - { - return index < MinReadOnlyIpr || index > MaxReadOnlyIpr; - } - - inline bool IprIsReadable(int index) - { - return index < MinWriteOnlyIpr || index > MaxWriteOnlyIpr; - } - - extern md_ipr_names MiscRegIndexToIpr[NumInternalProcRegs]; - extern int IprToMiscRegIndex[MaxInternalProcRegs]; - - void initializeIprTable(); + //Write only + MinWriteOnlyIpr, + IPR_HWINT_CLR = MinWriteOnlyIpr, + IPR_SL_XMIT, + IPR_DC_FLUSH, + IPR_IC_FLUSH, + IPR_ALT_MODE, + IPR_DTB_IA, + IPR_DTB_IAP, + IPR_ITB_IA, + MaxWriteOnlyIpr, + IPR_ITB_IAP = MaxWriteOnlyIpr, + + //Read only + MinReadOnlyIpr, + IPR_INTID = MinReadOnlyIpr, + IPR_SL_RCV, + IPR_MM_STAT, + IPR_ITB_PTE_TEMP, + MaxReadOnlyIpr, + IPR_DTB_PTE_TEMP = MaxReadOnlyIpr, + + IPR_ISR, + IPR_ITB_TAG, + IPR_ITB_PTE, + IPR_ITB_ASN, + IPR_ITB_IS, + IPR_SIRR, + IPR_ASTRR, + IPR_ASTER, + IPR_EXC_ADDR, + IPR_EXC_SUM, + IPR_EXC_MASK, + IPR_PAL_BASE, + IPR_ICM, + IPR_IPLR, + IPR_IFAULT_VA_FORM, + IPR_IVPTBR, + IPR_ICSR, + IPR_IC_PERR_STAT, + IPR_PMCTR, + + // PAL temporary registers... + // register meanings gleaned from osfpal.s source code + IPR_PALtemp0, + IPR_PALtemp1, + IPR_PALtemp2, + IPR_PALtemp3, + IPR_PALtemp4, + IPR_PALtemp5, + IPR_PALtemp6, + IPR_PALtemp7, + IPR_PALtemp8, + IPR_PALtemp9, + IPR_PALtemp10, + IPR_PALtemp11, + IPR_PALtemp12, + IPR_PALtemp13, + IPR_PALtemp14, + IPR_PALtemp15, + IPR_PALtemp16, + IPR_PALtemp17, + IPR_PALtemp18, + IPR_PALtemp19, + IPR_PALtemp20, + IPR_PALtemp21, + IPR_PALtemp22, + IPR_PALtemp23, + + IPR_DTB_ASN, + IPR_DTB_CM, + IPR_DTB_TAG, + IPR_DTB_PTE, + + IPR_VA, + IPR_VA_FORM, + IPR_MVPTBR, + IPR_DTB_IS, + IPR_CC, + IPR_CC_CTL, + IPR_MCSR, + + IPR_DC_PERR_STAT, + IPR_DC_TEST_CTL, + IPR_DC_TEST_TAG, + IPR_DC_TEST_TAG_TEMP, + IPR_DC_MODE, + IPR_MAF_MODE, + + NumInternalProcRegs // number of IPR registers +}; + +inline bool +IprIsWritable(int index) +{ + return index < MinReadOnlyIpr || index > MaxReadOnlyIpr; +} + +inline bool +IprIsReadable(int index) +{ + return index < MinWriteOnlyIpr || index > MaxWriteOnlyIpr; } -#endif +extern md_ipr_names MiscRegIndexToIpr[NumInternalProcRegs]; +extern int IprToMiscRegIndex[MaxInternalProcRegs]; + +void initializeIprTable(); + +} // namespace AlphaISA + +#endif // __ARCH_ALPHA_IPR_HH__ diff --git a/src/arch/alpha/isa_traits.hh b/src/arch/alpha/isa_traits.hh index 4837d4a34..e5e4542a7 100644 --- a/src/arch/alpha/isa_traits.hh +++ b/src/arch/alpha/isa_traits.hh @@ -42,142 +42,137 @@ namespace LittleEndianGuest {} class StaticInstPtr; -namespace AlphaISA +namespace AlphaISA { + +using namespace LittleEndianGuest; +using AlphaISAInst::MaxInstSrcRegs; +using AlphaISAInst::MaxInstDestRegs; + +// These enumerate all the registers for dependence tracking. +enum DependenceTags { + // 0..31 are the integer regs 0..31 + // 32..63 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag) + FP_Base_DepTag = 40, + Ctrl_Base_DepTag = 72 +}; + +StaticInstPtr decodeInst(ExtMachInst); + +// Alpha Does NOT have a delay slot +#define ISA_HAS_DELAY_SLOT 0 + +const Addr PageShift = 13; +const Addr PageBytes = ULL(1) << PageShift; +const Addr PageMask = ~(PageBytes - 1); +const Addr PageOffset = PageBytes - 1; + +//////////////////////////////////////////////////////////////////////// +// +// Translation stuff +// + +const Addr PteShift = 3; +const Addr NPtePageShift = PageShift - PteShift; +const Addr NPtePage = ULL(1) << NPtePageShift; +const Addr PteMask = NPtePage - 1; + +// User Virtual +const Addr USegBase = ULL(0x0); +const Addr USegEnd = ULL(0x000003ffffffffff); + +// Kernel Direct Mapped +const Addr K0SegBase = ULL(0xfffffc0000000000); +const Addr K0SegEnd = ULL(0xfffffdffffffffff); + +// Kernel Virtual +const Addr K1SegBase = ULL(0xfffffe0000000000); +const Addr K1SegEnd = ULL(0xffffffffffffffff); + +// For loading... XXX This maybe could be USegEnd?? --ali +const Addr LoadAddrMask = ULL(0xffffffffff); + +//////////////////////////////////////////////////////////////////////// +// +// Interrupt levels +// +enum InterruptLevels { - using namespace LittleEndianGuest; - using AlphaISAInst::MaxInstSrcRegs; - using AlphaISAInst::MaxInstDestRegs; - - // These enumerate all the registers for dependence tracking. - enum DependenceTags { - // 0..31 are the integer regs 0..31 - // 32..63 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag) - FP_Base_DepTag = 40, - Ctrl_Base_DepTag = 72 - }; - - StaticInstPtr decodeInst(ExtMachInst); - - // Alpha Does NOT have a delay slot - #define ISA_HAS_DELAY_SLOT 0 - - const Addr PageShift = 13; - const Addr PageBytes = ULL(1) << PageShift; - const Addr PageMask = ~(PageBytes - 1); - const Addr PageOffset = PageBytes - 1; - - - //////////////////////////////////////////////////////////////////////// - // - // Translation stuff - // - - const Addr PteShift = 3; - const Addr NPtePageShift = PageShift - PteShift; - const Addr NPtePage = ULL(1) << NPtePageShift; - const Addr PteMask = NPtePage - 1; - - // User Virtual - const Addr USegBase = ULL(0x0); - const Addr USegEnd = ULL(0x000003ffffffffff); - - // Kernel Direct Mapped - const Addr K0SegBase = ULL(0xfffffc0000000000); - const Addr K0SegEnd = ULL(0xfffffdffffffffff); - - // Kernel Virtual - const Addr K1SegBase = ULL(0xfffffe0000000000); - const Addr K1SegEnd = ULL(0xffffffffffffffff); - - // For loading... XXX This maybe could be USegEnd?? --ali - const Addr LoadAddrMask = ULL(0xffffffffff); - -#if FULL_SYSTEM - - //////////////////////////////////////////////////////////////////////// - // - // Interrupt levels - // - enum InterruptLevels - { - INTLEVEL_SOFTWARE_MIN = 4, - INTLEVEL_SOFTWARE_MAX = 19, - - INTLEVEL_EXTERNAL_MIN = 20, - INTLEVEL_EXTERNAL_MAX = 34, - - INTLEVEL_IRQ0 = 20, - INTLEVEL_IRQ1 = 21, - INTINDEX_ETHERNET = 0, - INTINDEX_SCSI = 1, - INTLEVEL_IRQ2 = 22, - INTLEVEL_IRQ3 = 23, - - INTLEVEL_SERIAL = 33, - - NumInterruptLevels = INTLEVEL_EXTERNAL_MAX - }; - -#endif - - // EV5 modes - enum mode_type - { - mode_kernel = 0, // kernel - mode_executive = 1, // executive (unused by unix) - mode_supervisor = 2, // supervisor (unused by unix) - mode_user = 3, // user mode - mode_number // number of modes - }; - - // Constants Related to the number of registers - - const int NumIntArchRegs = 32; - const int NumPALShadowRegs = 8; - const int NumFloatArchRegs = 32; - // @todo: Figure out what this number really should be. - const int NumMiscArchRegs = 77; - - const int NumIntRegs = NumIntArchRegs + NumPALShadowRegs; - const int NumFloatRegs = NumFloatArchRegs; - const int NumMiscRegs = NumMiscArchRegs; - - const int TotalNumRegs = NumIntRegs + NumFloatRegs + - NumMiscRegs + NumInternalProcRegs; - - const int TotalDataRegs = NumIntRegs + NumFloatRegs; - - // semantically meaningful register indices - const int ZeroReg = 31; // architecturally meaningful - // the rest of these depend on the ABI - const int StackPointerReg = 30; - const int GlobalPointerReg = 29; - const int ProcedureValueReg = 27; - const int ReturnAddressReg = 26; - const int ReturnValueReg = 0; - const int FramePointerReg = 15; + INTLEVEL_SOFTWARE_MIN = 4, + INTLEVEL_SOFTWARE_MAX = 19, - const int ArgumentReg[] = {16, 17, 18, 19, 20, 21}; - const int NumArgumentRegs = sizeof(ArgumentReg) / sizeof(const int); + INTLEVEL_EXTERNAL_MIN = 20, + INTLEVEL_EXTERNAL_MAX = 34, - const int SyscallNumReg = ReturnValueReg; - const int SyscallPseudoReturnReg = ArgumentReg[4]; - const int SyscallSuccessReg = 19; + INTLEVEL_IRQ0 = 20, + INTLEVEL_IRQ1 = 21, + INTINDEX_ETHERNET = 0, + INTINDEX_SCSI = 1, + INTLEVEL_IRQ2 = 22, + INTLEVEL_IRQ3 = 23, - const int LogVMPageSize = 13; // 8K bytes - const int VMPageSize = (1 << LogVMPageSize); - - const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned - - const int MachineBytes = 8; - const int WordBytes = 4; - const int HalfwordBytes = 2; - const int ByteBytes = 1; - - // return a no-op instruction... used for instruction fetch faults - // Alpha UNOP (ldq_u r31,0(r0)) - const ExtMachInst NoopMachInst = 0x2ffe0000; + INTLEVEL_SERIAL = 33, + NumInterruptLevels = INTLEVEL_EXTERNAL_MAX +}; + +// EV5 modes +enum mode_type +{ + mode_kernel = 0, // kernel + mode_executive = 1, // executive (unused by unix) + mode_supervisor = 2, // supervisor (unused by unix) + mode_user = 3, // user mode + mode_number // number of modes }; +// Constants Related to the number of registers + +const int NumIntArchRegs = 32; +const int NumPALShadowRegs = 8; +const int NumFloatArchRegs = 32; +// @todo: Figure out what this number really should be. +const int NumMiscArchRegs = 77; + +const int NumIntRegs = NumIntArchRegs + NumPALShadowRegs; +const int NumFloatRegs = NumFloatArchRegs; +const int NumMiscRegs = NumMiscArchRegs; + +const int TotalNumRegs = + NumIntRegs + NumFloatRegs + NumMiscRegs + NumInternalProcRegs; + +const int TotalDataRegs = NumIntRegs + NumFloatRegs; + +// semantically meaningful register indices +const int ZeroReg = 31; // architecturally meaningful +// the rest of these depend on the ABI +const int StackPointerReg = 30; +const int GlobalPointerReg = 29; +const int ProcedureValueReg = 27; +const int ReturnAddressReg = 26; +const int ReturnValueReg = 0; +const int FramePointerReg = 15; + +const int ArgumentReg[] = {16, 17, 18, 19, 20, 21}; +const int NumArgumentRegs = sizeof(ArgumentReg) / sizeof(const int); + +const int SyscallNumReg = ReturnValueReg; +const int SyscallPseudoReturnReg = ArgumentReg[4]; +const int SyscallSuccessReg = 19; + +const int LogVMPageSize = 13; // 8K bytes +const int VMPageSize = (1 << LogVMPageSize); + +const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned + +const int MachineBytes = 8; +const int WordBytes = 4; +const int HalfwordBytes = 2; +const int ByteBytes = 1; + +// return a no-op instruction... used for instruction fetch faults +// Alpha UNOP (ldq_u r31,0(r0)) +const ExtMachInst NoopMachInst = 0x2ffe0000; + +} // namespace AlphaISA + #endif // __ARCH_ALPHA_ISA_TRAITS_HH__ diff --git a/src/arch/alpha/linux/linux.cc b/src/arch/alpha/linux/linux.cc index 3e80f62a7..ad8388096 100644 --- a/src/arch/alpha/linux/linux.cc +++ b/src/arch/alpha/linux/linux.cc @@ -28,10 +28,10 @@ * Authors: Korey Sewell */ -#include "arch/alpha/linux/linux.hh" - #include +#include "arch/alpha/linux/linux.hh" + // open(2) flags translation table OpenFlagTransTable AlphaLinux::openFlagTable[] = { #ifdef _MSC_VER @@ -68,7 +68,4 @@ OpenFlagTransTable AlphaLinux::openFlagTable[] = { }; const int AlphaLinux::NUM_OPEN_FLAGS = - (sizeof(AlphaLinux::openFlagTable)/sizeof(AlphaLinux::openFlagTable[0])); - - - + (sizeof(AlphaLinux::openFlagTable)/sizeof(AlphaLinux::openFlagTable[0])); diff --git a/src/arch/alpha/linux/linux.hh b/src/arch/alpha/linux/linux.hh index 803970aa9..c622c5ef1 100644 --- a/src/arch/alpha/linux/linux.hh +++ b/src/arch/alpha/linux/linux.hh @@ -28,8 +28,8 @@ * Authors: Korey Sewell */ -#ifndef __ALPHA_ALPHA_LINUX_HH -#define __ALPHA_ALPHA_LINUX_HH +#ifndef __ALPHA_ALPHA_LINUX_LINUX_HH__ +#define __ALPHA_ALPHA_LINUX_LINUX_HH__ #include "kern/linux/linux.hh" @@ -72,13 +72,13 @@ class AlphaLinux : public Linux //@{ /// For getsysinfo(). - static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string - static const unsigned GSI_CPU_INFO = 59; //!< CPU information - static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type - static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine - static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system - static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB - static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz + static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string + static const unsigned GSI_CPU_INFO = 59; //!< CPU information + static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type + static const unsigned GSI_MAX_CPU = 30; //!< max # CPUs on machine + static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system + static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB + static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz static const unsigned GSI_IEEE_FP_CONTROL = 45; //@} @@ -127,4 +127,4 @@ class AlphaLinux : public Linux }; }; -#endif +#endif // __ALPHA_ALPHA_LINUX_LINUX_HH__ diff --git a/src/arch/alpha/linux/process.cc b/src/arch/alpha/linux/process.cc index 0a9d2f1a3..9527759ed 100644 --- a/src/arch/alpha/linux/process.cc +++ b/src/arch/alpha/linux/process.cc @@ -43,8 +43,6 @@ using namespace std; using namespace AlphaISA; - - /// Target uname() handler. static SyscallReturn unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, diff --git a/src/arch/alpha/linux/process.hh b/src/arch/alpha/linux/process.hh index 8d7c24e37..9ab7b0501 100644 --- a/src/arch/alpha/linux/process.hh +++ b/src/arch/alpha/linux/process.hh @@ -51,4 +51,5 @@ class AlphaLinuxProcess : public AlphaLiveProcess }; } // namespace AlphaISA + #endif // __ALPHA_LINUX_PROCESS_HH__ diff --git a/src/arch/alpha/linux/system.cc b/src/arch/alpha/linux/system.cc index a52bcae36..1d9332a58 100644 --- a/src/arch/alpha/linux/system.cc +++ b/src/arch/alpha/linux/system.cc @@ -157,7 +157,6 @@ LinuxAlphaSystem::~LinuxAlphaSystem() delete printThreadEvent; } - void LinuxAlphaSystem::setDelayLoop(ThreadContext *tc) { @@ -172,7 +171,6 @@ LinuxAlphaSystem::setDelayLoop(ThreadContext *tc) } } - void LinuxAlphaSystem::SkipDelayLoopEvent::process(ThreadContext *tc) { diff --git a/src/arch/alpha/linux/system.hh b/src/arch/alpha/linux/system.hh index 00cde826a..fa03736c3 100644 --- a/src/arch/alpha/linux/system.hh +++ b/src/arch/alpha/linux/system.hh @@ -54,23 +54,20 @@ using namespace Linux; class LinuxAlphaSystem : public AlphaSystem { private: - class SkipDelayLoopEvent : public SkipFuncEvent + struct SkipDelayLoopEvent : public SkipFuncEvent { - public: SkipDelayLoopEvent(PCEventQueue *q, const std::string &desc, Addr addr) : SkipFuncEvent(q, desc, addr) {} virtual void process(ThreadContext *tc); }; - class PrintThreadInfo : public PCEvent + struct PrintThreadInfo : public PCEvent { - public: PrintThreadInfo(PCEventQueue *q, const std::string &desc, Addr addr) : PCEvent(q, desc, addr) {} virtual void process(ThreadContext *tc); }; - /** * Addresses defining where the kernel bootloader places various * elements. Details found in include/asm-alpha/system.h diff --git a/src/arch/alpha/linux/threadinfo.hh b/src/arch/alpha/linux/threadinfo.hh index 3ec1aa098..db723bed3 100644 --- a/src/arch/alpha/linux/threadinfo.hh +++ b/src/arch/alpha/linux/threadinfo.hh @@ -147,6 +147,6 @@ class ThreadInfo } }; -/* namespace Linux */ } +} // namespace Linux #endif // __ARCH_ALPHA_LINUX_LINUX_THREADINFO_HH__ diff --git a/src/arch/alpha/locked_mem.hh b/src/arch/alpha/locked_mem.hh index df66b92bc..f629d982a 100644 --- a/src/arch/alpha/locked_mem.hh +++ b/src/arch/alpha/locked_mem.hh @@ -49,9 +49,8 @@ #include "base/misc.hh" #include "mem/request.hh" +namespace AlphaISA { -namespace AlphaISA -{ template inline void handleLockedRead(XC *xc, Request *req) @@ -99,7 +98,6 @@ handleLockedWrite(XC *xc, Request *req) return true; } - } // namespace AlphaISA -#endif +#endif // __ARCH_ALPHA_LOCKED_MEM_HH__ diff --git a/src/arch/alpha/miscregfile.cc b/src/arch/alpha/miscregfile.cc index cb5875349..f119ca6bb 100644 --- a/src/arch/alpha/miscregfile.cc +++ b/src/arch/alpha/miscregfile.cc @@ -33,118 +33,116 @@ #include "arch/alpha/miscregfile.hh" #include "base/misc.hh" -namespace AlphaISA -{ +namespace AlphaISA { - void - MiscRegFile::serialize(std::ostream &os) - { - SERIALIZE_SCALAR(fpcr); - SERIALIZE_SCALAR(uniq); - SERIALIZE_SCALAR(lock_flag); - SERIALIZE_SCALAR(lock_addr); - SERIALIZE_ARRAY(ipr, NumInternalProcRegs); - } +void +MiscRegFile::serialize(std::ostream &os) +{ + SERIALIZE_SCALAR(fpcr); + SERIALIZE_SCALAR(uniq); + SERIALIZE_SCALAR(lock_flag); + SERIALIZE_SCALAR(lock_addr); + SERIALIZE_ARRAY(ipr, NumInternalProcRegs); +} - void - MiscRegFile::unserialize(Checkpoint *cp, const std::string §ion) - { - UNSERIALIZE_SCALAR(fpcr); - UNSERIALIZE_SCALAR(uniq); - UNSERIALIZE_SCALAR(lock_flag); - UNSERIALIZE_SCALAR(lock_addr); - UNSERIALIZE_ARRAY(ipr, NumInternalProcRegs); - } +void +MiscRegFile::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_SCALAR(fpcr); + UNSERIALIZE_SCALAR(uniq); + UNSERIALIZE_SCALAR(lock_flag); + UNSERIALIZE_SCALAR(lock_addr); + UNSERIALIZE_ARRAY(ipr, NumInternalProcRegs); +} - MiscReg - MiscRegFile::readRegNoEffect(int misc_reg) - { - switch(misc_reg) { - case MISCREG_FPCR: - return fpcr; - case MISCREG_UNIQ: - return uniq; - case MISCREG_LOCKFLAG: - return lock_flag; - case MISCREG_LOCKADDR: - return lock_addr; - case MISCREG_INTR: - return intr_flag; - default: - assert(misc_reg < NumInternalProcRegs); - return ipr[misc_reg]; - } +MiscReg +MiscRegFile::readRegNoEffect(int misc_reg) +{ + switch (misc_reg) { + case MISCREG_FPCR: + return fpcr; + case MISCREG_UNIQ: + return uniq; + case MISCREG_LOCKFLAG: + return lock_flag; + case MISCREG_LOCKADDR: + return lock_addr; + case MISCREG_INTR: + return intr_flag; + default: + assert(misc_reg < NumInternalProcRegs); + return ipr[misc_reg]; } +} - MiscReg - MiscRegFile::readReg(int misc_reg, ThreadContext *tc) - { - switch(misc_reg) { - case MISCREG_FPCR: - return fpcr; - case MISCREG_UNIQ: - return uniq; - case MISCREG_LOCKFLAG: - return lock_flag; - case MISCREG_LOCKADDR: - return lock_addr; - case MISCREG_INTR: - return intr_flag; - default: - return readIpr(misc_reg, tc); - } +MiscReg +MiscRegFile::readReg(int misc_reg, ThreadContext *tc) +{ + switch (misc_reg) { + case MISCREG_FPCR: + return fpcr; + case MISCREG_UNIQ: + return uniq; + case MISCREG_LOCKFLAG: + return lock_flag; + case MISCREG_LOCKADDR: + return lock_addr; + case MISCREG_INTR: + return intr_flag; + default: + return readIpr(misc_reg, tc); } +} - void - MiscRegFile::setRegNoEffect(int misc_reg, const MiscReg &val) - { - switch(misc_reg) { - case MISCREG_FPCR: - fpcr = val; - return; - case MISCREG_UNIQ: - uniq = val; - return; - case MISCREG_LOCKFLAG: - lock_flag = val; - return; - case MISCREG_LOCKADDR: - lock_addr = val; - return; - case MISCREG_INTR: - intr_flag = val; - return; - default: - assert(misc_reg < NumInternalProcRegs); - ipr[misc_reg] = val; - return; - } +void +MiscRegFile::setRegNoEffect(int misc_reg, const MiscReg &val) +{ + switch (misc_reg) { + case MISCREG_FPCR: + fpcr = val; + return; + case MISCREG_UNIQ: + uniq = val; + return; + case MISCREG_LOCKFLAG: + lock_flag = val; + return; + case MISCREG_LOCKADDR: + lock_addr = val; + return; + case MISCREG_INTR: + intr_flag = val; + return; + default: + assert(misc_reg < NumInternalProcRegs); + ipr[misc_reg] = val; + return; } +} - void - MiscRegFile::setReg(int misc_reg, const MiscReg &val, - ThreadContext *tc) - { - switch(misc_reg) { - case MISCREG_FPCR: - fpcr = val; - return; - case MISCREG_UNIQ: - uniq = val; - return; - case MISCREG_LOCKFLAG: - lock_flag = val; - return; - case MISCREG_LOCKADDR: - lock_addr = val; - return; - case MISCREG_INTR: - intr_flag = val; - return; - default: - setIpr(misc_reg, val, tc); - return; - } +void +MiscRegFile::setReg(int misc_reg, const MiscReg &val, ThreadContext *tc) +{ + switch (misc_reg) { + case MISCREG_FPCR: + fpcr = val; + return; + case MISCREG_UNIQ: + uniq = val; + return; + case MISCREG_LOCKFLAG: + lock_flag = val; + return; + case MISCREG_LOCKADDR: + lock_addr = val; + return; + case MISCREG_INTR: + intr_flag = val; + return; + default: + setIpr(misc_reg, val, tc); + return; } - } + +} // namespace AlphaISA diff --git a/src/arch/alpha/miscregfile.hh b/src/arch/alpha/miscregfile.hh index f07b998e6..752099d01 100644 --- a/src/arch/alpha/miscregfile.hh +++ b/src/arch/alpha/miscregfile.hh @@ -32,85 +32,85 @@ #ifndef __ARCH_ALPHA_MISCREGFILE_HH__ #define __ARCH_ALPHA_MISCREGFILE_HH__ +#include + #include "arch/alpha/ipr.hh" #include "arch/alpha/types.hh" #include "sim/host.hh" #include "sim/serialize.hh" -#include - class Checkpoint; class ThreadContext; -namespace AlphaISA -{ - enum MiscRegIndex - { - MISCREG_FPCR = NumInternalProcRegs, - MISCREG_UNIQ, - MISCREG_LOCKFLAG, - MISCREG_LOCKADDR, - MISCREG_INTR - }; - - static inline std::string getMiscRegName(RegIndex) - { - return ""; - } - - class MiscRegFile { - protected: - uint64_t fpcr; // floating point condition codes - uint64_t uniq; // process-unique register - bool lock_flag; // lock flag for LL/SC - Addr lock_addr; // lock address for LL/SC - int intr_flag; +namespace AlphaISA { - public: - MiscRegFile() - { - initializeIprTable(); - } - - MiscReg readRegNoEffect(int misc_reg); +enum MiscRegIndex +{ + MISCREG_FPCR = NumInternalProcRegs, + MISCREG_UNIQ, + MISCREG_LOCKFLAG, + MISCREG_LOCKADDR, + MISCREG_INTR +}; + +static inline std::string +getMiscRegName(RegIndex) +{ + return ""; +} - MiscReg readReg(int misc_reg, ThreadContext *tc); +class MiscRegFile +{ + public: + friend class RegFile; + typedef uint64_t InternalProcReg; - //These functions should be removed once the simplescalar cpu model - //has been replaced. - int getInstAsid(); - int getDataAsid(); + protected: + uint64_t fpcr; // floating point condition codes + uint64_t uniq; // process-unique register + bool lock_flag; // lock flag for LL/SC + Addr lock_addr; // lock address for LL/SC + int intr_flag; - void setRegNoEffect(int misc_reg, const MiscReg &val); + InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs - void setReg(int misc_reg, const MiscReg &val, - ThreadContext *tc); + protected: + InternalProcReg readIpr(int idx, ThreadContext *tc); + void setIpr(int idx, InternalProcReg val, ThreadContext *tc); - void clear() - { - fpcr = uniq = 0; - lock_flag = 0; - lock_addr = 0; - intr_flag = 0; - } + public: + MiscRegFile() + { + initializeIprTable(); + } - void serialize(std::ostream &os); + // These functions should be removed once the simplescalar cpu + // model has been replaced. + int getInstAsid(); + int getDataAsid(); - void unserialize(Checkpoint *cp, const std::string §ion); - protected: - typedef uint64_t InternalProcReg; + MiscReg readRegNoEffect(int misc_reg); + MiscReg readReg(int misc_reg, ThreadContext *tc); - InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs + void setRegNoEffect(int misc_reg, const MiscReg &val); + void setReg(int misc_reg, const MiscReg &val, ThreadContext *tc); - private: - InternalProcReg readIpr(int idx, ThreadContext *tc); + void + clear() + { + fpcr = 0; + uniq = 0; + lock_flag = 0; + lock_addr = 0; + intr_flag = 0; + } - void setIpr(int idx, InternalProcReg val, ThreadContext *tc); - friend class RegFile; - }; + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); +}; - void copyIprs(ThreadContext *src, ThreadContext *dest); +void copyIprs(ThreadContext *src, ThreadContext *dest); -} +} // namespace AlphaISA -#endif +#endif // __ARCH_ALPHA_MISCREGFILE_HH__ diff --git a/src/arch/alpha/mmaped_ipr.hh b/src/arch/alpha/mmaped_ipr.hh index 2b4ba8745..af2469ca7 100644 --- a/src/arch/alpha/mmaped_ipr.hh +++ b/src/arch/alpha/mmaped_ipr.hh @@ -39,9 +39,8 @@ #include "mem/packet.hh" +namespace AlphaISA { -namespace AlphaISA -{ inline Tick handleIprRead(ThreadContext *xc, Packet *pkt) { @@ -58,4 +57,4 @@ handleIprWrite(ThreadContext *xc, Packet *pkt) } // namespace AlphaISA -#endif +#endif // __ARCH_ALPHA_MMAPED_IPR_HH__ diff --git a/src/arch/alpha/osfpal.cc b/src/arch/alpha/osfpal.cc index 0edbadb06..58a3d31eb 100644 --- a/src/arch/alpha/osfpal.cc +++ b/src/arch/alpha/osfpal.cc @@ -30,8 +30,10 @@ #include "arch/alpha/osfpal.hh" -namespace { - const char *strings[PAL::NumCodes] = { +const char * +PAL::name(int index) +{ + static const char *strings[PAL::NumCodes] = { // Priviledged PAL instructions "halt", // 0x00 "cflush", // 0x01 @@ -294,11 +296,7 @@ namespace { 0 // 0xff #endif }; -} -const char * -PAL::name(int index) -{ if (index > NumCodes || index < 0) return 0; diff --git a/src/arch/alpha/osfpal.hh b/src/arch/alpha/osfpal.hh index cf3940b85..2618e9dbd 100644 --- a/src/arch/alpha/osfpal.hh +++ b/src/arch/alpha/osfpal.hh @@ -28,8 +28,8 @@ * Authors: Nathan Binkert */ -#ifndef __OSFPAL_HH__ -#define __OSFPAL_HH__ +#ifndef __ARCH_ALPHA_OSFPAL_HH__ +#define __ARCH_ALPHA_OSFPAL_HH__ struct PAL { @@ -79,4 +79,4 @@ struct PAL static const char *name(int index); }; -#endif // __OSFPAL_HH__ +#endif // __ARCH_ALPHA_OSFPAL_HH__ diff --git a/src/arch/alpha/pagetable.cc b/src/arch/alpha/pagetable.cc index 3f9537834..6640e72e2 100644 --- a/src/arch/alpha/pagetable.cc +++ b/src/arch/alpha/pagetable.cc @@ -31,33 +31,34 @@ #include "arch/alpha/pagetable.hh" #include "sim/serialize.hh" -namespace AlphaISA +namespace AlphaISA { + +void +TlbEntry::serialize(std::ostream &os) { - void - TlbEntry::serialize(std::ostream &os) - { - SERIALIZE_SCALAR(tag); - SERIALIZE_SCALAR(ppn); - SERIALIZE_SCALAR(xre); - SERIALIZE_SCALAR(xwe); - SERIALIZE_SCALAR(asn); - SERIALIZE_SCALAR(asma); - SERIALIZE_SCALAR(fonr); - SERIALIZE_SCALAR(fonw); - SERIALIZE_SCALAR(valid); - } + SERIALIZE_SCALAR(tag); + SERIALIZE_SCALAR(ppn); + SERIALIZE_SCALAR(xre); + SERIALIZE_SCALAR(xwe); + SERIALIZE_SCALAR(asn); + SERIALIZE_SCALAR(asma); + SERIALIZE_SCALAR(fonr); + SERIALIZE_SCALAR(fonw); + SERIALIZE_SCALAR(valid); +} - void - TlbEntry::unserialize(Checkpoint *cp, const std::string §ion) - { - UNSERIALIZE_SCALAR(tag); - UNSERIALIZE_SCALAR(ppn); - UNSERIALIZE_SCALAR(xre); - UNSERIALIZE_SCALAR(xwe); - UNSERIALIZE_SCALAR(asn); - UNSERIALIZE_SCALAR(asma); - UNSERIALIZE_SCALAR(fonr); - UNSERIALIZE_SCALAR(fonw); - UNSERIALIZE_SCALAR(valid); - } +void +TlbEntry::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_SCALAR(tag); + UNSERIALIZE_SCALAR(ppn); + UNSERIALIZE_SCALAR(xre); + UNSERIALIZE_SCALAR(xwe); + UNSERIALIZE_SCALAR(asn); + UNSERIALIZE_SCALAR(asma); + UNSERIALIZE_SCALAR(fonr); + UNSERIALIZE_SCALAR(fonw); + UNSERIALIZE_SCALAR(valid); } + +} //namespace AlphaISA diff --git a/src/arch/alpha/pagetable.hh b/src/arch/alpha/pagetable.hh index b0689dce0..4f7beb19b 100644 --- a/src/arch/alpha/pagetable.hh +++ b/src/arch/alpha/pagetable.hh @@ -38,97 +38,102 @@ namespace AlphaISA { - struct VAddr - { - static const int ImplBits = 43; - static const Addr ImplMask = (ULL(1) << ImplBits) - 1; - static const Addr UnImplMask = ~ImplMask; - - VAddr(Addr a) : addr(a) {} - Addr addr; - operator Addr() const { return addr; } - const VAddr &operator=(Addr a) { addr = a; return *this; } - - Addr vpn() const { return (addr & ImplMask) >> PageShift; } - Addr page() const { return addr & PageMask; } - Addr offset() const { return addr & PageOffset; } - - Addr level3() const - { return PteAddr(addr >> PageShift); } - Addr level2() const - { return PteAddr(addr >> NPtePageShift + PageShift); } - Addr level1() const - { return PteAddr(addr >> 2 * NPtePageShift + PageShift); } - }; - - struct PageTableEntry +struct VAddr +{ + static const int ImplBits = 43; + static const Addr ImplMask = (ULL(1) << ImplBits) - 1; + static const Addr UnImplMask = ~ImplMask; + + Addr addr; + + VAddr(Addr a) : addr(a) {} + operator Addr() const { return addr; } + const VAddr &operator=(Addr a) { addr = a; return *this; } + + Addr vpn() const { return (addr & ImplMask) >> PageShift; } + Addr page() const { return addr & PageMask; } + Addr offset() const { return addr & PageOffset; } + + Addr level3() const + { return PteAddr(addr >> PageShift); } + Addr level2() const + { return PteAddr(addr >> NPtePageShift + PageShift); } + Addr level1() const + { return PteAddr(addr >> 2 * NPtePageShift + PageShift); } +}; + +struct PageTableEntry +{ + PageTableEntry(uint64_t e) : entry(e) {} + uint64_t entry; + operator uint64_t() const { return entry; } + const PageTableEntry &operator=(uint64_t e) { entry = e; return *this; } + const PageTableEntry &operator=(const PageTableEntry &e) + { entry = e.entry; return *this; } + + Addr _pfn() const { return (entry >> 32) & 0xffffffff; } + Addr _sw() const { return (entry >> 16) & 0xffff; } + int _rsv0() const { return (entry >> 14) & 0x3; } + bool _uwe() const { return (entry >> 13) & 0x1; } + bool _kwe() const { return (entry >> 12) & 0x1; } + int _rsv1() const { return (entry >> 10) & 0x3; } + bool _ure() const { return (entry >> 9) & 0x1; } + bool _kre() const { return (entry >> 8) & 0x1; } + bool _nomb() const { return (entry >> 7) & 0x1; } + int _gh() const { return (entry >> 5) & 0x3; } + bool _asm_() const { return (entry >> 4) & 0x1; } + bool _foe() const { return (entry >> 3) & 0x1; } + bool _fow() const { return (entry >> 2) & 0x1; } + bool _for() const { return (entry >> 1) & 0x1; } + bool valid() const { return (entry >> 0) & 0x1; } + + Addr paddr() const { return _pfn() << PageShift; } +}; + +// ITB/DTB table entry +struct TlbEntry +{ + Addr tag; // virtual page number tag + Addr ppn; // physical page number + uint8_t xre; // read permissions - VMEM_PERM_* mask + uint8_t xwe; // write permissions - VMEM_PERM_* mask + uint8_t asn; // address space number + bool asma; // address space match + bool fonr; // fault on read + bool fonw; // fault on write + bool valid; // valid page table entry + + + //Construct an entry that maps to physical address addr. + TlbEntry(Addr _asn, Addr _vaddr, Addr _paddr) { - PageTableEntry(uint64_t e) : entry(e) {} - uint64_t entry; - operator uint64_t() const { return entry; } - const PageTableEntry &operator=(uint64_t e) { entry = e; return *this; } - const PageTableEntry &operator=(const PageTableEntry &e) - { entry = e.entry; return *this; } - - Addr _pfn() const { return (entry >> 32) & 0xffffffff; } - Addr _sw() const { return (entry >> 16) & 0xffff; } - int _rsv0() const { return (entry >> 14) & 0x3; } - bool _uwe() const { return (entry >> 13) & 0x1; } - bool _kwe() const { return (entry >> 12) & 0x1; } - int _rsv1() const { return (entry >> 10) & 0x3; } - bool _ure() const { return (entry >> 9) & 0x1; } - bool _kre() const { return (entry >> 8) & 0x1; } - bool _nomb() const { return (entry >> 7) & 0x1; } - int _gh() const { return (entry >> 5) & 0x3; } - bool _asm_() const { return (entry >> 4) & 0x1; } - bool _foe() const { return (entry >> 3) & 0x1; } - bool _fow() const { return (entry >> 2) & 0x1; } - bool _for() const { return (entry >> 1) & 0x1; } - bool valid() const { return (entry >> 0) & 0x1; } - - Addr paddr() const { return _pfn() << PageShift; } - }; - - // ITB/DTB table entry - struct TlbEntry + VAddr vaddr(_vaddr); + VAddr paddr(_paddr); + tag = vaddr.vpn(); + ppn = paddr.vpn(); + xre = 15; + xwe = 15; + asn = _asn; + asma = false; + fonr = false; + fonw = false; + valid = true; + } + + TlbEntry() + {} + + Addr + pageStart() { - //Construct an entry that maps to physical address addr. - TlbEntry(Addr _asn, Addr _vaddr, Addr _paddr) - { - VAddr vaddr(_vaddr); - VAddr paddr(_paddr); - tag = vaddr.vpn(); - ppn = paddr.vpn(); - xre = 15; - xwe = 15; - asn = _asn; - asma = false; - fonr = false; - fonw = false; - valid = true; - } - TlbEntry() - {} - - Addr tag; // virtual page number tag - Addr ppn; // physical page number - uint8_t xre; // read permissions - VMEM_PERM_* mask - uint8_t xwe; // write permissions - VMEM_PERM_* mask - uint8_t asn; // address space number - bool asma; // address space match - bool fonr; // fault on read - bool fonw; // fault on write - bool valid; // valid page table entry - - Addr pageStart() - { - return ppn << PageShift; - } - - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); - }; + return ppn << PageShift; + } + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); }; + +} // namespace AlphaISA + #endif // __ARCH_ALPHA_PAGETABLE_H__ diff --git a/src/arch/alpha/predecoder.hh b/src/arch/alpha/predecoder.hh index 725b35b9d..5502342e1 100644 --- a/src/arch/alpha/predecoder.hh +++ b/src/arch/alpha/predecoder.hh @@ -38,62 +38,72 @@ class ThreadContext; -namespace AlphaISA +namespace AlphaISA { + +class Predecoder { - class Predecoder + protected: + ThreadContext *tc; + + // The extended machine instruction being generated + ExtMachInst ext_inst; + + public: + Predecoder(ThreadContext * _tc) + : tc(_tc) + {} + + ThreadContext * + getTC() { - protected: - ThreadContext * tc; - //The extended machine instruction being generated - ExtMachInst ext_inst; - - public: - Predecoder(ThreadContext * _tc) : tc(_tc) - {} - - ThreadContext * getTC() - { - return tc; - } - - void setTC(ThreadContext * _tc) - { - tc = _tc; - } - - void process() - { - } - - void reset() - {} - - //Use this to give data to the predecoder. This should be used - //when there is control flow. - void moreBytes(Addr pc, Addr fetchPC, MachInst inst) - { - ext_inst = inst; + return tc; + } + + void + setTC(ThreadContext * _tc) + { + tc = _tc; + } + + void + process() + { } + + void + reset() + { } + + // Use this to give data to the predecoder. This should be used + // when there is control flow. + void + moreBytes(Addr pc, Addr fetchPC, MachInst inst) + { + ext_inst = inst; #if FULL_SYSTEM - ext_inst|=(static_cast(pc & 0x1) << 32); + ext_inst |= (static_cast(pc & 0x1) << 32); #endif - } - - bool needMoreBytes() - { - return true; - } - - bool extMachInstReady() - { - return true; - } - - //This returns a constant reference to the ExtMachInst to avoid a copy - const ExtMachInst & getExtMachInst() - { - return ext_inst; - } - }; + } + + bool + needMoreBytes() + { + return true; + } + + bool + extMachInstReady() + { + return true; + } + + // This returns a constant reference to the ExtMachInst to avoid a copy + const ExtMachInst & + getExtMachInst() + { + return ext_inst; + } }; +} // namespace AlphaISA + #endif // __ARCH_ALPHA_PREDECODER_HH__ diff --git a/src/arch/alpha/process.cc b/src/arch/alpha/process.cc index c2d23ecdd..380e0e18e 100644 --- a/src/arch/alpha/process.cc +++ b/src/arch/alpha/process.cc @@ -36,12 +36,11 @@ #include "cpu/thread_context.hh" #include "sim/system.hh" - using namespace AlphaISA; using namespace std; -AlphaLiveProcess::AlphaLiveProcess(LiveProcessParams * params, - ObjectFile *objFile) +AlphaLiveProcess::AlphaLiveProcess(LiveProcessParams *params, + ObjectFile *objFile) : LiveProcess(params, objFile) { brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize(); @@ -77,4 +76,3 @@ AlphaLiveProcess::startup() threadContexts[0]->setMiscRegNoEffect(IPR_DTB_ASN, M5_pid << 57); } - diff --git a/src/arch/alpha/process.hh b/src/arch/alpha/process.hh index c66b97d23..0aeeb25db 100644 --- a/src/arch/alpha/process.hh +++ b/src/arch/alpha/process.hh @@ -29,24 +29,20 @@ * Ali Saidi */ -#ifndef __ALPHA_PROCESS_HH__ -#define __ALPHA_PROCESS_HH__ +#ifndef __ARCH_ALPHA_PROCESS_HH__ +#define __ARCH_ALPHA_PROCESS_HH__ -#include -#include #include "sim/process.hh" class ObjectFile; class System; - class AlphaLiveProcess : public LiveProcess { protected: - AlphaLiveProcess(LiveProcessParams * params, ObjectFile *objFile); + AlphaLiveProcess(LiveProcessParams *params, ObjectFile *objFile); void startup(); }; - -#endif // __ALPHA_PROCESS_HH__ +#endif // __ARCH_ALPHA_PROCESS_HH__ diff --git a/src/arch/alpha/regfile.cc b/src/arch/alpha/regfile.cc index e617b00ae..cd648844f 100644 --- a/src/arch/alpha/regfile.cc +++ b/src/arch/alpha/regfile.cc @@ -33,67 +33,66 @@ #include "arch/alpha/regfile.hh" #include "cpu/thread_context.hh" -namespace AlphaISA +namespace AlphaISA { + +void +RegFile::serialize(std::ostream &os) { - void - RegFile::serialize(std::ostream &os) - { - intRegFile.serialize(os); - floatRegFile.serialize(os); - miscRegFile.serialize(os); - SERIALIZE_SCALAR(pc); - SERIALIZE_SCALAR(npc); + intRegFile.serialize(os); + floatRegFile.serialize(os); + miscRegFile.serialize(os); + SERIALIZE_SCALAR(pc); + SERIALIZE_SCALAR(npc); #if FULL_SYSTEM - SERIALIZE_SCALAR(intrflag); + SERIALIZE_SCALAR(intrflag); #endif - } +} - void - RegFile::unserialize(Checkpoint *cp, const std::string §ion) - { - intRegFile.unserialize(cp, section); - floatRegFile.unserialize(cp, section); - miscRegFile.unserialize(cp, section); - UNSERIALIZE_SCALAR(pc); - UNSERIALIZE_SCALAR(npc); +void +RegFile::unserialize(Checkpoint *cp, const std::string §ion) +{ + intRegFile.unserialize(cp, section); + floatRegFile.unserialize(cp, section); + miscRegFile.unserialize(cp, section); + UNSERIALIZE_SCALAR(pc); + UNSERIALIZE_SCALAR(npc); #if FULL_SYSTEM - UNSERIALIZE_SCALAR(intrflag); + UNSERIALIZE_SCALAR(intrflag); #endif - } +} - void - copyRegs(ThreadContext *src, ThreadContext *dest) - { - // First loop through the integer registers. - for (int i = 0; i < NumIntRegs; ++i) { - dest->setIntReg(i, src->readIntReg(i)); - } +void +copyRegs(ThreadContext *src, ThreadContext *dest) +{ + // First loop through the integer registers. + for (int i = 0; i < NumIntRegs; ++i) + dest->setIntReg(i, src->readIntReg(i)); - // Then loop through the floating point registers. - for (int i = 0; i < NumFloatRegs; ++i) { - dest->setFloatRegBits(i, src->readFloatRegBits(i)); - } + // Then loop through the floating point registers. + for (int i = 0; i < NumFloatRegs; ++i) + dest->setFloatRegBits(i, src->readFloatRegBits(i)); - // Copy misc. registers - copyMiscRegs(src, dest); + // Copy misc. registers + copyMiscRegs(src, dest); - // Lastly copy PC/NPC - dest->setPC(src->readPC()); - dest->setNextPC(src->readNextPC()); - } + // Lastly copy PC/NPC + dest->setPC(src->readPC()); + dest->setNextPC(src->readNextPC()); +} - void - copyMiscRegs(ThreadContext *src, ThreadContext *dest) - { - dest->setMiscRegNoEffect(MISCREG_FPCR, - src->readMiscRegNoEffect(MISCREG_FPCR)); - dest->setMiscRegNoEffect(MISCREG_UNIQ, - src->readMiscRegNoEffect(MISCREG_UNIQ)); - dest->setMiscRegNoEffect(MISCREG_LOCKFLAG, - src->readMiscRegNoEffect(MISCREG_LOCKFLAG)); - dest->setMiscRegNoEffect(MISCREG_LOCKADDR, - src->readMiscRegNoEffect(MISCREG_LOCKADDR)); +void +copyMiscRegs(ThreadContext *src, ThreadContext *dest) +{ + dest->setMiscRegNoEffect(MISCREG_FPCR, + src->readMiscRegNoEffect(MISCREG_FPCR)); + dest->setMiscRegNoEffect(MISCREG_UNIQ, + src->readMiscRegNoEffect(MISCREG_UNIQ)); + dest->setMiscRegNoEffect(MISCREG_LOCKFLAG, + src->readMiscRegNoEffect(MISCREG_LOCKFLAG)); + dest->setMiscRegNoEffect(MISCREG_LOCKADDR, + src->readMiscRegNoEffect(MISCREG_LOCKADDR)); - copyIprs(src, dest); - } + copyIprs(src, dest); } + +} // namespace AlphaISA diff --git a/src/arch/alpha/regfile.hh b/src/arch/alpha/regfile.hh index 0c1f07bdd..c9fa8a91b 100644 --- a/src/arch/alpha/regfile.hh +++ b/src/arch/alpha/regfile.hh @@ -45,161 +45,190 @@ class Checkpoint; class ThreadContext; -namespace AlphaISA -{ - - class RegFile { +namespace AlphaISA { - protected: - Addr pc; // program counter - Addr npc; // next-cycle program counter - Addr nnpc; +class RegFile { + protected: + Addr pc; // program counter + Addr npc; // next-cycle program counter + Addr nnpc; // next next-cycle program counter - public: - Addr readPC() - { - return pc; - } - - void setPC(Addr val) - { - pc = val; - } + public: + Addr + readPC() + { + return pc; + } - Addr readNextPC() - { - return npc; - } + void + setPC(Addr val) + { + pc = val; + } - void setNextPC(Addr val) - { - npc = val; - } + Addr + readNextPC() + { + return npc; + } - Addr readNextNPC() - { - return npc + sizeof(MachInst); - } + void + setNextPC(Addr val) + { + npc = val; + } - void setNextNPC(Addr val) - { } + Addr + readNextNPC() + { + return npc + sizeof(MachInst); + } - protected: - IntRegFile intRegFile; // (signed) integer register file - FloatRegFile floatRegFile; // floating point register file - MiscRegFile miscRegFile; // control register file + void + setNextNPC(Addr val) + { } - public: + protected: + IntRegFile intRegFile; // (signed) integer register file + FloatRegFile floatRegFile; // floating point register file + MiscRegFile miscRegFile; // control register file + public: #if FULL_SYSTEM - int intrflag; // interrupt flag - inline int instAsid() - { return miscRegFile.getInstAsid(); } - inline int dataAsid() - { return miscRegFile.getDataAsid(); } -#endif // FULL_SYSTEM + int intrflag; // interrupt flag - void clear() - { - intRegFile.clear(); - floatRegFile.clear(); - miscRegFile.clear(); - } - - MiscReg readMiscRegNoEffect(int miscReg) - { - return miscRegFile.readRegNoEffect(miscReg); - } + int + instAsid() + { + return miscRegFile.getInstAsid(); + } - MiscReg readMiscReg(int miscReg, ThreadContext *tc) - { - return miscRegFile.readReg(miscReg, tc); - } + int + dataAsid() + { + return miscRegFile.getDataAsid(); + } +#endif // FULL_SYSTEM - void setMiscRegNoEffect(int miscReg, const MiscReg &val) - { - miscRegFile.setRegNoEffect(miscReg, val); - } + void + clear() + { + intRegFile.clear(); + floatRegFile.clear(); + miscRegFile.clear(); + } - void setMiscReg(int miscReg, const MiscReg &val, - ThreadContext * tc) - { - miscRegFile.setReg(miscReg, val, tc); - } + MiscReg + readMiscRegNoEffect(int miscReg) + { + return miscRegFile.readRegNoEffect(miscReg); + } - FloatReg readFloatReg(int floatReg) - { - return floatRegFile.d[floatReg]; - } + MiscReg + readMiscReg(int miscReg, ThreadContext *tc) + { + return miscRegFile.readReg(miscReg, tc); + } - FloatReg readFloatReg(int floatReg, int width) - { - return readFloatReg(floatReg); - } + void + setMiscRegNoEffect(int miscReg, const MiscReg &val) + { + miscRegFile.setRegNoEffect(miscReg, val); + } - FloatRegBits readFloatRegBits(int floatReg) - { - return floatRegFile.q[floatReg]; - } + void + setMiscReg(int miscReg, const MiscReg &val, ThreadContext *tc) + { + miscRegFile.setReg(miscReg, val, tc); + } - FloatRegBits readFloatRegBits(int floatReg, int width) - { - return readFloatRegBits(floatReg); - } + FloatReg + readFloatReg(int floatReg) + { + return floatRegFile.d[floatReg]; + } - void setFloatReg(int floatReg, const FloatReg &val) - { - floatRegFile.d[floatReg] = val; - } + FloatReg + readFloatReg(int floatReg, int width) + { + return readFloatReg(floatReg); + } - void setFloatReg(int floatReg, const FloatReg &val, int width) - { - setFloatReg(floatReg, val); - } + FloatRegBits + readFloatRegBits(int floatReg) + { + return floatRegFile.q[floatReg]; + } - void setFloatRegBits(int floatReg, const FloatRegBits &val) - { - floatRegFile.q[floatReg] = val; - } + FloatRegBits + readFloatRegBits(int floatReg, int width) + { + return readFloatRegBits(floatReg); + } - void setFloatRegBits(int floatReg, const FloatRegBits &val, int width) - { - setFloatRegBits(floatReg, val); - } + void + setFloatReg(int floatReg, const FloatReg &val) + { + floatRegFile.d[floatReg] = val; + } - IntReg readIntReg(int intReg) - { - return intRegFile.readReg(intReg); - } + void + setFloatReg(int floatReg, const FloatReg &val, int width) + { + setFloatReg(floatReg, val); + } - void setIntReg(int intReg, const IntReg &val) - { - intRegFile.setReg(intReg, val); - } + void + setFloatRegBits(int floatReg, const FloatRegBits &val) + { + floatRegFile.q[floatReg] = val; + } - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); + void + setFloatRegBits(int floatReg, const FloatRegBits &val, int width) + { + setFloatRegBits(floatReg, val); + } - void changeContext(RegContextParam param, RegContextVal val) - { - //This would be an alternative place to call/implement - //the swapPALShadow function - } - }; + IntReg + readIntReg(int intReg) + { + return intRegFile.readReg(intReg); + } - static inline int flattenIntIndex(ThreadContext * tc, int reg) + void + setIntReg(int intReg, const IntReg &val) { - return reg; + intRegFile.setReg(intReg, val); } - static inline int flattenFloatIndex(ThreadContext * tc, int reg) + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); + + void + changeContext(RegContextParam param, RegContextVal val) { - return reg; + //This would be an alternative place to call/implement + //the swapPALShadow function } +}; + +static inline int +flattenIntIndex(ThreadContext * tc, int reg) +{ + return reg; +} + +static inline int +flattenFloatIndex(ThreadContext * tc, int reg) +{ + return reg; +} + +void copyRegs(ThreadContext *src, ThreadContext *dest); - void copyRegs(ThreadContext *src, ThreadContext *dest); +void copyMiscRegs(ThreadContext *src, ThreadContext *dest); - void copyMiscRegs(ThreadContext *src, ThreadContext *dest); } // namespace AlphaISA -#endif +#endif // __ARCH_ALPHA_REGFILE_HH__ diff --git a/src/arch/alpha/remote_gdb.cc b/src/arch/alpha/remote_gdb.cc index 22a1f5224..c47293b98 100644 --- a/src/arch/alpha/remote_gdb.cc +++ b/src/arch/alpha/remote_gdb.cc @@ -117,9 +117,9 @@ */ #include +#include #include -#include #include "config/full_system.hh" #if FULL_SYSTEM @@ -142,17 +142,15 @@ using namespace std; using namespace AlphaISA; -RemoteGDB::RemoteGDB(System *_system, ThreadContext *c) - : BaseRemoteGDB(_system, c, KGDB_NUMREGS) +RemoteGDB::RemoteGDB(System *_system, ThreadContext *tc) + : BaseRemoteGDB(_system, tc, KGDB_NUMREGS) { memset(gdbregs.regs, 0, gdbregs.bytes()); } -/////////////////////////////////////////////////////////// -// RemoteGDB::acc -// -// Determine if the mapping at va..(va+len) is valid. -// +/* + * Determine if the mapping at va..(va+len) is valid. + */ bool RemoteGDB::acc(Addr va, size_t len) { @@ -177,18 +175,20 @@ RemoteGDB::acc(Addr va, size_t len) } } - /** - * This code says that all accesses to palcode (instruction and data) - * are valid since there isn't a va->pa mapping because palcode is - * accessed physically. At some point this should probably be cleaned up - * but there is no easy way to do it. - */ + /** + * This code says that all accesses to palcode (instruction + * and data) are valid since there isn't a va->pa mapping + * because palcode is accessed physically. At some point this + * should probably be cleaned up but there is no easy way to + * do it. + */ if (PcPAL(va) || va < 0x10000) return true; Addr ptbr = context->readMiscRegNoEffect(IPR_PALtemp20); - PageTableEntry pte = kernel_pte_lookup(context->getPhysPort(), ptbr, va); + PageTableEntry pte = + kernel_pte_lookup(context->getPhysPort(), ptbr, va); if (!pte.valid()) { DPRINTF(GDBAcc, "acc: %#x pte is invalid\n", va); return false; @@ -201,11 +201,10 @@ RemoteGDB::acc(Addr va, size_t len) #endif } -/////////////////////////////////////////////////////////// -// RemoteGDB::getregs -// -// Translate the kernel debugger register format into -// the GDB register format. +/* + * Translate the kernel debugger register format into the GDB register + * format. + */ void RemoteGDB::getregs() { @@ -231,12 +230,10 @@ RemoteGDB::getregs() #endif } -/////////////////////////////////////////////////////////// -// RemoteGDB::setregs -// -// Translate the GDB register format into the kernel -// debugger register format. -// +/* + * Translate the GDB register format into the kernel debugger register + * format. + */ void RemoteGDB::setregs() { diff --git a/src/arch/alpha/remote_gdb.hh b/src/arch/alpha/remote_gdb.hh index 7bef183c3..43d0580d8 100644 --- a/src/arch/alpha/remote_gdb.hh +++ b/src/arch/alpha/remote_gdb.hh @@ -44,31 +44,29 @@ class System; class ThreadContext; class PhysicalMemory; -namespace AlphaISA -{ - class RemoteGDB : public BaseRemoteGDB - { - protected: - // Machine memory - bool write(Addr addr, size_t size, const char *data); +namespace AlphaISA { - public: - RemoteGDB(System *system, ThreadContext *context); +class RemoteGDB : public BaseRemoteGDB +{ + protected: + Addr notTakenBkpt; + Addr takenBkpt; - bool acc(Addr addr, size_t len); + protected: + void getregs(); + void setregs(); - protected: - void getregs(); - void setregs(); + void clearSingleStep(); + void setSingleStep(); - void clearSingleStep(); - void setSingleStep(); + // Machine memory + bool acc(Addr addr, size_t len); + bool write(Addr addr, size_t size, const char *data); - protected: + public: + RemoteGDB(System *system, ThreadContext *context); +}; - Addr notTakenBkpt; - Addr takenBkpt; - }; -} +} // namespace AlphaISA -#endif /* __ARCH_ALPHA_REMOTE_GDB_H__ */ +#endif // __ARCH_ALPHA_REMOTE_GDB_HH__ diff --git a/src/arch/alpha/stacktrace.cc b/src/arch/alpha/stacktrace.cc index a29a4eb4d..1b5a9be34 100644 --- a/src/arch/alpha/stacktrace.cc +++ b/src/arch/alpha/stacktrace.cc @@ -41,326 +41,326 @@ using namespace std; -namespace AlphaISA +namespace AlphaISA { + +ProcessInfo::ProcessInfo(ThreadContext *_tc) + : tc(_tc) { - ProcessInfo::ProcessInfo(ThreadContext *_tc) - : tc(_tc) - { - Addr addr = 0; + Addr addr = 0; + VirtualPort *vp = tc->getVirtPort(); + SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; - VirtualPort *vp; + if (!symtab->findAddress("thread_info_size", addr)) + panic("thread info not compiled into kernel\n"); + thread_info_size = vp->readGtoH(addr); - vp = tc->getVirtPort(); + if (!symtab->findAddress("task_struct_size", addr)) + panic("thread info not compiled into kernel\n"); + task_struct_size = vp->readGtoH(addr); - if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr)) - panic("thread info not compiled into kernel\n"); - thread_info_size = vp->readGtoH(addr); + if (!symtab->findAddress("thread_info_task", addr)) + panic("thread info not compiled into kernel\n"); + task_off = vp->readGtoH(addr); - if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr)) - panic("thread info not compiled into kernel\n"); - task_struct_size = vp->readGtoH(addr); + if (!symtab->findAddress("task_struct_pid", addr)) + panic("thread info not compiled into kernel\n"); + pid_off = vp->readGtoH(addr); - if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr)) - panic("thread info not compiled into kernel\n"); - task_off = vp->readGtoH(addr); + if (!symtab->findAddress("task_struct_comm", addr)) + panic("thread info not compiled into kernel\n"); + name_off = vp->readGtoH(addr); +} - if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr)) - panic("thread info not compiled into kernel\n"); - pid_off = vp->readGtoH(addr); +Addr +ProcessInfo::task(Addr ksp) const +{ + Addr base = ksp & ~0x3fff; + if (base == ULL(0xfffffc0000000000)) + return 0; - if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr)) - panic("thread info not compiled into kernel\n"); - name_off = vp->readGtoH(addr); - } + Addr tsk; - Addr - ProcessInfo::task(Addr ksp) const - { - Addr base = ksp & ~0x3fff; - if (base == ULL(0xfffffc0000000000)) - return 0; + VirtualPort *vp; - Addr tsk; + vp = tc->getVirtPort(); + tsk = vp->readGtoH(base + task_off); - VirtualPort *vp; + return tsk; +} - vp = tc->getVirtPort(); - tsk = vp->readGtoH(base + task_off); +int +ProcessInfo::pid(Addr ksp) const +{ + Addr task = this->task(ksp); + if (!task) + return -1; - return tsk; - } + uint16_t pd; - int - ProcessInfo::pid(Addr ksp) const - { - Addr task = this->task(ksp); - if (!task) - return -1; + VirtualPort *vp; - uint16_t pd; + vp = tc->getVirtPort(); + pd = vp->readGtoH(task + pid_off); - VirtualPort *vp; + return pd; +} - vp = tc->getVirtPort(); - pd = vp->readGtoH(task + pid_off); +string +ProcessInfo::name(Addr ksp) const +{ + Addr task = this->task(ksp); + if (!task) + return "console"; - return pd; - } + char comm[256]; + CopyStringOut(tc, comm, task + name_off, sizeof(comm)); + if (!comm[0]) + return "startup"; - string - ProcessInfo::name(Addr ksp) const - { - Addr task = this->task(ksp); - if (!task) - return "console"; + return comm; +} - char comm[256]; - CopyStringOut(tc, comm, task + name_off, sizeof(comm)); - if (!comm[0]) - return "startup"; +StackTrace::StackTrace() + : tc(0), stack(64) +{ +} - return comm; - } +StackTrace::StackTrace(ThreadContext *_tc, StaticInstPtr inst) + : tc(0), stack(64) +{ + trace(_tc, inst); +} - StackTrace::StackTrace() - : tc(0), stack(64) - { - } +StackTrace::~StackTrace() +{ +} - StackTrace::StackTrace(ThreadContext *_tc, StaticInstPtr inst) - : tc(0), stack(64) - { - trace(_tc, inst); - } +void +StackTrace::trace(ThreadContext *_tc, bool is_call) +{ + tc = _tc; - StackTrace::~StackTrace() - { - } + System *sys = tc->getSystemPtr(); - void - StackTrace::trace(ThreadContext *_tc, bool is_call) - { - tc = _tc; + bool usermode = + (tc->readMiscRegNoEffect(IPR_DTB_CM) & 0x18) != 0; - bool usermode = (tc->readMiscRegNoEffect(IPR_DTB_CM) & 0x18) != 0; + Addr pc = tc->readNextPC(); + bool kernel = sys->kernelStart <= pc && pc <= sys->kernelEnd; - Addr pc = tc->readNextPC(); - bool kernel = tc->getSystemPtr()->kernelStart <= pc && - pc <= tc->getSystemPtr()->kernelEnd; + if (usermode) { + stack.push_back(user); + return; + } - if (usermode) { - stack.push_back(user); - return; - } + if (!kernel) { + stack.push_back(console); + return; + } - if (!kernel) { - stack.push_back(console); - return; - } + SymbolTable *symtab = sys->kernelSymtab; + Addr ksp = tc->readIntReg(StackPointerReg); + Addr bottom = ksp & ~0x3fff; - SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; - Addr ksp = tc->readIntReg(StackPointerReg); - Addr bottom = ksp & ~0x3fff; + if (is_call) { Addr addr; + if (!symtab->findNearestAddr(pc, addr)) + panic("could not find address %#x", pc); - if (is_call) { - if (!symtab->findNearestAddr(pc, addr)) - panic("could not find address %#x", pc); - - stack.push_back(addr); - pc = tc->readPC(); - } + stack.push_back(addr); + pc = tc->readPC(); + } - Addr ra; - int size; + while (ksp > bottom) { + Addr addr; + if (!symtab->findNearestAddr(pc, addr)) + panic("could not find symbol for pc=%#x", pc); + assert(pc >= addr && "symbol botch: callpc < func"); - while (ksp > bottom) { - if (!symtab->findNearestAddr(pc, addr)) - panic("could not find symbol for pc=%#x", pc); - assert(pc >= addr && "symbol botch: callpc < func"); + stack.push_back(addr); - stack.push_back(addr); + if (isEntry(addr)) + return; - if (isEntry(addr)) + Addr ra; + int size; + if (decodePrologue(ksp, pc, addr, size, ra)) { + if (!ra) return; - if (decodePrologue(ksp, pc, addr, size, ra)) { - if (!ra) - return; - - if (size <= 0) { - stack.push_back(unknown); - return; - } - - pc = ra; - ksp += size; - } else { + if (size <= 0) { stack.push_back(unknown); return; } - bool kernel = tc->getSystemPtr()->kernelStart <= pc && - pc <= tc->getSystemPtr()->kernelEnd; - if (!kernel) - return; - - if (stack.size() >= 1000) - panic("unwinding too far"); + pc = ra; + ksp += size; + } else { + stack.push_back(unknown); + return; } - panic("unwinding too far"); + bool kernel = sys->kernelStart <= pc && pc <= sys->kernelEnd; + if (!kernel) + return; + + if (stack.size() >= 1000) + panic("unwinding too far"); } - bool - StackTrace::isEntry(Addr addr) - { - if (addr == tc->readMiscRegNoEffect(IPR_PALtemp12)) - return true; + panic("unwinding too far"); +} - if (addr == tc->readMiscRegNoEffect(IPR_PALtemp7)) - return true; +bool +StackTrace::isEntry(Addr addr) +{ + if (addr == tc->readMiscRegNoEffect(IPR_PALtemp12)) + return true; - if (addr == tc->readMiscRegNoEffect(IPR_PALtemp11)) - return true; + if (addr == tc->readMiscRegNoEffect(IPR_PALtemp7)) + return true; - if (addr == tc->readMiscRegNoEffect(IPR_PALtemp21)) - return true; + if (addr == tc->readMiscRegNoEffect(IPR_PALtemp11)) + return true; - if (addr == tc->readMiscRegNoEffect(IPR_PALtemp9)) - return true; + if (addr == tc->readMiscRegNoEffect(IPR_PALtemp21)) + return true; - if (addr == tc->readMiscRegNoEffect(IPR_PALtemp2)) - return true; + if (addr == tc->readMiscRegNoEffect(IPR_PALtemp9)) + return true; - return false; - } + if (addr == tc->readMiscRegNoEffect(IPR_PALtemp2)) + return true; - bool - StackTrace::decodeStack(MachInst inst, int &disp) - { - // lda $sp, -disp($sp) - // - // Opcode<31:26> == 0x08 - // RA<25:21> == 30 - // RB<20:16> == 30 - // Disp<15:0> - const MachInst mem_mask = 0xffff0000; - const MachInst lda_pattern = 0x23de0000; - const MachInst lda_disp_mask = 0x0000ffff; - - // subq $sp, disp, $sp - // addq $sp, disp, $sp - // - // Opcode<31:26> == 0x10 - // RA<25:21> == 30 - // Lit<20:13> - // One<12> = 1 - // Func<11:5> == 0x20 (addq) - // Func<11:5> == 0x29 (subq) - // RC<4:0> == 30 - const MachInst intop_mask = 0xffe01fff; - const MachInst addq_pattern = 0x43c0141e; - const MachInst subq_pattern = 0x43c0153e; - const MachInst intop_disp_mask = 0x001fe000; - const int intop_disp_shift = 13; - - if ((inst & mem_mask) == lda_pattern) - disp = -sext<16>(inst & lda_disp_mask); - else if ((inst & intop_mask) == addq_pattern) - disp = -int((inst & intop_disp_mask) >> intop_disp_shift); - else if ((inst & intop_mask) == subq_pattern) - disp = int((inst & intop_disp_mask) >> intop_disp_shift); - else - return false; + return false; +} - return true; - } +bool +StackTrace::decodeStack(MachInst inst, int &disp) +{ + // lda $sp, -disp($sp) + // + // Opcode<31:26> == 0x08 + // RA<25:21> == 30 + // RB<20:16> == 30 + // Disp<15:0> + const MachInst mem_mask = 0xffff0000; + const MachInst lda_pattern = 0x23de0000; + const MachInst lda_disp_mask = 0x0000ffff; + + // subq $sp, disp, $sp + // addq $sp, disp, $sp + // + // Opcode<31:26> == 0x10 + // RA<25:21> == 30 + // Lit<20:13> + // One<12> = 1 + // Func<11:5> == 0x20 (addq) + // Func<11:5> == 0x29 (subq) + // RC<4:0> == 30 + const MachInst intop_mask = 0xffe01fff; + const MachInst addq_pattern = 0x43c0141e; + const MachInst subq_pattern = 0x43c0153e; + const MachInst intop_disp_mask = 0x001fe000; + const int intop_disp_shift = 13; + + if ((inst & mem_mask) == lda_pattern) + disp = -sext<16>(inst & lda_disp_mask); + else if ((inst & intop_mask) == addq_pattern) + disp = -int((inst & intop_disp_mask) >> intop_disp_shift); + else if ((inst & intop_mask) == subq_pattern) + disp = int((inst & intop_disp_mask) >> intop_disp_shift); + else + return false; - bool - StackTrace::decodeSave(MachInst inst, int ®, int &disp) - { - // lda $stq, disp($sp) - // - // Opcode<31:26> == 0x08 - // RA<25:21> == ? - // RB<20:16> == 30 - // Disp<15:0> - const MachInst stq_mask = 0xfc1f0000; - const MachInst stq_pattern = 0xb41e0000; - const MachInst stq_disp_mask = 0x0000ffff; - const MachInst reg_mask = 0x03e00000; - const int reg_shift = 21; - - if ((inst & stq_mask) == stq_pattern) { - reg = (inst & reg_mask) >> reg_shift; - disp = sext<16>(inst & stq_disp_mask); - } else { - return false; - } + return true; +} - return true; +bool +StackTrace::decodeSave(MachInst inst, int ®, int &disp) +{ + // lda $stq, disp($sp) + // + // Opcode<31:26> == 0x08 + // RA<25:21> == ? + // RB<20:16> == 30 + // Disp<15:0> + const MachInst stq_mask = 0xfc1f0000; + const MachInst stq_pattern = 0xb41e0000; + const MachInst stq_disp_mask = 0x0000ffff; + const MachInst reg_mask = 0x03e00000; + const int reg_shift = 21; + + if ((inst & stq_mask) == stq_pattern) { + reg = (inst & reg_mask) >> reg_shift; + disp = sext<16>(inst & stq_disp_mask); + } else { + return false; } - /* - * Decode the function prologue for the function we're in, and note - * which registers are stored where, and how large the stack frame is. - */ - bool - StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func, - int &size, Addr &ra) - { - size = 0; - ra = 0; - - for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) { - MachInst inst; - CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst)); - - int reg, disp; - if (decodeStack(inst, disp)) { - if (size) { - // panic("decoding frame size again"); - return true; - } - size += disp; - } else if (decodeSave(inst, reg, disp)) { - if (!ra && reg == ReturnAddressReg) { - CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr)); - if (!ra) { - // panic("no return address value pc=%#x\n", pc); - return false; - } + return true; +} + +/* + * Decode the function prologue for the function we're in, and note + * which registers are stored where, and how large the stack frame is. + */ +bool +StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func, int &size, + Addr &ra) +{ + size = 0; + ra = 0; + + for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) { + MachInst inst; + CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst)); + + int reg, disp; + if (decodeStack(inst, disp)) { + if (size) { + // panic("decoding frame size again"); + return true; + } + size += disp; + } else if (decodeSave(inst, reg, disp)) { + if (!ra && reg == ReturnAddressReg) { + CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr)); + if (!ra) { + // panic("no return address value pc=%#x\n", pc); + return false; } } } - - return true; } + return true; +} + #if TRACING_ON - void - StackTrace::dump() - { - StringWrap name(tc->getCpuPtr()->name()); - SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; - - DPRINTFN("------ Stack ------\n"); - - string symbol; - for (int i = 0, size = stack.size(); i < size; ++i) { - Addr addr = stack[size - i - 1]; - if (addr == user) - symbol = "user"; - else if (addr == console) - symbol = "console"; - else if (addr == unknown) - symbol = "unknown"; - else - symtab->findSymbol(addr, symbol); - - DPRINTFN("%#x: %s\n", addr, symbol); - } +void +StackTrace::dump() +{ + StringWrap name(tc->getCpuPtr()->name()); + SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; + + DPRINTFN("------ Stack ------\n"); + + string symbol; + for (int i = 0, size = stack.size(); i < size; ++i) { + Addr addr = stack[size - i - 1]; + if (addr == user) + symbol = "user"; + else if (addr == console) + symbol = "console"; + else if (addr == unknown) + symbol = "unknown"; + else + symtab->findSymbol(addr, symbol); + + DPRINTFN("%#x: %s\n", addr, symbol); } -#endif } +#endif + +} // namespace AlphaISA diff --git a/src/arch/alpha/stacktrace.hh b/src/arch/alpha/stacktrace.hh index 39fd3d286..db42c4399 100644 --- a/src/arch/alpha/stacktrace.hh +++ b/src/arch/alpha/stacktrace.hh @@ -36,88 +36,90 @@ class ThreadContext; -namespace AlphaISA -{ - class StackTrace; +namespace AlphaISA { - class ProcessInfo - { - private: - ThreadContext *tc; +class StackTrace; + +class ProcessInfo +{ + private: + ThreadContext *tc; - int thread_info_size; - int task_struct_size; - int task_off; - int pid_off; - int name_off; + int thread_info_size; + int task_struct_size; + int task_off; + int pid_off; + int name_off; - public: - ProcessInfo(ThreadContext *_tc); + public: + ProcessInfo(ThreadContext *_tc); - Addr task(Addr ksp) const; - int pid(Addr ksp) const; - std::string name(Addr ksp) const; - }; + Addr task(Addr ksp) const; + int pid(Addr ksp) const; + std::string name(Addr ksp) const; +}; - class StackTrace - { - private: - ThreadContext *tc; - std::vector stack; +class StackTrace +{ + private: + ThreadContext *tc; + std::vector stack; - private: - bool isEntry(Addr addr); - bool decodePrologue(Addr sp, Addr callpc, Addr func, int &size, Addr &ra); - bool decodeSave(MachInst inst, int ®, int &disp); - bool decodeStack(MachInst inst, int &disp); + private: + bool isEntry(Addr addr); + bool decodePrologue(Addr sp, Addr callpc, Addr func, int &size, Addr &ra); + bool decodeSave(MachInst inst, int ®, int &disp); + bool decodeStack(MachInst inst, int &disp); - void trace(ThreadContext *tc, bool is_call); + void trace(ThreadContext *tc, bool is_call); - public: - StackTrace(); - StackTrace(ThreadContext *tc, StaticInstPtr inst); - ~StackTrace(); + public: + StackTrace(); + StackTrace(ThreadContext *tc, StaticInstPtr inst); + ~StackTrace(); - void clear() - { - tc = 0; - stack.clear(); - } + void + clear() + { + tc = 0; + stack.clear(); + } - bool valid() const { return tc != NULL; } - bool trace(ThreadContext *tc, StaticInstPtr inst); + bool valid() const { return tc != NULL; } + bool trace(ThreadContext *tc, StaticInstPtr inst); - public: - const std::vector &getstack() const { return stack; } + public: + const std::vector &getstack() const { return stack; } - static const int user = 1; - static const int console = 2; - static const int unknown = 3; + static const int user = 1; + static const int console = 2; + static const int unknown = 3; #if TRACING_ON - private: - void dump(); + private: + void dump(); - public: - void dprintf() { if (DTRACE(Stack)) dump(); } + public: + void dprintf() { if (DTRACE(Stack)) dump(); } #else - public: - void dprintf() {} + public: + void dprintf() {} #endif - }; +}; - inline bool - StackTrace::trace(ThreadContext *tc, StaticInstPtr inst) - { - if (!inst->isCall() && !inst->isReturn()) - return false; +inline bool +StackTrace::trace(ThreadContext *tc, StaticInstPtr inst) +{ + if (!inst->isCall() && !inst->isReturn()) + return false; - if (valid()) - clear(); + if (valid()) + clear(); - trace(tc, !inst->isReturn()); - return true; - } + trace(tc, !inst->isReturn()); + return true; } +} // namespace AlphaISA + #endif // __ARCH_ALPHA_STACKTRACE_HH__ diff --git a/src/arch/alpha/syscallreturn.hh b/src/arch/alpha/syscallreturn.hh index 47b4ac8c7..776f34fbf 100644 --- a/src/arch/alpha/syscallreturn.hh +++ b/src/arch/alpha/syscallreturn.hh @@ -35,24 +35,25 @@ #include "cpu/thread_context.hh" #include "sim/syscallreturn.hh" -namespace AlphaISA +namespace AlphaISA { + +static inline void +setSyscallReturn(SyscallReturn return_value, ThreadContext *tc) { - static inline void setSyscallReturn(SyscallReturn return_value, - ThreadContext * tc) - { - // check for error condition. Alpha syscall convention is to - // indicate success/failure in reg a3 (r19) and put the - // return value itself in the standard return value reg (v0). - if (return_value.successful()) { - // no error - tc->setIntReg(SyscallSuccessReg, 0); - tc->setIntReg(ReturnValueReg, return_value.value()); - } else { - // got an error, return details - tc->setIntReg(SyscallSuccessReg, (IntReg)-1); - tc->setIntReg(ReturnValueReg, -return_value.value()); - } + // check for error condition. Alpha syscall convention is to + // indicate success/failure in reg a3 (r19) and put the + // return value itself in the standard return value reg (v0). + if (return_value.successful()) { + // no error + tc->setIntReg(SyscallSuccessReg, 0); + tc->setIntReg(ReturnValueReg, return_value.value()); + } else { + // got an error, return details + tc->setIntReg(SyscallSuccessReg, (IntReg)-1); + tc->setIntReg(ReturnValueReg, -return_value.value()); } } -#endif +} // namespace AlphaISA + +#endif // __ARCH_ALPHA_SYSCALLRETURN_HH__ diff --git a/src/arch/alpha/system.cc b/src/arch/alpha/system.cc index 6bff3d798..72d918870 100644 --- a/src/arch/alpha/system.cc +++ b/src/arch/alpha/system.cc @@ -116,7 +116,6 @@ AlphaSystem::AlphaSystem(Params *p) virtPort.write(addr+0x58, data); } else panic("could not find hwrpb\n"); - } AlphaSystem::~AlphaSystem() @@ -175,7 +174,7 @@ AlphaSystem::fixFuncEventAddr(Addr addr) if ((i1 & inst_mask) == gp_ldah_pattern && (i2 & inst_mask) == gp_lda_pattern) { - Addr new_addr = addr + 2* sizeof(MachInst); + Addr new_addr = addr + 2 * sizeof(MachInst); DPRINTF(Loader, "fixFuncEventAddr: %p -> %p", addr, new_addr); return new_addr; } else { @@ -183,15 +182,15 @@ AlphaSystem::fixFuncEventAddr(Addr addr) } } - void AlphaSystem::setAlphaAccess(Addr access) { Addr addr = 0; if (consoleSymtab->findAddress("m5AlphaAccess", addr)) { virtPort.write(addr, htog(Phys2K0Seg(access))); - } else + } else { panic("could not find m5AlphaAccess\n"); + } } void @@ -202,7 +201,6 @@ AlphaSystem::serialize(std::ostream &os) palSymtab->serialize("pal_symtab", os); } - void AlphaSystem::unserialize(Checkpoint *cp, const std::string §ion) { diff --git a/src/arch/alpha/system.hh b/src/arch/alpha/system.hh index a934550b7..da42ab263 100644 --- a/src/arch/alpha/system.hh +++ b/src/arch/alpha/system.hh @@ -49,10 +49,10 @@ class AlphaSystem : public System AlphaSystem(Params *p); ~AlphaSystem(); -/** - * Serialization stuff - */ public: + /** + * Serialization stuff + */ virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); @@ -77,26 +77,28 @@ class AlphaSystem : public System /** Event to halt the simulator if the console calls panic() */ BreakPCEvent *consolePanicEvent; #endif + protected: const Params *params() const { return (const Params *)_params; } /** Add a function-based event to PALcode. */ template - T *addPalFuncEvent(const char *lbl) + T * + addPalFuncEvent(const char *lbl) { return addFuncEvent(palSymtab, lbl); } /** Add a function-based event to the console code. */ template - T *addConsoleFuncEvent(const char *lbl) + T * + addConsoleFuncEvent(const char *lbl) { return addFuncEvent(consoleSymtab, lbl); } virtual Addr fixFuncEventAddr(Addr addr); - }; -#endif +#endif // __ARCH_ALPHA_SYSTEM_HH__ diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc index 5e231d4d8..9266b8337 100644 --- a/src/arch/alpha/tlb.cc +++ b/src/arch/alpha/tlb.cc @@ -45,16 +45,18 @@ using namespace std; namespace AlphaISA { + /////////////////////////////////////////////////////////////////////// // // Alpha TLB // + #ifdef DEBUG bool uncacheBit39 = false; bool uncacheBit40 = false; #endif -#define MODE2MASK(X) (1 << (X)) +#define MODE2MASK(X) (1 << (X)) TLB::TLB(const Params *p) : BaseTLB(p), size(p->size), nlu(0) @@ -113,20 +115,20 @@ TLB::lookup(Addr vpn, uint8_t asn) return retval; } - Fault TLB::checkCacheability(RequestPtr &req, bool itb) { -// in Alpha, cacheability is controlled by upper-level bits of the -// physical address - -/* - * We support having the uncacheable bit in either bit 39 or bit 40. - * The Turbolaser platform (and EV5) support having the bit in 39, but - * Tsunami (which Linux assumes uses an EV6) generates accesses with - * the bit in 40. So we must check for both, but we have debug flags - * to catch a weird case where both are used, which shouldn't happen. - */ + // in Alpha, cacheability is controlled by upper-level bits of the + // physical address + + /* + * We support having the uncacheable bit in either bit 39 or bit + * 40. The Turbolaser platform (and EV5) support having the bit + * in 39, but Tsunami (which Linux assumes uses an EV6) generates + * accesses with the bit in 40. So we must check for both, but we + * have debug flags to catch a weird case where both are used, + * which shouldn't happen. + */ #if ALPHA_TLASER @@ -143,7 +145,8 @@ TLB::checkCacheability(RequestPtr &req, bool itb) req->setFlags(req->getFlags() | UNCACHEABLE); #if !ALPHA_TLASER - // Clear bits 42:35 of the physical address (10-2 in Tsunami manual) + // Clear bits 42:35 of the physical address (10-2 in + // Tsunami manual) req->setPaddr(req->getPaddr() & PAddrUncachedMask); #endif } @@ -221,7 +224,8 @@ TLB::flushProcesses() ++i; if (!entry->asma) { - DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, entry->tag, entry->ppn); + DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, + entry->tag, entry->ppn); entry->valid = false; lookupTable.erase(cur); } @@ -284,7 +288,6 @@ TLB::unserialize(Checkpoint *cp, const string §ion) } } - /////////////////////////////////////////////////////////////////////// // // Alpha ITB @@ -313,12 +316,11 @@ ITB::regStats() accesses = hits + misses; } - Fault ITB::translate(RequestPtr &req, ThreadContext *tc) { //If this is a pal pc, then set PHYSICAL - if(FULL_SYSTEM && PcPAL(req->getPC())) + if (FULL_SYSTEM && PcPAL(req->getPC())) req->setFlags(req->getFlags() | PHYSICAL); if (PcPAL(req->getPC())) { @@ -403,7 +405,7 @@ ITB::translate(RequestPtr &req, ThreadContext *tc) // // Alpha DTB // - DTB::DTB(const Params *p) +DTB::DTB(const Params *p) : TLB(p) {} @@ -484,7 +486,6 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) mode_type mode = (mode_type)DTB_CM_CM(tc->readMiscRegNoEffect(IPR_DTB_CM)); - /** * Check for alignment faults */ @@ -522,14 +523,15 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) #endif { - // only valid in kernel mode if (DTB_CM_CM(tc->readMiscRegNoEffect(IPR_DTB_CM)) != mode_kernel) { if (write) { write_acv++; } else { read_acv++; } uint64_t flags = ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_ACV_MASK); - return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags); + + return new DtbAcvFault(req->getVaddr(), req->getFlags(), + flags); } req->setPaddr(req->getVaddr() & PAddrImplMask); @@ -575,25 +577,28 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) uint64_t flags = MM_STAT_WR_MASK | MM_STAT_ACV_MASK | (entry->fonw ? MM_STAT_FONW_MASK : 0); - return new DtbPageFault(req->getVaddr(), req->getFlags(), flags); + return new DtbPageFault(req->getVaddr(), req->getFlags(), + flags); } if (entry->fonw) { write_acv++; - uint64_t flags = MM_STAT_WR_MASK | - MM_STAT_FONW_MASK; - return new DtbPageFault(req->getVaddr(), req->getFlags(), flags); + uint64_t flags = MM_STAT_WR_MASK | MM_STAT_FONW_MASK; + return new DtbPageFault(req->getVaddr(), req->getFlags(), + flags); } } else { if (!(entry->xre & MODE2MASK(mode))) { read_acv++; uint64_t flags = MM_STAT_ACV_MASK | (entry->fonr ? MM_STAT_FONR_MASK : 0); - return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags); + return new DtbAcvFault(req->getVaddr(), req->getFlags(), + flags); } if (entry->fonr) { read_acv++; uint64_t flags = MM_STAT_FONR_MASK; - return new DtbPageFault(req->getVaddr(), req->getFlags(), flags); + return new DtbPageFault(req->getVaddr(), req->getFlags(), + flags); } } } @@ -622,7 +627,7 @@ TLB::index(bool advance) return *entry; } -} // namespace AlphaISA +/* end namespace AlphaISA */ } AlphaISA::ITB * AlphaITBParams::create() diff --git a/src/arch/alpha/tlb.hh b/src/arch/alpha/tlb.hh index f127d09a7..9267aa573 100644 --- a/src/arch/alpha/tlb.hh +++ b/src/arch/alpha/tlb.hh @@ -29,8 +29,8 @@ * Steve Reinhardt */ -#ifndef __ALPHA_MEMORY_HH__ -#define __ALPHA_MEMORY_HH__ +#ifndef __ARCH_ALPHA_TLB_HH__ +#define __ARCH_ALPHA_TLB_HH__ #include @@ -48,110 +48,116 @@ class ThreadContext; -namespace AlphaISA +namespace AlphaISA { + +class TlbEntry; + +class TLB : public BaseTLB { - class TlbEntry; + protected: + typedef std::multimap PageTable; + PageTable lookupTable; // Quick lookup into page table + + TlbEntry *table; // the Page Table + int size; // TLB Size + int nlu; // not last used entry (for replacement) + + void nextnlu() { if (++nlu >= size) nlu = 0; } + TlbEntry *lookup(Addr vpn, uint8_t asn); + + public: + typedef AlphaTLBParams Params; + TLB(const Params *p); + virtual ~TLB(); + + int getsize() const { return size; } + + TlbEntry &index(bool advance = true); + void insert(Addr vaddr, TlbEntry &entry); - class TLB : public BaseTLB + void flushAll(); + void flushProcesses(); + void flushAddr(Addr addr, uint8_t asn); + + void + demapPage(Addr vaddr, uint64_t asn) { - protected: - typedef std::multimap PageTable; - PageTable lookupTable; // Quick lookup into page table - - TlbEntry *table; // the Page Table - int size; // TLB Size - int nlu; // not last used entry (for replacement) - - void nextnlu() { if (++nlu >= size) nlu = 0; } - TlbEntry *lookup(Addr vpn, uint8_t asn); - - public: - typedef AlphaTLBParams Params; - TLB(const Params *p); - virtual ~TLB(); - - int getsize() const { return size; } - - TlbEntry &index(bool advance = true); - void insert(Addr vaddr, TlbEntry &entry); - - void flushAll(); - void flushProcesses(); - void flushAddr(Addr addr, uint8_t asn); - - void demapPage(Addr vaddr, uint64_t asn) - { - assert(asn < (1 << 8)); - flushAddr(vaddr, asn); - } - - // static helper functions... really EV5 VM traits - static bool validVirtualAddress(Addr vaddr) { - // unimplemented bits must be all 0 or all 1 - Addr unimplBits = vaddr & VAddrUnImplMask; - return (unimplBits == 0) || (unimplBits == VAddrUnImplMask); - } - - static Fault checkCacheability(RequestPtr &req, bool itb = false); - - // Checkpointing - virtual void serialize(std::ostream &os); - virtual void unserialize(Checkpoint *cp, const std::string §ion); - - // Most recently used page table entries - TlbEntry *EntryCache[3]; - inline void flushCache() - { - memset(EntryCache, 0, 3 * sizeof(TlbEntry*)); - } - - inline TlbEntry* updateCache(TlbEntry *entry) { - EntryCache[2] = EntryCache[1]; - EntryCache[1] = EntryCache[0]; - EntryCache[0] = entry; - return entry; - } - }; - - class ITB : public TLB + assert(asn < (1 << 8)); + flushAddr(vaddr, asn); + } + + // static helper functions... really EV5 VM traits + static bool + validVirtualAddress(Addr vaddr) { - protected: - mutable Stats::Scalar<> hits; - mutable Stats::Scalar<> misses; - mutable Stats::Scalar<> acv; - mutable Stats::Formula accesses; + // unimplemented bits must be all 0 or all 1 + Addr unimplBits = vaddr & VAddrUnImplMask; + return unimplBits == 0 || unimplBits == VAddrUnImplMask; + } - public: - typedef AlphaITBParams Params; - ITB(const Params *p); - virtual void regStats(); + static Fault checkCacheability(RequestPtr &req, bool itb = false); - Fault translate(RequestPtr &req, ThreadContext *tc); - }; + // Checkpointing + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); - class DTB : public TLB + // Most recently used page table entries + TlbEntry *EntryCache[3]; + inline void + flushCache() { - protected: - mutable Stats::Scalar<> read_hits; - mutable Stats::Scalar<> read_misses; - mutable Stats::Scalar<> read_acv; - mutable Stats::Scalar<> read_accesses; - mutable Stats::Scalar<> write_hits; - mutable Stats::Scalar<> write_misses; - mutable Stats::Scalar<> write_acv; - mutable Stats::Scalar<> write_accesses; - Stats::Formula hits; - Stats::Formula misses; - Stats::Formula acv; - Stats::Formula accesses; - - public: - typedef AlphaDTBParams Params; - DTB(const Params *p); - virtual void regStats(); - - Fault translate(RequestPtr &req, ThreadContext *tc, bool write); - }; -} - -#endif // __ALPHA_MEMORY_HH__ + memset(EntryCache, 0, 3 * sizeof(TlbEntry*)); + } + + inline TlbEntry * + updateCache(TlbEntry *entry) { + EntryCache[2] = EntryCache[1]; + EntryCache[1] = EntryCache[0]; + EntryCache[0] = entry; + return entry; + } +}; + +class ITB : public TLB +{ + protected: + mutable Stats::Scalar<> hits; + mutable Stats::Scalar<> misses; + mutable Stats::Scalar<> acv; + mutable Stats::Formula accesses; + + public: + typedef AlphaITBParams Params; + ITB(const Params *p); + virtual void regStats(); + + Fault translate(RequestPtr &req, ThreadContext *tc); +}; + +class DTB : public TLB +{ + protected: + mutable Stats::Scalar<> read_hits; + mutable Stats::Scalar<> read_misses; + mutable Stats::Scalar<> read_acv; + mutable Stats::Scalar<> read_accesses; + mutable Stats::Scalar<> write_hits; + mutable Stats::Scalar<> write_misses; + mutable Stats::Scalar<> write_acv; + mutable Stats::Scalar<> write_accesses; + Stats::Formula hits; + Stats::Formula misses; + Stats::Formula acv; + Stats::Formula accesses; + + public: + typedef AlphaDTBParams Params; + DTB(const Params *p); + virtual void regStats(); + + Fault translate(RequestPtr &req, ThreadContext *tc, bool write); +}; + +} // namespace AlphaISA + +#endif // __ARCH_ALPHA_TLB_HH__ diff --git a/src/arch/alpha/tru64/process.cc b/src/arch/alpha/tru64/process.cc index 455a24584..645cc6cf9 100644 --- a/src/arch/alpha/tru64/process.cc +++ b/src/arch/alpha/tru64/process.cc @@ -32,10 +32,8 @@ #include "arch/alpha/tru64/tru64.hh" #include "arch/alpha/isa_traits.hh" #include "arch/alpha/tru64/process.hh" - #include "cpu/thread_context.hh" #include "kern/tru64/tru64.hh" - #include "sim/process.hh" #include "sim/syscall_emul.hh" @@ -85,7 +83,7 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, case AlphaTru64::GSI_PHYSMEM: { TypedBufferArg physmem(tc->getSyscallArg(1)); - *physmem = htog((uint64_t)1024 * 1024); // physical memory in KB + *physmem = htog((uint64_t)1024 * 1024); // physical memory in KB physmem.copyOut(tc->getMemPort()); return 1; } @@ -159,14 +157,12 @@ setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, return 0; } - /// Target table() handler. -static -SyscallReturn tableFunc(SyscallDesc *desc, int callnum, LiveProcess *process, - ThreadContext *tc) +static SyscallReturn +tableFunc(SyscallDesc *desc, int callnum, LiveProcess *process, + ThreadContext *tc) { using namespace std; - using namespace AlphaISA; int id = tc->getSyscallArg(0); // table ID int index = tc->getSyscallArg(1); // index into table @@ -472,15 +468,14 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = { /* 266 */ SyscallDesc("sendfile", unimplementedFunc), }; - - SyscallDesc AlphaTru64Process::machSyscallDescs[] = { /* 0 */ SyscallDesc("kern_invalid", unimplementedFunc), /* 1 */ SyscallDesc("m5_mutex_lock", AlphaTru64::m5_mutex_lockFunc), /* 2 */ SyscallDesc("m5_mutex_trylock", AlphaTru64::m5_mutex_trylockFunc), /* 3 */ SyscallDesc("m5_mutex_unlock", AlphaTru64::m5_mutex_unlockFunc), /* 4 */ SyscallDesc("m5_cond_signal", AlphaTru64::m5_cond_signalFunc), - /* 5 */ SyscallDesc("m5_cond_broadcast", AlphaTru64::m5_cond_broadcastFunc), + /* 5 */ SyscallDesc("m5_cond_broadcast", + AlphaTru64::m5_cond_broadcastFunc), /* 6 */ SyscallDesc("m5_cond_wait", AlphaTru64::m5_cond_waitFunc), /* 7 */ SyscallDesc("m5_thread_exit", AlphaTru64::m5_thread_exitFunc), /* 8 */ SyscallDesc("kern_invalid", unimplementedFunc), @@ -507,7 +502,8 @@ SyscallDesc AlphaTru64Process::machSyscallDescs[] = { /* 29 */ SyscallDesc("nxm_thread_destroy", unimplementedFunc), /* 30 */ SyscallDesc("lw_wire", unimplementedFunc), /* 31 */ SyscallDesc("lw_unwire", unimplementedFunc), - /* 32 */ SyscallDesc("nxm_thread_create", AlphaTru64::nxm_thread_createFunc), + /* 32 */ SyscallDesc("nxm_thread_create", + AlphaTru64::nxm_thread_createFunc), /* 33 */ SyscallDesc("nxm_task_init", AlphaTru64::nxm_task_initFunc), /* 34 */ SyscallDesc("kern_invalid", unimplementedFunc), /* 35 */ SyscallDesc("nxm_idle", AlphaTru64::nxm_idleFunc), @@ -572,9 +568,8 @@ AlphaTru64Process::getDesc(int callnum) return &syscallDescs[callnum]; } - -AlphaTru64Process::AlphaTru64Process(LiveProcessParams * params, - ObjectFile *objFile) +AlphaTru64Process::AlphaTru64Process(LiveProcessParams *params, + ObjectFile *objFile) : AlphaLiveProcess(params, objFile), Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)), Num_Mach_Syscall_Descs(sizeof(machSyscallDescs) / sizeof(SyscallDesc)) diff --git a/src/arch/alpha/tru64/process.hh b/src/arch/alpha/tru64/process.hh index 16bc499c6..6d7a76555 100644 --- a/src/arch/alpha/tru64/process.hh +++ b/src/arch/alpha/tru64/process.hh @@ -28,12 +28,13 @@ * Authors: Steve Reinhardt */ -#ifndef __ALPHA_TRU64_PROCESS_HH__ -#define __ALPHA_TRU64_PROCESS_HH__ +#ifndef __ARCH_ALPHA_TRU64_PROCESS_HH__ +#define __ARCH_ALPHA_TRU64_PROCESS_HH__ #include "arch/alpha/process.hh" namespace AlphaISA { + /// A process with emulated Alpha Tru64 syscalls. class AlphaTru64Process : public AlphaLiveProcess { @@ -51,9 +52,9 @@ class AlphaTru64Process : public AlphaLiveProcess const int Num_Syscall_Descs; const int Num_Mach_Syscall_Descs; - virtual SyscallDesc* getDesc(int callnum); + virtual SyscallDesc *getDesc(int callnum); }; } // namespace AlphaISA -#endif // __ALPHA_TRU64_PROCESS_HH__ +#endif // __ARCH_ALPHA_TRU64_PROCESS_HH__ diff --git a/src/arch/alpha/tru64/tru64.hh b/src/arch/alpha/tru64/tru64.hh index 8aa959553..4ba35fc50 100644 --- a/src/arch/alpha/tru64/tru64.hh +++ b/src/arch/alpha/tru64/tru64.hh @@ -28,14 +28,13 @@ * Authors: Korey Sewell */ -#ifndef __ALPHA_ALPHA_TRU64_HH -#define __ALPHA_ALPHA_TRU64_HH +#ifndef __ALPHA_ALPHA_TRU64_TRU64_HH__ +#define __ALPHA_ALPHA_TRU64_TRU64_HH__ #include "kern/tru64/tru64.hh" class AlphaTru64 : public Tru64 { - public: /// This table maps the target open() flags to the corresponding /// host open() flags. @@ -68,13 +67,13 @@ class AlphaTru64 : public Tru64 //@{ /// For getsysinfo(). - static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string - static const unsigned GSI_CPU_INFO = 59; //!< CPU information - static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type - static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine - static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system - static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB - static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz + static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name string + static const unsigned GSI_CPU_INFO = 59; //!< CPU information + static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type + static const unsigned GSI_MAX_CPU = 30; //!< max # CPUs on machine + static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system + static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB + static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz //@} //@{ @@ -124,6 +123,4 @@ class AlphaTru64 : public Tru64 }; }; - - -#endif +#endif // __ALPHA_ALPHA_TRU64_TRU64_HH__ diff --git a/src/arch/alpha/types.hh b/src/arch/alpha/types.hh index f6648b776..94a4cb0e9 100644 --- a/src/arch/alpha/types.hh +++ b/src/arch/alpha/types.hh @@ -32,47 +32,50 @@ #ifndef __ARCH_ALPHA_TYPES_HH__ #define __ARCH_ALPHA_TYPES_HH__ -#include +#include "sim/host.hh" -namespace AlphaISA -{ +namespace AlphaISA { + +typedef uint32_t MachInst; +typedef uint64_t ExtMachInst; +typedef uint8_t RegIndex; - typedef uint32_t MachInst; - typedef uint64_t ExtMachInst; - typedef uint8_t RegIndex; +typedef uint64_t IntReg; +typedef uint64_t LargestRead; - typedef uint64_t IntReg; - typedef uint64_t LargestRead; +// floating point register file entry type +typedef double FloatReg; +typedef uint64_t FloatRegBits; - // floating point register file entry type - typedef double FloatReg; - typedef uint64_t FloatRegBits; +// control register file contents +typedef uint64_t MiscReg; - // control register file contents - typedef uint64_t MiscReg; +union AnyReg +{ + IntReg intreg; + FloatReg fpreg; + MiscReg ctrlreg; +}; - typedef union { - IntReg intreg; - FloatReg fpreg; - MiscReg ctrlreg; - } AnyReg; +enum RegContextParam +{ + CONTEXT_PALMODE +}; - enum RegContextParam - { - CONTEXT_PALMODE - }; +typedef bool RegContextVal; - typedef bool RegContextVal; +enum annotes +{ + ANNOTE_NONE = 0, + // An impossible number for instruction annotations + ITOUCH_ANNOTE = 0xffffffff, +}; - enum annotes { - ANNOTE_NONE = 0, - // An impossible number for instruction annotations - ITOUCH_ANNOTE = 0xffffffff, - }; +struct CoreSpecific +{ + int core_type; +}; - struct CoreSpecific { - int core_type; - }; } // namespace AlphaISA -#endif +#endif // __ARCH_ALPHA_TYPES_HH__ diff --git a/src/arch/alpha/utility.cc b/src/arch/alpha/utility.cc index 23abceb93..2cf64b799 100644 --- a/src/arch/alpha/utility.cc +++ b/src/arch/alpha/utility.cc @@ -36,10 +36,10 @@ #include "mem/vport.hh" #endif -namespace AlphaISA -{ +namespace AlphaISA { -uint64_t getArgument(ThreadContext *tc, int number, bool fp) +uint64_t +getArgument(ThreadContext *tc, int number, bool fp) { #if FULL_SYSTEM if (number < NumArgumentRegs) { @@ -56,7 +56,7 @@ uint64_t getArgument(ThreadContext *tc, int number, bool fp) } #else panic("getArgument() is Full system only\n"); - M5_DUMMY_RETURN + M5_DUMMY_RETURN; #endif } diff --git a/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh index 220aa6695..84f7cc487 100644 --- a/src/arch/alpha/utility.hh +++ b/src/arch/alpha/utility.hh @@ -32,137 +32,137 @@ #ifndef __ARCH_ALPHA_UTILITY_HH__ #define __ARCH_ALPHA_UTILITY_HH__ -#include "config/full_system.hh" #include "arch/alpha/types.hh" #include "arch/alpha/isa_traits.hh" #include "arch/alpha/regfile.hh" #include "base/misc.hh" +#include "config/full_system.hh" #include "cpu/thread_context.hh" -namespace AlphaISA +namespace AlphaISA { + +uint64_t getArgument(ThreadContext *tc, int number, bool fp); + +inline bool +inUserMode(ThreadContext *tc) +{ + return (tc->readMiscRegNoEffect(IPR_DTB_CM) & 0x18) != 0; +} + +inline bool +isCallerSaveIntegerRegister(unsigned int reg) +{ + panic("register classification not implemented"); + return (reg >= 1 && reg <= 8 || reg >= 22 && reg <= 25 || reg == 27); +} + +inline bool +isCalleeSaveIntegerRegister(unsigned int reg) +{ + panic("register classification not implemented"); + return (reg >= 9 && reg <= 15); +} + +inline bool +isCallerSaveFloatRegister(unsigned int reg) { - uint64_t getArgument(ThreadContext *tc, int number, bool fp); - - inline bool - inUserMode(ThreadContext *tc) - { - return (tc->readMiscRegNoEffect(IPR_DTB_CM) & 0x18) != 0; - } - - inline bool - isCallerSaveIntegerRegister(unsigned int reg) - { - panic("register classification not implemented"); - return (reg >= 1 && reg <= 8 || reg >= 22 && reg <= 25 || reg == 27); - } - - inline bool - isCalleeSaveIntegerRegister(unsigned int reg) - { - panic("register classification not implemented"); - return (reg >= 9 && reg <= 15); - } - - inline bool - isCallerSaveFloatRegister(unsigned int reg) - { - panic("register classification not implemented"); - return false; - } - - inline bool - isCalleeSaveFloatRegister(unsigned int reg) - { - panic("register classification not implemented"); - return false; - } - - inline Addr - alignAddress(const Addr &addr, unsigned int nbytes) - { - return (addr & ~(nbytes - 1)); - } - - // Instruction address compression hooks - inline Addr - realPCToFetchPC(const Addr &addr) - { - return addr; - } - - inline Addr - fetchPCToRealPC(const Addr &addr) - { - return addr; - } - - // the size of "fetched" instructions (not necessarily the size - // of real instructions for PISA) - inline size_t - fetchInstSize() - { - return sizeof(MachInst); - } - - inline MachInst - makeRegisterCopy(int dest, int src) - { - panic("makeRegisterCopy not implemented"); - return 0; - } - - // Machine operations - void saveMachineReg(AnyReg &savereg, const RegFile ®_file, int regnum); - void restoreMachineReg(RegFile ®s, const AnyReg ®, int regnum); - - /** - * Function to insure ISA semantics about 0 registers. - * @param tc The thread context. - */ - template - void zeroRegisters(TC *tc); - - // Alpha IPR register accessors - inline bool PcPAL(Addr addr) { return addr & 0x3; } - inline void startupCPU(ThreadContext *tc, int cpuId) { tc->activate(0); } - - //////////////////////////////////////////////////////////////////////// - // - // Translation stuff - // - - inline Addr PteAddr(Addr a) { return (a & PteMask) << PteShift; } - - // User Virtual - inline bool IsUSeg(Addr a) { return USegBase <= a && a <= USegEnd; } - - // Kernel Direct Mapped - inline bool IsK0Seg(Addr a) { return K0SegBase <= a && a <= K0SegEnd; } - inline Addr K0Seg2Phys(Addr addr) { return addr & ~K0SegBase; } - - // Kernel Virtual - inline bool IsK1Seg(Addr a) { return K1SegBase <= a && a <= K1SegEnd; } - - inline Addr - TruncPage(Addr addr) - { return addr & ~(PageBytes - 1); } - - inline Addr - RoundPage(Addr addr) - { return (addr + PageBytes - 1) & ~(PageBytes - 1); } - - void initIPRs(ThreadContext *tc, int cpuId); + panic("register classification not implemented"); + return false; +} + +inline bool +isCalleeSaveFloatRegister(unsigned int reg) +{ + panic("register classification not implemented"); + return false; +} + +inline Addr +alignAddress(const Addr &addr, unsigned int nbytes) +{ + return (addr & ~(nbytes - 1)); +} + +// Instruction address compression hooks +inline Addr +realPCToFetchPC(const Addr &addr) +{ + return addr; +} + +inline Addr +fetchPCToRealPC(const Addr &addr) +{ + return addr; +} + +// the size of "fetched" instructions (not necessarily the size +// of real instructions for PISA) +inline size_t +fetchInstSize() +{ + return sizeof(MachInst); +} + +inline MachInst +makeRegisterCopy(int dest, int src) +{ + panic("makeRegisterCopy not implemented"); + return 0; +} + +// Machine operations +void saveMachineReg(AnyReg &savereg, const RegFile ®_file, int regnum); +void restoreMachineReg(RegFile ®s, const AnyReg ®, int regnum); + +/** + * Function to insure ISA semantics about 0 registers. + * @param tc The thread context. + */ +template +void zeroRegisters(TC *tc); + +// Alpha IPR register accessors +inline bool PcPAL(Addr addr) { return addr & 0x3; } +inline void startupCPU(ThreadContext *tc, int cpuId) { tc->activate(0); } + +//////////////////////////////////////////////////////////////////////// +// +// Translation stuff +// + +inline Addr PteAddr(Addr a) { return (a & PteMask) << PteShift; } + +// User Virtual +inline bool IsUSeg(Addr a) { return USegBase <= a && a <= USegEnd; } + +// Kernel Direct Mapped +inline bool IsK0Seg(Addr a) { return K0SegBase <= a && a <= K0SegEnd; } +inline Addr K0Seg2Phys(Addr addr) { return addr & ~K0SegBase; } + +// Kernel Virtual +inline bool IsK1Seg(Addr a) { return K1SegBase <= a && a <= K1SegEnd; } + +inline Addr +TruncPage(Addr addr) +{ return addr & ~(PageBytes - 1); } + +inline Addr +RoundPage(Addr addr) +{ return (addr + PageBytes - 1) & ~(PageBytes - 1); } + +void initIPRs(ThreadContext *tc, int cpuId); #if FULL_SYSTEM - void initCPU(ThreadContext *tc, int cpuId); - - /** - * Function to check for and process any interrupts. - * @param tc The thread context. - */ - template - void processInterrupts(TC *tc); +void initCPU(ThreadContext *tc, int cpuId); + +/** + * Function to check for and process any interrupts. + * @param tc The thread context. + */ +template +void processInterrupts(TC *tc); #endif } // namespace AlphaISA -#endif +#endif // __ARCH_ALPHA_UTILITY_HH__ diff --git a/src/arch/alpha/vtophys.cc b/src/arch/alpha/vtophys.cc index 88e5a3090..4a043d8d1 100644 --- a/src/arch/alpha/vtophys.cc +++ b/src/arch/alpha/vtophys.cc @@ -115,4 +115,3 @@ vtophys(ThreadContext *tc, Addr addr) } } // namespace AlphaISA - diff --git a/src/arch/alpha/vtophys.hh b/src/arch/alpha/vtophys.hh index 9cce85d6c..b13afd090 100644 --- a/src/arch/alpha/vtophys.hh +++ b/src/arch/alpha/vtophys.hh @@ -41,12 +41,13 @@ class FunctionalPort; namespace AlphaISA { - PageTableEntry - kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, VAddr vaddr); +PageTableEntry kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, + VAddr vaddr); - Addr vtophys(Addr vaddr); - Addr vtophys(ThreadContext *tc, Addr vaddr); +Addr vtophys(Addr vaddr); +Addr vtophys(ThreadContext *tc, Addr vaddr); + +} // namespace AlphaISA -}; #endif // __ARCH_ALPHA_VTOPHYS_H__ diff --git a/src/kern/tru64/tru64_events.cc b/src/kern/tru64/tru64_events.cc index 9fa770c4d..9534c31de 100644 --- a/src/kern/tru64/tru64_events.cc +++ b/src/kern/tru64/tru64_events.cc @@ -59,20 +59,19 @@ BadAddrEvent::process(ThreadContext *tc) bool found = false; tc->getPhysPort()->getPeerAddressRanges(resp, snoop); - for(iter = resp.begin(); iter != resp.end(); iter++) - { - if (*iter == (TheISA::K0Seg2Phys(a0) & AlphaISA::PAddrImplMask)) + for (iter = resp.begin(); iter != resp.end(); iter++) { + if (*iter == (K0Seg2Phys(a0) & PAddrImplMask)) found = true; } - if (!TheISA::IsK0Seg(a0) || found ) { + if (!IsK0Seg(a0) || found ) { DPRINTF(BADADDR, "badaddr arg=%#x bad\n", a0); tc->setIntReg(ReturnValueReg, 0x1); SkipFuncEvent::process(tc); - } - else + } else { DPRINTF(BADADDR, "badaddr arg=%#x good\n", a0); + } } void -- cgit v1.2.3 From 80d9be86e616e819cc3c9a0bbc8a42a5beb41247 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 27 Sep 2008 21:03:49 -0700 Subject: gcc: Add extra parens to quell warnings. Even though we're not incorrect about operator precedence, let's add some parens in some particularly confusing places to placate GCC 4.3 so that we don't have to turn the warning off. Agreed that this is a bit of a pain for those users who get the order of operations correct, but it is likely to prevent bugs in certain cases. --- src/arch/alpha/ev5.hh | 4 ++-- src/arch/alpha/pagetable.hh | 4 ++-- src/arch/alpha/utility.hh | 4 ++-- src/arch/mips/dsp.cc | 4 ++-- src/arch/mips/isa/decoder.isa | 26 +++++++++++++------------- src/arch/mips/pagetable.hh | 4 ++-- src/arch/mips/utility.cc | 2 +- src/arch/sparc/faults.cc | 2 +- src/arch/sparc/isa/formats/mem/util.isa | 9 +++++---- src/arch/sparc/tlb.cc | 8 ++++---- src/arch/x86/emulenv.cc | 2 +- src/arch/x86/insts/microop.cc | 4 ++-- src/arch/x86/predecoder.cc | 8 ++++---- src/arch/x86/regfile.cc | 2 +- src/base/circlebuf.cc | 4 ++-- src/base/intmath.hh | 6 +++--- src/base/random_mt.cc | 6 +++--- src/base/stats/text.cc | 8 ++++---- src/cpu/o3/cpu.cc | 2 +- src/dev/alpha/tsunami_cchip.cc | 2 +- src/dev/terminal.cc | 3 +-- 21 files changed, 57 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/ev5.hh b/src/arch/alpha/ev5.hh index 4c4f282f1..1915d822b 100644 --- a/src/arch/alpha/ev5.hh +++ b/src/arch/alpha/ev5.hh @@ -80,7 +80,7 @@ Phys2K0Seg(Addr addr) inline int DTB_ASN_ASN(uint64_t reg) { return reg >> 57 & AsnMask; } inline Addr DTB_PTE_PPN(uint64_t reg) -{ return reg >> 32 & (ULL(1) << PAddrImplBits - PageShift) - 1; } +{ return reg >> 32 & ((ULL(1) << (PAddrImplBits - PageShift)) - 1); } inline int DTB_PTE_XRE(uint64_t reg) { return reg >> 8 & 0xf; } inline int DTB_PTE_XWE(uint64_t reg) { return reg >> 12 & 0xf; } inline int DTB_PTE_FONR(uint64_t reg) { return reg >> 1 & 0x1; } @@ -90,7 +90,7 @@ inline int DTB_PTE_ASMA(uint64_t reg) { return reg >> 4 & 0x1; } inline int ITB_ASN_ASN(uint64_t reg) { return reg >> 4 & AsnMask; } inline Addr ITB_PTE_PPN(uint64_t reg) -{ return reg >> 32 & (ULL(1) << PAddrImplBits - PageShift) - 1; } +{ return reg >> 32 & ((ULL(1) << (PAddrImplBits - PageShift)) - 1); } inline int ITB_PTE_XRE(uint64_t reg) { return reg >> 8 & 0xf; } inline bool ITB_PTE_FONR(uint64_t reg) { return reg >> 1 & 0x1; } inline bool ITB_PTE_FONW(uint64_t reg) { return reg >> 2 & 0x1; } diff --git a/src/arch/alpha/pagetable.hh b/src/arch/alpha/pagetable.hh index 4f7beb19b..6cf11be56 100644 --- a/src/arch/alpha/pagetable.hh +++ b/src/arch/alpha/pagetable.hh @@ -57,9 +57,9 @@ struct VAddr Addr level3() const { return PteAddr(addr >> PageShift); } Addr level2() const - { return PteAddr(addr >> NPtePageShift + PageShift); } + { return PteAddr(addr >> (NPtePageShift + PageShift)); } Addr level1() const - { return PteAddr(addr >> 2 * NPtePageShift + PageShift); } + { return PteAddr(addr >> (2 * NPtePageShift + PageShift)); } }; struct PageTableEntry diff --git a/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh index 84f7cc487..76c6c5726 100644 --- a/src/arch/alpha/utility.hh +++ b/src/arch/alpha/utility.hh @@ -53,14 +53,14 @@ inline bool isCallerSaveIntegerRegister(unsigned int reg) { panic("register classification not implemented"); - return (reg >= 1 && reg <= 8 || reg >= 22 && reg <= 25 || reg == 27); + return (reg >= 1 && reg <= 8) || (reg >= 22 && reg <= 25) || reg == 27; } inline bool isCalleeSaveIntegerRegister(unsigned int reg) { panic("register classification not implemented"); - return (reg >= 9 && reg <= 15); + return reg >= 9 && reg <= 15; } inline bool diff --git a/src/arch/mips/dsp.cc b/src/arch/mips/dsp.cc index fc3ae65d6..6e4f7afea 100755 --- a/src/arch/mips/dsp.cc +++ b/src/arch/mips/dsp.cc @@ -923,10 +923,10 @@ MipsISA::dspPrecrqu(int32_t a, int32_t b, uint32_t *dspctl) for (int i = 0; i<2; i++) { r_values[i] = - dspSaturate((int64_t)b_values[i] >> SIMD_NBITS[SIMD_FMT_QB] - 1, + dspSaturate((int64_t)b_values[i] >> (SIMD_NBITS[SIMD_FMT_QB] - 1), SIMD_FMT_QB, UNSIGNED, &ouflag); r_values[i + 2] = - dspSaturate((int64_t)a_values[i] >> SIMD_NBITS[SIMD_FMT_QB] - 1, + dspSaturate((int64_t)a_values[i] >> (SIMD_NBITS[SIMD_FMT_QB] - 1), SIMD_FMT_QB, UNSIGNED, &ouflag); } diff --git a/src/arch/mips/isa/decoder.isa b/src/arch/mips/isa/decoder.isa index b1cd03ca1..0a12c4f6e 100644 --- a/src/arch/mips/isa/decoder.isa +++ b/src/arch/mips/isa/decoder.isa @@ -416,16 +416,16 @@ decode OPCODE_HI default Unknown::unknown() { Ctrl_Base_DepTag); break; case 25: - data = 0 | fcsr_val & 0xFE000000 >> 24 - | fcsr_val & 0x00800000 >> 23; + data = (fcsr_val & 0xFE000000 >> 24) + | (fcsr_val & 0x00800000 >> 23); break; case 26: - data = 0 | fcsr_val & 0x0003F07C; + data = fcsr_val & 0x0003F07C; break; case 28: - data = 0 | fcsr_val & 0x00000F80 - | fcsr_val & 0x01000000 >> 21 - | fcsr_val & 0x00000003; + data = (fcsr_val & 0x00000F80) + | (fcsr_val & 0x01000000 >> 21) + | (fcsr_val & 0x00000003); break; case 31: data = fcsr_val; @@ -1963,7 +1963,7 @@ decode OPCODE_HI default Unknown::unknown() { 0x0: decode OP_LO { format IntOp { 0x0: append({{ Rt.uw = (Rt.uw << RD) | bits(Rs.uw,RD-1,0); }}); - 0x1: prepend({{ Rt.uw = (Rt.uw >> RD) | (bits(Rs.uw,RD-1,0) << 32-RD); }}); + 0x1: prepend({{ Rt.uw = (Rt.uw >> RD) | (bits(Rs.uw, RD - 1, 0) << (32 - RD)); }}); } } 0x2: decode OP_LO { @@ -2050,11 +2050,11 @@ decode OPCODE_HI default Unknown::unknown() { format LoadUnalignedMemory { 0x2: lwl({{ uint32_t mem_shift = 24 - (8 * byte_offset); Rt.uw = mem_word << mem_shift | - Rt.uw & mask(mem_shift); + (Rt.uw & mask(mem_shift)); }}); 0x6: lwr({{ uint32_t mem_shift = 8 * byte_offset; - Rt.uw = Rt.uw & (mask(mem_shift) << (32 - mem_shift)) | - mem_word >> mem_shift; + Rt.uw = (Rt.uw & (mask(mem_shift) << (32 - mem_shift))) | + (mem_word >> mem_shift); }}); } } @@ -2069,12 +2069,12 @@ decode OPCODE_HI default Unknown::unknown() { format StoreUnalignedMemory { 0x2: swl({{ uint32_t reg_shift = 24 - (8 * byte_offset); uint32_t mem_shift = 32 - reg_shift; - mem_word = mem_word & (mask(reg_shift) << mem_shift) | - Rt.uw >> reg_shift; + mem_word = (mem_word & (mask(reg_shift) << mem_shift)) | + (Rt.uw >> reg_shift); }}); 0x6: swr({{ uint32_t reg_shift = 8 * byte_offset; mem_word = Rt.uw << reg_shift | - mem_word & (mask(reg_shift)); + (mem_word & (mask(reg_shift))); }}); } format CP0Control { diff --git a/src/arch/mips/pagetable.hh b/src/arch/mips/pagetable.hh index 8c43a7b0c..bbed94194 100755 --- a/src/arch/mips/pagetable.hh +++ b/src/arch/mips/pagetable.hh @@ -59,9 +59,9 @@ namespace MipsISA { Addr level3() const { return MipsISA::PteAddr(addr >> PageShift); } Addr level2() const - { return MipsISA::PteAddr(addr >> NPtePageShift + PageShift); } + { return MipsISA::PteAddr(addr >> (NPtePageShift + PageShift)); } Addr level1() const - { return MipsISA::PteAddr(addr >> 2 * NPtePageShift + PageShift); } + { return MipsISA::PteAddr(addr >> (2 * NPtePageShift + PageShift)); } }; // ITB/DTB page table entry diff --git a/src/arch/mips/utility.cc b/src/arch/mips/utility.cc index 36cf76c67..1985c0f43 100644 --- a/src/arch/mips/utility.cc +++ b/src/arch/mips/utility.cc @@ -145,7 +145,7 @@ genCCVector(uint32_t fcsr, int cc_num, uint32_t cc_val) { int cc_idx = (cc_num == 0) ? 23 : cc_num + 24; - fcsr = bits(fcsr, 31, cc_idx + 1) << cc_idx + 1 | + fcsr = bits(fcsr, 31, cc_idx + 1) << (cc_idx + 1) | cc_val << cc_idx | bits(fcsr, cc_idx - 1, 0); diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc index e201cef95..9c189d164 100644 --- a/src/arch/sparc/faults.cc +++ b/src/arch/sparc/faults.cc @@ -546,7 +546,7 @@ void SparcFaultBase::invoke(ThreadContext * tc) doNormalFault(tc, trapType(), true); getHyperVector(tc, PC, NPC, 2); } else if (level == Hyperprivileged || - level == Privileged && trapType() >= 384) { + (level == Privileged && trapType() >= 384)) { doNormalFault(tc, trapType(), true); getHyperVector(tc, PC, NPC, trapType()); } else { diff --git a/src/arch/sparc/isa/formats/mem/util.isa b/src/arch/sparc/isa/formats/mem/util.isa index 38cde9a50..f2a2327ee 100644 --- a/src/arch/sparc/isa/formats/mem/util.isa +++ b/src/arch/sparc/isa/formats/mem/util.isa @@ -314,10 +314,11 @@ let {{ # are split into ones that are available in priv and hpriv, and # those that are only available in hpriv AlternateASIPrivFaultCheck = ''' - if(!bits(Pstate,2,2) && !bits(Hpstate,2,2) && !AsiIsUnPriv((ASI)EXT_ASI) || - !bits(Hpstate,2,2) && AsiIsHPriv((ASI)EXT_ASI)) - fault = new PrivilegedAction; - else if(AsiIsAsIfUser((ASI)EXT_ASI) && !bits(Pstate,2,2)) + if ((!bits(Pstate,2,2) && !bits(Hpstate,2,2) && + !AsiIsUnPriv((ASI)EXT_ASI)) || + (!bits(Hpstate,2,2) && AsiIsHPriv((ASI)EXT_ASI))) + fault = new PrivilegedAction; + else if (AsiIsAsIfUser((ASI)EXT_ASI) && !bits(Pstate,2,2)) fault = new PrivilegedAction; ''' diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc index defa33c51..125ceba69 100644 --- a/src/arch/sparc/tlb.cc +++ b/src/arch/sparc/tlb.cc @@ -562,7 +562,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) asi = (ASI)req->getAsi(); bool implicit = false; bool hpriv = bits(tlbdata,0,0); - bool unaligned = (vaddr & size-1); + bool unaligned = vaddr & (size - 1); DPRINTF(TLB, "TLB: DTB Request to translate va=%#x size=%d asi=%#x\n", vaddr, size, asi); @@ -801,8 +801,8 @@ handleIntRegAccess: return new PrivilegedAction; } - if (asi == ASI_SWVR_UDB_INTR_W && !write || - asi == ASI_SWVR_UDB_INTR_R && write) { + if ((asi == ASI_SWVR_UDB_INTR_W && !write) || + (asi == ASI_SWVR_UDB_INTR_R && write)) { writeSfsr(vaddr, write, Primary, true, IllegalAsi, asi); return new DataAccessException; } @@ -822,7 +822,7 @@ handleQueueRegAccess: writeSfsr(vaddr, write, Primary, true, IllegalAsi, asi); return new PrivilegedAction; } - if (!hpriv && vaddr & 0xF || vaddr > 0x3f8 || vaddr < 0x3c0) { + if ((!hpriv && vaddr & 0xF) || vaddr > 0x3f8 || vaddr < 0x3c0) { writeSfsr(vaddr, write, Primary, true, IllegalAsi, asi); return new DataAccessException; } diff --git a/src/arch/x86/emulenv.cc b/src/arch/x86/emulenv.cc index 31b705d79..142e233db 100644 --- a/src/arch/x86/emulenv.cc +++ b/src/arch/x86/emulenv.cc @@ -91,7 +91,7 @@ void EmulEnv::doModRM(const ExtMachInst & machInst) //Figure out what segment to use. This won't be entirely accurate since //the presence of a displacement is supposed to make the instruction //default to the data segment. - if (base != INTREG_RBP && base != INTREG_RSP || + if ((base != INTREG_RBP && base != INTREG_RSP) || 0/*Has an immediate offset*/) { seg = SEGMENT_REG_DS; //Handle any segment override that might have been in the instruction diff --git a/src/arch/x86/insts/microop.cc b/src/arch/x86/insts/microop.cc index 494c0b303..c7bfc3703 100644 --- a/src/arch/x86/insts/microop.cc +++ b/src/arch/x86/insts/microop.cc @@ -98,7 +98,7 @@ namespace X86ISA case ConditionTests::SxOF: return ccflags.sf ^ ccflags.of; case ConditionTests::SxOvZF: - return ccflags.sf ^ ccflags.of | ccflags.zf; + return (ccflags.sf ^ ccflags.of) | ccflags.zf; case ConditionTests::False: return false; case ConditionTests::NotECF: @@ -131,7 +131,7 @@ namespace X86ISA case ConditionTests::NotSxOF: return !(ccflags.sf ^ ccflags.of); case ConditionTests::NotSxOvZF: - return !(ccflags.sf ^ ccflags.of | ccflags.zf); + return !((ccflags.sf ^ ccflags.of) | ccflags.zf); } panic("Unknown condition: %d\n", condition); return true; diff --git a/src/arch/x86/predecoder.cc b/src/arch/x86/predecoder.cc index 1d415ffea..9d60089e3 100644 --- a/src/arch/x86/predecoder.cc +++ b/src/arch/x86/predecoder.cc @@ -319,17 +319,17 @@ namespace X86ISA if (emi.mode.submode != SixtyFourBitMode && !csAttr.defaultSize) { //figure out 16 bit displacement size - if(modRM.mod == 0 && modRM.rm == 6 || modRM.mod == 2) + if ((modRM.mod == 0 && modRM.rm == 6) || modRM.mod == 2) displacementSize = 2; - else if(modRM.mod == 1) + else if (modRM.mod == 1) displacementSize = 1; else displacementSize = 0; } else { //figure out 32/64 bit displacement size - if(modRM.mod == 0 && modRM.rm == 5 || modRM.mod == 2) + if ((modRM.mod == 0 && modRM.rm == 5) || modRM.mod == 2) displacementSize = 4; - else if(modRM.mod == 1) + else if (modRM.mod == 1) displacementSize = 1; else displacementSize = 0; diff --git a/src/arch/x86/regfile.cc b/src/arch/x86/regfile.cc index c27ab08ba..3fda345cc 100644 --- a/src/arch/x86/regfile.cc +++ b/src/arch/x86/regfile.cc @@ -214,7 +214,7 @@ int X86ISA::flattenIntIndex(ThreadContext * tc, int reg) //If we need to fold over the index to match byte semantics, do that. //Otherwise, just strip off any extra bits and pass it through. if (reg & (1 << 6)) - return (reg & ~(1 << 6) - 0x4); + return (reg & (~(1 << 6) - 0x4)); else return (reg & ~(1 << 6)); } diff --git a/src/base/circlebuf.cc b/src/base/circlebuf.cc index d42bb11c3..06d0075b2 100644 --- a/src/base/circlebuf.cc +++ b/src/base/circlebuf.cc @@ -208,7 +208,7 @@ CircleBuf::write(const char *b, int len) _rollover = true; } - if (old_start > old_stop && old_start < _stop || - old_start < old_stop && _stop < old_stop) + if ((old_start > old_stop && old_start < _stop) || + (old_start < old_stop && _stop < old_stop)) _start = _stop + 1; } diff --git a/src/base/intmath.hh b/src/base/intmath.hh index 227012e30..c536fda51 100644 --- a/src/base/intmath.hh +++ b/src/base/intmath.hh @@ -197,9 +197,9 @@ roundDown(T val, int align) inline bool isHex(char c) { - return c >= '0' && c <= '9' || - c >= 'A' && c <= 'F' || - c >= 'a' && c <= 'f'; + return (c >= '0' && c <= '9') || + (c >= 'A' && c <= 'F') || + (c >= 'a' && c <= 'f'); } inline bool diff --git a/src/base/random_mt.cc b/src/base/random_mt.cc index 1492240ee..6ea54ec03 100644 --- a/src/base/random_mt.cc +++ b/src/base/random_mt.cc @@ -123,15 +123,15 @@ Random::genrand() int kk; for (kk = 0; kk < N - M; kk++) { - y = mt[kk] & UPPER_MASK | mt[kk+1] & LOWER_MASK; + y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk + M] ^ (y >> 1) ^ mag01[y & 0x1UL]; } for (; kk < N - 1; kk++) { - y = mt[kk] & UPPER_MASK | mt[kk+1] & LOWER_MASK; + y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1UL]; } - y = mt[N - 1] & UPPER_MASK | mt[0] & LOWER_MASK; + y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ mag01[y & 0x1UL]; mti = 0; diff --git a/src/base/stats/text.cc b/src/base/stats/text.cc index a018c4837..6f40d92c8 100644 --- a/src/base/stats/text.cc +++ b/src/base/stats/text.cc @@ -191,8 +191,8 @@ struct ScalarPrint void ScalarPrint::operator()(ostream &stream) const { - if (flags & nozero && value == 0.0 || - flags & nonan && isnan(value)) + if ((flags & nozero && value == 0.0) || + (flags & nonan && isnan(value))) return; stringstream pdfstr, cdfstr; @@ -474,8 +474,8 @@ DistPrint::operator()(ostream &stream) const print.flags = flags | __substat; for (int i = 0; i < size; ++i) { - if (flags & nozero && vec[i] == 0.0 || - flags & nonan && isnan(vec[i])) + if ((flags & nozero && vec[i] == 0.0) || + (flags & nonan && isnan(vec[i]))) continue; _min = i * bucket_size + min; diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index f06aee634..13a0962fd 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -604,7 +604,7 @@ FullO3CPU::suspendContext(int tid) DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid); bool deallocated = deallocateContext(tid, false, 1); // If this was the last thread then unschedule the tick event. - if (activeThreads.size() == 1 && !deallocated || + if ((activeThreads.size() == 1 && !deallocated) || activeThreads.size() == 0) unscheduleTickEvent(); _status = Idle; diff --git a/src/dev/alpha/tsunami_cchip.cc b/src/dev/alpha/tsunami_cchip.cc index 891fe17da..4477b5adc 100644 --- a/src/dev/alpha/tsunami_cchip.cc +++ b/src/dev/alpha/tsunami_cchip.cc @@ -109,7 +109,7 @@ TsunamiCChip::read(PacketPtr pkt) panic("TSDEV_CC_MTR not implemeted\n"); break; case TSDEV_CC_MISC: - pkt->set((ipint << 8) & 0xF | (itint << 4) & 0xF | + pkt->set(((ipint << 8) & 0xF) | ((itint << 4) & 0xF) | (pkt->req->getCpuNum() & 0x3)); break; case TSDEV_CC_AAR0: diff --git a/src/dev/terminal.cc b/src/dev/terminal.cc index 8c18e3bbc..fba0c6130 100644 --- a/src/dev/terminal.cc +++ b/src/dev/terminal.cc @@ -294,8 +294,7 @@ Terminal::out(char c) if (DTRACE(Terminal)) { static char last = '\0'; - if (c != '\n' && c != '\r' || - last != '\n' && last != '\r') { + if ((c != '\n' && c != '\r') || (last != '\n' && last != '\r')) { if (c == '\n' || c == '\r') { int size = linebuf.size(); char *buffer = new char[size + 1]; -- cgit v1.2.3 From 1e9c428522144cb8df931e89314963ce8054a9d9 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 29 Sep 2008 07:15:30 -0700 Subject: alpha: Need to include cstring so that g++ 4.3 works. --- src/arch/alpha/floatregfile.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/arch/alpha/floatregfile.cc b/src/arch/alpha/floatregfile.cc index 15dc13166..192b0f1d4 100644 --- a/src/arch/alpha/floatregfile.cc +++ b/src/arch/alpha/floatregfile.cc @@ -30,6 +30,8 @@ * Kevin Lim */ +#include + #include "arch/alpha/floatregfile.hh" #include "sim/serialize.hh" -- cgit v1.2.3 From 45cba35fc11bbe4e57d9615cfbb79580904ef820 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Mon, 29 Sep 2008 23:30:14 -0700 Subject: Fix EVENTQ_DEBUG vs DEBUG_EVENTQ #define inconsistency. --- src/sim/eventq.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index d172c73da..967e558db 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -109,7 +109,7 @@ class Event : public Serializable, public FastAlloc Counter instance; #endif -#ifdef DEBUG_EVENTQ +#ifdef EVENTQ_DEBUG Tick whenCreated; //!< time created Tick whenScheduled; //!< time scheduled #endif @@ -119,7 +119,7 @@ class Event : public Serializable, public FastAlloc setWhen(Tick when) { _when = when; -#ifdef DEBUG_EVENTQ +#ifdef EVENTQ_DEBUG whenScheduled = curTick; #endif } -- cgit v1.2.3 From 7bf6a219db91406df91d4e9323b47e6d70ed73fb Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Mon, 29 Sep 2008 23:30:14 -0700 Subject: Make overriding port assignments in Python work, and print better error messages when it doesn't. --- src/dev/io_device.hh | 9 ++++++--- src/python/m5/params.py | 3 +++ 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh index 1e2e623f1..e18489378 100644 --- a/src/dev/io_device.hh +++ b/src/dev/io_device.hh @@ -212,7 +212,8 @@ class PioDevice : public MemObject { if (if_name == "pio") { if (pioPort != NULL) - panic("pio port already connected to."); + fatal("%s: pio port already connected to %s", + name(), pioPort->getPeer()->name()); pioPort = new PioPort(this, sys); return pioPort; } else @@ -289,12 +290,14 @@ class DmaDevice : public PioDevice { if (if_name == "pio") { if (pioPort != NULL) - panic("pio port already connected to."); + fatal("%s: pio port already connected to %s", + name(), pioPort->getPeer()->name()); pioPort = new PioPort(this, sys); return pioPort; } else if (if_name == "dma") { if (dmaPort != NULL) - panic("dma port already connected to."); + fatal("%s: dma port already connected to %s", + name(), pioPort->getPeer()->name()); dmaPort = new DmaPort(this, sys); return dmaPort; } else diff --git a/src/python/m5/params.py b/src/python/m5/params.py index 9394b11e2..081bd342e 100644 --- a/src/python/m5/params.py +++ b/src/python/m5/params.py @@ -1004,6 +1004,7 @@ class PortRef(object): if self.peer and not proxy.isproxy(self.peer): print "warning: overwriting port", self, \ "value", self.peer, "with", other + self.peer.peer = None self.peer = other if proxy.isproxy(other): other.set_param_desc(PortParamDesc()) @@ -1046,6 +1047,8 @@ class PortRef(object): if self.ccConnected: # already done this return peer = self.peer + if not self.peer: # nothing to connect to + return connectPorts(self.simobj.getCCObject(), self.name, self.index, peer.simobj.getCCObject(), peer.name, peer.index) self.ccConnected = True -- cgit v1.2.3 From 0a1613abe1d5ec9353001d68d6bb44bc64d97244 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Thu, 2 Oct 2008 12:46:57 -0400 Subject: Output: Verify output files are open after opening them. --- src/base/stats/text.cc | 8 +++++--- src/sim/serialize.cc | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/base/stats/text.cc b/src/base/stats/text.cc index 6f40d92c8..f65b77777 100644 --- a/src/base/stats/text.cc +++ b/src/base/stats/text.cc @@ -107,7 +107,8 @@ Text::open(std::ostream &_stream) mystream = false; stream = &_stream; - assert(valid()); + if (!valid()) + fatal("Unable to open output stream for writing\n"); } void @@ -118,13 +119,14 @@ Text::open(const std::string &file) mystream = true; stream = new ofstream(file.c_str(), ios::trunc); - assert(valid()); + if (!valid()) + fatal("Unable to open statistics file for writing\n"); } bool Text::valid() const { - return stream != NULL; + return stream != NULL && stream->good(); } void diff --git a/src/sim/serialize.cc b/src/sim/serialize.cc index 7050779b2..a4851d3f6 100644 --- a/src/sim/serialize.cc +++ b/src/sim/serialize.cc @@ -405,6 +405,8 @@ Serializable::serializeAll(const std::string &cpt_dir) string cpt_file = dir + Checkpoint::baseFilename; ofstream outstream(cpt_file.c_str()); time_t t = time(NULL); + if (!outstream.is_open()) + fatal("Unable to open file %s for writing\n", cpt_file.c_str()); outstream << "// checkpoint generated: " << ctime(&t); globals.serialize(outstream); -- cgit v1.2.3 From 67a2918abc057f8f6d693d8acadd70bf9337cf44 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 2 Oct 2008 11:26:59 -0700 Subject: stats: Fix small bug pointed out by unit testing. --- src/base/statistics.hh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/base/statistics.hh b/src/base/statistics.hh index 17aef14b9..25017031f 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -1009,8 +1009,7 @@ class ScalarProxy std::string str() const { - return csprintf("%s[%d]", stat->str(), index); - + return csprintf("%s[%d]", stat->statData()->name, index); } }; -- cgit v1.2.3 From 52493b27202fb61aaae74779ebcd91ca8f2bbc2c Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 2 Oct 2008 11:26:59 -0700 Subject: unittest: Cleanup unit tests. Follow style. Garbage Collect. --HG-- rename : src/unittest/rangemaptest2.cc => src/unittest/rangemultimaptest.cc --- src/unittest/bitvectest.cc | 48 ++++++++--------- src/unittest/circletest.cc | 55 ++++++++++---------- src/unittest/foo.ini | 1 - src/unittest/initest.ini | 14 ----- src/unittest/lru_test.cc | 85 ------------------------------ src/unittest/offtest.cc | 72 ------------------------- src/unittest/paramtest.cc | 107 -------------------------------------- src/unittest/rangemaptest.cc | 3 +- src/unittest/rangemaptest2.cc | 78 --------------------------- src/unittest/rangemultimaptest.cc | 80 ++++++++++++++++++++++++++++ src/unittest/rangetest.cc | 57 ++++++++++---------- src/unittest/sized_test.cc | 70 ------------------------- src/unittest/strnumtest.cc | 63 +++++++++++----------- src/unittest/tracetest.cc | 56 -------------------- 14 files changed, 194 insertions(+), 595 deletions(-) delete mode 100644 src/unittest/initest.ini delete mode 100644 src/unittest/lru_test.cc delete mode 100644 src/unittest/offtest.cc delete mode 100644 src/unittest/paramtest.cc delete mode 100644 src/unittest/rangemaptest2.cc create mode 100644 src/unittest/rangemultimaptest.cc delete mode 100644 src/unittest/sized_test.cc delete mode 100644 src/unittest/tracetest.cc (limited to 'src') diff --git a/src/unittest/bitvectest.cc b/src/unittest/bitvectest.cc index 440a150a3..2f01d636f 100644 --- a/src/unittest/bitvectest.cc +++ b/src/unittest/bitvectest.cc @@ -35,34 +35,34 @@ int main() { - vector v1(100); + vector v1(100); - v1[0] = true; - v1.resize(500); - v1[100] = true; - v1[499] = true; - v1.resize(10000); - v1[9999] = true; + v1[0] = true; + v1.resize(500); + v1[100] = true; + v1[499] = true; + v1.resize(10000); + v1[9999] = true; - cout << "v1.size() = " << v1.size() << "\n"; - for (int i = 0; i < v1.size(); i++) - if (v1[i]) - cout << "v1[" << i << "] = " << v1[i] << "\n"; + cout << "v1.size() = " << v1.size() << "\n"; + for (int i = 0; i < v1.size(); i++) + if (v1[i]) + cout << "v1[" << i << "] = " << v1[i] << "\n"; - cout << "\n"; + cout << "\n"; - vector v2 = v1; + vector v2 = v1; - for (int i = 0; i < v2.size(); i++) - if (v2[i]) - cout << "v2[" << i << "] = " << v2[i] << "\n"; + for (int i = 0; i < v2.size(); i++) + if (v2[i]) + cout << "v2[" << i << "] = " << v2[i] << "\n"; - cout << "v1 " << ((v1 == v2) ? "==" : "!=") << " v2" << "\n"; - v2[8583] = true; - cout << "v1 " << ((v1 == v2) ? "==" : "!=") << " v2" << "\n"; - v1[8583] = true; - cout << "v1 " << ((v1 == v2) ? "==" : "!=") << " v2" << "\n"; - v1.resize(100000); - cout << "v1 " << ((v1 == v2) ? "==" : "!=") << " v2" << "\n"; - cout << flush; + cout << "v1 " << ((v1 == v2) ? "==" : "!=") << " v2" << "\n"; + v2[8583] = true; + cout << "v1 " << ((v1 == v2) ? "==" : "!=") << " v2" << "\n"; + v1[8583] = true; + cout << "v1 " << ((v1 == v2) ? "==" : "!=") << " v2" << "\n"; + v1.resize(100000); + cout << "v1 " << ((v1 == v2) ? "==" : "!=") << " v2" << "\n"; + cout << flush; } diff --git a/src/unittest/circletest.cc b/src/unittest/circletest.cc index f072cf044..c6fce0f8f 100644 --- a/src/unittest/circletest.cc +++ b/src/unittest/circletest.cc @@ -34,14 +34,15 @@ #include "base/circlebuf.hh" -char *strings[] = -{ "This is the first test\n", - "he went with his woman to the store\n", - "the man with the bat hit the woman with the hat\n", - "that that is is that that was\n", - "sue sells sea shells by the sea shore\n", - "go to the store and buy me some milk and bread\n", - "the friendly flight attendants spoke soothingly to the frightened passengers in their native languages\n" +char *strings[] = { + "This is the first test\n", + "he went with his woman to the store\n", + "the man with the bat hit the woman with the hat\n", + "that that is is that that was\n", + "sue sells sea shells by the sea shore\n", + "go to the store and buy me some milk and bread\n", + "the friendly flight attendants spoke soothingly to " + "the frightened passengers in their native languages\n" }; const int num_strings = sizeof(strings) / sizeof(char *); @@ -49,26 +50,26 @@ const int num_strings = sizeof(strings) / sizeof(char *); int main() { - CircleBuf buf(1024); + CircleBuf buf(1024); - for (int count = 0; count < 100; count++) - buf.write(strings[count % num_strings]); - buf.read(STDOUT_FILENO); - write(STDOUT_FILENO, "<\n", 2); + for (int count = 0; count < 100; count++) + buf.write(strings[count % num_strings]); + buf.read(STDOUT_FILENO); + write(STDOUT_FILENO, "<\n", 2); - for (int count = 0; count < 100; count++) - buf.write(strings[count % num_strings]); - buf.read(STDOUT_FILENO, 100); - write(STDOUT_FILENO, "<\n", 2); + for (int count = 0; count < 100; count++) + buf.write(strings[count % num_strings]); + buf.read(STDOUT_FILENO, 100); + write(STDOUT_FILENO, "<\n", 2); - buf.flush(); - buf.write("asdfa asdf asd fasdf asdf\n"); - buf.write(""); - buf.write(""); - buf.write(""); - buf.write(""); - buf.write(""); - buf.write(""); - buf.read(STDOUT_FILENO); - write(STDOUT_FILENO, "<\n", 2); + buf.flush(); + buf.write("asdfa asdf asd fasdf asdf\n"); + buf.write(""); + buf.write(""); + buf.write(""); + buf.write(""); + buf.write(""); + buf.write(""); + buf.read(STDOUT_FILENO); + write(STDOUT_FILENO, "<\n", 2); } diff --git a/src/unittest/foo.ini b/src/unittest/foo.ini index 534a4e001..0f91c1fd6 100644 --- a/src/unittest/foo.ini +++ b/src/unittest/foo.ini @@ -1,4 +1,3 @@ -#define JUNK [Foo] Foo1=89 Foo2=384 diff --git a/src/unittest/initest.ini b/src/unittest/initest.ini deleted file mode 100644 index ebf2719d8..000000000 --- a/src/unittest/initest.ini +++ /dev/null @@ -1,14 +0,0 @@ -#define JUNK -// General stuff -#define FOO(X) BAR##X -[General] - Test1=FOO(asdf) - Test2=bar - -#ifdef JUNK -[Junk] // This is the junk -Test3=yo -Test4=mama -#endif - -#include "foo.ini" diff --git a/src/unittest/lru_test.cc b/src/unittest/lru_test.cc deleted file mode 100644 index d10eb1dd0..000000000 --- a/src/unittest/lru_test.cc +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2003-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Dave Greene - * Nathan Binkert - */ - -#include -#include "bhgp.hh" - -int main(void) -{ - typedef AssociativeTable tableType; - tableType table(10, 4); // 40 entry table - - std::cout << "Initial state:" << std::endl; - table.dump(); - - std::cout << "Inserting (2, 1)" << std::endl; - table[2] = 1; - table.dump(); - - std::cout << "Inserting (5, 2)" << std::endl; - table[5] = 2; - table.dump(); - - std::cout << "Inserting (10 + 2, 3)" << std::endl; - table[10 + 2] = 3; - table.dump(); - - tableType::const_iterator i = table.find(2); - assert(i != table.end()); - std::cout << "Accessed 2: " << *i << std::endl; - table.dump(); - - i = table.find(10 + 2); - assert(i != table.end()); - std::cout << "Accessed 10 + 2: " << *i << std::endl; - table.dump(); - - i = table.find(34); - assert(i == table.end()); - - std::cout << "Inserting (2 * 10 + 2, 4)" << std::endl; - table[2 * 10 + 2] = 4; - table.dump(); - - std::cout << "Replacing (10 + 2) with 5" << std::endl; - table[10 + 2] = 5; - table.dump(); - - std::cout << "Inserting (3 * 10 + 2, 6)" << std::endl; - table[3 * 10 + 2] = 6; - table.dump(); - - std::cout << "Inserting (4 * 10 + 2, 7)" << std::endl; - table[4 * 10 + 2] = 7; - table.dump(); - - return(0); -} diff --git a/src/unittest/offtest.cc b/src/unittest/offtest.cc deleted file mode 100644 index ebfb2515c..000000000 --- a/src/unittest/offtest.cc +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2002-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Nathan Binkert - */ - -#include -#include -#include -#include "dev/pcireg.h" - -int -main() -{ -#define POFFSET(x) \ - printf("offsetof(PCIConfig, hdr."#x") = %d\n", \ - offsetof(PCIConfig, hdr.x)) - - POFFSET(vendor); - POFFSET(device); - POFFSET(command); - POFFSET(status); - POFFSET(revision); - POFFSET(progIF); - POFFSET(subClassCode); - POFFSET(classCode); - POFFSET(cacheLineSize); - POFFSET(latencyTimer); - POFFSET(headerType); - POFFSET(bist); - POFFSET(pci0.baseAddr0); - POFFSET(pci0.baseAddr1); - POFFSET(pci0.baseAddr2); - POFFSET(pci0.baseAddr3); - POFFSET(pci0.baseAddr4); - POFFSET(pci0.baseAddr5); - POFFSET(pci0.cardbusCIS); - POFFSET(pci0.subsystemVendorID); - POFFSET(pci0.expansionROM); - POFFSET(pci0.reserved0); - POFFSET(pci0.reserved1); - POFFSET(pci0.interruptLine); - POFFSET(pci0.interruptPin); - POFFSET(pci0.minimumGrant); - POFFSET(pci0.minimumLatency); - - return 0; -} diff --git a/src/unittest/paramtest.cc b/src/unittest/paramtest.cc deleted file mode 100644 index e513ab981..000000000 --- a/src/unittest/paramtest.cc +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2002-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Nathan Binkert - */ - -// -// This file is not part of the regular simulator. It is solely for -// testing the parameter code. Edit the Makefile to add param_test.cc -// to the sources list, then use configs/test.ini as the configuration -// file. -// -#include "sim/sim_object.hh" -#include "mem/cache/cache.hh" - -class ParamTest : public SimObject -{ - public: - ParamTest(string name) - : SimObject(name) - { - } - - virtual ~ParamTest() {} -}; - -enum Enum1Type { Enum0 }; -enum Enum2Type { Enum10 }; - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(ParamTest) - - Param intparam; - VectorParam vecint; - Param stringparam; - VectorParam vecstring; - Param boolparam; - VectorParam vecbool; - SimObjectParam memobj; - SimObjectVectorParam vecmemobj; - SimpleEnumParam enum1; - MappedEnumParam enum2; - SimpleEnumVectorParam vecenum1; - MappedEnumVectorParam vecenum2; - -END_DECLARE_SIM_OBJECT_PARAMS(ParamTest) - -const char *enum1_strings[] = -{ - "zero", "one", "two", "three" -}; - -const EnumParamMap enum2_map[] = -{ - { "ten", 10 }, - { "twenty", 20 }, - { "thirty", 30 }, - { "forty", 40 } -}; - -BEGIN_INIT_SIM_OBJECT_PARAMS(ParamTest) - - INIT_PARAM(intparam, "intparam"), - INIT_PARAM(vecint, "vecint"), - INIT_PARAM(stringparam, "stringparam"), - INIT_PARAM(vecstring, "vecstring"), - INIT_PARAM(boolparam, "boolparam"), - INIT_PARAM(vecbool, "vecbool"), - INIT_PARAM(memobj, "memobj"), - INIT_PARAM(vecmemobj, "vecmemobj"), - INIT_ENUM_PARAM(enum1, "enum1", enum1_strings), - INIT_ENUM_PARAM(enum2, "enum2", enum2_map), - INIT_ENUM_PARAM(vecenum1, "vecenum1", enum1_strings), - INIT_ENUM_PARAM(vecenum2, "vecenum2", enum2_map) - -END_INIT_SIM_OBJECT_PARAMS(ParamTest) - - -CREATE_SIM_OBJECT(ParamTest) -{ - return new ParamTest(getInstanceName()); -} - -REGISTER_SIM_OBJECT("ParamTest", ParamTest) diff --git a/src/unittest/rangemaptest.cc b/src/unittest/rangemaptest.cc index 983a41520..36223ed9c 100644 --- a/src/unittest/rangemaptest.cc +++ b/src/unittest/rangemaptest.cc @@ -35,7 +35,8 @@ using namespace std; -int main() +int +main() { range_map r; diff --git a/src/unittest/rangemaptest2.cc b/src/unittest/rangemaptest2.cc deleted file mode 100644 index b253dbe86..000000000 --- a/src/unittest/rangemaptest2.cc +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Ali Saidi - */ - -#include -#include -#include "sim/host.hh" -#include "base/range_map.hh" - -using namespace std; - -int main() -{ - range_multimap r; - - range_multimap::iterator i; - std::pair::iterator,range_multimap::iterator> - jk; - - i = r.insert(RangeIn(10,40),5); - assert(i != r.end()); - i = r.insert(RangeIn(10,40),6); - assert(i != r.end()); - i = r.insert(RangeIn(60,90),3); - assert(i != r.end()); - - jk = r.find(RangeIn(20,30)); - assert(jk.first != r.end()); - cout << jk.first->first << " " << jk.first->second << endl; - cout << jk.second->first << " " << jk.second->second << endl; - - i = r.insert(RangeIn(0,3),5); - assert(i != r.end()); - - for( i = r.begin(); i != r.end(); i++) - cout << i->first << " " << i->second << endl; - - jk = r.find(RangeIn(20,30)); - assert(jk.first != r.end()); - cout << jk.first->first << " " << jk.first->second << endl; - cout << jk.second->first << " " << jk.second->second << endl; - - -} - - - - - - - - diff --git a/src/unittest/rangemultimaptest.cc b/src/unittest/rangemultimaptest.cc new file mode 100644 index 000000000..a110256c9 --- /dev/null +++ b/src/unittest/rangemultimaptest.cc @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + +#include +#include + +#include "sim/host.hh" +#include "base/range_map.hh" + +using namespace std; + +int +main() +{ + typedef range_multimap multimap_t; + + multimap_t r; + multimap_t::iterator i; + std::pair jk; + + i = r.insert(RangeIn(10,40),5); + assert(i != r.end()); + i = r.insert(RangeIn(10,40),6); + assert(i != r.end()); + i = r.insert(RangeIn(60,90),3); + assert(i != r.end()); + + jk = r.find(RangeIn(20,30)); + assert(jk.first != r.end()); + cout << jk.first->first << " " << jk.first->second << endl; + cout << jk.second->first << " " << jk.second->second << endl; + + i = r.insert(RangeIn(0,3),5); + assert(i != r.end()); + + for( i = r.begin(); i != r.end(); i++) + cout << i->first << " " << i->second << endl; + + jk = r.find(RangeIn(20,30)); + assert(jk.first != r.end()); + cout << jk.first->first << " " << jk.first->second << endl; + cout << jk.second->first << " " << jk.second->second << endl; + + +} + + + + + + + + diff --git a/src/unittest/rangetest.cc b/src/unittest/rangetest.cc index b7a68ab44..eab2f39a8 100644 --- a/src/unittest/rangetest.cc +++ b/src/unittest/rangetest.cc @@ -38,39 +38,40 @@ using namespace std; int main() { - Range r1(make_pair(9, 28)); - Range r2("0x1000:+0x100"); + Range r1(make_pair(9, 28)); + Range r2("0x1000:+0x100"); - cout << r1 << "\n" - << r2 << "\n"; + cout << r1 << "\n" + << r2 << "\n"; -#define RANGETEST(X, C, Y) \ - cout << X << " "#C" " << Y << " => " << ((X C Y) ? "true" : "false") << "\n" +#define RANGETEST(X, C, Y) \ + cout << X << " "#C" " << Y << " => " << \ + ((X C Y) ? "true" : "false") << "\n" #define TESTEM(X, Y) do { \ - RANGETEST(X, < , Y); \ - RANGETEST(X, <=, Y); \ - RANGETEST(X, > , Y); \ - RANGETEST(X, >=, Y); \ - RANGETEST(X, ==, Y); \ - RANGETEST(X, !=, Y); \ - RANGETEST(Y, < , X); \ - RANGETEST(Y, <=, X); \ - RANGETEST(Y, > , X); \ - RANGETEST(Y, >=, X); \ - RANGETEST(Y, ==, X); \ - RANGETEST(Y, !=, X); \ -} while (0) + RANGETEST(X, < , Y); \ + RANGETEST(X, <=, Y); \ + RANGETEST(X, > , Y); \ + RANGETEST(X, >=, Y); \ + RANGETEST(X, ==, Y); \ + RANGETEST(X, !=, Y); \ + RANGETEST(Y, < , X); \ + RANGETEST(Y, <=, X); \ + RANGETEST(Y, > , X); \ + RANGETEST(Y, >=, X); \ + RANGETEST(Y, ==, X); \ + RANGETEST(Y, !=, X); \ + } while (0) - TESTEM(8, r1); - TESTEM(9, r1); - TESTEM(27, r1); - TESTEM(28, r1); + TESTEM(8, r1); + TESTEM(9, r1); + TESTEM(27, r1); + TESTEM(28, r1); - TESTEM(0x0fff, r2); - TESTEM(0x1000, r2); - TESTEM(0x10ff, r2); - TESTEM(0x1100, r2); + TESTEM(0x0fff, r2); + TESTEM(0x1000, r2); + TESTEM(0x10ff, r2); + TESTEM(0x1100, r2); - return 0; + return 0; } diff --git a/src/unittest/sized_test.cc b/src/unittest/sized_test.cc deleted file mode 100644 index f1bf7528f..000000000 --- a/src/unittest/sized_test.cc +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2002-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Dave Greene - * Nathan Binkert - */ - -#include -#include - -#include "sized.hh" -#include -#include - -template -void print(C &cont) -{ - std::cout << std::endl; - std::cout << "Printing " << typeid(cont).name() << std::endl; - while (!cont.empty()) { - std::cout << cont.front() << " "; - cont.pop(); - } - std::cout << std::endl; -} - -int main(void) -{ - sized, sized_error_policy > > - error_queue(10); - sized, sized_drop_policy > > - drop_queue(5); - - for (int i = 0; i < 10; ++i) { - error_queue.push(i); - } - - for (int i = 0; i < 3; ++i) { - drop_queue.push(i); - } - - print(error_queue); - print(drop_queue); - - return(0); -} diff --git a/src/unittest/strnumtest.cc b/src/unittest/strnumtest.cc index ea28e35df..0e234884d 100644 --- a/src/unittest/strnumtest.cc +++ b/src/unittest/strnumtest.cc @@ -28,8 +28,7 @@ * Authors: Nathan Binkert */ -#include - +#include #include #include @@ -40,39 +39,39 @@ using namespace std; int main(int argc, char *argv[]) { - if (argc != 2) { - cout << "Usage: " << argv[0] << " \n"; - exit(1); - } + if (argc != 2) { + cout << "Usage: " << argv[0] << " \n"; + exit(1); + } - string s = argv[1]; + string s = argv[1]; #define OUTVAL(valtype, type) do { \ - valtype value; \ - cout << "TYPE = " #valtype "\n"; \ - if (to_number(s, value)) { \ - cout << "Number(" << s << ") = " << dec \ - << (unsigned long long)(unsigned type)value << "\n" \ - << "Number(" << s << ") = " << dec \ - << (signed long long)(signed type)value << "\n" \ - << "Number(" << s << ") = 0x" << hex \ - << (unsigned long long)(unsigned type)value << "\n" \ - << "Number(" << s << ") = 0" << oct \ - << (unsigned long long)(unsigned type)value << "\n\n"; \ - } else \ - cout << "Number(" << s << ") is invalid\n\n"; \ - } while (0) + valtype value; \ + cout << "TYPE = " #valtype "\n"; \ + if (to_number(s, value)) { \ + cout << "Number(" << s << ") = " << dec \ + << (unsigned long long)(unsigned type)value << "\n" \ + << "Number(" << s << ") = " << dec \ + << (signed long long)(signed type)value << "\n" \ + << "Number(" << s << ") = 0x" << hex \ + << (unsigned long long)(unsigned type)value << "\n" \ + << "Number(" << s << ") = 0" << oct \ + << (unsigned long long)(unsigned type)value << "\n\n"; \ + } else \ + cout << "Number(" << s << ") is invalid\n\n"; \ + } while (0) - OUTVAL(signed long long, long long); - OUTVAL(unsigned long long, long long); - OUTVAL(signed long, long); - OUTVAL(unsigned long, long); - OUTVAL(signed int, int); - OUTVAL(unsigned int, int); - OUTVAL(signed short, short); - OUTVAL(unsigned short, short); - OUTVAL(signed char, char); - OUTVAL(unsigned char, char); + OUTVAL(signed long long, long long); + OUTVAL(unsigned long long, long long); + OUTVAL(signed long, long); + OUTVAL(unsigned long, long); + OUTVAL(signed int, int); + OUTVAL(unsigned int, int); + OUTVAL(signed short, short); + OUTVAL(unsigned short, short); + OUTVAL(signed char, char); + OUTVAL(unsigned char, char); - return 0; + return 0; } diff --git a/src/unittest/tracetest.cc b/src/unittest/tracetest.cc deleted file mode 100644 index b1343aac3..000000000 --- a/src/unittest/tracetest.cc +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2003-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Nathan Binkert - */ - -#include "sim/host.hh" -#include "base/trace.hh" - -using namespace std; - -Tick curTick = 0; - -struct foo -{ - foo() - { - char foo[9] = "testing"; - DPRINTF(Loader, "%s\n", foo); - } -}; - -int -main() -{ - Trace::flags[Trace::Loader] = true; - Trace::dprintf_stream = &cout; - - foo f; - - return 0; -} -- cgit v1.2.3 From b25755993bbc04be0235975e2967533995a493f0 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 2 Oct 2008 11:27:01 -0700 Subject: unittest: Add unit tests to the scons framework. Also fix the unit tests so they actually compile correctly. --- src/SConscript | 18 ++++++++ src/unittest/Makefile | 101 --------------------------------------------- src/unittest/SConscript | 48 +++++++++++++++++++++ src/unittest/bitvectest.cc | 5 ++- src/unittest/circletest.cc | 5 ++- src/unittest/initest.cc | 20 +-------- src/unittest/nmtest.cc | 3 -- src/unittest/stattest.cc | 30 ++++++++------ src/unittest/symtest.cc | 4 +- 9 files changed, 92 insertions(+), 142 deletions(-) delete mode 100644 src/unittest/Makefile create mode 100644 src/unittest/SConscript (limited to 'src') diff --git a/src/SConscript b/src/SConscript index 14988bbbe..6b2ea4d60 100644 --- a/src/SConscript +++ b/src/SConscript @@ -144,12 +144,26 @@ def SwigSource(package, source): val = source,package swig_sources.append(val) +unit_tests = [] +def UnitTest(target, sources): + if not isinstance(sources, (list, tuple)): + sources = [ sources ] + + srcs = [] + for source in sources: + if not isinstance(source, SCons.Node.FS.File): + source = File(source) + srcs.append(source) + + unit_tests.append((target, srcs)) + # Children should have access Export('Source') Export('BinSource') Export('PySource') Export('SimObject') Export('SwigSource') +Export('UnitTest') ######################################################################## # @@ -962,6 +976,10 @@ def makeEnv(label, objsfx, strip = False, **kwargs): m5lib = newEnv.Library('m5_' + label, make_objs(cc_lib_sources, newEnv) + swig_objs) + for target, sources in unit_tests: + objs = [ newEnv.StaticObject(s) for s in sources ] + newEnv.Program("unittest/%s.%s" % (target, label), objs + m5lib) + # Now link a stub with main() and the library. exe = 'm5.' + label # final executable objects = [newEnv.Object(s) for s in cc_bin_sources] + m5lib diff --git a/src/unittest/Makefile b/src/unittest/Makefile deleted file mode 100644 index e6a621a9e..000000000 --- a/src/unittest/Makefile +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright (c) 2006-2007 The Regents of The University of Michigan -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer; -# redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution; -# neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Authors: Nathan Binkert -# Steve Reinhardt - -CC?= gcc -CXX?= g++ -PYTHON?=/usr/bin/env python - -CURDIR?= $(shell /bin/pwd) -SRCDIR?= $(CURDIR)/.. - -CCFLAGS= -g -O0 -MMD -I. -I$(SRCDIR) -I- -DTRACING_ON=0 -MYSQL= -I/usr/include/mysql -L/usr/lib/mysql -lmysqlclient - -VPATH=$(SRCDIR):$(CURDIR) - -default: - @echo "You must specify a target" - -base/traceflags.cc base/traceflags.hh: $(SRCDIR)/base/traceflags.py - mkdir -p base; \ - cd base; \ - $(PYTHON) $< - -bitvectest: unittest/bitvectest.cc - $(CXX) $(CCFLAGS) -o $@ $^ - -circletest: unittest/circletest.cc base/circlebuf.cc - $(CXX) $(CCFLAGS) -o $@ $^ - -cprintftest: unittest/cprintftest.cc base/cprintf.cc - $(CXX) $(CCFLAGS) -o $@ $^ - -cprintftime: unittest/cprintftime.cc base/cprintf.cc - $(CXX) $(CCFLAGS) -o $@ $^ - -initest: unittest/initest.cc base/str.cc base/inifile.cc base/cprintf.cc - $(CXX) $(CCFLAGS) -o $@ $^ - -lrutest: unittest/lru_test.cc - $(CXX) $(CCFLAGS) -o $@ $^ - -nmtest: unittest/nmtest.cc base/output.cc base/hostinfo.cc base/cprintf.cc base/misc.cc base/loader/object_file.cc base/loader/symtab.cc base/misc.cc base/str.cc base/loader/aout_object.cc base/loader/ecoff_object.cc base/loader/elf_object.cc - $(CXX) $(CCFLAGS) -I/n/ziff/z/binkertn/build/work/ALPHA_FS -lelf -o $@ $^ - -offtest: unittest/offtest.cc - $(CXX) $(CCFLAGS) -o $@ $^ - -rangetest: unittest/rangetest.cc base/range.cc base/str.cc - $(CXX) $(CCFLAGS) -o $@ $^ - -STATTEST+= base/cprintf.cc base/hostinfo.cc base/misc.cc base/mysql.cc -STATTEST+= base/python.cc base/str.cc base/time.cc -STATTEST+= base/statistics.cc base/stats/mysql.cc base/stats/python.cc -STATTEST+= base/stats/statdb.cc base/stats/text.cc base/stats/visit.cc -STATTEST+= unittest/stattest.cc -stattest: $(STATTEST) - $(CXX) $(CCFLAGS) $(MYSQL) -o $@ $^ - -strnumtest: unittest/strnumtest.cc base/str.cc - $(CXX) $(CCFLAGS) -o $@ $^ - -symtest: unittest/symtest.cc base/misc.cc base/symtab.cc base/str.cc - $(CXX) $(CCFLAGS) -o $@ $^ - -tokentest: unittest/tokentest.cc base/str.cc - $(CXX) $(CCFLAGS) -o $@ $^ - -TRACE+=unittest/tracetest.cc base/trace.cc base/trace_flags.cc base/cprintf.cc -TRACE+=base/str.cc base/misc.cc -tracetest: $(TRACE) - $(CXX) $(CCFLAGS) -o $@ $^ - -clean: - @rm -rf *test *~ .#* *.core core base -.PHONY: clean diff --git a/src/unittest/SConscript b/src/unittest/SConscript new file mode 100644 index 000000000..1c1959165 --- /dev/null +++ b/src/unittest/SConscript @@ -0,0 +1,48 @@ +# -*- mode:python -*- + +# Copyright (c) 2004-2005 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +UnitTest('bitvectest', 'bitvectest.cc') +UnitTest('circletest', 'circletest.cc') +UnitTest('cprintftest', 'cprintftest.cc') +UnitTest('cprintftime', 'cprintftest.cc') +UnitTest('initest', 'initest.cc') +UnitTest('lrutest', 'lru_test.cc') +UnitTest('nmtest', 'nmtest.cc') +UnitTest('offtest', 'offtest.cc') +UnitTest('rangetest', 'rangetest.cc') +UnitTest('rangemaptest', 'rangemaptest.cc') +UnitTest('rangemultimaptest', 'rangemultimaptest.cc') +UnitTest('stattest', 'stattest.cc') +UnitTest('strnumtest', 'strnumtest.cc') +UnitTest('symtest', 'symtest.cc') +UnitTest('tokentest', 'tokentest.cc') +UnitTest('tracetest', 'tracetest.cc') diff --git a/src/unittest/bitvectest.cc b/src/unittest/bitvectest.cc index 2f01d636f..29069081b 100644 --- a/src/unittest/bitvectest.cc +++ b/src/unittest/bitvectest.cc @@ -28,10 +28,11 @@ * Authors: Nathan Binkert */ -#include - +#include #include +using namespace std; + int main() { diff --git a/src/unittest/circletest.cc b/src/unittest/circletest.cc index c6fce0f8f..2ee75b6df 100644 --- a/src/unittest/circletest.cc +++ b/src/unittest/circletest.cc @@ -29,12 +29,13 @@ */ #include -#include #include +#include + #include "base/circlebuf.hh" -char *strings[] = { +const char *strings[] = { "This is the first test\n", "he went with his woman to the store\n", "the man with the bat hit the woman with the hat\n", diff --git a/src/unittest/initest.cc b/src/unittest/initest.cc index 8f53fce5c..67ac44874 100644 --- a/src/unittest/initest.cc +++ b/src/unittest/initest.cc @@ -68,32 +68,14 @@ main(int argc, char *argv[]) progname = argv[0]; - vector cppArgs; - - vector cpp_options; - cpp_options.reserve(argc * 2); - for (int i = 1; i < argc; ++i) { char *arg_str = argv[i]; // if arg starts with '-', parse as option, // else treat it as a configuration file name and load it if (arg_str[0] == '-') { - // switch on second char switch (arg_str[1]) { - case 'D': - case 'U': - case 'I': - // cpp options: record & pass to cpp. Note that these - // cannot have spaces, i.e., '-Dname=val' is OK, but - // '-D name=val' is not. I don't consider this a - // problem, since even though gnu cpp accepts the - // latter, other cpp implementations do not (Tru64, - // for one). - cppArgs.push_back(arg_str); - break; - case '-': // command-line configuration parameter: // '--
:=' @@ -115,7 +97,7 @@ main(int argc, char *argv[]) else { // no '-', treat as config file name - if (!simConfigDB.loadCPP(arg_str, cppArgs)) { + if (!simConfigDB.load(arg_str)) { cprintf("Error processing file %s\n", arg_str); exit(1); } diff --git a/src/unittest/nmtest.cc b/src/unittest/nmtest.cc index b6b74e08d..fdd865f2d 100644 --- a/src/unittest/nmtest.cc +++ b/src/unittest/nmtest.cc @@ -38,9 +38,6 @@ #include "base/str.hh" using namespace std; -Tick curTick; - -ostream *outputStream = &cout; int main(int argc, char *argv[]) diff --git a/src/unittest/stattest.cc b/src/unittest/stattest.cc index 4e504fde9..78d43c6f3 100644 --- a/src/unittest/stattest.cc +++ b/src/unittest/stattest.cc @@ -30,9 +30,7 @@ #include #include -#include #include -#include #include "base/cprintf.hh" #include "base/misc.hh" @@ -44,9 +42,6 @@ using namespace std; using namespace Stats; -Tick curTick = 0; -Tick ticksPerSecond = ULL(2000000000); - Scalar<> s1; Scalar<> s2; Average<> s3; @@ -72,8 +67,6 @@ Value f5; Formula f6; Formula f7; -ostream *outputStream = &cout; - double testfunc() { @@ -85,7 +78,7 @@ class TestClass { double operator()() { return 9.7; } }; -char *progname = ""; +const char *progname = ""; void usage() @@ -101,14 +94,18 @@ main(int argc, char *argv[]) bool descriptions = false; bool compat = false; bool text = false; + +#if USE_MYSQL string mysql_name; + string mysql_db; string mysql_host; string mysql_user = "binkertn"; string mysql_passwd; +#endif char c; progname = argv[0]; - while ((c = getopt(argc, argv, "cdh:P:p:s:tu:")) != -1) { + while ((c = getopt(argc, argv, "cD:dh:P:p:s:tu:")) != -1) { switch (c) { case 'c': compat = true; @@ -116,6 +113,13 @@ main(int argc, char *argv[]) case 'd': descriptions = true; break; + case 't': + text = true; + break; +#if USE_MYSQL + case 'D': + mysql_db = optarg; + break; case 'h': mysql_host = optarg; break; @@ -125,12 +129,10 @@ main(int argc, char *argv[]) case 's': mysql_name = optarg; break; - case 't': - text = true; - break; case 'u': mysql_user = optarg; break; +#endif default: usage(); } @@ -545,12 +547,14 @@ main(int argc, char *argv[]) out(); } +#if USE_MYSQL if (!mysql_name.empty()) { MySql out; - out.connect(mysql_host, mysql_user, mysql_passwd, "m5stats", + out.connect(mysql_host, mysql_db, mysql_user, mysql_passwd, "test", mysql_name, "test"); out(); } +#endif return 0; } diff --git a/src/unittest/symtest.cc b/src/unittest/symtest.cc index f0142b923..10ffb42e5 100644 --- a/src/unittest/symtest.cc +++ b/src/unittest/symtest.cc @@ -28,12 +28,12 @@ * Authors: Nathan Binkert */ -#include +#include #include "base/str.hh" #include "base/loader/symtab.hh" -Tick curTick = 0; +using namespace std; void usage(const char *progname) -- cgit v1.2.3 From 6c046a28dc6624f57655e5106568721972cbae1e Mon Sep 17 00:00:00 2001 From: Korey Sewell Date: Mon, 6 Oct 2008 02:07:04 -0400 Subject: fix shadow set bugs in MIPS code that caused out of bounds access... panic rdpgpr/wrpgpr instructions until a better impl. of MIPS shadow sets is available. --- src/arch/mips/isa/decoder.isa | 6 ++++-- src/arch/mips/isa_traits.hh | 2 ++ src/arch/mips/regfile/int_regfile.cc | 35 ++++++++++++++++++----------------- src/arch/mips/regfile/int_regfile.hh | 3 ++- src/arch/mips/regfile/misc_regfile.cc | 2 +- 5 files changed, 27 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/arch/mips/isa/decoder.isa b/src/arch/mips/isa/decoder.isa index 0a12c4f6e..8af504e55 100644 --- a/src/arch/mips/isa/decoder.isa +++ b/src/arch/mips/isa/decoder.isa @@ -603,7 +603,8 @@ decode OPCODE_HI default Unknown::unknown() { 0xA: rdpgpr({{ if(Config_AR >= 1) { // Rev 2 of the architecture - Rd = xc->tcBase()->readIntReg(RT + NumIntRegs * SRSCtl_PSS); + panic("Shadow Sets Not Fully Implemented.\n"); + //Rd = xc->tcBase()->readIntReg(RT + NumIntRegs * SRSCtl_PSS); } else { @@ -613,7 +614,8 @@ decode OPCODE_HI default Unknown::unknown() { 0xE: wrpgpr({{ if(Config_AR >= 1) { // Rev 2 of the architecture - xc->tcBase()->setIntReg(RD + NumIntRegs * SRSCtl_PSS,Rt); + panic("Shadow Sets Not Fully Implemented.\n"); + //xc->tcBase()->setIntReg(RD + NumIntRegs * SRSCtl_PSS,Rt); // warn("Writing %d to %d, PSS: %d, SRS: %x\n",Rt,RD + NumIntRegs * SRSCtl_PSS, SRSCtl_PSS,SRSCtl); } else diff --git a/src/arch/mips/isa_traits.hh b/src/arch/mips/isa_traits.hh index d4d1de479..3450c273e 100644 --- a/src/arch/mips/isa_traits.hh +++ b/src/arch/mips/isa_traits.hh @@ -181,6 +181,8 @@ namespace MipsISA const int NumIntRegs = NumIntArchRegs*NumShadowRegSets + NumIntSpecialRegs; //HI & LO Regs const int NumFloatRegs = NumFloatArchRegs + NumFloatSpecialRegs;// + const int TotalArchRegs = NumIntArchRegs * NumShadowRegSets; + // Static instruction parameters const int MaxInstSrcRegs = 10; const int MaxInstDestRegs = 8; diff --git a/src/arch/mips/regfile/int_regfile.cc b/src/arch/mips/regfile/int_regfile.cc index 4ffbcdfb8..88de4be94 100644 --- a/src/arch/mips/regfile/int_regfile.cc +++ b/src/arch/mips/regfile/int_regfile.cc @@ -44,6 +44,12 @@ IntRegFile::clear() currShadowSet=0; } +int +IntRegFile::readShadowSet() +{ + return currShadowSet; +} + void IntRegFile::setShadowSet(int css) { @@ -54,21 +60,17 @@ IntRegFile::setShadowSet(int css) IntReg IntRegFile::readReg(int intReg) { - if (intReg < NumIntRegs) { + if (intReg < NumIntArchRegs) { // Regular GPR Read DPRINTF(MipsPRA, "Reading Reg: %d, CurrShadowSet: %d\n", intReg, - currShadowSet); + currShadowSet); - if (intReg >= NumIntArchRegs * NumShadowRegSets) { - return regs[intReg + NumIntRegs * currShadowSet]; - } else { - int index = intReg + NumIntArchRegs * currShadowSet; - index = index % NumIntArchRegs; - return regs[index]; - } + return regs[intReg + NumIntArchRegs * currShadowSet]; } else { - // Read from shadow GPR .. probably called by RDPGPR - return regs[intReg]; + unsigned special_reg_num = intReg - NumIntArchRegs; + + // Read A Special Reg + return regs[TotalArchRegs + special_reg_num]; } } @@ -76,13 +78,12 @@ Fault IntRegFile::setReg(int intReg, const IntReg &val) { if (intReg != ZeroReg) { - if (intReg < NumIntRegs) { - if (intReg >= NumIntArchRegs * NumShadowRegSets) - regs[intReg] = val; - else - regs[intReg + NumIntRegs * currShadowSet] = val; + if (intReg < NumIntArchRegs) { + regs[intReg + NumIntArchRegs * currShadowSet] = val; } else { - regs[intReg] = val; + unsigned special_reg_num = intReg - NumIntArchRegs; + + regs[TotalArchRegs + special_reg_num] = val; } } diff --git a/src/arch/mips/regfile/int_regfile.hh b/src/arch/mips/regfile/int_regfile.hh index 8ddd276e6..0f453a382 100644 --- a/src/arch/mips/regfile/int_regfile.hh +++ b/src/arch/mips/regfile/int_regfile.hh @@ -48,7 +48,7 @@ namespace MipsISA } enum MiscIntRegNums { - LO = NumIntArchRegs*NumShadowRegSets, + LO = NumIntArchRegs, HI, DSPACX0, DSPLo1, @@ -72,6 +72,7 @@ namespace MipsISA int currShadowSet; public: void clear(); + int readShadowSet(); void setShadowSet(int css); IntReg readReg(int intReg); Fault setReg(int intReg, const IntReg &val); diff --git a/src/arch/mips/regfile/misc_regfile.cc b/src/arch/mips/regfile/misc_regfile.cc index e81f940f5..06523a8c9 100755 --- a/src/arch/mips/regfile/misc_regfile.cc +++ b/src/arch/mips/regfile/misc_regfile.cc @@ -40,7 +40,7 @@ #include "cpu/base.hh" #include "cpu/exetrace.hh" -#include "params/DerivO3CPU.hh" +//#include "params/DerivO3CPU.hh" using namespace std; -- cgit v1.2.3 From 6b2bb53fd6e59dee0c5524029c9422e2885d00d2 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 6 Oct 2008 09:31:51 -0700 Subject: python: cleanup options parsing stuff so that it properly deals with defaults. While we're at it, make it possible to run main.py in a somewhat standalone mode again so that we can test things without compiling. --- src/python/m5/main.py | 57 +++++++++++++++++++++++++++++------------------- src/python/m5/options.py | 39 +++++++++++++++------------------ 2 files changed, 52 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 1e217715c..66a422efa 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -34,9 +34,7 @@ import sys from util import attrdict import config -import defines from options import OptionParser -import traceflags __all__ = [ 'options', 'arguments', 'main' ] @@ -132,7 +130,6 @@ add_option("--list-sim-objects", action='store_true', default=False, help="List all built-in SimObjects, their parameters and default values") def main(): - import defines import event import info import internal @@ -176,6 +173,8 @@ def main(): done = False if options.build_info: + import defines + done = True print 'Build information:' print @@ -217,6 +216,8 @@ def main(): print if options.trace_help: + import traceflags + done = True print "Base Flags:" print_list(traceflags.baseFlags, indent=4) @@ -297,27 +298,30 @@ def main(): for when in options.debug_break: internal.debug.schedBreakCycle(int(when)) - on_flags = [] - off_flags = [] - for flag in options.trace_flags: - off = False - if flag.startswith('-'): - flag = flag[1:] - off = True - if flag not in traceflags.allFlags: - print >>sys.stderr, "invalid trace flag '%s'" % flag - sys.exit(1) - - if off: - off_flags.append(flag) - else: - on_flags.append(flag) + if options.trace_flags: + import traceflags + + on_flags = [] + off_flags = [] + for flag in options.trace_flags: + off = False + if flag.startswith('-'): + flag = flag[1:] + off = True + if flag not in traceflags.allFlags: + print >>sys.stderr, "invalid trace flag '%s'" % flag + sys.exit(1) - for flag in on_flags: - internal.trace.set(flag) + if off: + off_flags.append(flag) + else: + on_flags.append(flag) - for flag in off_flags: - internal.trace.clear(flag) + for flag in on_flags: + internal.trace.set(flag) + + for flag in off_flags: + internal.trace.clear(flag) if options.trace_start: def enable_trace(): @@ -358,7 +362,14 @@ def main(): if __name__ == '__main__': from pprint import pprint - parse_args() + # load the options.py config file to allow people to set their own + # default options + options_file = config.get('options.py') + if options_file: + scope = { 'options' : options } + execfile(options_file, scope) + + arguments = options.parse_args() print 'opts:' pprint(options, indent=4) diff --git a/src/python/m5/options.py b/src/python/m5/options.py index 50eea429c..1f534a314 100644 --- a/src/python/m5/options.py +++ b/src/python/m5/options.py @@ -28,7 +28,6 @@ import optparse import sys -import util from optparse import * @@ -45,19 +44,20 @@ class splitter(object): else: dest.extend(values) -class OptionParser(object): +class OptionParser(dict): def __init__(self, *args, **kwargs): kwargs.setdefault('formatter', optparse.TitledHelpFormatter()) self._optparse = optparse.OptionParser(*args, **kwargs) self._optparse.disable_interspersed_args() self._allopts = {} - self._defaults = {} - self._options = util.attrdict() # current option group self._group = self._optparse + def set_defaults(self, *args, **kwargs): + return self._optparse.set_defaults(*args, **kwargs) + def set_group(self, *args, **kwargs): '''set the current option group''' if not args and not kwargs: @@ -78,16 +78,11 @@ class OptionParser(object): kwargs['action'] = 'callback' kwargs['callback'] = splitter(split) - default = kwargs.pop('default', nodefault) option = self._group.add_option(*args, **kwargs) dest = option.dest if dest not in self._allopts: self._allopts[dest] = option - if default != nodefault: - if dest not in self._options: - self._options[dest] = default - return option def bool_option(self, name, default, help): @@ -113,28 +108,30 @@ class OptionParser(object): def __getattr__(self, attr): if attr.startswith('_'): - return super(OptionParser, self).__getattr__(attr) + return super(OptionParser, self).__getattribute__(attr) - if attr in self._options: - return self._options[attr] + if attr in self: + return self[attr] - raise AttributeError, "Option %s not found" % attr + return super(OptionParser, self).__getattribute__(attr) def __setattr__(self, attr, value): if attr.startswith('_'): - return super(OptionParser, self).__setattr__(attr, value) - - if attr in self._options: - self._options[attr] = value - - return super(OptionParser, self).__setattr__(attr, value) + super(OptionParser, self).__setattr__(attr, value) + elif attr in self._allopts: + defaults = { attr : value } + self.set_defaults(**defaults) + if attr in self: + self[attr] = value + else: + super(OptionParser, self).__setattr__(attr, value) def parse_args(self): opts,args = self._optparse.parse_args() for key,val in opts.__dict__.iteritems(): - if val is not None or key not in self._options: - self._options[key] = val + if val is not None or key not in self: + self[key] = val return args -- cgit v1.2.3 From 569db520ad69bc8b3f506accb0a86d1e519e63ad Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 9 Oct 2008 00:04:36 -0700 Subject: X86: Make far ret modify CS instead of some random selector. --- src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py b/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py index b18d48264..d1a8245e6 100644 --- a/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py +++ b/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py @@ -109,8 +109,8 @@ processDescriptor: chks t2, t3, IretCheck, dataSize=8 # There should be validity checks on the RIP checks here, but I'll do # that later. - wrdl reg, t3, t2 - wrsel reg, t2 + wrdl cs, t3, t2 + wrsel cs, t2 wrip t0, t1 bri t0, label("end") -- cgit v1.2.3 From e1b306fa537bd8fba4c522ee313a2915f7daec61 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 9 Oct 2008 00:05:39 -0700 Subject: X86: Fix the debugging microops. The debug functions can't handle a string object format. --- src/arch/x86/isa/microops/debug.isa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/isa/microops/debug.isa b/src/arch/x86/isa/microops/debug.isa index 7456b0d4e..895e97199 100644 --- a/src/arch/x86/isa/microops/debug.isa +++ b/src/arch/x86/isa/microops/debug.isa @@ -104,7 +104,7 @@ def template MicroDebugExecute {{ %(op_decl)s %(op_rd)s if (%(cond_test)s) { - %(func)s(message + "\n"); + %(func)s("%s\n", message); } return NoFault; } -- cgit v1.2.3 From c5c6ad7ed6dff171c888aa20d505f87293cc1159 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 9 Oct 2008 00:06:05 -0700 Subject: CPU: Fix where setMicroPC was being called instead of setNextMicroPC. --- src/cpu/thread_context.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index b1687a494..9dffbd8c6 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -429,7 +429,7 @@ class ProxyThreadContext : public ThreadContext uint64_t readNextMicroPC() { return actualTC->readMicroPC(); } - void setNextMicroPC(uint64_t val) { actualTC->setMicroPC(val); } + void setNextMicroPC(uint64_t val) { actualTC->setNextMicroPC(val); } MiscReg readMiscRegNoEffect(int misc_reg) { return actualTC->readMiscRegNoEffect(misc_reg); } -- cgit v1.2.3 From 523531a40e83b3023ae5911f48388e2490f16cba Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 9 Oct 2008 00:07:21 -0700 Subject: Microcode: Fix a very old bug with parsing external labels in microcode. --- src/arch/micro_asm.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/micro_asm.py b/src/arch/micro_asm.py index 36c9919c0..0982f6b89 100644 --- a/src/arch/micro_asm.py +++ b/src/arch/micro_asm.py @@ -242,7 +242,10 @@ def t_params_PARAMS(t): def t_asm_ID(t): r'[A-Za-z_]\w*' t.type = reserved_map.get(t.value, 'ID') - t.lexer.begin('params') + # If the ID is really "extern", we shouldn't start looking for parameters + # yet. The real ID, the label itself, is coming up. + if t.type != 'EXTERN': + t.lexer.begin('params') return t # If there is a label and you're -not- in the assembler (which would be caught -- cgit v1.2.3 From 975c9e3af869fb2905933c93c4d657e4d7187dad Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 9 Oct 2008 00:07:38 -0700 Subject: Microcode: Fix a silent typo error in the microcode assembler. --- src/arch/micro_asm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/micro_asm.py b/src/arch/micro_asm.py index 0982f6b89..3433a8076 100644 --- a/src/arch/micro_asm.py +++ b/src/arch/micro_asm.py @@ -141,7 +141,7 @@ def handle_statement(parser, container, statement): try: for label in statement.labels: container.labels[label.text] = microop - if label.extern: + if label.is_extern: container.externs[label.text] = microop container.add_microop(statement.mnemonic, microop) except: -- cgit v1.2.3 From e09c403d326488dbc709e3bddc8d497481273950 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 9 Oct 2008 00:08:50 -0700 Subject: O3: Generalize the O3 CPU object so it isn't split out by ISA. --- src/cpu/o3/alpha/cpu.cc | 5 +- src/cpu/o3/alpha/cpu.hh | 149 ----------------- src/cpu/o3/alpha/cpu_builder.cc | 9 +- src/cpu/o3/alpha/cpu_impl.hh | 316 ------------------------------------- src/cpu/o3/alpha/dyn_inst.hh | 2 +- src/cpu/o3/alpha/impl.hh | 4 +- src/cpu/o3/alpha/thread_context.hh | 76 --------- src/cpu/o3/base_dyn_inst.cc | 1 + src/cpu/o3/cpu.cc | 284 +++++++++++++++++++++++++++++++-- src/cpu/o3/cpu.hh | 89 ++++++++++- src/cpu/o3/isa_specific.hh | 3 - src/cpu/o3/mips/cpu.cc | 5 +- src/cpu/o3/mips/cpu.hh | 130 --------------- src/cpu/o3/mips/cpu_builder.cc | 9 +- src/cpu/o3/mips/cpu_impl.hh | 218 ------------------------- src/cpu/o3/mips/dyn_inst.hh | 2 +- src/cpu/o3/mips/impl.hh | 4 +- src/cpu/o3/mips/thread_context.hh | 68 -------- src/cpu/o3/sparc/cpu.cc | 5 +- src/cpu/o3/sparc/cpu.hh | 148 ----------------- src/cpu/o3/sparc/cpu_builder.cc | 8 +- src/cpu/o3/sparc/cpu_impl.hh | 300 ----------------------------------- src/cpu/o3/sparc/dyn_inst.hh | 2 +- src/cpu/o3/sparc/impl.hh | 4 +- src/cpu/o3/sparc/thread_context.hh | 78 --------- src/cpu/o3/thread_context.hh | 44 ++++++ 26 files changed, 428 insertions(+), 1535 deletions(-) delete mode 100644 src/cpu/o3/alpha/cpu.hh delete mode 100644 src/cpu/o3/alpha/cpu_impl.hh delete mode 100644 src/cpu/o3/alpha/thread_context.hh delete mode 100755 src/cpu/o3/mips/cpu.hh delete mode 100644 src/cpu/o3/mips/cpu_impl.hh delete mode 100644 src/cpu/o3/mips/thread_context.hh delete mode 100644 src/cpu/o3/sparc/cpu.hh delete mode 100644 src/cpu/o3/sparc/cpu_impl.hh delete mode 100644 src/cpu/o3/sparc/thread_context.hh (limited to 'src') diff --git a/src/cpu/o3/alpha/cpu.cc b/src/cpu/o3/alpha/cpu.cc index ed10b2fd1..740e6476d 100644 --- a/src/cpu/o3/alpha/cpu.cc +++ b/src/cpu/o3/alpha/cpu.cc @@ -29,10 +29,9 @@ */ #include "cpu/o3/alpha/impl.hh" -#include "cpu/o3/alpha/cpu_impl.hh" -#include "cpu/o3/alpha/dyn_inst.hh" +#include "cpu/o3/cpu.hh" // Force instantiation of AlphaO3CPU for all the implemntations that are // needed. Consider merging this and alpha_dyn_inst.cc, and maybe all // classes that depend on a certain impl, into one file (alpha_impl.cc?). -template class AlphaO3CPU; +template class FullO3CPU; diff --git a/src/cpu/o3/alpha/cpu.hh b/src/cpu/o3/alpha/cpu.hh deleted file mode 100644 index f9f0000d4..000000000 --- a/src/cpu/o3/alpha/cpu.hh +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2004-2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - */ - -#ifndef __CPU_O3_ALPHA_CPU_HH__ -#define __CPU_O3_ALPHA_CPU_HH__ - -#include "arch/regfile.hh" -#include "arch/types.hh" -#include "cpu/thread_context.hh" -#include "cpu/o3/cpu.hh" -#include "sim/byteswap.hh" - -class DerivO3CPUParams; -class EndQuiesceEvent; -namespace Kernel { - class Statistics; -}; - -class TranslatingPort; - -/** - * AlphaO3CPU class. Derives from the FullO3CPU class, and - * implements all ISA and implementation specific functions of the - * CPU. This is the CPU class that is used for the SimObjects, and is - * what is given to the DynInsts. Most of its state exists in the - * FullO3CPU; the state is has is mainly for ISA specific - * functionality. - */ -template -class AlphaO3CPU : public FullO3CPU -{ - public: - typedef O3ThreadState ImplState; - typedef O3ThreadState Thread; - - /** Constructs an AlphaO3CPU with the given parameters. */ - AlphaO3CPU(DerivO3CPUParams *params); - - /** Registers statistics. */ - void regStats(); - - /** Reads a miscellaneous register. */ - TheISA::MiscReg readMiscRegNoEffect(int misc_reg, unsigned tid); - - /** Reads a misc. register, including any side effects the read - * might have as defined by the architecture. - */ - TheISA::MiscReg readMiscReg(int misc_reg, unsigned tid); - - /** Sets a miscellaneous register. */ - void setMiscRegNoEffect(int misc_reg, const TheISA::MiscReg &val, - unsigned tid); - - /** Sets a misc. register, including any side effects the write - * might have as defined by the architecture. - */ - void setMiscReg(int misc_reg, const TheISA::MiscReg &val, - unsigned tid); - - /** Initiates a squash of all in-flight instructions for a given - * thread. The source of the squash is an external update of - * state through the TC. - */ - void squashFromTC(unsigned tid); - -#if FULL_SYSTEM - /** Posts an interrupt. */ - void post_interrupt(int int_num, int index); - /** HW return from error interrupt. */ - Fault hwrei(unsigned tid); - - bool simPalCheck(int palFunc, unsigned tid); - - /** Returns the Fault for any valid interrupt. */ - Fault getInterrupts(); - - /** Processes any an interrupt fault. */ - void processInterrupts(Fault interrupt); - - /** Halts the CPU. */ - void halt() { panic("Halt not implemented!\n"); } -#endif - - /** Traps to handle given fault. */ - void trap(Fault fault, unsigned tid); - -#if !FULL_SYSTEM - /** Executes a syscall. - * @todo: Determine if this needs to be virtual. - */ - void syscall(int64_t callnum, int tid); - /** Gets a syscall argument. */ - TheISA::IntReg getSyscallArg(int i, int tid); - - /** Used to shift args for indirect syscall. */ - void setSyscallArg(int i, TheISA::IntReg val, int tid); - - /** Sets the return value of a syscall. */ - void setSyscallReturn(SyscallReturn return_value, int tid); -#endif - - /** CPU read function, forwards read to LSQ. */ - template - Fault read(RequestPtr &req, T &data, int load_idx) - { - return this->iew.ldstQueue.read(req, data, load_idx); - } - - /** CPU write function, forwards write to LSQ. */ - template - Fault write(RequestPtr &req, T &data, int store_idx) - { - return this->iew.ldstQueue.write(req, data, store_idx); - } - - Addr lockAddr; - - /** Temporary fix for the lock flag, works in the UP case. */ - bool lockFlag; -}; - -#endif // __CPU_O3_ALPHA_CPU_HH__ diff --git a/src/cpu/o3/alpha/cpu_builder.cc b/src/cpu/o3/alpha/cpu_builder.cc index 0ff0d5d52..deeb437be 100644 --- a/src/cpu/o3/alpha/cpu_builder.cc +++ b/src/cpu/o3/alpha/cpu_builder.cc @@ -30,18 +30,17 @@ #include +#include "config/full_system.hh" #include "config/use_checker.hh" -#include "cpu/base.hh" -#include "cpu/o3/alpha/cpu.hh" +#include "cpu/o3/cpu.hh" #include "cpu/o3/alpha/impl.hh" -#include "cpu/o3/fu_pool.hh" #include "params/DerivO3CPU.hh" -class DerivO3CPU : public AlphaO3CPU +class DerivO3CPU : public FullO3CPU { public: DerivO3CPU(DerivO3CPUParams *p) - : AlphaO3CPU(p) + : FullO3CPU(p) { } }; diff --git a/src/cpu/o3/alpha/cpu_impl.hh b/src/cpu/o3/alpha/cpu_impl.hh deleted file mode 100644 index dc64113e1..000000000 --- a/src/cpu/o3/alpha/cpu_impl.hh +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright (c) 2004-2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - */ - -#include "config/use_checker.hh" - -#include "arch/alpha/faults.hh" -#include "arch/alpha/isa_traits.hh" -#include "base/cprintf.hh" -#include "base/statistics.hh" -#include "base/timebuf.hh" -#include "cpu/checker/thread_context.hh" -#include "sim/sim_events.hh" -#include "sim/stats.hh" - -#include "cpu/o3/alpha/cpu.hh" -#include "cpu/o3/alpha/thread_context.hh" -#include "cpu/o3/comm.hh" -#include "cpu/o3/thread_state.hh" - -#if FULL_SYSTEM -#include "arch/alpha/osfpal.hh" -#include "arch/isa_traits.hh" -#include "arch/kernel_stats.hh" -#include "cpu/quiesce_event.hh" -#include "sim/sim_exit.hh" -#include "sim/system.hh" -#endif - -#include "params/DerivO3CPU.hh" - -template -AlphaO3CPU::AlphaO3CPU(DerivO3CPUParams *params) : - FullO3CPU(this, params) -{ - DPRINTF(O3CPU, "Creating AlphaO3CPU object.\n"); - - // Setup any thread state. - this->thread.resize(this->numThreads); - - for (int i = 0; i < this->numThreads; ++i) { -#if FULL_SYSTEM - // SMT is not supported in FS mode yet. - assert(this->numThreads == 1); - this->thread[i] = new Thread(this, 0); - this->thread[i]->setStatus(ThreadContext::Suspended); -#else - if (i < params->workload.size()) { - DPRINTF(O3CPU, "Workload[%i] process is %#x", - i, this->thread[i]); - this->thread[i] = new Thread(this, i, params->workload[i], i); - - this->thread[i]->setStatus(ThreadContext::Suspended); - - //usedTids[i] = true; - //threadMap[i] = i; - } else { - //Allocate Empty thread so M5 can use later - //when scheduling threads to CPU - Process* dummy_proc = NULL; - - this->thread[i] = new Thread(this, i, dummy_proc, i); - //usedTids[i] = false; - } -#endif // !FULL_SYSTEM - - ThreadContext *tc; - - // Setup the TC that will serve as the interface to the threads/CPU. - AlphaTC *alpha_tc = - new AlphaTC; - - tc = alpha_tc; - - // If we're using a checker, then the TC should be the - // CheckerThreadContext. -#if USE_CHECKER - if (params->checker) { - tc = new CheckerThreadContext >( - alpha_tc, this->checker); - } -#endif - - alpha_tc->cpu = this; - alpha_tc->thread = this->thread[i]; - -#if FULL_SYSTEM - // Setup quiesce event. - this->thread[i]->quiesceEvent = new EndQuiesceEvent(tc); -#endif - // Give the thread the TC. - this->thread[i]->tc = tc; - this->thread[i]->setCpuId(params->cpu_id); - - // Add the TC to the CPU's list of TC's. - this->threadContexts.push_back(tc); - } - - for (int i=0; i < this->numThreads; i++) { - this->thread[i]->setFuncExeInst(0); - } - - lockAddr = 0; - lockFlag = false; -} - -template -void -AlphaO3CPU::regStats() -{ - // Register stats for everything that has stats. - this->fullCPURegStats(); - this->fetch.regStats(); - this->decode.regStats(); - this->rename.regStats(); - this->iew.regStats(); - this->commit.regStats(); -} - - -template -TheISA::MiscReg -AlphaO3CPU::readMiscRegNoEffect(int misc_reg, unsigned tid) -{ - return this->regFile.readMiscRegNoEffect(misc_reg, tid); -} - -template -TheISA::MiscReg -AlphaO3CPU::readMiscReg(int misc_reg, unsigned tid) -{ - return this->regFile.readMiscReg(misc_reg, tid); -} - -template -void -AlphaO3CPU::setMiscRegNoEffect(int misc_reg, const TheISA::MiscReg &val, - unsigned tid) -{ - this->regFile.setMiscRegNoEffect(misc_reg, val, tid); -} - -template -void -AlphaO3CPU::setMiscReg(int misc_reg, - const TheISA::MiscReg &val, unsigned tid) -{ - this->regFile.setMiscReg(misc_reg, val, tid); -} - -template -void -AlphaO3CPU::squashFromTC(unsigned tid) -{ - this->thread[tid]->inSyscall = true; - this->commit.generateTCEvent(tid); -} - -#if FULL_SYSTEM - -template -void -AlphaO3CPU::post_interrupt(int int_num, int index) -{ - BaseCPU::post_interrupt(int_num, index); - - if (this->thread[0]->status() == ThreadContext::Suspended) { - DPRINTF(IPI,"Suspended Processor awoke\n"); - this->threadContexts[0]->activate(); - } -} - -template -Fault -AlphaO3CPU::hwrei(unsigned tid) -{ - // Need to clear the lock flag upon returning from an interrupt. - this->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, false, tid); - - this->thread[tid]->kernelStats->hwrei(); - - // FIXME: XXX check for interrupts? XXX - return NoFault; -} - -template -bool -AlphaO3CPU::simPalCheck(int palFunc, unsigned tid) -{ - if (this->thread[tid]->kernelStats) - this->thread[tid]->kernelStats->callpal(palFunc, - this->threadContexts[tid]); - - switch (palFunc) { - case PAL::halt: - halt(); - if (--System::numSystemsRunning == 0) - exitSimLoop("all cpus halted"); - break; - - case PAL::bpt: - case PAL::bugchk: - if (this->system->breakpoint()) - return false; - break; - } - - return true; -} - -template -Fault -AlphaO3CPU::getInterrupts() -{ - // Check if there are any outstanding interrupts - return this->interrupts.getInterrupt(this->threadContexts[0]); -} - -template -void -AlphaO3CPU::processInterrupts(Fault interrupt) -{ - // Check for interrupts here. For now can copy the code that - // exists within isa_fullsys_traits.hh. Also assume that thread 0 - // is the one that handles the interrupts. - // @todo: Possibly consolidate the interrupt checking code. - // @todo: Allow other threads to handle interrupts. - - assert(interrupt != NoFault); - this->interrupts.updateIntrInfo(this->threadContexts[0]); - - DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name()); - this->trap(interrupt, 0); -} - -#endif // FULL_SYSTEM - -template -void -AlphaO3CPU::trap(Fault fault, unsigned tid) -{ - // Pass the thread's TC into the invoke method. - fault->invoke(this->threadContexts[tid]); -} - -#if !FULL_SYSTEM - -template -void -AlphaO3CPU::syscall(int64_t callnum, int tid) -{ - DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid); - - DPRINTF(Activity,"Activity: syscall() called.\n"); - - // Temporarily increase this by one to account for the syscall - // instruction. - ++(this->thread[tid]->funcExeInst); - - // Execute the actual syscall. - this->thread[tid]->syscall(callnum); - - // Decrease funcExeInst by one as the normal commit will handle - // incrementing it. - --(this->thread[tid]->funcExeInst); -} - -template -TheISA::IntReg -AlphaO3CPU::getSyscallArg(int i, int tid) -{ - assert(i < TheISA::NumArgumentRegs); - return this->readArchIntReg(AlphaISA::ArgumentReg[i], tid); -} - -template -void -AlphaO3CPU::setSyscallArg(int i, TheISA::IntReg val, int tid) -{ - assert(i < TheISA::NumArgumentRegs); - this->setArchIntReg(AlphaISA::ArgumentReg[i], val, tid); -} - -template -void -AlphaO3CPU::setSyscallReturn(SyscallReturn return_value, int tid) -{ - TheISA::setSyscallReturn(return_value, this->tcBase(tid)); -} -#endif diff --git a/src/cpu/o3/alpha/dyn_inst.hh b/src/cpu/o3/alpha/dyn_inst.hh index 180545c3d..06568bc94 100644 --- a/src/cpu/o3/alpha/dyn_inst.hh +++ b/src/cpu/o3/alpha/dyn_inst.hh @@ -34,8 +34,8 @@ #include "arch/isa_traits.hh" #include "cpu/base_dyn_inst.hh" #include "cpu/inst_seq.hh" -#include "cpu/o3/alpha/cpu.hh" #include "cpu/o3/alpha/impl.hh" +#include "cpu/o3/cpu.hh" class Packet; diff --git a/src/cpu/o3/alpha/impl.hh b/src/cpu/o3/alpha/impl.hh index d2d04292c..12ee495d1 100644 --- a/src/cpu/o3/alpha/impl.hh +++ b/src/cpu/o3/alpha/impl.hh @@ -41,7 +41,7 @@ template class AlphaDynInst; template -class AlphaO3CPU; +class FullO3CPU; /** Implementation specific struct that defines several key types to the * CPU, the stages within the CPU, the time buffers, and the DynInst. @@ -68,7 +68,7 @@ struct AlphaSimpleImpl typedef RefCountingPtr DynInstPtr; /** The O3CPU type to be used. */ - typedef AlphaO3CPU O3CPU; + typedef FullO3CPU O3CPU; /** Same typedef, but for CPUType. BaseDynInst may not always use * an O3 CPU, so it's clearer to call it CPUType instead in that diff --git a/src/cpu/o3/alpha/thread_context.hh b/src/cpu/o3/alpha/thread_context.hh deleted file mode 100644 index 6d61501ac..000000000 --- a/src/cpu/o3/alpha/thread_context.hh +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2004-2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - */ - -#include "arch/alpha/types.hh" -#include "cpu/o3/thread_context.hh" - -template -class AlphaTC : public O3ThreadContext -{ - public: -#if FULL_SYSTEM - /** Returns pointer to the quiesce event. */ - virtual EndQuiesceEvent *getQuiesceEvent() - { - return this->thread->quiesceEvent; - } -#endif - - virtual uint64_t readNextNPC() - { - return this->readNextPC() + sizeof(TheISA::MachInst); - } - - virtual void setNextNPC(uint64_t val) - { - panic("Alpha has no NextNPC!"); - } - - virtual void changeRegFileContext(TheISA::RegContextParam param, - TheISA::RegContextVal val) - { panic("Not supported on Alpha!"); } - - - /** This function exits the thread context in the CPU and returns - * 1 if the CPU has no more active threads (meaning it's OK to exit); - * Used in syscall-emulation mode when a thread executes the 'exit' - * syscall. - */ - virtual int exit() - { - this->deallocate(); - - // If there are still threads executing in the system - if (this->cpu->numActiveThreads()) - return 0; // don't exit simulation - else - return 1; // exit simulation - } -}; diff --git a/src/cpu/o3/base_dyn_inst.cc b/src/cpu/o3/base_dyn_inst.cc index 0979c5c8f..3cf89e1b6 100644 --- a/src/cpu/o3/base_dyn_inst.cc +++ b/src/cpu/o3/base_dyn_inst.cc @@ -29,6 +29,7 @@ */ #include "cpu/base_dyn_inst_impl.hh" +#include "cpu/o3/cpu.hh" #include "cpu/o3/isa_specific.hh" // Explicit instantiation diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 13a0962fd..18b417141 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -37,6 +37,7 @@ #include "cpu/thread_context.hh" #include "cpu/o3/isa_specific.hh" #include "cpu/o3/cpu.hh" +#include "cpu/o3/thread_context.hh" #include "enums/MemoryMode.hh" #include "sim/core.hh" #include "sim/stat_control.hh" @@ -52,6 +53,10 @@ #include "cpu/checker/cpu.hh" #endif +#if THE_ISA == ALPHA_ISA +#include "arch/alpha/osfpal.hh" +#endif + class BaseCPUParams; using namespace TheISA; @@ -149,26 +154,26 @@ FullO3CPU::DeallocateContextEvent::description() const } template -FullO3CPU::FullO3CPU(O3CPU *o3_cpu, DerivO3CPUParams *params) +FullO3CPU::FullO3CPU(DerivO3CPUParams *params) : BaseO3CPU(params), itb(params->itb), dtb(params->dtb), tickEvent(this), removeInstsThisCycle(false), - fetch(o3_cpu, params), - decode(o3_cpu, params), - rename(o3_cpu, params), - iew(o3_cpu, params), - commit(o3_cpu, params), + fetch(this, params), + decode(this, params), + rename(this, params), + iew(this, params), + commit(this, params), - regFile(o3_cpu, params->numPhysIntRegs, + regFile(this, params->numPhysIntRegs, params->numPhysFloatRegs), freeList(params->numThreads, TheISA::NumIntRegs, params->numPhysIntRegs, TheISA::NumFloatRegs, params->numPhysFloatRegs), - rob(o3_cpu, + rob(this, params->numROBEntries, params->squashWidth, params->smtROBPolicy, params->smtROBThreshold, params->numThreads), @@ -338,8 +343,109 @@ FullO3CPU::FullO3CPU(O3CPU *o3_cpu, DerivO3CPUParams *params) //} contextSwitch = false; + DPRINTF(O3CPU, "Creating O3CPU object.\n"); + + // Setup any thread state. + this->thread.resize(this->numThreads); + + for (int i = 0; i < this->numThreads; ++i) { +#if FULL_SYSTEM + // SMT is not supported in FS mode yet. + assert(this->numThreads == 1); + this->thread[i] = new Thread(this, 0); + this->thread[i]->setStatus(ThreadContext::Suspended); +#else + if (i < params->workload.size()) { + DPRINTF(O3CPU, "Workload[%i] process is %#x", + i, this->thread[i]); + this->thread[i] = new typename FullO3CPU::Thread( + (typename Impl::O3CPU *)(this), + i, params->workload[i], i); + + this->thread[i]->setStatus(ThreadContext::Suspended); + + //usedTids[i] = true; + //threadMap[i] = i; + } else { + //Allocate Empty thread so M5 can use later + //when scheduling threads to CPU + Process* dummy_proc = NULL; + + this->thread[i] = new typename FullO3CPU::Thread( + (typename Impl::O3CPU *)(this), + i, dummy_proc, i); + //usedTids[i] = false; + } +#endif // !FULL_SYSTEM + + ThreadContext *tc; + + // Setup the TC that will serve as the interface to the threads/CPU. + O3ThreadContext *o3_tc = new O3ThreadContext; + + tc = o3_tc; + + // If we're using a checker, then the TC should be the + // CheckerThreadContext. +#if USE_CHECKER + if (params->checker) { + tc = new CheckerThreadContext >( + o3_tc, this->checker); + } +#endif + + o3_tc->cpu = (typename Impl::O3CPU *)(this); + assert(o3_tc->cpu); + o3_tc->thread = this->thread[i]; + +#if FULL_SYSTEM + // Setup quiesce event. + this->thread[i]->quiesceEvent = new EndQuiesceEvent(tc); +#endif + // Give the thread the TC. + this->thread[i]->tc = tc; + this->thread[i]->setCpuId(params->cpu_id); + + // Add the TC to the CPU's list of TC's. + this->threadContexts.push_back(tc); + } + + for (int i=0; i < this->numThreads; i++) { + this->thread[i]->setFuncExeInst(0); + } + + lockAddr = 0; + lockFlag = false; +} + +#if !FULL_SYSTEM + +template +TheISA::IntReg +FullO3CPU::getSyscallArg(int i, int tid) +{ + assert(i < TheISA::NumArgumentRegs); + TheISA::IntReg idx = TheISA::flattenIntIndex(this->tcBase(tid), + TheISA::ArgumentReg[i]); + TheISA::IntReg val = this->readArchIntReg(idx, tid); +#if THE_ISA == SPARC_ISA + if (bits(this->readMiscRegNoEffect(SparcISA::MISCREG_PSTATE, tid), 3, 3)) + val = bits(val, 31, 0); +#endif + return val; } +template +void +FullO3CPU::setSyscallArg(int i, TheISA::IntReg val, int tid) +{ + assert(i < TheISA::NumArgumentRegs); + TheISA::IntReg idx = TheISA::flattenIntIndex(this->tcBase(tid), + TheISA::ArgumentReg[i]); + this->setArchIntReg(idx, val, tid); +} +#endif + template FullO3CPU::~FullO3CPU() { @@ -347,7 +453,7 @@ FullO3CPU::~FullO3CPU() template void -FullO3CPU::fullCPURegStats() +FullO3CPU::regStats() { BaseO3CPU::regStats(); @@ -401,6 +507,11 @@ FullO3CPU::fullCPURegStats() .precision(6); totalIpc = totalCommittedInsts / numCycles; + this->fetch.regStats(); + this->decode.regStats(); + this->rename.regStats(); + this->iew.regStats(); + this->commit.regStats(); } template @@ -783,6 +894,84 @@ FullO3CPU::activateWhenReady(int tid) } #if FULL_SYSTEM +template +void +FullO3CPU::post_interrupt(int int_num, int index) +{ + BaseCPU::post_interrupt(int_num, index); + + if (this->thread[0]->status() == ThreadContext::Suspended) { + DPRINTF(IPI,"Suspended Processor awoke\n"); + this->threadContexts[0]->activate(); + } +} + +template +Fault +FullO3CPU::hwrei(unsigned tid) +{ +#if THE_ISA == ALPHA_ISA + // Need to clear the lock flag upon returning from an interrupt. + this->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, false, tid); + + this->thread[tid]->kernelStats->hwrei(); + + // FIXME: XXX check for interrupts? XXX +#endif + return NoFault; +} + +template +bool +FullO3CPU::simPalCheck(int palFunc, unsigned tid) +{ +#if THE_ISA == ALPHA_ISA + if (this->thread[tid]->kernelStats) + this->thread[tid]->kernelStats->callpal(palFunc, + this->threadContexts[tid]); + + switch (palFunc) { + case PAL::halt: + halt(); + if (--System::numSystemsRunning == 0) + exitSimLoop("all cpus halted"); + break; + + case PAL::bpt: + case PAL::bugchk: + if (this->system->breakpoint()) + return false; + break; + } +#endif + return true; +} + +template +Fault +FullO3CPU::getInterrupts() +{ + // Check if there are any outstanding interrupts + return this->interrupts.getInterrupt(this->threadContexts[0]); +} + +template +void +FullO3CPU::processInterrupts(Fault interrupt) +{ + // Check for interrupts here. For now can copy the code that + // exists within isa_fullsys_traits.hh. Also assume that thread 0 + // is the one that handles the interrupts. + // @todo: Possibly consolidate the interrupt checking code. + // @todo: Allow other threads to handle interrupts. + + assert(interrupt != NoFault); + this->interrupts.updateIntrInfo(this->threadContexts[0]); + + DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name()); + this->trap(interrupt, 0); +} + template void FullO3CPU::updateMemPorts() @@ -794,6 +983,45 @@ FullO3CPU::updateMemPorts() } #endif +template +void +FullO3CPU::trap(Fault fault, unsigned tid) +{ + // Pass the thread's TC into the invoke method. + fault->invoke(this->threadContexts[tid]); +} + +#if !FULL_SYSTEM + +template +void +FullO3CPU::syscall(int64_t callnum, int tid) +{ + DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid); + + DPRINTF(Activity,"Activity: syscall() called.\n"); + + // Temporarily increase this by one to account for the syscall + // instruction. + ++(this->thread[tid]->funcExeInst); + + // Execute the actual syscall. + this->thread[tid]->syscall(callnum); + + // Decrease funcExeInst by one as the normal commit will handle + // incrementing it. + --(this->thread[tid]->funcExeInst); +} + +template +void +FullO3CPU::setSyscallReturn(SyscallReturn return_value, int tid) +{ + TheISA::setSyscallReturn(return_value, this->tcBase(tid)); +} + +#endif + template void FullO3CPU::serialize(std::ostream &os) @@ -993,6 +1221,36 @@ FullO3CPU::takeOverFrom(BaseCPU *oldCPU) tickEvent.schedule(nextCycle()); } +template +TheISA::MiscReg +FullO3CPU::readMiscRegNoEffect(int misc_reg, unsigned tid) +{ + return this->regFile.readMiscRegNoEffect(misc_reg, tid); +} + +template +TheISA::MiscReg +FullO3CPU::readMiscReg(int misc_reg, unsigned tid) +{ + return this->regFile.readMiscReg(misc_reg, tid); +} + +template +void +FullO3CPU::setMiscRegNoEffect(int misc_reg, + const TheISA::MiscReg &val, unsigned tid) +{ + this->regFile.setMiscRegNoEffect(misc_reg, val, tid); +} + +template +void +FullO3CPU::setMiscReg(int misc_reg, + const TheISA::MiscReg &val, unsigned tid) +{ + this->regFile.setMiscReg(misc_reg, val, tid); +} + template uint64_t FullO3CPU::readIntReg(int reg_idx) @@ -1211,6 +1469,14 @@ FullO3CPU::setNextMicroPC(Addr new_PC,unsigned tid) commit.setNextMicroPC(new_PC, tid); } +template +void +FullO3CPU::squashFromTC(unsigned tid) +{ + this->thread[tid]->inSyscall = true; + this->commit.generateTCEvent(tid); +} + template typename FullO3CPU::ListIt FullO3CPU::addInst(DynInstPtr &inst) diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 611d03bad..065dd10a0 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -99,6 +99,7 @@ class FullO3CPU : public BaseO3CPU typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::O3CPU O3CPU; + typedef O3ThreadState ImplState; typedef O3ThreadState Thread; typedef typename std::list::iterator ListIt; @@ -201,6 +202,13 @@ class FullO3CPU : public BaseO3CPU activateThreadEvent[tid].squash(); } +#if !FULL_SYSTEM + TheISA::IntReg getSyscallArg(int i, int tid); + + /** Used to shift args for indirect syscall. */ + void setSyscallArg(int i, TheISA::IntReg val, int tid); +#endif + /** The tick event used for scheduling CPU ticks. */ ActivateThreadEvent activateThreadEvent[Impl::MaxThreads]; @@ -257,12 +265,12 @@ class FullO3CPU : public BaseO3CPU public: /** Constructs a CPU with the given parameters. */ - FullO3CPU(O3CPU *o3_cpu, DerivO3CPUParams *params); + FullO3CPU(DerivO3CPUParams *params); /** Destructor. */ ~FullO3CPU(); /** Registers statistics. */ - void fullCPURegStats(); + void regStats(); void demapPage(Addr vaddr, uint64_t asn) { @@ -368,12 +376,16 @@ class FullO3CPU : public BaseO3CPU virtual void unserialize(Checkpoint *cp, const std::string §ion); public: - /** Executes a syscall on this cycle. - * --------------------------------------- - * Note: this is a virtual function. CPU-Specific - * functionality defined in derived classes +#if !FULL_SYSTEM + /** Executes a syscall. + * @todo: Determine if this needs to be virtual. */ - virtual void syscall(int tid) { panic("Unimplemented!"); } + void syscall(int64_t callnum, int tid); + + /** Sets the return value of a syscall. */ + void setSyscallReturn(SyscallReturn return_value, int tid); + +#endif /** Starts draining the CPU's pipeline of all instructions in * order to stop all memory accesses. */ @@ -395,7 +407,27 @@ class FullO3CPU : public BaseO3CPU InstSeqNum getAndIncrementInstSeq() { return globalSeqNum++; } + /** Traps to handle given fault. */ + void trap(Fault fault, unsigned tid); + #if FULL_SYSTEM + /** Posts an interrupt. */ + void post_interrupt(int int_num, int index); + + /** HW return from error interrupt. */ + Fault hwrei(unsigned tid); + + bool simPalCheck(int palFunc, unsigned tid); + + /** Returns the Fault for any valid interrupt. */ + Fault getInterrupts(); + + /** Processes any an interrupt fault. */ + void processInterrupts(Fault interrupt); + + /** 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(); @@ -425,6 +457,24 @@ class FullO3CPU : public BaseO3CPU #endif /** Register accessors. Index refers to the physical register index. */ + + /** Reads a miscellaneous register. */ + TheISA::MiscReg readMiscRegNoEffect(int misc_reg, unsigned tid); + + /** Reads a misc. register, including any side effects the read + * might have as defined by the architecture. + */ + TheISA::MiscReg readMiscReg(int misc_reg, unsigned tid); + + /** Sets a miscellaneous register. */ + void setMiscRegNoEffect(int misc_reg, const TheISA::MiscReg &val, unsigned tid); + + /** Sets a misc. register, including any side effects the write + * might have as defined by the architecture. + */ + void setMiscReg(int misc_reg, const TheISA::MiscReg &val, + unsigned tid); + uint64_t readIntReg(int reg_idx); TheISA::FloatReg readFloatReg(int reg_idx); @@ -496,6 +546,12 @@ class FullO3CPU : public BaseO3CPU /** Sets the commit next micro PC of a specific thread. */ void setNextMicroPC(Addr val, unsigned tid); + /** Initiates a squash of all in-flight instructions for a given + * thread. The source of the squash is an external update of + * state through the TC. + */ + void squashFromTC(unsigned tid); + /** Function to add instruction onto the head of the list of the * instructions. Used when new instructions are fetched. */ @@ -711,6 +767,25 @@ class FullO3CPU : public BaseO3CPU /** Available thread ids in the cpu*/ std::vector tids; + /** CPU read function, forwards read to LSQ. */ + template + Fault read(RequestPtr &req, T &data, int load_idx) + { + return this->iew.ldstQueue.read(req, data, load_idx); + } + + /** CPU write function, forwards write to LSQ. */ + template + Fault write(RequestPtr &req, T &data, int store_idx) + { + return this->iew.ldstQueue.write(req, data, store_idx); + } + + Addr lockAddr; + + /** Temporary fix for the lock flag, works in the UP case. */ + bool lockFlag; + /** Stat for total number of times the CPU is descheduled. */ Stats::Scalar<> timesIdled; /** Stat for total number of cycles the CPU spends descheduled. */ diff --git a/src/cpu/o3/isa_specific.hh b/src/cpu/o3/isa_specific.hh index 9e74f4c8c..5e759b41d 100755 --- a/src/cpu/o3/isa_specific.hh +++ b/src/cpu/o3/isa_specific.hh @@ -31,15 +31,12 @@ #include "cpu/base.hh" #if THE_ISA == ALPHA_ISA - #include "cpu/o3/alpha/cpu.hh" #include "cpu/o3/alpha/impl.hh" #include "cpu/o3/alpha/dyn_inst.hh" #elif THE_ISA == MIPS_ISA - #include "cpu/o3/mips/cpu.hh" #include "cpu/o3/mips/impl.hh" #include "cpu/o3/mips/dyn_inst.hh" #elif THE_ISA == SPARC_ISA - #include "cpu/o3/sparc/cpu.hh" #include "cpu/o3/sparc/impl.hh" #include "cpu/o3/sparc/dyn_inst.hh" #else diff --git a/src/cpu/o3/mips/cpu.cc b/src/cpu/o3/mips/cpu.cc index 420f460b2..bb78de0a6 100755 --- a/src/cpu/o3/mips/cpu.cc +++ b/src/cpu/o3/mips/cpu.cc @@ -29,11 +29,10 @@ * Korey Sewell */ +#include "cpu/o3/cpu.hh" #include "cpu/o3/mips/impl.hh" -#include "cpu/o3/mips/cpu_impl.hh" -#include "cpu/o3/mips/dyn_inst.hh" // Force instantiation of MipsO3CPU for all the implemntations that are // needed. Consider merging this and mips_dyn_inst.cc, and maybe all // classes that depend on a certain impl, into one file (mips_impl.cc?). -template class MipsO3CPU; +template class FullO3CPU; diff --git a/src/cpu/o3/mips/cpu.hh b/src/cpu/o3/mips/cpu.hh deleted file mode 100755 index 38eba5aeb..000000000 --- a/src/cpu/o3/mips/cpu.hh +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - * Korey Sewell - */ - -#ifndef __CPU_O3_MIPS_CPU_HH__ -#define __CPU_O3_MIPS_CPU_HH__ - -#include "arch/mips/regfile.hh" -#include "arch/mips/syscallreturn.hh" -#include "cpu/thread_context.hh" -#include "cpu/o3/cpu.hh" -#include "sim/byteswap.hh" -#include "sim/faults.hh" - -class DerivO3CPUParams; -class EndQuiesceEvent; -namespace Kernel { - class Statistics; -}; - -class TranslatingPort; - -/** - * MipsO3CPU class. Derives from the FullO3CPU class, and - * implements all ISA and implementation specific functions of the - * CPU. This is the CPU class that is used for the SimObjects, and is - * what is given to the DynInsts. Most of its state exists in the - * FullO3CPU; the state is has is mainly for ISA specific - * functionality. - */ -template -class MipsO3CPU : public FullO3CPU -{ - public: - typedef O3ThreadState ImplState; - typedef O3ThreadState Thread; - - /** Constructs an MipsO3CPU with the given parameters. */ - MipsO3CPU(DerivO3CPUParams *params); - - /** Registers statistics. */ - void regStats(); - - /** Reads a miscellaneous register. */ - TheISA::MiscReg readMiscRegNoEffect(int misc_reg, unsigned tid); - - /** Reads a misc. register, including any side effects the read - * might have as defined by the architecture. - */ - TheISA::MiscReg readMiscReg(int misc_reg, unsigned tid); - - /** Sets a miscellaneous register. */ - void setMiscRegNoEffect(int misc_reg, const TheISA::MiscReg &val, unsigned tid); - - /** Sets a misc. register, including any side effects the write - * might have as defined by the architecture. - */ - void setMiscReg(int misc_reg, - const TheISA::MiscReg &val, unsigned tid); - - /** Initiates a squash of all in-flight instructions for a given - * thread. The source of the squash is an external update of - * state through the TC. - */ - void squashFromTC(unsigned tid); - - /** Traps to handle given fault. */ - void trap(Fault fault, unsigned tid); - - /** Executes a syscall. - * @todo: Determine if this needs to be virtual. - */ - void syscall(int64_t callnum, int tid); - /** Gets a syscall argument. */ - TheISA::IntReg getSyscallArg(int i, int tid); - - /** Used to shift args for indirect syscall. */ - void setSyscallArg(int i, TheISA::IntReg val, int tid); - - /** Sets the return value of a syscall. */ - void setSyscallReturn(SyscallReturn return_value, int tid); - - /** CPU read function, forwards read to LSQ. */ - template - Fault read(RequestPtr &req, T &data, int load_idx) - { - return this->iew.ldstQueue.read(req, data, load_idx); - } - - /** CPU write function, forwards write to LSQ. */ - template - Fault write(RequestPtr &req, T &data, int store_idx) - { - return this->iew.ldstQueue.write(req, data, store_idx); - } - - Addr lockAddr; - - /** Temporary fix for the lock flag, works in the UP case. */ - bool lockFlag; -}; - -#endif // __CPU_O3_MIPS_CPU_HH__ diff --git a/src/cpu/o3/mips/cpu_builder.cc b/src/cpu/o3/mips/cpu_builder.cc index 8fe34afab..11942e597 100644 --- a/src/cpu/o3/mips/cpu_builder.cc +++ b/src/cpu/o3/mips/cpu_builder.cc @@ -31,18 +31,17 @@ #include +#include "config/full_system.hh" #include "config/use_checker.hh" -#include "cpu/base.hh" -#include "cpu/o3/mips/cpu.hh" +#include "cpu/o3/cpu.hh" #include "cpu/o3/mips/impl.hh" -#include "cpu/o3/fu_pool.hh" #include "params/DerivO3CPU.hh" -class DerivO3CPU : public MipsO3CPU +class DerivO3CPU : public FullO3CPU { public: DerivO3CPU(DerivO3CPUParams *p) - : MipsO3CPU(p) + : FullO3CPU(p) { } }; diff --git a/src/cpu/o3/mips/cpu_impl.hh b/src/cpu/o3/mips/cpu_impl.hh deleted file mode 100644 index 70dbb4ac4..000000000 --- a/src/cpu/o3/mips/cpu_impl.hh +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - * Korey Sewell - */ - -#include "config/use_checker.hh" - -#include "arch/mips/faults.hh" -#include "base/cprintf.hh" -#include "base/statistics.hh" -#include "base/timebuf.hh" -#include "cpu/checker/thread_context.hh" -#include "sim/sim_events.hh" -#include "sim/stats.hh" - -#include "cpu/o3/mips/cpu.hh" -#include "cpu/o3/mips/thread_context.hh" -#include "cpu/o3/comm.hh" -#include "cpu/o3/thread_state.hh" - -#include "params/DerivO3CPU.hh" - -template -MipsO3CPU::MipsO3CPU(DerivO3CPUParams *params) - : FullO3CPU(this, params) -{ - DPRINTF(O3CPU, "Creating MipsO3CPU object.\n"); - - // Setup any thread state. - this->thread.resize(this->numThreads); - - for (int i = 0; i < this->numThreads; ++i) { - if (i < params->workload.size()) { - DPRINTF(O3CPU, "Workload[%i] process is %#x", - i, this->thread[i]); - this->thread[i] = new Thread(this, i, params->workload[i], i); - - this->thread[i]->setStatus(ThreadContext::Suspended); - - //usedTids[i] = true; - //threadMap[i] = i; - } else { - //Allocate Empty thread so M5 can use later - //when scheduling threads to CPU - Process* dummy_proc = NULL; - - this->thread[i] = new Thread(this, i, dummy_proc, i); - //usedTids[i] = false; - } - - ThreadContext *tc; - - // Setup the TC that will serve as the interface to the threads/CPU. - MipsTC *mips_tc = - new MipsTC; - - tc = mips_tc; - - // If we're using a checker, then the TC should be the - // CheckerThreadContext. -#if USE_CHECKER - if (params->checker) { - tc = new CheckerThreadContext >( - mips_tc, this->checker); - } -#endif - - mips_tc->cpu = this; - mips_tc->thread = this->thread[i]; - - // Give the thread the TC. - this->thread[i]->tc = tc; - this->thread[i]->setCpuId(params->cpu_id); - - // Add the TC to the CPU's list of TC's. - this->threadContexts.push_back(tc); - } - - for (int i=0; i < this->numThreads; i++) { - this->thread[i]->setFuncExeInst(0); - } - - lockAddr = 0; - lockFlag = false; -} - -template -void -MipsO3CPU::regStats() -{ - // Register stats for everything that has stats. - this->fullCPURegStats(); - this->fetch.regStats(); - this->decode.regStats(); - this->rename.regStats(); - this->iew.regStats(); - this->commit.regStats(); -} - - -template -MiscReg -MipsO3CPU::readMiscRegNoEffect(int misc_reg, unsigned tid) -{ - return this->regFile.readMiscRegNoEffect(misc_reg, tid); -} - -template -MiscReg -MipsO3CPU::readMiscReg(int misc_reg, unsigned tid) -{ - return this->regFile.readMiscReg(misc_reg, tid); -} - -template -void -MipsO3CPU::setMiscRegNoEffect(int misc_reg, const MiscReg &val, unsigned tid) -{ - this->regFile.setMiscRegNoEffect(misc_reg, val, tid); -} - -template -void -MipsO3CPU::setMiscReg(int misc_reg, const MiscReg &val, - unsigned tid) -{ - this->regFile.setMiscReg(misc_reg, val, tid); -} - -template -void -MipsO3CPU::squashFromTC(unsigned tid) -{ - this->thread[tid]->inSyscall = true; - this->commit.generateTCEvent(tid); -} - -template -void -MipsO3CPU::trap(Fault fault, unsigned tid) -{ - // Pass the thread's TC into the invoke method. - fault->invoke(this->threadContexts[tid]); -} - -#if !FULL_SYSTEM - -template -void -MipsO3CPU::syscall(int64_t callnum, int tid) -{ - DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid); - - DPRINTF(Activity,"Activity: syscall() called.\n"); - - // Temporarily increase this by one to account for the syscall - // instruction. - ++(this->thread[tid]->funcExeInst); - - // Execute the actual syscall. - this->thread[tid]->syscall(callnum); - - // Decrease funcExeInst by one as the normal commit will handle - // incrementing it. - --(this->thread[tid]->funcExeInst); - - DPRINTF(O3CPU, "[tid:%i] Register 2 is %i ", tid, this->readIntReg(2)); -} - -template -TheISA::IntReg -MipsO3CPU::getSyscallArg(int i, int tid) -{ - assert(i < TheISA::NumArgumentRegs); - return this->readArchIntReg(MipsISA::ArgumentReg[i], tid); -} - -template -void -MipsO3CPU::setSyscallArg(int i, IntReg val, int tid) -{ - assert(i < TheISA::NumArgumentRegs); - this->setArchIntReg(MipsISA::ArgumentReg[i], val, tid); -} - -template -void -MipsO3CPU::setSyscallReturn(SyscallReturn return_value, int tid) -{ - TheISA::setSyscallReturn(return_value, this->tcBase(tid)); -} -#endif diff --git a/src/cpu/o3/mips/dyn_inst.hh b/src/cpu/o3/mips/dyn_inst.hh index 861577966..320d6703f 100755 --- a/src/cpu/o3/mips/dyn_inst.hh +++ b/src/cpu/o3/mips/dyn_inst.hh @@ -35,7 +35,7 @@ #include "arch/isa_traits.hh" #include "cpu/base_dyn_inst.hh" #include "cpu/inst_seq.hh" -#include "cpu/o3/mips/cpu.hh" +#include "cpu/o3/cpu.hh" #include "cpu/o3/mips/impl.hh" class Packet; diff --git a/src/cpu/o3/mips/impl.hh b/src/cpu/o3/mips/impl.hh index 481184006..dbaa4a276 100644 --- a/src/cpu/o3/mips/impl.hh +++ b/src/cpu/o3/mips/impl.hh @@ -42,7 +42,7 @@ template class MipsDynInst; template -class MipsO3CPU; +class FullO3CPU; /** Implementation specific struct that defines several key types to the * CPU, the stages within the CPU, the time buffers, and the DynInst. @@ -69,7 +69,7 @@ struct MipsSimpleImpl typedef RefCountingPtr DynInstPtr; /** The O3CPU type to be used. */ - typedef MipsO3CPU O3CPU; + typedef FullO3CPU O3CPU; /** Same typedef, but for CPUType. BaseDynInst may not always use * an O3 CPU, so it's clearer to call it CPUType instead in that diff --git a/src/cpu/o3/mips/thread_context.hh b/src/cpu/o3/mips/thread_context.hh deleted file mode 100644 index 26b1e2e7f..000000000 --- a/src/cpu/o3/mips/thread_context.hh +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - * Korey Sewell - */ - -#include "arch/mips/types.hh" -#include "cpu/o3/thread_context.hh" - -template -class MipsTC : public O3ThreadContext -{ - public: - virtual uint64_t readNextNPC() - { - return this->cpu->readNextNPC(this->thread->readTid()); - } - - virtual void setNextNPC(uint64_t val) - { - this->cpu->setNextNPC(val, this->thread->readTid()); - } - - virtual void changeRegFileContext(TheISA::RegContextParam param, - TheISA::RegContextVal val) - { panic("Not supported on Mips!"); } - - /** This function exits the thread context in the CPU and returns - * 1 if the CPU has no more active threads (meaning it's OK to exit); - * Used in syscall-emulation mode when a thread executes the 'exit' - * syscall. - */ - virtual int exit() - { - this->deallocate(); - - // If there are still threads executing in the system - if (this->cpu->numActiveThreads()) - return 0; // don't exit simulation - else - return 1; // exit simulation - } -}; diff --git a/src/cpu/o3/sparc/cpu.cc b/src/cpu/o3/sparc/cpu.cc index 1546a2b88..738ff0108 100644 --- a/src/cpu/o3/sparc/cpu.cc +++ b/src/cpu/o3/sparc/cpu.cc @@ -28,11 +28,10 @@ * Authors: Gabe Black */ +#include "cpu/o3/cpu.hh" #include "cpu/o3/sparc/impl.hh" -#include "cpu/o3/sparc/cpu_impl.hh" -#include "cpu/o3/sparc/dyn_inst.hh" // Force instantiation of SparcO3CPU for all the implementations that are // needed. Consider merging this and sparc_dyn_inst.cc, and maybe all // classes that depend on a certain impl, into one file (sparc_impl.cc?). -template class SparcO3CPU; +template class FullO3CPU; diff --git a/src/cpu/o3/sparc/cpu.hh b/src/cpu/o3/sparc/cpu.hh deleted file mode 100644 index cccfd7d52..000000000 --- a/src/cpu/o3/sparc/cpu.hh +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2004-2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - */ - -#ifndef __CPU_O3_SPARC_CPU_HH__ -#define __CPU_O3_SPARC_CPU_HH__ - -#include "arch/sparc/regfile.hh" -#include "arch/sparc/types.hh" -#include "cpu/thread_context.hh" -#include "cpu/o3/cpu.hh" -#include "sim/byteswap.hh" - -class DerivO3CPUParams; -class EndQuiesceEvent; -namespace Kernel { - class Statistics; -}; - -class TranslatingPort; - -/** - * SparcO3CPU class. Derives from the FullO3CPU class, and - * implements all ISA and implementation specific functions of the - * CPU. This is the CPU class that is used for the SimObjects, and is - * what is given to the DynInsts. Most of its state exists in the - * FullO3CPU; the state is has is mainly for ISA specific - * functionality. - */ -template -class SparcO3CPU : public FullO3CPU -{ - public: - typedef O3ThreadState ImplState; - typedef O3ThreadState Thread; - - /** Constructs an AlphaO3CPU with the given parameters. */ - SparcO3CPU(DerivO3CPUParams *params); - - /** Registers statistics. */ - void regStats(); - - /** Reads a miscellaneous register. */ - TheISA::MiscReg readMiscRegNoEffect(int misc_reg, unsigned tid); - - /** Reads a misc. register, including any side effects the read - * might have as defined by the architecture. - */ - TheISA::MiscReg readMiscReg(int misc_reg, unsigned tid); - - /** Sets a miscellaneous register. */ - void setMiscRegNoEffect(int misc_reg, const TheISA::MiscReg &val, unsigned tid); - - /** Sets a misc. register, including any side effects the write - * might have as defined by the architecture. - */ - void setMiscReg(int misc_reg, const TheISA::MiscReg &val, - unsigned tid); - - /** Initiates a squash of all in-flight instructions for a given - * thread. The source of the squash is an external update of - * state through the TC. - */ - void squashFromTC(unsigned tid); - -#if FULL_SYSTEM - /** Posts an interrupt. */ - void post_interrupt(int int_num, int index); - /** HW return from error interrupt. */ - Fault hwrei(unsigned tid); - - bool simPalCheck(int palFunc, unsigned tid); - - /** Returns the Fault for any valid interrupt. */ - Fault getInterrupts(); - - /** Processes any an interrupt fault. */ - void processInterrupts(Fault interrupt); - - /** Halts the CPU. */ - void halt() { panic("Halt not implemented!\n"); } -#endif - - /** Traps to handle given fault. */ - void trap(Fault fault, unsigned tid); - -#if !FULL_SYSTEM - /** Executes a syscall. - * @todo: Determine if this needs to be virtual. - */ - void syscall(int64_t callnum, int tid); - /** Gets a syscall argument. */ - TheISA::IntReg getSyscallArg(int i, int tid); - - /** Used to shift args for indirect syscall. */ - void setSyscallArg(int i, TheISA::IntReg val, int tid); - - /** Sets the return value of a syscall. */ - void setSyscallReturn(SyscallReturn return_value, int tid); -#endif - - /** CPU read function, forwards read to LSQ. */ - template - Fault read(RequestPtr &req, T &data, int load_idx) - { - return this->iew.ldstQueue.read(req, data, load_idx); - } - - /** CPU write function, forwards write to LSQ. */ - template - Fault write(RequestPtr &req, T &data, int store_idx) - { - return this->iew.ldstQueue.write(req, data, store_idx); - } - - Addr lockAddr; - - /** Temporary fix for the lock flag, works in the UP case. */ - bool lockFlag; -}; - -#endif // __CPU_O3_SPARC_CPU_HH__ diff --git a/src/cpu/o3/sparc/cpu_builder.cc b/src/cpu/o3/sparc/cpu_builder.cc index c5ea31210..c19b4871f 100644 --- a/src/cpu/o3/sparc/cpu_builder.cc +++ b/src/cpu/o3/sparc/cpu_builder.cc @@ -32,17 +32,15 @@ #include "config/full_system.hh" #include "config/use_checker.hh" -#include "cpu/base.hh" -#include "cpu/o3/sparc/cpu.hh" +#include "cpu/o3/cpu.hh" #include "cpu/o3/sparc/impl.hh" -#include "cpu/o3/fu_pool.hh" #include "params/DerivO3CPU.hh" -class DerivO3CPU : public SparcO3CPU +class DerivO3CPU : public FullO3CPU { public: DerivO3CPU(DerivO3CPUParams *p) - : SparcO3CPU(p) + : FullO3CPU(p) { } }; diff --git a/src/cpu/o3/sparc/cpu_impl.hh b/src/cpu/o3/sparc/cpu_impl.hh deleted file mode 100644 index 2dd38845f..000000000 --- a/src/cpu/o3/sparc/cpu_impl.hh +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright (c) 2004-2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#include "config/use_checker.hh" - -#include "arch/sparc/faults.hh" -#include "arch/sparc/isa_traits.hh" -#include "arch/sparc/miscregfile.hh" -#include "base/cprintf.hh" -#include "base/statistics.hh" -#include "base/timebuf.hh" -#include "cpu/checker/thread_context.hh" -#include "sim/sim_events.hh" -#include "sim/stats.hh" - -#include "cpu/o3/sparc/cpu.hh" -#include "cpu/o3/sparc/thread_context.hh" -#include "cpu/o3/comm.hh" -#include "cpu/o3/thread_state.hh" - -#if FULL_SYSTEM -#include "arch/sparc/isa_traits.hh" -#include "arch/sparc/kernel_stats.hh" -#include "cpu/quiesce_event.hh" -#include "sim/sim_exit.hh" -#include "sim/system.hh" -#endif - -#include "params/DerivO3CPU.hh" - -template -SparcO3CPU::SparcO3CPU(DerivO3CPUParams *params) : - FullO3CPU(this, params) -{ - DPRINTF(O3CPU, "Creating SparcO3CPU object.\n"); - - // Setup any thread state. - this->thread.resize(this->numThreads); - - for (int i = 0; i < this->numThreads; ++i) { -#if FULL_SYSTEM - // SMT is not supported in FS mode yet. - assert(this->numThreads == 1); - this->thread[i] = new Thread(this, 0); - this->thread[i]->setStatus(ThreadContext::Suspended); -#else - if (i < params->workload.size()) { - DPRINTF(O3CPU, "Workload[%i] process is %#x", - i, this->thread[i]); - this->thread[i] = new Thread(this, i, params->workload[i], i); - - this->thread[i]->setStatus(ThreadContext::Suspended); - - //usedTids[i] = true; - //threadMap[i] = i; - } else { - //Allocate Empty thread so M5 can use later - //when scheduling threads to CPU - Process* dummy_proc = NULL; - - this->thread[i] = new Thread(this, i, dummy_proc, i); - //usedTids[i] = false; - } -#endif // !FULL_SYSTEM - - ThreadContext *tc; - - // Setup the TC that will serve as the interface to the threads/CPU. - SparcTC *sparc_tc = new SparcTC; - - tc = sparc_tc; - - // If we're using a checker, then the TC should be the - // CheckerThreadContext. -#if USE_CHECKER - if (params->checker) { - tc = new CheckerThreadContext >( - sparc_tc, this->checker); - } -#endif - - sparc_tc->cpu = this; - sparc_tc->thread = this->thread[i]; - -#if FULL_SYSTEM - // Setup quiesce event. - this->thread[i]->quiesceEvent = new EndQuiesceEvent(tc); -#endif - // Give the thread the TC. - this->thread[i]->tc = tc; - this->thread[i]->setCpuId(params->cpu_id); - - // Add the TC to the CPU's list of TC's. - this->threadContexts.push_back(tc); - } - - for (int i=0; i < this->numThreads; i++) { - this->thread[i]->setFuncExeInst(0); - } - - lockAddr = 0; - lockFlag = false; -} - -template -void -SparcO3CPU::regStats() -{ - // Register stats for everything that has stats. - this->fullCPURegStats(); - this->fetch.regStats(); - this->decode.regStats(); - this->rename.regStats(); - this->iew.regStats(); - this->commit.regStats(); -} - - -template -TheISA::MiscReg -SparcO3CPU::readMiscRegNoEffect(int misc_reg, unsigned tid) -{ - return this->regFile.readMiscRegNoEffect(misc_reg, tid); -} - -template -TheISA::MiscReg -SparcO3CPU::readMiscReg(int misc_reg, unsigned tid) -{ - return this->regFile.readMiscReg(misc_reg, tid); -} - -template -void -SparcO3CPU::setMiscRegNoEffect(int misc_reg, - const SparcISA::MiscReg &val, unsigned tid) -{ - this->regFile.setMiscRegNoEffect(misc_reg, val, tid); -} - -template -void -SparcO3CPU::setMiscReg(int misc_reg, - const SparcISA::MiscReg &val, unsigned tid) -{ - this->regFile.setMiscReg(misc_reg, val, tid); -} - -template -void -SparcO3CPU::squashFromTC(unsigned tid) -{ - this->thread[tid]->inSyscall = true; - this->commit.generateTCEvent(tid); -} - -#if FULL_SYSTEM - -template -void -SparcO3CPU::post_interrupt(int int_num, int index) -{ - BaseCPU::post_interrupt(int_num, index); - - if (this->thread[0]->status() == ThreadContext::Suspended) { - DPRINTF(IPI,"Suspended Processor awoke\n"); - this->threadContexts[0]->activate(); - } -} - -template -Fault -SparcO3CPU::hwrei(unsigned tid) -{ - panic("This doesn't make sense for SPARC\n"); - return NoFault; -} - -template -bool -SparcO3CPU::simPalCheck(int palFunc, unsigned tid) -{ - panic("This doesn't make sense for SPARC\n"); - return true; -} - -template -Fault -SparcO3CPU::getInterrupts() -{ - // Check if there are any outstanding interrupts - return this->interrupts.getInterrupt(this->threadContexts[0]); -} - -template -void -SparcO3CPU::processInterrupts(Fault interrupt) -{ - // Check for interrupts here. For now can copy the code that - // exists within isa_fullsys_traits.hh. Also assume that thread 0 - // is the one that handles the interrupts. - // @todo: Possibly consolidate the interrupt checking code. - // @todo: Allow other threads to handle interrupts. - - assert(interrupt != NoFault); - this->interrupts.updateIntrInfo(this->threadContexts[0]); - - DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name()); - this->trap(interrupt, 0); -} - -#endif // FULL_SYSTEM - -template -void -SparcO3CPU::trap(Fault fault, unsigned tid) -{ - // Pass the thread's TC into the invoke method. - fault->invoke(this->threadContexts[tid]); -} - -#if !FULL_SYSTEM - -template -void -SparcO3CPU::syscall(int64_t callnum, int tid) -{ - DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid); - - DPRINTF(Activity,"Activity: syscall() called.\n"); - - // Temporarily increase this by one to account for the syscall - // instruction. - ++(this->thread[tid]->funcExeInst); - - // Execute the actual syscall. - this->thread[tid]->syscall(callnum); - - // Decrease funcExeInst by one as the normal commit will handle - // incrementing it. - --(this->thread[tid]->funcExeInst); -} - -template -TheISA::IntReg -SparcO3CPU::getSyscallArg(int i, int tid) -{ - assert(i < TheISA::NumArgumentRegs); - TheISA::IntReg idx = TheISA::flattenIntIndex(this->tcBase(tid), - SparcISA::ArgumentReg[i]); - TheISA::IntReg val = this->readArchIntReg(idx, tid); - if (bits(this->readMiscRegNoEffect(SparcISA::MISCREG_PSTATE, tid), 3, 3)) - val = bits(val, 31, 0); - return val; -} - -template -void -SparcO3CPU::setSyscallArg(int i, TheISA::IntReg val, int tid) -{ - assert(i < TheISA::NumArgumentRegs); - TheISA::IntReg idx = TheISA::flattenIntIndex(this->tcBase(tid), - SparcISA::ArgumentReg[i]); - this->setArchIntReg(idx, val, tid); -} - -template -void -SparcO3CPU::setSyscallReturn(SyscallReturn return_value, int tid) -{ - TheISA::setSyscallReturn(return_value, this->tcBase(tid)); -} -#endif diff --git a/src/cpu/o3/sparc/dyn_inst.hh b/src/cpu/o3/sparc/dyn_inst.hh index a7ab6cd79..4ec41946d 100644 --- a/src/cpu/o3/sparc/dyn_inst.hh +++ b/src/cpu/o3/sparc/dyn_inst.hh @@ -35,7 +35,7 @@ #include "arch/sparc/types.hh" #include "cpu/base_dyn_inst.hh" #include "cpu/inst_seq.hh" -#include "cpu/o3/sparc/cpu.hh" +#include "cpu/o3/cpu.hh" #include "cpu/o3/sparc/impl.hh" class Packet; diff --git a/src/cpu/o3/sparc/impl.hh b/src/cpu/o3/sparc/impl.hh index 982fe36cc..bcf8e5cc6 100644 --- a/src/cpu/o3/sparc/impl.hh +++ b/src/cpu/o3/sparc/impl.hh @@ -41,7 +41,7 @@ template class SparcDynInst; template -class SparcO3CPU; +class FullO3CPU; /** Implementation specific struct that defines several key types to the * CPU, the stages within the CPU, the time buffers, and the DynInst. @@ -68,7 +68,7 @@ struct SparcSimpleImpl typedef RefCountingPtr DynInstPtr; /** The O3CPU type to be used. */ - typedef SparcO3CPU O3CPU; + typedef FullO3CPU O3CPU; /** Same typedef, but for CPUType. BaseDynInst may not always use * an O3 CPU, so it's clearer to call it CPUType instead in that diff --git a/src/cpu/o3/sparc/thread_context.hh b/src/cpu/o3/sparc/thread_context.hh deleted file mode 100644 index 7497959e4..000000000 --- a/src/cpu/o3/sparc/thread_context.hh +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2004-2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#include "arch/sparc/types.hh" -#include "cpu/o3/thread_context.hh" - -template -class SparcTC : public O3ThreadContext -{ - public: -#if FULL_SYSTEM - /** Returns pointer to the quiesce event. */ - virtual EndQuiesceEvent *getQuiesceEvent() - { - return this->thread->quiesceEvent; - } -#endif - - virtual uint64_t readNextNPC() - { - return this->cpu->readNextNPC(this->thread->readTid()); - } - - virtual void setNextNPC(uint64_t val) - { - this->cpu->setNextNPC(val, this->thread->readTid()); - } - - virtual void changeRegFileContext(TheISA::RegContextParam param, - TheISA::RegContextVal val) - { - //XXX Ignore this for now. This -really- needs to get fixed. - } - - - /** This function exits the thread context in the CPU and returns - * 1 if the CPU has no more active threads (meaning it's OK to exit); - * Used in syscall-emulation mode when a thread executes the 'exit' - * syscall. - */ - virtual int exit() - { - this->deallocate(); - - // If there are still threads executing in the system - if (this->cpu->numActiveThreads()) - return 0; // don't exit simulation - else - return 1; // exit simulation - } -}; diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index 66dc47f0b..d92f85317 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -260,7 +260,51 @@ class O3ThreadContext : public ThreadContext /** Reads the funcExeInst counter. */ virtual Counter readFuncExeInst() { return thread->funcExeInst; } +#else + /** Returns pointer to the quiesce event. */ + virtual EndQuiesceEvent *getQuiesceEvent() + { + return this->thread->quiesceEvent; + } +#endif + + virtual uint64_t readNextNPC() + { + return this->cpu->readNextNPC(this->thread->readTid()); + } + + virtual void setNextNPC(uint64_t val) + { +#if THE_ISA == ALPHA_ISA + panic("Not supported on Alpha!"); #endif + this->cpu->setNextNPC(val, this->thread->readTid()); + } + + virtual void changeRegFileContext(TheISA::RegContextParam param, + TheISA::RegContextVal val) + { +#if THE_ISA != SPARC_ISA + panic("changeRegFileContext not implemented."); +#endif + } + + + /** This function exits the thread context in the CPU and returns + * 1 if the CPU has no more active threads (meaning it's OK to exit); + * Used in syscall-emulation mode when a thread executes the 'exit' + * syscall. + */ + virtual int exit() + { + this->deallocate(); + + // If there are still threads executing in the system + if (this->cpu->numActiveThreads()) + return 0; // don't exit simulation + else + return 1; // exit simulation + } }; #endif -- cgit v1.2.3 From f57c286d2c3fceae84fde60f148f70305c846772 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 9 Oct 2008 00:09:26 -0700 Subject: O3: Generaize the O3 dynamic instruction class so it isn't split out by ISA. --HG-- rename : src/cpu/o3/dyn_inst.hh => src/cpu/o3/dyn_inst_decl.hh rename : src/cpu/o3/alpha/dyn_inst_impl.hh => src/cpu/o3/dyn_inst_impl.hh --- src/arch/mips/locked_mem.hh | 19 ++- src/cpu/o3/alpha/dyn_inst.cc | 4 +- src/cpu/o3/alpha/dyn_inst.hh | 277 ------------------------------------- src/cpu/o3/alpha/dyn_inst_impl.hh | 175 ----------------------- src/cpu/o3/alpha/impl.hh | 4 +- src/cpu/o3/dyn_inst.hh | 282 ++++++++++++++++++++++++++++++++++---- src/cpu/o3/dyn_inst_decl.hh | 56 ++++++++ src/cpu/o3/dyn_inst_impl.hh | 181 ++++++++++++++++++++++++ src/cpu/o3/isa_specific.hh | 4 +- src/cpu/o3/mips/dyn_inst.cc | 4 +- src/cpu/o3/mips/dyn_inst.hh | 281 ------------------------------------- src/cpu/o3/mips/dyn_inst_impl.hh | 130 ------------------ src/cpu/o3/mips/impl.hh | 5 +- src/cpu/o3/sparc/dyn_inst.cc | 4 +- src/cpu/o3/sparc/dyn_inst.hh | 265 ----------------------------------- src/cpu/o3/sparc/dyn_inst_impl.hh | 154 --------------------- src/cpu/o3/sparc/impl.hh | 4 +- src/cpu/static_inst.hh | 2 +- 18 files changed, 515 insertions(+), 1336 deletions(-) delete mode 100644 src/cpu/o3/alpha/dyn_inst.hh delete mode 100644 src/cpu/o3/alpha/dyn_inst_impl.hh create mode 100644 src/cpu/o3/dyn_inst_decl.hh create mode 100644 src/cpu/o3/dyn_inst_impl.hh delete mode 100755 src/cpu/o3/mips/dyn_inst.hh delete mode 100755 src/cpu/o3/mips/dyn_inst_impl.hh delete mode 100644 src/cpu/o3/sparc/dyn_inst.hh delete mode 100644 src/cpu/o3/sparc/dyn_inst_impl.hh (limited to 'src') diff --git a/src/arch/mips/locked_mem.hh b/src/arch/mips/locked_mem.hh index 34da79ed9..07dc9d588 100644 --- a/src/arch/mips/locked_mem.hh +++ b/src/arch/mips/locked_mem.hh @@ -49,11 +49,10 @@ template inline void handleLockedRead(XC *xc, Request *req) { - unsigned tid = req->getThreadNum(); - xc->setMiscRegNoEffect(LLAddr, req->getPaddr() & ~0xf, tid); - xc->setMiscRegNoEffect(LLFlag, true, tid); + xc->setMiscRegNoEffect(LLAddr, req->getPaddr() & ~0xf); + xc->setMiscRegNoEffect(LLFlag, true); DPRINTF(LLSC, "[tid:%i]: Load-Link Flag Set & Load-Link Address set to %x.\n", - tid, req->getPaddr() & ~0xf); + req->getThreadNum(), req->getPaddr() & ~0xf); } @@ -61,22 +60,20 @@ template inline bool handleLockedWrite(XC *xc, Request *req) { - unsigned tid = req->getThreadNum(); - if (req->isUncacheable()) { // Funky Turbolaser mailbox access...don't update // result register (see stq_c in decoder.isa) req->setExtraData(2); } else { // standard store conditional - bool lock_flag = xc->readMiscRegNoEffect(LLFlag, tid); - Addr lock_addr = xc->readMiscRegNoEffect(LLAddr, tid); + bool lock_flag = xc->readMiscRegNoEffect(LLFlag); + Addr lock_addr = xc->readMiscRegNoEffect(LLAddr); if (!lock_flag || (req->getPaddr() & ~0xf) != lock_addr) { // Lock flag not set or addr mismatch in CPU; // don't even bother sending to memory system req->setExtraData(0); - xc->setMiscRegNoEffect(LLFlag, false, tid); + xc->setMiscRegNoEffect(LLFlag, false); // the rest of this code is not architectural; // it's just a debugging aid to help detect @@ -97,10 +94,10 @@ handleLockedWrite(XC *xc, Request *req) if (!lock_flag){ DPRINTF(LLSC, "[tid:%i]: Lock Flag Set, Store Conditional Failed.\n", - tid); + req->getThreadNum()); } else if ((req->getPaddr() & ~0xf) != lock_addr) { DPRINTF(LLSC, "[tid:%i]: Load-Link Address Mismatch, Store Conditional Failed.\n", - tid); + req->getThreadNum()); } // store conditional failed already, so don't issue it to mem return false; diff --git a/src/cpu/o3/alpha/dyn_inst.cc b/src/cpu/o3/alpha/dyn_inst.cc index 97d2f3d08..28e70be8a 100644 --- a/src/cpu/o3/alpha/dyn_inst.cc +++ b/src/cpu/o3/alpha/dyn_inst.cc @@ -28,9 +28,9 @@ * Authors: Kevin Lim */ -#include "cpu/o3/alpha/dyn_inst_impl.hh" #include "cpu/o3/alpha/impl.hh" +#include "cpu/o3/dyn_inst_impl.hh" // Force instantiation of AlphaDynInst for all the implementations that // are needed. -template class AlphaDynInst; +template class BaseO3DynInst; diff --git a/src/cpu/o3/alpha/dyn_inst.hh b/src/cpu/o3/alpha/dyn_inst.hh deleted file mode 100644 index 06568bc94..000000000 --- a/src/cpu/o3/alpha/dyn_inst.hh +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright (c) 2004-2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - */ - -#ifndef __CPU_O3_ALPHA_DYN_INST_HH__ -#define __CPU_O3_ALPHA_DYN_INST_HH__ - -#include "arch/isa_traits.hh" -#include "cpu/base_dyn_inst.hh" -#include "cpu/inst_seq.hh" -#include "cpu/o3/alpha/impl.hh" -#include "cpu/o3/cpu.hh" - -class Packet; - -/** - * Mostly implementation & ISA specific AlphaDynInst. As with most - * other classes in the new CPU model, it is templated on the Impl to - * allow for passing in of all types, such as the CPU type and the ISA - * type. The AlphaDynInst serves as the primary interface to the CPU - * for instructions that are executing. - */ -template -class AlphaDynInst : public BaseDynInst -{ - public: - /** Typedef for the CPU. */ - typedef typename Impl::O3CPU O3CPU; - - /** Binary machine instruction type. */ - typedef TheISA::MachInst MachInst; - /** Extended machine instruction type. */ - typedef TheISA::ExtMachInst ExtMachInst; - /** Logical register index type. */ - typedef TheISA::RegIndex RegIndex; - /** Integer register index type. */ - typedef TheISA::IntReg IntReg; - typedef TheISA::FloatReg FloatReg; - typedef TheISA::FloatRegBits FloatRegBits; - /** Misc register index type. */ - typedef TheISA::MiscReg MiscReg; - - enum { - MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs - MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs - }; - - public: - /** BaseDynInst constructor given a binary instruction. */ - AlphaDynInst(StaticInstPtr staticInst, Addr PC, Addr NPC, Addr microPC, - Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC, - InstSeqNum seq_num, O3CPU *cpu); - - /** BaseDynInst constructor given a binary instruction. */ - AlphaDynInst(ExtMachInst inst, Addr PC, Addr NPC, Addr microPC, - Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC, - InstSeqNum seq_num, O3CPU *cpu); - - /** BaseDynInst constructor given a static inst pointer. */ - AlphaDynInst(StaticInstPtr &_staticInst); - - /** Executes the instruction.*/ - Fault execute(); - - /** Initiates the access. Only valid for memory operations. */ - Fault initiateAcc(); - - /** Completes the access. Only valid for memory operations. */ - Fault completeAcc(PacketPtr pkt); - - private: - /** Initializes variables. */ - void initVars(); - - public: - /** Reads a miscellaneous register. */ - MiscReg readMiscRegNoEffect(int misc_reg) - { - return this->cpu->readMiscRegNoEffect(misc_reg, this->threadNumber); - } - - /** Reads a misc. register, including any side-effects the read - * might have as defined by the architecture. - */ - MiscReg readMiscReg(int misc_reg) - { - return this->cpu->readMiscReg(misc_reg, this->threadNumber); - } - - /** Sets a misc. register. */ - void setMiscRegNoEffect(int misc_reg, const MiscReg &val) - { - this->instResult.integer = val; - return this->cpu->setMiscRegNoEffect(misc_reg, val, this->threadNumber); - } - - /** Sets a misc. register, including any side-effects the write - * might have as defined by the architecture. - */ - void setMiscReg(int misc_reg, const MiscReg &val) - { - return this->cpu->setMiscReg(misc_reg, val, - this->threadNumber); - } - - /** Reads a miscellaneous register. */ - TheISA::MiscReg readMiscRegOperandNoEffect(const StaticInst *si, int idx) - { - return this->cpu->readMiscRegNoEffect( - si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, - this->threadNumber); - } - - /** Reads a misc. register, including any side-effects the read - * might have as defined by the architecture. - */ - TheISA::MiscReg readMiscRegOperand(const StaticInst *si, int idx) - { - return this->cpu->readMiscReg( - si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, - this->threadNumber); - } - - /** Sets a misc. register. */ - void setMiscRegOperandNoEffect(const StaticInst * si, int idx, const MiscReg &val) - { - this->instResult.integer = val; - return this->cpu->setMiscRegNoEffect( - si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag, - val, this->threadNumber); - } - - /** Sets a misc. register, including any side-effects the write - * might have as defined by the architecture. - */ - void setMiscRegOperand(const StaticInst *si, int idx, - const MiscReg &val) - { - return this->cpu->setMiscReg( - si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag, - val, this->threadNumber); - } - -#if FULL_SYSTEM - /** Calls hardware return from error interrupt. */ - Fault hwrei(); - /** Traps to handle specified fault. */ - void trap(Fault fault); - bool simPalCheck(int palFunc); -#else - /** Calls a syscall. */ - void syscall(int64_t callnum); -#endif - - public: - - // The register accessor methods provide the index of the - // instruction's operand (e.g., 0 or 1), not the architectural - // register index, to simplify the implementation of register - // renaming. We find the architectural register index by indexing - // into the instruction's own operand index table. Note that a - // raw pointer to the StaticInst is provided instead of a - // ref-counted StaticInstPtr to redice overhead. This is fine as - // long as these methods don't copy the pointer into any long-term - // storage (which is pretty hard to imagine they would have reason - // to do). - - uint64_t readIntRegOperand(const StaticInst *si, int idx) - { - return this->cpu->readIntReg(this->_srcRegIdx[idx]); - } - - FloatReg readFloatRegOperand(const StaticInst *si, int idx, int width) - { - return this->cpu->readFloatReg(this->_srcRegIdx[idx], width); - } - - FloatReg readFloatRegOperand(const StaticInst *si, int idx) - { - return this->cpu->readFloatReg(this->_srcRegIdx[idx]); - } - - FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx, - int width) - { - return this->cpu->readFloatRegBits(this->_srcRegIdx[idx], width); - } - - FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx) - { - return this->cpu->readFloatRegBits(this->_srcRegIdx[idx]); - } - - /** @todo: Make results into arrays so they can handle multiple dest - * registers. - */ - void setIntRegOperand(const StaticInst *si, int idx, uint64_t val) - { - this->cpu->setIntReg(this->_destRegIdx[idx], val); - BaseDynInst::setIntRegOperand(si, idx, val); - } - - void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val, - int width) - { - this->cpu->setFloatReg(this->_destRegIdx[idx], val, width); - BaseDynInst::setFloatRegOperand(si, idx, val, width); - } - - void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val) - { - this->cpu->setFloatReg(this->_destRegIdx[idx], val); - BaseDynInst::setFloatRegOperand(si, idx, val); - } - - void setFloatRegOperandBits(const StaticInst *si, int idx, - FloatRegBits val, int width) - { - this->cpu->setFloatRegBits(this->_destRegIdx[idx], val, width); - BaseDynInst::setFloatRegOperandBits(si, idx, val); - } - - void setFloatRegOperandBits(const StaticInst *si, int idx, - FloatRegBits val) - { - this->cpu->setFloatRegBits(this->_destRegIdx[idx], val); - BaseDynInst::setFloatRegOperandBits(si, idx, val); - } - - public: - /** Calculates EA part of a memory instruction. Currently unused, - * though it may be useful in the future if we want to split - * memory operations into EA calculation and memory access parts. - */ - Fault calcEA() - { - return this->staticInst->eaCompInst()->execute(this, this->traceData); - } - - /** Does the memory access part of a memory instruction. Currently unused, - * though it may be useful in the future if we want to split - * memory operations into EA calculation and memory access parts. - */ - Fault memAccess() - { - return this->staticInst->memAccInst()->execute(this, this->traceData); - } -}; - -#endif // __CPU_O3_ALPHA_DYN_INST_HH__ - diff --git a/src/cpu/o3/alpha/dyn_inst_impl.hh b/src/cpu/o3/alpha/dyn_inst_impl.hh deleted file mode 100644 index 610a313cf..000000000 --- a/src/cpu/o3/alpha/dyn_inst_impl.hh +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2004-2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - */ - -#include "cpu/o3/alpha/dyn_inst.hh" - -template -AlphaDynInst::AlphaDynInst(StaticInstPtr staticInst, - Addr PC, Addr NPC, Addr microPC, - Addr Pred_PC, Addr Pred_NPC, - Addr Pred_MicroPC, - InstSeqNum seq_num, O3CPU *cpu) - : BaseDynInst(staticInst, PC, NPC, microPC, - Pred_PC, Pred_NPC, Pred_MicroPC, seq_num, cpu) -{ - initVars(); -} - -template -AlphaDynInst::AlphaDynInst(ExtMachInst inst, - Addr PC, Addr NPC, Addr microPC, - Addr Pred_PC, Addr Pred_NPC, - Addr Pred_MicroPC, - InstSeqNum seq_num, O3CPU *cpu) - : BaseDynInst(inst, PC, NPC, microPC, - Pred_PC, Pred_NPC, Pred_MicroPC, seq_num, cpu) -{ - initVars(); -} - -template -AlphaDynInst::AlphaDynInst(StaticInstPtr &_staticInst) - : BaseDynInst(_staticInst) -{ - initVars(); -} - -template -void -AlphaDynInst::initVars() -{ - // Make sure to have the renamed register entries set to the same - // as the normal register entries. It will allow the IQ to work - // without any modifications. - for (int i = 0; i < this->staticInst->numDestRegs(); i++) { - this->_destRegIdx[i] = this->staticInst->destRegIdx(i); - } - - for (int i = 0; i < this->staticInst->numSrcRegs(); i++) { - this->_srcRegIdx[i] = this->staticInst->srcRegIdx(i); - this->_readySrcRegIdx[i] = 0; - } -} - -template -Fault -AlphaDynInst::execute() -{ - // @todo: Pretty convoluted way to avoid squashing from happening - // when using the TC during an instruction's execution - // (specifically for instructions that have side-effects that use - // the TC). Fix this. - bool in_syscall = this->thread->inSyscall; - this->thread->inSyscall = true; - - this->fault = this->staticInst->execute(this, this->traceData); - - this->thread->inSyscall = in_syscall; - - return this->fault; -} - -template -Fault -AlphaDynInst::initiateAcc() -{ - // @todo: Pretty convoluted way to avoid squashing from happening - // when using the TC during an instruction's execution - // (specifically for instructions that have side-effects that use - // the TC). Fix this. - bool in_syscall = this->thread->inSyscall; - this->thread->inSyscall = true; - - this->fault = this->staticInst->initiateAcc(this, this->traceData); - - this->thread->inSyscall = in_syscall; - - return this->fault; -} - -template -Fault -AlphaDynInst::completeAcc(PacketPtr pkt) -{ - this->fault = this->staticInst->completeAcc(pkt, this, this->traceData); - - return this->fault; -} - -#if FULL_SYSTEM -template -Fault -AlphaDynInst::hwrei() -{ - // Can only do a hwrei when in pal mode. - if (!(this->readPC() & 0x3)) - return new AlphaISA::UnimplementedOpcodeFault; - - // Set the next PC based on the value of the EXC_ADDR IPR. - this->setNextPC(this->cpu->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR, - this->threadNumber)); - - // Tell CPU to clear any state it needs to if a hwrei is taken. - this->cpu->hwrei(this->threadNumber); - - // FIXME: XXX check for interrupts? XXX - return NoFault; -} - -template -void -AlphaDynInst::trap(Fault fault) -{ - this->cpu->trap(fault, this->threadNumber); -} - -template -bool -AlphaDynInst::simPalCheck(int palFunc) -{ - return this->cpu->simPalCheck(palFunc, this->threadNumber); -} -#else -template -void -AlphaDynInst::syscall(int64_t callnum) -{ - // HACK: check CPU's nextPC before and after syscall. If it - // changes, update this instruction's nextPC because the syscall - // must have changed the nextPC. - Addr cpu_next_pc = this->cpu->readNextPC(this->threadNumber); - this->cpu->syscall(callnum, this->threadNumber); - Addr new_next_pc = this->cpu->readNextPC(this->threadNumber); - if (cpu_next_pc != new_next_pc) { - this->setNextPC(new_next_pc); - } -} -#endif - diff --git a/src/cpu/o3/alpha/impl.hh b/src/cpu/o3/alpha/impl.hh index 12ee495d1..7d956cd6a 100644 --- a/src/cpu/o3/alpha/impl.hh +++ b/src/cpu/o3/alpha/impl.hh @@ -38,7 +38,7 @@ // Forward declarations. template -class AlphaDynInst; +class BaseO3DynInst; template class FullO3CPU; @@ -60,7 +60,7 @@ struct AlphaSimpleImpl typedef SimpleCPUPolicy CPUPol; /** The DynInst type to be used. */ - typedef AlphaDynInst DynInst; + typedef BaseO3DynInst DynInst; /** The refcounted DynInst pointer to be used. In most cases this is * what should be used, and not DynInst *. diff --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh index a1f9e0591..292547b6b 100644 --- a/src/cpu/o3/dyn_inst.hh +++ b/src/cpu/o3/dyn_inst.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 The Regents of The University of Michigan + * Copyright (c) 2004-2006 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,36 +25,266 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Authors: Korey Sewell + * Authors: Kevin Lim */ #ifndef __CPU_O3_DYN_INST_HH__ #define __CPU_O3_DYN_INST_HH__ -#include "arch/isa_specific.hh" - -#if THE_ISA == ALPHA_ISA - template class AlphaDynInst; - struct AlphaSimpleImpl; - typedef AlphaDynInst O3DynInst; -#elif THE_ISA == MIPS_ISA - template class MipsDynInst; - struct MipsSimpleImpl; - typedef MipsDynInst O3DynInst; -#elif THE_ISA == SPARC_ISA - template class SparcDynInst; - struct SparcSimpleImpl; - typedef SparcDynInst O3DynInst; -#elif THE_ISA == X86_ISA - template class X86DynInst; - struct X86SimpleImpl; - typedef X86DynInst O3DynInst; -#elif THE_ISA == ARM_ISA - template class ArmDynInst; - struct ArmSimpleImpl; - typedef ArmDynInst O3DynInst; +#include "arch/isa_traits.hh" +#include "cpu/base_dyn_inst.hh" +#include "cpu/inst_seq.hh" +#include "cpu/o3/cpu.hh" +#include "cpu/o3/isa_specific.hh" + +class Packet; + +/** + * Mostly implementation & ISA specific AlphaDynInst. As with most + * other classes in the new CPU model, it is templated on the Impl to + * allow for passing in of all types, such as the CPU type and the ISA + * type. The AlphaDynInst serves as the primary interface to the CPU + * for instructions that are executing. + */ +template +class BaseO3DynInst : public BaseDynInst +{ + public: + /** Typedef for the CPU. */ + typedef typename Impl::O3CPU O3CPU; + + /** Binary machine instruction type. */ + typedef TheISA::MachInst MachInst; + /** Extended machine instruction type. */ + typedef TheISA::ExtMachInst ExtMachInst; + /** Logical register index type. */ + typedef TheISA::RegIndex RegIndex; + /** Integer register index type. */ + typedef TheISA::IntReg IntReg; + typedef TheISA::FloatReg FloatReg; + typedef TheISA::FloatRegBits FloatRegBits; + /** Misc register index type. */ + typedef TheISA::MiscReg MiscReg; + + enum { + MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs + MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs + }; + + public: + /** BaseDynInst constructor given a binary instruction. */ + BaseO3DynInst(StaticInstPtr staticInst, Addr PC, Addr NPC, Addr microPC, + Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC, + InstSeqNum seq_num, O3CPU *cpu); + + /** BaseDynInst constructor given a binary instruction. */ + BaseO3DynInst(ExtMachInst inst, Addr PC, Addr NPC, Addr microPC, + Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC, + InstSeqNum seq_num, O3CPU *cpu); + + /** BaseDynInst constructor given a static inst pointer. */ + BaseO3DynInst(StaticInstPtr &_staticInst); + + /** Executes the instruction.*/ + Fault execute(); + + /** Initiates the access. Only valid for memory operations. */ + Fault initiateAcc(); + + /** Completes the access. Only valid for memory operations. */ + Fault completeAcc(PacketPtr pkt); + + private: + /** Initializes variables. */ + void initVars(); + + public: + /** Reads a miscellaneous register. */ + MiscReg readMiscRegNoEffect(int misc_reg) + { + return this->cpu->readMiscRegNoEffect(misc_reg, this->threadNumber); + } + + /** Reads a misc. register, including any side-effects the read + * might have as defined by the architecture. + */ + MiscReg readMiscReg(int misc_reg) + { + return this->cpu->readMiscReg(misc_reg, this->threadNumber); + } + + /** Sets a misc. register. */ + void setMiscRegNoEffect(int misc_reg, const MiscReg &val) + { + this->instResult.integer = val; + return this->cpu->setMiscRegNoEffect(misc_reg, val, this->threadNumber); + } + + /** Sets a misc. register, including any side-effects the write + * might have as defined by the architecture. + */ + void setMiscReg(int misc_reg, const MiscReg &val) + { + return this->cpu->setMiscReg(misc_reg, val, + this->threadNumber); + } + + /** Reads a miscellaneous register. */ + TheISA::MiscReg readMiscRegOperandNoEffect(const StaticInst *si, int idx) + { + return this->cpu->readMiscRegNoEffect( + si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, + this->threadNumber); + } + + /** Reads a misc. register, including any side-effects the read + * might have as defined by the architecture. + */ + TheISA::MiscReg readMiscRegOperand(const StaticInst *si, int idx) + { + return this->cpu->readMiscReg( + si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, + this->threadNumber); + } + + /** Sets a misc. register. */ + void setMiscRegOperandNoEffect(const StaticInst * si, int idx, const MiscReg &val) + { + this->instResult.integer = val; + return this->cpu->setMiscRegNoEffect( + si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag, + val, this->threadNumber); + } + + /** Sets a misc. register, including any side-effects the write + * might have as defined by the architecture. + */ + void setMiscRegOperand(const StaticInst *si, int idx, + const MiscReg &val) + { + return this->cpu->setMiscReg( + si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag, + val, this->threadNumber); + } + +#if FULL_SYSTEM + /** Calls hardware return from error interrupt. */ + Fault hwrei(); + /** Traps to handle specified fault. */ + void trap(Fault fault); + bool simPalCheck(int palFunc); #else - #error "O3DynInst not defined for this ISA" + /** Calls a syscall. */ + void syscall(int64_t callnum); #endif -#endif // __CPU_O3_DYN_INST_HH__ + public: + + // The register accessor methods provide the index of the + // instruction's operand (e.g., 0 or 1), not the architectural + // register index, to simplify the implementation of register + // renaming. We find the architectural register index by indexing + // into the instruction's own operand index table. Note that a + // raw pointer to the StaticInst is provided instead of a + // ref-counted StaticInstPtr to redice overhead. This is fine as + // long as these methods don't copy the pointer into any long-term + // storage (which is pretty hard to imagine they would have reason + // to do). + + uint64_t readIntRegOperand(const StaticInst *si, int idx) + { + return this->cpu->readIntReg(this->_srcRegIdx[idx]); + } + + FloatReg readFloatRegOperand(const StaticInst *si, int idx, int width) + { + return this->cpu->readFloatReg(this->_srcRegIdx[idx], width); + } + + FloatReg readFloatRegOperand(const StaticInst *si, int idx) + { + return this->cpu->readFloatReg(this->_srcRegIdx[idx]); + } + + FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx, + int width) + { + return this->cpu->readFloatRegBits(this->_srcRegIdx[idx], width); + } + + FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx) + { + return this->cpu->readFloatRegBits(this->_srcRegIdx[idx]); + } + + /** @todo: Make results into arrays so they can handle multiple dest + * registers. + */ + void setIntRegOperand(const StaticInst *si, int idx, uint64_t val) + { + this->cpu->setIntReg(this->_destRegIdx[idx], val); + BaseDynInst::setIntRegOperand(si, idx, val); + } + + void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val, + int width) + { + this->cpu->setFloatReg(this->_destRegIdx[idx], val, width); + BaseDynInst::setFloatRegOperand(si, idx, val, width); + } + + void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val) + { + this->cpu->setFloatReg(this->_destRegIdx[idx], val); + BaseDynInst::setFloatRegOperand(si, idx, val); + } + + void setFloatRegOperandBits(const StaticInst *si, int idx, + FloatRegBits val, int width) + { + this->cpu->setFloatRegBits(this->_destRegIdx[idx], val, width); + BaseDynInst::setFloatRegOperandBits(si, idx, val); + } + + void setFloatRegOperandBits(const StaticInst *si, int idx, + FloatRegBits val) + { + this->cpu->setFloatRegBits(this->_destRegIdx[idx], val); + BaseDynInst::setFloatRegOperandBits(si, idx, val); + } + +#if THE_ISA == MIPS_ISA + uint64_t readRegOtherThread(int misc_reg) + { + panic("MIPS MT not defined for O3 CPU.\n"); + return 0; + } + + void setRegOtherThread(int misc_reg, const TheISA::MiscReg &val) + { + panic("MIPS MT not defined for O3 CPU.\n"); + } +#endif + + public: + /** Calculates EA part of a memory instruction. Currently unused, + * though it may be useful in the future if we want to split + * memory operations into EA calculation and memory access parts. + */ + Fault calcEA() + { + return this->staticInst->eaCompInst()->execute(this, this->traceData); + } + + /** Does the memory access part of a memory instruction. Currently unused, + * though it may be useful in the future if we want to split + * memory operations into EA calculation and memory access parts. + */ + Fault memAccess() + { + return this->staticInst->memAccInst()->execute(this, this->traceData); + } +}; + +#endif // __CPU_O3_ALPHA_DYN_INST_HH__ + diff --git a/src/cpu/o3/dyn_inst_decl.hh b/src/cpu/o3/dyn_inst_decl.hh new file mode 100644 index 000000000..750c3279d --- /dev/null +++ b/src/cpu/o3/dyn_inst_decl.hh @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + */ + +#ifndef __CPU_O3_DYN_INST_DECL_HH__ +#define __CPU_O3_DYN_INST_DECL_HH__ + +#include "arch/isa_specific.hh" + +template class BaseO3DynInst; +#if THE_ISA == ALPHA_ISA + struct AlphaSimpleImpl; + typedef BaseO3DynInst O3DynInst; +#elif THE_ISA == MIPS_ISA + struct MipsSimpleImpl; + typedef BaseO3DynInst O3DynInst; +#elif THE_ISA == SPARC_ISA + struct SparcSimpleImpl; + typedef BaseO3DynInst O3DynInst; +#elif THE_ISA == X86_ISA + struct X86SimpleImpl; + typedef BaseO3DynInst O3DynInst; +#elif THE_ISA == ARM_ISA + struct ArmSimpleImpl; + typedef BaseO3DynInst O3DynInst; +#else + #error "O3DynInst not defined for this ISA" +#endif + +#endif // __CPU_O3_DYN_INST_DECL_HH__ diff --git a/src/cpu/o3/dyn_inst_impl.hh b/src/cpu/o3/dyn_inst_impl.hh new file mode 100644 index 000000000..6398a3afe --- /dev/null +++ b/src/cpu/o3/dyn_inst_impl.hh @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2004-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + */ + +#include "cpu/o3/dyn_inst.hh" + +template +BaseO3DynInst::BaseO3DynInst(StaticInstPtr staticInst, + Addr PC, Addr NPC, Addr microPC, + Addr Pred_PC, Addr Pred_NPC, + Addr Pred_MicroPC, + InstSeqNum seq_num, O3CPU *cpu) + : BaseDynInst(staticInst, PC, NPC, microPC, + Pred_PC, Pred_NPC, Pred_MicroPC, seq_num, cpu) +{ + initVars(); +} + +template +BaseO3DynInst::BaseO3DynInst(ExtMachInst inst, + Addr PC, Addr NPC, Addr microPC, + Addr Pred_PC, Addr Pred_NPC, + Addr Pred_MicroPC, + InstSeqNum seq_num, O3CPU *cpu) + : BaseDynInst(inst, PC, NPC, microPC, + Pred_PC, Pred_NPC, Pred_MicroPC, seq_num, cpu) +{ + initVars(); +} + +template +BaseO3DynInst::BaseO3DynInst(StaticInstPtr &_staticInst) + : BaseDynInst(_staticInst) +{ + initVars(); +} + +template +void +BaseO3DynInst::initVars() +{ + // Make sure to have the renamed register entries set to the same + // as the normal register entries. It will allow the IQ to work + // without any modifications. + for (int i = 0; i < this->staticInst->numDestRegs(); i++) { + this->_destRegIdx[i] = this->staticInst->destRegIdx(i); + } + + for (int i = 0; i < this->staticInst->numSrcRegs(); i++) { + this->_srcRegIdx[i] = this->staticInst->srcRegIdx(i); + this->_readySrcRegIdx[i] = 0; + } +} + +template +Fault +BaseO3DynInst::execute() +{ + // @todo: Pretty convoluted way to avoid squashing from happening + // when using the TC during an instruction's execution + // (specifically for instructions that have side-effects that use + // the TC). Fix this. + bool in_syscall = this->thread->inSyscall; + this->thread->inSyscall = true; + + this->fault = this->staticInst->execute(this, this->traceData); + + this->thread->inSyscall = in_syscall; + + return this->fault; +} + +template +Fault +BaseO3DynInst::initiateAcc() +{ + // @todo: Pretty convoluted way to avoid squashing from happening + // when using the TC during an instruction's execution + // (specifically for instructions that have side-effects that use + // the TC). Fix this. + bool in_syscall = this->thread->inSyscall; + this->thread->inSyscall = true; + + this->fault = this->staticInst->initiateAcc(this, this->traceData); + + this->thread->inSyscall = in_syscall; + + return this->fault; +} + +template +Fault +BaseO3DynInst::completeAcc(PacketPtr pkt) +{ + this->fault = this->staticInst->completeAcc(pkt, this, this->traceData); + + return this->fault; +} + +#if FULL_SYSTEM +template +Fault +BaseO3DynInst::hwrei() +{ +#if THE_ISA == ALPHA_ISA + // Can only do a hwrei when in pal mode. + if (!(this->readPC() & 0x3)) + return new AlphaISA::UnimplementedOpcodeFault; + + // Set the next PC based on the value of the EXC_ADDR IPR. + this->setNextPC(this->cpu->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR, + this->threadNumber)); + + // Tell CPU to clear any state it needs to if a hwrei is taken. + this->cpu->hwrei(this->threadNumber); +#else + +#endif + // FIXME: XXX check for interrupts? XXX + return NoFault; +} + +template +void +BaseO3DynInst::trap(Fault fault) +{ + this->cpu->trap(fault, this->threadNumber); +} + +template +bool +BaseO3DynInst::simPalCheck(int palFunc) +{ +#if THE_ISA != ALPHA_ISA + panic("simPalCheck called, but PAL only exists in Alpha!\n"); +#endif + return this->cpu->simPalCheck(palFunc, this->threadNumber); +} +#else +template +void +BaseO3DynInst::syscall(int64_t callnum) +{ + // HACK: check CPU's nextPC before and after syscall. If it + // changes, update this instruction's nextPC because the syscall + // must have changed the nextPC. + Addr cpu_next_pc = this->cpu->readNextPC(this->threadNumber); + this->cpu->syscall(callnum, this->threadNumber); + Addr new_next_pc = this->cpu->readNextPC(this->threadNumber); + if (cpu_next_pc != new_next_pc) { + this->setNextPC(new_next_pc); + } +} +#endif + diff --git a/src/cpu/o3/isa_specific.hh b/src/cpu/o3/isa_specific.hh index 5e759b41d..6111a5336 100755 --- a/src/cpu/o3/isa_specific.hh +++ b/src/cpu/o3/isa_specific.hh @@ -32,13 +32,11 @@ #if THE_ISA == ALPHA_ISA #include "cpu/o3/alpha/impl.hh" - #include "cpu/o3/alpha/dyn_inst.hh" #elif THE_ISA == MIPS_ISA #include "cpu/o3/mips/impl.hh" - #include "cpu/o3/mips/dyn_inst.hh" #elif THE_ISA == SPARC_ISA #include "cpu/o3/sparc/impl.hh" - #include "cpu/o3/sparc/dyn_inst.hh" #else #error "ISA-specific header files O3CPU not defined ISA" #endif +#include "cpu/o3/dyn_inst.hh" diff --git a/src/cpu/o3/mips/dyn_inst.cc b/src/cpu/o3/mips/dyn_inst.cc index 216aa7d2c..88205afaf 100755 --- a/src/cpu/o3/mips/dyn_inst.cc +++ b/src/cpu/o3/mips/dyn_inst.cc @@ -29,9 +29,9 @@ * Korey Sewell */ -#include "cpu/o3/mips/dyn_inst_impl.hh" +#include "cpu/o3/dyn_inst_impl.hh" #include "cpu/o3/mips/impl.hh" // Force instantiation of MipsDynInst for all the implementations that // are needed. -template class MipsDynInst; +template class BaseO3DynInst; diff --git a/src/cpu/o3/mips/dyn_inst.hh b/src/cpu/o3/mips/dyn_inst.hh deleted file mode 100755 index 320d6703f..000000000 --- a/src/cpu/o3/mips/dyn_inst.hh +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (c) 2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - * Korey Sewell - */ - -#ifndef __CPU_O3_MIPS_DYN_INST_HH__ -#define __CPU_O3_MIPS_DYN_INST_HH__ - -#include "arch/isa_traits.hh" -#include "cpu/base_dyn_inst.hh" -#include "cpu/inst_seq.hh" -#include "cpu/o3/cpu.hh" -#include "cpu/o3/mips/impl.hh" - -class Packet; - -/** - * Mostly implementation & ISA specific MipsDynInst. As with most - * other classes in the new CPU model, it is templated on the Impl to - * allow for passing in of all types, such as the CPU type and the ISA - * type. The MipsDynInst serves as the primary interface to the CPU - * for instructions that are executing. - */ -template -class MipsDynInst : public BaseDynInst -{ - public: - /** Typedef for the CPU. */ - typedef typename Impl::O3CPU O3CPU; - - /** Logical register index type. */ - typedef TheISA::RegIndex RegIndex; - /** Integer register index type. */ - typedef TheISA::IntReg IntReg; - typedef TheISA::FloatReg FloatReg; - typedef TheISA::FloatRegBits FloatRegBits; - /** Misc register index type. */ - typedef TheISA::MiscReg MiscReg; - - enum { - MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs - MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs - }; - - public: - /** BaseDynInst constructor given a binary instruction. */ - MipsDynInst(StaticInstPtr staticInst, - Addr PC, Addr NPC, Addr microPC, - Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC, - InstSeqNum seq_num, O3CPU *cpu); - - /** BaseDynInst constructor given a binary instruction. */ - MipsDynInst(ExtMachInst inst, - Addr PC, Addr NPC, Addr microPC, - Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC, - InstSeqNum seq_num, O3CPU *cpu); - - /** BaseDynInst constructor given a static inst pointer. */ - MipsDynInst(StaticInstPtr &_staticInst); - - /** Executes the instruction.*/ - Fault execute(); - - /** Initiates the access. Only valid for memory operations. */ - Fault initiateAcc(); - - /** Completes the access. Only valid for memory operations. */ - Fault completeAcc(PacketPtr pkt); - - private: - /** Initializes variables. */ - void initVars(); - - public: - /** Reads a miscellaneous register. */ - /** TODO: Use thread number from argument if given, will probably not work for MIPS MT as is */ - MiscReg readMiscRegNoEffect(int misc_reg, unsigned tid = 0) - { - return this->cpu->readMiscRegNoEffect(misc_reg, this->threadNumber); - } - - /** Reads a misc. register, including any side-effects the read - * might have as defined by the architecture. - */ - MiscReg readMiscReg(int misc_reg, unsigned tid = 0) - { - return this->cpu->readMiscReg(misc_reg, this->threadNumber); - } - - /** Sets a misc. register. */ - void setMiscRegNoEffect(int misc_reg, const MiscReg &val, unsigned tid = 0) - { - this->instResult.integer = val; - this->cpu->setMiscRegNoEffect(misc_reg, val, this->threadNumber); - } - - /** Sets a misc. register, including any side-effects the write - * might have as defined by the architecture. - */ - void setMiscReg(int misc_reg, const MiscReg &val, unsigned tid = 0) - { - return this->cpu->setMiscReg(misc_reg, val, - this->threadNumber); - } - - - /** Calls a syscall. */ - void syscall(int64_t callnum); - - public: - - // The register accessor methods provide the index of the - // instruction's operand (e.g., 0 or 1), not the architectural - // register index, to simplify the implementation of register - // renaming. We find the architectural register index by indexing - // into the instruction's own operand index table. Note that a - // raw pointer to the StaticInst is provided instead of a - // ref-counted StaticInstPtr to redice overhead. This is fine as - // long as these methods don't copy the pointer into any long-term - // storage (which is pretty hard to imagine they would have reason - // to do). - - uint64_t readIntRegOperand(const StaticInst *si, int idx) - { - return this->cpu->readIntReg(this->_srcRegIdx[idx]); - } - - FloatReg readFloatRegOperand(const StaticInst *si, int idx, int width) - { - return this->cpu->readFloatReg(this->_srcRegIdx[idx], width); - } - - FloatReg readFloatRegOperand(const StaticInst *si, int idx) - { - return this->cpu->readFloatReg(this->_srcRegIdx[idx]); - } - - FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx, - int width) - { - return this->cpu->readFloatRegBits(this->_srcRegIdx[idx], width); - } - - FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx) - { - return this->cpu->readFloatRegBits(this->_srcRegIdx[idx]); - } - - /** @todo: Make results into arrays so they can handle multiple dest - * registers. - */ - void setIntRegOperand(const StaticInst *si, int idx, uint64_t val) - { - this->cpu->setIntReg(this->_destRegIdx[idx], val); - BaseDynInst::setIntRegOperand(si, idx, val); - } - - void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val, - int width) - { - this->cpu->setFloatReg(this->_destRegIdx[idx], val, width); - BaseDynInst::setFloatRegOperand(si, idx, val, width); - } - - void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val) - { - this->cpu->setFloatReg(this->_destRegIdx[idx], val); - BaseDynInst::setFloatRegOperand(si, idx, val); - } - - void setFloatRegOperandBits(const StaticInst *si, int idx, - FloatRegBits val, int width) - { - this->cpu->setFloatRegBits(this->_destRegIdx[idx], val, width); - BaseDynInst::setFloatRegOperandBits(si, idx, val); - } - - void setFloatRegOperandBits(const StaticInst *si, int idx, - FloatRegBits val) - { - this->cpu->setFloatRegBits(this->_destRegIdx[idx], val); - BaseDynInst::setFloatRegOperandBits(si, idx, val); - } - - /** Reads a miscellaneous register. */ - TheISA::MiscReg readMiscRegOperandNoEffect(const StaticInst *si, int idx) - { - return this->cpu->readMiscRegNoEffect( - si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, - this->threadNumber); - } - - /** Reads a misc. register, including any side-effects the read - * might have as defined by the architecture. - */ - TheISA::MiscReg readMiscRegOperand(const StaticInst *si, int idx) - { - return this->cpu->readMiscReg( - si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, - this->threadNumber); - } - - /** Sets a misc. register. */ - void setMiscRegOperandNoEffect(const StaticInst * si, int idx, const MiscReg &val) - { - this->instResult.integer = val; - return this->cpu->setMiscRegNoEffect( - si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag, - val, this->threadNumber); - } - - /** Sets a misc. register, including any side-effects the write - * might have as defined by the architecture. - */ - void setMiscRegOperand(const StaticInst *si, int idx, - const MiscReg &val) - { - return this->cpu->setMiscReg( - si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag, - val, this->threadNumber); - } - - uint64_t readRegOtherThread(int misc_reg) - { - panic("MIPS MT not defined for O3 CPU.\n"); - return 0; - } - - void setRegOtherThread(int misc_reg, const TheISA::MiscReg &val) - { - panic("MIPS MT not defined for O3 CPU.\n"); - } - - public: - /** Calculates EA part of a memory instruction. Currently unused, - * though it may be useful in the future if we want to split - * memory operations into EA calculation and memory access parts. - */ - Fault calcEA() - { - return this->staticInst->eaCompInst()->execute(this, this->traceData); - } - - /** Does the memory access part of a memory instruction. Currently unused, - * though it may be useful in the future if we want to split - * memory operations into EA calculation and memory access parts. - */ - Fault memAccess() - { - return this->staticInst->memAccInst()->execute(this, this->traceData); - } -}; - -#endif // __CPU_O3_MIPS_DYN_INST_HH__ - diff --git a/src/cpu/o3/mips/dyn_inst_impl.hh b/src/cpu/o3/mips/dyn_inst_impl.hh deleted file mode 100755 index 7e8697b32..000000000 --- a/src/cpu/o3/mips/dyn_inst_impl.hh +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2004-2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - */ - -#include "cpu/o3/mips/dyn_inst.hh" - -template -MipsDynInst::MipsDynInst(StaticInstPtr staticInst, - Addr PC, Addr NPC, Addr microPC, - Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC, - InstSeqNum seq_num, O3CPU *cpu) - : BaseDynInst(staticInst, PC, NPC, microPC, - Pred_PC, Pred_NPC, Pred_MicroPC, seq_num, cpu) -{ - initVars(); -} - -template -MipsDynInst::MipsDynInst(ExtMachInst inst, - Addr PC, Addr NPC, Addr microPC, - Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC, - InstSeqNum seq_num, O3CPU *cpu) - : BaseDynInst(inst, PC, NPC, microPC, - Pred_PC, Pred_NPC, Pred_MicroPC, seq_num, cpu) -{ - initVars(); -} - -template -MipsDynInst::MipsDynInst(StaticInstPtr &_staticInst) - : BaseDynInst(_staticInst) -{ - initVars(); -} - -template -void -MipsDynInst::initVars() -{ - // Make sure to have the renamed register entries set to the same - // as the normal register entries. It will allow the IQ to work - // without any modifications. - for (int i = 0; i < this->staticInst->numDestRegs(); i++) { - this->_destRegIdx[i] = this->staticInst->destRegIdx(i); - } - - for (int i = 0; i < this->staticInst->numSrcRegs(); i++) { - this->_srcRegIdx[i] = this->staticInst->srcRegIdx(i); - this->_readySrcRegIdx[i] = 0; - } -} - -template -Fault -MipsDynInst::execute() -{ - // @todo: Pretty convoluted way to avoid squashing from happening - // when using the TC during an instruction's execution - // (specifically for instructions that have side-effects that use - // the TC). Fix this. - bool in_syscall = this->thread->inSyscall; - this->thread->inSyscall = true; - - this->fault = this->staticInst->execute(this, this->traceData); - - this->thread->inSyscall = in_syscall; - - return this->fault; -} - -template -Fault -MipsDynInst::initiateAcc() -{ - // @todo: Pretty convoluted way to avoid squashing from happening - // when using the TC during an instruction's execution - // (specifically for instructions that have side-effects that use - // the TC). Fix this. - bool in_syscall = this->thread->inSyscall; - this->thread->inSyscall = true; - - this->fault = this->staticInst->initiateAcc(this, this->traceData); - - this->thread->inSyscall = in_syscall; - - return this->fault; -} - -template -Fault -MipsDynInst::completeAcc(PacketPtr pkt) -{ - this->fault = this->staticInst->completeAcc(pkt, this, this->traceData); - - return this->fault; -} - -template -void -MipsDynInst::syscall(int64_t callnum) -{ - this->cpu->syscall(callnum, this->threadNumber); -} - diff --git a/src/cpu/o3/mips/impl.hh b/src/cpu/o3/mips/impl.hh index dbaa4a276..78afd1387 100644 --- a/src/cpu/o3/mips/impl.hh +++ b/src/cpu/o3/mips/impl.hh @@ -36,10 +36,9 @@ #include "cpu/o3/cpu_policy.hh" - // Forward declarations. template -class MipsDynInst; +class BaseO3DynInst; template class FullO3CPU; @@ -61,7 +60,7 @@ struct MipsSimpleImpl typedef SimpleCPUPolicy CPUPol; /** The DynInst type to be used. */ - typedef MipsDynInst DynInst; + typedef BaseO3DynInst DynInst; /** The refcounted DynInst pointer to be used. In most cases this is * what should be used, and not DynInst *. diff --git a/src/cpu/o3/sparc/dyn_inst.cc b/src/cpu/o3/sparc/dyn_inst.cc index 984b58f4b..ea86f8719 100644 --- a/src/cpu/o3/sparc/dyn_inst.cc +++ b/src/cpu/o3/sparc/dyn_inst.cc @@ -28,9 +28,9 @@ * Authors: Gabe Black */ -#include "cpu/o3/sparc/dyn_inst_impl.hh" +#include "cpu/o3/dyn_inst_impl.hh" #include "cpu/o3/sparc/impl.hh" // Force instantiation of SparcDynInst for all the implementations that // are needed. -template class SparcDynInst; +template class BaseO3DynInst; diff --git a/src/cpu/o3/sparc/dyn_inst.hh b/src/cpu/o3/sparc/dyn_inst.hh deleted file mode 100644 index 4ec41946d..000000000 --- a/src/cpu/o3/sparc/dyn_inst.hh +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (c) 2004-2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#ifndef __CPU_O3_SPARC_DYN_INST_HH__ -#define __CPU_O3_SPARC_DYN_INST_HH__ - -#include "arch/sparc/isa_traits.hh" -#include "arch/sparc/types.hh" -#include "cpu/base_dyn_inst.hh" -#include "cpu/inst_seq.hh" -#include "cpu/o3/cpu.hh" -#include "cpu/o3/sparc/impl.hh" - -class Packet; - -/** - * Mostly implementation & ISA specific SparcDynInst. As with most - * other classes in the new CPU model, it is templated on the Impl to - * allow for passing in of all types, such as the CPU type and the ISA - * type. The SparcDynInst serves as the primary interface to the CPU - * for instructions that are executing. - */ -template -class SparcDynInst : public BaseDynInst -{ - public: - /** Typedef for the CPU. */ - typedef typename Impl::O3CPU O3CPU; - - public: - /** BaseDynInst constructor given a binary instruction. */ - SparcDynInst(StaticInstPtr staticInst, Addr PC, Addr NPC, Addr microPC, - Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC, - InstSeqNum seq_num, O3CPU *cpu); - - /** BaseDynInst constructor given a binary instruction. */ - SparcDynInst(TheISA::ExtMachInst inst, Addr PC, Addr NPC, Addr microPC, - Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC, - InstSeqNum seq_num, O3CPU *cpu); - - /** BaseDynInst constructor given a static inst pointer. */ - SparcDynInst(StaticInstPtr &_staticInst); - - /** Executes the instruction.*/ - Fault execute(); - - /** Initiates the access. Only valid for memory operations. */ - Fault initiateAcc(); - - /** Completes the access. Only valid for memory operations. */ - Fault completeAcc(PacketPtr pkt); - - private: - /** Initializes variables. */ - void initVars(); - - public: - /** Reads a miscellaneous register. */ - TheISA::MiscReg readMiscRegNoEffect(int misc_reg) - { - return this->cpu->readMiscRegNoEffect(misc_reg, this->threadNumber); - } - - /** Reads a misc. register, including any side-effects the read - * might have as defined by the architecture. - */ - TheISA::MiscReg readMiscReg(int misc_reg) - { - return this->cpu->readMiscReg(misc_reg, this->threadNumber); - } - - /** Sets a misc. register. */ - void setMiscRegNoEffect(int misc_reg, const TheISA::MiscReg &val) - { - this->instResult.integer = val; - return this->cpu->setMiscRegNoEffect(misc_reg, val, this->threadNumber); - } - - /** Sets a misc. register, including any side-effects the write - * might have as defined by the architecture. - */ - void setMiscReg(int misc_reg, const TheISA::MiscReg &val) - { - return this->cpu->setMiscReg(misc_reg, val, - this->threadNumber); - } - - /** Reads a miscellaneous register. */ - TheISA::MiscReg readMiscRegOperandNoEffect(const StaticInst *si, int idx) - { - return this->cpu->readMiscRegNoEffect( - si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, - this->threadNumber); - } - - /** Reads a misc. register, including any side-effects the read - * might have as defined by the architecture. - */ - TheISA::MiscReg readMiscRegOperand(const StaticInst *si, int idx) - { - return this->cpu->readMiscReg( - si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, - this->threadNumber); - } - - /** Sets a misc. register. */ - void setMiscRegOperandNoEffect(const StaticInst * si, - int idx, const TheISA::MiscReg &val) - { - this->instResult.integer = val; - return this->cpu->setMiscRegNoEffect( - si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag, - val, this->threadNumber); - } - - /** Sets a misc. register, including any side-effects the write - * might have as defined by the architecture. - */ - void setMiscRegOperand( - const StaticInst *si, int idx, const TheISA::MiscReg &val) - { - return this->cpu->setMiscReg( - si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag, - val, this->threadNumber); - } - -#if FULL_SYSTEM - /** Calls hardware return from error interrupt. */ - Fault hwrei(); - /** Traps to handle specified fault. */ - void trap(Fault fault); - bool simPalCheck(int palFunc); -#else - /** Calls a syscall. */ - void syscall(int64_t callnum); -#endif - - public: - - // The register accessor methods provide the index of the - // instruction's operand (e.g., 0 or 1), not the architectural - // register index, to simplify the implementation of register - // renaming. We find the architectural register index by indexing - // into the instruction's own operand index table. Note that a - // raw pointer to the StaticInst is provided instead of a - // ref-counted StaticInstPtr to redice overhead. This is fine as - // long as these methods don't copy the pointer into any long-term - // storage (which is pretty hard to imagine they would have reason - // to do). - - uint64_t readIntRegOperand(const StaticInst *si, int idx) - { - uint64_t val = this->cpu->readIntReg(this->_srcRegIdx[idx]); - DPRINTF(Sparc, "Reading int reg %d (%d, %d) as %x\n", (int)this->_flatSrcRegIdx[idx], (int)this->_srcRegIdx[idx], idx, val); - return val; - } - - TheISA::FloatReg readFloatRegOperand(const StaticInst *si, - int idx, int width) - { - return this->cpu->readFloatReg(this->_srcRegIdx[idx], width); - } - - TheISA::FloatReg readFloatRegOperand(const StaticInst *si, int idx) - { - return this->cpu->readFloatReg(this->_srcRegIdx[idx]); - } - - TheISA::FloatRegBits readFloatRegOperandBits(const StaticInst *si, - int idx, int width) - { - return this->cpu->readFloatRegBits(this->_srcRegIdx[idx], width); - } - - TheISA::FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx) - { - return this->cpu->readFloatRegBits(this->_srcRegIdx[idx]); - } - - /** @todo: Make results into arrays so they can handle multiple dest - * registers. - */ - void setIntRegOperand(const StaticInst *si, int idx, uint64_t val) - { - DPRINTF(Sparc, "Setting int reg %d (%d, %d) to %x\n", (int)this->_flatDestRegIdx[idx], (int)this->_destRegIdx[idx], idx, val); - this->cpu->setIntReg(this->_destRegIdx[idx], val); - BaseDynInst::setIntRegOperand(si, idx, val); - } - - void setFloatRegOperand(const StaticInst *si, int idx, - TheISA::FloatReg val, int width) - { - this->cpu->setFloatReg(this->_destRegIdx[idx], val, width); - BaseDynInst::setFloatRegOperand(si, idx, val, width); - } - - void setFloatRegOperand(const StaticInst *si, int idx, TheISA::FloatReg val) - { - this->cpu->setFloatReg(this->_destRegIdx[idx], val); - BaseDynInst::setFloatRegOperand(si, idx, val); - } - - void setFloatRegOperandBits(const StaticInst *si, int idx, - TheISA::FloatRegBits val, int width) - { - this->cpu->setFloatRegBits(this->_destRegIdx[idx], val, width); - BaseDynInst::setFloatRegOperandBits(si, idx, val); - } - - void setFloatRegOperandBits(const StaticInst *si, - int idx, TheISA::FloatRegBits val) - { - this->cpu->setFloatRegBits(this->_destRegIdx[idx], val); - BaseDynInst::setFloatRegOperandBits(si, idx, val); - } - - public: - /** Calculates EA part of a memory instruction. Currently unused, - * though it may be useful in the future if we want to split - * memory operations into EA calculation and memory access parts. - */ - Fault calcEA() - { - return this->staticInst->eaCompInst()->execute(this, this->traceData); - } - - /** Does the memory access part of a memory instruction. Currently unused, - * though it may be useful in the future if we want to split - * memory operations into EA calculation and memory access parts. - */ - Fault memAccess() - { - return this->staticInst->memAccInst()->execute(this, this->traceData); - } -}; - -#endif // __CPU_O3_SPARC_DYN_INST_HH__ - diff --git a/src/cpu/o3/sparc/dyn_inst_impl.hh b/src/cpu/o3/sparc/dyn_inst_impl.hh deleted file mode 100644 index 6bfe97717..000000000 --- a/src/cpu/o3/sparc/dyn_inst_impl.hh +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2004-2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#include "cpu/o3/sparc/dyn_inst.hh" - -template -SparcDynInst::SparcDynInst(StaticInstPtr staticInst, - Addr PC, Addr NPC, Addr microPC, - Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC, - InstSeqNum seq_num, O3CPU *cpu) - : BaseDynInst(staticInst, PC, NPC, microPC, - Pred_PC, Pred_NPC, Pred_MicroPC, seq_num, cpu) -{ - initVars(); -} - -template -SparcDynInst::SparcDynInst(TheISA::ExtMachInst inst, - Addr PC, Addr NPC, Addr microPC, - Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC, - InstSeqNum seq_num, O3CPU *cpu) - : BaseDynInst(inst, PC, NPC, microPC, - Pred_PC, Pred_NPC, Pred_MicroPC, seq_num, cpu) -{ - initVars(); -} - -template -SparcDynInst::SparcDynInst(StaticInstPtr &_staticInst) - : BaseDynInst(_staticInst) -{ - initVars(); -} - -template -void -SparcDynInst::initVars() -{ - // Make sure to have the renamed register entries set to the same - // as the normal register entries. It will allow the IQ to work - // without any modifications. - for (int i = 0; i < this->staticInst->numDestRegs(); i++) { - this->_destRegIdx[i] = this->staticInst->destRegIdx(i); - } - - for (int i = 0; i < this->staticInst->numSrcRegs(); i++) { - this->_srcRegIdx[i] = this->staticInst->srcRegIdx(i); - this->_readySrcRegIdx[i] = 0; - } -} - -template -Fault -SparcDynInst::execute() -{ - // @todo: Pretty convoluted way to avoid squashing from happening - // when using the TC during an instruction's execution - // (specifically for instructions that have side-effects that use - // the TC). Fix this. - bool in_syscall = this->thread->inSyscall; - this->thread->inSyscall = true; - - this->fault = this->staticInst->execute(this, this->traceData); - - this->thread->inSyscall = in_syscall; - - return this->fault; -} - -template -Fault -SparcDynInst::initiateAcc() -{ - // @todo: Pretty convoluted way to avoid squashing from happening - // when using the TC during an instruction's execution - // (specifically for instructions that have side-effects that use - // the TC). Fix this. - bool in_syscall = this->thread->inSyscall; - this->thread->inSyscall = true; - - this->fault = this->staticInst->initiateAcc(this, this->traceData); - - this->thread->inSyscall = in_syscall; - - return this->fault; -} - -template -Fault -SparcDynInst::completeAcc(PacketPtr pkt) -{ - this->fault = this->staticInst->completeAcc(pkt, this, this->traceData); - - return this->fault; -} - -#if FULL_SYSTEM -template -Fault -SparcDynInst::hwrei() -{ - return NoFault; -} - -template -void -SparcDynInst::trap(Fault fault) -{ - this->cpu->trap(fault, this->threadNumber); -} - -template -bool -SparcDynInst::simPalCheck(int palFunc) -{ - panic("simPalCheck called, but there's no PAL in SPARC!\n"); - return false; -} -#else -template -void -SparcDynInst::syscall(int64_t callnum) -{ - this->cpu->syscall(callnum, this->threadNumber); -} -#endif - diff --git a/src/cpu/o3/sparc/impl.hh b/src/cpu/o3/sparc/impl.hh index bcf8e5cc6..cf0e33e42 100644 --- a/src/cpu/o3/sparc/impl.hh +++ b/src/cpu/o3/sparc/impl.hh @@ -38,7 +38,7 @@ // Forward declarations. template -class SparcDynInst; +class BaseO3DynInst; template class FullO3CPU; @@ -60,7 +60,7 @@ struct SparcSimpleImpl typedef SimpleCPUPolicy CPUPol; /** The DynInst type to be used. */ - typedef SparcDynInst DynInst; + typedef BaseO3DynInst DynInst; /** The refcounted DynInst pointer to be used. In most cases this is * what should be used, and not DynInst *. diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index cd4009e76..2c3c3dbc2 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -42,7 +42,7 @@ #include "base/misc.hh" #include "base/refcnt.hh" #include "cpu/op_class.hh" -#include "cpu/o3/dyn_inst.hh" +#include "cpu/o3/dyn_inst_decl.hh" #include "sim/faults.hh" #include "sim/host.hh" -- cgit v1.2.3 From b66eb3b8d1e759bacb55ef187541f4c37767241a Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 9 Oct 2008 00:10:02 -0700 Subject: O3: Generaize the O3 IMPL class so it isn't split out by ISA. --HG-- rename : src/cpu/o3/sparc/cpu_builder.cc => src/cpu/o3/cpu_builder.cc rename : src/cpu/o3/sparc/dyn_inst.cc => src/cpu/o3/dyn_inst.cc rename : src/cpu/o3/sparc/impl.hh => src/cpu/o3/impl.hh rename : src/cpu/o3/sparc/thread_context.cc => src/cpu/o3/thread_context.cc --- src/cpu/o3/SConscript | 21 ++------- src/cpu/o3/alpha/cpu.cc | 37 ---------------- src/cpu/o3/alpha/cpu_builder.cc | 78 --------------------------------- src/cpu/o3/alpha/dyn_inst.cc | 36 ---------------- src/cpu/o3/alpha/impl.hh | 88 -------------------------------------- src/cpu/o3/alpha/thread_context.cc | 36 ---------------- src/cpu/o3/cpu_builder.cc | 78 +++++++++++++++++++++++++++++++++ src/cpu/o3/dyn_inst.cc | 36 ++++++++++++++++ src/cpu/o3/dyn_inst_decl.hh | 56 ------------------------ src/cpu/o3/impl.hh | 85 ++++++++++++++++++++++++++++++++++++ src/cpu/o3/isa_specific.hh | 10 +---- src/cpu/o3/mips/cpu.cc | 38 ---------------- src/cpu/o3/mips/cpu_builder.cc | 79 ---------------------------------- src/cpu/o3/mips/dyn_inst.cc | 37 ---------------- src/cpu/o3/mips/impl.hh | 88 -------------------------------------- src/cpu/o3/mips/thread_context.cc | 36 ---------------- src/cpu/o3/sparc/cpu.cc | 37 ---------------- src/cpu/o3/sparc/cpu_builder.cc | 78 --------------------------------- src/cpu/o3/sparc/dyn_inst.cc | 36 ---------------- src/cpu/o3/sparc/impl.hh | 88 -------------------------------------- src/cpu/o3/sparc/thread_context.cc | 35 --------------- src/cpu/o3/thread_context.cc | 36 ++++++++++++++++ src/cpu/static_inst.hh | 5 ++- 23 files changed, 243 insertions(+), 911 deletions(-) delete mode 100644 src/cpu/o3/alpha/cpu.cc delete mode 100644 src/cpu/o3/alpha/cpu_builder.cc delete mode 100644 src/cpu/o3/alpha/dyn_inst.cc delete mode 100644 src/cpu/o3/alpha/impl.hh delete mode 100755 src/cpu/o3/alpha/thread_context.cc create mode 100644 src/cpu/o3/cpu_builder.cc create mode 100644 src/cpu/o3/dyn_inst.cc delete mode 100644 src/cpu/o3/dyn_inst_decl.hh create mode 100644 src/cpu/o3/impl.hh delete mode 100755 src/cpu/o3/mips/cpu.cc delete mode 100644 src/cpu/o3/mips/cpu_builder.cc delete mode 100755 src/cpu/o3/mips/dyn_inst.cc delete mode 100644 src/cpu/o3/mips/impl.hh delete mode 100755 src/cpu/o3/mips/thread_context.cc delete mode 100644 src/cpu/o3/sparc/cpu.cc delete mode 100644 src/cpu/o3/sparc/cpu_builder.cc delete mode 100644 src/cpu/o3/sparc/dyn_inst.cc delete mode 100644 src/cpu/o3/sparc/impl.hh delete mode 100755 src/cpu/o3/sparc/thread_context.cc create mode 100755 src/cpu/o3/thread_context.cc (limited to 'src') diff --git a/src/cpu/o3/SConscript b/src/cpu/o3/SConscript index 2de106d8b..f05986bf5 100755 --- a/src/cpu/o3/SConscript +++ b/src/cpu/o3/SConscript @@ -51,7 +51,9 @@ if 'O3CPU' in env['CPU_MODELS']: Source('bpred_unit.cc') Source('commit.cc') Source('cpu.cc') + Source('cpu_builder.cc') Source('decode.cc') + Source('dyn_inst.cc') Source('fetch.cc') Source('free_list.cc') Source('fu_pool.cc') @@ -65,6 +67,7 @@ if 'O3CPU' in env['CPU_MODELS']: Source('rob.cc') Source('scoreboard.cc') Source('store_set.cc') + Source('thread_context.cc') TraceFlag('FreeList') TraceFlag('LSQ') @@ -81,24 +84,6 @@ if 'O3CPU' in env['CPU_MODELS']: 'IQ', 'ROB', 'FreeList', 'LSQ', 'LSQUnit', 'StoreSet', 'MemDepUnit', 'DynInst', 'O3CPU', 'Activity', 'Scoreboard', 'Writeback' ]) - if env['TARGET_ISA'] == 'alpha': - Source('alpha/cpu.cc') - Source('alpha/cpu_builder.cc') - Source('alpha/dyn_inst.cc') - Source('alpha/thread_context.cc') - elif env['TARGET_ISA'] == 'mips': - Source('mips/cpu.cc') - Source('mips/cpu_builder.cc') - Source('mips/dyn_inst.cc') - Source('mips/thread_context.cc') - elif env['TARGET_ISA'] == 'sparc': - Source('sparc/cpu.cc') - Source('sparc/cpu_builder.cc') - Source('sparc/dyn_inst.cc') - Source('sparc/thread_context.cc') - else: - sys.exit('O3 CPU does not support the \'%s\' ISA' % env['TARGET_ISA']) - if env['USE_CHECKER']: SimObject('O3Checker.py') Source('checker_builder.cc') diff --git a/src/cpu/o3/alpha/cpu.cc b/src/cpu/o3/alpha/cpu.cc deleted file mode 100644 index 740e6476d..000000000 --- a/src/cpu/o3/alpha/cpu.cc +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - */ - -#include "cpu/o3/alpha/impl.hh" -#include "cpu/o3/cpu.hh" - -// Force instantiation of AlphaO3CPU for all the implemntations that are -// needed. Consider merging this and alpha_dyn_inst.cc, and maybe all -// classes that depend on a certain impl, into one file (alpha_impl.cc?). -template class FullO3CPU; diff --git a/src/cpu/o3/alpha/cpu_builder.cc b/src/cpu/o3/alpha/cpu_builder.cc deleted file mode 100644 index deeb437be..000000000 --- a/src/cpu/o3/alpha/cpu_builder.cc +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2004-2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - */ - -#include - -#include "config/full_system.hh" -#include "config/use_checker.hh" -#include "cpu/o3/cpu.hh" -#include "cpu/o3/alpha/impl.hh" -#include "params/DerivO3CPU.hh" - -class DerivO3CPU : public FullO3CPU -{ - public: - DerivO3CPU(DerivO3CPUParams *p) - : FullO3CPU(p) - { } -}; - -DerivO3CPU * -DerivO3CPUParams::create() -{ -#if FULL_SYSTEM - // Full-system only supports a single thread for the moment. - int actual_num_threads = 1; -#else - // In non-full-system mode, we infer the number of threads from - // the workload if it's not explicitly specified. - int actual_num_threads = - (numThreads >= workload.size()) ? numThreads : workload.size(); - - if (workload.size() == 0) { - fatal("Must specify at least one workload!"); - } -#endif - - numThreads = actual_num_threads; - - // Default smtFetchPolicy to "RoundRobin", if necessary. - std::string round_robin_policy = "RoundRobin"; - std::string single_thread = "SingleThread"; - - if (actual_num_threads > 1 && single_thread.compare(smtFetchPolicy) == 0) - smtFetchPolicy = round_robin_policy; - else - smtFetchPolicy = smtFetchPolicy; - - instShiftAmt = 2; - - return new DerivO3CPU(this); -} diff --git a/src/cpu/o3/alpha/dyn_inst.cc b/src/cpu/o3/alpha/dyn_inst.cc deleted file mode 100644 index 28e70be8a..000000000 --- a/src/cpu/o3/alpha/dyn_inst.cc +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - */ - -#include "cpu/o3/alpha/impl.hh" -#include "cpu/o3/dyn_inst_impl.hh" - -// Force instantiation of AlphaDynInst for all the implementations that -// are needed. -template class BaseO3DynInst; diff --git a/src/cpu/o3/alpha/impl.hh b/src/cpu/o3/alpha/impl.hh deleted file mode 100644 index 7d956cd6a..000000000 --- a/src/cpu/o3/alpha/impl.hh +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - */ - -#ifndef __CPU_O3_ALPHA_IMPL_HH__ -#define __CPU_O3_ALPHA_IMPL_HH__ - -#include "arch/alpha/isa_traits.hh" - -#include "cpu/o3/cpu_policy.hh" - - -// Forward declarations. -template -class BaseO3DynInst; - -template -class FullO3CPU; - -/** Implementation specific struct that defines several key types to the - * CPU, the stages within the CPU, the time buffers, and the DynInst. - * The struct defines the ISA, the CPU policy, the specific DynInst, the - * specific O3CPU, and all of the structs from the time buffers to do - * communication. - * This is one of the key things that must be defined for each hardware - * specific CPU implementation. - */ -struct AlphaSimpleImpl -{ - /** The type of MachInst. */ - typedef TheISA::MachInst MachInst; - - /** The CPU policy to be used, which defines all of the CPU stages. */ - typedef SimpleCPUPolicy CPUPol; - - /** The DynInst type to be used. */ - typedef BaseO3DynInst DynInst; - - /** The refcounted DynInst pointer to be used. In most cases this is - * what should be used, and not DynInst *. - */ - typedef RefCountingPtr DynInstPtr; - - /** The O3CPU type to be used. */ - typedef FullO3CPU O3CPU; - - /** Same typedef, but for CPUType. BaseDynInst may not always use - * an O3 CPU, so it's clearer to call it CPUType instead in that - * case. - */ - typedef O3CPU CPUType; - - enum { - MaxWidth = 8, - MaxThreads = 4 - }; -}; - -/** The O3Impl to be used. */ -typedef AlphaSimpleImpl O3CPUImpl; - -#endif // __CPU_O3_ALPHA_IMPL_HH__ diff --git a/src/cpu/o3/alpha/thread_context.cc b/src/cpu/o3/alpha/thread_context.cc deleted file mode 100755 index 4a02715bc..000000000 --- a/src/cpu/o3/alpha/thread_context.cc +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2004-2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - * Korey Sewell - */ - -#include "cpu/o3/thread_context.hh" -#include "cpu/o3/thread_context_impl.hh" - -template class O3ThreadContext; - diff --git a/src/cpu/o3/cpu_builder.cc b/src/cpu/o3/cpu_builder.cc new file mode 100644 index 000000000..77d7091ad --- /dev/null +++ b/src/cpu/o3/cpu_builder.cc @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2004-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + */ + +#include + +#include "config/full_system.hh" +#include "config/use_checker.hh" +#include "cpu/o3/cpu.hh" +#include "cpu/o3/impl.hh" +#include "params/DerivO3CPU.hh" + +class DerivO3CPU : public FullO3CPU +{ + public: + DerivO3CPU(DerivO3CPUParams *p) + : FullO3CPU(p) + { } +}; + +DerivO3CPU * +DerivO3CPUParams::create() +{ +#if FULL_SYSTEM + // Full-system only supports a single thread for the moment. + int actual_num_threads = 1; +#else + // In non-full-system mode, we infer the number of threads from + // the workload if it's not explicitly specified. + int actual_num_threads = + (numThreads >= workload.size()) ? numThreads : workload.size(); + + if (workload.size() == 0) { + fatal("Must specify at least one workload!"); + } +#endif + + numThreads = actual_num_threads; + + // Default smtFetchPolicy to "RoundRobin", if necessary. + std::string round_robin_policy = "RoundRobin"; + std::string single_thread = "SingleThread"; + + if (actual_num_threads > 1 && single_thread.compare(smtFetchPolicy) == 0) + smtFetchPolicy = round_robin_policy; + else + smtFetchPolicy = smtFetchPolicy; + + instShiftAmt = 2; + + return new DerivO3CPU(this); +} diff --git a/src/cpu/o3/dyn_inst.cc b/src/cpu/o3/dyn_inst.cc new file mode 100644 index 000000000..d828ef1b0 --- /dev/null +++ b/src/cpu/o3/dyn_inst.cc @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "cpu/o3/dyn_inst_impl.hh" +#include "cpu/o3/impl.hh" + +// Force instantiation of BaseO3DynInst for all the implementations that +// are needed. +template class BaseO3DynInst; diff --git a/src/cpu/o3/dyn_inst_decl.hh b/src/cpu/o3/dyn_inst_decl.hh deleted file mode 100644 index 750c3279d..000000000 --- a/src/cpu/o3/dyn_inst_decl.hh +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Korey Sewell - */ - -#ifndef __CPU_O3_DYN_INST_DECL_HH__ -#define __CPU_O3_DYN_INST_DECL_HH__ - -#include "arch/isa_specific.hh" - -template class BaseO3DynInst; -#if THE_ISA == ALPHA_ISA - struct AlphaSimpleImpl; - typedef BaseO3DynInst O3DynInst; -#elif THE_ISA == MIPS_ISA - struct MipsSimpleImpl; - typedef BaseO3DynInst O3DynInst; -#elif THE_ISA == SPARC_ISA - struct SparcSimpleImpl; - typedef BaseO3DynInst O3DynInst; -#elif THE_ISA == X86_ISA - struct X86SimpleImpl; - typedef BaseO3DynInst O3DynInst; -#elif THE_ISA == ARM_ISA - struct ArmSimpleImpl; - typedef BaseO3DynInst O3DynInst; -#else - #error "O3DynInst not defined for this ISA" -#endif - -#endif // __CPU_O3_DYN_INST_DECL_HH__ diff --git a/src/cpu/o3/impl.hh b/src/cpu/o3/impl.hh new file mode 100644 index 000000000..4b29b4daa --- /dev/null +++ b/src/cpu/o3/impl.hh @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + */ + +#ifndef __CPU_O3_IMPL_HH__ +#define __CPU_O3_IMPL_HH__ + +#include "arch/isa_traits.hh" + +#include "cpu/o3/cpu_policy.hh" + + +// Forward declarations. +template +class BaseO3DynInst; + +template +class FullO3CPU; + +/** Implementation specific struct that defines several key types to the + * CPU, the stages within the CPU, the time buffers, and the DynInst. + * The struct defines the ISA, the CPU policy, the specific DynInst, the + * specific O3CPU, and all of the structs from the time buffers to do + * communication. + * This is one of the key things that must be defined for each hardware + * specific CPU implementation. + */ +struct O3CPUImpl +{ + /** The type of MachInst. */ + typedef TheISA::MachInst MachInst; + + /** The CPU policy to be used, which defines all of the CPU stages. */ + typedef SimpleCPUPolicy CPUPol; + + /** The DynInst type to be used. */ + typedef BaseO3DynInst DynInst; + + /** The refcounted DynInst pointer to be used. In most cases this is + * what should be used, and not DynInst *. + */ + typedef RefCountingPtr DynInstPtr; + + /** The O3CPU type to be used. */ + typedef FullO3CPU O3CPU; + + /** Same typedef, but for CPUType. BaseDynInst may not always use + * an O3 CPU, so it's clearer to call it CPUType instead in that + * case. + */ + typedef O3CPU CPUType; + + enum { + MaxWidth = 8, + MaxThreads = 4 + }; +}; + +#endif // __CPU_O3_SPARC_IMPL_HH__ diff --git a/src/cpu/o3/isa_specific.hh b/src/cpu/o3/isa_specific.hh index 6111a5336..e9347af91 100755 --- a/src/cpu/o3/isa_specific.hh +++ b/src/cpu/o3/isa_specific.hh @@ -30,13 +30,5 @@ #include "cpu/base.hh" -#if THE_ISA == ALPHA_ISA - #include "cpu/o3/alpha/impl.hh" -#elif THE_ISA == MIPS_ISA - #include "cpu/o3/mips/impl.hh" -#elif THE_ISA == SPARC_ISA - #include "cpu/o3/sparc/impl.hh" -#else - #error "ISA-specific header files O3CPU not defined ISA" -#endif +#include "cpu/o3/impl.hh" #include "cpu/o3/dyn_inst.hh" diff --git a/src/cpu/o3/mips/cpu.cc b/src/cpu/o3/mips/cpu.cc deleted file mode 100755 index bb78de0a6..000000000 --- a/src/cpu/o3/mips/cpu.cc +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - * Korey Sewell - */ - -#include "cpu/o3/cpu.hh" -#include "cpu/o3/mips/impl.hh" - -// Force instantiation of MipsO3CPU for all the implemntations that are -// needed. Consider merging this and mips_dyn_inst.cc, and maybe all -// classes that depend on a certain impl, into one file (mips_impl.cc?). -template class FullO3CPU; diff --git a/src/cpu/o3/mips/cpu_builder.cc b/src/cpu/o3/mips/cpu_builder.cc deleted file mode 100644 index 11942e597..000000000 --- a/src/cpu/o3/mips/cpu_builder.cc +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - * Korey Sewell - */ - -#include - -#include "config/full_system.hh" -#include "config/use_checker.hh" -#include "cpu/o3/cpu.hh" -#include "cpu/o3/mips/impl.hh" -#include "params/DerivO3CPU.hh" - -class DerivO3CPU : public FullO3CPU -{ - public: - DerivO3CPU(DerivO3CPUParams *p) - : FullO3CPU(p) - { } -}; - -DerivO3CPU * -DerivO3CPUParams::create() -{ -#if FULL_SYSTEM - // Full-system only supports a single thread for the moment. - int actual_num_threads = 1; -#else - // In non-full-system mode, we infer the number of threads from - // the workload if it's not explicitly specified. - int actual_num_threads = - (numThreads >= workload.size()) ? numThreads : workload.size(); - - if (workload.size() == 0) { - fatal("Must specify at least one workload!"); - } -#endif - - numThreads = actual_num_threads; - - // Default smtFetchPolicy to "RoundRobin", if necessary. - std::string round_robin_policy = "RoundRobin"; - std::string single_thread = "SingleThread"; - - if (actual_num_threads > 1 && single_thread.compare(smtFetchPolicy) == 0) - smtFetchPolicy = round_robin_policy; - else - smtFetchPolicy = smtFetchPolicy; - - instShiftAmt = 2; - - return new DerivO3CPU(this); -} diff --git a/src/cpu/o3/mips/dyn_inst.cc b/src/cpu/o3/mips/dyn_inst.cc deleted file mode 100755 index 88205afaf..000000000 --- a/src/cpu/o3/mips/dyn_inst.cc +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - * Korey Sewell - */ - -#include "cpu/o3/dyn_inst_impl.hh" -#include "cpu/o3/mips/impl.hh" - -// Force instantiation of MipsDynInst for all the implementations that -// are needed. -template class BaseO3DynInst; diff --git a/src/cpu/o3/mips/impl.hh b/src/cpu/o3/mips/impl.hh deleted file mode 100644 index 78afd1387..000000000 --- a/src/cpu/o3/mips/impl.hh +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - * Korey Sewell - */ - -#ifndef __CPU_O3_MIPS_IMPL_HH__ -#define __CPU_O3_MIPS_IMPL_HH__ - -#include "arch/mips/isa_traits.hh" - -#include "cpu/o3/cpu_policy.hh" - -// Forward declarations. -template -class BaseO3DynInst; - -template -class FullO3CPU; - -/** Implementation specific struct that defines several key types to the - * CPU, the stages within the CPU, the time buffers, and the DynInst. - * The struct defines the ISA, the CPU policy, the specific DynInst, the - * specific O3CPU, and all of the structs from the time buffers to do - * communication. - * This is one of the key things that must be defined for each hardware - * specific CPU implementation. - */ -struct MipsSimpleImpl -{ - /** The type of MachInst. */ - typedef TheISA::MachInst MachInst; - - /** The CPU policy to be used, which defines all of the CPU stages. */ - typedef SimpleCPUPolicy CPUPol; - - /** The DynInst type to be used. */ - typedef BaseO3DynInst DynInst; - - /** The refcounted DynInst pointer to be used. In most cases this is - * what should be used, and not DynInst *. - */ - typedef RefCountingPtr DynInstPtr; - - /** The O3CPU type to be used. */ - typedef FullO3CPU O3CPU; - - /** Same typedef, but for CPUType. BaseDynInst may not always use - * an O3 CPU, so it's clearer to call it CPUType instead in that - * case. - */ - typedef O3CPU CPUType; - - enum { - MaxWidth = 8, - MaxThreads = 4 - }; -}; - -/** The O3Impl to be used. */ -typedef MipsSimpleImpl O3CPUImpl; - -#endif // __CPU_O3_MIPS_IMPL_HH__ diff --git a/src/cpu/o3/mips/thread_context.cc b/src/cpu/o3/mips/thread_context.cc deleted file mode 100755 index 0061a2a63..000000000 --- a/src/cpu/o3/mips/thread_context.cc +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - * Korey Sewell - */ - -#include "cpu/o3/thread_context.hh" -#include "cpu/o3/thread_context_impl.hh" - -template class O3ThreadContext; - diff --git a/src/cpu/o3/sparc/cpu.cc b/src/cpu/o3/sparc/cpu.cc deleted file mode 100644 index 738ff0108..000000000 --- a/src/cpu/o3/sparc/cpu.cc +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#include "cpu/o3/cpu.hh" -#include "cpu/o3/sparc/impl.hh" - -// Force instantiation of SparcO3CPU for all the implementations that are -// needed. Consider merging this and sparc_dyn_inst.cc, and maybe all -// classes that depend on a certain impl, into one file (sparc_impl.cc?). -template class FullO3CPU; diff --git a/src/cpu/o3/sparc/cpu_builder.cc b/src/cpu/o3/sparc/cpu_builder.cc deleted file mode 100644 index c19b4871f..000000000 --- a/src/cpu/o3/sparc/cpu_builder.cc +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2004-2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#include - -#include "config/full_system.hh" -#include "config/use_checker.hh" -#include "cpu/o3/cpu.hh" -#include "cpu/o3/sparc/impl.hh" -#include "params/DerivO3CPU.hh" - -class DerivO3CPU : public FullO3CPU -{ - public: - DerivO3CPU(DerivO3CPUParams *p) - : FullO3CPU(p) - { } -}; - -DerivO3CPU * -DerivO3CPUParams::create() -{ -#if FULL_SYSTEM - // Full-system only supports a single thread for the moment. - int actual_num_threads = 1; -#else - // In non-full-system mode, we infer the number of threads from - // the workload if it's not explicitly specified. - int actual_num_threads = - (numThreads >= workload.size()) ? numThreads : workload.size(); - - if (workload.size() == 0) { - fatal("Must specify at least one workload!"); - } -#endif - - numThreads = actual_num_threads; - - // Default smtFetchPolicy to "RoundRobin", if necessary. - std::string round_robin_policy = "RoundRobin"; - std::string single_thread = "SingleThread"; - - if (actual_num_threads > 1 && single_thread.compare(smtFetchPolicy) == 0) - smtFetchPolicy = round_robin_policy; - else - smtFetchPolicy = smtFetchPolicy; - - instShiftAmt = 2; - - return new DerivO3CPU(this); -} diff --git a/src/cpu/o3/sparc/dyn_inst.cc b/src/cpu/o3/sparc/dyn_inst.cc deleted file mode 100644 index ea86f8719..000000000 --- a/src/cpu/o3/sparc/dyn_inst.cc +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#include "cpu/o3/dyn_inst_impl.hh" -#include "cpu/o3/sparc/impl.hh" - -// Force instantiation of SparcDynInst for all the implementations that -// are needed. -template class BaseO3DynInst; diff --git a/src/cpu/o3/sparc/impl.hh b/src/cpu/o3/sparc/impl.hh deleted file mode 100644 index cf0e33e42..000000000 --- a/src/cpu/o3/sparc/impl.hh +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#ifndef __CPU_O3_SPARC_IMPL_HH__ -#define __CPU_O3_SPARC_IMPL_HH__ - -#include "arch/sparc/isa_traits.hh" - -#include "cpu/o3/cpu_policy.hh" - - -// Forward declarations. -template -class BaseO3DynInst; - -template -class FullO3CPU; - -/** Implementation specific struct that defines several key types to the - * CPU, the stages within the CPU, the time buffers, and the DynInst. - * The struct defines the ISA, the CPU policy, the specific DynInst, the - * specific O3CPU, and all of the structs from the time buffers to do - * communication. - * This is one of the key things that must be defined for each hardware - * specific CPU implementation. - */ -struct SparcSimpleImpl -{ - /** The type of MachInst. */ - typedef TheISA::MachInst MachInst; - - /** The CPU policy to be used, which defines all of the CPU stages. */ - typedef SimpleCPUPolicy CPUPol; - - /** The DynInst type to be used. */ - typedef BaseO3DynInst DynInst; - - /** The refcounted DynInst pointer to be used. In most cases this is - * what should be used, and not DynInst *. - */ - typedef RefCountingPtr DynInstPtr; - - /** The O3CPU type to be used. */ - typedef FullO3CPU O3CPU; - - /** Same typedef, but for CPUType. BaseDynInst may not always use - * an O3 CPU, so it's clearer to call it CPUType instead in that - * case. - */ - typedef O3CPU CPUType; - - enum { - MaxWidth = 8, - MaxThreads = 4 - }; -}; - -/** The O3Impl to be used. */ -typedef SparcSimpleImpl O3CPUImpl; - -#endif // __CPU_O3_SPARC_IMPL_HH__ diff --git a/src/cpu/o3/sparc/thread_context.cc b/src/cpu/o3/sparc/thread_context.cc deleted file mode 100755 index d85aff502..000000000 --- a/src/cpu/o3/sparc/thread_context.cc +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2004-2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#include "cpu/o3/thread_context.hh" -#include "cpu/o3/thread_context_impl.hh" - -template class O3ThreadContext; - diff --git a/src/cpu/o3/thread_context.cc b/src/cpu/o3/thread_context.cc new file mode 100755 index 000000000..0d8c67643 --- /dev/null +++ b/src/cpu/o3/thread_context.cc @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2004-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + */ + +#include "cpu/o3/thread_context.hh" +#include "cpu/o3/thread_context_impl.hh" +#include "cpu/o3/impl.hh" + +template class O3ThreadContext; + diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index 2c3c3dbc2..8a1b3e749 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -42,7 +42,6 @@ #include "base/misc.hh" #include "base/refcnt.hh" #include "cpu/op_class.hh" -#include "cpu/o3/dyn_inst_decl.hh" #include "sim/faults.hh" #include "sim/host.hh" @@ -54,6 +53,10 @@ class ThreadContext; class DynInst; class Packet; +class O3CPUImpl; +template class BaseO3DynInst; +typedef BaseO3DynInst O3DynInst; + template class OzoneDynInst; -- cgit v1.2.3 From a52dce6d623f6cb289004d4af12be0769966dadf Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 9 Oct 2008 04:58:23 -0700 Subject: style: Bring statistics code in line with the proper style. --- src/base/statistics.hh | 326 ++++++++++++++++++++++++++++++-------------- src/base/stats/events.cc | 2 +- src/base/stats/flags.hh | 1 + src/base/stats/mysql.cc | 2 +- src/base/stats/mysql.hh | 20 +-- src/base/stats/mysql_run.hh | 8 +- src/base/stats/statdb.cc | 3 +- src/base/stats/text.cc | 10 +- src/base/stats/types.hh | 1 + 9 files changed, 251 insertions(+), 122 deletions(-) (limited to 'src') diff --git a/src/base/statistics.hh b/src/base/statistics.hh index 25017031f..05daeed0f 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -177,7 +177,9 @@ struct VectorData : public StatData virtual const VCounter &value() const = 0; virtual const VResult &result() const = 0; virtual Result total() const = 0; - void update() + + void + update() { if (!subnames.empty()) { int s = size(); @@ -206,18 +208,25 @@ class VectorStatData : public VectorData virtual void reset() { s.reset(); } virtual size_t size() const { return s.size(); } - virtual VCounter &value() const + + virtual VCounter & + value() const { s.value(cvec); return cvec; } - virtual const VResult &result() const + + virtual const VResult & + result() const { s.result(rvec); return rvec; } + virtual Result total() const { return s.total(); } - virtual void visit(Visit &visitor) + + virtual void + visit(Visit &visitor) { update(); s.update(this); @@ -261,7 +270,9 @@ class DistStatData : public DistData virtual bool check() const { return s.check(); } virtual void reset() { s.reset(); } virtual bool zero() const { return s.zero(); } - virtual void visit(Visit &visitor) + + virtual void + visit(Visit &visitor) { s.update(this); visitor.visit(*this); @@ -280,7 +291,9 @@ struct VectorDistData : public StatData mutable VResult rvec; virtual size_t size() const = 0; - void update() + + void + update() { int s = size(); if (subnames.size() < s) @@ -304,7 +317,9 @@ class VectorDistStatData : public VectorDistData virtual void reset() { s.reset(); } virtual size_t size() const { return s.size(); } virtual bool zero() const { return s.zero(); } - virtual void visit(Visit &visitor) + + virtual void + visit(Visit &visitor) { update(); s.update(this); @@ -324,7 +339,8 @@ struct Vector2dData : public StatData mutable int x; mutable int y; - void update() + void + update() { if (subnames.size() < x) subnames.resize(x); @@ -343,7 +359,9 @@ class Vector2dStatData : public Vector2dData virtual bool check() const { return s.check(); } virtual void reset() { s.reset(); } virtual bool zero() const { return s.zero(); } - virtual void visit(Visit &visitor) + + virtual void + visit(Visit &visitor) { update(); s.update(this); @@ -371,7 +389,8 @@ class Wrap : public Child Parent &self() { return *reinterpret_cast(this); } protected: - Data *statData() + Data * + statData() { StatData *__data = DataAccess::statData(); Data *ptr = dynamic_cast *>(__data); @@ -380,7 +399,8 @@ class Wrap : public Child } public: - const Data *statData() const + const Data * + statData() const { const StatData *__data = DataAccess::statData(); const Data *ptr = dynamic_cast *>(__data); @@ -393,6 +413,7 @@ class Wrap : public Child * Copy constructor, copies are not allowed. */ Wrap(const Wrap &stat); + /** * Can't copy stats. */ @@ -409,7 +430,8 @@ class Wrap : public Child * @param name The new name. * @return A reference to this stat. */ - Parent &name(const std::string &_name) + Parent & + name(const std::string &_name) { Data *data = this->statData(); data->name = _name; @@ -423,7 +445,8 @@ class Wrap : public Child * @param desc The new description. * @return A reference to this stat. */ - Parent &desc(const std::string &_desc) + Parent & + desc(const std::string &_desc) { this->statData()->desc = _desc; return this->self(); @@ -434,7 +457,8 @@ class Wrap : public Child * @param p The new precision * @return A reference to this stat. */ - Parent &precision(int _precision) + Parent & + precision(int _precision) { this->statData()->precision = _precision; return this->self(); @@ -445,7 +469,8 @@ class Wrap : public Child * @param f The new flags. * @return A reference to this stat. */ - Parent &flags(StatFlags _flags) + Parent & + flags(StatFlags _flags) { this->statData()->flags |= _flags; return this->self(); @@ -458,7 +483,8 @@ class Wrap : public Child * @return A reference to this stat. */ template - Parent &prereq(const Stat &prereq) + Parent & + prereq(const Stat &prereq) { this->statData()->prereq = prereq.statData(); return this->self(); @@ -479,7 +505,8 @@ class WrapVec : public Wrap * @param name The new name of the subfield. * @return A reference to this stat. */ - Parent &subname(int index, const std::string &name) + Parent & + subname(int index, const std::string &name) { std::vector &subn = this->statData()->subnames; if (subn.size() <= index) @@ -495,7 +522,8 @@ class WrapVec : public Wrap * @param desc The new description of the subfield * @return A reference to this stat. */ - Parent &subdesc(int index, const std::string &desc) + Parent & + subdesc(int index, const std::string &desc) { std::vector &subd = this->statData()->subdescs; if (subd.size() <= index) @@ -515,7 +543,8 @@ class WrapVec2d : public WrapVec * @warning This makes the assumption that if you're gonna subnames a 2d * vector, you're subnaming across all y */ - Parent &ysubnames(const char **names) + Parent & + ysubnames(const char **names) { Data *data = this->statData(); data->y_subnames.resize(this->y); @@ -523,7 +552,9 @@ class WrapVec2d : public WrapVec data->y_subnames[i] = names[i]; return this->self(); } - Parent &ysubname(int index, const std::string subname) + + Parent & + ysubname(int index, const std::string subname) { Data *data = this->statData(); assert(index < this->y); @@ -633,7 +664,8 @@ struct AvgStor * @param val The new count. * @param p The parameters for this storage. */ - void set(Counter val, Params &p) { + void + set(Counter val, Params &p) { total += current * (curTick - last); last = curTick; current = val; @@ -665,7 +697,8 @@ struct AvgStor * @param p The parameters for this storage. * @return The current average. */ - Result result(const Params &p) const + Result + result(const Params &p) const { total += current * (curTick - last); last = curTick; @@ -675,7 +708,8 @@ struct AvgStor /** * Reset stat value to default */ - void reset() + void + reset() { total = 0; last = curTick; @@ -864,14 +898,16 @@ class ValueBase : public DataAccess ~ValueBase() { if (proxy) delete proxy; } template - void scalar(T &value) + void + scalar(T &value) { proxy = new ValueProxy(value); setInit(); } template - void functor(T &func) + void + functor(T &func) { proxy = new FunctorProxy(func); setInit(); @@ -946,7 +982,8 @@ class ScalarProxy * @param sp The proxy to copy. * @return A reference to this proxy. */ - const ScalarProxy &operator=(const ScalarProxy &sp) { + const ScalarProxy & + operator=(const ScalarProxy &sp) { stat = sp.stat; index = sp.index; return *this; @@ -976,7 +1013,11 @@ class ScalarProxy * @param v The new value. */ template - void operator=(const U &v) { stat->data(index)->set(v, stat->params); } + void + operator=(const U &v) + { + stat->data(index)->set(v, stat->params); + } /** * Increment the stat by the given value. This calls the associated @@ -984,7 +1025,11 @@ class ScalarProxy * @param v The value to add. */ template - void operator+=(const U &v) { stat->data(index)->inc(v, stat->params); } + void + operator+=(const U &v) + { + stat->data(index)->inc(v, stat->params); + } /** * Decrement the stat by the given value. This calls the associated @@ -992,7 +1037,11 @@ class ScalarProxy * @param v The value to substract. */ template - void operator-=(const U &v) { stat->data(index)->dec(v, stat->params); } + void + operator-=(const U &v) + { + stat->data(index)->dec(v, stat->params); + } /** * Return the number of elements, always 1 for a scalar. @@ -1071,7 +1120,8 @@ class VectorBase : public DataAccess } public: - void value(VCounter &vec) const + void + value(VCounter &vec) const { vec.resize(size()); for (int i = 0; i < size(); ++i) @@ -1082,7 +1132,8 @@ class VectorBase : public DataAccess * Copy the values to a local vector and return a reference to it. * @return A reference to a vector of the stat values. */ - void result(VResult &vec) const + void + result(VResult &vec) const { vec.resize(size()); for (int i = 0; i < size(); ++i) @@ -1093,7 +1144,9 @@ class VectorBase : public DataAccess * Return a total of all entries in this vector. * @return The total of all vector entries. */ - Result total() const { + Result + total() const + { Result total = 0.0; for (int i = 0; i < size(); ++i) total += data(i)->result(params); @@ -1223,7 +1276,8 @@ class VectorProxy return *this; } - ScalarProxy operator[](int index) + ScalarProxy + operator[](int index) { assert (index >= 0 && index < size()); return ScalarProxy(stat, offset + index); @@ -1408,14 +1462,15 @@ struct DistStor * @param number The number of times to add the value. * @param params The paramters of the distribution. */ - void sample(Counter val, int number, const Params ¶ms) + void + sample(Counter val, int number, const Params ¶ms) { if (val < params.min) underflow += number; else if (val > params.max) overflow += number; else { - int index = (int)std::floor((val - params.min) / params.bucket_size); + size_t index = std::floor((val - params.min) / params.bucket_size); assert(index < size(params)); cvec[index] += number; } @@ -1444,12 +1499,14 @@ struct DistStor * @param params The paramters of the distribution. * @return True if any values have been sampled. */ - bool zero(const Params ¶ms) const + bool + zero(const Params ¶ms) const { return samples == Counter(); } - void update(DistDataData *data, const Params ¶ms) + void + update(DistDataData *data, const Params ¶ms) { data->min = params.min; data->max = params.max; @@ -1472,7 +1529,8 @@ struct DistStor /** * Reset stat value to default */ - void reset() + void + reset() { min_val = CounterLimits::max(); max_val = CounterLimits::min(); @@ -1526,7 +1584,8 @@ struct FancyStor * @param number The number of times to add the value. * @param p The parameters of this stat. */ - void sample(Counter val, int number, const Params &p) + void + sample(Counter val, int number, const Params &p) { Counter value = val * number; sum += value; @@ -1534,7 +1593,8 @@ struct FancyStor samples += number; } - void update(DistDataData *data, const Params ¶ms) + void + update(DistDataData *data, const Params ¶ms) { data->sum = sum; data->squares = squares; @@ -1556,7 +1616,8 @@ struct FancyStor /** * Reset stat value to default */ - void reset() + void + reset() { sum = Counter(); squares = Counter(); @@ -1594,14 +1655,16 @@ struct AvgFancy * @param number The number of times to add the value. * @param p The paramters of the distribution. */ - void sample(Counter val, int number, const Params &p) + void + sample(Counter val, int number, const Params &p) { Counter value = val * number; sum += value; squares += value * value; } - void update(DistDataData *data, const Params ¶ms) + void + update(DistDataData *data, const Params ¶ms) { data->sum = sum; data->squares = squares; @@ -1613,15 +1676,18 @@ struct AvgFancy * @return 1. */ size_t size(const Params ¶ms) const { return 1; } + /** * Return true if no samples have been added. * @return True if the sum is zero. */ bool zero(const Params ¶ms) const { return sum == Counter(); } + /** * Reset stat value to default */ - void reset() + void + reset() { sum = Counter(); squares = Counter(); @@ -1652,7 +1718,8 @@ class DistBase : public DataAccess * Retrieve the storage. * @return The storage object for this stat. */ - Storage *data() + Storage * + data() { return reinterpret_cast(storage); } @@ -1697,7 +1764,8 @@ class DistBase : public DataAccess */ bool zero() const { return data()->zero(params); } - void update(DistData *base) + void + update(DistData *base) { base->data.fancy = Storage::fancy; data()->update(&(base->data), params); @@ -1848,7 +1916,8 @@ class DistProxy : stat(sp.stat), index(sp.index) {} - const DistProxy &operator=(const DistProxy &sp) + const DistProxy & + operator=(const DistProxy &sp) { stat = sp.stat; index = sp.index; @@ -1895,9 +1964,8 @@ Result VectorDistBase::total(int index) const { int total = 0; - for (int i = 0; i < x_size(); ++i) { + for (int i = 0; i < x_size(); ++i) total += data(i)->result(stat->params); - } } #endif @@ -1947,11 +2015,14 @@ class ScalarStatNode : public Node public: ScalarStatNode(const ScalarData *d) : data(d), vresult(1) {} - virtual const VResult &result() const + + virtual const VResult & + result() const { vresult[0] = data->result(); return vresult; } + virtual Result total() const { return data->result(); }; virtual size_t size() const { return 1; } @@ -2041,25 +2112,25 @@ class ConstVectorNode : public Node public: ConstVectorNode(const T &s) : vresult(s.begin(), s.end()) {} const VResult &result() const { return vresult; } - virtual Result total() const + + virtual Result + total() const { int size = this->size(); Result tmp = 0; for (int i = 0; i < size; i++) - { tmp += vresult[i]; - } return tmp; } + virtual size_t size() const { return vresult.size(); } - virtual std::string str() const + virtual std::string + str() const { int size = this->size(); std::string tmp = "("; for (int i = 0; i < size; i++) - { tmp += csprintf("%s ",to_string(vresult[i])); - } tmp += ")"; return tmp; } @@ -2114,7 +2185,8 @@ class UnaryNode : public Node public: UnaryNode(NodePtr &p) : l(p) {} - const VResult &result() const + const VResult & + result() const { const VResult &lvec = l->result(); int size = lvec.size(); @@ -2129,7 +2201,8 @@ class UnaryNode : public Node return vresult; } - Result total() const + Result + total() const { const VResult &vec = this->result(); Result total = 0; @@ -2140,7 +2213,8 @@ class UnaryNode : public Node virtual size_t size() const { return l->size(); } - virtual std::string str() const + virtual std::string + str() const { return OpString::str() + l->str(); } @@ -2157,7 +2231,8 @@ class BinaryNode : public Node public: BinaryNode(NodePtr &a, NodePtr &b) : l(a), r(b) {} - const VResult &result() const + const VResult & + result() const { Op op; const VResult &lvec = l->result(); @@ -2188,7 +2263,8 @@ class BinaryNode : public Node return vresult; } - Result total() const + Result + total() const { const VResult &vec = this->result(); Result total = 0; @@ -2197,20 +2273,23 @@ class BinaryNode : public Node return total; } - virtual size_t size() const { + virtual size_t + size() const + { int ls = l->size(); int rs = r->size(); - if (ls == 1) + if (ls == 1) { return rs; - else if (rs == 1) + } else if (rs == 1) { return ls; - else { + } else { assert(ls == rs && "Node vector sizes are not equal"); return ls; } } - virtual std::string str() const + virtual std::string + str() const { return csprintf("(%s %s %s)", l->str(), OpString::str(), r->str()); } @@ -2226,7 +2305,8 @@ class SumNode : public Node public: SumNode(NodePtr &p) : l(p), vresult(1) {} - const VResult &result() const + const VResult & + result() const { const VResult &lvec = l->result(); int size = lvec.size(); @@ -2241,7 +2321,8 @@ class SumNode : public Node return vresult; } - Result total() const + Result + total() const { const VResult &lvec = l->result(); int size = lvec.size(); @@ -2258,7 +2339,8 @@ class SumNode : public Node virtual size_t size() const { return 1; } - virtual std::string str() const + virtual std::string + str() const { return csprintf("total(%s)", l->str()); } @@ -2308,14 +2390,16 @@ class Value : public Wrap typedef ValueBase Base; template - Value &scalar(T &value) + Value & + scalar(T &value) { Base::scalar(value); return *this; } template - Value &functor(T &func) + Value & + functor(T &func) { Base::functor(func); return *this; @@ -2344,7 +2428,11 @@ class Average : public Wrap, ScalarBase, ScalarStatData> * @param v The new value. */ template - void operator=(const U &v) { Base::operator=(v); } + void + operator=(const U &v) + { + Base::operator=(v); + } }; /** @@ -2363,7 +2451,9 @@ class Vector : public WrapVec, VectorBase, VectorStatData> * @param size The new size. * @return A reference to this stat. */ - Vector &init(size_t size) { + Vector & + init(size_t size) + { this->doInit(size); return *this; } @@ -2383,7 +2473,9 @@ class AverageVector * @param size The new size. * @return A reference to this stat. */ - AverageVector &init(size_t size) { + AverageVector & + init(size_t size) + { this->doInit(size); return *this; } @@ -2398,7 +2490,9 @@ class Vector2d : public WrapVec2d, Vector2dBase, Vector2dStatData> { public: - Vector2d &init(size_t x, size_t y) { + Vector2d & + init(size_t x, size_t y) + { this->doInit(x, y); return *this; } @@ -2426,7 +2520,9 @@ class Distribution * @param bkt The number of values in each bucket. * @return A reference to this distribution. */ - Distribution &init(Counter min, Counter max, Counter bkt) { + Distribution & + init(Counter min, Counter max, Counter bkt) + { this->params.min = min; this->params.max = max; this->params.bucket_size = bkt; @@ -2454,7 +2550,8 @@ class StandardDeviation /** * Construct and initialize this distribution. */ - StandardDeviation() { + StandardDeviation() + { this->doInit(); } }; @@ -2508,7 +2605,9 @@ class VectorDistribution * @param bkt The number of values in each bucket. * @return A reference to this distribution. */ - VectorDistribution &init(int size, Counter min, Counter max, Counter bkt) { + VectorDistribution & + init(int size, Counter min, Counter max, Counter bkt) + { this->params.min = min; this->params.max = max; this->params.bucket_size = bkt; @@ -2540,7 +2639,9 @@ class VectorStandardDeviation * @param size The size of the vector. * @return A reference to this distribution. */ - VectorStandardDeviation &init(int size) { + VectorStandardDeviation & + init(int size) + { this->doInit(size); return *this; } @@ -2568,7 +2669,9 @@ class VectorAverageDeviation * @param size The size of the vector. * @return A reference to this distribution. */ - VectorAverageDeviation &init(int size) { + VectorAverageDeviation & + init(int size) + { this->doInit(size); return *this; } @@ -2655,19 +2758,24 @@ class FormulaStatData : public FormulaData virtual void reset() { s.reset(); } virtual size_t size() const { return s.size(); } - virtual const VResult &result() const + + virtual const VResult & + result() const { s.result(vec); return vec; } virtual Result total() const { return s.total(); } virtual VCounter &value() const { return cvec; } - virtual void visit(Visit &visitor) + + virtual void + visit(Visit &visitor) { update(); s.update(this); visitor.visit(*this); } + virtual std::string str() const { return s.str(); } }; @@ -2752,14 +2860,16 @@ class Temp */ template Temp(const Scalar &s) - : node(new ScalarStatNode(s.statData())) { } + : node(new ScalarStatNode(s.statData())) + { } /** * Create a new ScalarStatNode. * @param s The ScalarStat to place in a node. */ Temp(const Value &s) - : node(new ScalarStatNode(s.statData())) { } + : node(new ScalarStatNode(s.statData())) + { } /** * Create a new ScalarStatNode. @@ -2767,7 +2877,8 @@ class Temp */ template Temp(const Average &s) - : node(new ScalarStatNode(s.statData())) { } + : node(new ScalarStatNode(s.statData())) + { } /** * Create a new VectorStatNode. @@ -2775,13 +2886,15 @@ class Temp */ template Temp(const Vector &s) - : node(new VectorStatNode(s.statData())) { } + : node(new VectorStatNode(s.statData())) + { } /** * */ Temp(const Formula &f) - : node(new FormulaNode(f)) { } + : node(new FormulaNode(f)) + { } /** * Create a new ScalarProxyNode. @@ -2789,91 +2902,104 @@ class Temp */ template Temp(const ScalarProxy &p) - : node(new ScalarProxyNode(p)) { } + : node(new ScalarProxyNode(p)) + { } /** * Create a ConstNode * @param value The value of the const node. */ Temp(signed char value) - : node(new ConstNode(value)) {} + : node(new ConstNode(value)) + { } /** * Create a ConstNode * @param value The value of the const node. */ Temp(unsigned char value) - : node(new ConstNode(value)) {} + : node(new ConstNode(value)) + { } /** * Create a ConstNode * @param value The value of the const node. */ Temp(signed short value) - : node(new ConstNode(value)) {} + : node(new ConstNode(value)) + { } /** * Create a ConstNode * @param value The value of the const node. */ Temp(unsigned short value) - : node(new ConstNode(value)) {} + : node(new ConstNode(value)) + { } /** * Create a ConstNode * @param value The value of the const node. */ Temp(signed int value) - : node(new ConstNode(value)) {} + : node(new ConstNode(value)) + { } /** * Create a ConstNode * @param value The value of the const node. */ Temp(unsigned int value) - : node(new ConstNode(value)) {} + : node(new ConstNode(value)) + { } /** * Create a ConstNode * @param value The value of the const node. */ Temp(signed long value) - : node(new ConstNode(value)) {} + : node(new ConstNode(value)) + { } /** * Create a ConstNode * @param value The value of the const node. */ Temp(unsigned long value) - : node(new ConstNode(value)) {} + : node(new ConstNode(value)) + { } /** * Create a ConstNode * @param value The value of the const node. */ Temp(signed long long value) - : node(new ConstNode(value)) {} + : node(new ConstNode(value)) + { } /** * Create a ConstNode * @param value The value of the const node. */ Temp(unsigned long long value) - : node(new ConstNode(value)) {} + : node(new ConstNode(value)) + { } /** * Create a ConstNode * @param value The value of the const node. */ Temp(float value) - : node(new ConstNode(value)) {} + : node(new ConstNode(value)) + { } /** * Create a ConstNode * @param value The value of the const node. */ Temp(double value) - : node(new ConstNode(value)) {} + : node(new ConstNode(value)) + { } }; diff --git a/src/base/stats/events.cc b/src/base/stats/events.cc index dc56fe75f..dcf52e6d8 100644 --- a/src/base/stats/events.cc +++ b/src/base/stats/events.cc @@ -38,7 +38,7 @@ using namespace std; namespace Stats { -Tick EventStart = ULL(0x7fffffffffffffff); +Tick EventStart = MaxTick; extern list OutputList; diff --git a/src/base/stats/flags.hh b/src/base/stats/flags.hh index b8b0171ed..77eedaee8 100644 --- a/src/base/stats/flags.hh +++ b/src/base/stats/flags.hh @@ -30,6 +30,7 @@ #ifndef __BASE_STATS_FLAGS_HH__ #define __BASE_STATS_FLAGS_HH__ + namespace Stats { /** diff --git a/src/base/stats/mysql.cc b/src/base/stats/mysql.cc index ee15d4231..c3498dc60 100644 --- a/src/base/stats/mysql.cc +++ b/src/base/stats/mysql.cc @@ -930,7 +930,7 @@ MySql::visit(const FormulaData &data) bool initMySQL(string host, string user, string password, string database, - string project, string name, string sample) + string project, string name, string sample) { extern list OutputList; static MySql mysql; diff --git a/src/base/stats/mysql.hh b/src/base/stats/mysql.hh index 0ce381c2f..5caac69de 100644 --- a/src/base/stats/mysql.hh +++ b/src/base/stats/mysql.hh @@ -127,13 +127,15 @@ class MySql : public Output protected: std::map idmap; - void insert(int sim_id, int db_id) + void + insert(int sim_id, int db_id) { using namespace std; idmap.insert(make_pair(sim_id, db_id)); } - int find(int sim_id) + int + find(int sim_id) { using namespace std; map::const_iterator i = idmap.find(sim_id); @@ -146,9 +148,9 @@ class MySql : public Output ~MySql(); void connect(const std::string &host, const std::string &user, - const std::string &passwd, const std::string &db, - const std::string &name, const std::string &sample, - const std::string &project); + const std::string &passwd, const std::string &db, + const std::string &name, const std::string &sample, + const std::string &project); bool connected() const; public: @@ -188,14 +190,14 @@ class MySql : public Output }; bool initMySQL(std::string host, std::string database, std::string user, - std::string passwd, std::string project, std::string name, - std::string sample); + std::string passwd, std::string project, std::string name, + std::string sample); #if !USE_MYSQL inline bool initMySQL(std::string host, std::string user, std::string password, - std::string database, std::string project, std::string name, - std::string sample) + std::string database, std::string project, std::string name, + std::string sample) { return false; } diff --git a/src/base/stats/mysql_run.hh b/src/base/stats/mysql_run.hh index 487224551..7c606370e 100644 --- a/src/base/stats/mysql_run.hh +++ b/src/base/stats/mysql_run.hh @@ -46,7 +46,7 @@ struct MySqlRun protected: void setup(const std::string &name, const std::string &sample, - const std::string &user, const std::string &project); + const std::string &user, const std::string &project); void remove(const std::string &name); void cleanup(); @@ -54,9 +54,9 @@ struct MySqlRun public: bool connected() const { return mysql.connected(); } void connect(const std::string &host, const std::string &user, - const std::string &passwd, const std::string &db, - const std::string &name, const std::string &sample, - const std::string &project); + const std::string &passwd, const std::string &db, + const std::string &name, const std::string &sample, + const std::string &project); MySQL::Connection &conn() { return mysql; } uint16_t run() const { return run_id; } diff --git a/src/base/stats/statdb.cc b/src/base/stats/statdb.cc index f9136807a..c54dbb8ec 100644 --- a/src/base/stats/statdb.cc +++ b/src/base/stats/statdb.cc @@ -73,7 +73,8 @@ regPrint(void *stat) data->flags |= print; } -TheDatabase &db() +TheDatabase & +db() { static TheDatabase db; return db; diff --git a/src/base/stats/text.cc b/src/base/stats/text.cc index f65b77777..a39bfe242 100644 --- a/src/base/stats/text.cc +++ b/src/base/stats/text.cc @@ -447,7 +447,6 @@ DistPrint::operator()(ostream &stream) const print(stream); } - if (!compat) { for (int i = 0; i < size; ++i) { stringstream namestr; @@ -467,7 +466,6 @@ DistPrint::operator()(ostream &stream) const } print(stream); } - } else { Counter _min; Result _pdf; @@ -633,7 +631,8 @@ Text::visit(const Vector2dData &data) super_total += yvec[j]; } - print.name = data.name + "_" + (havesub ? data.subnames[i] : to_string(i)); + print.name = data.name + "_" + + (havesub ? data.subnames[i] : to_string(i)); print.desc = data.desc; print.vec = yvec; print.total = total; @@ -693,8 +692,8 @@ Text::visit(const VectorDistData &data) for (int i = 0; i < data.size(); ++i) { DistPrint print; - print.name = data.name + - (data.subnames[i].empty() ? ("_" + to_string(i)) : data.subnames[i]); + print.name = data.name + "_" + + (data.subnames[i].empty() ? (to_string(i)) : data.subnames[i]); print.desc = data.subdescs[i].empty() ? data.desc : data.subdescs[i]; print.flags = data.flags; print.compat = compat; @@ -748,5 +747,4 @@ initText(const string &filename, bool desc, bool compat) return true; } - /* namespace Stats */ } diff --git a/src/base/stats/types.hh b/src/base/stats/types.hh index b64e8fb17..1ae29afbd 100644 --- a/src/base/stats/types.hh +++ b/src/base/stats/types.hh @@ -32,6 +32,7 @@ #define __BASE_STATS_TYPES_HH__ #include + #include "sim/host.hh" namespace Stats { -- cgit v1.2.3 From 7cc2a88038ccfd828a0caa7aa9d1b758d096d37d Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 9 Oct 2008 04:58:23 -0700 Subject: stats: use properly signed types for looping and comparison --- src/base/statistics.cc | 10 +- src/base/statistics.hh | 251 ++++++++++++++++++++++++------------------------ src/base/stats/mysql.cc | 26 ++--- src/base/stats/mysql.hh | 8 +- src/base/stats/text.cc | 38 ++++---- src/base/stats/types.hh | 3 + 6 files changed, 170 insertions(+), 166 deletions(-) (limited to 'src') diff --git a/src/base/statistics.cc b/src/base/statistics.cc index 2acef83c5..cf2e6d4e7 100644 --- a/src/base/statistics.cc +++ b/src/base/statistics.cc @@ -117,8 +117,8 @@ StatData::less(StatData *stat1, StatData *stat2) tokenize(v1, name1, '.'); tokenize(v2, name2, '.'); - int last = min(v1.size(), v2.size()) - 1; - for (int i = 0; i < last; ++i) + size_type last = min(v1.size(), v2.size()) - 1; + for (off_type i = 0; i < last; ++i) if (v1[i] != v2[i]) return v1[i] < v2[i]; @@ -164,7 +164,7 @@ FormulaBase::total() const return root ? root->total() : 0.0; } -size_t +size_type FormulaBase::size() const { if (!root) @@ -183,7 +183,7 @@ FormulaBase::zero() const { VResult vec; result(vec); - for (int i = 0; i < vec.size(); ++i) + for (off_t i = 0; i < vec.size(); ++i) if (vec[i] != 0.0) return false; return true; @@ -244,7 +244,7 @@ check() panic("stat check failed for %s\n", data->name); } - int j = 0; + off_t j = 0; for (i = Database::stats().begin(); i != end; ++i) { StatData *data = *i; if (!(data->flags & print)) diff --git a/src/base/statistics.hh b/src/base/statistics.hh index 05daeed0f..d50302d49 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -173,7 +173,7 @@ struct VectorData : public StatData mutable std::vector subnames; mutable std::vector subdescs; - virtual size_t size() const = 0; + virtual size_type size() const = 0; virtual const VCounter &value() const = 0; virtual const VResult &result() const = 0; virtual Result total() const = 0; @@ -182,7 +182,7 @@ struct VectorData : public StatData update() { if (!subnames.empty()) { - int s = size(); + size_type s = size(); if (subnames.size() < s) subnames.resize(s); @@ -207,7 +207,7 @@ class VectorStatData : public VectorData virtual bool zero() const { return s.zero(); } virtual void reset() { s.reset(); } - virtual size_t size() const { return s.size(); } + virtual size_type size() const { return s.size(); } virtual VCounter & value() const @@ -248,7 +248,7 @@ struct DistDataData Counter min; Counter max; Counter bucket_size; - int size; + size_type size; bool fancy; }; @@ -290,12 +290,12 @@ struct VectorDistData : public StatData /** Local storage for the entry values, used for printing. */ mutable VResult rvec; - virtual size_t size() const = 0; + virtual size_type size() const = 0; void update() { - int s = size(); + size_type s = size(); if (subnames.size() < s) subnames.resize(s); @@ -315,7 +315,7 @@ class VectorDistStatData : public VectorDistData virtual bool check() const { return s.check(); } virtual void reset() { s.reset(); } - virtual size_t size() const { return s.size(); } + virtual size_type size() const { return s.size(); } virtual bool zero() const { return s.zero(); } virtual void @@ -336,8 +336,8 @@ struct Vector2dData : public StatData /** Local storage for the entry values, used for printing. */ mutable VCounter cvec; - mutable int x; - mutable int y; + mutable size_type x; + mutable size_type y; void update() @@ -506,7 +506,7 @@ class WrapVec : public Wrap * @return A reference to this stat. */ Parent & - subname(int index, const std::string &name) + subname(off_type index, const std::string &name) { std::vector &subn = this->statData()->subnames; if (subn.size() <= index) @@ -523,7 +523,7 @@ class WrapVec : public Wrap * @return A reference to this stat. */ Parent & - subdesc(int index, const std::string &desc) + subdesc(off_type index, const std::string &desc) { std::vector &subd = this->statData()->subdescs; if (subd.size() <= index) @@ -548,13 +548,13 @@ class WrapVec2d : public WrapVec { Data *data = this->statData(); data->y_subnames.resize(this->y); - for (int i = 0; i < this->y; ++i) + for (off_type i = 0; i < this->y; ++i) data->y_subnames[i] = names[i]; return this->self(); } Parent & - ysubname(int index, const std::string subname) + ysubname(off_type index, const std::string subname) { Data *data = this->statData(); assert(index < this->y); @@ -832,7 +832,7 @@ class ScalarBase : public DataAccess * Return the number of elements, always 1 for a scalar. * @return 1. */ - size_t size() const { return 1; } + size_type size() const { return 1; } bool check() const { return true; } @@ -856,7 +856,7 @@ class ProxyData : public ScalarData public: virtual void visit(Visit &visitor) { visitor.visit(*this); } virtual std::string str() const { return to_string(value()); } - virtual size_t size() const { return 1; } + virtual size_type size() const { return 1; } virtual bool zero() const { return value() == 0; } virtual bool check() const { return true; } virtual void reset() { } @@ -916,7 +916,7 @@ class ValueBase : public DataAccess Counter value() { return proxy->value(); } Result result() const { return proxy->result(); } Result total() const { return proxy->total(); }; - size_t size() const { return proxy->size(); } + size_type size() const { return proxy->size(); } std::string str() const { return proxy->str(); } bool zero() const { return proxy->zero(); } @@ -942,7 +942,7 @@ class ScalarProxy Stat *stat; /** The index to access in the parent VectorBase. */ - int index; + off_type index; public: /** @@ -963,7 +963,7 @@ class ScalarProxy * @param p The params to use. * @param i The index to access. */ - ScalarProxy(Stat *s, int i) + ScalarProxy(Stat *s, off_type i) : stat(s), index(i) { assert(stat); @@ -1047,7 +1047,7 @@ class ScalarProxy * Return the number of elements, always 1 for a scalar. * @return 1. */ - size_t size() const { return 1; } + size_type size() const { return 1; } /** * This stat has no state. Nothing to reset @@ -1083,7 +1083,7 @@ class VectorBase : public DataAccess protected: /** The storage of this stat. */ Storage *storage; - size_t _size; + size_type _size; /** The parameters for this stat. */ Params params; @@ -1094,17 +1094,17 @@ class VectorBase : public DataAccess * @param index The vector index to access. * @return The storage object at the given index. */ - Storage *data(int index) { return &storage[index]; } + Storage *data(off_type index) { return &storage[index]; } /** * Retrieve a const pointer to the storage. * @param index The vector index to access. * @return A const pointer to the storage object at the given index. */ - const Storage *data(int index) const { return &storage[index]; } + const Storage *data(off_type index) const { return &storage[index]; } void - doInit(int s) + doInit(size_type s) { assert(s > 0 && "size must be positive!"); assert(!storage && "already initialized"); @@ -1113,7 +1113,7 @@ class VectorBase : public DataAccess char *ptr = new char[_size * sizeof(Storage)]; storage = reinterpret_cast(ptr); - for (int i = 0; i < _size; ++i) + for (off_type i = 0; i < _size; ++i) new (&storage[i]) Storage(params); setInit(); @@ -1124,7 +1124,7 @@ class VectorBase : public DataAccess value(VCounter &vec) const { vec.resize(size()); - for (int i = 0; i < size(); ++i) + for (off_type i = 0; i < size(); ++i) vec[i] = data(i)->value(params); } @@ -1136,7 +1136,7 @@ class VectorBase : public DataAccess result(VResult &vec) const { vec.resize(size()); - for (int i = 0; i < size(); ++i) + for (off_type i = 0; i < size(); ++i) vec[i] = data(i)->result(params); } @@ -1148,7 +1148,7 @@ class VectorBase : public DataAccess total() const { Result total = 0.0; - for (int i = 0; i < size(); ++i) + for (off_type i = 0; i < size(); ++i) total += data(i)->result(params); return total; } @@ -1156,12 +1156,12 @@ class VectorBase : public DataAccess /** * @return the number of elements in this vector. */ - size_t size() const { return _size; } + size_type size() const { return _size; } bool zero() const { - for (int i = 0; i < size(); ++i) + for (off_type i = 0; i < size(); ++i) if (data(i)->zero()) return false; return true; @@ -1176,7 +1176,7 @@ class VectorBase : public DataAccess void reset() { - for (int i = 0; i < size(); ++i) + for (off_type i = 0; i < size(); ++i) data(i)->reset(); } @@ -1190,7 +1190,7 @@ class VectorBase : public DataAccess if (!storage) return; - for (int i = 0; i < _size; ++i) + for (off_type i = 0; i < _size; ++i) data(i)->~Storage(); delete [] reinterpret_cast(storage); } @@ -1201,7 +1201,7 @@ class VectorBase : public DataAccess * @return A reference of the stat. */ Proxy - operator[](int index) + operator[](off_type index) { assert (index >= 0 && index < size()); return Proxy(this, index); @@ -1215,21 +1215,21 @@ class VectorProxy { private: Stat *stat; - int offset; - int len; + off_type offset; + size_type len; private: mutable VResult vec; typename Stat::Storage * - data(int index) + data(off_type index) { assert(index < len); return stat->data(offset + index); } const typename Stat::Storage * - data(int index) const + data(off_type index) const { assert(index < len); return const_cast(stat)->data(offset + index); @@ -1241,7 +1241,7 @@ class VectorProxy { vec.resize(size()); - for (int i = 0; i < size(); ++i) + for (off_type i = 0; i < size(); ++i) vec[i] = data(i)->result(stat->params); return vec; @@ -1251,13 +1251,13 @@ class VectorProxy total() const { Result total = 0; - for (int i = 0; i < size(); ++i) + for (off_type i = 0; i < size(); ++i) total += data(i)->result(stat->params); return total; } public: - VectorProxy(Stat *s, int o, int l) + VectorProxy(Stat *s, off_type o, size_type l) : stat(s), offset(o), len(l) { } @@ -1277,13 +1277,13 @@ class VectorProxy } ScalarProxy - operator[](int index) + operator[](off_type index) { assert (index >= 0 && index < size()); return ScalarProxy(stat, offset + index); } - size_t size() const { return len; } + size_type size() const { return len; } /** * This stat has no state. Nothing to reset. @@ -1302,18 +1302,18 @@ class Vector2dBase : public DataAccess friend class VectorProxy >; protected: - size_t x; - size_t y; - size_t _size; + size_type x; + size_type y; + size_type _size; Storage *storage; Params params; protected: - Storage *data(int index) { return &storage[index]; } - const Storage *data(int index) const { return &storage[index]; } + Storage *data(off_type index) { return &storage[index]; } + const Storage *data(off_type index) const { return &storage[index]; } void - doInit(int _x, int _y) + doInit(size_type _x, size_type _y) { assert(_x > 0 && _y > 0 && "sizes must be positive!"); assert(!storage && "already initialized"); @@ -1329,7 +1329,7 @@ class Vector2dBase : public DataAccess char *ptr = new char[_size * sizeof(Storage)]; storage = reinterpret_cast(ptr); - for (int i = 0; i < _size; ++i) + for (off_type i = 0; i < _size; ++i) new (&storage[i]) Storage(params); setInit(); @@ -1345,7 +1345,7 @@ class Vector2dBase : public DataAccess if (!storage) return; - for (int i = 0; i < _size; ++i) + for (off_type i = 0; i < _size; ++i) data(i)->~Storage(); delete [] reinterpret_cast(storage); } @@ -1353,24 +1353,24 @@ class Vector2dBase : public DataAccess void update(Vector2dData *newdata) { - int size = this->size(); + size_type size = this->size(); newdata->cvec.resize(size); - for (int i = 0; i < size; ++i) + for (off_type i = 0; i < size; ++i) newdata->cvec[i] = data(i)->value(params); } - std::string ysubname(int i) const { return (*this->y_subnames)[i]; } + std::string ysubname(off_type i) const { return (*this->y_subnames)[i]; } Proxy - operator[](int index) + operator[](off_type index) { - int offset = index * y; + off_type offset = index * y; assert (index >= 0 && offset + index < size()); return Proxy(this, offset, y); } - size_t + size_type size() const { return _size; @@ -1381,7 +1381,7 @@ class Vector2dBase : public DataAccess { return data(0)->zero(); #if 0 - for (int i = 0; i < size(); ++i) + for (off_type i = 0; i < size(); ++i) if (!data(i)->zero()) return false; return true; @@ -1394,7 +1394,7 @@ class Vector2dBase : public DataAccess void reset() { - for (int i = 0; i < size(); ++i) + for (off_type i = 0; i < size(); ++i) data(i)->reset(); } @@ -1427,7 +1427,7 @@ struct DistStor /** The number of entries in each bucket. */ Counter bucket_size; /** The number of buckets. Equal to (max-min)/bucket_size. */ - int size; + size_type size; }; enum { fancy = false }; @@ -1470,7 +1470,8 @@ struct DistStor else if (val > params.max) overflow += number; else { - size_t index = std::floor((val - params.min) / params.bucket_size); + size_type index = + (size_type)std::floor((val - params.min) / params.bucket_size); assert(index < size(params)); cvec[index] += number; } @@ -1492,7 +1493,7 @@ struct DistStor * @return the number of buckets. * @todo Is it faster to return the size from the parameters? */ - size_t size(const Params &) const { return cvec.size(); } + size_type size(const Params &) const { return cvec.size(); } /** * Returns true if any calls to sample have been made. @@ -1518,7 +1519,7 @@ struct DistStor data->underflow = underflow; data->overflow = overflow; data->cvec.resize(params.size); - for (int i = 0; i < params.size; ++i) + for (off_type i = 0; i < params.size; ++i) data->cvec[i] = cvec[i]; data->sum = sum; @@ -1537,8 +1538,8 @@ struct DistStor underflow = 0; overflow = 0; - int size = cvec.size(); - for (int i = 0; i < size; ++i) + size_type size = cvec.size(); + for (off_type i = 0; i < size; ++i) cvec[i] = Counter(); sum = Counter(); @@ -1605,7 +1606,7 @@ struct FancyStor * Return the number of entries in this stat, 1 * @return 1. */ - size_t size(const Params &) const { return 1; } + size_type size(const Params &) const { return 1; } /** * Return true if no samples have been added. @@ -1675,7 +1676,7 @@ struct AvgFancy * Return the number of entries, in this case 1. * @return 1. */ - size_t size(const Params ¶ms) const { return 1; } + size_type size(const Params ¶ms) const { return 1; } /** * Return true if no samples have been added. @@ -1757,7 +1758,7 @@ class DistBase : public DataAccess * Return the number of entries in this stat. * @return The number of entries. */ - size_t size() const { return data()->size(params); } + size_type size() const { return data()->size(params); } /** * Return true if no samples have been added. * @return True if there haven't been any samples. @@ -1801,24 +1802,24 @@ class VectorDistBase : public DataAccess protected: Storage *storage; - size_t _size; + size_type _size; Params params; protected: Storage * - data(int index) + data(off_type index) { return &storage[index]; } const Storage * - data(int index) const + data(off_type index) const { return &storage[index]; } void - doInit(int s) + doInit(size_type s) { assert(s > 0 && "size must be positive!"); assert(!storage && "already initialized"); @@ -1827,7 +1828,7 @@ class VectorDistBase : public DataAccess char *ptr = new char[_size * sizeof(Storage)]; storage = reinterpret_cast(ptr); - for (int i = 0; i < _size; ++i) + for (off_type i = 0; i < _size; ++i) new (&storage[i]) Storage(params); setInit(); @@ -1843,14 +1844,14 @@ class VectorDistBase : public DataAccess if (!storage) return ; - for (int i = 0; i < _size; ++i) + for (off_type i = 0; i < _size; ++i) data(i)->~Storage(); delete [] reinterpret_cast(storage); } - Proxy operator[](int index); + Proxy operator[](off_type index); - size_t + size_type size() const { return _size; @@ -1861,7 +1862,7 @@ class VectorDistBase : public DataAccess { return false; #if 0 - for (int i = 0; i < size(); ++i) + for (off_type i = 0; i < size(); ++i) if (!data(i)->zero(params)) return false; return true; @@ -1874,7 +1875,7 @@ class VectorDistBase : public DataAccess void reset() { - for (int i = 0; i < size(); ++i) + for (off_type i = 0; i < size(); ++i) data(i)->reset(); } @@ -1887,9 +1888,9 @@ class VectorDistBase : public DataAccess void update(VectorDistData *base) { - int size = this->size(); + size_type size = this->size(); base->data.resize(size); - for (int i = 0; i < size; ++i) { + for (off_type i = 0; i < size; ++i) { base->data[i].fancy = Storage::fancy; data(i)->update(&(base->data[i]), params); } @@ -1901,14 +1902,14 @@ class DistProxy { private: Stat *stat; - int index; + off_type index; protected: typename Stat::Storage *data() { return stat->data(index); } const typename Stat::Storage *data() const { return stat->data(index); } public: - DistProxy(Stat *s, int i) + DistProxy(Stat *s, off_type i) : stat(s), index(i) {} @@ -1932,7 +1933,7 @@ class DistProxy data()->sample(v, n, stat->params); } - size_t + size_type size() const { return 1; @@ -1952,7 +1953,7 @@ class DistProxy template inline typename VectorDistBase::Proxy -VectorDistBase::operator[](int index) +VectorDistBase::operator[](off_type index) { assert (index >= 0 && index < size()); return typename VectorDistBase::Proxy(this, index); @@ -1961,10 +1962,10 @@ VectorDistBase::operator[](int index) #if 0 template Result -VectorDistBase::total(int index) const +VectorDistBase::total(off_type index) const { - int total = 0; - for (int i = 0; i < x_size(); ++i) + Result total = 0; + for (off_type i = 0; i < x_size(); ++i) total += data(i)->result(stat->params); } #endif @@ -1986,7 +1987,7 @@ class Node : public RefCounted * Return the number of nodes in the subtree starting at this node. * @return the number of nodes in this subtree. */ - virtual size_t size() const = 0; + virtual size_type size() const = 0; /** * Return the result vector of this subtree. * @return The result vector of this subtree. @@ -2025,7 +2026,7 @@ class ScalarStatNode : public Node virtual Result total() const { return data->result(); }; - virtual size_t size() const { return 1; } + virtual size_type size() const { return 1; } /** * @@ -2058,7 +2059,7 @@ class ScalarProxyNode : public Node return proxy.result(); } - virtual size_t + virtual size_type size() const { return 1; @@ -2084,7 +2085,7 @@ class VectorStatNode : public Node virtual const VResult &result() const { return data->result(); } virtual Result total() const { return data->total(); }; - virtual size_t size() const { return data->size(); } + virtual size_type size() const { return data->size(); } virtual std::string str() const { return data->name; } }; @@ -2099,7 +2100,7 @@ class ConstNode : public Node ConstNode(T s) : vresult(1, (Result)s) {} const VResult &result() const { return vresult; } virtual Result total() const { return vresult[0]; }; - virtual size_t size() const { return 1; } + virtual size_type size() const { return 1; } virtual std::string str() const { return to_string(vresult[0]); } }; @@ -2116,20 +2117,20 @@ class ConstVectorNode : public Node virtual Result total() const { - int size = this->size(); + size_type size = this->size(); Result tmp = 0; - for (int i = 0; i < size; i++) + for (off_type i = 0; i < size; i++) tmp += vresult[i]; return tmp; } - virtual size_t size() const { return vresult.size(); } + virtual size_type size() const { return vresult.size(); } virtual std::string str() const { - int size = this->size(); + size_type size = this->size(); std::string tmp = "("; - for (int i = 0; i < size; i++) + for (off_type i = 0; i < size; i++) tmp += csprintf("%s ",to_string(vresult[i])); tmp += ")"; return tmp; @@ -2189,13 +2190,13 @@ class UnaryNode : public Node result() const { const VResult &lvec = l->result(); - int size = lvec.size(); + size_type size = lvec.size(); assert(size > 0); vresult.resize(size); Op op; - for (int i = 0; i < size; ++i) + for (off_type i = 0; i < size; ++i) vresult[i] = op(lvec[i]); return vresult; @@ -2206,12 +2207,12 @@ class UnaryNode : public Node { const VResult &vec = this->result(); Result total = 0; - for (int i = 0; i < size(); i++) + for (off_type i = 0; i < size(); i++) total += vec[i]; return total; } - virtual size_t size() const { return l->size(); } + virtual size_type size() const { return l->size(); } virtual std::string str() const @@ -2244,19 +2245,19 @@ class BinaryNode : public Node vresult.resize(1); vresult[0] = op(lvec[0], rvec[0]); } else if (lvec.size() == 1) { - int size = rvec.size(); + size_type size = rvec.size(); vresult.resize(size); - for (int i = 0; i < size; ++i) + for (off_type i = 0; i < size; ++i) vresult[i] = op(lvec[0], rvec[i]); } else if (rvec.size() == 1) { - int size = lvec.size(); + size_type size = lvec.size(); vresult.resize(size); - for (int i = 0; i < size; ++i) + for (off_type i = 0; i < size; ++i) vresult[i] = op(lvec[i], rvec[0]); } else if (rvec.size() == lvec.size()) { - int size = rvec.size(); + size_type size = rvec.size(); vresult.resize(size); - for (int i = 0; i < size; ++i) + for (off_type i = 0; i < size; ++i) vresult[i] = op(lvec[i], rvec[i]); } @@ -2268,16 +2269,16 @@ class BinaryNode : public Node { const VResult &vec = this->result(); Result total = 0; - for (int i = 0; i < size(); i++) + for (off_type i = 0; i < size(); i++) total += vec[i]; return total; } - virtual size_t + virtual size_type size() const { - int ls = l->size(); - int rs = r->size(); + size_type ls = l->size(); + size_type rs = r->size(); if (ls == 1) { return rs; } else if (rs == 1) { @@ -2309,13 +2310,13 @@ class SumNode : public Node result() const { const VResult &lvec = l->result(); - int size = lvec.size(); + size_type size = lvec.size(); assert(size > 0); vresult[0] = 0.0; Op op; - for (int i = 0; i < size; ++i) + for (off_type i = 0; i < size; ++i) vresult[0] = op(vresult[0], lvec[i]); return vresult; @@ -2325,19 +2326,19 @@ class SumNode : public Node total() const { const VResult &lvec = l->result(); - int size = lvec.size(); + size_type size = lvec.size(); assert(size > 0); Result vresult = 0.0; Op op; - for (int i = 0; i < size; ++i) + for (off_type i = 0; i < size; ++i) vresult = op(vresult, lvec[i]); return vresult; } - virtual size_t size() const { return 1; } + virtual size_type size() const { return 1; } virtual std::string str() const @@ -2452,7 +2453,7 @@ class Vector : public WrapVec, VectorBase, VectorStatData> * @return A reference to this stat. */ Vector & - init(size_t size) + init(size_type size) { this->doInit(size); return *this; @@ -2474,7 +2475,7 @@ class AverageVector * @return A reference to this stat. */ AverageVector & - init(size_t size) + init(size_type size) { this->doInit(size); return *this; @@ -2491,7 +2492,7 @@ class Vector2d { public: Vector2d & - init(size_t x, size_t y) + init(size_type x, size_type y) { this->doInit(x, y); return *this; @@ -2526,7 +2527,7 @@ class Distribution this->params.min = min; this->params.max = max; this->params.bucket_size = bkt; - this->params.size = (int)rint((max - min) / bkt + 1.0); + this->params.size = (size_type)rint((max - min) / bkt + 1.0); this->doInit(); return *this; } @@ -2606,12 +2607,12 @@ class VectorDistribution * @return A reference to this distribution. */ VectorDistribution & - init(int size, Counter min, Counter max, Counter bkt) + init(size_type size, Counter min, Counter max, Counter bkt) { this->params.min = min; this->params.max = max; this->params.bucket_size = bkt; - this->params.size = (int)rint((max - min) / bkt + 1.0); + this->params.size = rint((max - min) / bkt + 1.0); this->doInit(size); return *this; } @@ -2640,7 +2641,7 @@ class VectorStandardDeviation * @return A reference to this distribution. */ VectorStandardDeviation & - init(int size) + init(size_type size) { this->doInit(size); return *this; @@ -2670,7 +2671,7 @@ class VectorAverageDeviation * @return A reference to this distribution. */ VectorAverageDeviation & - init(int size) + init(size_type size) { this->doInit(size); return *this; @@ -2714,7 +2715,7 @@ class FormulaBase : public DataAccess /** * Return the number of elements in the tree. */ - size_t size() const; + size_type size() const; bool check() const { return true; } @@ -2757,7 +2758,7 @@ class FormulaStatData : public FormulaData virtual bool zero() const { return s.zero(); } virtual void reset() { s.reset(); } - virtual size_t size() const { return s.size(); } + virtual size_type size() const { return s.size(); } virtual const VResult & result() const @@ -2822,7 +2823,7 @@ class FormulaNode : public Node public: FormulaNode(const Formula &f) : formula(f) {} - virtual size_t size() const { return formula.size(); } + virtual size_type size() const { return formula.size(); } virtual const VResult &result() const { formula.result(vec); return vec; } virtual Result total() const { return formula.total(); } diff --git a/src/base/stats/mysql.cc b/src/base/stats/mysql.cc index c3498dc60..8d263d2b9 100644 --- a/src/base/stats/mysql.cc +++ b/src/base/stats/mysql.cc @@ -568,7 +568,7 @@ MySql::configure(const VectorData &data) InsertSubData subdata; subdata.stat = statid; subdata.y = 0; - for (int i = 0; i < data.subnames.size(); ++i) { + for (off_type i = 0; i < data.subnames.size(); ++i) { subdata.x = i; subdata.name = data.subnames[i]; subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i]; @@ -615,7 +615,7 @@ MySql::configure(const VectorDistData &data) InsertSubData subdata; subdata.stat = statid; subdata.y = 0; - for (int i = 0; i < data.subnames.size(); ++i) { + for (off_type i = 0; i < data.subnames.size(); ++i) { subdata.x = i; subdata.name = data.subnames[i]; subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i]; @@ -639,7 +639,7 @@ MySql::configure(const Vector2dData &data) InsertSubData subdata; subdata.stat = statid; subdata.y = -1; - for (int i = 0; i < data.subnames.size(); ++i) { + for (off_type i = 0; i < data.subnames.size(); ++i) { subdata.x = i; subdata.name = data.subnames[i]; subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i]; @@ -653,7 +653,7 @@ MySql::configure(const Vector2dData &data) subdata.stat = statid; subdata.x = -1; subdata.descr = ""; - for (int i = 0; i < data.y_subnames.size(); ++i) { + for (off_type i = 0; i < data.y_subnames.size(); ++i) { subdata.y = i; subdata.name = data.y_subnames[i]; if (!subdata.name.empty()) @@ -760,8 +760,8 @@ MySql::output(const VectorData &data) newdata.y = 0; const VCounter &cvec = data.value(); - int size = data.size(); - for (int x = 0; x < size; x++) { + size_type size = data.size(); + for (off_type x = 0; x < size; x++) { newdata.x = x; newdata.data = cvec[x]; newdata.insert(); @@ -808,8 +808,8 @@ MySql::output(const DistDataData &data) newdata.data = data.overflow; newdata.insert(); - int size = data.cvec.size(); - for (int x = 0; x < size; x++) { + size_type size = data.cvec.size(); + for (off_type x = 0; x < size; x++) { newdata.x = x; newdata.data = data.cvec[x]; newdata.insert(); @@ -837,8 +837,8 @@ MySql::output(const VectorDistData &data) newdata.stat = find(data.id); - int size = data.data.size(); - for (int y = 0; y < size; ++y) { + size_type size = data.data.size(); + for (off_type y = 0; y < size; ++y) { newdata.y = y; output(data.data[y]); } @@ -852,10 +852,10 @@ MySql::output(const Vector2dData &data) newdata.stat = find(data.id); - int index = 0; - for (int x = 0; x < data.x; x++) { + off_type index = 0; + for (off_type x = 0; x < data.x; x++) { newdata.x = x; - for (int y = 0; y < data.y; y++) { + for (off_type y = 0; y < data.y; y++) { newdata.y = y; newdata.data = data.cvec[index++]; newdata.insert(); diff --git a/src/base/stats/mysql.hh b/src/base/stats/mysql.hh index 5caac69de..6e47719ce 100644 --- a/src/base/stats/mysql.hh +++ b/src/base/stats/mysql.hh @@ -69,9 +69,9 @@ class InsertData { private: char *query; - int size; + size_type size; bool first; - static const int maxsize = 1024*1024; + static const size_type maxsize = 1024*1024; public: MySqlRun *run; @@ -95,9 +95,9 @@ class InsertEvent { private: char *query; - int size; + size_type size; bool first; - static const int maxsize = 1024*1024; + static const size_type maxsize = 1024*1024; typedef std::map event_map_t; event_map_t events; diff --git a/src/base/stats/text.cc b/src/base/stats/text.cc index a39bfe242..84336f5e4 100644 --- a/src/base/stats/text.cc +++ b/src/base/stats/text.cc @@ -239,11 +239,11 @@ struct VectorPrint void VectorPrint::operator()(std::ostream &stream) const { - int _size = vec.size(); + size_type _size = vec.size(); Result _total = 0.0; if (flags & (pdf | cdf)) { - for (int i = 0; i < _size; ++i) { + for (off_type i = 0; i < _size; ++i) { _total += vec[i]; } } @@ -266,7 +266,7 @@ VectorPrint::operator()(std::ostream &stream) const print.value = vec[0]; print(stream); } else if (!compat) { - for (int i = 0; i < _size; ++i) { + for (off_type i = 0; i < _size; ++i) { if (havesub && (i >= subnames.size() || subnames[i].empty())) continue; @@ -298,7 +298,7 @@ VectorPrint::operator()(std::ostream &stream) const Result _cdf = 0.0; if (flags & dist) { ccprintf(stream, "%s.start_dist\n", name); - for (int i = 0; i < _size; ++i) { + for (off_type i = 0; i < _size; ++i) { print.name = havesub ? subnames[i] : to_string(i); print.desc = subdescs.empty() ? desc : subdescs[i]; print.flags |= __substat; @@ -318,7 +318,7 @@ VectorPrint::operator()(std::ostream &stream) const } ccprintf(stream, "%s.end_dist\n", name); } else { - for (int i = 0; i < _size; ++i) { + for (off_type i = 0; i < _size; ++i) { if (havesub && subnames[i].empty()) continue; @@ -366,7 +366,7 @@ struct DistPrint Counter min; Counter max; Counter bucket_size; - int size; + size_type size; bool fancy; void operator()(ostream &stream) const; @@ -407,7 +407,7 @@ DistPrint::operator()(ostream &stream) const Result total = 0.0; total += underflow; - for (int i = 0; i < size; ++i) + for (off_type i = 0; i < size; ++i) total += vec[i]; total += overflow; @@ -448,7 +448,7 @@ DistPrint::operator()(ostream &stream) const } if (!compat) { - for (int i = 0; i < size; ++i) { + for (off_type i = 0; i < size; ++i) { stringstream namestr; namestr << name; @@ -473,7 +473,7 @@ DistPrint::operator()(ostream &stream) const print.flags = flags | __substat; - for (int i = 0; i < size; ++i) { + for (off_type i = 0; i < size; ++i) { if ((flags & nozero && vec[i] == 0.0) || (flags & nonan && isnan(vec[i]))) continue; @@ -560,7 +560,7 @@ Text::visit(const VectorData &data) if (noOutput(data)) return; - int size = data.size(); + size_type size = data.size(); VectorPrint print; print.name = data.name; @@ -573,11 +573,11 @@ Text::visit(const VectorData &data) print.total = data.total(); if (!data.subnames.empty()) { - for (int i = 0; i < size; ++i) { + for (off_type i = 0; i < size; ++i) { if (!data.subnames[i].empty()) { print.subnames = data.subnames; print.subnames.resize(size); - for (int i = 0; i < size; ++i) { + for (off_type i = 0; i < size; ++i) { if (!data.subnames[i].empty() && !data.subdescs[i].empty()) { print.subdescs = data.subdescs; @@ -609,22 +609,22 @@ Text::visit(const Vector2dData &data) print.precision = data.precision; if (!data.subnames.empty()) { - for (int i = 0; i < data.x; ++i) + for (off_type i = 0; i < data.x; ++i) if (!data.subnames[i].empty()) havesub = true; } VResult tot_vec(data.y); Result super_total = 0.0; - for (int i = 0; i < data.x; ++i) { + for (off_type i = 0; i < data.x; ++i) { if (havesub && (i >= data.subnames.size() || data.subnames[i].empty())) continue; - int iy = i * data.y; + off_type iy = i * data.y; VResult yvec(data.y); Result total = 0.0; - for (int j = 0; j < data.y; ++j) { + for (off_type j = 0; j < data.y; ++j) { yvec[j] = data.cvec[iy + j]; tot_vec[j] += yvec[j]; total += yvec[j]; @@ -668,7 +668,7 @@ Text::visit(const DistData &data) print.underflow = data.data.underflow; print.overflow = data.data.overflow; print.vec.resize(data.data.cvec.size()); - for (int i = 0; i < print.vec.size(); ++i) + for (off_type i = 0; i < print.vec.size(); ++i) print.vec[i] = (Result)data.data.cvec[i]; print.sum = data.data.sum; print.squares = data.data.squares; @@ -689,7 +689,7 @@ Text::visit(const VectorDistData &data) if (noOutput(data)) return; - for (int i = 0; i < data.size(); ++i) { + for (off_type i = 0; i < data.size(); ++i) { DistPrint print; print.name = data.name + "_" + @@ -705,7 +705,7 @@ Text::visit(const VectorDistData &data) print.underflow = data.data[i].underflow; print.overflow = data.data[i].overflow; print.vec.resize(data.data[i].cvec.size()); - for (int j = 0; j < print.vec.size(); ++j) + for (off_type j = 0; j < print.vec.size(); ++j) print.vec[j] = (Result)data.data[i].cvec[j]; print.sum = data.data[i].sum; print.squares = data.data[i].squares; diff --git a/src/base/stats/types.hh b/src/base/stats/types.hh index 1ae29afbd..6f56aec9a 100644 --- a/src/base/stats/types.hh +++ b/src/base/stats/types.hh @@ -47,6 +47,9 @@ typedef double Result; /** vector of results. */ typedef std::vector VResult; +typedef unsigned int size_type; +typedef unsigned int off_type; + /* namespace Stats */ } #endif // __BASE_STATS_TYPES_HH__ -- cgit v1.2.3 From 0b83563a9c7368ffdb82d70054ceda3cb7f3828f Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 9 Oct 2008 04:58:23 -0700 Subject: eventq: I'm sick of the warning about MaxTick being unused. --- src/sim/host.hh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src') diff --git a/src/sim/host.hh b/src/sim/host.hh index 518873ab3..dd29534fd 100644 --- a/src/sim/host.hh +++ b/src/sim/host.hh @@ -38,8 +38,6 @@ #define __HOST_HH__ #include -#include - /** uint64_t constant */ #define ULL(N) ((uint64_t)N##ULL) @@ -58,7 +56,7 @@ typedef int64_t Counter; */ typedef int64_t Tick; -const Tick MaxTick = std::numeric_limits::max(); +const Tick MaxTick = LL(0x7fffffffffffffff); /** * Address type -- cgit v1.2.3 From a589eb4053d9a902f9e9047830955963aec94e64 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 9 Oct 2008 04:58:23 -0700 Subject: SCons: add code to provide a libm5 shared library. Targets look like libm5_debug.so. This target can be dynamically linked into another C++ program and provide just about all of the M5 features. Additionally, this library is a standalone module that can be imported into python with an "import libm5_debug" type command line. --- src/SConscript | 63 ++++++++++++++++++++++++++++++++------------------------- src/sim/init.cc | 7 +++++++ 2 files changed, 43 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/SConscript b/src/SConscript index 6b2ea4d60..1b968ec90 100644 --- a/src/SConscript +++ b/src/SConscript @@ -934,21 +934,26 @@ envList = [] # Object nodes (including an extra one for date.cc). We explicitly # add the Object nodes so we can set up special dependencies for # date.cc. -def make_objs(sources, env): - objs = [env.Object(s) for s in sources] +def make_objs(sources, env, static): + if static: + XObject = env.StaticObject + else: + XObject = env.SharedObject + + objs = [ XObject(s) for s in sources ] # make date.cc depend on all other objects so it always gets # recompiled whenever anything else does - date_obj = env.Object('base/date.cc') + date_obj = XObject('base/date.cc') # Make the generation of program_info.cc dependend on all # the other cc files and the compiling of program_info.cc # dependent on all the objects but program_info.o - pinfo_obj = env.Object('base/program_info.cc') + pinfo_obj = XObject('base/program_info.cc') env.Depends('base/program_info.cc', sources) env.Depends(date_obj, objs) env.Depends(pinfo_obj, objs) - objs.extend([date_obj,pinfo_obj]) + objs.extend([date_obj, pinfo_obj]) return objs # Function to create a new build environment as clone of current @@ -956,46 +961,50 @@ def make_objs(sources, env): # binary. Additional keyword arguments are appended to corresponding # build environment vars. def makeEnv(label, objsfx, strip = False, **kwargs): - newEnv = env.Copy(OBJSUFFIX=objsfx) - newEnv.Label = label - newEnv.Append(**kwargs) + # SCons doesn't know to append a library suffix when there is a '.' in the + # name. Use '_' instead. + libname = 'm5_' + label + exename = 'm5.' + label + + new_env = env.Copy(OBJSUFFIX=objsfx, SHOBJSUFFIX=objsfx + 's') + new_env.Label = label + new_env.Append(**kwargs) - swig_env = newEnv.Copy() + swig_env = new_env.Copy() if env['GCC']: swig_env.Append(CCFLAGS='-Wno-uninitialized') swig_env.Append(CCFLAGS='-Wno-sign-compare') swig_env.Append(CCFLAGS='-Wno-parentheses') - swig_objs = [ swig_env.Object(s) for s in cc_swig_sources ] + + static_objs = make_objs(cc_lib_sources, new_env, static=True) + shared_objs = make_objs(cc_lib_sources, new_env, static=False) + static_objs += [ swig_env.StaticObject(s) for s in cc_swig_sources ] + shared_objs += [ swig_env.SharedObject(s) for s in cc_swig_sources ] # First make a library of everything but main() so other programs can # link against m5. - # - # SCons doesn't know to append a library suffix when there is a '.' in the - # name. Use '_' instead. - - m5lib = newEnv.Library('m5_' + label, - make_objs(cc_lib_sources, newEnv) + swig_objs) + static_lib = new_env.StaticLibrary(libname, static_objs + static_objs) + shared_lib = new_env.SharedLibrary(libname, shared_objs + shared_objs) for target, sources in unit_tests: - objs = [ newEnv.StaticObject(s) for s in sources ] - newEnv.Program("unittest/%s.%s" % (target, label), objs + m5lib) + objs = [ new_env.StaticObject(s) for s in sources ] + new_env.Program("unittest/%s.%s" % (target, label), objs + static_lib) - # Now link a stub with main() and the library. - exe = 'm5.' + label # final executable - objects = [newEnv.Object(s) for s in cc_bin_sources] + m5lib + # Now link a stub with main() and the static library. + objects = [new_env.Object(s) for s in cc_bin_sources] + static_lib if strip: - unstripped_exe = exe + '.unstripped' - newEnv.Program(unstripped_exe, objects) + unstripped_exe = exename + '.unstripped' + new_env.Program(unstripped_exe, objects) if sys.platform == 'sunos5': cmd = 'cp $SOURCE $TARGET; strip $TARGET' else: cmd = 'strip $SOURCE -o $TARGET' - targets = newEnv.Command(exe, unstripped_exe, cmd) + targets = new_env.Command(exename, unstripped_exe, cmd) else: - targets = newEnv.Program(exe, objects) + targets = new_env.Program(exename, objects) - newEnv.M5Binary = targets[0] - envList.append(newEnv) + new_env.M5Binary = targets[0] + envList.append(new_env) # Debug binary ccflags = {} diff --git a/src/sim/init.cc b/src/sim/init.cc index 804389dae..66eddfb6f 100644 --- a/src/sim/init.cc +++ b/src/sim/init.cc @@ -200,3 +200,10 @@ m5Main(int argc, char **argv) return 0; } + +PyMODINIT_FUNC +initm5(void) +{ + initM5Python(); + PyImport_ImportModule(PyCC("m5")); +} -- cgit v1.2.3 From eb89a23556a16958d9931b93f57b626f20af0ddd Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 9 Oct 2008 04:58:23 -0700 Subject: eventq: Don't use inline friend function when a static function will do. Another good reason to avoid this is that swig will try to wrap the friend, but it won't try to wrap a private static function. --- src/sim/eventq.cc | 16 ++++++++-------- src/sim/eventq.hh | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/sim/eventq.cc b/src/sim/eventq.cc index 4f0b51e08..78d6a458f 100644 --- a/src/sim/eventq.cc +++ b/src/sim/eventq.cc @@ -57,8 +57,8 @@ EventQueue mainEventQueue("MainEventQueue"); Counter Event::instanceCounter = 0; #endif -inline Event * -insertBefore(Event *event, Event *curr) +Event * +Event::insertBefore(Event *event, Event *curr) { // Either way, event will be the top element in the 'in bin' list // which is the pointer we need in order to look into the list, so @@ -83,7 +83,7 @@ EventQueue::insert(Event *event) { // Deal with the head case if (!head || *event <= *head) { - head = insertBefore(event, head); + head = Event::insertBefore(event, head); return; } @@ -98,11 +98,11 @@ EventQueue::insert(Event *event) // Note: this operation may render all nextBin pointers on the // prev 'in bin' list stale (except for the top one) - prev->nextBin = insertBefore(event, curr); + prev->nextBin = Event::insertBefore(event, curr); } -inline Event * -removeItem(Event *event, Event *top) +Event * +Event::removeItem(Event *event, Event *top) { Event *curr = top; Event *next = top->nextInBin; @@ -141,7 +141,7 @@ EventQueue::remove(Event *event) // deal with an event on the head's 'in bin' list (event has the same // time as the head) if (*head == *event) { - head = removeItem(event, head); + head = Event::removeItem(event, head); return; } @@ -159,7 +159,7 @@ EventQueue::remove(Event *event) // curr points to the top item of the the correct 'in bin' list, when // we remove an item, it returns the new top item (which may be // unchanged) - prev->nextBin = removeItem(event, curr); + prev->nextBin = Event::removeItem(event, curr); } Event * diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index 967e558db..e0194a742 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -87,8 +87,8 @@ class Event : public Serializable, public FastAlloc Event *nextBin; Event *nextInBin; - friend Event *insertBefore(Event *event, Event *curr); - friend Event *removeItem(Event *event, Event *last); + static Event *insertBefore(Event *event, Event *curr); + static Event *removeItem(Event *event, Event *last); /// queue to which this event belongs (though it may or may not be /// scheduled on this queue yet) -- cgit v1.2.3 From 886c5f8fe5011bf9a610d2bc3cb3bb010c592510 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 9 Oct 2008 04:58:23 -0700 Subject: SINIC: Commit old code from ASPLOS 2006 studies. NOTE: This code was written by Nathan Binkert in 2006 and is properly copyright "The Regents of the University of Michigan" --- src/dev/Ethernet.py | 3 + src/dev/sinic.cc | 226 ++++++++++++++++++++++++++++++++++++++-------------- src/dev/sinic.hh | 45 +++++++---- src/dev/sinicreg.hh | 89 ++++++++++++--------- 4 files changed, 252 insertions(+), 111 deletions(-) (limited to 'src') diff --git a/src/dev/Ethernet.py b/src/dev/Ethernet.py index 01384b32b..cf513b834 100644 --- a/src/dev/Ethernet.py +++ b/src/dev/Ethernet.py @@ -171,6 +171,9 @@ class Sinic(EtherDevBase): tx_fifo_high_mark = Param.MemorySize('384kB', "tx fifo high threshold") tx_fifo_threshold = Param.MemorySize('128kB', "tx fifo low threshold") virtual_count = Param.UInt32(1, "Virtualized SINIC") + zero_copy_size = Param.UInt32(64, "Bytes to copy if below threshold") + zero_copy_threshold = Param.UInt32(256, + "Only zero copy above this threshold") zero_copy = Param.Bool(False, "Zero copy receive") delay_copy = Param.Bool(False, "Delayed copy transmit") virtual_addr = Param.Bool(False, "Virtual addressing") diff --git a/src/dev/sinic.cc b/src/dev/sinic.cc index e875a8bcc..1fa8095d3 100644 --- a/src/dev/sinic.cc +++ b/src/dev/sinic.cc @@ -45,6 +45,7 @@ #include "sim/host.hh" #include "sim/stats.hh" +using namespace std; using namespace Net; using namespace TheISA; @@ -265,6 +266,35 @@ Device::regStats() totPackets = txPackets + rxPackets; txPacketRate = txPackets / simSeconds; rxPacketRate = rxPackets / simSeconds; + + _maxVnicDistance = 0; + + maxVnicDistance + .name(name() + ".maxVnicDistance") + .desc("maximum vnic distance") + ; + + totalVnicDistance + .name(name() + ".totalVnicDistance") + .desc("total vnic distance") + ; + numVnicDistance + .name(name() + ".numVnicDistance") + .desc("number of vnic distance measurements") + ; + + avgVnicDistance + .name(name() + ".avgVnicDistance") + .desc("average vnic distance") + ; + + avgVnicDistance = totalVnicDistance / numVnicDistance; +} + +void +Device::resetStats() +{ + _maxVnicDistance = 0; } EtherInt* @@ -289,6 +319,10 @@ Device::prepareIO(int cpu, int index) index, size); } +//add stats for head of line blocking +//add stats for average fifo length +//add stats for average number of vnics busy + void Device::prepareRead(int cpu, int index) { @@ -301,7 +335,7 @@ Device::prepareRead(int cpu, int index) uint64_t rxdone = vnic.RxDone; rxdone = set_RxDone_Packets(rxdone, rxFifo.countPacketsAfter(rxFifoPtr)); rxdone = set_RxDone_Empty(rxdone, rxFifo.empty()); - rxdone = set_RxDone_High(rxdone, rxFifo.size() > regs.RxFifoMark); + rxdone = set_RxDone_High(rxdone, rxFifo.size() > regs.RxFifoHigh); rxdone = set_RxDone_NotHigh(rxdone, rxLow); regs.RxData = vnic.RxData; regs.RxDone = rxdone; @@ -311,10 +345,23 @@ Device::prepareRead(int cpu, int index) uint64_t txdone = vnic.TxDone; txdone = set_TxDone_Packets(txdone, txFifo.packets()); txdone = set_TxDone_Full(txdone, txFifo.avail() < regs.TxMaxCopy); - txdone = set_TxDone_Low(txdone, txFifo.size() < regs.TxFifoMark); + txdone = set_TxDone_Low(txdone, txFifo.size() < regs.TxFifoLow); regs.TxData = vnic.TxData; regs.TxDone = txdone; regs.TxWait = txdone; + + int head = 0xffff; + + if (!rxFifo.empty()) { + int vnic = rxFifo.begin()->priv; + if (vnic != -1 && virtualRegs[vnic].rxPacketOffset > 0) + head = vnic; + } + + regs.RxStatus = set_RxStatus_Head(regs.RxStatus, head); + regs.RxStatus = set_RxStatus_Busy(regs.RxStatus, rxBusyCount); + regs.RxStatus = set_RxStatus_Mapped(regs.RxStatus, rxMappedCount); + regs.RxStatus = set_RxStatus_Dirty(regs.RxStatus, rxDirtyCount); } void @@ -473,22 +520,25 @@ Device::write(PacketPtr pkt) vnic.rxUnique = rxUnique++; vnic.RxDone = Regs::RxDone_Busy; vnic.RxData = pkt->get(); + rxBusyCount++; if (Regs::get_RxData_Vaddr(pkt->get())) { panic("vtophys not implemented in newmem"); -/* Addr vaddr = Regs::get_RxData_Addr(reg64); +#ifdef SINIC_VTOPHYS + Addr vaddr = Regs::get_RxData_Addr(reg64); Addr paddr = vtophys(req->xc, vaddr); DPRINTF(EthernetPIO, "write RxData vnic %d (rxunique %d): " "vaddr=%#x, paddr=%#x\n", index, vnic.rxUnique, vaddr, paddr); - vnic.RxData = Regs::set_RxData_Addr(vnic.RxData, paddr);*/ + vnic.RxData = Regs::set_RxData_Addr(vnic.RxData, paddr); +#endif } else { DPRINTF(EthernetPIO, "write RxData vnic %d (rxunique %d)\n", index, vnic.rxUnique); } - if (vnic.rxPacket == rxFifo.end()) { + if (vnic.rxIndex == rxFifo.end()) { DPRINTF(EthernetPIO, "request new packet...appending to rxList\n"); rxList.push_back(index); } else { @@ -512,15 +562,17 @@ Device::write(PacketPtr pkt) if (Regs::get_TxData_Vaddr(pkt->get())) { panic("vtophys won't work here in newmem.\n"); - /*Addr vaddr = Regs::get_TxData_Addr(reg64); +#ifdef SINIC_VTOPHYS + Addr vaddr = Regs::get_TxData_Addr(reg64); Addr paddr = vtophys(req->xc, vaddr); - DPRINTF(EthernetPIO, "write TxData vnic %d (rxunique %d): " + DPRINTF(EthernetPIO, "write TxData vnic %d (txunique %d): " "vaddr=%#x, paddr=%#x\n", index, vnic.txUnique, vaddr, paddr); - vnic.TxData = Regs::set_TxData_Addr(vnic.TxData, paddr);*/ + vnic.TxData = Regs::set_TxData_Addr(vnic.TxData, paddr); +#endif } else { - DPRINTF(EthernetPIO, "write TxData vnic %d (rxunique %d)\n", + DPRINTF(EthernetPIO, "write TxData vnic %d (txunique %d)\n", index, vnic.txUnique); } @@ -761,18 +813,31 @@ Device::reset() regs.IntrMask = Intr_Soft | Intr_RxHigh | Intr_RxPacket | Intr_TxLow; regs.RxMaxCopy = params()->rx_max_copy; regs.TxMaxCopy = params()->tx_max_copy; - regs.RxMaxIntr = params()->rx_max_intr; + regs.ZeroCopySize = params()->zero_copy_size; + regs.ZeroCopyMark = params()->zero_copy_threshold; regs.VirtualCount = params()->virtual_count; + regs.RxMaxIntr = params()->rx_max_intr; regs.RxFifoSize = params()->rx_fifo_size; regs.TxFifoSize = params()->tx_fifo_size; - regs.RxFifoMark = params()->rx_fifo_threshold; - regs.TxFifoMark = params()->tx_fifo_threshold; + regs.RxFifoLow = params()->rx_fifo_low_mark; + regs.TxFifoLow = params()->tx_fifo_threshold; + regs.RxFifoHigh = params()->rx_fifo_threshold; + regs.TxFifoHigh = params()->tx_fifo_high_mark; regs.HwAddr = params()->hardware_address; + if (regs.RxMaxCopy < regs.ZeroCopyMark) + panic("Must be able to copy at least as many bytes as the threshold"); + + if (regs.ZeroCopySize >= regs.ZeroCopyMark) + panic("The number of bytes to copy must be less than the threshold"); + rxList.clear(); rxBusy.clear(); rxActive = -1; txList.clear(); + rxBusyCount = 0; + rxDirtyCount = 0; + rxMappedCount = 0; rxState = rxIdle; txState = txIdle; @@ -788,7 +853,7 @@ Device::reset() virtualRegs.clear(); virtualRegs.resize(size); for (int i = 0; i < size; ++i) - virtualRegs[i].rxPacket = rxFifo.end(); + virtualRegs[i].rxIndex = rxFifo.end(); } void @@ -822,6 +887,7 @@ Device::rxKick() } next: + rxFifo.check(); if (rxState == rxIdle) goto exit; @@ -845,12 +911,28 @@ Device::rxKick() int size = virtualRegs.size(); for (int i = 0; i < size; ++i) { VirtualReg *vn = &virtualRegs[i]; - if (vn->rxPacket != end && - !Regs::get_RxDone_Busy(vn->RxDone)) { + bool busy = Regs::get_RxDone_Busy(vn->RxDone); + if (vn->rxIndex != end) { + bool dirty = vn->rxPacketOffset > 0; + const char *status; + + if (busy && dirty) + status = "busy,dirty"; + else if (busy) + status = "busy"; + else if (dirty) + status = "dirty"; + else + status = "mapped"; + DPRINTF(EthernetSM, - "vnic %d (rxunique %d), has outstanding packet %d\n", - i, vn->rxUnique, - rxFifo.countPacketsBefore(vn->rxPacket)); + "vnic %d %s (rxunique %d), packet %d, slack %d\n", + i, status, vn->rxUnique, + rxFifo.countPacketsBefore(vn->rxIndex), + vn->rxIndex->slack); + } else if (busy) { + DPRINTF(EthernetSM, "vnic %d unmapped (rxunique %d)\n", + i, vn->rxUnique); } } } @@ -860,7 +942,7 @@ Device::rxKick() rxBusy.pop_front(); vnic = &virtualRegs[rxActive]; - if (vnic->rxPacket == rxFifo.end()) + if (vnic->rxIndex == rxFifo.end()) panic("continuing vnic without packet\n"); DPRINTF(EthernetSM, @@ -869,6 +951,14 @@ Device::rxKick() rxState = rxBeginCopy; + int vnic_distance = rxFifo.countPacketsBefore(vnic->rxIndex); + totalVnicDistance += vnic_distance; + numVnicDistance += 1; + if (vnic_distance > _maxVnicDistance) { + maxVnicDistance = vnic_distance; + _maxVnicDistance = vnic_distance; + } + break; } @@ -891,14 +981,16 @@ Device::rxKick() rxActive, vnic->rxUnique); // Grab a new packet from the fifo. - vnic->rxPacket = rxFifoPtr++; + vnic->rxIndex = rxFifoPtr++; + vnic->rxIndex->priv = rxActive; vnic->rxPacketOffset = 0; - vnic->rxPacketBytes = vnic->rxPacket->packet->length; + vnic->rxPacketBytes = vnic->rxIndex->packet->length; assert(vnic->rxPacketBytes); + rxMappedCount++; vnic->rxDoneData = 0; /* scope for variables */ { - IpPtr ip(vnic->rxPacket->packet); + IpPtr ip(vnic->rxIndex->packet); if (ip) { DPRINTF(Ethernet, "ID is %d\n", ip->id()); vnic->rxDoneData |= Regs::RxDone_IpPacket; @@ -939,16 +1031,26 @@ Device::rxKick() rxDmaAddr = params()->platform->pciToDma( Regs::get_RxData_Addr(vnic->RxData)); - rxDmaLen = std::min(Regs::get_RxData_Len(vnic->RxData), + rxDmaLen = min(Regs::get_RxData_Len(vnic->RxData), vnic->rxPacketBytes); - rxDmaData = vnic->rxPacket->packet->data + vnic->rxPacketOffset; + + /* + * if we're doing zero/delay copy and we're below the fifo + * threshold, see if we should try to do the zero/defer copy + */ + if ((Regs::get_Config_ZeroCopy(regs.Config) || + Regs::get_Config_DelayCopy(regs.Config)) && + !Regs::get_RxData_NoDelay(vnic->RxData) && rxLow) { + if (rxDmaLen > regs.ZeroCopyMark) + rxDmaLen = regs.ZeroCopySize; + } + rxDmaData = vnic->rxIndex->packet->data + vnic->rxPacketOffset; rxState = rxCopy; if (rxDmaAddr == 1LL) { rxState = rxCopyDone; break; } - dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaEvent, rxDmaData); break; @@ -959,17 +1061,25 @@ Device::rxKick() case rxCopyDone: vnic->RxDone = vnic->rxDoneData; vnic->RxDone |= Regs::RxDone_Complete; + rxBusyCount--; if (vnic->rxPacketBytes == rxDmaLen) { + if (vnic->rxPacketOffset) + rxDirtyCount--; + // Packet is complete. Indicate how many bytes were copied vnic->RxDone = Regs::set_RxDone_CopyLen(vnic->RxDone, rxDmaLen); DPRINTF(EthernetSM, "rxKick: packet complete on vnic %d (rxunique %d)\n", rxActive, vnic->rxUnique); - rxFifo.remove(vnic->rxPacket); - vnic->rxPacket = rxFifo.end(); + rxFifo.remove(vnic->rxIndex); + vnic->rxIndex = rxFifo.end(); + rxMappedCount--; } else { + if (!vnic->rxPacketOffset) + rxDirtyCount++; + vnic->rxPacketBytes -= rxDmaLen; vnic->rxPacketOffset += rxDmaLen; vnic->RxDone |= Regs::RxDone_More; @@ -989,10 +1099,10 @@ Device::rxKick() rxEmpty = true; } - if (rxFifo.size() < params()->rx_fifo_low_mark) + if (rxFifo.size() < regs.RxFifoLow) rxLow = true; - if (rxFifo.size() > params()->rx_fifo_threshold) + if (rxFifo.size() > regs.RxFifoHigh) rxLow = false; devIntrPost(Regs::Intr_RxDMA); @@ -1044,7 +1154,7 @@ Device::transmit() if (!interface->sendPacket(packet)) { DPRINTF(Ethernet, "Packet Transmit: failed txFifo available %d\n", txFifo.avail()); - goto reschedule; + return; } txFifo.pop(); @@ -1072,15 +1182,9 @@ Device::transmit() txFifo.avail()); interrupts = Regs::Intr_TxPacket; - if (txFifo.size() < regs.TxFifoMark) + if (txFifo.size() < regs.TxFifoLow) interrupts |= Regs::Intr_TxLow; devIntrPost(interrupts); - - reschedule: - if (!txFifo.empty() && !txEvent.scheduled()) { - DPRINTF(Ethernet, "reschedule transmit\n"); - txEvent.schedule(curTick + retryTime); - } } void @@ -1278,7 +1382,7 @@ Device::recvPacket(EthPacketPtr packet) return true; } - if (rxFifo.size() >= regs.RxFifoMark) + if (rxFifo.size() >= regs.RxFifoHigh) devIntrPost(Regs::Intr_RxHigh); if (!rxFifo.push(packet)) { @@ -1372,19 +1476,13 @@ Device::serialize(std::ostream &os) TxStateStrings[txState]); /* - * Serialize the device registers + * Serialize the device registers that could be modified by the OS. */ SERIALIZE_SCALAR(regs.Config); SERIALIZE_SCALAR(regs.IntrStatus); SERIALIZE_SCALAR(regs.IntrMask); - SERIALIZE_SCALAR(regs.RxMaxCopy); - SERIALIZE_SCALAR(regs.TxMaxCopy); - SERIALIZE_SCALAR(regs.RxMaxIntr); - SERIALIZE_SCALAR(regs.VirtualCount); SERIALIZE_SCALAR(regs.RxData); - SERIALIZE_SCALAR(regs.RxDone); SERIALIZE_SCALAR(regs.TxData); - SERIALIZE_SCALAR(regs.TxDone); /* * Serialize the virtual nic state @@ -1400,12 +1498,12 @@ Device::serialize(std::ostream &os) paramOut(os, reg + ".TxData", vnic->TxData); paramOut(os, reg + ".TxDone", vnic->TxDone); - bool rxPacketExists = vnic->rxPacket != rxFifo.end(); + bool rxPacketExists = vnic->rxIndex != rxFifo.end(); paramOut(os, reg + ".rxPacketExists", rxPacketExists); if (rxPacketExists) { int rxPacket = 0; PacketFifo::iterator i = rxFifo.begin(); - while (i != vnic->rxPacket) { + while (i != vnic->rxIndex) { assert(i != rxFifo.end()); ++i; ++rxPacket; @@ -1418,10 +1516,15 @@ Device::serialize(std::ostream &os) paramOut(os, reg + ".rxDoneData", vnic->rxDoneData); } - int rxFifoPtr = rxFifo.countPacketsBefore(this->rxFifoPtr); + int rxFifoPtr = -1; + if (this->rxFifoPtr != rxFifo.end()) + rxFifoPtr = rxFifo.countPacketsBefore(this->rxFifoPtr); SERIALIZE_SCALAR(rxFifoPtr); SERIALIZE_SCALAR(rxActive); + SERIALIZE_SCALAR(rxBusyCount); + SERIALIZE_SCALAR(rxDirtyCount); + SERIALIZE_SCALAR(rxMappedCount); VirtualList::iterator i, end; for (count = 0, i = rxList.begin(), end = rxList.end(); i != end; ++i) @@ -1478,21 +1581,18 @@ Device::unserialize(Checkpoint *cp, const std::string §ion) Base::unserialize(cp, section); /* - * Unserialize the device registers + * Unserialize the device registers that may have been written by the OS. */ UNSERIALIZE_SCALAR(regs.Config); UNSERIALIZE_SCALAR(regs.IntrStatus); UNSERIALIZE_SCALAR(regs.IntrMask); - UNSERIALIZE_SCALAR(regs.RxMaxCopy); - UNSERIALIZE_SCALAR(regs.TxMaxCopy); - UNSERIALIZE_SCALAR(regs.RxMaxIntr); - UNSERIALIZE_SCALAR(regs.VirtualCount); UNSERIALIZE_SCALAR(regs.RxData); - UNSERIALIZE_SCALAR(regs.RxDone); UNSERIALIZE_SCALAR(regs.TxData); - UNSERIALIZE_SCALAR(regs.TxDone); UNSERIALIZE_SCALAR(rxActive); + UNSERIALIZE_SCALAR(rxBusyCount); + UNSERIALIZE_SCALAR(rxDirtyCount); + UNSERIALIZE_SCALAR(rxMappedCount); int rxListSize; UNSERIALIZE_SCALAR(rxListSize); @@ -1533,9 +1633,13 @@ Device::unserialize(Checkpoint *cp, const std::string §ion) int rxFifoPtr; UNSERIALIZE_SCALAR(rxFifoPtr); - this->rxFifoPtr = rxFifo.begin(); - for (int i = 0; i < rxFifoPtr; ++i) - ++this->rxFifoPtr; + if (rxFifoPtr >= 0) { + this->rxFifoPtr = rxFifo.begin(); + for (int i = 0; i < rxFifoPtr; ++i) + ++this->rxFifoPtr; + } else { + this->rxFifoPtr = rxFifo.end(); + } /* * Unserialize tx state machine @@ -1582,15 +1686,15 @@ Device::unserialize(Checkpoint *cp, const std::string §ion) if (rxPacketExists) { int rxPacket; paramIn(cp, section, reg + ".rxPacket", rxPacket); - vnic->rxPacket = rxFifo.begin(); + vnic->rxIndex = rxFifo.begin(); while (rxPacket--) - ++vnic->rxPacket; + ++vnic->rxIndex; paramIn(cp, section, reg + ".rxPacketOffset", vnic->rxPacketOffset); paramIn(cp, section, reg + ".rxPacketBytes", vnic->rxPacketBytes); } else { - vnic->rxPacket = rxFifo.end(); + vnic->rxIndex = rxFifo.end(); } paramIn(cp, section, reg + ".rxDoneData", vnic->rxDoneData); } diff --git a/src/dev/sinic.hh b/src/dev/sinic.hh index e85d93fe4..3185e8696 100644 --- a/src/dev/sinic.hh +++ b/src/dev/sinic.hh @@ -115,19 +115,24 @@ class Device : public Base uint32_t IntrMask; // 0x0c uint32_t RxMaxCopy; // 0x10 uint32_t TxMaxCopy; // 0x14 - uint32_t RxMaxIntr; // 0x18 - uint32_t VirtualCount; // 0x1c - uint32_t RxFifoSize; // 0x20 - uint32_t TxFifoSize; // 0x24 - uint32_t RxFifoMark; // 0x28 - uint32_t TxFifoMark; // 0x2c - uint64_t RxData; // 0x30 - uint64_t RxDone; // 0x38 - uint64_t RxWait; // 0x40 - uint64_t TxData; // 0x48 - uint64_t TxDone; // 0x50 - uint64_t TxWait; // 0x58 - uint64_t HwAddr; // 0x60 + uint32_t ZeroCopySize; // 0x18 + uint32_t ZeroCopyMark; // 0x1c + uint32_t VirtualCount; // 0x20 + uint32_t RxMaxIntr; // 0x24 + uint32_t RxFifoSize; // 0x28 + uint32_t TxFifoSize; // 0x2c + uint32_t RxFifoLow; // 0x30 + uint32_t TxFifoLow; // 0x34 + uint32_t RxFifoHigh; // 0x38 + uint32_t TxFifoHigh; // 0x3c + uint64_t RxData; // 0x40 + uint64_t RxDone; // 0x48 + uint64_t RxWait; // 0x50 + uint64_t TxData; // 0x58 + uint64_t TxDone; // 0x60 + uint64_t TxWait; // 0x68 + uint64_t HwAddr; // 0x70 + uint64_t RxStatus; // 0x78 } regs; struct VirtualReg { @@ -136,7 +141,7 @@ class Device : public Base uint64_t TxData; uint64_t TxDone; - PacketFifo::iterator rxPacket; + PacketFifo::iterator rxIndex; int rxPacketOffset; int rxPacketBytes; uint64_t rxDoneData; @@ -159,6 +164,10 @@ class Device : public Base int rxActive; VirtualList txList; + int rxBusyCount; + int rxMappedCount; + int rxDirtyCount; + uint8_t ®Data8(Addr daddr) { return *((uint8_t *)®s + daddr); } uint32_t ®Data32(Addr daddr) { return *(uint32_t *)®Data8(daddr); } uint64_t ®Data64(Addr daddr) { return *(uint64_t *)®Data8(daddr); } @@ -300,8 +309,16 @@ class Device : public Base Stats::Scalar<> txTcpChecksums; Stats::Scalar<> txUdpChecksums; + Stats::Scalar<> totalVnicDistance; + Stats::Scalar<> numVnicDistance; + Stats::Scalar<> maxVnicDistance; + Stats::Formula avgVnicDistance; + + int _maxVnicDistance; + public: virtual void regStats(); + virtual void resetStats(); /** * Serialization stuff diff --git a/src/dev/sinicreg.hh b/src/dev/sinicreg.hh index 791aabf6b..7ac7abad0 100644 --- a/src/dev/sinicreg.hh +++ b/src/dev/sinicreg.hh @@ -67,20 +67,25 @@ __SINIC_REG32(IntrStatus, 0x08); // 32: interrupt status __SINIC_REG32(IntrMask, 0x0c); // 32: interrupt mask __SINIC_REG32(RxMaxCopy, 0x10); // 32: max bytes per rx copy __SINIC_REG32(TxMaxCopy, 0x14); // 32: max bytes per tx copy -__SINIC_REG32(RxMaxIntr, 0x18); // 32: max receives per interrupt -__SINIC_REG32(VirtualCount, 0x1c); // 32: number of virutal NICs -__SINIC_REG32(RxFifoSize, 0x20); // 32: rx fifo capacity in bytes -__SINIC_REG32(TxFifoSize, 0x24); // 32: tx fifo capacity in bytes -__SINIC_REG32(RxFifoMark, 0x28); // 32: rx fifo high watermark -__SINIC_REG32(TxFifoMark, 0x2c); // 32: tx fifo low watermark -__SINIC_REG32(RxData, 0x30); // 64: receive data -__SINIC_REG32(RxDone, 0x38); // 64: receive done -__SINIC_REG32(RxWait, 0x40); // 64: receive done (busy wait) -__SINIC_REG32(TxData, 0x48); // 64: transmit data -__SINIC_REG32(TxDone, 0x50); // 64: transmit done -__SINIC_REG32(TxWait, 0x58); // 64: transmit done (busy wait) -__SINIC_REG32(HwAddr, 0x60); // 64: mac address -__SINIC_REG32(Size, 0x68); // register addres space size +__SINIC_REG32(ZeroCopySize, 0x18); // 32: bytes to copy if below threshold +__SINIC_REG32(ZeroCopyMark, 0x1c); // 32: only zero-copy above this threshold +__SINIC_REG32(VirtualCount, 0x20); // 32: number of virutal NICs +__SINIC_REG32(RxMaxIntr, 0x24); // 32: max receives per interrupt +__SINIC_REG32(RxFifoSize, 0x28); // 32: rx fifo capacity in bytes +__SINIC_REG32(TxFifoSize, 0x2c); // 32: tx fifo capacity in bytes +__SINIC_REG32(RxFifoLow, 0x30); // 32: rx fifo low watermark +__SINIC_REG32(TxFifoLow, 0x34); // 32: tx fifo low watermark +__SINIC_REG32(RxFifoHigh, 0x38); // 32: rx fifo high watermark +__SINIC_REG32(TxFifoHigh, 0x3c); // 32: tx fifo high watermark +__SINIC_REG32(RxData, 0x40); // 64: receive data +__SINIC_REG32(RxDone, 0x48); // 64: receive done +__SINIC_REG32(RxWait, 0x50); // 64: receive done (busy wait) +__SINIC_REG32(TxData, 0x58); // 64: transmit data +__SINIC_REG32(TxDone, 0x60); // 64: transmit done +__SINIC_REG32(TxWait, 0x68); // 64: transmit done (busy wait) +__SINIC_REG32(HwAddr, 0x70); // 64: mac address +__SINIC_REG32(RxStatus, 0x78); +__SINIC_REG32(Size, 0x80); // register addres space size // Config register bits __SINIC_VAL32(Config_ZeroCopy, 12, 1); // enable zero copy @@ -116,9 +121,10 @@ __SINIC_REG32(Intr_NoDelay, 0x01cc); // interrupts that aren't coalesced __SINIC_REG32(Intr_Res, ~0x01ff); // reserved interrupt bits // RX Data Description -__SINIC_VAL64(RxData_Vaddr, 60, 1); // Addr is virtual -__SINIC_VAL64(RxData_Len, 40, 20); // 0 - 256k -__SINIC_VAL64(RxData_Addr, 0, 40); // Address 1TB +__SINIC_VAL64(RxData_NoDelay, 61, 1); // Don't Delay this copy +__SINIC_VAL64(RxData_Vaddr, 60, 1); // Addr is virtual +__SINIC_VAL64(RxData_Len, 40, 20); // 0 - 256k +__SINIC_VAL64(RxData_Addr, 0, 40); // Address 1TB // TX Data Description __SINIC_VAL64(TxData_More, 63, 1); // Packet not complete (will dma more) @@ -159,6 +165,11 @@ __SINIC_VAL64(TxDone_Res6, 21, 1); // reserved __SINIC_VAL64(TxDone_Res7, 20, 1); // reserved __SINIC_VAL64(TxDone_CopyLen, 0, 20); // up to 256k +__SINIC_VAL64(RxStatus_Dirty, 48, 16); +__SINIC_VAL64(RxStatus_Mapped, 32, 16); +__SINIC_VAL64(RxStatus_Busy, 16, 16); +__SINIC_VAL64(RxStatus_Head, 0, 16); + struct Info { uint8_t size; @@ -174,31 +185,37 @@ regInfo(Addr daddr) { static Regs::Info invalid = { 0, false, false, "invalid" }; static Regs::Info info [] = { - { 4, true, true, "Config" }, - { 4, false, true, "Command" }, - { 4, true, true, "IntrStatus" }, - { 4, true, true, "IntrMask" }, - { 4, true, false, "RxMaxCopy" }, - { 4, true, false, "TxMaxCopy" }, - { 4, true, false, "RxMaxIntr" }, - { 4, true, false, "VirtualCount" }, - { 4, true, false, "RxFifoSize" }, - { 4, true, false, "TxFifoSize" }, - { 4, true, false, "RxFifoMark" }, - { 4, true, false, "TxFifoMark" }, - { 8, true, true, "RxData" }, + { 4, true, true, "Config" }, + { 4, false, true, "Command" }, + { 4, true, true, "IntrStatus" }, + { 4, true, true, "IntrMask" }, + { 4, true, false, "RxMaxCopy" }, + { 4, true, false, "TxMaxCopy" }, + { 4, true, false, "ZeroCopySize" }, + { 4, true, false, "ZeroCopyMark" }, + { 4, true, false, "VirtualCount" }, + { 4, true, false, "RxMaxIntr" }, + { 4, true, false, "RxFifoSize" }, + { 4, true, false, "TxFifoSize" }, + { 4, true, false, "RxFifoLow" }, + { 4, true, false, "TxFifoLow" }, + { 4, true, false, "RxFifoHigh" }, + { 4, true, false, "TxFifoHigh" }, + { 8, true, true, "RxData" }, + invalid, + { 8, true, false, "RxDone" }, invalid, - { 8, true, false, "RxDone" }, + { 8, true, false, "RxWait" }, invalid, - { 8, true, false, "RxWait" }, + { 8, true, true, "TxData" }, invalid, - { 8, true, true, "TxData" }, + { 8, true, false, "TxDone" }, invalid, - { 8, true, false, "TxDone" }, + { 8, true, false, "TxWait" }, invalid, - { 8, true, false, "TxWait" }, + { 8, true, false, "HwAddr" }, invalid, - { 8, true, false, "HwAddr" }, + { 8, true, false, "RxStatus" }, invalid, }; -- cgit v1.2.3 From 68c75c589b2e006292f623bd6428754d7d590f01 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 9 Oct 2008 04:58:23 -0700 Subject: pdb: Try to make pdb work better. I've done a few things here. First, I invoke the script a little bit differently so that pdb doesn't get confused. Second, I've stored the actual filename in the module's __file__ so that pdb can find the source file on your machine. --- src/SConscript | 20 +++++++++++++------- src/python/m5/main.py | 26 +++++++++++++++++++++----- 2 files changed, 34 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/SConscript b/src/SConscript index 1b968ec90..09ccf7722 100644 --- a/src/SConscript +++ b/src/SConscript @@ -61,8 +61,9 @@ def sort_list(_list): class PySourceFile(object): invalid_sym_char = re.compile('[^A-z0-9_]') - def __init__(self, package, source): - filename = str(source) + def __init__(self, package, tnode): + snode = tnode.srcnode() + filename = str(tnode) pyname = basename(filename) assert pyname.endswith('.py') name = pyname[:-3] @@ -70,7 +71,8 @@ class PySourceFile(object): path = package.split('.') else: path = [] - modpath = path + + modpath = path[:] if name != '__init__': modpath += [name] modpath = '.'.join(modpath) @@ -78,13 +80,17 @@ class PySourceFile(object): arcpath = path + [ pyname ] arcname = joinpath(*arcpath) - self.tnode = source - self.snode = source.srcnode() + debugname = snode.abspath + if not exists(debugname): + debugname = tnode.abspath + + self.tnode = tnode + self.snode = snode self.pyname = pyname self.package = package self.modpath = modpath self.arcname = arcname - self.filename = filename + self.debugname = debugname self.compiled = File(filename + 'c') self.assembly = File(filename + '.s') self.symname = "PyEMB_" + self.invalid_sym_char.sub('_', modpath) @@ -849,7 +855,7 @@ def objectifyPyFile(target, source, env): dst = file(str(target[0]), 'w') pysource = py_sources_tnodes[source[0]] - compiled = compile(src, pysource.snode.path, 'exec') + compiled = compile(src, pysource.debugname, 'exec') marshalled = marshal.dumps(compiled) compressed = zlib.compress(marshalled) data = compressed diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 66a422efa..1f9a21899 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -338,7 +338,10 @@ def main(): sys.argv = arguments sys.path = [ os.path.dirname(sys.argv[0]) ] + sys.path - scope = { '__file__' : sys.argv[0], + filename = sys.argv[0] + filedata = file(filename, 'r').read() + filecode = compile(filedata, filename, 'exec') + scope = { '__file__' : filename, '__name__' : '__m5_main__' } # we want readline if we're doing anything interactive @@ -348,11 +351,24 @@ def main(): # if pdb was requested, execfile the thing under pdb, otherwise, # just do the execfile normally if options.pdb: - from pdb import Pdb - debugger = Pdb() - debugger.run('execfile("%s")' % sys.argv[0], scope) + import pdb + import traceback + + pdb = pdb.Pdb() + try: + pdb.run(filecode, scope) + except SystemExit: + print "The program exited via sys.exit(). Exit status: ", + print sys.exc_info()[1] + except: + traceback.print_exc() + print "Uncaught exception. Entering post mortem debugging" + t = sys.exc_info()[2] + while t.tb_next is not None: + t = t.tb_next + pdb.interaction(t.tb_frame,t) else: - execfile(sys.argv[0], scope) + exec filecode in scope # once the script is done if options.interactive: -- cgit v1.2.3 From 8291d9db0a0bdeecb2a13f28962893ed3659230e Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 9 Oct 2008 04:58:23 -0700 Subject: eventq: Major API change for the Event and EventQueue structures. Since the early days of M5, an event needed to know which event queue it was on, and that data was required at the time of construction of the event object. In the future parallelized M5, this sort of requirement does not work well since the proper event queue will not always be known at the time of construction of an event. Now, events are created, and the EventQueue itself has the schedule function, e.g. eventq->schedule(event, when). To simplify the syntax, I created a class called EventManager which holds a pointer to an EventQueue and provides the schedule interface that is a proxy for the EventQueue. The intent is that objects that frequently schedule events can be derived from EventManager and then they have the schedule interface. SimObject and Port are examples of objects that will become EventManagers. The end result is that any SimObject can just call schedule(event, when) and it will just call that SimObject's eventq->schedule function. Of course, some objects may have more than one EventQueue, so this interface might not be perfect for those, but they should be relatively few. --- src/mem/port.cc | 17 ++- src/mem/port.hh | 11 +- src/python/m5/event.py | 33 +++-- src/python/swig/event.i | 26 ++-- src/python/swig/pyevent.cc | 38 +++++- src/python/swig/pyevent.hh | 28 +--- src/sim/eventq.cc | 8 +- src/sim/eventq.hh | 304 ++++++++++++++++++++++--------------------- src/sim/sim_object.cc | 2 +- src/sim/sim_object.hh | 4 +- src/sim/sim_object_params.hh | 2 + 11 files changed, 254 insertions(+), 219 deletions(-) (limited to 'src') diff --git a/src/mem/port.cc b/src/mem/port.cc index 0e03194c9..a666c968b 100644 --- a/src/mem/port.cc +++ b/src/mem/port.cc @@ -49,7 +49,7 @@ class DefaultPeerPort : public Port public: DefaultPeerPort() - : Port("default_port") + : Port("default_port", NULL) { } bool recvTiming(PacketPtr) @@ -90,13 +90,9 @@ class DefaultPeerPort : public Port DefaultPeerPort defaultPeerPort; -Port::Port() - : peer(&defaultPeerPort), owner(NULL) -{ -} - Port::Port(const std::string &_name, MemObject *_owner) - : portName(_name), peer(&defaultPeerPort), owner(_owner) + : EventManager(_owner), portName(_name), peer(&defaultPeerPort), + owner(_owner) { } @@ -112,6 +108,13 @@ Port::setPeer(Port *port) peer = port; } +void +Port::setOwner(MemObject *_owner) +{ + eventq = _owner->queue(); + owner = _owner; +} + void Port::removeConn() { diff --git a/src/mem/port.hh b/src/mem/port.hh index 15fda2164..1d9135ae6 100644 --- a/src/mem/port.hh +++ b/src/mem/port.hh @@ -47,6 +47,7 @@ #include "base/range.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 @@ -58,6 +59,7 @@ typedef std::list > AddrRangeList; typedef std::list >::iterator AddrRangeIter; +class EventQueue; class MemObject; /** @@ -71,7 +73,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 +class Port : public EventManager { protected: /** Descriptive name (for DPRINTF output) */ @@ -86,9 +88,6 @@ class Port MemObject *owner; public: - - Port(); - /** * Constructor. * @@ -97,7 +96,7 @@ class Port * @param _owner Pointer to the MemObject that owns this port. * Will not necessarily be set. */ - Port(const std::string &_name, MemObject *_owner = NULL); + Port(const std::string &_name, MemObject *_owner); /** Return port name (for DPRINTF). */ const std::string &name() const { return portName; } @@ -121,7 +120,7 @@ class Port Port *getPeer() { return peer; } /** Function to set the owner of this port. */ - void setOwner(MemObject *_owner) { owner = _owner; } + void setOwner(MemObject *_owner); /** Function to return the owner of this port. */ MemObject *getOwner() { return owner; } diff --git a/src/python/m5/event.py b/src/python/m5/event.py index 2d6497464..5d50448e7 100644 --- a/src/python/m5/event.py +++ b/src/python/m5/event.py @@ -26,17 +26,32 @@ # # Authors: Nathan Binkert -from internal.event import create -from internal.event import SimLoopExitEvent as SimExit +import internal.event -class ProgressEvent(object): - def __init__(self, period): - self.period = int(period) - self.schedule() +from internal.event import PythonEvent, SimLoopExitEvent as SimExit + +mainq = internal.event.cvar.mainEventQueue + +def create(obj, priority=None): + if priority is None: + priority = internal.event.Event.Default_Pri + return internal.event.PythonEvent(obj, priority) - def schedule(self): - create(self, m5.curTick() + self.period) +class Event(PythonEvent): + def __init__(self, priority=None): + if priority is None: + priority = internal.event.Event.Default_Pri + super(PythonEvent, self).__init__(self, priority) + +class ProgressEvent(Event): + def __init__(self, eventq, period): + super(ProgressEvent, self).__init__() + self.period = int(period) + self.eventq = eventq + self.eventq.schedule(self, m5.curTick() + self.period) def __call__(self): print "Progress! Time now %fs" % (m5.curTick()/1e12) - self.schedule() + self.eventq.schedule(self, m5.curTick() + self.period) + +__all__ = [ 'create', 'Event', 'ProgressEvent', 'SimExit', 'mainq' ] diff --git a/src/python/swig/event.i b/src/python/swig/event.i index 9a2093c99..10d75d2de 100644 --- a/src/python/swig/event.i +++ b/src/python/swig/event.i @@ -32,34 +32,36 @@ %{ #include "python/swig/pyevent.hh" - +#include "sim/host.hh" +#include "sim/eventq.hh" #include "sim/sim_events.hh" #include "sim/sim_exit.hh" #include "sim/simulate.hh" %} +#pragma SWIG nowarn=350,351 + +%import "base/fast_alloc.hh" +%import "sim/serialize.hh" + %include "stdint.i" %include "std_string.i" %include "sim/host.hh" +%include "sim/eventq.hh" +%include "python/swig/pyevent.hh" -void create(PyObject *object, Tick when); - -class Event; -class CountedDrainEvent : public Event { - public: +struct CountedDrainEvent : public Event +{ void setCount(int _count); }; -CountedDrainEvent *createCountedDrain(); -void cleanupCountedDrain(Event *drain_event); - // minimal definition of SimExitEvent interface to wrap -class SimLoopExitEvent { +class SimLoopExitEvent : public Event +{ public: std::string getCause(); int getCode(); - SimLoopExitEvent(EventQueue *q, Tick _when, Tick _repeat, - const std::string &_cause, int c = 0); + SimLoopExitEvent(const std::string &_cause, int c, Tick _repeat = 0); }; %exception simulate { diff --git a/src/python/swig/pyevent.cc b/src/python/swig/pyevent.cc index 7f23b8874..bf993bc3e 100644 --- a/src/python/swig/pyevent.cc +++ b/src/python/swig/pyevent.cc @@ -33,8 +33,8 @@ #include "python/swig/pyevent.hh" #include "sim/async.hh" -PythonEvent::PythonEvent(PyObject *obj, Tick when, Priority priority) - : Event(&mainEventQueue, priority), object(obj) +PythonEvent::PythonEvent(PyObject *obj, Priority priority) + : Event(priority), object(obj) { if (object == NULL) panic("Passed in invalid object"); @@ -42,7 +42,6 @@ PythonEvent::PythonEvent(PyObject *obj, Tick when, Priority priority) Py_INCREF(object); setFlags(AutoDelete); - schedule(when); } PythonEvent::~PythonEvent() @@ -67,3 +66,36 @@ PythonEvent::process() async_exception = true; } } + +Event * +createCountedDrain() +{ + return new CountedDrainEvent(); +} + +void +cleanupCountedDrain(Event *counted_drain) +{ + CountedDrainEvent *event = + dynamic_cast(counted_drain); + if (event == NULL) { + fatal("Called cleanupCountedDrain() on an event that was not " + "a CountedDrainEvent."); + } + assert(event->getCount() == 0); + delete event; +} + +#if 0 +Event * +create(PyObject *object, Event::Priority priority) +{ + return new PythonEvent(object, priority); +} + +void +destroy(Event *event) +{ + delete event; +} +#endif diff --git a/src/python/swig/pyevent.hh b/src/python/swig/pyevent.hh index 65e80e9e4..c6d6ac993 100644 --- a/src/python/swig/pyevent.hh +++ b/src/python/swig/pyevent.hh @@ -40,35 +40,13 @@ class PythonEvent : public Event PyObject *object; public: - PythonEvent(PyObject *obj, Tick when, Priority priority = Default_Pri); + PythonEvent(PyObject *obj, Event::Priority priority); ~PythonEvent(); virtual void process(); }; -inline void -create(PyObject *object, Tick when) -{ - new PythonEvent(object, when); -} - -inline Event * -createCountedDrain() -{ - return new CountedDrainEvent(); -} - -inline void -cleanupCountedDrain(Event *counted_drain) -{ - CountedDrainEvent *event = - dynamic_cast(counted_drain); - if (event == NULL) { - fatal("Called cleanupCountedDrain() on an event that was not " - "a CountedDrainEvent."); - } - assert(event->getCount() == 0); - delete event; -} +Event *createCountedDrain(); +void cleanupCountedDrain(Event *counted_drain); #endif // __PYTHON_SWIG_PYEVENT_HH__ diff --git a/src/sim/eventq.cc b/src/sim/eventq.cc index 78d6a458f..f4fa0ac8b 100644 --- a/src/sim/eventq.cc +++ b/src/sim/eventq.cc @@ -51,7 +51,7 @@ using namespace std; // Events on this queue are processed at the *beginning* of each // cycle, before the pipeline simulation is performed. // -EventQueue mainEventQueue("MainEventQueue"); +EventQueue mainEventQueue("Main Event Queue"); #ifndef NDEBUG Counter Event::instanceCounter = 0; @@ -209,8 +209,7 @@ Event::serialize(std::ostream &os) void Event::unserialize(Checkpoint *cp, const string §ion) { - if (scheduled()) - deschedule(); + assert(!scheduled() && "we used to deschedule these events"); UNSERIALIZE_SCALAR(_when); UNSERIALIZE_SCALAR(_priority); @@ -224,7 +223,8 @@ Event::unserialize(Checkpoint *cp, const string §ion) if (wasScheduled) { DPRINTF(Config, "rescheduling at %d\n", _when); - schedule(_when); + panic("need to figure out how to unserialize scheduled events"); + //schedule(_when); } } diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index e0194a742..2db652b54 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -51,16 +51,6 @@ class EventQueue; // forward declaration -////////////////////// -// -// Main Event Queue -// -// Events on this queue are processed at the *beginning* of each -// cycle, before the pipeline simulation is performed. -// -// defined in eventq.cc -// -////////////////////// extern EventQueue mainEventQueue; /* @@ -90,10 +80,6 @@ class Event : public Serializable, public FastAlloc static Event *insertBefore(Event *event, Event *curr); static Event *removeItem(Event *event, Event *last); - /// queue to which this event belongs (though it may or may not be - /// scheduled on this queue yet) - EventQueue *_queue; - Tick _when; //!< timestamp when event should be processed short _priority; //!< event priority short _flags; @@ -107,6 +93,10 @@ class Event : public Serializable, public FastAlloc /// more difficult. Thus we use a global counter value when /// debugging. Counter instance; + + /// queue to which this event belongs (though it may or may not be + /// scheduled on this queue yet) + EventQueue *queue; #endif #ifdef EVENTQ_DEBUG @@ -114,11 +104,13 @@ class Event : public Serializable, public FastAlloc Tick whenScheduled; //!< time scheduled #endif - protected: void - setWhen(Tick when) + setWhen(Tick when, EventQueue *q) { _when = when; +#ifndef NDEBUG + queue = q; +#endif #ifdef EVENTQ_DEBUG whenScheduled = curTick; #endif @@ -131,7 +123,8 @@ class Event : public Serializable, public FastAlloc Scheduled = 0x2, AutoDelete = 0x4, AutoSerialize = 0x8, - IsExitEvent = 0x10 + IsExitEvent = 0x10, + IsMainQueue = 0x20 }; bool getFlags(Flags f) const { return (_flags & f) == f; } @@ -139,8 +132,6 @@ class Event : public Serializable, public FastAlloc void clearFlags(Flags f) { _flags &= ~f; } protected: - EventQueue *queue() const { return _queue; } - // This function isn't really useful if TRACING_ON is not defined virtual void trace(const char *action); //!< trace event activity @@ -205,11 +196,12 @@ class Event : public Serializable, public FastAlloc * Event constructor * @param queue that the event gets scheduled on */ - Event(EventQueue *q, Priority p = Default_Pri) - : nextBin(NULL), nextInBin(NULL), _queue(q), _priority(p), _flags(None) + Event(Priority p = Default_Pri) + : nextBin(NULL), nextInBin(NULL), _priority(p), _flags(None) { #ifndef NDEBUG instance = ++instanceCounter; + queue = NULL; #endif #ifdef EVENTQ_DEBUG whenCreated = curTick; @@ -256,16 +248,6 @@ class Event : public Serializable, public FastAlloc /// Determine if the current event is scheduled bool scheduled() const { return getFlags(Scheduled); } - /// Schedule the event with the current priority or default priority - void schedule(Tick t); - - /// Reschedule the event with the current priority - // always parameter means to schedule if not already scheduled - void reschedule(Tick t, bool always = false); - - /// Remove the event from the current schedule - void deschedule(); - /// Squash the current event void squash() { setFlags(Squashed); } @@ -281,6 +263,7 @@ class Event : public Serializable, public FastAlloc /// Get the event priority int priority() const { return _priority; } +#ifndef SWIG struct priority_compare : public std::binary_function { @@ -293,55 +276,7 @@ class Event : public Serializable, public FastAlloc virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); -}; - -template -void -DelayFunction(Tick when, T *object) -{ - class DelayEvent : public Event - { - private: - T *object; - - public: - DelayEvent(Tick when, T *o) - : Event(&mainEventQueue), object(o) - { setFlags(this->AutoDestroy); schedule(when); } - void process() { (object->*F)(); } - const char *description() const { return "delay"; } - }; - - new DelayEvent(when, object); -} - -template -class EventWrapper : public Event -{ - private: - T *object; - - public: - EventWrapper(T *obj, bool del = false, - EventQueue *q = &mainEventQueue, - Priority p = Default_Pri) - : Event(q, p), object(obj) - { - if (del) - setFlags(AutoDelete); - } - - EventWrapper(T *obj, Tick t, bool del = false, - EventQueue *q = &mainEventQueue, - Priority p = Default_Pri) - : Event(q, p), object(obj) - { - if (del) - setFlags(AutoDelete); - schedule(t); - } - - void process() { (object->*F)(); } +#endif }; /* @@ -349,18 +284,14 @@ class EventWrapper : public Event */ class EventQueue : public Serializable { - protected: - std::string objName; - private: + std::string objName; Event *head; void insert(Event *event); void remove(Event *event); public: - - // constructor EventQueue(const std::string &n) : objName(n), head(NULL) {} @@ -370,7 +301,7 @@ class EventQueue : public Serializable // schedule the given event on this queue void schedule(Event *ev, Tick when); void deschedule(Event *ev); - void reschedule(Event *ev, Tick when); + void reschedule(Event *ev, Tick when, bool always = false); Tick nextTick() const { return head->when(); } Event *serviceOne(); @@ -406,83 +337,103 @@ class EventQueue : public Serializable bool debugVerify() const; +#ifndef SWIG virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); +#endif }; +#ifndef SWIG +class EventManager +{ + protected: + /** A pointer to this object's event queue */ + EventQueue *eventq; -////////////////////// -// -// inline functions -// -// can't put these inside declaration due to circular dependence -// between Event and EventQueue classes. -// -////////////////////// + public: + EventManager(EventManager &em) : eventq(em.queue()) {} + EventManager(EventManager *em) : eventq(em ? em->queue() : NULL) {} + EventManager(EventQueue *eq) : eventq(eq) {} -// schedule at specified time (place on event queue specified via -// constructor) -inline void -Event::schedule(Tick when) -{ - _queue->schedule(this, when); -} + EventQueue * + queue() const + { + return eventq; + } -inline void -Event::deschedule() -{ - _queue->deschedule(this); -} + void + schedule(Event &event, Tick when) + { + eventq->schedule(&event, when); + } -inline void -Event::reschedule(Tick when, bool always) -{ - if (scheduled()) { - _queue->reschedule(this, when); - } else { - assert(always); - _queue->schedule(this, when); + void + deschedule(Event &event) + { + eventq->deschedule(&event); } -} -inline bool -operator<(const Event &l, const Event &r) -{ - return l.when() < r.when() || - (l.when() == r.when() && l.priority() < r.priority()); -} + void + reschedule(Event &event, Tick when, bool always = false) + { + eventq->reschedule(&event, when, always); + } -inline bool -operator>(const Event &l, const Event &r) -{ - return l.when() > r.when() || - (l.when() == r.when() && l.priority() > r.priority()); -} + void + schedule(Event *event, Tick when) + { + eventq->schedule(event, when); + } -inline bool -operator<=(const Event &l, const Event &r) -{ - return l.when() < r.when() || - (l.when() == r.when() && l.priority() <= r.priority()); -} -inline bool -operator>=(const Event &l, const Event &r) -{ - return l.when() > r.when() || - (l.when() == r.when() && l.priority() >= r.priority()); -} + void + deschedule(Event *event) + { + eventq->deschedule(event); + } -inline bool -operator==(const Event &l, const Event &r) + void + reschedule(Event *event, Tick when, bool always = false) + { + eventq->reschedule(event, when, always); + } +}; + +template +void +DelayFunction(EventQueue *eventq, Tick when, T *object) { - return l.when() == r.when() && l.priority() == r.priority(); + class DelayEvent : public Event + { + private: + T *object; + + public: + DelayEvent(T *o) + : object(o) + { setFlags(this->AutoDestroy); } + void process() { (object->*F)(); } + const char *description() const { return "delay"; } + }; + + eventq->schedule(new DelayEvent(object), when); } -inline bool -operator!=(const Event &l, const Event &r) +template +class EventWrapper : public Event { - return l.when() != r.when() || l.priority() != r.priority(); -} + private: + T *object; + + public: + EventWrapper(T *obj, bool del = false, Priority p = Default_Pri) + : Event(p), object(obj) + { + if (del) + setFlags(AutoDelete); + } + + void process() { (object->*F)(); } +}; inline void EventQueue::schedule(Event *event, Tick when) @@ -490,9 +441,13 @@ EventQueue::schedule(Event *event, Tick when) assert(when >= curTick); assert(!event->scheduled()); - event->setWhen(when); + event->setWhen(when, this); insert(event); event->setFlags(Event::Scheduled); + if (this == &mainEventQueue) + event->setFlags(Event::IsMainQueue); + else + event->clearFlags(Event::IsMainQueue); if (DTRACE(Event)) event->trace("scheduled"); @@ -516,18 +471,65 @@ EventQueue::deschedule(Event *event) } inline void -EventQueue::reschedule(Event *event, Tick when) +EventQueue::reschedule(Event *event, Tick when, bool always) { assert(when >= curTick); - assert(event->scheduled()); + assert(always || event->scheduled()); - remove(event); - event->setWhen(when); + if (event->scheduled()) + remove(event); + + event->setWhen(when, this); insert(event); event->clearFlags(Event::Squashed); + event->setFlags(Event::Scheduled); + if (this == &mainEventQueue) + event->setFlags(Event::IsMainQueue); + else + event->clearFlags(Event::IsMainQueue); if (DTRACE(Event)) event->trace("rescheduled"); } +inline bool +operator<(const Event &l, const Event &r) +{ + return l.when() < r.when() || + (l.when() == r.when() && l.priority() < r.priority()); +} + +inline bool +operator>(const Event &l, const Event &r) +{ + return l.when() > r.when() || + (l.when() == r.when() && l.priority() > r.priority()); +} + +inline bool +operator<=(const Event &l, const Event &r) +{ + return l.when() < r.when() || + (l.when() == r.when() && l.priority() <= r.priority()); +} +inline bool +operator>=(const Event &l, const Event &r) +{ + return l.when() > r.when() || + (l.when() == r.when() && l.priority() >= r.priority()); +} + +inline bool +operator==(const Event &l, const Event &r) +{ + return l.when() == r.when() && l.priority() == r.priority(); +} + +inline bool +operator!=(const Event &l, const Event &r) +{ + return l.when() != r.when() || l.priority() != r.priority(); +} +#endif + #endif // __SIM_EVENTQ_HH__ diff --git a/src/sim/sim_object.cc b/src/sim/sim_object.cc index 2c2213987..dad8f6e8b 100644 --- a/src/sim/sim_object.cc +++ b/src/sim/sim_object.cc @@ -59,7 +59,7 @@ SimObject::SimObjectList SimObject::simObjectList; // SimObject constructor: used to maintain static simObjectList // SimObject::SimObject(const Params *p) - : _params(p) + : EventManager(p->eventq), _params(p) { #ifdef DEBUG doDebugBreak = false; diff --git a/src/sim/sim_object.hh b/src/sim/sim_object.hh index 0141c16cc..d6d08f255 100644 --- a/src/sim/sim_object.hh +++ b/src/sim/sim_object.hh @@ -43,6 +43,7 @@ #include #include "params/SimObject.hh" +#include "sim/eventq.hh" #include "sim/serialize.hh" #include "sim/startup.hh" @@ -54,7 +55,8 @@ class Event; * correspond to physical components and can be specified via the * config file (CPUs, caches, etc.). */ -class SimObject : public Serializable, protected StartupCallback +class SimObject + : public EventManager, public Serializable, protected StartupCallback { public: enum State { diff --git a/src/sim/sim_object_params.hh b/src/sim/sim_object_params.hh index 5a629a949..74d433495 100644 --- a/src/sim/sim_object_params.hh +++ b/src/sim/sim_object_params.hh @@ -38,12 +38,14 @@ struct PyObject; #include +struct EventQueue; struct SimObjectParams { virtual ~SimObjectParams() {} std::string name; PyObject *pyobj; + EventQueue *eventq; }; -- cgit v1.2.3 From e06321091d4e931ff1a4d753e56d76f9746c3cd2 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 9 Oct 2008 04:58:24 -0700 Subject: eventq: convert all usage of events to use the new API. For now, there is still a single global event queue, but this is necessary for making the steps towards a parallelized m5. --- src/arch/alpha/regfile.cc | 6 ++- src/arch/alpha/regfile.hh | 6 ++- src/arch/mips/regfile/misc_regfile.cc | 10 ++--- src/arch/mips/regfile/regfile.cc | 5 ++- src/arch/mips/regfile/regfile.hh | 8 ++-- src/arch/sparc/miscregfile.cc | 13 +++--- src/arch/sparc/miscregfile.hh | 5 ++- src/arch/sparc/regfile.cc | 10 +++-- src/arch/sparc/regfile.hh | 5 ++- src/arch/sparc/ua2005.cc | 30 ++++++++------ src/arch/x86/miscregfile.hh | 6 +-- src/arch/x86/regfile.cc | 6 ++- src/arch/x86/regfile.hh | 6 ++- src/cpu/base.cc | 76 +++++++++++++++++++---------------- src/cpu/base.hh | 2 +- src/cpu/cpuevent.hh | 9 ++--- src/cpu/memtest/memtest.cc | 4 +- src/cpu/memtest/memtest.hh | 6 +-- src/cpu/o3/commit_impl.hh | 4 +- src/cpu/o3/cpu.cc | 17 ++++---- src/cpu/o3/cpu.hh | 20 ++++----- src/cpu/o3/fetch.hh | 2 +- src/cpu/o3/inst_queue_impl.hh | 9 ++--- src/cpu/o3/lsq.hh | 2 +- src/cpu/o3/lsq_unit.hh | 2 +- src/cpu/o3/lsq_unit_impl.hh | 4 +- src/cpu/quiesce_event.cc | 2 +- src/cpu/simple/atomic.cc | 15 ++++--- src/cpu/simple/timing.cc | 16 ++++---- src/cpu/simple/timing.hh | 3 +- src/cpu/simple_thread.cc | 4 +- src/cpu/thread_state.cc | 2 +- src/dev/alpha/tsunami_io.cc | 9 +++-- src/dev/alpha/tsunami_io.hh | 8 ++-- src/dev/etherbus.cc | 4 +- src/dev/etherbus.hh | 3 +- src/dev/etherlink.cc | 16 ++++---- src/dev/ethertap.cc | 4 +- src/dev/ethertap.hh | 3 +- src/dev/i8254xGBe.cc | 55 ++++++++++++------------- src/dev/i8254xGBe.hh | 12 +++--- src/dev/ide_disk.cc | 24 +++++------ src/dev/intel_8254_timer.cc | 19 ++++----- src/dev/intel_8254_timer.hh | 15 ++++--- src/dev/io_device.cc | 10 ++--- src/dev/mc146818.cc | 22 +++++----- src/dev/mc146818.hh | 8 ++-- src/dev/ns_gige.cc | 20 ++++----- src/dev/pcidev.cc | 4 +- src/dev/sinic.cc | 10 +++-- src/dev/uart8250.cc | 14 +++---- src/mem/bridge.cc | 12 +++--- src/mem/bridge.hh | 5 +-- src/mem/bus.cc | 20 ++++----- src/mem/cache/base.cc | 2 +- src/mem/cache/cache_impl.hh | 2 +- src/mem/physical.cc | 2 +- src/mem/tport.cc | 2 +- src/mem/tport.hh | 9 +++-- src/python/m5/main.py | 4 +- src/sim/debug.cc | 16 ++++---- src/sim/pseudo_inst.cc | 11 +++-- src/sim/sim_events.cc | 54 ++++++++++++------------- src/sim/sim_events.hh | 34 ++++------------ src/sim/sim_exit.hh | 8 ---- src/sim/sim_object_params.hh | 6 +++ src/sim/simulate.cc | 9 +++-- src/sim/stat_control.cc | 15 +++---- 68 files changed, 398 insertions(+), 388 deletions(-) mode change 100755 => 100644 src/arch/mips/regfile/misc_regfile.cc (limited to 'src') diff --git a/src/arch/alpha/regfile.cc b/src/arch/alpha/regfile.cc index cd648844f..b3aa55b19 100644 --- a/src/arch/alpha/regfile.cc +++ b/src/arch/alpha/regfile.cc @@ -33,10 +33,12 @@ #include "arch/alpha/regfile.hh" #include "cpu/thread_context.hh" +using namespace std; + namespace AlphaISA { void -RegFile::serialize(std::ostream &os) +RegFile::serialize(EventManager *em, ostream &os) { intRegFile.serialize(os); floatRegFile.serialize(os); @@ -49,7 +51,7 @@ RegFile::serialize(std::ostream &os) } void -RegFile::unserialize(Checkpoint *cp, const std::string §ion) +RegFile::unserialize(EventManager *em, Checkpoint *cp, const string §ion) { intRegFile.unserialize(cp, section); floatRegFile.unserialize(cp, section); diff --git a/src/arch/alpha/regfile.hh b/src/arch/alpha/regfile.hh index c9fa8a91b..d6d2f587e 100644 --- a/src/arch/alpha/regfile.hh +++ b/src/arch/alpha/regfile.hh @@ -43,6 +43,7 @@ //XXX These should be implemented by someone who knows the alpha stuff better class Checkpoint; +class EventManager; class ThreadContext; namespace AlphaISA { @@ -202,8 +203,9 @@ class RegFile { intRegFile.setReg(intReg, val); } - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); + void serialize(EventManager *em, std::ostream &os); + void unserialize(EventManager *em, Checkpoint *cp, + const std::string §ion); void changeContext(RegContextParam param, RegContextVal val) diff --git a/src/arch/mips/regfile/misc_regfile.cc b/src/arch/mips/regfile/misc_regfile.cc old mode 100755 new mode 100644 index 06523a8c9..08487db90 --- a/src/arch/mips/regfile/misc_regfile.cc +++ b/src/arch/mips/regfile/misc_regfile.cc @@ -567,7 +567,7 @@ MiscRegFile::scheduleCP0Update(int delay) //schedule UPDATE CP0Event *cp0_event = new CP0Event(this, cpu, UpdateCP0); - cp0_event->schedule(curTick + cpu->ticks(delay)); + cpu->schedule(cp0_event, curTick + cpu->ticks(delay)); } } @@ -601,8 +601,7 @@ MiscRegFile::updateCPU() } MiscRegFile::CP0Event::CP0Event(CP0 *_cp0, BaseCPU *_cpu, CP0EventType e_type) - : Event(&mainEventQueue, CPU_Tick_Pri), cp0(_cp0), cpu(_cpu), - cp0EventType(e_type) + : Event(CPU_Tick_Pri), cp0(_cp0), cpu(_cpu), cp0EventType(e_type) { } void @@ -627,10 +626,7 @@ MiscRegFile::CP0Event::description() const void MiscRegFile::CP0Event::scheduleEvent(int delay) { - if (squashed()) - reschedule(curTick + cpu->ticks(delay)); - else if (!scheduled()) - schedule(curTick + cpu->ticks(delay)); + cpu->reschedule(this, curTick + cpu->ticks(delay), true); } void diff --git a/src/arch/mips/regfile/regfile.cc b/src/arch/mips/regfile/regfile.cc index 996c14f14..a1c8eab6a 100644 --- a/src/arch/mips/regfile/regfile.cc +++ b/src/arch/mips/regfile/regfile.cc @@ -193,7 +193,7 @@ RegFile::setNextNPC(Addr val) } void -RegFile::serialize(std::ostream &os) +RegFile::serialize(EventManager *em, std::ostream &os) { intRegFile.serialize(os); //SERIALIZE_ARRAY(floatRegFile, NumFloatRegs); @@ -207,7 +207,8 @@ RegFile::serialize(std::ostream &os) } void -RegFile::unserialize(Checkpoint *cp, const std::string §ion) +RegFile::unserialize(EventManager *em, Checkpoint *cp, + const std::string §ion) { intRegFile.unserialize(cp, section); //UNSERIALIZE_ARRAY(floatRegFile); diff --git a/src/arch/mips/regfile/regfile.hh b/src/arch/mips/regfile/regfile.hh index 407d9b50a..076cf45f5 100644 --- a/src/arch/mips/regfile/regfile.hh +++ b/src/arch/mips/regfile/regfile.hh @@ -41,8 +41,9 @@ //#include "cpu/base.hh" #include "sim/faults.hh" -class Checkpoint; class BaseCPU; +class Checkpoint; +class EventManager; namespace MipsISA { @@ -99,8 +100,9 @@ namespace MipsISA Addr readNextNPC(); void setNextNPC(Addr val); - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); + void serialize(EventManager *em, std::ostream &os); + void unserialize(EventManager *em, Checkpoint *cp, + const std::string §ion); void changeContext(RegContextParam param, RegContextVal val) { diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc index 195db90a6..d66cefa7a 100644 --- a/src/arch/sparc/miscregfile.cc +++ b/src/arch/sparc/miscregfile.cc @@ -593,7 +593,8 @@ void MiscRegFile::setReg(int miscReg, setRegNoEffect(miscReg, new_val); } -void MiscRegFile::serialize(std::ostream & os) +void +MiscRegFile::serialize(EventManager *em, std::ostream &os) { SERIALIZE_SCALAR(asi); SERIALIZE_SCALAR(tick); @@ -670,7 +671,9 @@ void MiscRegFile::serialize(std::ostream & os) #endif } -void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section) +void +MiscRegFile::unserialize(EventManager *em, Checkpoint *cp, + const string §ion) { UNSERIALIZE_SCALAR(asi); UNSERIALIZE_SCALAR(tick); @@ -729,15 +732,15 @@ void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section) if (tick_cmp) { tickCompare = new TickCompareEvent(this, tc); - tickCompare->schedule(tick_cmp); + em->schedule(tickCompare, tick_cmp); } if (stick_cmp) { sTickCompare = new STickCompareEvent(this, tc); - sTickCompare->schedule(stick_cmp); + em->schedule(sTickCompare, stick_cmp); } if (hstick_cmp) { hSTickCompare = new HSTickCompareEvent(this, tc); - hSTickCompare->schedule(hstick_cmp); + em->schedule(hSTickCompare, hstick_cmp); } } } diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh index bf9c880fa..6a010f529 100644 --- a/src/arch/sparc/miscregfile.hh +++ b/src/arch/sparc/miscregfile.hh @@ -288,9 +288,10 @@ namespace SparcISA return priContext | (uint32_t)partId << 13; } - void serialize(std::ostream & os); + void serialize(EventManager *em, std::ostream & os); - void unserialize(Checkpoint * cp, const std::string & section); + void unserialize(EventManager *em, Checkpoint *cp, + const std::string & section); void copyMiscRegs(ThreadContext * tc); diff --git a/src/arch/sparc/regfile.cc b/src/arch/sparc/regfile.cc index 76516daca..8815b094c 100644 --- a/src/arch/sparc/regfile.cc +++ b/src/arch/sparc/regfile.cc @@ -219,21 +219,23 @@ int SparcISA::flattenIntIndex(ThreadContext * tc, int reg) //return intRegFile.flattenIndex(reg); } -void RegFile::serialize(std::ostream &os) +void +RegFile::serialize(EventManager *em, ostream &os) { intRegFile.serialize(os); floatRegFile.serialize(os); - miscRegFile.serialize(os); + miscRegFile.serialize(em, os); SERIALIZE_SCALAR(pc); SERIALIZE_SCALAR(npc); SERIALIZE_SCALAR(nnpc); } -void RegFile::unserialize(Checkpoint *cp, const std::string §ion) +void +RegFile::unserialize(EventManager *em, Checkpoint *cp, const string §ion) { intRegFile.unserialize(cp, section); floatRegFile.unserialize(cp, section); - miscRegFile.unserialize(cp, section); + miscRegFile.unserialize(em, cp, section); UNSERIALIZE_SCALAR(pc); UNSERIALIZE_SCALAR(npc); UNSERIALIZE_SCALAR(nnpc); diff --git a/src/arch/sparc/regfile.hh b/src/arch/sparc/regfile.hh index 581785714..da7e022e9 100644 --- a/src/arch/sparc/regfile.hh +++ b/src/arch/sparc/regfile.hh @@ -112,8 +112,9 @@ namespace SparcISA void setIntReg(int intReg, const IntReg &val); - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); + void serialize(EventManager *em, std::ostream &os); + void unserialize(EventManager *em, Checkpoint *cp, + const std::string §ion); public: diff --git a/src/arch/sparc/ua2005.cc b/src/arch/sparc/ua2005.cc index 990250159..7b8524703 100644 --- a/src/arch/sparc/ua2005.cc +++ b/src/arch/sparc/ua2005.cc @@ -84,12 +84,12 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc) tickCompare = new TickCompareEvent(this, tc); setRegNoEffect(miscReg, val); if ((tick_cmpr & ~mask(63)) && tickCompare->scheduled()) - tickCompare->deschedule(); + cpu->deschedule(tickCompare); time = (tick_cmpr & mask(63)) - (tick & mask(63)); if (!(tick_cmpr & ~mask(63)) && time > 0) { if (tickCompare->scheduled()) - tickCompare->deschedule(); - tickCompare->schedule(time * cpu->ticks(1)); + cpu->deschedule(tickCompare); + cpu->schedule(tickCompare, curTick + time * cpu->ticks(1)); } panic("writing to TICK compare register %#X\n", val); break; @@ -99,13 +99,13 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc) sTickCompare = new STickCompareEvent(this, tc); setRegNoEffect(miscReg, val); if ((stick_cmpr & ~mask(63)) && sTickCompare->scheduled()) - sTickCompare->deschedule(); + cpu->deschedule(sTickCompare); time = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) - cpu->instCount(); if (!(stick_cmpr & ~mask(63)) && time > 0) { if (sTickCompare->scheduled()) - sTickCompare->deschedule(); - sTickCompare->schedule(time * cpu->ticks(1) + curTick); + cpu->deschedule(sTickCompare); + cpu->schedule(sTickCompare, curTick + time * cpu->ticks(1)); } DPRINTF(Timer, "writing to sTICK compare register value %#X\n", val); break; @@ -169,13 +169,13 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc) hSTickCompare = new HSTickCompareEvent(this, tc); setRegNoEffect(miscReg, val); if ((hstick_cmpr & ~mask(63)) && hSTickCompare->scheduled()) - hSTickCompare->deschedule(); + cpu->deschedule(hSTickCompare); time = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) - cpu->instCount(); if (!(hstick_cmpr & ~mask(63)) && time > 0) { if (hSTickCompare->scheduled()) - hSTickCompare->deschedule(); - hSTickCompare->schedule(curTick + time * cpu->ticks(1)); + cpu->deschedule(hSTickCompare); + cpu->schedule(hSTickCompare, curTick + time * cpu->ticks(1)); } DPRINTF(Timer, "writing to hsTICK compare register value %#X\n", val); break; @@ -296,12 +296,14 @@ MiscRegFile::processTickCompare(ThreadContext *tc) void MiscRegFile::processSTickCompare(ThreadContext *tc) { + BaseCPU *cpu = tc->getCpuPtr(); + // since our microcode instructions take two cycles we need to check if // we're actually at the correct cycle or we need to wait a little while // more int ticks; ticks = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) - - tc->getCpuPtr()->instCount(); + cpu->instCount(); assert(ticks >= 0 && "stick compare missed interrupt cycle"); if (ticks == 0 || tc->status() == ThreadContext::Suspended) { @@ -311,12 +313,14 @@ MiscRegFile::processSTickCompare(ThreadContext *tc) setReg(MISCREG_SOFTINT, softint | (ULL(1) << 16), tc); } } else - sTickCompare->schedule(ticks * tc->getCpuPtr()->ticks(1) + curTick); + cpu->schedule(sTickCompare, curTick + ticks * cpu->ticks(1)); } void MiscRegFile::processHSTickCompare(ThreadContext *tc) { + BaseCPU *cpu = tc->getCpuPtr(); + // since our microcode instructions take two cycles we need to check if // we're actually at the correct cycle or we need to wait a little while // more @@ -326,7 +330,7 @@ MiscRegFile::processHSTickCompare(ThreadContext *tc) return; ticks = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) - - tc->getCpuPtr()->instCount(); + cpu->instCount(); assert(ticks >= 0 && "hstick compare missed interrupt cycle"); if (ticks == 0 || tc->status() == ThreadContext::Suspended) { @@ -337,6 +341,6 @@ MiscRegFile::processHSTickCompare(ThreadContext *tc) } // Need to do something to cause interrupt to happen here !!! @todo } else - hSTickCompare->schedule(ticks * tc->getCpuPtr()->ticks(1) + curTick); + cpu->schedule(hSTickCompare, curTick + ticks * cpu->ticks(1)); } diff --git a/src/arch/x86/miscregfile.hh b/src/arch/x86/miscregfile.hh index 3abe4ec58..21caf3aa1 100644 --- a/src/arch/x86/miscregfile.hh +++ b/src/arch/x86/miscregfile.hh @@ -115,10 +115,8 @@ namespace X86ISA class ApicTimerEvent : public Event { public: - ApicTimerEvent() : Event(&mainEventQueue) - {} - - void process() + void + process() { warn("Local APIC timer event doesn't do anything!\n"); } diff --git a/src/arch/x86/regfile.cc b/src/arch/x86/regfile.cc index 3fda345cc..c8ec2a957 100644 --- a/src/arch/x86/regfile.cc +++ b/src/arch/x86/regfile.cc @@ -228,7 +228,8 @@ int X86ISA::flattenFloatIndex(ThreadContext * tc, int reg) return reg; } -void RegFile::serialize(std::ostream &os) +void +RegFile::serialize(EventManager *em, std::ostream &os) { intRegFile.serialize(os); floatRegFile.serialize(os); @@ -237,7 +238,8 @@ void RegFile::serialize(std::ostream &os) SERIALIZE_SCALAR(nextRip); } -void RegFile::unserialize(Checkpoint *cp, const std::string §ion) +void +RegFile::unserialize(EventManager *em, Checkpoint *cp, const string §ion) { intRegFile.unserialize(cp, section); floatRegFile.unserialize(cp, section); diff --git a/src/arch/x86/regfile.hh b/src/arch/x86/regfile.hh index 650181aca..3c2387346 100644 --- a/src/arch/x86/regfile.hh +++ b/src/arch/x86/regfile.hh @@ -68,6 +68,7 @@ #include class Checkpoint; +class EventManager; namespace X86ISA { @@ -139,8 +140,9 @@ namespace X86ISA void setIntReg(int intReg, const IntReg &val); - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); + void serialize(EventManager *em, std::ostream &os); + void unserialize(EventManager *em, Checkpoint *cp, + const std::string §ion); public: diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 7b6404419..5a0359e53 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -60,13 +60,12 @@ vector BaseCPU::cpuList; // been initialized int maxThreadsPerCPU = 1; -CPUProgressEvent::CPUProgressEvent(EventQueue *q, Tick ival, - BaseCPU *_cpu) - : Event(q, Event::Progress_Event_Pri), interval(ival), - lastNumInst(0), cpu(_cpu) +CPUProgressEvent::CPUProgressEvent(BaseCPU *_cpu, Tick ival) + : Event(Event::Progress_Event_Pri), interval(ival), lastNumInst(0), + cpu(_cpu) { if (interval) - schedule(curTick + interval); + cpu->schedule(this, curTick + interval); } void @@ -84,7 +83,7 @@ CPUProgressEvent::process() curTick, cpu->name(), temp - lastNumInst); #endif lastNumInst = temp; - schedule(curTick + interval); + cpu->schedule(this, curTick + interval); } const char * @@ -121,22 +120,26 @@ BaseCPU::BaseCPU(Params *p) // // set up instruction-count-based termination events, if any // - if (p->max_insts_any_thread != 0) - for (int i = 0; i < number_of_threads; ++i) - schedExitSimLoop("a thread reached the max instruction count", - p->max_insts_any_thread, 0, - comInstEventQueue[i]); + if (p->max_insts_any_thread != 0) { + const char *cause = "a thread reached the max instruction count"; + for (int i = 0; i < number_of_threads; ++i) { + Event *event = new SimLoopExitEvent(cause, 0); + comInstEventQueue[i]->schedule(event, p->max_insts_any_thread); + } + } if (p->max_insts_all_threads != 0) { + const char *cause = "all threads reached the max instruction count"; + // allocate & initialize shared downcounter: each event will // decrement this when triggered; simulation will terminate // when counter reaches 0 int *counter = new int; *counter = number_of_threads; - for (int i = 0; i < number_of_threads; ++i) - new CountedExitEvent(comInstEventQueue[i], - "all threads reached the max instruction count", - p->max_insts_all_threads, *counter); + for (int i = 0; i < number_of_threads; ++i) { + Event *event = new CountedExitEvent(cause, *counter); + comInstEventQueue[i]->schedule(event, p->max_insts_any_thread); + } } // allocate per-thread load-based event queues @@ -147,22 +150,25 @@ BaseCPU::BaseCPU(Params *p) // // set up instruction-count-based termination events, if any // - if (p->max_loads_any_thread != 0) - for (int i = 0; i < number_of_threads; ++i) - schedExitSimLoop("a thread reached the max load count", - p->max_loads_any_thread, 0, - comLoadEventQueue[i]); + if (p->max_loads_any_thread != 0) { + const char *cause = "a thread reached the max load count"; + for (int i = 0; i < number_of_threads; ++i) { + Event *event = new SimLoopExitEvent(cause, 0); + comLoadEventQueue[i]->schedule(event, p->max_loads_any_thread); + } + } if (p->max_loads_all_threads != 0) { + const char *cause = "all threads reached the max load count"; // allocate & initialize shared downcounter: each event will // decrement this when triggered; simulation will terminate // when counter reaches 0 int *counter = new int; *counter = number_of_threads; - for (int i = 0; i < number_of_threads; ++i) - new CountedExitEvent(comLoadEventQueue[i], - "all threads reached the max load count", - p->max_loads_all_threads, *counter); + for (int i = 0; i < number_of_threads; ++i) { + Event *event = new CountedExitEvent(cause, *counter); + comLoadEventQueue[i]->schedule(event, p->max_loads_all_threads); + } } functionTracingEnabled = false; @@ -174,9 +180,9 @@ BaseCPU::BaseCPU(Params *p) if (p->function_trace_start == 0) { functionTracingEnabled = true; } else { - new EventWrapper( - this, p->function_trace_start, true); + typedef EventWrapper wrap; + Event *event = new wrap(this, true); + schedule(event, p->function_trace_start); } } #if FULL_SYSTEM @@ -209,13 +215,13 @@ BaseCPU::startup() { #if FULL_SYSTEM if (!params()->defer_registration && profileEvent) - profileEvent->schedule(curTick); + schedule(profileEvent, curTick); #endif if (params()->progress_interval) { - new CPUProgressEvent(&mainEventQueue, - ticks(params()->progress_interval), - this); + Tick num_ticks = ticks(params()->progress_interval); + Event *event = new CPUProgressEvent(this, num_ticks); + schedule(event, curTick + num_ticks); } } @@ -300,7 +306,7 @@ BaseCPU::switchOut() // panic("This CPU doesn't support sampling!"); #if FULL_SYSTEM if (profileEvent && profileEvent->scheduled()) - profileEvent->deschedule(); + deschedule(profileEvent); #endif } @@ -336,7 +342,7 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc) threadContexts[i]->profileClear(); if (profileEvent) - profileEvent->schedule(curTick); + schedule(profileEvent, curTick); #endif // Connect new CPU to old CPU's memory only if new CPU isn't @@ -358,7 +364,7 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc) #if FULL_SYSTEM BaseCPU::ProfileEvent::ProfileEvent(BaseCPU *_cpu, Tick _interval) - : Event(&mainEventQueue), cpu(_cpu), interval(_interval) + : cpu(_cpu), interval(_interval) { } void @@ -369,7 +375,7 @@ BaseCPU::ProfileEvent::process() tc->profileSample(); } - schedule(curTick + interval); + cpu->schedule(this, curTick + interval); } void diff --git a/src/cpu/base.hh b/src/cpu/base.hh index 251adc1b7..c2b78a675 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -65,7 +65,7 @@ class CPUProgressEvent : public Event BaseCPU *cpu; public: - CPUProgressEvent(EventQueue *q, Tick ival, BaseCPU *_cpu); + CPUProgressEvent(BaseCPU *_cpu, Tick ival); void process(); diff --git a/src/cpu/cpuevent.hh b/src/cpu/cpuevent.hh index 5816c6ca1..65f0e87e1 100644 --- a/src/cpu/cpuevent.hh +++ b/src/cpu/cpuevent.hh @@ -58,8 +58,8 @@ class CpuEvent : public Event ThreadContext *tc; public: - CpuEvent(EventQueue *q, ThreadContext *_tc, Priority p = Default_Pri) - : Event(q, p), tc(_tc) + CpuEvent(ThreadContext *_tc, Priority p = Default_Pri) + : Event(p), tc(_tc) { cpuEventList.push_back(this); } /** delete the cpu event from the global list. */ @@ -81,9 +81,8 @@ class CpuEventWrapper : public CpuEvent T *object; public: - CpuEventWrapper(T *obj, ThreadContext *_tc, - EventQueue *q = &mainEventQueue, Priority p = Default_Pri) - : CpuEvent(q, _tc, p), object(obj) + CpuEventWrapper(T *obj, ThreadContext *_tc, Priority p = Default_Pri) + : CpuEvent(_tc, p), object(obj) { } void process() { (object->*F)(tc); } }; diff --git a/src/cpu/memtest/memtest.cc b/src/cpu/memtest/memtest.cc index 42889163a..9e5b9d099 100644 --- a/src/cpu/memtest/memtest.cc +++ b/src/cpu/memtest/memtest.cc @@ -152,7 +152,7 @@ MemTest::MemTest(const Params *p) // set up counters noResponseCycles = 0; numReads = 0; - tickEvent.schedule(0); + schedule(tickEvent, 0); id = TESTER_ALLOCATOR++; @@ -262,7 +262,7 @@ void MemTest::tick() { if (!tickEvent.scheduled()) - tickEvent.schedule(curTick + ticks(1)); + schedule(tickEvent, curTick + ticks(1)); if (++noResponseCycles >= 500000) { cerr << name() << ": deadlocked at cycle " << curTick << endl; diff --git a/src/cpu/memtest/memtest.hh b/src/cpu/memtest/memtest.hh index 5a7e0b9ae..82438b41f 100644 --- a/src/cpu/memtest/memtest.hh +++ b/src/cpu/memtest/memtest.hh @@ -74,10 +74,10 @@ class MemTest : public MemObject { private: MemTest *cpu; + public: - TickEvent(MemTest *c) - : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c) {} - void process() {cpu->tick();} + TickEvent(MemTest *c) : Event(CPU_Tick_Pri), cpu(c) {} + void process() { cpu->tick(); } virtual const char *description() const { return "MemTest tick"; } }; diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index b16955691..68fc6ef3b 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -51,7 +51,7 @@ template DefaultCommit::TrapEvent::TrapEvent(DefaultCommit *_commit, unsigned _tid) - : Event(&mainEventQueue, CPU_Tick_Pri), commit(_commit), tid(_tid) + : Event(CPU_Tick_Pri), commit(_commit), tid(_tid) { this->setFlags(Event::AutoDelete); } @@ -462,7 +462,7 @@ DefaultCommit::generateTrapEvent(unsigned tid) TrapEvent *trap = new TrapEvent(this, tid); - trap->schedule(curTick + trapLatency); + cpu->schedule(trap, curTick + trapLatency); trapInFlight[tid] = true; } diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 18b417141..eb1115565 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -74,7 +74,7 @@ BaseO3CPU::regStats() template FullO3CPU::TickEvent::TickEvent(FullO3CPU *c) - : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c) + : Event(CPU_Tick_Pri), cpu(c) { } @@ -94,7 +94,7 @@ FullO3CPU::TickEvent::description() const template FullO3CPU::ActivateThreadEvent::ActivateThreadEvent() - : Event(&mainEventQueue, CPU_Switch_Pri) + : Event(CPU_Switch_Pri) { } @@ -123,7 +123,7 @@ FullO3CPU::ActivateThreadEvent::description() const template FullO3CPU::DeallocateContextEvent::DeallocateContextEvent() - : Event(&mainEventQueue, CPU_Tick_Pri), tid(0), remove(false), cpu(NULL) + : Event(CPU_Tick_Pri), tid(0), remove(false), cpu(NULL) { } @@ -576,7 +576,7 @@ FullO3CPU::tick() lastRunningCycle = curTick; timesIdled++; } else { - tickEvent.schedule(nextCycle(curTick + ticks(1))); + schedule(tickEvent, nextCycle(curTick + ticks(1))); DPRINTF(O3CPU, "Scheduling next tick!\n"); } } @@ -584,7 +584,6 @@ FullO3CPU::tick() #if !FULL_SYSTEM updateThreadPriority(); #endif - } template @@ -1121,7 +1120,7 @@ FullO3CPU::resume() #endif if (!tickEvent.scheduled()) - tickEvent.schedule(nextCycle()); + schedule(tickEvent, nextCycle()); _status = Running; } @@ -1214,11 +1213,11 @@ FullO3CPU::takeOverFrom(BaseCPU *oldCPU) ThreadContext *tc = threadContexts[i]; if (tc->status() == ThreadContext::Active && _status != Running) { _status = Running; - tickEvent.schedule(nextCycle()); + schedule(tickEvent, nextCycle()); } } if (!tickEvent.scheduled()) - tickEvent.schedule(nextCycle()); + schedule(tickEvent, nextCycle()); } template @@ -1687,7 +1686,7 @@ FullO3CPU::wakeCPU() idleCycles += tickToCycles((curTick - 1) - lastRunningCycle); numCycles += tickToCycles((curTick - 1) - lastRunningCycle); - tickEvent.schedule(nextCycle()); + schedule(tickEvent, nextCycle()); } template diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 065dd10a0..406d965be 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -148,9 +148,9 @@ class FullO3CPU : public BaseO3CPU void scheduleTickEvent(int delay) { if (tickEvent.squashed()) - tickEvent.reschedule(nextCycle(curTick + ticks(delay))); + reschedule(tickEvent, nextCycle(curTick + ticks(delay))); else if (!tickEvent.scheduled()) - tickEvent.schedule(nextCycle(curTick + ticks(delay))); + schedule(tickEvent, nextCycle(curTick + ticks(delay))); } /** Unschedule tick event, regardless of its current state. */ @@ -188,11 +188,11 @@ class FullO3CPU : public BaseO3CPU { // Schedule thread to activate, regardless of its current state. if (activateThreadEvent[tid].squashed()) - activateThreadEvent[tid]. - reschedule(nextCycle(curTick + ticks(delay))); + reschedule(activateThreadEvent[tid], + nextCycle(curTick + ticks(delay))); else if (!activateThreadEvent[tid].scheduled()) - activateThreadEvent[tid]. - schedule(nextCycle(curTick + ticks(delay))); + schedule(activateThreadEvent[tid], + nextCycle(curTick + ticks(delay))); } /** Unschedule actiavte thread event, regardless of its current state. */ @@ -246,11 +246,11 @@ class FullO3CPU : public BaseO3CPU { // Schedule thread to activate, regardless of its current state. if (deallocateContextEvent[tid].squashed()) - deallocateContextEvent[tid]. - reschedule(nextCycle(curTick + ticks(delay))); + reschedule(deallocateContextEvent[tid], + nextCycle(curTick + ticks(delay))); else if (!deallocateContextEvent[tid].scheduled()) - deallocateContextEvent[tid]. - schedule(nextCycle(curTick + ticks(delay))); + schedule(deallocateContextEvent[tid], + nextCycle(curTick + ticks(delay))); } /** Unschedule thread deallocation in CPU */ diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index f12228ff9..9886b6675 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -82,7 +82,7 @@ class DefaultFetch public: /** Default constructor. */ IcachePort(DefaultFetch *_fetch) - : Port(_fetch->name() + "-iport"), fetch(_fetch) + : Port(_fetch->name() + "-iport", _fetch->cpu), fetch(_fetch) { } bool snoopRangeSent; diff --git a/src/cpu/o3/inst_queue_impl.hh b/src/cpu/o3/inst_queue_impl.hh index f3ce770fa..1d0f4b9f6 100644 --- a/src/cpu/o3/inst_queue_impl.hh +++ b/src/cpu/o3/inst_queue_impl.hh @@ -41,10 +41,9 @@ template InstructionQueue::FUCompletion::FUCompletion(DynInstPtr &_inst, - int fu_idx, - InstructionQueue *iq_ptr) - : Event(&mainEventQueue, Stat_Event_Pri), - inst(_inst), fuIdx(fu_idx), iqPtr(iq_ptr), freeFU(false) + int fu_idx, InstructionQueue *iq_ptr) + : Event(Stat_Event_Pri), inst(_inst), fuIdx(fu_idx), iqPtr(iq_ptr), + freeFU(false) { this->setFlags(Event::AutoDelete); } @@ -754,7 +753,7 @@ InstructionQueue::scheduleReadyInsts() FUCompletion *execution = new FUCompletion(issuing_inst, idx, this); - execution->schedule(curTick + cpu->ticks(op_latency - 1)); + cpu->schedule(execution, curTick + cpu->ticks(op_latency - 1)); // @todo: Enforce that issue_latency == 1 or op_latency if (issue_latency > 1) { diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh index 44b69ab40..f8a825726 100644 --- a/src/cpu/o3/lsq.hh +++ b/src/cpu/o3/lsq.hh @@ -298,7 +298,7 @@ class LSQ { public: /** Default constructor. */ DcachePort(LSQ *_lsq) - : Port(_lsq->name() + "-dport"), lsq(_lsq) + : Port(_lsq->name() + "-dport", _lsq->cpu), lsq(_lsq) { } bool snoopRangeSent; diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh index a82ba3ad5..8af8f18e6 100644 --- a/src/cpu/o3/lsq_unit.hh +++ b/src/cpu/o3/lsq_unit.hh @@ -584,7 +584,7 @@ LSQUnit::read(Request *req, T &data, int load_idx) // We'll say this has a 1 cycle load-store forwarding latency // for now. // @todo: Need to make this a parameter. - wb->schedule(curTick); + cpu->schedule(wb, curTick); ++lsqForwLoads; return NoFault; diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh index 4b8d693a6..85662d496 100644 --- a/src/cpu/o3/lsq_unit_impl.hh +++ b/src/cpu/o3/lsq_unit_impl.hh @@ -45,7 +45,7 @@ template LSQUnit::WritebackEvent::WritebackEvent(DynInstPtr &_inst, PacketPtr _pkt, LSQUnit *lsq_ptr) - : Event(&mainEventQueue), inst(_inst), pkt(_pkt), lsqPtr(lsq_ptr) + : inst(_inst), pkt(_pkt), lsqPtr(lsq_ptr) { this->setFlags(Event::AutoDelete); } @@ -684,7 +684,7 @@ LSQUnit::writebackStores() "Instantly completing it.\n", inst->seqNum); WritebackEvent *wb = new WritebackEvent(inst, data_pkt, this); - wb->schedule(curTick + 1); + cpu->schedule(wb, curTick + 1); completeStore(storeWBIdx); incrStIdx(storeWBIdx); continue; diff --git a/src/cpu/quiesce_event.cc b/src/cpu/quiesce_event.cc index 81384d529..38ffb74e4 100644 --- a/src/cpu/quiesce_event.cc +++ b/src/cpu/quiesce_event.cc @@ -33,7 +33,7 @@ #include "cpu/quiesce_event.hh" EndQuiesceEvent::EndQuiesceEvent(ThreadContext *_tc) - : Event(&mainEventQueue), tc(_tc) + : tc(_tc) { } diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 7ed1ee0c3..154a66162 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -43,7 +43,7 @@ using namespace std; using namespace TheISA; AtomicSimpleCPU::TickEvent::TickEvent(AtomicSimpleCPU *c) - : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c) + : Event(CPU_Tick_Pri), cpu(c) { } @@ -201,9 +201,8 @@ AtomicSimpleCPU::resume() changeState(SimObject::Running); if (thread->status() == ThreadContext::Active) { - if (!tickEvent.scheduled()) { - tickEvent.schedule(nextCycle()); - } + if (!tickEvent.scheduled()) + schedule(tickEvent, nextCycle()); } } @@ -230,7 +229,7 @@ AtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU) ThreadContext *tc = threadContexts[i]; if (tc->status() == ThreadContext::Active && _status != Running) { _status = Running; - tickEvent.schedule(nextCycle()); + schedule(tickEvent, nextCycle()); break; } } @@ -260,7 +259,7 @@ AtomicSimpleCPU::activateContext(int thread_num, int delay) numCycles += tickToCycles(thread->lastActivate - thread->lastSuspend); //Make sure ticks are still on multiples of cycles - tickEvent.schedule(nextCycle(curTick + ticks(delay))); + schedule(tickEvent, nextCycle(curTick + ticks(delay))); _status = Running; } @@ -278,7 +277,7 @@ AtomicSimpleCPU::suspendContext(int thread_num) // tick event may not be scheduled if this gets called from inside // an instruction's execution, e.g. "quiesce" if (tickEvent.scheduled()) - tickEvent.deschedule(); + deschedule(tickEvent); notIdleFraction--; _status = Idle; @@ -794,7 +793,7 @@ AtomicSimpleCPU::tick() latency = ticks(1); if (_status != Idle) - tickEvent.schedule(curTick + latency); + schedule(tickEvent, curTick + latency); } diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index ac67341ff..c4635d6a3 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -101,7 +101,7 @@ void TimingSimpleCPU::CpuPort::TickEvent::schedule(PacketPtr _pkt, Tick t) { pkt = _pkt; - Event::schedule(t); + cpu->schedule(this, t); } TimingSimpleCPU::TimingSimpleCPU(TimingSimpleCPUParams *p) @@ -165,7 +165,7 @@ TimingSimpleCPU::resume() // Delete the old event if it existed. if (fetchEvent) { if (fetchEvent->scheduled()) - fetchEvent->deschedule(); + deschedule(fetchEvent); delete fetchEvent; } @@ -186,7 +186,7 @@ TimingSimpleCPU::switchOut() // If we've been scheduled to resume but are then told to switch out, // we'll need to cancel it. if (fetchEvent && fetchEvent->scheduled()) - fetchEvent->deschedule(); + deschedule(fetchEvent); } @@ -228,7 +228,8 @@ TimingSimpleCPU::activateContext(int thread_num, int delay) _status = Running; // kick things off by initiating the fetch of the next instruction - fetchEvent = new FetchEvent(this, nextCycle(curTick + ticks(delay))); + fetchEvent = new FetchEvent(this); + schedule(fetchEvent, nextCycle(curTick + ticks(delay))); } @@ -819,10 +820,11 @@ TimingSimpleCPU::DcachePort::recvRetry() } } -TimingSimpleCPU::IprEvent::IprEvent(Packet *_pkt, TimingSimpleCPU *_cpu, Tick t) - : Event(&mainEventQueue), pkt(_pkt), cpu(_cpu) +TimingSimpleCPU::IprEvent::IprEvent(Packet *_pkt, TimingSimpleCPU *_cpu, + Tick t) + : pkt(_pkt), cpu(_cpu) { - schedule(t); + cpu->schedule(this, t); } void diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index e405f6a41..081051ea7 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -80,8 +80,7 @@ class TimingSimpleCPU : public BaseSimpleCPU PacketPtr pkt; TimingSimpleCPU *cpu; - TickEvent(TimingSimpleCPU *_cpu) - :Event(&mainEventQueue), cpu(_cpu) {} + TickEvent(TimingSimpleCPU *_cpu) : cpu(_cpu) {} const char *description() const { return "Timing CPU tick"; } void schedule(PacketPtr _pkt, Tick t); }; diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index 0124184e0..42da659f2 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -189,7 +189,7 @@ void SimpleThread::serialize(ostream &os) { ThreadState::serialize(os); - regs.serialize(os); + regs.serialize(cpu, os); // thread_num and cpu_id are deterministic from the config } @@ -198,7 +198,7 @@ void SimpleThread::unserialize(Checkpoint *cp, const std::string §ion) { ThreadState::unserialize(cp, section); - regs.unserialize(cp, section); + regs.unserialize(cpu, cp, section); // thread_num and cpu_id are deterministic from the config } diff --git a/src/cpu/thread_state.cc b/src/cpu/thread_state.cc index 18845baf7..8d519c563 100644 --- a/src/cpu/thread_state.cc +++ b/src/cpu/thread_state.cc @@ -105,7 +105,7 @@ ThreadState::unserialize(Checkpoint *cp, const std::string §ion) Tick quiesceEndTick; UNSERIALIZE_SCALAR(quiesceEndTick); if (quiesceEndTick) - quiesceEvent->schedule(quiesceEndTick); + baseCpu->schedule(quiesceEvent, quiesceEndTick); if (kernelStats) kernelStats->unserialize(cp, section); #endif diff --git a/src/dev/alpha/tsunami_io.cc b/src/dev/alpha/tsunami_io.cc index fa4e697cf..2aaf323a2 100644 --- a/src/dev/alpha/tsunami_io.cc +++ b/src/dev/alpha/tsunami_io.cc @@ -56,14 +56,15 @@ using namespace std; //Should this be AlphaISA? using namespace TheISA; -TsunamiIO::TsunamiRTC::TsunamiRTC(const string &n, const TsunamiIOParams *p) : - MC146818(n, p->time, p->year_is_bcd, p->frequency), tsunami(p->tsunami) +TsunamiIO::RTC::RTC(const string &n, const TsunamiIOParams *p) + : MC146818(p->tsunami, n, p->time, p->year_is_bcd, p->frequency), + tsunami(p->tsunami) { } TsunamiIO::TsunamiIO(const Params *p) - : BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"), - rtc(p->name + ".rtc", p) + : BasicPioDevice(p), tsunami(p->tsunami), + pitimer(this, p->name + "pitimer"), rtc(p->name + ".rtc", p) { pioSize = 0x100; diff --git a/src/dev/alpha/tsunami_io.hh b/src/dev/alpha/tsunami_io.hh index 736f498c7..b6d63322b 100644 --- a/src/dev/alpha/tsunami_io.hh +++ b/src/dev/alpha/tsunami_io.hh @@ -56,11 +56,11 @@ class TsunamiIO : public BasicPioDevice protected: - class TsunamiRTC : public MC146818 + class RTC : public MC146818 { public: - Tsunami * tsunami; - TsunamiRTC(const std::string &n, const TsunamiIOParams *p); + Tsunami *tsunami; + RTC(const std::string &n, const TsunamiIOParams *p); protected: void handleEvent() @@ -94,7 +94,7 @@ class TsunamiIO : public BasicPioDevice /** Intel 8253 Periodic Interval Timer */ Intel8254Timer pitimer; - TsunamiRTC rtc; + RTC rtc; uint8_t rtcAddr; diff --git a/src/dev/etherbus.cc b/src/dev/etherbus.cc index 2316bfed9..063a594e7 100644 --- a/src/dev/etherbus.cc +++ b/src/dev/etherbus.cc @@ -49,7 +49,7 @@ using namespace std; EtherBus::EtherBus(const Params *p) : EtherObject(p), ticksPerByte(p->speed), loopback(p->loopback), - event(&mainEventQueue, this), sender(0), dump(p->dump) + event(this), sender(0), dump(p->dump) { } @@ -99,7 +99,7 @@ EtherBus::send(EtherInt *sndr, EthPacketPtr &pkt) int delay = (int)ceil(((double)pkt->length * ticksPerByte) + 1.0); DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", delay, ticksPerByte); - event.schedule(curTick + delay); + schedule(event, curTick + delay); return true; } diff --git a/src/dev/etherbus.hh b/src/dev/etherbus.hh index 624ceb81a..6408f7f1f 100644 --- a/src/dev/etherbus.hh +++ b/src/dev/etherbus.hh @@ -59,8 +59,7 @@ class EtherBus : public EtherObject EtherBus *bus; public: - DoneEvent(EventQueue *q, EtherBus *b) - : Event(q), bus(b) {} + DoneEvent(EtherBus *b) : bus(b) {} virtual void process() { bus->txDone(); } virtual const char *description() const { return "ethernet bus completion"; } diff --git a/src/dev/etherlink.cc b/src/dev/etherlink.cc index b1266000b..f3f38fc20 100644 --- a/src/dev/etherlink.cc +++ b/src/dev/etherlink.cc @@ -135,7 +135,7 @@ class LinkDelayEvent : public Event public: // non-scheduling version for createForUnserialize() LinkDelayEvent(); - LinkDelayEvent(EtherLink::Link *link, EthPacketPtr pkt, Tick when); + LinkDelayEvent(EtherLink::Link *link, EthPacketPtr pkt); void process(); @@ -153,7 +153,8 @@ EtherLink::Link::txDone() if (linkDelay > 0) { DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay); - new LinkDelayEvent(this, packet, curTick + linkDelay); + Event *event = new LinkDelayEvent(this, packet); + parent->schedule(event, curTick + linkDelay); } else { txComplete(packet); } @@ -182,7 +183,7 @@ EtherLink::Link::transmit(EthPacketPtr pkt) DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n", delay, ticksPerByte); - doneEvent.schedule(curTick + delay); + parent->schedule(doneEvent, curTick + delay); return true; } @@ -220,23 +221,22 @@ EtherLink::Link::unserialize(const string &base, Checkpoint *cp, if (event_scheduled) { Tick event_time; paramIn(cp, section, base + ".event_time", event_time); - doneEvent.schedule(event_time); + parent->schedule(doneEvent, event_time); } } LinkDelayEvent::LinkDelayEvent() - : Event(&mainEventQueue), link(NULL) + : link(NULL) { setFlags(AutoSerialize); setFlags(AutoDelete); } -LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, EthPacketPtr p, Tick when) - : Event(&mainEventQueue), link(l), packet(p) +LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, EthPacketPtr p) + : link(l), packet(p) { setFlags(AutoSerialize); setFlags(AutoDelete); - schedule(when); } void diff --git a/src/dev/ethertap.cc b/src/dev/ethertap.cc index f1fd1800b..85d6370be 100644 --- a/src/dev/ethertap.cc +++ b/src/dev/ethertap.cc @@ -246,7 +246,7 @@ EtherTap::process(int revent) DPRINTF(Ethernet, "bus busy...buffer for retransmission\n"); packetBuffer.push(packet); if (!txEvent.scheduled()) - txEvent.schedule(curTick + retryTime); + schedule(txEvent, curTick + retryTime); } else if (dump) { dump->dump(packet); } @@ -269,7 +269,7 @@ EtherTap::retransmit() } if (!packetBuffer.empty() && !txEvent.scheduled()) - txEvent.schedule(curTick + retryTime); + schedule(txEvent, curTick + retryTime); } EtherInt* diff --git a/src/dev/ethertap.hh b/src/dev/ethertap.hh index be3d73a24..ac287cecb 100644 --- a/src/dev/ethertap.hh +++ b/src/dev/ethertap.hh @@ -90,8 +90,7 @@ class EtherTap : public EtherObject EtherTap *tap; public: - TxEvent(EtherTap *_tap) - : Event(&mainEventQueue), tap(_tap) {} + TxEvent(EtherTap *_tap) : tap(_tap) {} void process() { tap->retransmit(); } virtual const char *description() const { return "EtherTap retransmit"; } diff --git a/src/dev/i8254xGBe.cc b/src/dev/i8254xGBe.cc index f362a7a0a..0fbda1897 100644 --- a/src/dev/i8254xGBe.cc +++ b/src/dev/i8254xGBe.cc @@ -592,7 +592,7 @@ IGbE::postInterrupt(IntTypes t, bool now) if (regs.itr.interval() == 0 || now || lastInterrupt + itr_interval <= curTick) { if (interEvent.scheduled()) { - interEvent.deschedule(); + deschedule(interEvent); } cpuPostInt(); } else { @@ -601,7 +601,7 @@ IGbE::postInterrupt(IntTypes t, bool now) DPRINTF(EthernetIntr, "EINT: Scheduling timer interrupt for tick %d\n", int_time); if (!interEvent.scheduled()) { - interEvent.schedule(int_time); + schedule(interEvent, int_time); } } } @@ -628,24 +628,24 @@ IGbE::cpuPostInt() if (interEvent.scheduled()) { - interEvent.deschedule(); + deschedule(interEvent); } if (rdtrEvent.scheduled()) { regs.icr.rxt0(1); - rdtrEvent.deschedule(); + deschedule(rdtrEvent); } if (radvEvent.scheduled()) { regs.icr.rxt0(1); - radvEvent.deschedule(); + deschedule(radvEvent); } if (tadvEvent.scheduled()) { regs.icr.txdw(1); - tadvEvent.deschedule(); + deschedule(tadvEvent); } if (tidvEvent.scheduled()) { regs.icr.txdw(1); - tidvEvent.deschedule(); + deschedule(tidvEvent); } regs.icr.int_assert(1); @@ -677,7 +677,7 @@ IGbE::chkInterrupt() if (!(regs.icr() & regs.imr)) { DPRINTF(Ethernet, "Mask cleaned all interrupts\n"); if (interEvent.scheduled()) - interEvent.deschedule(); + deschedule(interEvent); if (regs.icr.int_assert()) cpuClearInt(); } @@ -691,7 +691,8 @@ IGbE::chkInterrupt() if (!interEvent.scheduled()) { DPRINTF(Ethernet, "Scheduling for %d\n", curTick + Clock::Int::ns * 256 * regs.itr.interval()); - interEvent.schedule(curTick + Clock::Int::ns * 256 * regs.itr.interval()); + schedule(interEvent, + curTick + Clock::Int::ns * 256 * regs.itr.interval()); } } } @@ -799,16 +800,16 @@ IGbE::RxDescCache::pktComplete() if (igbe->regs.rdtr.delay()) { DPRINTF(EthernetSM, "RXS: Scheduling DTR for %d\n", igbe->regs.rdtr.delay() * igbe->intClock()); - igbe->rdtrEvent.reschedule(curTick + igbe->regs.rdtr.delay() * - igbe->intClock(),true); + igbe->reschedule(igbe->rdtrEvent, + curTick + igbe->regs.rdtr.delay() * igbe->intClock(), true); } if (igbe->regs.radv.idv()) { DPRINTF(EthernetSM, "RXS: Scheduling ADV for %d\n", igbe->regs.radv.idv() * igbe->intClock()); if (!igbe->radvEvent.scheduled()) { - igbe->radvEvent.schedule(curTick + igbe->regs.radv.idv() * - igbe->intClock()); + igbe->schedule(igbe->radvEvent, + curTick + igbe->regs.radv.idv() * igbe->intClock()); } } @@ -1040,15 +1041,15 @@ IGbE::TxDescCache::pktComplete() DPRINTF(EthernetDesc, "Descriptor had IDE set\n"); if (igbe->regs.tidv.idv()) { DPRINTF(EthernetDesc, "setting tidv\n"); - igbe->tidvEvent.reschedule(curTick + igbe->regs.tidv.idv() * - igbe->intClock(), true); + igbe->reschedule(igbe->tidvEvent, + curTick + igbe->regs.tidv.idv() * igbe->intClock(), true); } if (igbe->regs.tadv.idv() && igbe->regs.tidv.idv()) { DPRINTF(EthernetDesc, "setting tadv\n"); if (!igbe->tadvEvent.scheduled()) { - igbe->tadvEvent.schedule(curTick + igbe->regs.tadv.idv() * - igbe->intClock()); + igbe->schedule(igbe->tadvEvent, + curTick + igbe->regs.tadv.idv() * igbe->intClock()); } } } @@ -1126,9 +1127,9 @@ IGbE::TxDescCache::hasOutstandingEvents() void IGbE::restartClock() { - if (!tickEvent.scheduled() && (rxTick || txTick || txFifoTick) && getState() == - SimObject::Running) - tickEvent.schedule((curTick/ticks(1)) * ticks(1) + ticks(1)); + if (!tickEvent.scheduled() && (rxTick || txTick || txFifoTick) && + getState() == SimObject::Running) + schedule(tickEvent, (curTick / ticks(1)) * ticks(1) + ticks(1)); } unsigned int @@ -1147,7 +1148,7 @@ IGbE::drain(Event *de) rxTick = false; if (tickEvent.scheduled()) - tickEvent.deschedule(); + deschedule(tickEvent); if (count) changeState(Draining); @@ -1432,7 +1433,7 @@ IGbE::tick() if (rxTick || txTick || txFifoTick) - tickEvent.schedule(curTick + ticks(1)); + schedule(tickEvent, curTick + ticks(1)); } void @@ -1538,19 +1539,19 @@ IGbE::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(inter_time); if (rdtr_time) - rdtrEvent.schedule(rdtr_time); + schedule(rdtrEvent, rdtr_time); if (radv_time) - radvEvent.schedule(radv_time); + schedule(radvEvent, radv_time); if (tidv_time) - tidvEvent.schedule(tidv_time); + schedule(tidvEvent, tidv_time); if (tadv_time) - tadvEvent.schedule(tadv_time); + schedule(tadvEvent, tadv_time); if (inter_time) - interEvent.schedule(inter_time); + schedule(interEvent, inter_time); txDescCache.unserialize(cp, csprintf("%s.TxDescCache", section)); diff --git a/src/dev/i8254xGBe.hh b/src/dev/i8254xGBe.hh index 4c3896e36..618145d07 100644 --- a/src/dev/i8254xGBe.hh +++ b/src/dev/i8254xGBe.hh @@ -293,14 +293,14 @@ class IGbE : public EtherDevice wbOut = max_to_wb; assert(!wbDelayEvent.scheduled()); - wbDelayEvent.schedule(igbe->wbDelay + curTick); + igbe->schedule(wbDelayEvent, curTick + igbe->wbDelay); } void writeback1() { // If we're draining delay issuing this DMA if (igbe->drainEvent) { - wbDelayEvent.schedule(igbe->wbDelay + curTick); + igbe->schedule(wbDelayEvent, curTick + igbe->wbDelay); return; } @@ -356,14 +356,14 @@ class IGbE : public EtherDevice curFetching = max_to_fetch; assert(!fetchDelayEvent.scheduled()); - fetchDelayEvent.schedule(igbe->fetchDelay + curTick); + igbe->schedule(fetchDelayEvent, curTick + igbe->fetchDelay); } void fetchDescriptors1() { // If we're draining delay issuing this DMA if (igbe->drainEvent) { - fetchDelayEvent.schedule(igbe->fetchDelay + curTick); + igbe->schedule(fetchDelayEvent, curTick + igbe->fetchDelay); return; } @@ -557,9 +557,9 @@ class IGbE : public EtherDevice UNSERIALIZE_SCALAR(fetch_delay); UNSERIALIZE_SCALAR(wb_delay); if (fetch_delay) - fetchDelayEvent.schedule(fetch_delay); + igbe->schedule(fetchDelayEvent, fetch_delay); if (wb_delay) - wbDelayEvent.schedule(wb_delay); + igbe->schedule(wbDelayEvent, wb_delay); } diff --git a/src/dev/ide_disk.cc b/src/dev/ide_disk.cc index 8f9999beb..9022cf087 100644 --- a/src/dev/ide_disk.cc +++ b/src/dev/ide_disk.cc @@ -315,7 +315,7 @@ IdeDisk::doDmaTransfer() dmaState, devState); if (ctrl->dmaPending() || ctrl->getState() != SimObject::Running) { - dmaTransferEvent.schedule(curTick + DMA_BACKOFF_PERIOD); + schedule(dmaTransferEvent, curTick + DMA_BACKOFF_PERIOD); return; } else ctrl->dmaRead(curPrdAddr, sizeof(PrdEntry_t), &dmaPrdReadEvent, @@ -349,7 +349,7 @@ IdeDisk::doDmaDataRead() DPRINTF(IdeDisk, "doDmaRead, diskDelay: %d totalDiskDelay: %d\n", diskDelay, totalDiskDelay); - dmaReadWaitEvent.schedule(curTick + totalDiskDelay); + schedule(dmaReadWaitEvent, curTick + totalDiskDelay); } void @@ -395,7 +395,7 @@ IdeDisk::doDmaRead() } if (ctrl->dmaPending() || ctrl->getState() != SimObject::Running) { - dmaReadWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD); + schedule(dmaReadWaitEvent, curTick + DMA_BACKOFF_PERIOD); return; } else if (!dmaReadCG->done()) { assert(dmaReadCG->complete() < MAX_DMA_SIZE); @@ -457,7 +457,7 @@ IdeDisk::doDmaDataWrite() cmdBytesLeft -= SectorSize; } - dmaWriteWaitEvent.schedule(curTick + totalDiskDelay); + schedule(dmaWriteWaitEvent, curTick + totalDiskDelay); } void @@ -470,7 +470,7 @@ IdeDisk::doDmaWrite() curPrd.getByteCount(), TheISA::PageBytes); } if (ctrl->dmaPending() || ctrl->getState() != SimObject::Running) { - dmaWriteWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD); + schedule(dmaWriteWaitEvent, curTick + DMA_BACKOFF_PERIOD); return; } else if (!dmaWriteCG->done()) { assert(dmaWriteCG->complete() < MAX_DMA_SIZE); @@ -545,7 +545,7 @@ IdeDisk::startDma(const uint32_t &prdTableBase) dmaState = Dma_Transfer; // schedule dma transfer (doDmaTransfer) - dmaTransferEvent.schedule(curTick + 1); + schedule(dmaTransferEvent, curTick + 1); } void @@ -1073,12 +1073,12 @@ IdeDisk::unserialize(Checkpoint *cp, const string §ion) switch (event) { case None : break; - case Transfer : dmaTransferEvent.schedule(reschedule); break; - case ReadWait : dmaReadWaitEvent.schedule(reschedule); break; - case WriteWait : dmaWriteWaitEvent.schedule(reschedule); break; - case PrdRead : dmaPrdReadEvent.schedule(reschedule); break; - case DmaRead : dmaReadEvent.schedule(reschedule); break; - case DmaWrite : dmaWriteEvent.schedule(reschedule); break; + case Transfer : schedule(dmaTransferEvent, reschedule); break; + case ReadWait : schedule(dmaReadWaitEvent, reschedule); break; + case WriteWait : schedule(dmaWriteWaitEvent, reschedule); break; + case PrdRead : schedule(dmaPrdReadEvent, reschedule); break; + case DmaRead : schedule(dmaReadEvent, reschedule); break; + case DmaWrite : schedule(dmaWriteEvent, reschedule); break; } // Unserialize device registers diff --git a/src/dev/intel_8254_timer.cc b/src/dev/intel_8254_timer.cc index 802dd44f5..27f55fd92 100644 --- a/src/dev/intel_8254_timer.cc +++ b/src/dev/intel_8254_timer.cc @@ -35,9 +35,11 @@ using namespace std; -Intel8254Timer::Intel8254Timer(const string &name) - : _name(name), counter0(name + ".counter0"), counter1(name + ".counter1"), - counter2(name + ".counter2") +Intel8254Timer::Intel8254Timer(EventManager *em, const string &name) + : EventManager(em), _name(name), + counter0(this, name + ".counter0"), + counter1(this, name + ".counter1"), + counter2(this, name + ".counter2") { counter[0] = &counter0; counter[1] = &counter0; @@ -80,10 +82,10 @@ Intel8254Timer::unserialize(const string &base, Checkpoint *cp, counter2.unserialize(base + ".counter2", cp, section); } -Intel8254Timer::Counter::Counter(const string &name) +Intel8254Timer::Counter::Counter(Intel8254Timer *p, const string &name) : _name(name), event(this), count(0), latched_count(0), period(0), mode(0), output_high(false), latch_on(false), read_byte(LSB), - write_byte(LSB) + write_byte(LSB), parent(p) { } @@ -140,7 +142,7 @@ Intel8254Timer::Counter::write(const uint8_t data) count = (count & 0xFF00) | data; if (event.scheduled()) - event.deschedule(); + parent->deschedule(event); output_high = false; write_byte = MSB; break; @@ -226,11 +228,10 @@ Intel8254Timer::Counter::unserialize(const string &base, Checkpoint *cp, Tick event_tick; paramIn(cp, section, base + ".event_tick", event_tick); if (event_tick) - event.schedule(event_tick); + parent->schedule(event, event_tick); } Intel8254Timer::Counter::CounterEvent::CounterEvent(Counter* c_ptr) - : Event(&mainEventQueue) { interval = (Tick)(Clock::Float::s / 1193180.0); counter = c_ptr; @@ -260,7 +261,7 @@ Intel8254Timer::Counter::CounterEvent::setTo(int clocks) panic("Timer can't be set to go off instantly.\n"); DPRINTF(Intel8254Timer, "Timer set to curTick + %d\n", clocks * interval); - schedule(curTick + clocks * interval); + counter->parent->schedule(this, curTick + clocks * interval); } const char * diff --git a/src/dev/intel_8254_timer.hh b/src/dev/intel_8254_timer.hh index 23596a687..439432aed 100644 --- a/src/dev/intel_8254_timer.hh +++ b/src/dev/intel_8254_timer.hh @@ -33,16 +33,16 @@ #ifndef __DEV_8254_HH__ #define __DEV_8254_HH__ +#include +#include + #include "base/bitunion.hh" #include "sim/eventq.hh" #include "sim/host.hh" #include "sim/serialize.hh" -#include -#include - /** Programmable Interval Timer (Intel 8254) */ -class Intel8254Timer +class Intel8254Timer : public EventManager { BitUnion8(CtrlReg) Bitfield<7, 6> sel; @@ -129,8 +129,11 @@ class Intel8254Timer /** Determine which byte of a 16-bit count value to read/write */ uint8_t read_byte, write_byte; + /** Pointer to container */ + Intel8254Timer *parent; + public: - Counter(const std::string &name); + Counter(Intel8254Timer *p, const std::string &name); /** Latch the current count (if one is not already latched) */ void latchCount(); @@ -183,7 +186,7 @@ class Intel8254Timer Counter counter1; Counter counter2; - Intel8254Timer(const std::string &name); + Intel8254Timer(EventManager *em, const std::string &name); /** Write control word */ void writeControl(const CtrlReg data); diff --git a/src/dev/io_device.cc b/src/dev/io_device.cc index 41fcec8ac..cdba171a6 100644 --- a/src/dev/io_device.cc +++ b/src/dev/io_device.cc @@ -117,7 +117,7 @@ DmaPort::recvTiming(PacketPtr pkt) else if (backoffTime < device->maxBackoffDelay) backoffTime <<= 1; - backoffEvent.reschedule(curTick + backoffTime, true); + reschedule(backoffEvent, curTick + backoffTime, true); DPRINTF(DMA, "Backoff time set to %d ticks\n", backoffTime); @@ -139,7 +139,7 @@ DmaPort::recvTiming(PacketPtr pkt) assert(state->totBytes >= state->numBytes); if (state->totBytes == state->numBytes) { if (state->delay) - state->completionEvent->schedule(state->delay + curTick); + schedule(state->completionEvent, curTick + state->delay); else state->completionEvent->process(); delete state; @@ -209,7 +209,7 @@ DmaPort::recvRetry() if (transmitList.size() && backoffTime && !inRetry) { DPRINTF(DMA, "Scheduling backoff for %d\n", curTick+backoffTime); if (!backoffEvent.scheduled()) - backoffEvent.schedule(backoffTime+curTick); + schedule(backoffEvent, backoffTime + curTick); } DPRINTF(DMA, "TransmitList: %d, backoffTime: %d inRetry: %d es: %d\n", transmitList.size(), backoffTime, inRetry, @@ -297,7 +297,7 @@ DmaPort::sendDma() !backoffEvent.scheduled()) { DPRINTF(DMA, "-- Scheduling backoff timer for %d\n", backoffTime+curTick); - backoffEvent.schedule(backoffTime+curTick); + schedule(backoffEvent, backoffTime + curTick); } } else if (state == Enums::atomic) { transmitList.pop_front(); @@ -317,7 +317,7 @@ DmaPort::sendDma() if (state->totBytes == state->numBytes) { assert(!state->completionEvent->scheduled()); - state->completionEvent->schedule(curTick + lat + state->delay); + schedule(state->completionEvent, curTick + lat + state->delay); delete state; delete pkt->req; } diff --git a/src/dev/mc146818.cc b/src/dev/mc146818.cc index 984422105..e5a81ff75 100644 --- a/src/dev/mc146818.cc +++ b/src/dev/mc146818.cc @@ -42,9 +42,9 @@ using namespace std; -MC146818::MC146818(const string &n, const struct tm time, - bool bcd, Tick frequency) - : _name(n), event(this, frequency) +MC146818::MC146818(EventManager *em, const string &n, const struct tm time, + bool bcd, Tick frequency) + : EventManager(em), _name(n), event(this, frequency) { memset(clock_data, 0, sizeof(clock_data)); stat_regA = RTCA_32768HZ | RTCA_1024HZ; @@ -75,6 +75,10 @@ MC146818::MC146818(const string &n, const struct tm time, DPRINTFN("Real-time clock set to %s", asctime(&time)); } +MC146818::~MC146818() +{ +} + void MC146818::writeData(const uint8_t addr, const uint8_t data) { @@ -96,7 +100,7 @@ MC146818::writeData(const uint8_t addr, const uint8_t data) event.scheduleIntr(); } else { if (event.scheduled()) - event.deschedule(); + deschedule(event); } stat_regB = data; break; @@ -153,27 +157,27 @@ MC146818::unserialize(const string &base, Checkpoint *cp, // We're not unserializing the event here, but we need to // rescehedule the event since curTick was moved forward by the // checkpoint - event.reschedule(curTick + event.interval); + reschedule(event, curTick + event.interval); } MC146818::RTCEvent::RTCEvent(MC146818 * _parent, Tick i) - : Event(&mainEventQueue), parent(_parent), interval(i) + : parent(_parent), interval(i) { DPRINTF(MC146818, "RTC Event Initilizing\n"); - schedule(curTick + interval); + parent->schedule(this, curTick + interval); } void MC146818::RTCEvent::scheduleIntr() { - schedule(curTick + interval); + parent->schedule(this, curTick + interval); } void MC146818::RTCEvent::process() { DPRINTF(MC146818, "RTC Timer Interrupt\n"); - schedule(curTick + interval); + parent->schedule(this, curTick + interval); parent->handleEvent(); } diff --git a/src/dev/mc146818.hh b/src/dev/mc146818.hh index f91e462d9..e145ad3fd 100644 --- a/src/dev/mc146818.hh +++ b/src/dev/mc146818.hh @@ -37,7 +37,7 @@ #include "sim/eventq.hh" /** Real-Time Clock (MC146818) */ -class MC146818 +class MC146818 : public EventManager { protected: virtual void handleEvent() @@ -96,11 +96,9 @@ class MC146818 uint8_t stat_regB; public: - virtual ~MC146818() - {} - - MC146818(const std::string &name, const struct tm time, + MC146818(EventManager *em, const std::string &name, const struct tm time, bool bcd, Tick frequency); + virtual ~MC146818(); /** RTC write data */ void writeData(const uint8_t addr, const uint8_t data); diff --git a/src/dev/ns_gige.cc b/src/dev/ns_gige.cc index f19ca20e5..d326b103f 100644 --- a/src/dev/ns_gige.cc +++ b/src/dev/ns_gige.cc @@ -945,7 +945,8 @@ NSGigE::cpuIntrPost(Tick when) if (intrEvent) intrEvent->squash(); - intrEvent = new IntrEvent(this, intrTick, true); + intrEvent = new IntrEvent(this, true); + schedule(intrEvent, intrTick); } void @@ -1442,7 +1443,7 @@ NSGigE::rxKick() NsRxStateStrings[rxState]); if (clock && !rxKickEvent.scheduled()) - rxKickEvent.schedule(rxKickTick); + schedule(rxKickEvent, rxKickTick); } void @@ -1492,7 +1493,7 @@ NSGigE::transmit() if (!txFifo.empty() && !txEvent.scheduled()) { DPRINTF(Ethernet, "reschedule transmit\n"); - txEvent.schedule(curTick + retryTime); + schedule(txEvent, curTick + retryTime); } } @@ -1885,7 +1886,7 @@ NSGigE::txKick() NsTxStateStrings[txState]); if (clock && !txKickEvent.scheduled()) - txKickEvent.schedule(txKickTick); + schedule(txKickEvent, txKickTick); } /** @@ -1999,7 +2000,7 @@ NSGigE::transferDone() DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n"); - txEvent.reschedule(curTick + ticks(1), true); + reschedule(txEvent, curTick + ticks(1), true); } bool @@ -2400,7 +2401,7 @@ NSGigE::unserialize(Checkpoint *cp, const std::string §ion) this->txDmaState = (DmaState) txDmaState; UNSERIALIZE_SCALAR(txKickTick); if (txKickTick) - txKickEvent.schedule(txKickTick); + schedule(txKickEvent, txKickTick); /* * unserialize rx state machine @@ -2418,7 +2419,7 @@ NSGigE::unserialize(Checkpoint *cp, const std::string §ion) this->rxDmaState = (DmaState) rxDmaState; UNSERIALIZE_SCALAR(rxKickTick); if (rxKickTick) - rxKickEvent.schedule(rxKickTick); + schedule(rxKickEvent, rxKickTick); /* * Unserialize EEPROM state machine @@ -2438,7 +2439,7 @@ NSGigE::unserialize(Checkpoint *cp, const std::string §ion) Tick transmitTick; UNSERIALIZE_SCALAR(transmitTick); if (transmitTick) - txEvent.schedule(curTick + transmitTick); + schedule(txEvent, curTick + transmitTick); /* * unserialize receive address filter settings @@ -2459,7 +2460,8 @@ NSGigE::unserialize(Checkpoint *cp, const std::string §ion) Tick intrEventTick; UNSERIALIZE_SCALAR(intrEventTick); if (intrEventTick) { - intrEvent = new IntrEvent(this, intrEventTick, true); + intrEvent = new IntrEvent(this, true); + schedule(intrEvent, intrEventTick); } } diff --git a/src/dev/pcidev.cc b/src/dev/pcidev.cc index 63b4a806e..e1dd7e553 100644 --- a/src/dev/pcidev.cc +++ b/src/dev/pcidev.cc @@ -56,8 +56,8 @@ using namespace std; PciDev::PciConfigPort::PciConfigPort(PciDev *dev, int busid, int devid, int funcid, Platform *p) - : SimpleTimingPort(dev->name() + "-pciconf"), device(dev), platform(p), - busId(busid), deviceId(devid), functionId(funcid) + : SimpleTimingPort(dev->name() + "-pciconf", dev), device(dev), + platform(p), busId(busid), deviceId(devid), functionId(funcid) { configAddr = platform->calcConfigAddr(busId, deviceId, functionId); } diff --git a/src/dev/sinic.cc b/src/dev/sinic.cc index 1fa8095d3..49806d37c 100644 --- a/src/dev/sinic.cc +++ b/src/dev/sinic.cc @@ -695,7 +695,8 @@ Base::cpuIntrPost(Tick when) if (intrEvent) intrEvent->squash(); - intrEvent = new IntrEvent(this, intrTick, true); + intrEvent = new IntrEvent(this, true); + schedule(intrEvent, intrTick); } void @@ -1315,7 +1316,7 @@ Device::transferDone() DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n"); - txEvent.reschedule(curTick + ticks(1), true); + reschedule(txEvent, curTick + ticks(1), true); } bool @@ -1455,7 +1456,8 @@ Base::unserialize(Checkpoint *cp, const std::string §ion) Tick intrEventTick; UNSERIALIZE_SCALAR(intrEventTick); if (intrEventTick) { - intrEvent = new IntrEvent(this, intrEventTick, true); + intrEvent = new IntrEvent(this, true); + schedule(intrEvent, intrEventTick); } } @@ -1705,7 +1707,7 @@ Device::unserialize(Checkpoint *cp, const std::string §ion) Tick transmitTick; UNSERIALIZE_SCALAR(transmitTick); if (transmitTick) - txEvent.schedule(curTick + transmitTick); + schedule(txEvent, curTick + transmitTick); pioPort->sendStatusChange(Port::RangeChange); diff --git a/src/dev/uart8250.cc b/src/dev/uart8250.cc index eefda76e5..93f71f49b 100644 --- a/src/dev/uart8250.cc +++ b/src/dev/uart8250.cc @@ -48,7 +48,7 @@ using namespace std; using namespace TheISA; Uart8250::IntrEvent::IntrEvent(Uart8250 *u, int bit) - : Event(&mainEventQueue), uart(u) + : uart(u) { DPRINTF(Uart, "UART Interrupt Event Initilizing\n"); intrBit = bit; @@ -93,9 +93,9 @@ Uart8250::IntrEvent::scheduleIntr() DPRINTF(Uart, "Scheduling IER interrupt for %#x, at cycle %lld\n", intrBit, curTick + interval); if (!scheduled()) - schedule(curTick + interval); + uart->schedule(this, curTick + interval); else - reschedule(curTick + interval); + uart->reschedule(this, curTick + interval); } @@ -231,7 +231,7 @@ Uart8250::write(PacketPtr pkt) { DPRINTF(Uart, "IER: IER_THRI cleared, descheduling TX intrrupt\n"); if (txIntrEvent.scheduled()) - txIntrEvent.deschedule(); + deschedule(txIntrEvent); if (status & TX_INT) platform->clearConsoleInt(); status &= ~TX_INT; @@ -243,7 +243,7 @@ Uart8250::write(PacketPtr pkt) } else { DPRINTF(Uart, "IER: IER_RDI cleared, descheduling RX intrrupt\n"); if (rxIntrEvent.scheduled()) - rxIntrEvent.deschedule(); + deschedule(rxIntrEvent); if (status & RX_INT) platform->clearConsoleInt(); status &= ~RX_INT; @@ -329,9 +329,9 @@ Uart8250::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(rxintrwhen); UNSERIALIZE_SCALAR(txintrwhen); if (rxintrwhen != 0) - rxIntrEvent.schedule(rxintrwhen); + schedule(rxIntrEvent, rxintrwhen); if (txintrwhen != 0) - txIntrEvent.schedule(txintrwhen); + schedule(txIntrEvent, txintrwhen); } Uart8250 * diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc index 2e668ec32..cc9b83d3e 100644 --- a/src/mem/bridge.cc +++ b/src/mem/bridge.cc @@ -47,7 +47,7 @@ Bridge::BridgePort::BridgePort(const std::string &_name, int _delay, int _nack_delay, int _req_limit, int _resp_limit, std::vector > filter_ranges) - : Port(_name), bridge(_bridge), otherPort(_otherPort), + : 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) @@ -162,7 +162,7 @@ Bridge::BridgePort::nackRequest(PacketPtr pkt) // nothing on the list, add it and we're done if (sendQueue.empty()) { assert(!sendEvent.scheduled()); - sendEvent.schedule(readyTime); + schedule(sendEvent, readyTime); sendQueue.push_back(buf); return; } @@ -184,7 +184,7 @@ Bridge::BridgePort::nackRequest(PacketPtr pkt) while (i != end && !done) { if (readyTime < (*i)->ready) { if (i == begin) - sendEvent.reschedule(readyTime); + reschedule(sendEvent, readyTime); sendQueue.insert(i,buf); done = true; } @@ -227,7 +227,7 @@ Bridge::BridgePort::queueForSendTiming(PacketPtr pkt) // should already be an event scheduled for sending the head // packet. if (sendQueue.empty()) { - sendEvent.schedule(readyTime); + schedule(sendEvent, readyTime); } sendQueue.push_back(buf); } @@ -281,7 +281,7 @@ Bridge::BridgePort::trySend() if (!sendQueue.empty()) { buf = sendQueue.front(); DPRINTF(BusBridge, "Scheduling next send\n"); - sendEvent.schedule(std::max(buf->ready, curTick + 1)); + schedule(sendEvent, std::max(buf->ready, curTick + 1)); } } else { DPRINTF(BusBridge, " unsuccessful\n"); @@ -302,7 +302,7 @@ Bridge::BridgePort::recvRetry() if (nextReady <= curTick) trySend(); else - sendEvent.schedule(nextReady); + schedule(sendEvent, nextReady); } /** Function called by the port when the bus is receiving a Atomic diff --git a/src/mem/bridge.hh b/src/mem/bridge.hh index a9dd67a2b..40f033811 100644 --- a/src/mem/bridge.hh +++ b/src/mem/bridge.hh @@ -146,11 +146,8 @@ class Bridge : public MemObject BridgePort *port; public: - SendEvent(BridgePort *p) - : Event(&mainEventQueue), port(p) {} - + SendEvent(BridgePort *p) : port(p) {} virtual void process() { port->trySend(); } - virtual const char *description() const { return "bridge send"; } }; diff --git a/src/mem/bus.cc b/src/mem/bus.cc index 41e9f0ac9..2eb823051 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -97,20 +97,24 @@ Bus::init() intIter->second->sendStatusChange(Port::RangeChange); } -Bus::BusFreeEvent::BusFreeEvent(Bus *_bus) : Event(&mainEventQueue), bus(_bus) +Bus::BusFreeEvent::BusFreeEvent(Bus *_bus) + : bus(_bus) {} -void Bus::BusFreeEvent::process() +void +Bus::BusFreeEvent::process() { bus->recvRetry(-1); } -const char * Bus::BusFreeEvent::description() const +const char * +Bus::BusFreeEvent::description() const { return "bus became available"; } -Tick Bus::calcPacketTiming(PacketPtr pkt) +Tick +Bus::calcPacketTiming(PacketPtr pkt) { // Bring tickNextIdle up to the present tick. // There is some potential ambiguity where a cycle starts, which @@ -155,12 +159,8 @@ void Bus::occupyBus(Tick until) } tickNextIdle = until; + reschedule(busIdle, tickNextIdle, true); - if (!busIdle.scheduled()) { - busIdle.schedule(tickNextIdle); - } else { - busIdle.reschedule(tickNextIdle); - } DPRINTF(Bus, "The bus is now occupied from tick %d to %d\n", curTick, tickNextIdle); } @@ -293,7 +293,7 @@ Bus::recvRetry(int id) //Burn a cycle for the missed grant. tickNextIdle += clock; - busIdle.reschedule(tickNextIdle, true); + reschedule(busIdle, tickNextIdle, true); } } //If we weren't able to drain before, we might be able to now. diff --git a/src/mem/cache/base.cc b/src/mem/cache/base.cc index ac0d54bf6..956375530 100644 --- a/src/mem/cache/base.cc +++ b/src/mem/cache/base.cc @@ -122,7 +122,7 @@ BaseCache::CachePort::clearBlocked() mustSendRetry = false; SendRetryEvent *ev = new SendRetryEvent(this, true); // @TODO: need to find a better time (next bus cycle?) - ev->schedule(curTick + 1); + schedule(ev, curTick + 1); } } diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 3b56c0a2e..abe3f9b5f 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -1489,7 +1489,7 @@ Cache::MemSidePort::sendPacket() // @TODO: need to facotr in prefetch requests here somehow if (nextReady != MaxTick) { DPRINTF(CachePort, "more packets to send @ %d\n", nextReady); - sendEvent->schedule(std::max(nextReady, curTick + 1)); + schedule(sendEvent, std::max(nextReady, curTick + 1)); } else { // no more to send right now: if we're draining, we may be done if (drainEvent) { diff --git a/src/mem/physical.cc b/src/mem/physical.cc index 325606eb1..20e19669c 100644 --- a/src/mem/physical.cc +++ b/src/mem/physical.cc @@ -383,7 +383,7 @@ PhysicalMemory::recvStatusChange(Port::Status status) PhysicalMemory::MemoryPort::MemoryPort(const std::string &_name, PhysicalMemory *_memory) - : SimpleTimingPort(_name), memory(_memory) + : SimpleTimingPort(_name, _memory), memory(_memory) { } void diff --git a/src/mem/tport.cc b/src/mem/tport.cc index 15c7fdf9f..254487af8 100644 --- a/src/mem/tport.cc +++ b/src/mem/tport.cc @@ -138,7 +138,7 @@ SimpleTimingPort::sendDeferredPacket() if (success) { if (!transmitList.empty() && !sendEvent->scheduled()) { Tick time = transmitList.front().tick; - sendEvent->schedule(time <= curTick ? curTick+1 : time); + schedule(sendEvent, time <= curTick ? curTick+1 : time); } if (transmitList.empty() && drainEvent) { diff --git a/src/mem/tport.hh b/src/mem/tport.hh index d0f1be425..f1cb5317d 100644 --- a/src/mem/tport.hh +++ b/src/mem/tport.hh @@ -108,7 +108,8 @@ class SimpleTimingPort : public Port Tick deferredPacketReadyTime() { return transmitList.empty() ? MaxTick : transmitList.front().tick; } - void schedSendEvent(Tick when) + void + schedSendEvent(Tick when) { if (waitingOnRetry) { assert(!sendEvent->scheduled()); @@ -116,9 +117,9 @@ class SimpleTimingPort : public Port } if (!sendEvent->scheduled()) { - sendEvent->schedule(when); + schedule(sendEvent, when); } else if (sendEvent->when() > when) { - sendEvent->reschedule(when); + reschedule(sendEvent, when); } } @@ -155,7 +156,7 @@ class SimpleTimingPort : public Port public: - SimpleTimingPort(std::string pname, MemObject *_owner = NULL) + SimpleTimingPort(std::string pname, MemObject *_owner) : Port(pname, _owner), sendEvent(new SendEvent(this)), drainEvent(NULL), diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 1f9a21899..a4324a1d6 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -326,7 +326,9 @@ def main(): if options.trace_start: def enable_trace(): internal.trace.cvar.enabled = True - event.create(enable_trace, int(options.trace_start)) + + e = event.create(enable_trace) + event.mainq.schedule(e, options.trace_start) else: internal.trace.cvar.enabled = True diff --git a/src/sim/debug.cc b/src/sim/debug.cc index 5a65f096a..3684f6767 100644 --- a/src/sim/debug.cc +++ b/src/sim/debug.cc @@ -56,12 +56,9 @@ debug_break() // Debug event: place a breakpoint on the process function and // schedule the event to break at a particular cycle // -class DebugBreakEvent : public Event +struct DebugBreakEvent : public Event { - public: - - DebugBreakEvent(EventQueue *q, Tick _when); - + DebugBreakEvent(); void process(); // process event virtual const char *description() const; }; @@ -69,11 +66,10 @@ class DebugBreakEvent : public Event // // constructor: schedule at specified time // -DebugBreakEvent::DebugBreakEvent(EventQueue *q, Tick _when) - : Event(q, Debug_Break_Pri) +DebugBreakEvent::DebugBreakEvent() + : Event(Debug_Break_Pri) { setFlags(AutoDelete); - schedule(_when); } // @@ -99,13 +95,15 @@ DebugBreakEvent::description() const void schedBreakCycle(Tick when) { - new DebugBreakEvent(&mainEventQueue, when); + mainEventQueue.schedule(new DebugBreakEvent, when); + warn("need to stop all queues"); } void eventqDump() { mainEventQueue.dump(); + warn("need to dump all queues"); } diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index 3b5965340..409a6e009 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -44,6 +44,7 @@ #include "params/BaseCPU.hh" #include "sim/pseudo_inst.hh" #include "sim/serialize.hh" +#include "sim/sim_events.hh" #include "sim/sim_exit.hh" #include "sim/stat_control.hh" #include "sim/stats.hh" @@ -88,7 +89,7 @@ quiesceNs(ThreadContext *tc, uint64_t ns) Tick resume = curTick + Clock::Int::ns * ns; - quiesceEvent->reschedule(resume, true); + mainEventQueue.reschedule(quiesceEvent, resume, true); DPRINTF(Quiesce, "%s: quiesceNs(%d) until %d\n", tc->getCpuPtr()->name(), ns, resume); @@ -108,7 +109,7 @@ quiesceCycles(ThreadContext *tc, uint64_t cycles) Tick resume = curTick + tc->getCpuPtr()->ticks(cycles); - quiesceEvent->reschedule(resume, true); + mainEventQueue.reschedule(quiesceEvent, resume, true); DPRINTF(Quiesce, "%s: quiesceCycles(%d) until %d\n", tc->getCpuPtr()->name(), cycles, resume); @@ -128,7 +129,8 @@ void m5exit(ThreadContext *tc, Tick delay) { Tick when = curTick + delay * Clock::Int::ns; - schedExitSimLoop("m5_exit instruction encountered", when); + Event *event = new SimLoopExitEvent("m5_exit instruction encountered", 0); + mainEventQueue.schedule(event, when); } void @@ -239,7 +241,8 @@ m5checkpoint(ThreadContext *tc, Tick delay, Tick period) Tick when = curTick + delay * Clock::Int::ns; Tick repeat = period * Clock::Int::ns; - schedExitSimLoop("checkpoint", when, repeat); + Event *event = new SimLoopExitEvent("checkpoint", 0, repeat); + mainEventQueue.schedule(event, when); } uint64_t diff --git a/src/sim/sim_events.cc b/src/sim/sim_events.cc index 5fe59286c..a6e3f0af3 100644 --- a/src/sim/sim_events.cc +++ b/src/sim/sim_events.cc @@ -40,6 +40,13 @@ using namespace std; +SimLoopExitEvent::SimLoopExitEvent(const std::string &_cause, int c, Tick r) + : Event(Sim_Exit_Pri), cause(_cause), code(c), repeat(r) +{ + setFlags(IsExitEvent); +} + + // // handle termination event // @@ -49,7 +56,7 @@ SimLoopExitEvent::process() // if this got scheduled on a different queue (e.g. the committed // instruction queue) then make a corresponding event on the main // queue. - if (queue() != &mainEventQueue) { + if (!getFlags(IsMainQueue)) { exitSimLoop(cause, code); delete this; } @@ -59,7 +66,8 @@ SimLoopExitEvent::process() // but if you are doing this on intervals, don't forget to make another if (repeat) { - schedule(curTick + repeat); + assert(getFlags(IsMainQueue)); + mainEventQueue.schedule(this, curTick + repeat); } } @@ -70,43 +78,32 @@ SimLoopExitEvent::description() const return "simulation loop exit"; } -SimLoopExitEvent * -schedExitSimLoop(const std::string &message, Tick when, Tick repeat, - EventQueue *q, int exit_code) -{ - if (q == NULL) - q = &mainEventQueue; - - return new SimLoopExitEvent(q, when, repeat, message, exit_code); -} - void exitSimLoop(const std::string &message, int exit_code) { - schedExitSimLoop(message, curTick, 0, NULL, exit_code); + Event *event = new SimLoopExitEvent(message, exit_code); + mainEventQueue.schedule(event, curTick); } +CountedDrainEvent::CountedDrainEvent() + : SimLoopExitEvent("Finished drain", 0), count(0) +{ } + void CountedDrainEvent::process() { - if (--count == 0) { - exitSimLoop("Finished drain"); - } + if (--count == 0) + exitSimLoop(cause, code); } // // constructor: automatically schedules at specified time // -CountedExitEvent::CountedExitEvent(EventQueue *q, const std::string &_cause, - Tick _when, int &_downCounter) - : Event(q, Sim_Exit_Pri), - cause(_cause), - downCounter(_downCounter) +CountedExitEvent::CountedExitEvent(const std::string &_cause, int &counter) + : Event(Sim_Exit_Pri), cause(_cause), downCounter(counter) { // catch stupid mistakes assert(downCounter > 0); - - schedule(_when); } @@ -128,9 +125,11 @@ CountedExitEvent::description() const return "counted exit"; } -#ifdef CHECK_SWAP_CYCLES -new CheckSwapEvent(&mainEventQueue, CHECK_SWAP_CYCLES); -#endif +CheckSwapEvent::CheckSwapEvent(int ival) + : interval(ival) +{ + mainEventQueue.schedule(this, curTick + interval); +} void CheckSwapEvent::process() @@ -149,7 +148,8 @@ CheckSwapEvent::process() exitSimLoop("Lack of swap space"); } - schedule(curTick + interval); + assert(getFlags(IsMainQueue)); + mainEventQueue.schedule(this, curTick + interval); } const char * diff --git a/src/sim/sim_events.hh b/src/sim/sim_events.hh index 6f9b7f612..ffd31f385 100644 --- a/src/sim/sim_events.hh +++ b/src/sim/sim_events.hh @@ -38,30 +38,14 @@ // class SimLoopExitEvent : public Event { - private: + protected: // string explaining why we're terminating std::string cause; int code; Tick repeat; public: - // Default constructor. Only really used for derived classes. - SimLoopExitEvent() - : Event(&mainEventQueue, Sim_Exit_Pri) - { } - - SimLoopExitEvent(EventQueue *q, - Tick _when, Tick _repeat, const std::string &_cause, - int c = 0) - : Event(q, Sim_Exit_Pri), cause(_cause), - code(c), repeat(_repeat) - { setFlags(IsExitEvent); schedule(_when); } - -// SimLoopExitEvent(EventQueue *q, -// Tick _when, const std::string &_cause, -// Tick _repeat = 0, int c = 0) -// : Event(q, Sim_Exit_Pri), cause(_cause), code(c), repeat(_repeat) -// { setFlags(IsExitEvent); schedule(_when); } + SimLoopExitEvent(const std::string &_cause, int c, Tick repeat = 0); std::string getCause() { return cause; } int getCode() { return code; } @@ -76,10 +60,10 @@ class CountedDrainEvent : public SimLoopExitEvent private: // Count of how many objects have not yet drained int count; + public: - CountedDrainEvent() - : count(0) - { } + CountedDrainEvent(); + void process(); void setCount(int _count) { count = _count; } @@ -99,8 +83,7 @@ class CountedExitEvent : public Event int &downCounter; // decrement & terminate if zero public: - CountedExitEvent(EventQueue *q, const std::string &_cause, - Tick _when, int &_downCounter); + CountedExitEvent(const std::string &_cause, int &_downCounter); void process(); // process event @@ -116,10 +99,7 @@ class CheckSwapEvent : public Event int interval; public: - CheckSwapEvent(EventQueue *q, int ival) - : Event(q), interval(ival) - { schedule(curTick + interval); } - + CheckSwapEvent(int ival); void process(); // process event virtual const char *description() const; diff --git a/src/sim/sim_exit.hh b/src/sim/sim_exit.hh index d4b31d1ea..174b00024 100644 --- a/src/sim/sim_exit.hh +++ b/src/sim/sim_exit.hh @@ -45,14 +45,6 @@ class SimLoopExitEvent; /// sim/main.cc. void registerExitCallback(Callback *); -/// Schedule an event to exit the simulation loop (returning to -/// Python) at the indicated tick. The message and exit_code -/// parameters are saved in the SimLoopExitEvent to indicate why the -/// exit occurred. -SimLoopExitEvent *schedExitSimLoop(const std::string &message, Tick when, - Tick repeat = 0, EventQueue *q = NULL, - int exit_code = 0); - /// Schedule an event to exit the simulation loop (returning to /// Python) at the end of the current cycle (curTick). The message /// and exit_code parameters are saved in the SimLoopExitEvent to diff --git a/src/sim/sim_object_params.hh b/src/sim/sim_object_params.hh index 74d433495..750181135 100644 --- a/src/sim/sim_object_params.hh +++ b/src/sim/sim_object_params.hh @@ -39,8 +39,14 @@ struct PyObject; #include struct EventQueue; + struct SimObjectParams { + SimObjectParams() + { + extern EventQueue mainEventQueue; + eventq = &mainEventQueue; + } virtual ~SimObjectParams() {} std::string name; diff --git a/src/sim/simulate.cc b/src/sim/simulate.cc index 36bdff45e..59d79b7c6 100644 --- a/src/sim/simulate.cc +++ b/src/sim/simulate.cc @@ -56,8 +56,9 @@ simulate(Tick num_cycles) else num_cycles = curTick + num_cycles; - Event *limit_event; - limit_event = schedExitSimLoop("simulate() limit reached", num_cycles); + Event *limit_event = + new SimLoopExitEvent("simulate() limit reached", 0); + mainEventQueue.schedule(limit_event, num_cycles); while (1) { // there should always be at least one event (the SimLoopExitEvent @@ -82,8 +83,8 @@ simulate(Tick num_cycles) // if we didn't hit limit_event, delete it if (se_event != limit_event) { assert(limit_event->scheduled()); - limit_event->deschedule(); - delete limit_event; + limit_event->squash(); + warn_once("be nice to actually delete the event here"); } return se_event; diff --git a/src/sim/stat_control.cc b/src/sim/stat_control.cc index 228c83898..25c5be104 100644 --- a/src/sim/stat_control.cc +++ b/src/sim/stat_control.cc @@ -154,12 +154,10 @@ class _StatEvent : public Event Tick repeat; public: - _StatEvent(bool _dump, bool _reset, Tick _when, Tick _repeat) - : Event(&mainEventQueue, Stat_Event_Pri), dump(_dump), reset(_reset), - repeat(_repeat) + _StatEvent(bool _dump, bool _reset, Tick _repeat) + : Event(Stat_Event_Pri), dump(_dump), reset(_reset), repeat(_repeat) { setFlags(AutoDelete); - schedule(_when); } virtual void @@ -171,15 +169,18 @@ class _StatEvent : public Event if (reset) Stats::reset(); - if (repeat) - new _StatEvent(dump, reset, curTick + repeat, repeat); + if (repeat) { + Event *event = new _StatEvent(dump, reset, repeat); + mainEventQueue.schedule(event, curTick + repeat); + } } }; void StatEvent(bool dump, bool reset, Tick when, Tick repeat) { - new _StatEvent(dump, reset, when, repeat); + Event *event = new _StatEvent(dump, reset, repeat); + mainEventQueue.schedule(event, when); } /* namespace Stats */ } -- cgit v1.2.3 From b556dc4119fdaa031b594241eacf51e2139e8490 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 9 Oct 2008 04:58:24 -0700 Subject: mem: Add a method for setting the time on a packet. --- src/mem/request.hh | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/mem/request.hh b/src/mem/request.hh index ab8f9d596..613655ea4 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -221,6 +221,12 @@ class Request : public FastAlloc /** Accessor for time. */ Tick getTime() { assert(validPaddr || validAsidVaddr); return time; } void resetTime() { assert(validPaddr || validAsidVaddr); time = curTick; } + void + setTime(Tick when) + { + assert(validPaddr || validAsidVaddr); + time = when; + } /** Accessor for flags. */ uint32_t getFlags() { assert(validPaddr || validAsidVaddr); return flags; } -- cgit v1.2.3 From 6ccf28c896f358d18cd942ab0f8d24fde96e153e Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 9 Oct 2008 09:25:41 -0700 Subject: style: conform to M5 style. --- src/base/range_map.hh | 63 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/base/range_map.hh b/src/base/range_map.hh index 6d3450739..1c121925d 100644 --- a/src/base/range_map.hh +++ b/src/base/range_map.hh @@ -46,7 +46,8 @@ class range_map typedef typename RangeMap::iterator iterator; template - const iterator find(const Range &r) + const iterator + find(const Range &r) { iterator i; @@ -69,7 +70,8 @@ class range_map } template - bool intersect(const Range &r) + bool + intersect(const Range &r) { iterator i; i = find(r); @@ -80,7 +82,8 @@ class range_map template - iterator insert(const Range &r, const W d) + iterator + insert(const Range &r, const W d) { if (intersect(r)) return tree.end(); @@ -88,42 +91,50 @@ class range_map return tree.insert(std::make_pair,V>(r, d)).first; } - size_t erase(T k) + size_t + erase(T k) { return tree.erase(k); } - void erase(iterator p) + void + erase(iterator p) { tree.erase(p); } - void erase(iterator p, iterator q) + void + erase(iterator p, iterator q) { tree.erase(p,q); } - void clear() + void + clear() { tree.erase(tree.begin(), tree.end()); } - iterator begin() + iterator + begin() { return tree.begin(); } - iterator end() + iterator + end() { return tree.end(); } - size_t size() + size_t + size() { return tree.size(); } - bool empty() + bool + empty() { return tree.empty(); } @@ -180,7 +191,8 @@ class range_multimap } template - bool intersect(const Range &r) + bool + intersect(const Range &r) { std::pair p; p = find(r); @@ -191,7 +203,8 @@ class range_multimap template - iterator insert(const Range &r, const W d) + iterator + insert(const Range &r, const W d) { std::pair p; p = find(r); @@ -202,42 +215,50 @@ class range_multimap return tree.end(); } - size_t erase(T k) + size_t + erase(T k) { return tree.erase(k); } - void erase(iterator p) + void + erase(iterator p) { tree.erase(p); } - void erase(iterator p, iterator q) + void + erase(iterator p, iterator q) { tree.erase(p,q); } - void clear() + void + clear() { tree.erase(tree.begin(), tree.end()); } - iterator begin() + iterator + begin() { return tree.begin(); } - iterator end() + iterator + end() { return tree.end(); } - size_t size() + size_t + size() { return tree.size(); } - bool empty() + bool + empty() { return tree.empty(); } -- cgit v1.2.3 From 4ecc5d53a302c5e494df5853a314a61e8bba3a50 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 9 Oct 2008 22:19:38 -0700 Subject: range_map: Add a method to find which range a single value falls into. --- src/base/range_map.hh | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/base/range_map.hh b/src/base/range_map.hh index 1c121925d..0ffc28ed9 100644 --- a/src/base/range_map.hh +++ b/src/base/range_map.hh @@ -69,6 +69,13 @@ class range_map return tree.end(); } + template + const iterator + find(const U &r) + { + return find(RangeSize(r, 1)); + } + template bool intersect(const Range &r) -- cgit v1.2.3 From 94b08bed07d13106381a0bb692bf0d879c5353d4 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 9 Oct 2008 22:19:39 -0700 Subject: SimObjects: Clean up handling of C++ namespaces. Make them easier to express by only having the cxx_type parameter which has the full namespace name, and drop the cxx_namespace thing. Add support for multiple levels of namespace. --- src/SConscript | 21 +++++++-------- src/arch/alpha/AlphaTLB.py | 8 ++---- src/arch/mips/MipsTLB.py | 9 +++---- src/arch/sparc/SparcTLB.py | 8 ++---- src/arch/x86/X86TLB.py | 11 +++----- src/arch/x86/bios/E820.py | 6 ++--- src/cpu/ExeTracer.py | 3 +-- src/cpu/IntelTrace.py | 3 +-- src/cpu/LegionTrace.py | 3 +-- src/cpu/NativeTrace.py | 3 +-- src/dev/Ethernet.py | 3 +-- src/python/m5/SimObject.py | 64 ++++++++++++---------------------------------- src/sim/InstTracer.py | 2 +- 13 files changed, 46 insertions(+), 98 deletions(-) (limited to 'src') diff --git a/src/SConscript b/src/SConscript index 09ccf7722..be721d57e 100644 --- a/src/SConscript +++ b/src/SConscript @@ -531,23 +531,24 @@ def buildParams(target, source, env): print >>out, decl continue - code = '' - base = obj.get_base() + class_path = obj.cxx_class.split('::') + class_path.reverse() + classname = class_path[0] + namespaces = class_path[1:] + code = '' code += '// stop swig from creating/wrapping default ctor/dtor\n' - code += '%%nodefault %s;\n' % obj.cxx_class - code += 'class %s ' % obj.cxx_class - if base: - code += ': public %s' % base + code += '%%nodefault %s;\n' % classname + code += 'class %s ' % classname + if obj._base: + code += ': public %s' % obj._base.cxx_class code += ' {};\n' - klass = obj.cxx_class; - if hasattr(obj, 'cxx_namespace'): - new_code = 'namespace %s {\n' % obj.cxx_namespace + for ns in namespaces: + new_code = 'namespace %s {\n' % ns new_code += code new_code += '}\n' code = new_code - klass = '%s::%s' % (obj.cxx_namespace, klass) print >>out, code diff --git a/src/arch/alpha/AlphaTLB.py b/src/arch/alpha/AlphaTLB.py index fec245b75..7cfb549f3 100644 --- a/src/arch/alpha/AlphaTLB.py +++ b/src/arch/alpha/AlphaTLB.py @@ -35,14 +35,10 @@ class AlphaTLB(SimObject): class AlphaDTB(AlphaTLB): type = 'AlphaDTB' - cxx_namespace = 'AlphaISA' - cxx_class = 'DTB' - + cxx_class = 'AlphaISA::DTB' size = 64 class AlphaITB(AlphaTLB): type = 'AlphaITB' - cxx_namespace = 'AlphaISA' - cxx_class = 'ITB' - + cxx_class = 'AlphaISA::ITB' size = 48 diff --git a/src/arch/mips/MipsTLB.py b/src/arch/mips/MipsTLB.py index 1d0244e22..0054acae5 100644 --- a/src/arch/mips/MipsTLB.py +++ b/src/arch/mips/MipsTLB.py @@ -39,19 +39,16 @@ class MipsTLB(SimObject): class MipsDTB(MipsTLB): type = 'MipsDTB' - cxx_namespace = 'MipsISA' - cxx_class = 'DTB' + cxx_class = 'MipsISA::DTB' size = 64 class MipsITB(MipsTLB): type = 'MipsITB' - cxx_namespace = 'MipsISA' - cxx_class = 'ITB' + cxx_class = 'MipsISA::ITB' size = 64 class MipsUTB(MipsTLB): type = 'MipsUTB' - cxx_namespace = 'MipsISA' - cxx_class = 'UTB' + cxx_class = 'MipsISA::UTB' size = 64 diff --git a/src/arch/sparc/SparcTLB.py b/src/arch/sparc/SparcTLB.py index 2d0257cd7..20672a24e 100644 --- a/src/arch/sparc/SparcTLB.py +++ b/src/arch/sparc/SparcTLB.py @@ -35,14 +35,10 @@ class SparcTLB(SimObject): class SparcDTB(SparcTLB): type = 'SparcDTB' - cxx_namespace = 'SparcISA' - cxx_class = 'DTB' - + cxx_class = 'SparcISA::DTB' size = 64 class SparcITB(SparcTLB): type = 'SparcITB' - cxx_namespace = 'SparcISA' - cxx_class = 'ITB' - + cxx_class = 'SparcISA::ITB' size = 64 diff --git a/src/arch/x86/X86TLB.py b/src/arch/x86/X86TLB.py index 8dd53620e..c20566efb 100644 --- a/src/arch/x86/X86TLB.py +++ b/src/arch/x86/X86TLB.py @@ -62,8 +62,7 @@ from m5 import build_env if build_env['FULL_SYSTEM']: class X86PagetableWalker(MemObject): type = 'X86PagetableWalker' - cxx_namespace = 'X86ISA' - cxx_class = 'Walker' + cxx_class = 'X86ISA::Walker' port = Port("Port for the hardware table walker") system = Param.System(Parent.any, "system object") @@ -77,14 +76,10 @@ class X86TLB(SimObject): class X86DTB(X86TLB): type = 'X86DTB' - cxx_namespace = 'X86ISA' - cxx_class = 'DTB' - + cxx_class = 'X86ISA::DTB' size = 64 class X86ITB(X86TLB): type = 'X86ITB' - cxx_namespace = 'X86ISA' - cxx_class = 'ITB' - + cxx_class = 'X86ISA::ITB' size = 64 diff --git a/src/arch/x86/bios/E820.py b/src/arch/x86/bios/E820.py index e161cd56f..288c253fb 100644 --- a/src/arch/x86/bios/E820.py +++ b/src/arch/x86/bios/E820.py @@ -58,8 +58,7 @@ from m5.SimObject import SimObject class X86E820Entry(SimObject): type = 'X86E820Entry' - cxx_namespace = 'X86ISA' - cxx_class = 'E820Entry' + cxx_class = 'X86ISA::E820Entry' addr = Param.Addr(0, 'address of the beginning of the region') size = Param.MemorySize('0B', 'size of the region') @@ -67,7 +66,6 @@ class X86E820Entry(SimObject): class X86E820Table(SimObject): type = 'X86E820Table' - cxx_namespace = 'X86ISA' - cxx_class = 'E820Table' + cxx_class = 'X86ISA::E820Table' entries = VectorParam.X86E820Entry([], 'entries for the e820 table') diff --git a/src/cpu/ExeTracer.py b/src/cpu/ExeTracer.py index e904f9e7d..5754f5d5b 100644 --- a/src/cpu/ExeTracer.py +++ b/src/cpu/ExeTracer.py @@ -32,5 +32,4 @@ from InstTracer import InstTracer class ExeTracer(InstTracer): type = 'ExeTracer' - cxx_namespace = 'Trace' - cxx_class = 'ExeTracer' + cxx_class = 'Trace::ExeTracer' diff --git a/src/cpu/IntelTrace.py b/src/cpu/IntelTrace.py index 6e8f567b3..3642f3174 100644 --- a/src/cpu/IntelTrace.py +++ b/src/cpu/IntelTrace.py @@ -32,5 +32,4 @@ from InstTracer import InstTracer class IntelTrace(InstTracer): type = 'IntelTrace' - cxx_namespace = 'Trace' - cxx_class = 'IntelTrace' + cxx_class = 'Trace::IntelTrace' diff --git a/src/cpu/LegionTrace.py b/src/cpu/LegionTrace.py index f9b6470a6..d450dd00e 100644 --- a/src/cpu/LegionTrace.py +++ b/src/cpu/LegionTrace.py @@ -32,5 +32,4 @@ from InstTracer import InstTracer class LegionTrace(InstTracer): type = 'LegionTrace' - cxx_namespace = 'Trace' - cxx_class = 'LegionTrace' + cxx_class = 'Trace::LegionTrace' diff --git a/src/cpu/NativeTrace.py b/src/cpu/NativeTrace.py index 96b4e991b..f410b5473 100644 --- a/src/cpu/NativeTrace.py +++ b/src/cpu/NativeTrace.py @@ -32,5 +32,4 @@ from InstTracer import InstTracer class NativeTrace(InstTracer): type = 'NativeTrace' - cxx_namespace = 'Trace' - cxx_class = 'NativeTrace' + cxx_class = 'Trace::NativeTrace' diff --git a/src/dev/Ethernet.py b/src/dev/Ethernet.py index cf513b834..5821a3e96 100644 --- a/src/dev/Ethernet.py +++ b/src/dev/Ethernet.py @@ -160,8 +160,7 @@ class NSGigE(EtherDevBase): class Sinic(EtherDevBase): type = 'Sinic' - cxx_namespace = 'Sinic' - cxx_class = 'Device' + cxx_class = 'Sinic::Device' rx_max_copy = Param.MemorySize('1514B', "rx max copy") tx_max_copy = Param.MemorySize('16kB', "tx max copy") diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index 64f4ec5af..ac81582f3 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -123,7 +123,6 @@ instanceDict = {} class MetaSimObject(type): # Attributes that can be set only at initialization time init_keywords = { 'abstract' : types.BooleanType, - 'cxx_namespace' : types.StringType, 'cxx_class' : types.StringType, 'cxx_type' : types.StringType, 'cxx_predecls' : types.ListType, @@ -190,36 +189,31 @@ class MetaSimObject(type): # the following is not true is when we define the SimObject # class itself (in which case the multidicts have no parent). if isinstance(base, MetaSimObject): + cls._base = base cls._params.parent = base._params cls._ports.parent = base._ports cls._values.parent = base._values cls._port_refs.parent = base._port_refs # mark base as having been subclassed base._instantiated = True + else: + cls._base = None # default keyword values if 'type' in cls._value_dict: - _type = cls._value_dict['type'] if 'cxx_class' not in cls._value_dict: - cls._value_dict['cxx_class'] = _type + cls._value_dict['cxx_class'] = cls._value_dict['type'] - namespace = cls._value_dict.get('cxx_namespace', None) - - _cxx_class = cls._value_dict['cxx_class'] - if 'cxx_type' not in cls._value_dict: - t = _cxx_class + '*' - if namespace: - t = '%s::%s' % (namespace, t) - cls._value_dict['cxx_type'] = t + cls._value_dict['cxx_type'] = '%s *' % cls._value_dict['cxx_class'] + if 'cxx_predecls' not in cls._value_dict: # A forward class declaration is sufficient since we are # just declaring a pointer. - decl = 'class %s;' % _cxx_class - if namespace: - namespaces = namespace.split('::') - namespaces.reverse() - for namespace in namespaces: - decl = 'namespace %s { %s }' % (namespace, decl) + class_path = cls._value_dict['cxx_class'].split('::') + class_path.reverse() + decl = 'class %s;' % class_path[0] + for ns in class_path[1:]: + decl = 'namespace %s { %s }' % (ns, decl) cls._value_dict['cxx_predecls'] = [decl] if 'swig_predecls' not in cls._value_dict: @@ -351,12 +345,6 @@ class MetaSimObject(type): def __str__(cls): return cls.__name__ - def get_base(cls): - if str(cls) == 'SimObject': - return None - - return cls.__bases__[0].type - def cxx_decl(cls): code = "#ifndef __PARAMS__%s\n" % cls code += "#define __PARAMS__%s\n\n" % cls @@ -387,16 +375,15 @@ class MetaSimObject(type): code += "\n".join(predecls2) code += "\n\n"; - base = cls.get_base() - if base: - code += '#include "params/%s.hh"\n\n' % base + if cls._base: + code += '#include "params/%s.hh"\n\n' % cls._base.type for ptype in ptypes: if issubclass(ptype, Enum): code += '#include "enums/%s.hh"\n' % ptype.__name__ code += "\n\n" - code += cls.cxx_struct(base, params) + code += cls.cxx_struct(cls._base, params) # close #ifndef __PARAMS__* guard code += "\n#endif\n" @@ -409,7 +396,7 @@ class MetaSimObject(type): # now generate the actual param struct code = "struct %sParams" % cls if base: - code += " : public %sParams" % base + code += " : public %sParams" % base.type code += "\n{\n" if not hasattr(cls, 'abstract') or not cls.abstract: if 'type' in cls.__dict__: @@ -421,24 +408,7 @@ class MetaSimObject(type): return code - def cxx_type_decl(cls): - base = cls.get_base() - code = '' - - if base: - code += '#include "%s_type.h"\n' % base - - # now generate dummy code for inheritance - code += "struct %s" % cls.cxx_class - if base: - code += " : public %s" % base.cxx_class - code += "\n{};\n" - - return code - def swig_decl(cls): - base = cls.get_base() - code = '%%module %s\n' % cls code += '%{\n' @@ -466,8 +436,8 @@ class MetaSimObject(type): code += "\n".join(predecls2) code += "\n\n"; - if base: - code += '%%import "params/%s.i"\n\n' % base + if cls._base: + code += '%%import "params/%s.i"\n\n' % cls._base.type for ptype in ptypes: if issubclass(ptype, Enum): diff --git a/src/sim/InstTracer.py b/src/sim/InstTracer.py index f7500f1e8..9ba91a019 100644 --- a/src/sim/InstTracer.py +++ b/src/sim/InstTracer.py @@ -31,5 +31,5 @@ from m5.params import * class InstTracer(SimObject): type = 'InstTracer' - cxx_namespace = 'Trace' + cxx_class = 'Trace::InstTracer' abstract = True -- cgit v1.2.3 From 57d663877e2d8de9a4614b82f2b755fee0961e0d Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 10 Oct 2008 03:50:07 -0700 Subject: X86: Fix compilation with new eventq API. --- src/dev/x86/south_bridge/cmos.hh | 15 ++++++++------- src/dev/x86/south_bridge/i8254.hh | 11 ++++++----- src/dev/x86/south_bridge/south_bridge.cc | 4 ++-- 3 files changed, 16 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/dev/x86/south_bridge/cmos.hh b/src/dev/x86/south_bridge/cmos.hh index d1aa74b72..1cb22fa9e 100644 --- a/src/dev/x86/south_bridge/cmos.hh +++ b/src/dev/x86/south_bridge/cmos.hh @@ -56,8 +56,9 @@ class Cmos : public SubDevice class X86RTC : public MC146818 { public: - X86RTC(const std::string &n, const struct tm time, - bool bcd, Tick frequency) : MC146818(n, time, bcd, frequency) + X86RTC(EventManager *em, const std::string &n, const struct tm time, + bool bcd, Tick frequency) : + MC146818(em, n, time, bcd, frequency) { } protected: @@ -69,22 +70,22 @@ class Cmos : public SubDevice public: - Cmos() : rtc("rtc", foo_time, true, ULL(5000000000)) + Cmos(EventManager *em) : rtc(em, "rtc", foo_time, true, ULL(5000000000)) { memset(regs, 0, numRegs * sizeof(uint8_t)); address = 0; } - Cmos(Tick _latency) : SubDevice(_latency), - rtc("rtc", foo_time, true, ULL(5000000000)) + Cmos(EventManager *em, Tick _latency) : SubDevice(_latency), + rtc(em, "rtc", foo_time, true, ULL(5000000000)) { memset(regs, 0, numRegs * sizeof(uint8_t)); address = 0; } - Cmos(Addr start, Addr size, Tick _latency) : + Cmos(EventManager *em, Addr start, Addr size, Tick _latency) : SubDevice(start, size, _latency), - rtc("rtc", foo_time, true, ULL(5000000000)) + rtc(em, "rtc", foo_time, true, ULL(5000000000)) { memset(regs, 0, numRegs * sizeof(uint8_t)); address = 0; diff --git a/src/dev/x86/south_bridge/i8254.hh b/src/dev/x86/south_bridge/i8254.hh index 6f718a853..b6dd388a7 100644 --- a/src/dev/x86/south_bridge/i8254.hh +++ b/src/dev/x86/south_bridge/i8254.hh @@ -46,13 +46,14 @@ class I8254 : public SubDevice public: Intel8254Timer pit; - I8254(const std::string &name) : pit(name) + I8254(EventManager *em, const std::string &name) : pit(em, name) {} - I8254(const std::string &name, Tick _latency) : - SubDevice(_latency), pit(name) + I8254(EventManager *em, const std::string &name, Tick _latency) : + SubDevice(_latency), pit(em, name) {} - I8254(const std::string &name, Addr start, Addr size, Tick _latency) : - SubDevice(start, size, _latency), pit(name) + I8254(EventManager *em, const std::string &name, + Addr start, Addr size, Tick _latency) : + SubDevice(start, size, _latency), pit(em, name) {} Tick read(PacketPtr pkt); diff --git a/src/dev/x86/south_bridge/south_bridge.cc b/src/dev/x86/south_bridge/south_bridge.cc index b1f0abfe6..ded5d7ac5 100644 --- a/src/dev/x86/south_bridge/south_bridge.cc +++ b/src/dev/x86/south_bridge/south_bridge.cc @@ -69,8 +69,8 @@ SouthBridge::write(PacketPtr pkt) SouthBridge::SouthBridge(const Params *p) : PioDevice(p), pic1(0x20, 2, p->pio_latency), pic2(0xA0, 2, p->pio_latency), - pit(p->name + ".pit", 0x40, 4, p->pio_latency), - cmos(0x70, 2, p->pio_latency), + pit(this, p->name + ".pit", 0x40, 4, p->pio_latency), + cmos(this, 0x70, 2, p->pio_latency), speaker(&pit, 0x61, 1, p->pio_latency) { addDevice(pic1); -- cgit v1.2.3 From d897aa939f4fe558a8e41ba612d0f43931450677 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 10 Oct 2008 03:50:18 -0700 Subject: X86: Move the smbios objects into a folder for BIOS objects. --- src/arch/x86/SConscript | 3 - src/arch/x86/bios/SConscript | 65 ++++++++++ src/arch/x86/bios/smbios.cc | 245 ++++++++++++++++++++++++++++++++++++ src/arch/x86/bios/smbios.hh | 292 +++++++++++++++++++++++++++++++++++++++++++ src/arch/x86/smbios.cc | 245 ------------------------------------ src/arch/x86/smbios.hh | 292 ------------------------------------------- src/arch/x86/system.cc | 2 +- 7 files changed, 603 insertions(+), 541 deletions(-) create mode 100644 src/arch/x86/bios/SConscript create mode 100644 src/arch/x86/bios/smbios.cc create mode 100644 src/arch/x86/bios/smbios.hh delete mode 100644 src/arch/x86/smbios.cc delete mode 100644 src/arch/x86/smbios.hh (limited to 'src') diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript index 184bb4809..0d8760fdc 100644 --- a/src/arch/x86/SConscript +++ b/src/arch/x86/SConscript @@ -110,13 +110,10 @@ if env['TARGET_ISA'] == 'x86': if env['FULL_SYSTEM']: SimObject('X86System.py') - SimObject('bios/E820.py') # Full-system sources - Source('bios/e820.cc') Source('linux/system.cc') Source('pagetable_walker.cc') - Source('smbios.cc') Source('system.cc') Source('stacktrace.cc') Source('vtophys.cc') diff --git a/src/arch/x86/bios/SConscript b/src/arch/x86/bios/SConscript new file mode 100644 index 000000000..904fab086 --- /dev/null +++ b/src/arch/x86/bios/SConscript @@ -0,0 +1,65 @@ +# -*- mode:python -*- + +# Copyright (c) 2007-2008 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use of this software in source and binary forms, +# with or without modification, are permitted provided that the +# following conditions are met: +# +# The software must be used only for Non-Commercial Use which means any +# use which is NOT directed to receiving any direct monetary +# compensation for, or commercial advantage from such use. Illustrative +# examples of non-commercial use are academic research, personal study, +# teaching, education and corporate research & development. +# Illustrative examples of commercial use are distributing products for +# commercial advantage and providing services using the software for +# commercial advantage. +# +# If you wish to use this software or functionality therein that may be +# covered by patents for commercial use, please contact: +# Director of Intellectual Property Licensing +# Office of Strategy and Technology +# Hewlett-Packard Company +# 1501 Page Mill Road +# Palo Alto, California 94304 +# +# 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. No right of +# sublicense is granted herewith. Derivatives of the software and +# output created using the software may be prepared, but only for +# Non-Commercial Uses. Derivatives of the software may be shared with +# others provided: (i) the others agree to abide by the list of +# conditions herein which includes the Non-Commercial Use restrictions; +# and (ii) such Derivatives of the software include the above copyright +# notice to acknowledge the contribution from this software where +# applicable, this list of conditions and the disclaimer below. +# +# 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: Gabe Black + +Import('*') + +if env['TARGET_ISA'] == 'x86': + if env['FULL_SYSTEM']: + SimObject('E820.py') + Source('e820.cc') + + Source('smbios.cc') diff --git a/src/arch/x86/bios/smbios.cc b/src/arch/x86/bios/smbios.cc new file mode 100644 index 000000000..de4a263b7 --- /dev/null +++ b/src/arch/x86/bios/smbios.cc @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +/* + * Copyright (c) 2008 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * 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: Gabe Black + */ + +#include "arch/x86/bios/smbios.hh" +#include "arch/x86/isa_traits.hh" +#include "mem/port.hh" +#include "sim/byteswap.hh" +#include "sim/host.hh" + +const char X86ISA::SMBios::SMBiosTable::SMBiosHeader::anchorString[] = "_SM_"; +const uint8_t X86ISA::SMBios::SMBiosTable:: + SMBiosHeader::formattedArea[] = {0,0,0,0,0}; +const uint8_t X86ISA::SMBios::SMBiosTable:: + SMBiosHeader::entryPointLength = 0x1F; +const uint8_t X86ISA::SMBios::SMBiosTable:: + SMBiosHeader::entryPointRevision = 0; +const char X86ISA::SMBios::SMBiosTable:: + SMBiosHeader::IntermediateHeader::anchorString[] = "_DMI_"; + +uint16_t +X86ISA::SMBios::BiosInformation::writeOut(FunctionalPort * port, Addr addr) +{ + uint8_t size = SMBiosStructure::writeOut(port, addr); + + port->writeBlob(addr + 0x4, (uint8_t *)(&vendor), 1); + port->writeBlob(addr + 0x5, (uint8_t *)(&version), 1); + + uint16_t startingAddrSegmentGuest = X86ISA::htog(startingAddrSegment); + port->writeBlob(addr + 0x6, (uint8_t *)(&startingAddrSegmentGuest), 2); + + port->writeBlob(addr + 0x8, (uint8_t *)(&releaseDate), 1); + port->writeBlob(addr + 0x9, (uint8_t *)(&romSize), 1); + + uint64_t characteristicsGuest = X86ISA::htog(characteristics); + port->writeBlob(addr + 0xA, (uint8_t *)(&characteristicsGuest), 8); + + uint16_t characteristicExtBytesGuest = + X86ISA::htog(characteristicExtBytes); + port->writeBlob(addr + 0x12, (uint8_t *)(&characteristicExtBytesGuest), 2); + + port->writeBlob(addr + 0x14, (uint8_t *)(&major), 1); + port->writeBlob(addr + 0x15, (uint8_t *)(&minor), 1); + port->writeBlob(addr + 0x16, (uint8_t *)(&embContFirmwareMajor), 1); + port->writeBlob(addr + 0x17, (uint8_t *)(&embContFirmwareMinor), 1); + + writeOutStrings(port, addr + getLength()); + + return size; +} + +void +X86ISA::SMBios::SMBiosTable::writeOut(FunctionalPort * port, Addr addr) +{ + + /* + * The main header + */ + uint8_t mainChecksum = 0; + + port->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, + (uint8_t *)(&smbiosHeader.entryPointLength), 1); + mainChecksum += smbiosHeader.entryPointLength; + port->writeBlob(addr + 0x6, + (uint8_t *)(&smbiosHeader.majorVersion), 1); + mainChecksum += smbiosHeader.majorVersion; + port->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, + (uint8_t *)(&smbiosHeader.entryPointRevision), 1); + mainChecksum += smbiosHeader.entryPointRevision; + port->writeBlob(addr + 0xB, + (uint8_t *)(&smbiosHeader.formattedArea), 5); + for (int i = 0; i < 5; i++) + mainChecksum += smbiosHeader.formattedArea[i]; + + /* + * The intermediate header + */ + uint8_t intChecksum = 0; + + port->writeBlob(addr + 0x10, + (uint8_t *)smbiosHeader.intermediateHeader.anchorString, 5); + for (int i = 0; i < 5; i++) + intChecksum += smbiosHeader.intermediateHeader.anchorString[i]; + + // The checksum goes here, but we're figuring it out as we go. + // Then the length of the structure table which we'll find later + + uint32_t tableAddrGuest = + X86ISA::htog(smbiosHeader.intermediateHeader.tableAddr); + port->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); + for (int i = 0; i < 2; i++) { + intChecksum += numStructs; + numStructs >>= 8; + } + + port->writeBlob(addr + 0x1E, + (uint8_t *)(&smbiosHeader.intermediateHeader.smbiosBCDRevision), + 1); + intChecksum += smbiosHeader.intermediateHeader.smbiosBCDRevision; + + /* + * Structure table + */ + + Addr base = smbiosHeader.intermediateHeader.tableAddr; + Addr offset = 0; + uint16_t maxSize = 0; + std::vector::iterator it; + for (it = structures.begin(); it != structures.end(); it++) { + uint16_t size = it->writeOut(port, base + offset); + if (size > maxSize) + maxSize = size; + offset += size; + } + + /* + * Header + */ + + maxSize = X86ISA::htog(maxSize); + port->writeBlob(addr + 0x8, (uint8_t *)(&maxSize), 2); + for (int i = 0; i < 2; i++) { + mainChecksum += maxSize; + maxSize >>= 8; + } + + // Set the checksum + mainChecksum = -mainChecksum; + port->writeBlob(addr + 0x4, (uint8_t *)(&mainChecksum), 1); + + /* + * Intermediate header + */ + + uint16_t tableSize = offset; + tableSize = X86ISA::htog(tableSize); + port->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); +} diff --git a/src/arch/x86/bios/smbios.hh b/src/arch/x86/bios/smbios.hh new file mode 100644 index 000000000..8d3994fc7 --- /dev/null +++ b/src/arch/x86/bios/smbios.hh @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +/* + * Copyright (c) 2008 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * 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: Gabe Black + */ + +#ifndef __ARCH_X86_BIOS_SMBIOS_HH__ +#define __ARCH_X86_BIOS_SMBIOS_HH__ + +#include +#include + +#include "arch/x86/isa_traits.hh" +#include "mem/port.hh" +#include "sim/byteswap.hh" +#include "sim/host.hh" + +namespace X86ISA +{ + +namespace SMBios +{ + +class SMBiosStructure +{ + public: + + virtual + ~SMBiosStructure() + {} + + // Offset 00h, 1 byte + uint8_t type; + + // Offset 01h, 1 byte + //Length: computed when written to memory. + + // Offset 02h, 2 bytes + uint16_t handle; + + virtual uint8_t + getLength() + { + // This is the size of a structure with nothing but the header + return 4; + } + + virtual uint16_t + writeOut(FunctionalPort * port, Addr addr) + { + port->writeBlob(addr, (uint8_t *)(&type), 1); + + uint8_t length = getLength(); + port->writeBlob(addr + 1, (uint8_t *)(&length), 1); + + uint16_t handleGuest = X86ISA::htog(handle); + port->writeBlob(addr + 2, (uint8_t *)(&handleGuest), 2); + + return length + getStringLength(); + } + + protected: + std::vector strings; + + void writeOutStrings(FunctionalPort * port, Addr addr) + { + std::vector::iterator it; + Addr offset = 0; + + for (it = strings.begin(); it != strings.end(); it++) { + port->writeBlob(addr + offset, + (uint8_t *)it->c_str(), it->length() + 1); + offset += it->length() + 1; + } + + const uint8_t nullTerminator = 0; + port->writeBlob(addr + offset, (uint8_t *)(&nullTerminator), 1); + } + + int getStringLength() + { + int size = 0; + std::vector::iterator it; + + for (it = strings.begin(); it != strings.end(); it++) { + size += it->length() + 1; + } + + return size + 1; + } + + public: + + int addString(std::string & newString) + { + strings.push_back(newString); + return strings.size(); + } + + std::string readString(int n) + { + assert(n > 0 && n <= strings.size()); + return strings[n - 1]; + } + + void setString(int n, std::string & newString) + { + assert(n > 0 && n <= strings.size()); + strings[n - 1] = newString; + } +}; + +class BiosInformation : public SMBiosStructure +{ + public: + // Offset 04h, 1 byte + uint8_t vendor; + // Offset 05h, 1 byte + uint8_t version; + // Offset 06h, 2 bytes + uint16_t startingAddrSegment; + // Offset 08h, 1 byte + uint8_t releaseDate; + // Offset 09h, 1 byte + uint8_t romSize; + // Offset 0Ah, 8 bytes + //See tables in 3.3.1 in the SMBios 2.5 spec from the DMTF for + //bit definitions. + uint64_t characteristics; + // Offset 12h, 2 bytes + uint16_t characteristicExtBytes; + // Offset 14h, 1 byte + uint8_t major; + // Offset 15h, 1 byte + uint8_t minor; + // Offset 16h, 1 byte + uint8_t embContFirmwareMajor; + // Offset 17h, 1 byte + uint8_t embContFirmwareMinor; + + uint8_t getLength() { return 0x18; } + uint16_t writeOut(FunctionalPort * port, Addr addr); +}; + +class SMBiosTable +{ + public: + struct SMBiosHeader + { + SMBiosHeader() + {} + + // Offset 00h, 4 bytes + static const char anchorString[]; + + // Offset 04h, 1 byte + //Checksum: computed when written to memory. + + // Offset 05h, 1 byte + static const uint8_t entryPointLength; + + // Offset 06h, 1 byte + uint8_t majorVersion; + + // Offset 07h, 1 byte + uint8_t minorVersion; + + // Offset 08h, 2 bytes + //Maximum structure size: computed when written to memory. + + // Offset 0Ah, 1 byte + static const uint8_t entryPointRevision; + + // Offset 0Bh, 5 bytes + static const uint8_t formattedArea[5]; + + // Offset 10h, 15 bytes + struct IntermediateHeader + { + IntermediateHeader() : tableAddr(0) + {} + // Offset 10h, 5 bytes + static const char anchorString[]; + + // Offset 15h, 1 byte + //Checksum: computed when written to memory. + + // Offset 16h, 2 bytes + //Length of the structure table in bytes: computed when + //written to memory. + + // Offset 18h, 4 bytes + uint32_t tableAddr; + + // Offset 1Ch, 2 bytes + //Number of structures: computed when written to memory + + // Offset 1Eh, 1 byte + uint8_t smbiosBCDRevision; + } intermediateHeader; + } smbiosHeader; + + void writeOut(FunctionalPort * port, Addr addr); + + std::vector structures; +}; + +} //SMBios +} //X86ISA + +#endif diff --git a/src/arch/x86/smbios.cc b/src/arch/x86/smbios.cc deleted file mode 100644 index 319650c1f..000000000 --- a/src/arch/x86/smbios.cc +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (c) 2008 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -/* - * Copyright (c) 2008 The Hewlett-Packard Development Company - * All rights reserved. - * - * Redistribution and use of this software in source and binary forms, - * with or without modification, are permitted provided that the - * following conditions are met: - * - * The software must be used only for Non-Commercial Use which means any - * use which is NOT directed to receiving any direct monetary - * compensation for, or commercial advantage from such use. Illustrative - * examples of non-commercial use are academic research, personal study, - * teaching, education and corporate research & development. - * Illustrative examples of commercial use are distributing products for - * commercial advantage and providing services using the software for - * commercial advantage. - * - * If you wish to use this software or functionality therein that may be - * covered by patents for commercial use, please contact: - * Director of Intellectual Property Licensing - * Office of Strategy and Technology - * Hewlett-Packard Company - * 1501 Page Mill Road - * Palo Alto, California 94304 - * - * 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. No right of - * sublicense is granted herewith. Derivatives of the software and - * output created using the software may be prepared, but only for - * Non-Commercial Uses. Derivatives of the software may be shared with - * others provided: (i) the others agree to abide by the list of - * conditions herein which includes the Non-Commercial Use restrictions; - * and (ii) such Derivatives of the software include the above copyright - * notice to acknowledge the contribution from this software where - * applicable, this list of conditions and the disclaimer below. - * - * 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: Gabe Black - */ - -#include "arch/x86/smbios.hh" -#include "arch/x86/isa_traits.hh" -#include "mem/port.hh" -#include "sim/byteswap.hh" -#include "sim/host.hh" - -const char X86ISA::SMBios::SMBiosTable::SMBiosHeader::anchorString[] = "_SM_"; -const uint8_t X86ISA::SMBios::SMBiosTable:: - SMBiosHeader::formattedArea[] = {0,0,0,0,0}; -const uint8_t X86ISA::SMBios::SMBiosTable:: - SMBiosHeader::entryPointLength = 0x1F; -const uint8_t X86ISA::SMBios::SMBiosTable:: - SMBiosHeader::entryPointRevision = 0; -const char X86ISA::SMBios::SMBiosTable:: - SMBiosHeader::IntermediateHeader::anchorString[] = "_DMI_"; - -uint16_t -X86ISA::SMBios::BiosInformation::writeOut(FunctionalPort * port, Addr addr) -{ - uint8_t size = SMBiosStructure::writeOut(port, addr); - - port->writeBlob(addr + 0x4, (uint8_t *)(&vendor), 1); - port->writeBlob(addr + 0x5, (uint8_t *)(&version), 1); - - uint16_t startingAddrSegmentGuest = X86ISA::htog(startingAddrSegment); - port->writeBlob(addr + 0x6, (uint8_t *)(&startingAddrSegmentGuest), 2); - - port->writeBlob(addr + 0x8, (uint8_t *)(&releaseDate), 1); - port->writeBlob(addr + 0x9, (uint8_t *)(&romSize), 1); - - uint64_t characteristicsGuest = X86ISA::htog(characteristics); - port->writeBlob(addr + 0xA, (uint8_t *)(&characteristicsGuest), 8); - - uint16_t characteristicExtBytesGuest = - X86ISA::htog(characteristicExtBytes); - port->writeBlob(addr + 0x12, (uint8_t *)(&characteristicExtBytesGuest), 2); - - port->writeBlob(addr + 0x14, (uint8_t *)(&major), 1); - port->writeBlob(addr + 0x15, (uint8_t *)(&minor), 1); - port->writeBlob(addr + 0x16, (uint8_t *)(&embContFirmwareMajor), 1); - port->writeBlob(addr + 0x17, (uint8_t *)(&embContFirmwareMinor), 1); - - writeOutStrings(port, addr + getLength()); - - return size; -} - -void -X86ISA::SMBios::SMBiosTable::writeOut(FunctionalPort * port, Addr addr) -{ - - /* - * The main header - */ - uint8_t mainChecksum = 0; - - port->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, - (uint8_t *)(&smbiosHeader.entryPointLength), 1); - mainChecksum += smbiosHeader.entryPointLength; - port->writeBlob(addr + 0x6, - (uint8_t *)(&smbiosHeader.majorVersion), 1); - mainChecksum += smbiosHeader.majorVersion; - port->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, - (uint8_t *)(&smbiosHeader.entryPointRevision), 1); - mainChecksum += smbiosHeader.entryPointRevision; - port->writeBlob(addr + 0xB, - (uint8_t *)(&smbiosHeader.formattedArea), 5); - for (int i = 0; i < 5; i++) - mainChecksum += smbiosHeader.formattedArea[i]; - - /* - * The intermediate header - */ - uint8_t intChecksum = 0; - - port->writeBlob(addr + 0x10, - (uint8_t *)smbiosHeader.intermediateHeader.anchorString, 5); - for (int i = 0; i < 5; i++) - intChecksum += smbiosHeader.intermediateHeader.anchorString[i]; - - // The checksum goes here, but we're figuring it out as we go. - // Then the length of the structure table which we'll find later - - uint32_t tableAddrGuest = - X86ISA::htog(smbiosHeader.intermediateHeader.tableAddr); - port->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); - for (int i = 0; i < 2; i++) { - intChecksum += numStructs; - numStructs >>= 8; - } - - port->writeBlob(addr + 0x1E, - (uint8_t *)(&smbiosHeader.intermediateHeader.smbiosBCDRevision), - 1); - intChecksum += smbiosHeader.intermediateHeader.smbiosBCDRevision; - - /* - * Structure table - */ - - Addr base = smbiosHeader.intermediateHeader.tableAddr; - Addr offset = 0; - uint16_t maxSize = 0; - std::vector::iterator it; - for (it = structures.begin(); it != structures.end(); it++) { - uint16_t size = it->writeOut(port, base + offset); - if (size > maxSize) - maxSize = size; - offset += size; - } - - /* - * Header - */ - - maxSize = X86ISA::htog(maxSize); - port->writeBlob(addr + 0x8, (uint8_t *)(&maxSize), 2); - for (int i = 0; i < 2; i++) { - mainChecksum += maxSize; - maxSize >>= 8; - } - - // Set the checksum - mainChecksum = -mainChecksum; - port->writeBlob(addr + 0x4, (uint8_t *)(&mainChecksum), 1); - - /* - * Intermediate header - */ - - uint16_t tableSize = offset; - tableSize = X86ISA::htog(tableSize); - port->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); -} diff --git a/src/arch/x86/smbios.hh b/src/arch/x86/smbios.hh deleted file mode 100644 index c126de220..000000000 --- a/src/arch/x86/smbios.hh +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright (c) 2008 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -/* - * Copyright (c) 2008 The Hewlett-Packard Development Company - * All rights reserved. - * - * Redistribution and use of this software in source and binary forms, - * with or without modification, are permitted provided that the - * following conditions are met: - * - * The software must be used only for Non-Commercial Use which means any - * use which is NOT directed to receiving any direct monetary - * compensation for, or commercial advantage from such use. Illustrative - * examples of non-commercial use are academic research, personal study, - * teaching, education and corporate research & development. - * Illustrative examples of commercial use are distributing products for - * commercial advantage and providing services using the software for - * commercial advantage. - * - * If you wish to use this software or functionality therein that may be - * covered by patents for commercial use, please contact: - * Director of Intellectual Property Licensing - * Office of Strategy and Technology - * Hewlett-Packard Company - * 1501 Page Mill Road - * Palo Alto, California 94304 - * - * 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. No right of - * sublicense is granted herewith. Derivatives of the software and - * output created using the software may be prepared, but only for - * Non-Commercial Uses. Derivatives of the software may be shared with - * others provided: (i) the others agree to abide by the list of - * conditions herein which includes the Non-Commercial Use restrictions; - * and (ii) such Derivatives of the software include the above copyright - * notice to acknowledge the contribution from this software where - * applicable, this list of conditions and the disclaimer below. - * - * 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: Gabe Black - */ - -#ifndef __ARCH_X86_SMBIOS_HH__ -#define __ARCH_X86_SMBIOS_HH__ - -#include -#include - -#include "arch/x86/isa_traits.hh" -#include "mem/port.hh" -#include "sim/byteswap.hh" -#include "sim/host.hh" - -namespace X86ISA -{ - -namespace SMBios -{ - -class SMBiosStructure -{ - public: - - virtual - ~SMBiosStructure() - {} - - // Offset 00h, 1 byte - uint8_t type; - - // Offset 01h, 1 byte - //Length: computed when written to memory. - - // Offset 02h, 2 bytes - uint16_t handle; - - virtual uint8_t - getLength() - { - // This is the size of a structure with nothing but the header - return 4; - } - - virtual uint16_t - writeOut(FunctionalPort * port, Addr addr) - { - port->writeBlob(addr, (uint8_t *)(&type), 1); - - uint8_t length = getLength(); - port->writeBlob(addr + 1, (uint8_t *)(&length), 1); - - uint16_t handleGuest = X86ISA::htog(handle); - port->writeBlob(addr + 2, (uint8_t *)(&handleGuest), 2); - - return length + getStringLength(); - } - - protected: - std::vector strings; - - void writeOutStrings(FunctionalPort * port, Addr addr) - { - std::vector::iterator it; - Addr offset = 0; - - for (it = strings.begin(); it != strings.end(); it++) { - port->writeBlob(addr + offset, - (uint8_t *)it->c_str(), it->length() + 1); - offset += it->length() + 1; - } - - const uint8_t nullTerminator = 0; - port->writeBlob(addr + offset, (uint8_t *)(&nullTerminator), 1); - } - - int getStringLength() - { - int size = 0; - std::vector::iterator it; - - for (it = strings.begin(); it != strings.end(); it++) { - size += it->length() + 1; - } - - return size + 1; - } - - public: - - int addString(std::string & newString) - { - strings.push_back(newString); - return strings.size(); - } - - std::string readString(int n) - { - assert(n > 0 && n <= strings.size()); - return strings[n - 1]; - } - - void setString(int n, std::string & newString) - { - assert(n > 0 && n <= strings.size()); - strings[n - 1] = newString; - } -}; - -class BiosInformation : public SMBiosStructure -{ - public: - // Offset 04h, 1 byte - uint8_t vendor; - // Offset 05h, 1 byte - uint8_t version; - // Offset 06h, 2 bytes - uint16_t startingAddrSegment; - // Offset 08h, 1 byte - uint8_t releaseDate; - // Offset 09h, 1 byte - uint8_t romSize; - // Offset 0Ah, 8 bytes - //See tables in 3.3.1 in the SMBios 2.5 spec from the DMTF for - //bit definitions. - uint64_t characteristics; - // Offset 12h, 2 bytes - uint16_t characteristicExtBytes; - // Offset 14h, 1 byte - uint8_t major; - // Offset 15h, 1 byte - uint8_t minor; - // Offset 16h, 1 byte - uint8_t embContFirmwareMajor; - // Offset 17h, 1 byte - uint8_t embContFirmwareMinor; - - uint8_t getLength() { return 0x18; } - uint16_t writeOut(FunctionalPort * port, Addr addr); -}; - -class SMBiosTable -{ - public: - struct SMBiosHeader - { - SMBiosHeader() - {} - - // Offset 00h, 4 bytes - static const char anchorString[]; - - // Offset 04h, 1 byte - //Checksum: computed when written to memory. - - // Offset 05h, 1 byte - static const uint8_t entryPointLength; - - // Offset 06h, 1 byte - uint8_t majorVersion; - - // Offset 07h, 1 byte - uint8_t minorVersion; - - // Offset 08h, 2 bytes - //Maximum structure size: computed when written to memory. - - // Offset 0Ah, 1 byte - static const uint8_t entryPointRevision; - - // Offset 0Bh, 5 bytes - static const uint8_t formattedArea[5]; - - // Offset 10h, 15 bytes - struct IntermediateHeader - { - IntermediateHeader() : tableAddr(0) - {} - // Offset 10h, 5 bytes - static const char anchorString[]; - - // Offset 15h, 1 byte - //Checksum: computed when written to memory. - - // Offset 16h, 2 bytes - //Length of the structure table in bytes: computed when - //written to memory. - - // Offset 18h, 4 bytes - uint32_t tableAddr; - - // Offset 1Ch, 2 bytes - //Number of structures: computed when written to memory - - // Offset 1Eh, 1 byte - uint8_t smbiosBCDRevision; - } intermediateHeader; - } smbiosHeader; - - void writeOut(FunctionalPort * port, Addr addr); - - std::vector structures; -}; - -} //SMBios -} //X86ISA - -#endif diff --git a/src/arch/x86/system.cc b/src/arch/x86/system.cc index 947a7793e..48f34918d 100644 --- a/src/arch/x86/system.cc +++ b/src/arch/x86/system.cc @@ -55,9 +55,9 @@ * Authors: Gabe Black */ +#include "arch/x86/bios/smbios.hh" #include "arch/x86/miscregs.hh" #include "arch/x86/system.hh" -#include "arch/x86/smbios.hh" #include "arch/vtophys.hh" #include "base/remote_gdb.hh" #include "base/loader/object_file.hh" -- cgit v1.2.3 From 9be6e082270aad53f8ba40bf66a91fcf176a45ab Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 10 Oct 2008 03:50:42 -0700 Subject: X86: Add a couple comments to the bios SConscript --- src/arch/x86/bios/SConscript | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/arch/x86/bios/SConscript b/src/arch/x86/bios/SConscript index 904fab086..1ec717b11 100644 --- a/src/arch/x86/bios/SConscript +++ b/src/arch/x86/bios/SConscript @@ -59,7 +59,10 @@ Import('*') if env['TARGET_ISA'] == 'x86': if env['FULL_SYSTEM']: + # The table generated by the bootloader using the BIOS and passed to + # the operating system which maps out physical memory. SimObject('E820.py') Source('e820.cc') + # The DMI tables. Source('smbios.cc') -- cgit v1.2.3 From ec0fb05d643323ae036156be76acd42c8275a2f4 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 10 Oct 2008 03:50:51 -0700 Subject: X86: Turn SMBios structures into simobjects. --- src/arch/x86/X86System.py | 3 + src/arch/x86/bios/SConscript | 1 + src/arch/x86/bios/SMBios.py | 140 +++++++++++++++++++++++++++++++++++++++ src/arch/x86/bios/smbios.cc | 152 +++++++++++++++++++++++++++++++++++++++++-- src/arch/x86/bios/smbios.hh | 114 ++++++++++++++------------------ src/arch/x86/system.cc | 35 +++++----- src/arch/x86/system.hh | 3 +- 7 files changed, 361 insertions(+), 87 deletions(-) create mode 100644 src/arch/x86/bios/SMBios.py (limited to 'src') diff --git a/src/arch/x86/X86System.py b/src/arch/x86/X86System.py index b4ec393c3..5fe69c709 100644 --- a/src/arch/x86/X86System.py +++ b/src/arch/x86/X86System.py @@ -55,10 +55,13 @@ from m5.params import * from E820 import X86E820Table, X86E820Entry +from SMBios import X86SMBiosSMBiosTable from System import System class X86System(System): type = 'X86System' + smbios_table = Param.X86SMBiosSMBiosTable( + X86SMBiosSMBiosTable(), 'table of smbios/dmi information') class LinuxX86System(X86System): type = 'LinuxX86System' diff --git a/src/arch/x86/bios/SConscript b/src/arch/x86/bios/SConscript index 1ec717b11..cdb5f390f 100644 --- a/src/arch/x86/bios/SConscript +++ b/src/arch/x86/bios/SConscript @@ -65,4 +65,5 @@ if env['TARGET_ISA'] == 'x86': Source('e820.cc') # The DMI tables. + SimObject('SMBios.py') Source('smbios.cc') diff --git a/src/arch/x86/bios/SMBios.py b/src/arch/x86/bios/SMBios.py new file mode 100644 index 000000000..4947b2854 --- /dev/null +++ b/src/arch/x86/bios/SMBios.py @@ -0,0 +1,140 @@ +# Copyright (c) 2008 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use of this software in source and binary forms, +# with or without modification, are permitted provided that the +# following conditions are met: +# +# The software must be used only for Non-Commercial Use which means any +# use which is NOT directed to receiving any direct monetary +# compensation for, or commercial advantage from such use. Illustrative +# examples of non-commercial use are academic research, personal study, +# teaching, education and corporate research & development. +# Illustrative examples of commercial use are distributing products for +# commercial advantage and providing services using the software for +# commercial advantage. +# +# If you wish to use this software or functionality therein that may be +# covered by patents for commercial use, please contact: +# Director of Intellectual Property Licensing +# Office of Strategy and Technology +# Hewlett-Packard Company +# 1501 Page Mill Road +# Palo Alto, California 94304 +# +# 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. No right of +# sublicense is granted herewith. Derivatives of the software and +# output created using the software may be prepared, but only for +# Non-Commercial Uses. Derivatives of the software may be shared with +# others provided: (i) the others agree to abide by the list of +# conditions herein which includes the Non-Commercial Use restrictions; +# and (ii) such Derivatives of the software include the above copyright +# notice to acknowledge the contribution from this software where +# applicable, this list of conditions and the disclaimer below. +# +# 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: Gabe Black + +from m5.params import * +from m5.SimObject import SimObject + +class X86SMBiosSMBiosStructure(SimObject): + type = 'X86SMBiosSMBiosStructure' + cxx_class = 'X86ISA::SMBios::SMBiosStructure' + abstract = True + +class Characteristic(Enum): + map = {'Unknown' : 2, + 'Unsupported' : 3, + 'ISA' : 4, + 'MCA' : 5, + 'EISA' : 6, + 'PCI' : 7, + 'PCMCIA' : 8, + 'PnP' : 9, + 'APM' : 10, + 'Flash' : 11, + 'Shadow' : 12, + 'VL_Vesa' : 13, + 'ESCD' : 14, + 'CDBoot' : 15, + 'SelectBoot' : 16, + 'Socketed' : 17, + 'PCMCIABoot' : 18, + 'EDD' : 19, + 'NEC9800' : 20, + 'Toshiba' : 21, + 'Floppy_5_25_360KB' : 22, + 'Floppy_5_25_1_2MB' : 23, + 'Floppy_3_5_720KB' : 24, + 'Floppy_3_5_2_88MB' : 25, + 'PrintScreen' : 26, + 'Keyboard8024' : 27, + 'Serial' : 28, + 'Printer' : 29, + 'CGA_Mono' : 30, + 'NEC_PC_98' : 31 + } + +class ExtCharacteristic(Enum): + map = {'ACPI' : 0, + 'USBLegacy' : 1, + 'AGP' : 2, + 'I20Boot' : 3, + 'LS_120Boot' : 4, + 'ZIPBoot' : 5, + 'FirewireBoot' : 6, + 'SmartBattery' : 7, + 'BootSpec' : 8, + 'NetServiceBoot' : 9, + 'TargetContent' : 10 + } + +class X86SMBiosBiosInformation(X86SMBiosSMBiosStructure): + type = 'X86SMBiosBiosInformation' + cxx_class = 'X86ISA::SMBios::BiosInformation' + + vendor = Param.String("", "vendor name string") + version = Param.String("", "version string") + starting_addr_segment = \ + Param.UInt16(0, "segment location of bios starting address") + release_date = Param.String("06/08/2008", "release date") + rom_size = Param.UInt8(0, "rom size") + characteristics = VectorParam.Characteristic([], + "bios characteristic bit vector") + characteristic_ext_bytes = VectorParam.ExtCharacteristic([], + "extended bios characteristic bit vector") + major = Param.UInt8(0, "major version number") + minor = Param.UInt8(0, "minor version number") + emb_cont_firmware_major = Param.UInt8(0, + "embedded controller firmware major version number") + + emb_cont_firmware_minor = Param.UInt8(0, + "embedded controller firmware minor version number") + +class X86SMBiosSMBiosTable(SimObject): + type = 'X86SMBiosSMBiosTable' + cxx_class = 'X86ISA::SMBios::SMBiosTable' + + major_version = Param.UInt8(2, "major version number") + minor_version = Param.UInt8(5, "minor version number") + + structures = VectorParam.X86SMBiosSMBiosStructure([], "smbios structures") diff --git a/src/arch/x86/bios/smbios.cc b/src/arch/x86/bios/smbios.cc index de4a263b7..95ade1e4d 100644 --- a/src/arch/x86/bios/smbios.cc +++ b/src/arch/x86/bios/smbios.cc @@ -88,9 +88,14 @@ #include "arch/x86/bios/smbios.hh" #include "arch/x86/isa_traits.hh" #include "mem/port.hh" +#include "params/X86SMBiosBiosInformation.hh" +#include "params/X86SMBiosSMBiosStructure.hh" +#include "params/X86SMBiosSMBiosTable.hh" #include "sim/byteswap.hh" #include "sim/host.hh" +using namespace std; + const char X86ISA::SMBios::SMBiosTable::SMBiosHeader::anchorString[] = "_SM_"; const uint8_t X86ISA::SMBios::SMBiosTable:: SMBiosHeader::formattedArea[] = {0,0,0,0,0}; @@ -101,6 +106,116 @@ const uint8_t X86ISA::SMBios::SMBiosTable:: const char X86ISA::SMBios::SMBiosTable:: SMBiosHeader::IntermediateHeader::anchorString[] = "_DMI_"; +template +uint64_t +composeBitVector(T vec) +{ + uint64_t val = 0; + typename T::iterator vecIt; + for (vecIt = vec.begin(); vecIt != vec.end(); vecIt++) { + val |= (1 << (*vecIt)); + } + return val; +} + +uint16_t +X86ISA::SMBios::SMBiosStructure::writeOut(FunctionalPort * port, Addr addr) +{ + port->writeBlob(addr, (uint8_t *)(&type), 1); + + uint8_t length = getLength(); + port->writeBlob(addr + 1, (uint8_t *)(&length), 1); + + uint16_t handleGuest = X86ISA::htog(handle); + port->writeBlob(addr + 2, (uint8_t *)(&handleGuest), 2); + + return length + getStringLength(); +} + +X86ISA::SMBios::SMBiosStructure::SMBiosStructure(Params * p, uint8_t _type) : + SimObject(p), type(_type), handle(0), stringFields(false) +{} + +void +X86ISA::SMBios::SMBiosStructure::writeOutStrings( + FunctionalPort * port, Addr addr) +{ + std::vector::iterator it; + Addr offset = 0; + + const uint8_t nullTerminator = 0; + + // 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); + offset++; + } else { + for (it = strings.begin(); it != strings.end(); it++) { + port->writeBlob(addr + offset, + (uint8_t *)it->c_str(), it->length() + 1); + offset += it->length() + 1; + } + } + port->writeBlob(addr + offset, (uint8_t *)(&nullTerminator), 1); +} + +int +X86ISA::SMBios::SMBiosStructure::getStringLength() +{ + int size = 0; + std::vector::iterator it; + + for (it = strings.begin(); it != strings.end(); it++) { + size += it->length() + 1; + } + + return size + 1; +} + +int +X86ISA::SMBios::SMBiosStructure::addString(string & newString) +{ + stringFields = true; + // If a string is empty, treat it as not existing. The index for empty + // strings is 0. + if (newString.length() == 0) + return 0; + strings.push_back(newString); + return strings.size(); +} + +string +X86ISA::SMBios::SMBiosStructure::readString(int n) +{ + assert(n > 0 && n <= strings.size()); + return strings[n - 1]; +} + +void +X86ISA::SMBios::SMBiosStructure::setString(int n, std::string & newString) +{ + assert(n > 0 && n <= strings.size()); + strings[n - 1] = newString; +} + +X86ISA::SMBios::BiosInformation::BiosInformation(Params * p) : + SMBiosStructure(p, Type), + startingAddrSegment(p->starting_addr_segment), + romSize(p->rom_size), + majorVer(p->major), minorVer(p->minor), + embContFirmwareMajor(p->emb_cont_firmware_major), + embContFirmwareMinor(p->emb_cont_firmware_minor) + { + vendor = addString(p->vendor); + version = addString(p->version); + releaseDate = addString(p->release_date); + + characteristics = composeBitVector(p->characteristics); + characteristicExtBytes = + composeBitVector(p->characteristic_ext_bytes); + } + uint16_t X86ISA::SMBios::BiosInformation::writeOut(FunctionalPort * port, Addr addr) { @@ -122,8 +237,8 @@ X86ISA::SMBios::BiosInformation::writeOut(FunctionalPort * port, Addr addr) X86ISA::htog(characteristicExtBytes); port->writeBlob(addr + 0x12, (uint8_t *)(&characteristicExtBytesGuest), 2); - port->writeBlob(addr + 0x14, (uint8_t *)(&major), 1); - port->writeBlob(addr + 0x15, (uint8_t *)(&minor), 1); + 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); @@ -132,9 +247,22 @@ X86ISA::SMBios::BiosInformation::writeOut(FunctionalPort * port, Addr addr) return size; } +X86ISA::SMBios::SMBiosTable::SMBiosTable(Params * p) : + SimObject(p), structures(p->structures) +{ + smbiosHeader.majorVersion = p->major_version; + smbiosHeader.minorVersion = p->minor_version; + assert(p->major_version <= 9); + assert(p->minor_version <= 9); + smbiosHeader.intermediateHeader.smbiosBCDRevision = + (p->major_version << 4) | p->minor_version; +} + void -X86ISA::SMBios::SMBiosTable::writeOut(FunctionalPort * port, Addr addr) +X86ISA::SMBios::SMBiosTable::writeOut(FunctionalPort * port, Addr addr, + Addr &headerSize, Addr &structSize) { + headerSize = 0x1F; /* * The main header @@ -205,14 +333,16 @@ X86ISA::SMBios::SMBiosTable::writeOut(FunctionalPort * port, Addr addr) Addr base = smbiosHeader.intermediateHeader.tableAddr; Addr offset = 0; uint16_t maxSize = 0; - std::vector::iterator it; + std::vector::iterator it; for (it = structures.begin(); it != structures.end(); it++) { - uint16_t size = it->writeOut(port, base + offset); + uint16_t size = (*it)->writeOut(port, base + offset); if (size > maxSize) maxSize = size; offset += size; } + structSize = offset; + /* * Header */ @@ -243,3 +373,15 @@ X86ISA::SMBios::SMBiosTable::writeOut(FunctionalPort * port, Addr addr) intChecksum = -intChecksum; port->writeBlob(addr + 0x15, (uint8_t *)(&intChecksum), 1); } + +X86ISA::SMBios::BiosInformation * +X86SMBiosBiosInformationParams::create() +{ + return new X86ISA::SMBios::BiosInformation(this); +} + +X86ISA::SMBios::SMBiosTable * +X86SMBiosSMBiosTableParams::create() +{ + return new X86ISA::SMBios::SMBiosTable(this); +} diff --git a/src/arch/x86/bios/smbios.hh b/src/arch/x86/bios/smbios.hh index 8d3994fc7..1c50d0b48 100644 --- a/src/arch/x86/bios/smbios.hh +++ b/src/arch/x86/bios/smbios.hh @@ -91,10 +91,15 @@ #include #include -#include "arch/x86/isa_traits.hh" -#include "mem/port.hh" -#include "sim/byteswap.hh" +#include "enums/Characteristic.hh" +#include "enums/ExtCharacteristic.hh" #include "sim/host.hh" +#include "sim/sim_object.hh" + +class FunctionalPort; +class X86SMBiosBiosInformationParams; +class X86SMBiosSMBiosStructureParams; +class X86SMBiosSMBiosTableParams; namespace X86ISA { @@ -102,8 +107,11 @@ namespace X86ISA namespace SMBios { -class SMBiosStructure +class SMBiosStructure : public SimObject { + protected: + typedef X86SMBiosSMBiosStructureParams Params; + public: virtual @@ -126,73 +134,33 @@ class SMBiosStructure return 4; } - virtual uint16_t - writeOut(FunctionalPort * port, Addr addr) - { - port->writeBlob(addr, (uint8_t *)(&type), 1); - - uint8_t length = getLength(); - port->writeBlob(addr + 1, (uint8_t *)(&length), 1); - - uint16_t handleGuest = X86ISA::htog(handle); - port->writeBlob(addr + 2, (uint8_t *)(&handleGuest), 2); - - return length + getStringLength(); - } + virtual uint16_t writeOut(FunctionalPort * port, Addr addr); protected: - std::vector strings; - - void writeOutStrings(FunctionalPort * port, Addr addr) - { - std::vector::iterator it; - Addr offset = 0; - - for (it = strings.begin(); it != strings.end(); it++) { - port->writeBlob(addr + offset, - (uint8_t *)it->c_str(), it->length() + 1); - offset += it->length() + 1; - } + bool stringFields; - const uint8_t nullTerminator = 0; - port->writeBlob(addr + offset, (uint8_t *)(&nullTerminator), 1); - } + SMBiosStructure(Params * p, uint8_t _type); - int getStringLength() - { - int size = 0; - std::vector::iterator it; + std::vector strings; - for (it = strings.begin(); it != strings.end(); it++) { - size += it->length() + 1; - } + void writeOutStrings(FunctionalPort * port, Addr addr); - return size + 1; - } + int getStringLength(); public: - int addString(std::string & newString) - { - strings.push_back(newString); - return strings.size(); - } - - std::string readString(int n) - { - assert(n > 0 && n <= strings.size()); - return strings[n - 1]; - } - - void setString(int n, std::string & newString) - { - assert(n > 0 && n <= strings.size()); - strings[n - 1] = newString; - } + int addString(std::string & newString); + std::string readString(int n); + void setString(int n, std::string & newString); }; class BiosInformation : public SMBiosStructure { + protected: + const static uint8_t Type = 0; + + typedef X86SMBiosBiosInformationParams Params; + public: // Offset 04h, 1 byte uint8_t vendor; @@ -211,21 +179,25 @@ class BiosInformation : public SMBiosStructure // Offset 12h, 2 bytes uint16_t characteristicExtBytes; // Offset 14h, 1 byte - uint8_t major; + uint8_t majorVer; // Offset 15h, 1 byte - uint8_t minor; + uint8_t minorVer; // Offset 16h, 1 byte uint8_t embContFirmwareMajor; // Offset 17h, 1 byte uint8_t embContFirmwareMinor; + BiosInformation(Params * p); + uint8_t getLength() { return 0x18; } uint16_t writeOut(FunctionalPort * port, Addr addr); }; -class SMBiosTable +class SMBiosTable : public SimObject { - public: + protected: + typedef X86SMBiosSMBiosTableParams Params; + struct SMBiosHeader { SMBiosHeader() @@ -281,9 +253,23 @@ class SMBiosTable } intermediateHeader; } smbiosHeader; - void writeOut(FunctionalPort * port, Addr addr); + std::vector structures; + + public: + SMBiosTable(Params * p); + + Addr getTableAddr() + { + return smbiosHeader.intermediateHeader.tableAddr; + } + + void setTableAddr(Addr addr) + { + smbiosHeader.intermediateHeader.tableAddr = addr; + } - std::vector structures; + void writeOut(FunctionalPort * port, Addr addr, + Addr &headerSize, Addr &structSize); }; } //SMBios diff --git a/src/arch/x86/system.cc b/src/arch/x86/system.cc index 48f34918d..9006ce227 100644 --- a/src/arch/x86/system.cc +++ b/src/arch/x86/system.cc @@ -73,13 +73,8 @@ using namespace LittleEndianGuest; using namespace X86ISA; X86System::X86System(Params *p) - : System(p) -{ - smbiosTable = new X86ISA::SMBios::SMBiosTable; - smbiosTable->smbiosHeader.majorVersion = 2; - smbiosTable->smbiosHeader.minorVersion = 5; - smbiosTable->smbiosHeader.intermediateHeader.smbiosBCDRevision = 0x25; -} + : System(p), smbiosTable(p->smbios_table) +{} void X86System::startup() @@ -236,27 +231,33 @@ X86System::startup() // We should now be in long mode. Yay! + Addr ebdaPos = 0xF0000; + + Addr headerSize, structSize; //Write out the SMBios/DMI table - writeOutSMBiosTable(0xF0000); + writeOutSMBiosTable(ebdaPos, headerSize, structSize); + ebdaPos += (headerSize + structSize); } void -X86System::writeOutSMBiosTable(Addr header, Addr table) +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(); // 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 - if (!table) { - if (!smbiosTable->smbiosHeader.intermediateHeader.tableAddr) - smbiosTable->smbiosHeader. - intermediateHeader.tableAddr = header + 0x1F; - } else { - smbiosTable->smbiosHeader.intermediateHeader.tableAddr = table; - } + if (!table) + table = header + 0x1F; + smbiosTable->setTableAddr(table); + + smbiosTable->writeOut(physPort, header, headerSize, structSize); - smbiosTable->writeOut(physPort, header); + // Do some bounds checking to make sure we at least didn't step on + // ourselves. + assert(header > table || header + headerSize <= table); + assert(table > header || table + structSize <= header); } diff --git a/src/arch/x86/system.hh b/src/arch/x86/system.hh index 8a5483ebf..2120bc090 100644 --- a/src/arch/x86/system.hh +++ b/src/arch/x86/system.hh @@ -96,7 +96,8 @@ class X86System : public System X86ISA::SMBios::SMBiosTable * smbiosTable; - void writeOutSMBiosTable(Addr header, Addr table = 0); + void writeOutSMBiosTable(Addr header, + Addr &headerSize, Addr &tableSize, Addr table = 0); const Params *params() const { return (const Params *)_params; } -- cgit v1.2.3 From 5586b1539baf6dd9029473a4ec1596a9fc8b7765 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 10 Oct 2008 10:15:00 -0700 Subject: misc: remove #include from misc.hh since not everyone needs it. --- src/arch/alpha/miscregfile.cc | 2 ++ src/arch/sparc/pagetable.hh | 2 ++ src/arch/x86/emulenv.cc | 2 ++ src/arch/x86/predecoder.hh | 2 ++ src/base/loader/elf_object.cc | 1 + src/base/misc.hh | 8 +++----- 6 files changed, 12 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/miscregfile.cc b/src/arch/alpha/miscregfile.cc index f119ca6bb..61a86f1fb 100644 --- a/src/arch/alpha/miscregfile.cc +++ b/src/arch/alpha/miscregfile.cc @@ -30,6 +30,8 @@ * Kevin Lim */ +#include + #include "arch/alpha/miscregfile.hh" #include "base/misc.hh" diff --git a/src/arch/sparc/pagetable.hh b/src/arch/sparc/pagetable.hh index d787f30e4..ee4ca0c2c 100644 --- a/src/arch/sparc/pagetable.hh +++ b/src/arch/sparc/pagetable.hh @@ -31,6 +31,8 @@ #ifndef __ARCH_SPARC_PAGETABLE_HH__ #define __ARCH_SPARC_PAGETABLE_HH__ +#include + #include "arch/sparc/isa_traits.hh" #include "base/bitfield.hh" #include "base/misc.hh" diff --git a/src/arch/x86/emulenv.cc b/src/arch/x86/emulenv.cc index 142e233db..30ed80942 100644 --- a/src/arch/x86/emulenv.cc +++ b/src/arch/x86/emulenv.cc @@ -55,6 +55,8 @@ * Authors: Gabe Black */ +#include + #include "arch/x86/emulenv.hh" #include "base/misc.hh" diff --git a/src/arch/x86/predecoder.hh b/src/arch/x86/predecoder.hh index 6e41e8134..a16ce6fb8 100644 --- a/src/arch/x86/predecoder.hh +++ b/src/arch/x86/predecoder.hh @@ -58,6 +58,8 @@ #ifndef __ARCH_X86_PREDECODER_HH__ #define __ARCH_X86_PREDECODER_HH__ +#include + #include "arch/x86/types.hh" #include "base/bitfield.hh" #include "base/misc.hh" diff --git a/src/base/loader/elf_object.cc b/src/base/loader/elf_object.cc index ad46a7de5..f71c4456b 100644 --- a/src/base/loader/elf_object.cc +++ b/src/base/loader/elf_object.cc @@ -29,6 +29,7 @@ * Ali Saidi */ +#include #include #include "gelf.h" diff --git a/src/base/misc.hh b/src/base/misc.hh index 6b0025c34..8d38fa731 100644 --- a/src/base/misc.hh +++ b/src/base/misc.hh @@ -29,10 +29,8 @@ * Dave Greene */ -#ifndef __MISC_HH__ -#define __MISC_HH__ - -#include +#ifndef __BASE_MISC_HH__ +#define __BASE_MISC_HH__ #include "base/compiler.hh" #include "base/cprintf.hh" @@ -113,4 +111,4 @@ __warn(const char *func, const char *file, int line, const std::string &format, } \ } while (0) -#endif // __MISC_HH__ +#endif // __BASE_MISC_HH__ -- cgit v1.2.3 From 84364f36d0f763d3cef9847396fa4195184cb930 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 10 Oct 2008 10:15:00 -0700 Subject: python: Add a utility for nested attribute dicts. Change attrdict so that attributes that begin with an underscore don't go into the dict. --- src/python/m5/util/attrdict.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/python/m5/util/attrdict.py b/src/python/m5/util/attrdict.py index 44479c456..56f67217b 100644 --- a/src/python/m5/util/attrdict.py +++ b/src/python/m5/util/attrdict.py @@ -26,16 +26,17 @@ # # Authors: Nathan Binkert -__all__ = [ 'attrdict', 'optiondict' ] +__all__ = [ 'attrdict', 'multiattrdict', 'optiondict' ] class attrdict(dict): + """Wrap dict, so you can use attribute access to get/set elements""" def __getattr__(self, attr): if attr in self: return self.__getitem__(attr) return super(attrdict, self).__getattribute__(attr) def __setattr__(self, attr, value): - if attr in dir(self): + if attr in dir(self) or attr.startswith('_'): return super(attrdict, self).__setattr__(attr, value) return self.__setitem__(attr, value) @@ -44,13 +45,23 @@ class attrdict(dict): return self.__delitem__(attr) return super(attrdict, self).__delattr__(attr, value) +class multiattrdict(attrdict): + """Wrap attrdict so that nested attribute accesses automatically create + nested dictionaries.""" + def __getattr__(self, attr): + try: + return super(multiattrdict, self).__getattr__(attr) + except AttributeError: + d = optiondict() + setattr(self, attr, d) + return d + class optiondict(attrdict): + """Modify attrdict so that a missing attribute just returns None""" def __getattr__(self, attr): try: return super(optiondict, self).__getattr__(attr) except AttributeError: - #d = optionsdict() - #setattr(self, attr, d) return None if __name__ == '__main__': @@ -68,3 +79,9 @@ if __name__ == '__main__': del x.z print dir(x) print(x) + + x = multiattrdict() + x.y.z = 9 + print x + print x.y + print x.y.z -- cgit v1.2.3 From 70dbe61ffc8dae4fc2ecc252f963a760a4387517 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 10 Oct 2008 10:15:01 -0700 Subject: jobfile: Add support for dictionaries as jobfile options. If the same dictionary option is seen in several options, those dictionaries are composed. If you define the same dictionary key in multiple options, the system flags an error. Also, clean up the jobfile code so that it is more debuggable. --- src/python/m5/util/jobfile.py | 52 ++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/python/m5/util/jobfile.py b/src/python/m5/util/jobfile.py index 5e015c4ad..c830895f6 100644 --- a/src/python/m5/util/jobfile.py +++ b/src/python/m5/util/jobfile.py @@ -28,8 +28,8 @@ import sys -from attrdict import attrdict, optiondict -from misc import crossproduct, flatten +from attrdict import optiondict +from misc import crossproduct class Data(object): def __init__(self, name, desc, **kwargs): @@ -41,9 +41,29 @@ class Data(object): if not isinstance(obj, Data): raise AttributeError, "can only update from Data object" - for k,v in obj.__dict__.iteritems(): - if not k.startswith('_'): - self.__dict__[k] = v + for key,val in obj.__dict__.iteritems(): + if key.startswith('_') or key in ('name', 'desc'): + continue + + if key not in self.__dict__: + self.__dict__[key] = val + continue + + if not isinstance(val, dict): + if self.__dict__[key] == val: + continue + + raise AttributeError, \ + "%s specified more than once old: %s new: %s" % \ + (key, self.__dict__[key], val) + + d = self.__dict__[key] + for k,v in val.iteritems(): + if k in d: + raise AttributeError, \ + "%s specified more than once in %s" % (k, key) + d[k] = v + if hasattr(self, 'system') and hasattr(obj, 'system'): if self.system != obj.system: raise AttributeError, \ @@ -93,6 +113,14 @@ class Data(object): result[key] = self[key] return result + def __repr__(self): + d = {} + for key,value in self.__dict__.iteritems(): + if not key.startswith('_'): + d[key] = value + + return "<%s: %s>" % (type(self).__name__, d) + def __str__(self): return self.name @@ -391,18 +419,12 @@ def JobFile(jobfile): execfile(filename, data) if 'conf' not in data: raise ImportError, 'cannot import name conf from %s' % jobfile - conf = data['conf'] - import jobfile - if not isinstance(conf, Configuration): - raise AttributeError, \ - 'conf in jobfile: %s (%s) is not type %s' % \ - (jobfile, type(conf), Configuration) - return conf + return data['conf'] def main(conf=None): - import sys - - usage = 'Usage: %s [-b] [-c] [-v] ' % sys.argv[0] + usage = 'Usage: %s [-b] [-c] [-v]' % sys.argv[0] + if conf is None: + usage += ' ' try: import getopt -- cgit v1.2.3 From b25e56b32a3af5d11680b465f6443c73156ddf86 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 10 Oct 2008 10:15:01 -0700 Subject: gdb: add a debugging function that enters the python interpreter. --- src/sim/debug.cc | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src') diff --git a/src/sim/debug.cc b/src/sim/debug.cc index 3684f6767..57ca0458c 100644 --- a/src/sim/debug.cc +++ b/src/sim/debug.cc @@ -29,6 +29,7 @@ * Steve Reinhardt */ +#include #include #include #include @@ -106,6 +107,21 @@ eventqDump() warn("need to dump all queues"); } +void +py_interact() +{ + PyObject *globals; + PyObject *locals; + + globals = PyEval_GetGlobals(); + Py_INCREF(globals); + locals = PyDict_New(); + PyRun_String("import code", Py_file_input, globals, locals); + PyRun_String("code.interact(local=globals())", Py_file_input, + globals, locals); + Py_DECREF(globals); + Py_DECREF(locals); +} int remote_gdb_base_port = 7000; -- cgit v1.2.3 From afb279b1bb8f7c01a74c4fe783ce14365916e920 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 10 Oct 2008 10:18:28 -0700 Subject: output: Make panic/fatal/warn more flexible so we can add some new ones. The major thrust of this change is to limit the amount of code duplication surrounding the code for these functions. This code also adds two new message types called info and hack. Info is meant to be less harsh than warn so people don't get confused and start thinking that the simulator is broken. Hack is a way for people to add runtime messages indicating that the simulator just executed a code "hack" that should probably be fixed. The benefit of knowing about these code hacks is that it will let people know what sorts of inaccuracies or potential bugs might be entering their experiments. Finally, I've added some flags to turn on and off these message types so command line options can change them. --- src/base/misc.cc | 79 ++++++++++++----------------- src/base/misc.hh | 132 +++++++++++++++++++++++++++++++------------------ src/python/swig/core.i | 5 ++ src/sim/simulate.cc | 2 +- 4 files changed, 121 insertions(+), 97 deletions(-) (limited to 'src') diff --git a/src/base/misc.cc b/src/base/misc.cc index 7d284a378..b0c769ac6 100644 --- a/src/base/misc.cc +++ b/src/base/misc.cc @@ -43,42 +43,24 @@ using namespace std; -void -__panic(const char *func, const char *file, int line, const char *fmt, - CPRINTF_DEFINITION) -{ - string format = "panic: "; - format += fmt; - switch (format[format.size() - 1]) { - case '\n': - case '\r': - break; - default: - format += "\n"; - } +bool want_warn = true; +bool want_info = true; +bool want_hack = true; - format += " @ cycle %d\n[%s:%s, line %d]\n"; - - CPrintfArgsList args(VARARGS_ALLARGS); - - args.push_back(curTick); - args.push_back(func); - args.push_back(file); - args.push_back(line); - - ccprintf(cerr, format.c_str(), args); - - abort(); -} +bool warn_verbose = false; +bool info_verbose = false; +bool hack_verbose = false; void -__fatal(const char *func, const char *file, int line, const char *fmt, - CPRINTF_DEFINITION) +__exit_message(const char *prefix, int code, + const char *func, const char *file, int line, + const char *fmt, CPRINTF_DEFINITION) { CPrintfArgsList args(VARARGS_ALLARGS); - string format = "fatal: "; - format += fmt; + string format = prefix; + format += ": "; + format += fmt; switch (format[format.size() - 1]) { case '\n': case '\r': @@ -98,16 +80,22 @@ __fatal(const char *func, const char *file, int line, const char *fmt, ccprintf(cerr, format.c_str(), args); - exit(1); + if (code < 0) + abort(); + else + exit(code); } void -__warn(const char *func, const char *file, int line, const char *fmt, - CPRINTF_DEFINITION) +__base_message(std::ostream &stream, const char *prefix, bool verbose, + const char *func, const char *file, int line, + const char *fmt, CPRINTF_DEFINITION) { - string format = "warn: "; - format += fmt; + CPrintfArgsList args(VARARGS_ALLARGS); + string format = prefix; + format += ": "; + format += fmt; switch (format[format.size() - 1]) { case '\n': case '\r': @@ -116,18 +104,13 @@ __warn(const char *func, const char *file, int line, const char *fmt, format += "\n"; } -#ifdef VERBOSE_WARN - format += " @ cycle %d\n[%s:%s, line %d]\n"; -#endif - - CPrintfArgsList args(VARARGS_ALLARGS); - -#ifdef VERBOSE_WARN - args.push_back(curTick); - args.push_back(func); - args.push_back(file); - args.push_back(line); -#endif + if (verbose) { + format += " @ cycle %d\n[%s:%s, line %d]\n"; + args.push_back(curTick); + args.push_back(func); + args.push_back(file); + args.push_back(line); + } - ccprintf(cerr, format.c_str(), args); + ccprintf(stream, format.c_str(), args); } diff --git a/src/base/misc.hh b/src/base/misc.hh index 8d38fa731..5bb4e0e77 100644 --- a/src/base/misc.hh +++ b/src/base/misc.hh @@ -40,6 +40,30 @@ #define __FUNCTION__ "how to fix me?" #endif +// General exit message, these functions will never return and will +// either abort() if code is < 0 or exit with the code if >= 0 +void __exit_message(const char *prefix, int code, + const char *func, const char *file, int line, + const char *format, CPRINTF_DECLARATION) M5_ATTR_NORETURN; + +void __exit_message(const char *prefix, int code, + const char *func, const char *file, int line, + const std::string &format, CPRINTF_DECLARATION) M5_ATTR_NORETURN; + +inline void +__exit_message(const char *prefix, int code, + const char *func, const char *file, int line, + const std::string& format, CPRINTF_DEFINITION) +{ + __exit_message(prefix, code, func, file, line, format.c_str(), + VARARGS_ALLARGS); +} + +M5_PRAGMA_NORETURN(__exit_message) +#define exit_message(prefix, code, ...) \ + __exit_message(prefix, code, __FUNCTION__, __FILE__, __LINE__, \ + __VA_ARGS__) + // // This implements a cprintf based panic() function. panic() should // be called when something happens that should never ever happen @@ -47,20 +71,7 @@ // calls abort which can dump core or enter the debugger. // // -void __panic(const char *func, const char *file, int line, const char *format, - CPRINTF_DECLARATION) M5_ATTR_NORETURN; -void __panic(const char *func, const char *file, int line, - const std::string &format, CPRINTF_DECLARATION) -M5_ATTR_NORETURN; - -inline void -__panic(const char *func, const char *file, int line, - const std::string &format, CPRINTF_DEFINITION) -{ - __panic(func, file, line, format.c_str(), VARARGS_ALLARGS); -} -M5_PRAGMA_NORETURN(__panic) -#define panic(...) __panic(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__) +#define panic(...) exit_message("panic", -1, __VA_ARGS__) // // This implements a cprintf based fatal() function. fatal() should @@ -70,45 +81,70 @@ M5_PRAGMA_NORETURN(__panic) // "normal" exit with an error code, as opposed to abort() like // panic() does. // -void __fatal(const char *func, const char *file, int line, const char *format, - CPRINTF_DECLARATION) M5_ATTR_NORETURN; -void __fatal(const char *func, const char *file, int line, - const std::string &format, CPRINTF_DECLARATION) - M5_ATTR_NORETURN; +#define fatal(...) exit_message("fatal", 1, __VA_ARGS__) -inline void -__fatal(const char *func, const char *file, int line, - const std::string &format, CPRINTF_DEFINITION) -{ - __fatal(func, file, line, format.c_str(), VARARGS_ALLARGS); -} -M5_PRAGMA_NORETURN(__fatal) -#define fatal(...) __fatal(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__) +void +__base_message(std::ostream &stream, const char *prefix, bool verbose, + const char *func, const char *file, int line, + const char *format, CPRINTF_DECLARATION); -// -// This implements a cprintf based warn -// -void __warn(const char *func, const char *file, int line, const char *format, - CPRINTF_DECLARATION); inline void -__warn(const char *func, const char *file, int line, const std::string &format, - CPRINTF_DECLARATION) +__base_message(std::ostream &stream, const char *prefix, bool verbose, + const char *func, const char *file, int line, + const std::string &format, CPRINTF_DECLARATION) { - __warn(func, file, line, format, VARARGS_ALLARGS); + __base_message(stream, prefix, verbose, func, file, line, format.c_str(), + VARARGS_ALLARGS); } -#define warn(...) __warn(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__) - -// Only print the warning message the first time it is seen. This -// doesn't check the warning string itself, it just only lets one -// warning come from the statement. So, even if the arguments change -// and that would have resulted in a different warning message, -// subsequent messages would still be supressed. -#define warn_once(...) do { \ - static bool once = false; \ - if (!once) { \ - warn(__VA_ARGS__); \ - once = true; \ - } \ + +#define base_message(stream, prefix, verbose, ...) \ + __base_message(stream, prefix, verbose, __FUNCTION__, __FILE__, __LINE__, \ + __VA_ARGS__) + +// Only print the message the first time this expression is +// encountered. i.e. This doesn't check the string itself and +// prevent duplicate strings, this prevents the statement from +// happening more than once. So, even if the arguments change and that +// would have resulted in a different message thoes messages would be +// supressed. +#define base_message_once(...) do { \ + static bool once = false; \ + if (!once) { \ + base_message(__VA_ARGS__); \ + once = true; \ + } \ + } while (0) + +#define cond_message(cond, ...) do { \ + if (cond) \ + base_message(__VA_ARGS__); \ } while (0) +#define cond_message_once(cond, ...) do { \ + static bool once = false; \ + if (!once && cond) { \ + base_message(__VA_ARGS__); \ + once = true; \ + } \ + } while (0) + + +extern bool want_warn, warn_verbose; +extern bool want_info, info_verbose; +extern bool want_hack, hack_verbose; + +#define warn(...) \ + cond_message(want_warn, std::cerr, "warn", warn_verbose, __VA_ARGS__) +#define info(...) \ + cond_message(want_info, std::cout, "info", info_verbose, __VA_ARGS__) +#define hack(...) \ + cond_message(want_hack, std::cerr, "hack", hack_verbose, __VA_ARGS__) + +#define warn_once(...) \ + cond_message_once(want_warn, std::cerr, "warn", warn_verbose, __VA_ARGS__) +#define info_once(...) \ + cond_message_once(want_info, std::cout, "info", info_verbose, __VA_ARGS__) +#define hack_once(...) \ + cond_message_once(want_hack, std::cerr, "hack", hack_verbose, __VA_ARGS__) + #endif // __BASE_MISC_HH__ diff --git a/src/python/swig/core.i b/src/python/swig/core.i index b0773ca68..566998639 100644 --- a/src/python/swig/core.i +++ b/src/python/swig/core.i @@ -34,6 +34,7 @@ %{ #include "python/swig/pyobject.hh" +#include "base/misc.hh" #include "base/socket.hh" #include "sim/core.hh" #include "sim/host.hh" @@ -76,6 +77,10 @@ void unserializeAll(const std::string &cpt_dir); void initAll(); void regAllStats(); +bool want_warn, warn_verbose; +bool want_info, info_verbose; +bool want_hack, hack_verbose; + %wrapper %{ // fix up module name to reflect the fact that it's inside the m5 package #undef SWIG_name diff --git a/src/sim/simulate.cc b/src/sim/simulate.cc index 59d79b7c6..7f40805e6 100644 --- a/src/sim/simulate.cc +++ b/src/sim/simulate.cc @@ -47,7 +47,7 @@ SimLoopExitEvent * simulate(Tick num_cycles) { - warn("Entering event queue @ %d. Starting simulation...\n", curTick); + info("Entering event queue @ %d. Starting simulation...\n", curTick); if (num_cycles < 0) fatal("simulate: num_cycles must be >= 0 (was %d)\n", num_cycles); -- cgit v1.2.3 From 96936c6bf57b40c6da2582ad6dd1bdd0de2ea3db Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 10 Oct 2008 12:17:53 -0700 Subject: Rename the info function to inform to avoid likely name conflicts --- src/base/misc.hh | 4 ++-- src/sim/simulate.cc | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/base/misc.hh b/src/base/misc.hh index 5bb4e0e77..25dcbaa62 100644 --- a/src/base/misc.hh +++ b/src/base/misc.hh @@ -135,14 +135,14 @@ extern bool want_hack, hack_verbose; #define warn(...) \ cond_message(want_warn, std::cerr, "warn", warn_verbose, __VA_ARGS__) -#define info(...) \ +#define inform(...) \ cond_message(want_info, std::cout, "info", info_verbose, __VA_ARGS__) #define hack(...) \ cond_message(want_hack, std::cerr, "hack", hack_verbose, __VA_ARGS__) #define warn_once(...) \ cond_message_once(want_warn, std::cerr, "warn", warn_verbose, __VA_ARGS__) -#define info_once(...) \ +#define inform_once(...) \ cond_message_once(want_info, std::cout, "info", info_verbose, __VA_ARGS__) #define hack_once(...) \ cond_message_once(want_hack, std::cerr, "hack", hack_verbose, __VA_ARGS__) diff --git a/src/sim/simulate.cc b/src/sim/simulate.cc index 7f40805e6..9af873f90 100644 --- a/src/sim/simulate.cc +++ b/src/sim/simulate.cc @@ -47,7 +47,7 @@ SimLoopExitEvent * simulate(Tick num_cycles) { - info("Entering event queue @ %d. Starting simulation...\n", curTick); + inform("Entering event queue @ %d. Starting simulation...\n", curTick); if (num_cycles < 0) fatal("simulate: num_cycles must be >= 0 (was %d)\n", num_cycles); -- cgit v1.2.3 From 1f57193439925d2098052d0648031dc04b1ad440 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 10 Oct 2008 21:45:34 -0700 Subject: swig: Add in a %rename to allow the same name to appear in multiple namespaces. --- src/SConscript | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/SConscript b/src/SConscript index be721d57e..2ea35b778 100644 --- a/src/SConscript +++ b/src/SConscript @@ -532,11 +532,18 @@ def buildParams(target, source, env): continue class_path = obj.cxx_class.split('::') - class_path.reverse() - classname = class_path[0] - namespaces = class_path[1:] + classname = class_path[-1] + namespaces = class_path[:-1] + namespaces.reverse() code = '' + + if namespaces: + code += '// avoid name conflicts\n' + sep_string = '_COLONS_' + flat_name = sep_string.join(class_path) + code += '%%rename(%s) %s;\n' % (flat_name, classname) + code += '// stop swig from creating/wrapping default ctor/dtor\n' code += '%%nodefault %s;\n' % classname code += 'class %s ' % classname -- cgit v1.2.3 From 89f016aacbe92f90c1af98678043f2f6fc82c364 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 10 Oct 2008 21:45:35 -0700 Subject: cprintf: properly deal with pointer types --- src/base/varargs.hh | 16 ++++++++++++++++ src/unittest/cprintftest.cc | 9 +++++++++ 2 files changed, 25 insertions(+) (limited to 'src') diff --git a/src/base/varargs.hh b/src/base/varargs.hh index f307e58d1..4328f2057 100644 --- a/src/base/varargs.hh +++ b/src/base/varargs.hh @@ -147,6 +147,20 @@ struct Any : public Base } }; +template +struct Any : public Base +{ + const T *argument; + + Any(const T *arg) : argument(arg) {} + + virtual void + add_arg(RECV &receiver) const + { + receiver.add_arg(argument); + } +}; + template struct Argument : public RefCountingPtr > { @@ -156,6 +170,8 @@ struct Argument : public RefCountingPtr > Argument(const Null &null) { } template Argument(const T& arg) : Base(new Any(arg)) { } + template + Argument(const T* arg) : Base(new Any(arg)) { } void add_arg(RECV &receiver) const diff --git a/src/unittest/cprintftest.cc b/src/unittest/cprintftest.cc index 7fb10375c..1438f194b 100644 --- a/src/unittest/cprintftest.cc +++ b/src/unittest/cprintftest.cc @@ -34,6 +34,7 @@ #include #include "base/cprintf.hh" +#include "base/misc.hh" using namespace std; @@ -43,6 +44,14 @@ main() char foo[] = "foo"; cprintf("%s\n", foo); + string _bar = "asdfkhasdlkfjhasdlkfhjalksdjfhalksdjhfalksdjfhalksdjhf"; + int length = 11; + char bar[length + 1]; + bar[length] = 0; + + memcpy(bar, _bar.c_str(), length); + warn("%s\n", bar); + cprintf("%d\n", 'A'); cprintf("%shits%%s + %smisses%%s\n", "test", "test"); cprintf("%%s%-10s %c he went home \'\"%d %#o %#x %1.5f %1.2E\n", -- cgit v1.2.3 From b03c95d075b74913313576e6e1fa4fc6b1f4dcb2 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 10 Oct 2008 23:39:53 -0700 Subject: X86: Create SimObjects in python and C++ to represent the Intel MP tables. --- src/arch/x86/X86System.py | 7 + src/arch/x86/bios/IntelMP.py | 233 +++++++++++++++++++++ src/arch/x86/bios/SConscript | 4 + src/arch/x86/bios/intelmp.cc | 476 +++++++++++++++++++++++++++++++++++++++++++ src/arch/x86/bios/intelmp.hh | 330 ++++++++++++++++++++++++++++++ src/arch/x86/system.cc | 50 ++++- src/arch/x86/system.hh | 10 + 7 files changed, 1104 insertions(+), 6 deletions(-) create mode 100644 src/arch/x86/bios/IntelMP.py create mode 100644 src/arch/x86/bios/intelmp.cc create mode 100644 src/arch/x86/bios/intelmp.hh (limited to 'src') diff --git a/src/arch/x86/X86System.py b/src/arch/x86/X86System.py index 5fe69c709..fc7a5acd0 100644 --- a/src/arch/x86/X86System.py +++ b/src/arch/x86/X86System.py @@ -56,12 +56,19 @@ from m5.params import * from E820 import X86E820Table, X86E820Entry from SMBios import X86SMBiosSMBiosTable +from IntelMP import X86IntelMPFloatingPointer, X86IntelMPConfigTable from System import System class X86System(System): type = 'X86System' smbios_table = Param.X86SMBiosSMBiosTable( X86SMBiosSMBiosTable(), 'table of smbios/dmi information') + intel_mp_pointer = Param.X86IntelMPFloatingPointer( + X86IntelMPFloatingPointer(), + 'intel mp spec floating pointer structure') + intel_mp_table = Param.X86IntelMPConfigTable( + X86IntelMPConfigTable(), + 'intel mp spec configuration table') class LinuxX86System(X86System): type = 'LinuxX86System' diff --git a/src/arch/x86/bios/IntelMP.py b/src/arch/x86/bios/IntelMP.py new file mode 100644 index 000000000..70e7963fa --- /dev/null +++ b/src/arch/x86/bios/IntelMP.py @@ -0,0 +1,233 @@ +# Copyright (c) 2008 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use of this software in source and binary forms, +# with or without modification, are permitted provided that the +# following conditions are met: +# +# The software must be used only for Non-Commercial Use which means any +# use which is NOT directed to receiving any direct monetary +# compensation for, or commercial advantage from such use. Illustrative +# examples of non-commercial use are academic research, personal study, +# teaching, education and corporate research & development. +# Illustrative examples of commercial use are distributing products for +# commercial advantage and providing services using the software for +# commercial advantage. +# +# If you wish to use this software or functionality therein that may be +# covered by patents for commercial use, please contact: +# Director of Intellectual Property Licensing +# Office of Strategy and Technology +# Hewlett-Packard Company +# 1501 Page Mill Road +# Palo Alto, California 94304 +# +# 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. No right of +# sublicense is granted herewith. Derivatives of the software and +# output created using the software may be prepared, but only for +# Non-Commercial Uses. Derivatives of the software may be shared with +# others provided: (i) the others agree to abide by the list of +# conditions herein which includes the Non-Commercial Use restrictions; +# and (ii) such Derivatives of the software include the above copyright +# notice to acknowledge the contribution from this software where +# applicable, this list of conditions and the disclaimer below. +# +# 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: Gabe Black + +from m5.params import * +from m5.SimObject import SimObject + +class X86IntelMPFloatingPointer(SimObject): + type = 'X86IntelMPFloatingPointer' + cxx_class = 'X86ISA::IntelMP::FloatingPointer' + + # The minor revision of the spec to support. The major version is assumed + # to be 1 in accordance with the spec. + spec_rev = Param.UInt8(4, 'minor revision of the MP spec supported') + # If no default configuration is used, set this to 0. + default_config = Param.UInt8(0, 'which default configuration to use') + imcr_present = Param.Bool(True, + 'whether the IMCR register is present in the APIC') + +class X86IntelMPConfigTable(SimObject): + type = 'X86IntelMPConfigTable' + cxx_class = 'X86ISA::IntelMP::ConfigTable' + + spec_rev = Param.UInt8(4, 'minor revision of the MP spec supported') + oem_id = Param.String("", 'system manufacturer') + product_id = Param.String("", 'product family') + oem_table_addr = Param.UInt32(0, + 'pointer to the optional oem configuration table') + oem_table_size = Param.UInt16(0, 'size of the oem configuration table') + local_apic = Param.UInt32(0xFEE00000, 'address of the local APIC') + + base_entries = VectorParam.X86IntelMPBaseConfigEntry([], + 'base configuration table entries') + + ext_entries = VectorParam.X86IntelMPExtConfigEntry([], + 'extended configuration table entries') + +class X86IntelMPBaseConfigEntry(SimObject): + type = 'X86IntelMPBaseConfigEntry' + cxx_class = 'X86ISA::IntelMP::BaseConfigEntry' + abstract = True + +class X86IntelMPExtConfigEntry(SimObject): + type = 'X86IntelMPExtConfigEntry' + cxx_class = 'X86ISA::IntelMP::ExtConfigEntry' + abstract = True + +class X86IntelMPProcessor(X86IntelMPBaseConfigEntry): + type = 'X86IntelMPProcessor' + cxx_class = 'X86ISA::IntelMP::Processor' + + local_apic_id = Param.UInt8(0, 'local APIC id') + local_apic_version = Param.UInt8(0, + 'bits 0-7 of the local APIC version register') + enable = Param.Bool(True, 'if this processor is usable') + bootstrap = Param.Bool(False, 'if this is the bootstrap processor') + + stepping = Param.UInt8(0) + model = Param.UInt8(0) + family = Param.UInt8(0) + + feature_flags = Param.UInt32(0, 'flags returned by the CPUID instruction') + +class X86IntelMPBus(X86IntelMPBaseConfigEntry): + type = 'X86IntelMPBus' + cxx_class = 'X86ISA::IntelMP::Bus' + + bus_id = Param.UInt8(0, 'bus id assigned by the bios') + bus_type = Param.String("", 'string that identify the bus type') + # Legal values for bus_type are: + # + # "CBUS", "CBUSII", "EISA", "FUTURE", "INTERN", "ISA", "MBI", "MBII", + # "MCA", "MPI", "MPSA", "NUBUS", "PCI", "PCMCIA", "TC", "VL", "VME", + # "XPRESS" + +class X86IntelMPIOAPIC(X86IntelMPBaseConfigEntry): + type = 'X86IntelMPIOAPIC' + cxx_class = 'X86ISA::IntelMP::IOAPIC' + + id = Param.UInt8(0, 'id of this APIC') + version = Param.UInt8(0, 'bits 0-7 of the version register') + + enable = Param.Bool(True, 'if this APIC is usable') + + address = Param.UInt32(0xfec00000, 'address of this APIC') + +class X86IntelMPInterruptType(Enum): + map = {'INT' : 0, + 'NMI' : 1, + 'SMI' : 2, + 'ExtInt' : 3 + } + +class X86IntelMPPolarity(Enum): + map = {'ConformPolarity' : 0, + 'ActiveHigh' : 1, + 'ActiveLow' : 3 + } + +class X86IntelMPTriggerMode(Enum): + map = {'ConformTrigger' : 0, + 'EdgeTrigger' : 1, + 'LevelTrigger' : 3 + } + +class X86IntelMPIOIntAssignment(X86IntelMPBaseConfigEntry): + type = 'X86IntelMPIOIntAssignment' + cxx_class = 'X86ISA::IntelMP::IOIntAssignment' + + interrupt_type = Param.X86IntelMPInterruptType('INT', 'type of interrupt') + + polarity = Param.X86IntelMPPolarity('ConformPolarity', 'polarity') + trigger = Param.X86IntelMPTriggerMode('ConformTrigger', 'trigger mode') + + source_bus_id = Param.UInt8(0, + 'id of the bus from which the interrupt signal comes') + source_bus_irq = Param.UInt8(0, + 'which interrupt signal from the source bus') + + dest_io_apic_id = Param.UInt8(0, + 'id of the IO APIC the interrupt is going to') + dest_io_apic_intin = Param.UInt8(0, + 'the INTIN pin on the IO APIC the interrupt is connected to') + +class X86IntelMPLocalIntAssignment(X86IntelMPBaseConfigEntry): + type = 'X86IntelMPLocalIntAssignment' + cxx_class = 'X86ISA::IntelMP::LocalIntAssignment' + + interrupt_type = Param.X86IntelMPInterruptType('INT', 'type of interrupt') + + polarity = Param.X86IntelMPPolarity('ConformPolarity', 'polarity') + trigger = Param.X86IntelMPTriggerMode('ConformTrigger', 'trigger mode') + + source_bus_id = Param.UInt8(0, + 'id of the bus from which the interrupt signal comes') + source_bus_irq = Param.UInt8(0, + 'which interrupt signal from the source bus') + + dest_local_apic_id = Param.UInt8(0, + 'id of the local APIC the interrupt is going to') + dest_local_apic_intin = Param.UInt8(0, + 'the INTIN pin on the local APIC the interrupt is connected to') + +class X86IntelMPAddressType(Enum): + map = {"IOAddress" : 0, + "MemoryAddress" : 1, + "PrefetchAddress" : 2 + } + +class X86IntelMPAddrSpaceMapping(X86IntelMPExtConfigEntry): + type = 'X86IntelMPAddrSpaceMapping' + cxx_class = 'X86ISA::IntelMP::AddrSpaceMapping' + + bus_id = Param.UInt8(0, 'id of the bus the address space is mapped to') + address_type = Param.X86IntelMPAddressType('IOAddress', + 'address type used to access bus') + address = Param.Addr(0, 'starting address of the mapping') + length = Param.UInt64(0, 'length of mapping in bytes') + +class X86IntelMPBusHierarchy(X86IntelMPExtConfigEntry): + type = 'X86IntelMPBusHierarchy' + cxx_class = 'X86ISA::IntelMP::BusHierarchy' + + bus_id = Param.UInt8(0, 'id of the bus being described') + subtractive_decode = Param.Bool(False, + 'whether this bus contains all addresses not used by its children') + parent_bus = Param.UInt8(0, 'bus id of this busses parent') + +class X86IntelMPRangeList(Enum): + map = {"ISACompatible" : 0, + "VGACompatible" : 1 + } + +class X86IntelMPCompatAddrSpaceMod(X86IntelMPExtConfigEntry): + type = 'X86IntelMPCompatAddrSpaceMod' + cxx_class = 'X86ISA::IntelMP::CompatAddrSpaceMod' + + bus_id = Param.UInt8(0, 'id of the bus being described') + add = Param.Bool(False, + 'if the range should be added to the original mapping') + range_list = Param.X86IntelMPRangeList('ISACompatible', + 'which predefined range of addresses to use') diff --git a/src/arch/x86/bios/SConscript b/src/arch/x86/bios/SConscript index cdb5f390f..c4f4f80e6 100644 --- a/src/arch/x86/bios/SConscript +++ b/src/arch/x86/bios/SConscript @@ -67,3 +67,7 @@ if env['TARGET_ISA'] == 'x86': # The DMI tables. SimObject('SMBios.py') Source('smbios.cc') + + # Intel Multiprocessor Specification Configuration Table + SimObject('IntelMP.py') + Source('intelmp.cc') diff --git a/src/arch/x86/bios/intelmp.cc b/src/arch/x86/bios/intelmp.cc new file mode 100644 index 000000000..2332e7a5c --- /dev/null +++ b/src/arch/x86/bios/intelmp.cc @@ -0,0 +1,476 @@ +/* + * Copyright (c) 2008 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * 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: Gabe Black + */ + +#include "arch/x86/bios/intelmp.hh" +#include "arch/x86/isa_traits.hh" +#include "base/misc.hh" +#include "mem/port.hh" +#include "sim/byteswap.hh" +#include "sim/host.hh" + +// Config entry types +#include "params/X86IntelMPBaseConfigEntry.hh" +#include "params/X86IntelMPExtConfigEntry.hh" + +// General table structures +#include "params/X86IntelMPConfigTable.hh" +#include "params/X86IntelMPFloatingPointer.hh" + +// Base entry types +#include "params/X86IntelMPBus.hh" +#include "params/X86IntelMPIOAPIC.hh" +#include "params/X86IntelMPIOIntAssignment.hh" +#include "params/X86IntelMPLocalIntAssignment.hh" +#include "params/X86IntelMPProcessor.hh" + +// Extended entry types +#include "params/X86IntelMPAddrSpaceMapping.hh" +#include "params/X86IntelMPBusHierarchy.hh" +#include "params/X86IntelMPCompatAddrSpaceMod.hh" + +using namespace std; + +const char X86ISA::IntelMP::FloatingPointer::signature[] = "_MP_"; + +template +uint8_t +writeOutField(FunctionalPort * port, Addr addr, T val) +{ + T guestVal = X86ISA::htog(val); + port->writeBlob(addr, (uint8_t *)(&guestVal), sizeof(T)); + + uint8_t checkSum = 0; + while(guestVal) { + checkSum += guestVal; + guestVal >>= 8; + } + return checkSum; +} + +uint8_t +writeOutString(FunctionalPort * port, Addr addr, string str, int length) +{ + char cleanedString[length + 1]; + cleanedString[length] = 0; + + if (str.length() > length) { + memcpy(cleanedString, str.c_str(), length); + warn("Intel MP configuration table string \"%s\" " + "will be truncated to \"%s\".\n", str, cleanedString); + } else { + memcpy(cleanedString, str.c_str(), str.length()); + memset(cleanedString + str.length(), 0, length - str.length()); + } + port->writeBlob(addr, (uint8_t *)(&cleanedString), length); + + uint8_t checkSum = 0; + for (int i = 0; i < length; i++) + checkSum += cleanedString[i]; + + return checkSum; +} + +Addr +X86ISA::IntelMP::FloatingPointer::writeOut(FunctionalPort * port, Addr addr) +{ + // Make sure that either a config table is present or a default + // configuration was found but not both. + if (!tableAddr && !defaultConfig) + fatal("Either an MP configuration table or a default configuration " + "must be used."); + if (tableAddr && defaultConfig) + fatal("Both an MP configuration table and a default configuration " + "were set."); + + uint8_t checkSum = 0; + + port->writeBlob(addr, (uint8_t *)signature, 4); + for (int i = 0; i < 4; i++) + checkSum += signature[i]; + + checkSum += writeOutField(port, addr + 4, tableAddr); + + // The length of the structure in paragraphs, aka 16 byte chunks. + uint8_t length = 1; + port->writeBlob(addr + 8, &length, 1); + checkSum += length; + + port->writeBlob(addr + 9, &specRev, 1); + checkSum += specRev; + + port->writeBlob(addr + 11, &defaultConfig, 1); + checkSum += defaultConfig; + + uint32_t features2_5 = imcrPresent ? (1 << 7) : 0; + checkSum += writeOutField(port, addr + 12, features2_5); + + checkSum = -checkSum; + port->writeBlob(addr + 10, &checkSum, 1); + + return 16; +} + +X86ISA::IntelMP::FloatingPointer::FloatingPointer(Params * p) : + SimObject(p), tableAddr(0), specRev(p->spec_rev), + defaultConfig(p->default_config), imcrPresent(p->imcr_present) +{} + +X86ISA::IntelMP::FloatingPointer * +X86IntelMPFloatingPointerParams::create() +{ + return new X86ISA::IntelMP::FloatingPointer(this); +} + +Addr +X86ISA::IntelMP::BaseConfigEntry::writeOut(FunctionalPort * port, + Addr addr, uint8_t &checkSum) +{ + port->writeBlob(addr, &type, 1); + checkSum += type; + return 1; +} + +X86ISA::IntelMP::BaseConfigEntry::BaseConfigEntry(Params * p, uint8_t _type) : + SimObject(p), type(_type) +{} + +Addr +X86ISA::IntelMP::ExtConfigEntry::writeOut(FunctionalPort * port, + Addr addr, uint8_t &checkSum) +{ + port->writeBlob(addr, &type, 1); + checkSum += type; + port->writeBlob(addr + 1, &length, 1); + checkSum += length; + return 1; +} + +X86ISA::IntelMP::ExtConfigEntry::ExtConfigEntry(Params * p, + uint8_t _type, uint8_t _length) : + SimObject(p), type(_type), length(_length) +{} + +const char X86ISA::IntelMP::ConfigTable::signature[] = "PCMP"; + +Addr +X86ISA::IntelMP::ConfigTable::writeOut(FunctionalPort * port, Addr addr) +{ + uint8_t checkSum = 0; + + port->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); + 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 += 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); + + uint8_t reserved = 0; + port->writeBlob(addr + 43, &reserved, 1); + checkSum += reserved; + + vector::iterator baseEnt; + uint16_t offset = 44; + for (baseEnt = baseEntries.begin(); + baseEnt != baseEntries.end(); baseEnt++) { + offset += (*baseEnt)->writeOut(port, addr + offset, checkSum); + } + + // We've found the end of the base table this point. + checkSum += writeOutField(port, addr + 4, offset); + + vector::iterator extEnt; + uint16_t extOffset = 0; + uint8_t extCheckSum = 0; + for (extEnt = extEntries.begin(); + extEnt != extEntries.end(); extEnt++) { + extOffset += (*extEnt)->writeOut(port, + addr + offset + extOffset, extCheckSum); + } + + checkSum += writeOutField(port, addr + 40, extOffset); + extCheckSum = -extCheckSum; + checkSum += writeOutField(port, addr + 42, extCheckSum); + + // And now, we finally have the whole check sum completed. + checkSum = -checkSum; + writeOutField(port, addr + 7, checkSum); + + return offset + extOffset; +}; + +X86ISA::IntelMP::ConfigTable::ConfigTable(Params * p) : SimObject(p), + specRev(p->spec_rev), oemID(p->oem_id), productID(p->product_id), + oemTableAddr(p->oem_table_addr), oemTableSize(p->oem_table_size), + localApic(p->local_apic), + baseEntries(p->base_entries), extEntries(p->ext_entries) +{} + +X86ISA::IntelMP::ConfigTable * +X86IntelMPConfigTableParams::create() +{ + return new X86ISA::IntelMP::ConfigTable(this); +} + +Addr +X86ISA::IntelMP::Processor::writeOut( + FunctionalPort * port, 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); + + uint32_t reserved = 0; + port->writeBlob(addr + 12, (uint8_t *)(&reserved), 4); + port->writeBlob(addr + 16, (uint8_t *)(&reserved), 4); + return 20; +} + +X86ISA::IntelMP::Processor::Processor(Params * p) : BaseConfigEntry(p, 0), + localApicID(p->local_apic_id), localApicVersion(p->local_apic_version), + cpuFlags(0), cpuSignature(0), featureFlags(p->feature_flags) +{ + if (p->enable) + cpuFlags |= (1 << 0); + if (p->bootstrap) + cpuFlags |= (1 << 1); + + replaceBits(cpuSignature, 0, 3, p->stepping); + replaceBits(cpuSignature, 4, 7, p->model); + replaceBits(cpuSignature, 8, 11, p->family); +} + +X86ISA::IntelMP::Processor * +X86IntelMPProcessorParams::create() +{ + return new X86ISA::IntelMP::Processor(this); +} + +Addr +X86ISA::IntelMP::Bus::writeOut( + FunctionalPort * port, Addr addr, uint8_t &checkSum) +{ + BaseConfigEntry::writeOut(port, addr, checkSum); + checkSum += writeOutField(port, addr + 1, busID); + checkSum += writeOutString(port, addr + 2, busType, 6); + return 8; +} + +X86ISA::IntelMP::Bus::Bus(Params * p) : BaseConfigEntry(p, 1), + busID(p->bus_id), busType(p->bus_type) +{} + +X86ISA::IntelMP::Bus * +X86IntelMPBusParams::create() +{ + return new X86ISA::IntelMP::Bus(this); +} + +Addr +X86ISA::IntelMP::IOAPIC::writeOut( + FunctionalPort * port, 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); + return 8; +} + +X86ISA::IntelMP::IOAPIC::IOAPIC(Params * p) : BaseConfigEntry(p, 2), + id(p->id), version(p->version), flags(0), address(p->address) +{ + if (p->enable) + flags |= 1; +} + +X86ISA::IntelMP::IOAPIC * +X86IntelMPIOAPICParams::create() +{ + return new X86ISA::IntelMP::IOAPIC(this); +} + +Addr +X86ISA::IntelMP::IntAssignment::writeOut( + FunctionalPort * port, 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); + return 8; +} + +X86ISA::IntelMP::IOIntAssignment::IOIntAssignment(Params * p) : + IntAssignment(p, p->interrupt_type, p->polarity, p->trigger, 3, + p->source_bus_id, p->source_bus_irq, + p->dest_io_apic_id, p->dest_io_apic_intin) +{} + +X86ISA::IntelMP::IOIntAssignment * +X86IntelMPIOIntAssignmentParams::create() +{ + return new X86ISA::IntelMP::IOIntAssignment(this); +} + +X86ISA::IntelMP::LocalIntAssignment::LocalIntAssignment(Params * p) : + IntAssignment(p, p->interrupt_type, p->polarity, p->trigger, 4, + p->source_bus_id, p->source_bus_irq, + p->dest_local_apic_id, p->dest_local_apic_intin) +{} + +X86ISA::IntelMP::LocalIntAssignment * +X86IntelMPLocalIntAssignmentParams::create() +{ + return new X86ISA::IntelMP::LocalIntAssignment(this); +} + +Addr +X86ISA::IntelMP::AddrSpaceMapping::writeOut( + FunctionalPort * port, 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); + return length; +} + +X86ISA::IntelMP::AddrSpaceMapping::AddrSpaceMapping(Params * p) : + ExtConfigEntry(p, 128, 20), + busID(p->bus_id), addrType(p->address_type), + addr(p->address), addrLength(p->length) +{} + +X86ISA::IntelMP::AddrSpaceMapping * +X86IntelMPAddrSpaceMappingParams::create() +{ + return new X86ISA::IntelMP::AddrSpaceMapping(this); +} + +Addr +X86ISA::IntelMP::BusHierarchy::writeOut( + FunctionalPort * port, 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); + + uint32_t reserved = 0; + port->writeBlob(addr + 5, (uint8_t *)(&reserved), 3); + + return length; +} + +X86ISA::IntelMP::BusHierarchy::BusHierarchy(Params * p) : + ExtConfigEntry(p, 129, 8), + busID(p->bus_id), info(0), parentBus(p->parent_bus) +{ + if (p->subtractive_decode) + info |= 1; +} + +X86ISA::IntelMP::BusHierarchy * +X86IntelMPBusHierarchyParams::create() +{ + return new X86ISA::IntelMP::BusHierarchy(this); +} + +Addr +X86ISA::IntelMP::CompatAddrSpaceMod::writeOut( + FunctionalPort * port, 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); + return length; +} + +X86ISA::IntelMP::CompatAddrSpaceMod::CompatAddrSpaceMod(Params * p) : + ExtConfigEntry(p, 130, 8), + busID(p->bus_id), mod(0), rangeList(p->range_list) +{ + if (p->add) + mod |= 1; +} + +X86ISA::IntelMP::CompatAddrSpaceMod * +X86IntelMPCompatAddrSpaceModParams::create() +{ + return new X86ISA::IntelMP::CompatAddrSpaceMod(this); +} diff --git a/src/arch/x86/bios/intelmp.hh b/src/arch/x86/bios/intelmp.hh new file mode 100644 index 000000000..e8d1d656e --- /dev/null +++ b/src/arch/x86/bios/intelmp.hh @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2008 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * 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: Gabe Black + */ + +#ifndef __ARCH_X86_BIOS_INTELMP_HH__ +#define __ARCH_X86_BIOS_INTELMP_HH__ + +#include +#include + +#include "base/bitfield.hh" +#include "sim/sim_object.hh" + +#include "enums/X86IntelMPAddressType.hh" +#include "enums/X86IntelMPInterruptType.hh" +#include "enums/X86IntelMPPolarity.hh" +#include "enums/X86IntelMPRangeList.hh" +#include "enums/X86IntelMPTriggerMode.hh" + +class FunctionalPort; + +// Config entry types +class X86IntelMPBaseConfigEntryParams; +class X86IntelMPExtConfigEntryParams; + +// General table structures +class X86IntelMPConfigTableParams; +class X86IntelMPFloatingPointerParams; + +// Base entry types +class X86IntelMPBusParams; +class X86IntelMPIOAPICParams; +class X86IntelMPIOIntAssignmentParams; +class X86IntelMPLocalIntAssignmentParams; +class X86IntelMPProcessorParams; + +// Extended entry types +class X86IntelMPAddrSpaceMappingParams; +class X86IntelMPBusHierarchyParams; +class X86IntelMPCompatAddrSpaceModParams; + +namespace X86ISA +{ + +namespace IntelMP +{ + +class FloatingPointer : public SimObject +{ + protected: + typedef X86IntelMPFloatingPointerParams Params; + + uint32_t tableAddr; + uint8_t specRev; + uint8_t defaultConfig; + bool imcrPresent; + + static const char signature[]; + + public: + + Addr writeOut(FunctionalPort * port, Addr addr); + + Addr getTableAddr() + { + return tableAddr; + } + + void setTableAddr(Addr addr) + { + tableAddr = addr; + } + + FloatingPointer(Params * p); +}; + +class BaseConfigEntry : public SimObject +{ + protected: + typedef X86IntelMPBaseConfigEntryParams Params; + + uint8_t type; + + public: + + virtual Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum); + + BaseConfigEntry(Params * p, uint8_t _type); +}; + +class ExtConfigEntry : public SimObject +{ + protected: + typedef X86IntelMPExtConfigEntryParams Params; + + uint8_t type; + uint8_t length; + + public: + + virtual Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum); + + ExtConfigEntry(Params * p, uint8_t _type, uint8_t _length); +}; + +class ConfigTable : public SimObject +{ + protected: + typedef X86IntelMPConfigTableParams Params; + + static const char signature[]; + + uint8_t specRev; + std::string oemID; + std::string productID; + uint32_t oemTableAddr; + uint16_t oemTableSize; + uint32_t localApic; + + std::vector baseEntries; + std::vector extEntries; + + public: + Addr writeOut(FunctionalPort * port, Addr addr); + + ConfigTable(Params * p); +}; + +class Processor : public BaseConfigEntry +{ + protected: + typedef X86IntelMPProcessorParams Params; + + uint8_t localApicID; + uint8_t localApicVersion; + uint8_t cpuFlags; + uint32_t cpuSignature; + uint32_t featureFlags; + + public: + Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum); + + Processor(Params * p); +}; + +class Bus : public BaseConfigEntry +{ + protected: + typedef X86IntelMPBusParams Params; + + uint8_t busID; + std::string busType; + + public: + Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum); + + Bus(Params * p); +}; + +class IOAPIC : public BaseConfigEntry +{ + protected: + typedef X86IntelMPIOAPICParams Params; + + uint8_t id; + uint8_t version; + uint8_t flags; + uint32_t address; + + public: + Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum); + + IOAPIC(Params * p); +}; + +class IntAssignment : public BaseConfigEntry +{ + protected: + uint8_t interruptType; + + uint16_t flags; + + uint8_t sourceBusID; + uint8_t sourceBusIRQ; + + uint8_t destApicID; + uint8_t destApicIntIn; + + public: + Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum); + + IntAssignment(X86IntelMPBaseConfigEntryParams * p, + Enums::X86IntelMPInterruptType _interruptType, + Enums::X86IntelMPPolarity polarity, + Enums::X86IntelMPTriggerMode trigger, + uint8_t _type, + uint8_t _sourceBusID, uint8_t _sourceBusIRQ, + uint8_t _destApicID, uint8_t _destApicIntIn) : + BaseConfigEntry(p, _type), + interruptType(_interruptType), flags(0), + sourceBusID(_sourceBusID), sourceBusIRQ(_sourceBusIRQ), + destApicID(_destApicID), destApicIntIn(_destApicIntIn) + { + replaceBits(flags, 0, 1, polarity); + replaceBits(flags, 2, 3, trigger); + } +}; + +class IOIntAssignment : public IntAssignment +{ + protected: + typedef X86IntelMPIOIntAssignmentParams Params; + + public: + IOIntAssignment(Params * p); +}; + +class LocalIntAssignment : public IntAssignment +{ + protected: + typedef X86IntelMPLocalIntAssignmentParams Params; + + public: + LocalIntAssignment(Params * p); +}; + +class AddrSpaceMapping : public ExtConfigEntry +{ + protected: + typedef X86IntelMPAddrSpaceMappingParams Params; + + uint8_t busID; + uint8_t addrType; + uint64_t addr; + uint64_t addrLength; + + public: + Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum); + + AddrSpaceMapping(Params * p); +}; + +class BusHierarchy : public ExtConfigEntry +{ + protected: + typedef X86IntelMPBusHierarchyParams Params; + + uint8_t busID; + uint8_t info; + uint8_t parentBus; + + public: + Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum); + + BusHierarchy(Params * p); +}; + +class CompatAddrSpaceMod : public ExtConfigEntry +{ + protected: + typedef X86IntelMPCompatAddrSpaceModParams Params; + + uint8_t busID; + uint8_t mod; + uint32_t rangeList; + + public: + Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum); + + CompatAddrSpaceMod(Params * p); +}; + +} //IntelMP + +} //X86ISA + +#endif diff --git a/src/arch/x86/system.cc b/src/arch/x86/system.cc index 9006ce227..b2fadd682 100644 --- a/src/arch/x86/system.cc +++ b/src/arch/x86/system.cc @@ -56,12 +56,14 @@ */ #include "arch/x86/bios/smbios.hh" +#include "arch/x86/bios/intelmp.hh" #include "arch/x86/miscregs.hh" #include "arch/x86/system.hh" #include "arch/vtophys.hh" -#include "base/remote_gdb.hh" +#include "base/intmath.hh" #include "base/loader/object_file.hh" #include "base/loader/symtab.hh" +#include "base/remote_gdb.hh" #include "base/trace.hh" #include "cpu/thread_context.hh" #include "mem/physical.hh" @@ -72,8 +74,10 @@ using namespace LittleEndianGuest; using namespace X86ISA; -X86System::X86System(Params *p) - : System(p), smbiosTable(p->smbios_table) +X86System::X86System(Params *p) : + System(p), smbiosTable(p->smbios_table), + mpFloatingPointer(p->intel_mp_pointer), + mpConfigTable(p->intel_mp_table) {} void @@ -232,11 +236,16 @@ X86System::startup() // We should now be in long mode. Yay! Addr ebdaPos = 0xF0000; + Addr fixed, table; - Addr headerSize, structSize; //Write out the SMBios/DMI table - writeOutSMBiosTable(ebdaPos, headerSize, structSize); - ebdaPos += (headerSize + structSize); + writeOutSMBiosTable(ebdaPos, fixed, table); + ebdaPos += (fixed + table); + ebdaPos = roundUp(ebdaPos, 16); + + //Write out the Intel MP Specification configuration table + writeOutMPTable(ebdaPos, fixed, table); + ebdaPos += (fixed + table); } void @@ -260,6 +269,35 @@ X86System::writeOutSMBiosTable(Addr header, assert(table > header || table + structSize <= header); } +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(); + + // 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 + // specification is 0x10 bytes. + if (mpConfigTable) { + if (!table) + table = fp + 0x10; + mpFloatingPointer->setTableAddr(table); + } + + fpSize = mpFloatingPointer->writeOut(physPort, fp); + if (mpConfigTable) + tableSize = mpConfigTable->writeOut(physPort, table); + else + tableSize = 0; + + // Do some bounds checking to make sure we at least didn't step on + // ourselves and the fp structure was the size we thought it was. + assert(fp > table || fp + fpSize <= table); + assert(table > fp || table + tableSize <= fp); + assert(fpSize == 0x10); +} + X86System::~X86System() { diff --git a/src/arch/x86/system.hh b/src/arch/x86/system.hh index 2120bc090..7433cc644 100644 --- a/src/arch/x86/system.hh +++ b/src/arch/x86/system.hh @@ -74,6 +74,11 @@ namespace X86ISA { class SMBiosTable; } + namespace IntelMP + { + class FloatingPointer; + class ConfigTable; + } } class X86System : public System @@ -95,10 +100,15 @@ class X86System : public System protected: X86ISA::SMBios::SMBiosTable * smbiosTable; + X86ISA::IntelMP::FloatingPointer * mpFloatingPointer; + X86ISA::IntelMP::ConfigTable * mpConfigTable; void writeOutSMBiosTable(Addr header, Addr &headerSize, Addr &tableSize, Addr table = 0); + void writeOutMPTable(Addr fp, + Addr &fpSize, Addr &tableSize, Addr table = 0); + const Params *params() const { return (const Params *)_params; } virtual Addr fixFuncEventAddr(Addr addr) -- cgit v1.2.3 From f85a7f00c0a9da6181fb803d760b1378fbc8bd27 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 10 Oct 2008 23:42:31 -0700 Subject: X86: Make the time on the RTC configurable. --- src/dev/x86/south_bridge/SouthBridge.py | 2 ++ src/dev/x86/south_bridge/cmos.hh | 17 +++++------------ src/dev/x86/south_bridge/south_bridge.cc | 2 +- 3 files changed, 8 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/dev/x86/south_bridge/SouthBridge.py b/src/dev/x86/south_bridge/SouthBridge.py index bec3c4223..9e1b66896 100644 --- a/src/dev/x86/south_bridge/SouthBridge.py +++ b/src/dev/x86/south_bridge/SouthBridge.py @@ -32,4 +32,6 @@ from Device import PioDevice class SouthBridge(PioDevice): type = 'SouthBridge' + time = Param.Time('01/01/2009', + "System time to use ('Now' for actual time)") pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") diff --git a/src/dev/x86/south_bridge/cmos.hh b/src/dev/x86/south_bridge/cmos.hh index 1cb22fa9e..585d9351e 100644 --- a/src/dev/x86/south_bridge/cmos.hh +++ b/src/dev/x86/south_bridge/cmos.hh @@ -44,8 +44,6 @@ class Cmos : public SubDevice protected: uint8_t address; - struct tm foo_time; - static const int numRegs = 128; uint8_t regs[numRegs]; @@ -70,22 +68,17 @@ class Cmos : public SubDevice public: - Cmos(EventManager *em) : rtc(em, "rtc", foo_time, true, ULL(5000000000)) - { - memset(regs, 0, numRegs * sizeof(uint8_t)); - address = 0; - } - - Cmos(EventManager *em, Tick _latency) : SubDevice(_latency), - rtc(em, "rtc", foo_time, true, ULL(5000000000)) + Cmos(EventManager *em, Tick _latency, struct tm time) : + SubDevice(_latency), rtc(em, "rtc", time, true, ULL(5000000000)) { memset(regs, 0, numRegs * sizeof(uint8_t)); address = 0; } - Cmos(EventManager *em, Addr start, Addr size, Tick _latency) : + Cmos(EventManager *em, Addr start, Addr size, + Tick _latency, struct tm time) : SubDevice(start, size, _latency), - rtc(em, "rtc", foo_time, true, ULL(5000000000)) + rtc(em, "rtc", time, true, ULL(5000000000)) { memset(regs, 0, numRegs * sizeof(uint8_t)); address = 0; diff --git a/src/dev/x86/south_bridge/south_bridge.cc b/src/dev/x86/south_bridge/south_bridge.cc index ded5d7ac5..fda5acbda 100644 --- a/src/dev/x86/south_bridge/south_bridge.cc +++ b/src/dev/x86/south_bridge/south_bridge.cc @@ -70,7 +70,7 @@ SouthBridge::SouthBridge(const Params *p) : PioDevice(p), pic1(0x20, 2, p->pio_latency), pic2(0xA0, 2, p->pio_latency), pit(this, p->name + ".pit", 0x40, 4, p->pio_latency), - cmos(this, 0x70, 2, p->pio_latency), + cmos(this, 0x70, 2, p->pio_latency, p->time), speaker(&pit, 0x61, 1, p->pio_latency) { addDevice(pic1); -- cgit v1.2.3 From 3d1734ec29a0572a2c0fe403d737adbd9756c993 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 10 Oct 2008 23:43:33 -0700 Subject: X86: Create SimObjects in python and C++ to represent the ACPI system description tables. --- src/arch/x86/X86System.py | 3 + src/arch/x86/bios/ACPI.py | 99 +++++++++++++++++++++++++++++ src/arch/x86/bios/SConscript | 4 ++ src/arch/x86/bios/acpi.cc | 109 ++++++++++++++++++++++++++++++++ src/arch/x86/bios/acpi.hh | 147 +++++++++++++++++++++++++++++++++++++++++++ src/arch/x86/system.cc | 3 +- src/arch/x86/system.hh | 1 + 7 files changed, 365 insertions(+), 1 deletion(-) create mode 100644 src/arch/x86/bios/ACPI.py create mode 100644 src/arch/x86/bios/acpi.cc create mode 100644 src/arch/x86/bios/acpi.hh (limited to 'src') diff --git a/src/arch/x86/X86System.py b/src/arch/x86/X86System.py index fc7a5acd0..527831205 100644 --- a/src/arch/x86/X86System.py +++ b/src/arch/x86/X86System.py @@ -57,6 +57,7 @@ from m5.params import * from E820 import X86E820Table, X86E820Entry from SMBios import X86SMBiosSMBiosTable from IntelMP import X86IntelMPFloatingPointer, X86IntelMPConfigTable +from ACPI import X86ACPIRSDP from System import System class X86System(System): @@ -69,6 +70,8 @@ class X86System(System): intel_mp_table = Param.X86IntelMPConfigTable( X86IntelMPConfigTable(), 'intel mp spec configuration table') + acpi_description_table_pointer = Param.X86ACPIRSDP( + X86ACPIRSDP(), 'ACPI root description pointer structure') class LinuxX86System(X86System): type = 'LinuxX86System' diff --git a/src/arch/x86/bios/ACPI.py b/src/arch/x86/bios/ACPI.py new file mode 100644 index 000000000..20eb66be0 --- /dev/null +++ b/src/arch/x86/bios/ACPI.py @@ -0,0 +1,99 @@ +# Copyright (c) 2008 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use of this software in source and binary forms, +# with or without modification, are permitted provided that the +# following conditions are met: +# +# The software must be used only for Non-Commercial Use which means any +# use which is NOT directed to receiving any direct monetary +# compensation for, or commercial advantage from such use. Illustrative +# examples of non-commercial use are academic research, personal study, +# teaching, education and corporate research & development. +# Illustrative examples of commercial use are distributing products for +# commercial advantage and providing services using the software for +# commercial advantage. +# +# If you wish to use this software or functionality therein that may be +# covered by patents for commercial use, please contact: +# Director of Intellectual Property Licensing +# Office of Strategy and Technology +# Hewlett-Packard Company +# 1501 Page Mill Road +# Palo Alto, California 94304 +# +# 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. No right of +# sublicense is granted herewith. Derivatives of the software and +# output created using the software may be prepared, but only for +# Non-Commercial Uses. Derivatives of the software may be shared with +# others provided: (i) the others agree to abide by the list of +# conditions herein which includes the Non-Commercial Use restrictions; +# and (ii) such Derivatives of the software include the above copyright +# notice to acknowledge the contribution from this software where +# applicable, this list of conditions and the disclaimer below. +# +# 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: Gabe Black + +from m5.params import * +from m5.SimObject import SimObject + +# ACPI description table header. Subclasses contain and handle the actual +# contents as appropriate for that type of table. +class X86ACPISysDescTable(SimObject): + type = 'X86ACPISysDescTable' + cxx_class = 'X86ISA::ACPI::SysDescTable' + abstract = True + + oem_id = Param.String('', 'string identifying the oem') + oem_table_id = Param.String('', 'oem table ID') + oem_revision = Param.UInt32(0, 'oem revision number for the table') + + creator_id = Param.String('', + 'string identifying the generator of the table') + creator_revision = Param.UInt32(0, + 'revision number for the creator of the table') + +class X86ACPIRSDT(X86ACPISysDescTable): + type = 'X86ACPIRSDT' + cxx_class = 'X86ISA::ACPI::RSDT' + + entries = VectorParam.X86ACPISysDescTable([], 'system description tables') + +class X86ACPIXSDT(X86ACPISysDescTable): + type = 'X86ACPIXSDT' + cxx_class = 'X86ISA::ACPI::XSDT' + + entries = VectorParam.X86ACPISysDescTable([], 'system description tables') + +# Root System Description Pointer Structure +class X86ACPIRSDP(SimObject): + type = 'X86ACPIRSDP' + cxx_class = 'X86ISA::ACPI::RSDP' + + oem_id = Param.String('', 'string identifying the oem') + # Because 0 encodes ACPI 1.0, 2 encodes ACPI 3.0, the version implemented + # here. + revision = Param.UInt8(2, 'revision of ACPI being used, zero indexed') + + rsdt = Param.X86ACPIRSDT('root system description table') + xsdt = Param.X86ACPIXSDT(X86ACPIXSDT(), + 'extended system description table') diff --git a/src/arch/x86/bios/SConscript b/src/arch/x86/bios/SConscript index c4f4f80e6..912d6599c 100644 --- a/src/arch/x86/bios/SConscript +++ b/src/arch/x86/bios/SConscript @@ -71,3 +71,7 @@ if env['TARGET_ISA'] == 'x86': # Intel Multiprocessor Specification Configuration Table SimObject('IntelMP.py') Source('intelmp.cc') + + # ACPI system description tables + SimObject('ACPI.py') + Source('acpi.cc') diff --git a/src/arch/x86/bios/acpi.cc b/src/arch/x86/bios/acpi.cc new file mode 100644 index 000000000..15b3901eb --- /dev/null +++ b/src/arch/x86/bios/acpi.cc @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2008 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * 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: Gabe Black + */ + +#include "arch/x86/bios/acpi.hh" +#include "mem/port.hh" +#include "sim/byteswap.hh" +#include "sim/sim_object.hh" + +#include "params/X86ACPIRSDP.hh" + +#include "params/X86ACPISysDescTable.hh" +#include "params/X86ACPIRSDT.hh" +#include "params/X86ACPIXSDT.hh" + +using namespace std; + +const char X86ISA::ACPI::RSDP::signature[] = "RSD PTR "; + +X86ISA::ACPI::RSDP::RSDP(Params *p) : SimObject(p), oemID(p->oem_id), + revision(p->revision), rsdt(p->rsdt), xsdt(p->xsdt) +{} + +X86ISA::ACPI::SysDescTable::SysDescTable(Params *p, + const char * _signature, uint8_t _revision) : SimObject(p), + signature(_signature), revision(_revision), + oemID(p->oem_id), oemTableID(p->oem_table_id), + oemRevision(p->oem_revision), + creatorID(p->creator_id), creatorRevision(p->creator_revision) +{} + +X86ISA::ACPI::RSDT::RSDT(Params *p) : + SysDescTable(p, "RSDT", 1), entries(p->entries) +{} + +X86ISA::ACPI::XSDT::XSDT(Params *p) : + SysDescTable(p, "XSDT", 1), entries(p->entries) +{} + +X86ISA::ACPI::RSDP * +X86ACPIRSDPParams::create() +{ + return new X86ISA::ACPI::RSDP(this); +} + +X86ISA::ACPI::RSDT * +X86ACPIRSDTParams::create() +{ + return new X86ISA::ACPI::RSDT(this); +} + +X86ISA::ACPI::XSDT * +X86ACPIXSDTParams::create() +{ + return new X86ISA::ACPI::XSDT(this); +} diff --git a/src/arch/x86/bios/acpi.hh b/src/arch/x86/bios/acpi.hh new file mode 100644 index 000000000..7bca17790 --- /dev/null +++ b/src/arch/x86/bios/acpi.hh @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2008 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * 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: Gabe Black + */ + +#ifndef __ARCH_X86_BIOS_ACPI_HH__ +#define __ARCH_X86_BIOS_ACPI_HH__ + +#include "sim/host.hh" +#include "sim/sim_object.hh" + +#include +#include + +class Port; + +class X86ACPIRSDPParams; + +class X86ACPISysDescTableParams; +class X86ACPIRSDTParams; +class X86ACPIXSDTParams; + +namespace X86ISA +{ + +namespace ACPI +{ + +class RSDT; +class XSDT; +class SysDescTable; + +class RSDP : public SimObject +{ + protected: + typedef X86ACPIRSDPParams Params; + + static const char signature[]; + + std::string oemID; + uint8_t revision; + + RSDT * rsdt; + XSDT * xsdt; + + public: + RSDP(Params *p); +}; + +class SysDescTable : public SimObject +{ + protected: + typedef X86ACPISysDescTableParams Params; + + const char * signature; + uint8_t revision; + + std::string oemID; + std::string oemTableID; + uint32_t oemRevision; + + std::string creatorID; + uint32_t creatorRevision; + + public: + SysDescTable(Params *p, const char * _signature, uint8_t _revision); +}; + +class RSDT : public SysDescTable +{ + protected: + typedef X86ACPIRSDTParams Params; + + std::vector entries; + + public: + RSDT(Params *p); +}; + +class XSDT : public SysDescTable +{ + protected: + typedef X86ACPIXSDTParams Params; + + std::vector entries; + + public: + XSDT(Params *p); +}; + +} // namespace ACPI + +} // namespace X86ISA + +#endif // __ARCH_X86_BIOS_E820_HH__ diff --git a/src/arch/x86/system.cc b/src/arch/x86/system.cc index b2fadd682..ed3dae4e6 100644 --- a/src/arch/x86/system.cc +++ b/src/arch/x86/system.cc @@ -77,7 +77,8 @@ using namespace X86ISA; X86System::X86System(Params *p) : System(p), smbiosTable(p->smbios_table), mpFloatingPointer(p->intel_mp_pointer), - mpConfigTable(p->intel_mp_table) + mpConfigTable(p->intel_mp_table), + rsdp(p->acpi_description_table_pointer) {} void diff --git a/src/arch/x86/system.hh b/src/arch/x86/system.hh index 7433cc644..12a471f6f 100644 --- a/src/arch/x86/system.hh +++ b/src/arch/x86/system.hh @@ -102,6 +102,7 @@ class X86System : public System X86ISA::SMBios::SMBiosTable * smbiosTable; X86ISA::IntelMP::FloatingPointer * mpFloatingPointer; X86ISA::IntelMP::ConfigTable * mpConfigTable; + X86ISA::ACPI::RSDP * rsdp; void writeOutSMBiosTable(Addr header, Addr &headerSize, Addr &tableSize, Addr table = 0); -- cgit v1.2.3 From 8c5dfa453296c5a87a46c409f68e0ef50ebfceb6 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 10 Oct 2008 23:47:42 -0700 Subject: TLB: Make all tlbs derive from a common base class in both python and C++. --- src/arch/alpha/AlphaTLB.py | 5 ++++- src/arch/mips/MipsTLB.py | 4 +++- src/arch/sparc/SparcTLB.py | 5 ++++- src/arch/x86/X86TLB.py | 4 ++-- src/sim/BaseTLB.py | 33 +++++++++++++++++++++++++++++++++ src/sim/SConscript | 1 + 6 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 src/sim/BaseTLB.py (limited to 'src') diff --git a/src/arch/alpha/AlphaTLB.py b/src/arch/alpha/AlphaTLB.py index 7cfb549f3..099327470 100644 --- a/src/arch/alpha/AlphaTLB.py +++ b/src/arch/alpha/AlphaTLB.py @@ -28,7 +28,10 @@ from m5.SimObject import SimObject from m5.params import * -class AlphaTLB(SimObject): + +from BaseTLB import BaseTLB + +class AlphaTLB(BaseTLB): type = 'AlphaTLB' abstract = True size = Param.Int("TLB size") diff --git a/src/arch/mips/MipsTLB.py b/src/arch/mips/MipsTLB.py index 0054acae5..41d46c572 100644 --- a/src/arch/mips/MipsTLB.py +++ b/src/arch/mips/MipsTLB.py @@ -32,7 +32,9 @@ from m5.SimObject import SimObject from m5.params import * -class MipsTLB(SimObject): +from BaseTLB import BaseTLB + +class MipsTLB(BaseTLB): type = 'MipsTLB' abstract = True size = Param.Int("TLB size") diff --git a/src/arch/sparc/SparcTLB.py b/src/arch/sparc/SparcTLB.py index 20672a24e..6758d612a 100644 --- a/src/arch/sparc/SparcTLB.py +++ b/src/arch/sparc/SparcTLB.py @@ -28,7 +28,10 @@ from m5.SimObject import SimObject from m5.params import * -class SparcTLB(SimObject): + +from BaseTLB import BaseTLB + +class SparcTLB(BaseTLB): type = 'SparcTLB' abstract = True size = Param.Int("TLB size") diff --git a/src/arch/x86/X86TLB.py b/src/arch/x86/X86TLB.py index c20566efb..d5ae95372 100644 --- a/src/arch/x86/X86TLB.py +++ b/src/arch/x86/X86TLB.py @@ -54,10 +54,10 @@ # Authors: Gabe Black from MemObject import MemObject -from m5.SimObject import SimObject from m5.params import * from m5.proxy import * from m5 import build_env +from BaseTLB import BaseTLB if build_env['FULL_SYSTEM']: class X86PagetableWalker(MemObject): @@ -66,7 +66,7 @@ if build_env['FULL_SYSTEM']: port = Port("Port for the hardware table walker") system = Param.System(Parent.any, "system object") -class X86TLB(SimObject): +class X86TLB(BaseTLB): type = 'X86TLB' abstract = True size = Param.Int("TLB size") diff --git a/src/sim/BaseTLB.py b/src/sim/BaseTLB.py new file mode 100644 index 000000000..9aca4a97c --- /dev/null +++ b/src/sim/BaseTLB.py @@ -0,0 +1,33 @@ +# Copyright (c) 2008 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +from m5.SimObject import SimObject + +class BaseTLB(SimObject): + type = 'BaseTLB' + abstract = True diff --git a/src/sim/SConscript b/src/sim/SConscript index 3e6adb85a..7acf4e9b6 100644 --- a/src/sim/SConscript +++ b/src/sim/SConscript @@ -30,6 +30,7 @@ Import('*') +SimObject('BaseTLB.py') SimObject('Root.py') SimObject('System.py') SimObject('InstTracer.py') -- cgit v1.2.3 From f22c7d48f3b99994c697075f5cc3b59c72f84092 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 11 Oct 2008 01:13:11 -0700 Subject: X86: Change the CMOS from a sub-device to a real SimObject --HG-- rename : src/dev/x86/south_bridge/cmos.cc => src/dev/x86/cmos.cc rename : src/dev/x86/south_bridge/cmos.hh => src/dev/x86/cmos.hh --- src/dev/x86/Cmos.py | 38 +++++++++++ src/dev/x86/PC.py | 3 + src/dev/x86/SConscript | 5 +- src/dev/x86/cmos.cc | 106 +++++++++++++++++++++++++++++++ src/dev/x86/cmos.hh | 88 +++++++++++++++++++++++++ src/dev/x86/south_bridge/SConscript | 1 - src/dev/x86/south_bridge/SouthBridge.py | 2 - src/dev/x86/south_bridge/cmos.cc | 93 --------------------------- src/dev/x86/south_bridge/cmos.hh | 94 --------------------------- src/dev/x86/south_bridge/south_bridge.cc | 2 - src/dev/x86/south_bridge/south_bridge.hh | 4 -- 11 files changed, 239 insertions(+), 197 deletions(-) create mode 100644 src/dev/x86/Cmos.py create mode 100644 src/dev/x86/cmos.cc create mode 100644 src/dev/x86/cmos.hh delete mode 100644 src/dev/x86/south_bridge/cmos.cc delete mode 100644 src/dev/x86/south_bridge/cmos.hh (limited to 'src') diff --git a/src/dev/x86/Cmos.py b/src/dev/x86/Cmos.py new file mode 100644 index 000000000..c786eda36 --- /dev/null +++ b/src/dev/x86/Cmos.py @@ -0,0 +1,38 @@ +# Copyright (c) 2008 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +from m5.params import * +from m5.proxy import * +from Device import BasicPioDevice + +class Cmos(BasicPioDevice): + type = 'Cmos' + cxx_class='X86ISA::Cmos' + time = Param.Time('01/01/2009', + "System time to use ('Now' for actual time)") + pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") diff --git a/src/dev/x86/PC.py b/src/dev/x86/PC.py index 5165308ed..6460e7402 100644 --- a/src/dev/x86/PC.py +++ b/src/dev/x86/PC.py @@ -29,6 +29,7 @@ from m5.params import * from m5.proxy import * +from Cmos import Cmos from Device import IsaFake from Pci import PciConfigAll from Platform import Platform @@ -47,6 +48,7 @@ class PC(Platform): pciconfig = PciConfigAll() south_bridge = SouthBridge() + cmos = Cmos(pio_addr=x86IOAddress(0x70)) # "Non-existant" port used for timing purposes by the linux kernel i_dont_exist = IsaFake(pio_addr=x86IOAddress(0x80), pio_size=1) @@ -63,6 +65,7 @@ class PC(Platform): def attachIO(self, bus): self.south_bridge.pio = bus.port + self.cmos.pio = bus.port self.i_dont_exist.pio = bus.port self.behind_pci.pio = bus.port self.com_1.pio = bus.port diff --git a/src/dev/x86/SConscript b/src/dev/x86/SConscript index 463344001..c9ac19a91 100644 --- a/src/dev/x86/SConscript +++ b/src/dev/x86/SConscript @@ -32,5 +32,8 @@ Import('*') if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'x86': SimObject('PC.py') - Source('pc.cc') + + SimObject('Cmos.py') + Source('cmos.cc') + TraceFlag('CMOS', 'Accesses to CMOS devices') diff --git a/src/dev/x86/cmos.cc b/src/dev/x86/cmos.cc new file mode 100644 index 000000000..5bbded260 --- /dev/null +++ b/src/dev/x86/cmos.cc @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "dev/x86/cmos.hh" +#include "mem/packet_access.hh" + +Tick +X86ISA::Cmos::read(PacketPtr pkt) +{ + assert(pkt->getSize() == 1); + switch(pkt->getAddr() - pioAddr) + { + case 0x0: + pkt->set(address); + break; + case 0x1: + pkt->set(readRegister(address)); + break; + default: + panic("Read from undefined CMOS port.\n"); + } + return latency; +} + +Tick +X86ISA::Cmos::write(PacketPtr pkt) +{ + assert(pkt->getSize() == 1); + switch(pkt->getAddr() - pioAddr) + { + case 0x0: + address = pkt->get(); + break; + case 0x1: + writeRegister(address, pkt->get()); + break; + default: + panic("Write to undefined CMOS port.\n"); + } + return latency; +} + +uint8_t +X86ISA::Cmos::readRegister(uint8_t reg) +{ + assert(reg < numRegs); + uint8_t val; + if (reg <= 0xD) { + val = rtc.readData(reg); + DPRINTF(CMOS, + "Reading CMOS RTC reg %x as %x.\n", reg, val); + } else { + val = regs[reg]; + DPRINTF(CMOS, + "Reading non-volitile CMOS address %x as %x.\n", reg, val); + } + return val; +} + +void +X86ISA::Cmos::writeRegister(uint8_t reg, uint8_t val) +{ + assert(reg < numRegs); + if (reg <= 0xD) { + DPRINTF(CMOS, "Writing CMOS RTC reg %x with %x.\n", + reg, val); + rtc.writeData(reg, val); + } else { + DPRINTF(CMOS, "Writing non-volitile CMOS address %x with %x.\n", + reg, val); + regs[reg] = val; + } +} + +X86ISA::Cmos * +CmosParams::create() +{ + return new X86ISA::Cmos(this); +} diff --git a/src/dev/x86/cmos.hh b/src/dev/x86/cmos.hh new file mode 100644 index 000000000..04df9dd04 --- /dev/null +++ b/src/dev/x86/cmos.hh @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __DEV_X86_CMOS_HH__ +#define __DEV_X86_CMOS_HH__ + +#include "dev/io_device.hh" +#include "dev/mc146818.hh" +#include "params/Cmos.hh" + +namespace X86ISA +{ + +class Cmos : public BasicPioDevice +{ + protected: + Tick latency; + + uint8_t address; + + static const int numRegs = 128; + + uint8_t regs[numRegs]; + + uint8_t readRegister(uint8_t reg); + void writeRegister(uint8_t reg, uint8_t val); + + class X86RTC : public MC146818 + { + public: + X86RTC(EventManager *em, const std::string &n, const struct tm time, + bool bcd, Tick frequency) : + MC146818(em, n, time, bcd, frequency) + { + } + protected: + void handleEvent() + { + return; + } + } rtc; + + public: + typedef CmosParams Params; + + Cmos(const Params *p) : BasicPioDevice(p), latency(p->pio_latency), + rtc(this, "rtc", p->time, true, ULL(5000000000)) + { + pioSize = 2; + memset(regs, 0, numRegs * sizeof(uint8_t)); + address = 0; + } + + Tick read(PacketPtr pkt); + + Tick write(PacketPtr pkt); +}; + +}; // namespace X86ISA + +#endif //__DEV_X86_CMOS_HH__ diff --git a/src/dev/x86/south_bridge/SConscript b/src/dev/x86/south_bridge/SConscript index d01106c5c..edc091e12 100644 --- a/src/dev/x86/south_bridge/SConscript +++ b/src/dev/x86/south_bridge/SConscript @@ -36,7 +36,6 @@ if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'x86': Source('south_bridge.cc') # Sub devices - Source('cmos.cc') Source('i8254.cc') Source('i8259.cc') Source('speaker.cc') diff --git a/src/dev/x86/south_bridge/SouthBridge.py b/src/dev/x86/south_bridge/SouthBridge.py index 9e1b66896..bec3c4223 100644 --- a/src/dev/x86/south_bridge/SouthBridge.py +++ b/src/dev/x86/south_bridge/SouthBridge.py @@ -32,6 +32,4 @@ from Device import PioDevice class SouthBridge(PioDevice): type = 'SouthBridge' - time = Param.Time('01/01/2009', - "System time to use ('Now' for actual time)") pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") diff --git a/src/dev/x86/south_bridge/cmos.cc b/src/dev/x86/south_bridge/cmos.cc deleted file mode 100644 index 164b23d84..000000000 --- a/src/dev/x86/south_bridge/cmos.cc +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#include "dev/x86/south_bridge/cmos.hh" -#include "mem/packet_access.hh" - -Tick -X86ISA::Cmos::read(PacketPtr pkt) -{ - assert(pkt->getSize() == 1); - switch(pkt->getAddr() - addrRange.start) - { - case 0x0: - pkt->set(address); - break; - case 0x1: - pkt->set(readRegister(address)); - break; - default: - panic("Read from undefined CMOS port.\n"); - } - return latency; -} - -Tick -X86ISA::Cmos::write(PacketPtr pkt) -{ - assert(pkt->getSize() == 1); - switch(pkt->getAddr() - addrRange.start) - { - case 0x0: - address = pkt->get(); - break; - case 0x1: - writeRegister(address, pkt->get()); - break; - default: - panic("Write to undefined CMOS port.\n"); - } - return latency; -} - -uint8_t -X86ISA::Cmos::readRegister(uint8_t reg) -{ - assert(reg < numRegs); - if (reg <= 0xD) { - return rtc.readData(reg); - } else { - warn("Reading non-volitile CMOS address %x as %x.\n", reg, regs[reg]); - } - return regs[reg]; -} - -void -X86ISA::Cmos::writeRegister(uint8_t reg, uint8_t val) -{ - assert(reg < numRegs); - if (reg <= 0xD) { - rtc.writeData(reg, val); - return; - } else { - warn("Writing non-volitile CMOS address %x with %x.\n", reg, val); - } - regs[reg] = val; -} diff --git a/src/dev/x86/south_bridge/cmos.hh b/src/dev/x86/south_bridge/cmos.hh deleted file mode 100644 index 585d9351e..000000000 --- a/src/dev/x86/south_bridge/cmos.hh +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2008 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#ifndef __DEV_X86_SOUTH_BRIDGE_CMOS_HH__ -#define __DEV_X86_SOUTH_BRIDGE_CMOS_HH__ - -#include "arch/x86/x86_traits.hh" -#include "base/range.hh" -#include "dev/mc146818.hh" -#include "dev/x86/south_bridge/sub_device.hh" - -namespace X86ISA -{ - -class Cmos : public SubDevice -{ - protected: - uint8_t address; - - static const int numRegs = 128; - - uint8_t regs[numRegs]; - - uint8_t readRegister(uint8_t reg); - void writeRegister(uint8_t reg, uint8_t val); - - class X86RTC : public MC146818 - { - public: - X86RTC(EventManager *em, const std::string &n, const struct tm time, - bool bcd, Tick frequency) : - MC146818(em, n, time, bcd, frequency) - { - } - protected: - void handleEvent() - { - return; - } - } rtc; - - public: - - Cmos(EventManager *em, Tick _latency, struct tm time) : - SubDevice(_latency), rtc(em, "rtc", time, true, ULL(5000000000)) - { - memset(regs, 0, numRegs * sizeof(uint8_t)); - address = 0; - } - - Cmos(EventManager *em, Addr start, Addr size, - Tick _latency, struct tm time) : - SubDevice(start, size, _latency), - rtc(em, "rtc", time, true, ULL(5000000000)) - { - memset(regs, 0, numRegs * sizeof(uint8_t)); - address = 0; - } - - Tick read(PacketPtr pkt); - - Tick write(PacketPtr pkt); -}; - -}; // namespace X86ISA - -#endif //__DEV_X86_SOUTH_BRIDGE_CMOS_HH__ diff --git a/src/dev/x86/south_bridge/south_bridge.cc b/src/dev/x86/south_bridge/south_bridge.cc index fda5acbda..6edb3364c 100644 --- a/src/dev/x86/south_bridge/south_bridge.cc +++ b/src/dev/x86/south_bridge/south_bridge.cc @@ -70,13 +70,11 @@ SouthBridge::SouthBridge(const Params *p) : PioDevice(p), pic1(0x20, 2, p->pio_latency), pic2(0xA0, 2, p->pio_latency), pit(this, p->name + ".pit", 0x40, 4, p->pio_latency), - cmos(this, 0x70, 2, p->pio_latency, p->time), speaker(&pit, 0x61, 1, p->pio_latency) { addDevice(pic1); addDevice(pic2); addDevice(pit); - addDevice(cmos); addDevice(speaker); // Let the platform know where we are diff --git a/src/dev/x86/south_bridge/south_bridge.hh b/src/dev/x86/south_bridge/south_bridge.hh index 203cb6ee2..6510ab348 100644 --- a/src/dev/x86/south_bridge/south_bridge.hh +++ b/src/dev/x86/south_bridge/south_bridge.hh @@ -33,7 +33,6 @@ #include "base/range_map.hh" #include "dev/io_device.hh" -#include "dev/x86/south_bridge/cmos.hh" #include "dev/x86/south_bridge/i8254.hh" #include "dev/x86/south_bridge/i8259.hh" #include "dev/x86/south_bridge/speaker.hh" @@ -60,9 +59,6 @@ class SouthBridge : public PioDevice // I8254 Programmable Interval Timer X86ISA::I8254 pit; - // CMOS apperature - X86ISA::Cmos cmos; - // PC speaker X86ISA::Speaker speaker; -- cgit v1.2.3 From 2753c07dc5131972d1dcbb7628e2f0712c778fec Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 11 Oct 2008 01:22:20 -0700 Subject: X86: Change the I8259 from a subdevice into a real SimObject. --HG-- rename : src/dev/x86/south_bridge/i8259.cc => src/dev/x86/i8259.cc rename : src/dev/x86/south_bridge/i8259.hh => src/dev/x86/i8259.hh --- src/dev/x86/I8259.py | 37 +++++++++++++++++ src/dev/x86/PC.py | 5 +++ src/dev/x86/SConscript | 4 ++ src/dev/x86/i8259.cc | 51 +++++++++++++++++++++++ src/dev/x86/i8259.hh | 69 ++++++++++++++++++++++++++++++++ src/dev/x86/south_bridge/SConscript | 1 - src/dev/x86/south_bridge/i8259.cc | 45 --------------------- src/dev/x86/south_bridge/i8259.hh | 60 --------------------------- src/dev/x86/south_bridge/south_bridge.cc | 4 -- src/dev/x86/south_bridge/south_bridge.hh | 5 --- 10 files changed, 166 insertions(+), 115 deletions(-) create mode 100644 src/dev/x86/I8259.py create mode 100644 src/dev/x86/i8259.cc create mode 100644 src/dev/x86/i8259.hh delete mode 100644 src/dev/x86/south_bridge/i8259.cc delete mode 100644 src/dev/x86/south_bridge/i8259.hh (limited to 'src') diff --git a/src/dev/x86/I8259.py b/src/dev/x86/I8259.py new file mode 100644 index 000000000..a599a5b3c --- /dev/null +++ b/src/dev/x86/I8259.py @@ -0,0 +1,37 @@ +# Copyright (c) 2008 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +from m5.params import * +from m5.proxy import * +from Device import BasicPioDevice + +class I8259(BasicPioDevice): + type = 'I8259' + cxx_class='X86ISA::I8259' + pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") + master = Param.Bool(True, 'If this PIC is the master or slave') diff --git a/src/dev/x86/PC.py b/src/dev/x86/PC.py index 6460e7402..d0516ec13 100644 --- a/src/dev/x86/PC.py +++ b/src/dev/x86/PC.py @@ -32,6 +32,7 @@ from m5.proxy import * from Cmos import Cmos from Device import IsaFake from Pci import PciConfigAll +from I8259 import I8259 from Platform import Platform from SouthBridge import SouthBridge from Terminal import Terminal @@ -49,6 +50,8 @@ class PC(Platform): south_bridge = SouthBridge() cmos = Cmos(pio_addr=x86IOAddress(0x70)) + pic1 = I8259(pio_addr=x86IOAddress(0x20), master=True) + pic2 = I8259(pio_addr=x86IOAddress(0xA0), master=False) # "Non-existant" port used for timing purposes by the linux kernel i_dont_exist = IsaFake(pio_addr=x86IOAddress(0x80), pio_size=1) @@ -66,6 +69,8 @@ class PC(Platform): def attachIO(self, bus): self.south_bridge.pio = bus.port self.cmos.pio = bus.port + self.pic1.pio = bus.port + self.pic2.pio = bus.port self.i_dont_exist.pio = bus.port self.behind_pci.pio = bus.port self.com_1.pio = bus.port diff --git a/src/dev/x86/SConscript b/src/dev/x86/SConscript index c9ac19a91..6cc010f71 100644 --- a/src/dev/x86/SConscript +++ b/src/dev/x86/SConscript @@ -37,3 +37,7 @@ if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'x86': SimObject('Cmos.py') Source('cmos.cc') TraceFlag('CMOS', 'Accesses to CMOS devices') + + SimObject('I8259.py') + Source('i8259.cc') + TraceFlag('I8259', 'Accesses to the I8259 PIC devices') diff --git a/src/dev/x86/i8259.cc b/src/dev/x86/i8259.cc new file mode 100644 index 000000000..62698c0eb --- /dev/null +++ b/src/dev/x86/i8259.cc @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "dev/x86/i8259.hh" + +Tick +X86ISA::I8259::read(PacketPtr pkt) +{ + DPRINTF(I8259, "Reading from PIC device.\n"); + return latency; +} + +Tick +X86ISA::I8259::write(PacketPtr pkt) +{ + DPRINTF(I8259, "Writing to PIC device.\n"); + return latency; +} + +X86ISA::I8259 * +I8259Params::create() +{ + return new X86ISA::I8259(this); +} diff --git a/src/dev/x86/i8259.hh b/src/dev/x86/i8259.hh new file mode 100644 index 000000000..a2f245513 --- /dev/null +++ b/src/dev/x86/i8259.hh @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __DEV_X86_I8259_HH__ +#define __DEV_X86_I8259_HH__ + +#include "dev/io_device.hh" +#include "params/I8259.hh" + +namespace X86ISA +{ + +class I8259 : public BasicPioDevice +{ + protected: + Tick latency; + bool master; + + public: + typedef I8259Params Params; + + const Params * + params() const + { + return dynamic_cast(_params); + } + + I8259(Params * p) : BasicPioDevice(p) + { + pioSize = 2; + latency = p->pio_latency; + master = p->master; + } + + Tick read(PacketPtr pkt); + + Tick write(PacketPtr pkt); +}; + +}; // namespace X86ISA + +#endif //__DEV_X86_I8259_HH__ diff --git a/src/dev/x86/south_bridge/SConscript b/src/dev/x86/south_bridge/SConscript index edc091e12..c4e31bb8c 100644 --- a/src/dev/x86/south_bridge/SConscript +++ b/src/dev/x86/south_bridge/SConscript @@ -37,7 +37,6 @@ if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'x86': # Sub devices Source('i8254.cc') - Source('i8259.cc') Source('speaker.cc') TraceFlag('PCSpeaker') diff --git a/src/dev/x86/south_bridge/i8259.cc b/src/dev/x86/south_bridge/i8259.cc deleted file mode 100644 index 0cf83dece..000000000 --- a/src/dev/x86/south_bridge/i8259.cc +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#include "dev/x86/south_bridge/i8259.hh" - -Tick -X86ISA::I8259::read(PacketPtr pkt) -{ - warn("Reading from PIC device.\n"); - return SubDevice::read(pkt); -} - -Tick -X86ISA::I8259::write(PacketPtr pkt) -{ - warn("Writing to PIC device.\n"); - return SubDevice::write(pkt); -} diff --git a/src/dev/x86/south_bridge/i8259.hh b/src/dev/x86/south_bridge/i8259.hh deleted file mode 100644 index 3fda75dfb..000000000 --- a/src/dev/x86/south_bridge/i8259.hh +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#ifndef __DEV_X86_SOUTH_BRIDGE_I8259_HH__ -#define __DEV_X86_SOUTH_BRIDGE_I8259_HH__ - -#include "arch/x86/x86_traits.hh" -#include "base/range.hh" -#include "dev/x86/south_bridge/sub_device.hh" - -namespace X86ISA -{ - -class I8259 : public SubDevice -{ - public: - - I8259() - {} - I8259(Tick _latency) : SubDevice(_latency) - {} - I8259(Addr start, Addr size, Tick _latency) : - SubDevice(start, size, _latency) - {} - - Tick read(PacketPtr pkt); - - Tick write(PacketPtr pkt); -}; - -}; // namespace X86ISA - -#endif //__DEV_X86_SOUTH_BRIDGE_I8259_HH__ diff --git a/src/dev/x86/south_bridge/south_bridge.cc b/src/dev/x86/south_bridge/south_bridge.cc index 6edb3364c..0e9a63a74 100644 --- a/src/dev/x86/south_bridge/south_bridge.cc +++ b/src/dev/x86/south_bridge/south_bridge.cc @@ -67,13 +67,9 @@ SouthBridge::write(PacketPtr pkt) } SouthBridge::SouthBridge(const Params *p) : PioDevice(p), - pic1(0x20, 2, p->pio_latency), - pic2(0xA0, 2, p->pio_latency), pit(this, p->name + ".pit", 0x40, 4, p->pio_latency), speaker(&pit, 0x61, 1, p->pio_latency) { - addDevice(pic1); - addDevice(pic2); addDevice(pit); addDevice(speaker); diff --git a/src/dev/x86/south_bridge/south_bridge.hh b/src/dev/x86/south_bridge/south_bridge.hh index 6510ab348..171589cf3 100644 --- a/src/dev/x86/south_bridge/south_bridge.hh +++ b/src/dev/x86/south_bridge/south_bridge.hh @@ -34,7 +34,6 @@ #include "base/range_map.hh" #include "dev/io_device.hh" #include "dev/x86/south_bridge/i8254.hh" -#include "dev/x86/south_bridge/i8259.hh" #include "dev/x86/south_bridge/speaker.hh" #include "dev/x86/south_bridge/sub_device.hh" #include "params/SouthBridge.hh" @@ -52,10 +51,6 @@ class SouthBridge : public PioDevice void addDevice(X86ISA::SubDevice &); public: - // PICs - X86ISA::I8259 pic1; - X86ISA::I8259 pic2; - // I8254 Programmable Interval Timer X86ISA::I8254 pit; -- cgit v1.2.3 From cf9afbba510ceac86e011a4b37ec848cd7f7a6ed Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 11 Oct 2008 01:28:35 -0700 Subject: X86: Make the I8259 decipher the commands it's given, and add some of it's registers. --- src/dev/x86/i8259.cc | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/dev/x86/i8259.hh | 15 ++++++ 2 files changed, 154 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/dev/x86/i8259.cc b/src/dev/x86/i8259.cc index 62698c0eb..ed9b429c8 100644 --- a/src/dev/x86/i8259.cc +++ b/src/dev/x86/i8259.cc @@ -28,19 +28,156 @@ * Authors: Gabe Black */ +#include "base/bitfield.hh" #include "dev/x86/i8259.hh" Tick X86ISA::I8259::read(PacketPtr pkt) { - DPRINTF(I8259, "Reading from PIC device.\n"); + assert(pkt->getSize() == 1); + switch(pkt->getAddr() - pioAddr) + { + case 0x0: + if (readIRR) { + DPRINTF(I8259, "Reading IRR as %#x.\n", IRR); + pkt->set(IRR); + } else { + DPRINTF(I8259, "Reading ISR as %#x.\n", ISR); + pkt->set(ISR); + } + break; + case 0x1: + DPRINTF(I8259, "Reading IMR as %#x.\n", IMR); + pkt->set(IMR); + break; + } return latency; } Tick X86ISA::I8259::write(PacketPtr pkt) { - DPRINTF(I8259, "Writing to PIC device.\n"); + assert(pkt->getSize() == 1); + uint8_t val = pkt->get(); + switch (pkt->getAddr() - pioAddr) { + case 0x0: + if (bits(val, 4)) { + DPRINTF(I8259, "Received initialization command word 1.\n"); + IMR = 0; + edgeTriggered = bits(val, 3); + DPRINTF(I8259, "%s triggered mode.\n", + edgeTriggered ? "Edge" : "Level"); + cascadeMode = !bits(val, 1); + DPRINTF(I8259, "%s mode.\n", + cascadeMode ? "Cascade" : "Single"); + expectICW4 = bits(val, 0); + initControlWord = 1; + DPRINTF(I8259, "Expecting %d more bytes.\n", expectICW4 ? 3 : 2); + } else if (bits(val, 4, 3) == 0) { + DPRINTF(I8259, "Received operation command word 2.\n"); + switch (bits(val, 7, 5)) { + case 0x0: + DPRINTF(I8259, + "Subcommand: Rotate in auto-EOI mode (clear).\n"); + break; + case 0x1: + DPRINTF(I8259, "Subcommand: Nonspecific EOI.\n"); + break; + case 0x2: + DPRINTF(I8259, "Subcommand: No operation.\n"); + break; + case 0x3: + DPRINTF(I8259, "Subcommand: Specific EIO."); + DPRINTF(I8259, "Reset In-Service bit %d.\n", bits(val, 2, 0)); + break; + case 0x4: + DPRINTF(I8259, "Subcommand: Rotate in auto-EOI mode (set).\n"); + break; + case 0x5: + DPRINTF(I8259, "Subcommand: Rotate on nonspecific EOI.\n"); + break; + case 0x6: + DPRINTF(I8259, "Subcommand: Set priority command.\n"); + DPRINTF(I8259, "Lowest: IRQ%d Highest IRQ%d.\n", + bits(val, 2, 0), (bits(val, 2, 0) + 1) % 8); + break; + case 0x7: + DPRINTF(I8259, "Subcommand: Rotate on specific EOI.\n"); + DPRINTF(I8259, "Lowest: IRQ%d Highest IRQ%d.\n", + bits(val, 2, 0), (bits(val, 2, 0) + 1) % 8); + break; + } + } else if (bits(val, 4, 3) == 1) { + DPRINTF(I8259, "Received operation command word 3.\n"); + if (bits(val, 7)) { + DPRINTF(I8259, "%s special mask mode.\n", + bits(val, 6) ? "Set" : "Clear"); + } + if (bits(val, 1)) { + readIRR = bits(val, 0); + DPRINTF(I8259, "Read %s.\n", readIRR ? "IRR" : "ISR"); + } + } + break; + case 0x1: + switch (initControlWord) { + case 0x0: + DPRINTF(I8259, "Received operation command word 1.\n"); + DPRINTF(I8259, "Wrote IMR value %#x.\n", val); + IMR = val; + break; + case 0x1: + DPRINTF(I8259, "Received initialization command word 2.\n"); + DPRINTF(I8259, "Responsible for vectors %#x-%#x.\n", + val & ~mask(3), val | mask(3)); + if (cascadeMode) { + initControlWord++; + } else { + initControlWord = 0; + } + break; + case 0x2: + DPRINTF(I8259, "Received initialization command word 3.\n"); + if (master) { + DPRINTF(I8259, "Slaves attached to IRQs:%s%s%s%s%s%s%s%s\n", + bits(val, 0) ? " 0" : "", + bits(val, 1) ? " 1" : "", + bits(val, 2) ? " 2" : "", + bits(val, 3) ? " 3" : "", + bits(val, 4) ? " 4" : "", + bits(val, 5) ? " 5" : "", + bits(val, 6) ? " 6" : "", + bits(val, 7) ? " 7" : ""); + } else { + DPRINTF(I8259, "Slave ID is %d.\n", val & mask(3)); + } + if (expectICW4) + initControlWord++; + else + initControlWord = 0; + break; + case 0x3: + DPRINTF(I8259, "Received initialization command word 4.\n"); + if (bits(val, 4)) { + DPRINTF(I8259, "Special fully nested mode.\n"); + } else { + DPRINTF(I8259, "Not special fully nested mode.\n"); + } + if (bits(val, 3) == 0) { + DPRINTF(I8259, "Nonbuffered.\n"); + } else if (bits(val, 2) == 0) { + DPRINTF(I8259, "Buffered.\n"); + } else { + DPRINTF(I8259, "Unrecognized buffer mode.\n"); + } + DPRINTF(I8259, "%s End Of Interrupt.\n", + bits(val, 1) ? "Automatic" : "Normal"); + DPRINTF(I8259, "%s mode.\n", bits(val, 0) ? "80x86" : "MCX-80/85"); + initControlWord = 0; + break; + } + break; + } return latency; } diff --git a/src/dev/x86/i8259.hh b/src/dev/x86/i8259.hh index a2f245513..131adc93f 100644 --- a/src/dev/x86/i8259.hh +++ b/src/dev/x86/i8259.hh @@ -43,6 +43,19 @@ class I8259 : public BasicPioDevice Tick latency; bool master; + // Interrupt Request Register + uint8_t IRR; + // In Service Register + uint8_t ISR; + // Interrupt Mask Register + uint8_t IMR; + + bool edgeTriggered; + bool cascadeMode; + bool expectICW4; + bool readIRR; + int initControlWord; + public: typedef I8259Params Params; @@ -55,6 +68,8 @@ class I8259 : public BasicPioDevice I8259(Params * p) : BasicPioDevice(p) { pioSize = 2; + initControlWord = 0; + readIRR = true; latency = p->pio_latency; master = p->master; } -- cgit v1.2.3 From 8c532d629732e93fa23a38328b653eb4c2314936 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 11 Oct 2008 01:31:32 -0700 Subject: X86: Hook the CMOS device to the I8259 PICs. --- src/dev/x86/Cmos.py | 4 ++++ src/dev/x86/I8259.py | 2 +- src/dev/x86/PC.py | 6 +++--- src/dev/x86/cmos.cc | 7 +++++++ src/dev/x86/cmos.hh | 18 +++++++++++------- src/dev/x86/i8259.cc | 19 ++++++++++++++++++- src/dev/x86/i8259.hh | 14 +++++++++++--- 7 files changed, 55 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/dev/x86/Cmos.py b/src/dev/x86/Cmos.py index c786eda36..810432035 100644 --- a/src/dev/x86/Cmos.py +++ b/src/dev/x86/Cmos.py @@ -29,6 +29,7 @@ from m5.params import * from m5.proxy import * from Device import BasicPioDevice +from I8259 import I8259 class Cmos(BasicPioDevice): type = 'Cmos' @@ -36,3 +37,6 @@ class Cmos(BasicPioDevice): time = Param.Time('01/01/2009', "System time to use ('Now' for actual time)") pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") + i8259 = Param.I8259('PIC to send RTC alarm interrupts to') + int_line = Param.Int(0, + 'PIC relative interrupt line to use for alarm interrupts') diff --git a/src/dev/x86/I8259.py b/src/dev/x86/I8259.py index a599a5b3c..19670dde9 100644 --- a/src/dev/x86/I8259.py +++ b/src/dev/x86/I8259.py @@ -34,4 +34,4 @@ class I8259(BasicPioDevice): type = 'I8259' cxx_class='X86ISA::I8259' pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") - master = Param.Bool(True, 'If this PIC is the master or slave') + master = Param.I8259('The master PIC this PIC is cascaded with, if any') diff --git a/src/dev/x86/PC.py b/src/dev/x86/PC.py index d0516ec13..d3d3118c6 100644 --- a/src/dev/x86/PC.py +++ b/src/dev/x86/PC.py @@ -49,9 +49,9 @@ class PC(Platform): pciconfig = PciConfigAll() south_bridge = SouthBridge() - cmos = Cmos(pio_addr=x86IOAddress(0x70)) - pic1 = I8259(pio_addr=x86IOAddress(0x20), master=True) - pic2 = I8259(pio_addr=x86IOAddress(0xA0), master=False) + pic1 = I8259(pio_addr=x86IOAddress(0x20)) + pic2 = I8259(pio_addr=x86IOAddress(0xA0), master=pic1) + cmos = Cmos(pio_addr=x86IOAddress(0x70), i8259=pic2) # "Non-existant" port used for timing purposes by the linux kernel i_dont_exist = IsaFake(pio_addr=x86IOAddress(0x80), pio_size=1) diff --git a/src/dev/x86/cmos.cc b/src/dev/x86/cmos.cc index 5bbded260..d4ec58ddb 100644 --- a/src/dev/x86/cmos.cc +++ b/src/dev/x86/cmos.cc @@ -29,8 +29,15 @@ */ #include "dev/x86/cmos.hh" +#include "dev/x86/i8259.hh" #include "mem/packet_access.hh" +void +X86ISA::Cmos::X86RTC::handleEvent() +{ + i8259->signalInterrupt(intLine); +} + Tick X86ISA::Cmos::read(PacketPtr pkt) { diff --git a/src/dev/x86/cmos.hh b/src/dev/x86/cmos.hh index 04df9dd04..337fb8b02 100644 --- a/src/dev/x86/cmos.hh +++ b/src/dev/x86/cmos.hh @@ -38,6 +38,8 @@ namespace X86ISA { +class I8259; + class Cmos : public BasicPioDevice { protected: @@ -54,24 +56,26 @@ class Cmos : public BasicPioDevice class X86RTC : public MC146818 { + protected: + I8259 * i8259; + int intLine; public: X86RTC(EventManager *em, const std::string &n, const struct tm time, - bool bcd, Tick frequency) : - MC146818(em, n, time, bcd, frequency) + bool bcd, Tick frequency, I8259 *_i8259, int _intLine) : + MC146818(em, n, time, bcd, frequency), + i8259(_i8259), intLine(_intLine) { } protected: - void handleEvent() - { - return; - } + void handleEvent(); } rtc; public: typedef CmosParams Params; Cmos(const Params *p) : BasicPioDevice(p), latency(p->pio_latency), - rtc(this, "rtc", p->time, true, ULL(5000000000)) + rtc(this, "rtc", p->time, true, ULL(5000000000), + p->i8259, p->int_line) { pioSize = 2; memset(regs, 0, numRegs * sizeof(uint8_t)); diff --git a/src/dev/x86/i8259.cc b/src/dev/x86/i8259.cc index ed9b429c8..2dd6caaff 100644 --- a/src/dev/x86/i8259.cc +++ b/src/dev/x86/i8259.cc @@ -133,12 +133,13 @@ X86ISA::I8259::write(PacketPtr pkt) if (cascadeMode) { initControlWord++; } else { + cascadeBits = 0; initControlWord = 0; } break; case 0x2: DPRINTF(I8259, "Received initialization command word 3.\n"); - if (master) { + if (master == NULL) { DPRINTF(I8259, "Slaves attached to IRQs:%s%s%s%s%s%s%s%s\n", bits(val, 0) ? " 0" : "", bits(val, 1) ? " 1" : "", @@ -148,8 +149,10 @@ X86ISA::I8259::write(PacketPtr pkt) bits(val, 5) ? " 5" : "", bits(val, 6) ? " 6" : "", bits(val, 7) ? " 7" : ""); + cascadeBits = val; } else { DPRINTF(I8259, "Slave ID is %d.\n", val & mask(3)); + cascadeBits = val & mask(3); } if (expectICW4) initControlWord++; @@ -181,6 +184,20 @@ X86ISA::I8259::write(PacketPtr pkt) return latency; } +void +X86ISA::I8259::signalInterrupt(int line) +{ + DPRINTF(I8259, "Interrupt raised on line %d.\n", line); + if (line > 7) + fatal("Line number %d doesn't exist. The max is 7.\n"); + if (bits(IMR, line)) { + DPRINTF(I8259, "Interrupt %d was masked.\n", line); + } else if (master != NULL) { + DPRINTF(I8259, "Propogating interrupt to master.\n"); + master->signalInterrupt(cascadeBits); + } +} + X86ISA::I8259 * I8259Params::create() { diff --git a/src/dev/x86/i8259.hh b/src/dev/x86/i8259.hh index 131adc93f..c51ab1a6a 100644 --- a/src/dev/x86/i8259.hh +++ b/src/dev/x86/i8259.hh @@ -41,7 +41,7 @@ class I8259 : public BasicPioDevice { protected: Tick latency; - bool master; + I8259 *master; // Interrupt Request Register uint8_t IRR; @@ -50,10 +50,16 @@ class I8259 : public BasicPioDevice // Interrupt Mask Register uint8_t IMR; - bool edgeTriggered; bool cascadeMode; - bool expectICW4; + // A bit vector of lines with slaves attached, or the slave id, depending + // on if this is a master or slave PIC. + uint8_t cascadeBits; + + bool edgeTriggered; bool readIRR; + + // State machine information for reading in initialization control words. + bool expectICW4; int initControlWord; public: @@ -77,6 +83,8 @@ class I8259 : public BasicPioDevice Tick read(PacketPtr pkt); Tick write(PacketPtr pkt); + + void signalInterrupt(int line); }; }; // namespace X86ISA -- cgit v1.2.3 From 119e127d7128edfb729101b92ca160c1f01391ca Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 11 Oct 2008 01:37:04 -0700 Subject: X86: Create the IntDev and IntPin system. The IntDev class is a base for anything that supports IntPins. IntPins allow devices to generically trigger interrupts on a particular pin of an IntDev device without having to know what the device is or what pin they're attached to. --- src/dev/x86/SConscript | 3 ++ src/dev/x86/X86IntPin.py | 37 ++++++++++++++++++++++ src/dev/x86/intdev.cc | 37 ++++++++++++++++++++++ src/dev/x86/intdev.hh | 80 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 157 insertions(+) create mode 100644 src/dev/x86/X86IntPin.py create mode 100644 src/dev/x86/intdev.cc create mode 100644 src/dev/x86/intdev.hh (limited to 'src') diff --git a/src/dev/x86/SConscript b/src/dev/x86/SConscript index 6cc010f71..71e5a9528 100644 --- a/src/dev/x86/SConscript +++ b/src/dev/x86/SConscript @@ -41,3 +41,6 @@ if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'x86': SimObject('I8259.py') Source('i8259.cc') TraceFlag('I8259', 'Accesses to the I8259 PIC devices') + + SimObject('X86IntPin.py') + Source('intdev.cc') diff --git a/src/dev/x86/X86IntPin.py b/src/dev/x86/X86IntPin.py new file mode 100644 index 000000000..372b4ab66 --- /dev/null +++ b/src/dev/x86/X86IntPin.py @@ -0,0 +1,37 @@ +# Copyright (c) 2008 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +from m5.params import * +from m5.SimObject import SimObject + +class X86IntPin(SimObject): + type = 'X86IntPin' + cxx_class = 'X86ISA::IntPin' + + line = Param.Int("Interrupt line for this pin") + device = Param.SimObject("Device which handles interrupts") diff --git a/src/dev/x86/intdev.cc b/src/dev/x86/intdev.cc new file mode 100644 index 000000000..463b3c9fe --- /dev/null +++ b/src/dev/x86/intdev.cc @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "dev/x86/intdev.hh" + +X86ISA::IntPin * +X86IntPinParams::create() +{ + return new X86ISA::IntPin(this); +} diff --git a/src/dev/x86/intdev.hh b/src/dev/x86/intdev.hh new file mode 100644 index 000000000..7a369f8fa --- /dev/null +++ b/src/dev/x86/intdev.hh @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __DEV_X86_INTDEV_HH__ +#define __DEV_X86_INTDEV_HH__ + +#include + +#include "sim/sim_object.hh" +#include "params/X86IntPin.hh" + +namespace X86ISA { + +class IntDev +{ + public: + virtual ~IntDev() + {} + virtual void + signalInterrupt(int line) = 0; +}; + +class IntPin : public SimObject +{ + protected: + IntDev * device; + int line; + + public: + typedef X86IntPinParams Params; + + const Params * + params() const + { + return dynamic_cast(_params); + } + + IntPin(Params *p) : SimObject(p), + device(dynamic_cast(p->device)), line(p->line) + { + assert(device); + } + + void + signalInterrupt() + { + device->signalInterrupt(line); + } +}; + +}; // namespace X86ISA + +#endif //__DEV_X86_INTDEV_HH__ -- cgit v1.2.3 From 539563e04b4925e88c28cb44f5180915c3b3a5be Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 11 Oct 2008 01:45:25 -0700 Subject: X86: Make the CMOS and I8259 devices use IntDev and IntPin. --- src/dev/x86/Cmos.py | 5 +---- src/dev/x86/I8259.py | 13 ++++++++++++- src/dev/x86/PC.py | 7 ++++--- src/dev/x86/cmos.cc | 5 +++-- src/dev/x86/cmos.hh | 13 +++++-------- src/dev/x86/i8259.cc | 13 +++++++++---- src/dev/x86/i8259.hh | 15 ++++++++------- 7 files changed, 42 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/dev/x86/Cmos.py b/src/dev/x86/Cmos.py index 810432035..a9910f70d 100644 --- a/src/dev/x86/Cmos.py +++ b/src/dev/x86/Cmos.py @@ -29,7 +29,6 @@ from m5.params import * from m5.proxy import * from Device import BasicPioDevice -from I8259 import I8259 class Cmos(BasicPioDevice): type = 'Cmos' @@ -37,6 +36,4 @@ class Cmos(BasicPioDevice): time = Param.Time('01/01/2009', "System time to use ('Now' for actual time)") pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") - i8259 = Param.I8259('PIC to send RTC alarm interrupts to') - int_line = Param.Int(0, - 'PIC relative interrupt line to use for alarm interrupts') + int_pin = Param.X86IntPin('Pin to signal RTC alarm interrupts to') diff --git a/src/dev/x86/I8259.py b/src/dev/x86/I8259.py index 19670dde9..d241b092a 100644 --- a/src/dev/x86/I8259.py +++ b/src/dev/x86/I8259.py @@ -29,9 +29,20 @@ from m5.params import * from m5.proxy import * from Device import BasicPioDevice +from X86IntPin import X86IntPin + +class X86I8259CascadeMode(Enum): + map = {'I8259Master' : 0, + 'I8259Slave' : 1, + 'I8259Single' : 2 + } class I8259(BasicPioDevice): type = 'I8259' cxx_class='X86ISA::I8259' pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") - master = Param.I8259('The master PIC this PIC is cascaded with, if any') + output = Param.X86IntPin('The pin this I8259 drives') + mode = Param.X86I8259CascadeMode('How this I8259 is cascaded') + + def pin(self, line): + return X86IntPin(device=self, line=line) diff --git a/src/dev/x86/PC.py b/src/dev/x86/PC.py index d3d3118c6..e14c4cc9c 100644 --- a/src/dev/x86/PC.py +++ b/src/dev/x86/PC.py @@ -49,9 +49,10 @@ class PC(Platform): pciconfig = PciConfigAll() south_bridge = SouthBridge() - pic1 = I8259(pio_addr=x86IOAddress(0x20)) - pic2 = I8259(pio_addr=x86IOAddress(0xA0), master=pic1) - cmos = Cmos(pio_addr=x86IOAddress(0x70), i8259=pic2) + pic1 = I8259(pio_addr=x86IOAddress(0x20), mode='I8259Master') + pic2 = I8259(pio_addr=x86IOAddress(0xA0), + mode='I8259Slave', output=pic1.pin(2)) + cmos = Cmos(pio_addr=x86IOAddress(0x70), int_pin=pic2.pin(0)) # "Non-existant" port used for timing purposes by the linux kernel i_dont_exist = IsaFake(pio_addr=x86IOAddress(0x80), pio_size=1) diff --git a/src/dev/x86/cmos.cc b/src/dev/x86/cmos.cc index d4ec58ddb..c88592870 100644 --- a/src/dev/x86/cmos.cc +++ b/src/dev/x86/cmos.cc @@ -29,13 +29,14 @@ */ #include "dev/x86/cmos.hh" -#include "dev/x86/i8259.hh" +#include "dev/x86/intdev.hh" #include "mem/packet_access.hh" void X86ISA::Cmos::X86RTC::handleEvent() { - i8259->signalInterrupt(intLine); + assert(intPin); + intPin->signalInterrupt(); } Tick diff --git a/src/dev/x86/cmos.hh b/src/dev/x86/cmos.hh index 337fb8b02..45fb9e8f2 100644 --- a/src/dev/x86/cmos.hh +++ b/src/dev/x86/cmos.hh @@ -38,7 +38,7 @@ namespace X86ISA { -class I8259; +class IntPin; class Cmos : public BasicPioDevice { @@ -57,13 +57,11 @@ class Cmos : public BasicPioDevice class X86RTC : public MC146818 { protected: - I8259 * i8259; - int intLine; + IntPin * intPin; public: X86RTC(EventManager *em, const std::string &n, const struct tm time, - bool bcd, Tick frequency, I8259 *_i8259, int _intLine) : - MC146818(em, n, time, bcd, frequency), - i8259(_i8259), intLine(_intLine) + bool bcd, Tick frequency, IntPin * _intPin) : + MC146818(em, n, time, bcd, frequency), intPin(_intPin) { } protected: @@ -74,8 +72,7 @@ class Cmos : public BasicPioDevice typedef CmosParams Params; Cmos(const Params *p) : BasicPioDevice(p), latency(p->pio_latency), - rtc(this, "rtc", p->time, true, ULL(5000000000), - p->i8259, p->int_line) + rtc(this, "rtc", p->time, true, ULL(5000000000), p->int_pin) { pioSize = 2; memset(regs, 0, numRegs * sizeof(uint8_t)); diff --git a/src/dev/x86/i8259.cc b/src/dev/x86/i8259.cc index 2dd6caaff..dbc8ab768 100644 --- a/src/dev/x86/i8259.cc +++ b/src/dev/x86/i8259.cc @@ -139,7 +139,7 @@ X86ISA::I8259::write(PacketPtr pkt) break; case 0x2: DPRINTF(I8259, "Received initialization command word 3.\n"); - if (master == NULL) { + if (mode == Enums::I8259Master) { DPRINTF(I8259, "Slaves attached to IRQs:%s%s%s%s%s%s%s%s\n", bits(val, 0) ? " 0" : "", bits(val, 1) ? " 1" : "", @@ -192,9 +192,14 @@ X86ISA::I8259::signalInterrupt(int line) fatal("Line number %d doesn't exist. The max is 7.\n"); if (bits(IMR, line)) { DPRINTF(I8259, "Interrupt %d was masked.\n", line); - } else if (master != NULL) { - DPRINTF(I8259, "Propogating interrupt to master.\n"); - master->signalInterrupt(cascadeBits); + } else { + if (output) { + DPRINTF(I8259, "Propogating interrupt.\n"); + output->signalInterrupt(); + } else { + warn("Received interrupt but didn't have " + "anyone to tell about it.\n"); + } } } diff --git a/src/dev/x86/i8259.hh b/src/dev/x86/i8259.hh index c51ab1a6a..f38644222 100644 --- a/src/dev/x86/i8259.hh +++ b/src/dev/x86/i8259.hh @@ -32,16 +32,19 @@ #define __DEV_X86_I8259_HH__ #include "dev/io_device.hh" +#include "dev/x86/intdev.hh" #include "params/I8259.hh" +#include "enums/X86I8259CascadeMode.hh" namespace X86ISA { -class I8259 : public BasicPioDevice +class I8259 : public BasicPioDevice, public IntDev { protected: Tick latency; - I8259 *master; + IntPin *output; + Enums::X86I8259CascadeMode mode; // Interrupt Request Register uint8_t IRR; @@ -71,13 +74,11 @@ class I8259 : public BasicPioDevice return dynamic_cast(_params); } - I8259(Params * p) : BasicPioDevice(p) + I8259(Params * p) : BasicPioDevice(p), latency(p->pio_latency), + output(p->output), mode(p->mode), readIRR(true), + initControlWord(0) { pioSize = 2; - initControlWord = 0; - readIRR = true; - latency = p->pio_latency; - master = p->master; } Tick read(PacketPtr pkt); -- cgit v1.2.3 From a6600fdd8885f9765c859935a5c97d9017653745 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 11 Oct 2008 01:49:39 -0700 Subject: Devices: Make the Intel8254Timer device only use pointers to its counters. --- src/dev/alpha/tsunami_io.cc | 14 +++++++------- src/dev/intel_8254_timer.cc | 34 ++++++++++++++++++++-------------- src/dev/intel_8254_timer.hh | 31 ++++++++++++++++++++++++++----- src/dev/x86/pc.cc | 4 ++-- src/dev/x86/south_bridge/i8254.cc | 12 ++++++------ src/dev/x86/south_bridge/speaker.cc | 2 +- 6 files changed, 62 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/dev/alpha/tsunami_io.cc b/src/dev/alpha/tsunami_io.cc index 2aaf323a2..9c88904e3 100644 --- a/src/dev/alpha/tsunami_io.cc +++ b/src/dev/alpha/tsunami_io.cc @@ -114,19 +114,19 @@ TsunamiIO::read(PacketPtr pkt) pkt->set(0x00); break; case TSDEV_TMR0_DATA: - pkt->set(pitimer.counter0.read()); + pkt->set(pitimer.readCounter(0)); break; case TSDEV_TMR1_DATA: - pkt->set(pitimer.counter1.read()); + pkt->set(pitimer.readCounter(1)); break; case TSDEV_TMR2_DATA: - pkt->set(pitimer.counter2.read()); + pkt->set(pitimer.readCounter(2)); break; case TSDEV_RTC_DATA: pkt->set(rtc.readData(rtcAddr)); break; case TSDEV_CTRL_PORTB: - if (pitimer.counter2.outputHigh()) + if (pitimer.outputHigh(2)) pkt->set(PORTB_SPKR_HIGH); else pkt->set(0x00); @@ -189,13 +189,13 @@ TsunamiIO::write(PacketPtr pkt) mode2 = pkt->get(); break; case TSDEV_TMR0_DATA: - pitimer.counter0.write(pkt->get()); + pitimer.writeCounter(0, pkt->get()); break; case TSDEV_TMR1_DATA: - pitimer.counter1.write(pkt->get()); + pitimer.writeCounter(1, pkt->get()); break; case TSDEV_TMR2_DATA: - pitimer.counter2.write(pkt->get()); + pitimer.writeCounter(2, pkt->get()); break; case TSDEV_TMR_CTRL: pitimer.writeControl(pkt->get()); diff --git a/src/dev/intel_8254_timer.cc b/src/dev/intel_8254_timer.cc index 27f55fd92..35fbd9c38 100644 --- a/src/dev/intel_8254_timer.cc +++ b/src/dev/intel_8254_timer.cc @@ -35,15 +35,21 @@ using namespace std; -Intel8254Timer::Intel8254Timer(EventManager *em, const string &name) - : EventManager(em), _name(name), - counter0(this, name + ".counter0"), - counter1(this, name + ".counter1"), - counter2(this, name + ".counter2") +Intel8254Timer::Intel8254Timer(EventManager *em, const string &name, + Counter *counter0, Counter *counter1, Counter *counter2) : + EventManager(em), _name(name) { - counter[0] = &counter0; - counter[1] = &counter0; - counter[2] = &counter0; + counter[0] = counter0; + counter[1] = counter1; + counter[2] = counter2; +} + +Intel8254Timer::Intel8254Timer(EventManager *em, const string &name) : + EventManager(em), _name(name) +{ + counter[0] = new Counter(this, name + ".counter0"); + counter[1] = new Counter(this, name + ".counter1"); + counter[2] = new Counter(this, name + ".counter2"); } void @@ -67,9 +73,9 @@ void Intel8254Timer::serialize(const string &base, ostream &os) { // serialize the counters - counter0.serialize(base + ".counter0", os); - counter1.serialize(base + ".counter1", os); - counter2.serialize(base + ".counter2", os); + counter[0]->serialize(base + ".counter0", os); + counter[1]->serialize(base + ".counter1", os); + counter[2]->serialize(base + ".counter2", os); } void @@ -77,9 +83,9 @@ Intel8254Timer::unserialize(const string &base, Checkpoint *cp, const string §ion) { // unserialze the counters - counter0.unserialize(base + ".counter0", cp, section); - counter1.unserialize(base + ".counter1", cp, section); - counter2.unserialize(base + ".counter2", cp, section); + counter[0]->unserialize(base + ".counter0", cp, section); + counter[1]->unserialize(base + ".counter1", cp, section); + counter[2]->unserialize(base + ".counter2", cp, section); } Intel8254Timer::Counter::Counter(Intel8254Timer *p, const string &name) diff --git a/src/dev/intel_8254_timer.hh b/src/dev/intel_8254_timer.hh index 439432aed..9391b0f9e 100644 --- a/src/dev/intel_8254_timer.hh +++ b/src/dev/intel_8254_timer.hh @@ -44,6 +44,7 @@ /** Programmable Interval Timer (Intel 8254) */ class Intel8254Timer : public EventManager { + protected: BitUnion8(CtrlReg) Bitfield<7, 6> sel; Bitfield<5, 4> rw; @@ -173,7 +174,7 @@ class Intel8254Timer : public EventManager const std::string §ion); }; - private: + protected: std::string _name; const std::string &name() const { return _name; } @@ -181,16 +182,36 @@ class Intel8254Timer : public EventManager Counter *counter[3]; public: - /** Public way to access individual counters (avoid array accesses) */ - Counter counter0; - Counter counter1; - Counter counter2; + + Intel8254Timer(EventManager *em, const std::string &name, + Counter *counter0, Counter *counter1, Counter *counter2); Intel8254Timer(EventManager *em, const std::string &name); /** Write control word */ void writeControl(const CtrlReg data); + uint8_t + readCounter(unsigned int num) + { + assert(num < 3); + return counter[num]->read(); + } + + void + writeCounter(unsigned int num, const uint8_t data) + { + assert(num < 3); + counter[num]->write(data); + } + + bool + outputHigh(unsigned int num) + { + assert(num < 3); + return counter[num]->outputHigh(); + } + /** * Serialize this object to the given output stream. * @param base The base name of the counter object. diff --git a/src/dev/x86/pc.cc b/src/dev/x86/pc.cc index d04529ab9..3de28bce5 100644 --- a/src/dev/x86/pc.cc +++ b/src/dev/x86/pc.cc @@ -64,8 +64,8 @@ PC::init() //Timer 0, latch command timer.writeControl(0x00); //Write a 16 bit count of 0 - timer.counter0.write(0); - timer.counter0.write(0); + timer.writeCounter(0, 0); + timer.writeCounter(0, 0); } Tick diff --git a/src/dev/x86/south_bridge/i8254.cc b/src/dev/x86/south_bridge/i8254.cc index 7c3501c37..c9c0d625a 100644 --- a/src/dev/x86/south_bridge/i8254.cc +++ b/src/dev/x86/south_bridge/i8254.cc @@ -38,13 +38,13 @@ X86ISA::I8254::read(PacketPtr pkt) switch(pkt->getAddr() - addrRange.start) { case 0x0: - pkt->set(pit.counter0.read()); + pkt->set(pit.readCounter(0)); break; case 0x1: - pkt->set(pit.counter1.read()); + pkt->set(pit.readCounter(1)); break; case 0x2: - pkt->set(pit.counter2.read()); + pkt->set(pit.readCounter(2)); break; case 0x3: pkt->set(uint8_t(-1)); @@ -62,13 +62,13 @@ X86ISA::I8254::write(PacketPtr pkt) switch(pkt->getAddr() - addrRange.start) { case 0x0: - pit.counter0.write(pkt->get()); + pit.writeCounter(0, pkt->get()); break; case 0x1: - pit.counter1.write(pkt->get()); + pit.writeCounter(1, pkt->get()); break; case 0x2: - pit.counter2.write(pkt->get()); + pit.writeCounter(2, pkt->get()); break; case 0x3: pit.writeControl(pkt->get()); diff --git a/src/dev/x86/south_bridge/speaker.cc b/src/dev/x86/south_bridge/speaker.cc index 784c9504b..59a86c634 100644 --- a/src/dev/x86/south_bridge/speaker.cc +++ b/src/dev/x86/south_bridge/speaker.cc @@ -39,7 +39,7 @@ X86ISA::Speaker::read(PacketPtr pkt) { assert(pkt->getAddr() == addrRange.start); assert(pkt->getSize() == 1); - controlVal.timer = timer->pit.counter2.outputHigh() ? 1 : 0; + controlVal.timer = timer->pit.outputHigh(2) ? 1 : 0; DPRINTF(PCSpeaker, "Reading from speaker device: gate %s, speaker %s, output %s.\n", controlVal.gate ? "on" : "off", -- cgit v1.2.3 From bc2217eefc8db831b72dfdcae7ecc9bd95a31c3c Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 11 Oct 2008 02:16:11 -0700 Subject: X86: Change I8254 and PCSpeaker devices from subdevices to SimObjects and eliminate subdevices. --HG-- rename : src/dev/x86/south_bridge/i8254.cc => src/dev/x86/i8254.cc rename : src/dev/x86/south_bridge/i8254.hh => src/dev/x86/i8254.hh rename : src/dev/x86/south_bridge/speaker.cc => src/dev/x86/speaker.cc rename : src/dev/x86/south_bridge/speaker.hh => src/dev/x86/speaker.hh --- src/dev/x86/I8254.py | 37 ++++++++++++ src/dev/x86/PC.py | 11 +--- src/dev/x86/PcSpeaker.py | 37 ++++++++++++ src/dev/x86/SConscript | 7 +++ src/dev/x86/i8254.cc | 69 +++++++++++++++++++++++ src/dev/x86/i8254.hh | 96 ++++++++++++++++++++++++++++++++ src/dev/x86/pc.cc | 5 +- src/dev/x86/pc.hh | 4 +- src/dev/x86/south_bridge/SConscript | 6 -- src/dev/x86/south_bridge/SouthBridge.py | 38 ++++++++++++- src/dev/x86/south_bridge/i8254.cc | 80 -------------------------- src/dev/x86/south_bridge/i8254.hh | 66 ---------------------- src/dev/x86/south_bridge/south_bridge.cc | 44 ++------------- src/dev/x86/south_bridge/south_bridge.hh | 41 ++++++-------- src/dev/x86/south_bridge/speaker.cc | 70 ----------------------- src/dev/x86/south_bridge/speaker.hh | 74 ------------------------ src/dev/x86/south_bridge/sub_device.hh | 79 -------------------------- src/dev/x86/speaker.cc | 77 +++++++++++++++++++++++++ src/dev/x86/speaker.hh | 79 ++++++++++++++++++++++++++ 19 files changed, 465 insertions(+), 455 deletions(-) create mode 100644 src/dev/x86/I8254.py create mode 100644 src/dev/x86/PcSpeaker.py create mode 100644 src/dev/x86/i8254.cc create mode 100644 src/dev/x86/i8254.hh delete mode 100644 src/dev/x86/south_bridge/i8254.cc delete mode 100644 src/dev/x86/south_bridge/i8254.hh delete mode 100644 src/dev/x86/south_bridge/speaker.cc delete mode 100644 src/dev/x86/south_bridge/speaker.hh delete mode 100644 src/dev/x86/south_bridge/sub_device.hh create mode 100644 src/dev/x86/speaker.cc create mode 100644 src/dev/x86/speaker.hh (limited to 'src') diff --git a/src/dev/x86/I8254.py b/src/dev/x86/I8254.py new file mode 100644 index 000000000..d67d04e86 --- /dev/null +++ b/src/dev/x86/I8254.py @@ -0,0 +1,37 @@ +# Copyright (c) 2008 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +from m5.params import * +from m5.proxy import * +from Device import BasicPioDevice + +class I8254(BasicPioDevice): + type = 'I8254' + cxx_class = 'X86ISA::I8254' + pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") + int_pin = Param.X86IntPin('Pin to signal timer interrupts to') diff --git a/src/dev/x86/PC.py b/src/dev/x86/PC.py index e14c4cc9c..28a722be9 100644 --- a/src/dev/x86/PC.py +++ b/src/dev/x86/PC.py @@ -29,10 +29,8 @@ from m5.params import * from m5.proxy import * -from Cmos import Cmos from Device import IsaFake from Pci import PciConfigAll -from I8259 import I8259 from Platform import Platform from SouthBridge import SouthBridge from Terminal import Terminal @@ -49,10 +47,6 @@ class PC(Platform): pciconfig = PciConfigAll() south_bridge = SouthBridge() - pic1 = I8259(pio_addr=x86IOAddress(0x20), mode='I8259Master') - pic2 = I8259(pio_addr=x86IOAddress(0xA0), - mode='I8259Slave', output=pic1.pin(2)) - cmos = Cmos(pio_addr=x86IOAddress(0x70), int_pin=pic2.pin(0)) # "Non-existant" port used for timing purposes by the linux kernel i_dont_exist = IsaFake(pio_addr=x86IOAddress(0x80), pio_size=1) @@ -68,10 +62,7 @@ class PC(Platform): com_1.terminal = terminal def attachIO(self, bus): - self.south_bridge.pio = bus.port - self.cmos.pio = bus.port - self.pic1.pio = bus.port - self.pic2.pio = bus.port + self.south_bridge.attachIO(bus) self.i_dont_exist.pio = bus.port self.behind_pci.pio = bus.port self.com_1.pio = bus.port diff --git a/src/dev/x86/PcSpeaker.py b/src/dev/x86/PcSpeaker.py new file mode 100644 index 000000000..7ca62ec1e --- /dev/null +++ b/src/dev/x86/PcSpeaker.py @@ -0,0 +1,37 @@ +# Copyright (c) 2008 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +from m5.params import * +from m5.proxy import * +from Device import BasicPioDevice + +class PcSpeaker(BasicPioDevice): + type = 'PcSpeaker' + cxx_class = 'X86ISA::Speaker' + pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") + i8254 = Param.I8254('Timer that drives the speaker') diff --git a/src/dev/x86/SConscript b/src/dev/x86/SConscript index 71e5a9528..0e2bf0be6 100644 --- a/src/dev/x86/SConscript +++ b/src/dev/x86/SConscript @@ -42,5 +42,12 @@ if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'x86': Source('i8259.cc') TraceFlag('I8259', 'Accesses to the I8259 PIC devices') + SimObject('I8254.py') + Source('i8254.cc') + + SimObject('PcSpeaker.py') + Source('speaker.cc') + TraceFlag('PcSpeaker') + SimObject('X86IntPin.py') Source('intdev.cc') diff --git a/src/dev/x86/i8254.cc b/src/dev/x86/i8254.cc new file mode 100644 index 000000000..cc7c48980 --- /dev/null +++ b/src/dev/x86/i8254.cc @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "dev/x86/i8254.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" + +Tick +X86ISA::I8254::read(PacketPtr pkt) +{ + assert(pkt->getSize() == 1); + Addr offset = pkt->getAddr() - pioAddr; + if (offset < 3) { + pkt->set(pit.readCounter(offset)); + } else if (offset == 3) { + pkt->set(uint8_t(-1)); + } else { + panic("Read from undefined i8254 register.\n"); + } + return latency; +} + +Tick +X86ISA::I8254::write(PacketPtr pkt) +{ + assert(pkt->getSize() == 1); + Addr offset = pkt->getAddr() - pioAddr; + if (offset < 3) { + pit.writeCounter(offset, pkt->get()); + } else if (offset == 3) { + pit.writeControl(pkt->get()); + } else { + panic("Write to undefined i8254 register.\n"); + } + return latency; +} + +X86ISA::I8254 * +I8254Params::create() +{ + return new X86ISA::I8254(this); +} diff --git a/src/dev/x86/i8254.hh b/src/dev/x86/i8254.hh new file mode 100644 index 000000000..9528013c8 --- /dev/null +++ b/src/dev/x86/i8254.hh @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __DEV_X86_I8254_HH__ +#define __DEV_X86_I8254_HH__ + +#include "dev/intel_8254_timer.hh" +#include "dev/io_device.hh" +#include "params/I8254.hh" + +namespace X86ISA +{ + +class IntPin; + +class I8254 : public BasicPioDevice +{ + protected: + Tick latency; + Intel8254Timer pit; + + IntPin *intPin; + + public: + typedef I8254Params Params; + + const Params * + params() const + { + return dynamic_cast(_params); + } + + I8254(Params *p) : BasicPioDevice(p), latency(p->pio_latency), + pit(this, p->name), intPin(p->int_pin) + { + pioSize = 4; + } + Tick read(PacketPtr pkt); + + Tick write(PacketPtr pkt); + + bool + outputHigh(unsigned int num) + { + return pit.outputHigh(num); + } + + uint8_t + readCounter(unsigned int num) + { + return pit.readCounter(num); + } + + void + writeCounter(unsigned int num, const uint8_t data) + { + pit.writeCounter(num, data); + } + + void + writeControl(uint8_t val) + { + pit.writeControl(val); + } +}; + +}; // namespace X86ISA + +#endif //__DEV_X86_SOUTH_BRIDGE_I8254_HH__ diff --git a/src/dev/x86/pc.cc b/src/dev/x86/pc.cc index 3de28bce5..0cfd2b0f9 100644 --- a/src/dev/x86/pc.cc +++ b/src/dev/x86/pc.cc @@ -37,10 +37,11 @@ #include #include "arch/x86/x86_traits.hh" -#include "dev/intel_8254_timer.hh" #include "cpu/intr_control.hh" #include "dev/terminal.hh" +#include "dev/x86/i8254.hh" #include "dev/x86/pc.hh" +#include "dev/x86/south_bridge/south_bridge.hh" #include "sim/system.hh" using namespace std; @@ -58,7 +59,7 @@ void PC::init() { assert(southBridge); - Intel8254Timer & timer = southBridge->pit.pit; + I8254 & timer = *southBridge->pit; //Timer 0, mode 2, no bcd, 16 bit count timer.writeControl(0x34); //Timer 0, latch command diff --git a/src/dev/x86/pc.hh b/src/dev/x86/pc.hh index 3a042fc46..418a2e830 100644 --- a/src/dev/x86/pc.hh +++ b/src/dev/x86/pc.hh @@ -38,18 +38,18 @@ #define __DEV_PC_HH__ #include "dev/platform.hh" -#include "dev/x86/south_bridge/south_bridge.hh" #include "params/PC.hh" class IdeController; class System; +class SouthBridge; class PC : public Platform { public: /** Pointer to the system */ System *system; - SouthBridge * southBridge; + SouthBridge *southBridge; public: typedef PCParams Params; diff --git a/src/dev/x86/south_bridge/SConscript b/src/dev/x86/south_bridge/SConscript index c4e31bb8c..639298ca1 100644 --- a/src/dev/x86/south_bridge/SConscript +++ b/src/dev/x86/south_bridge/SConscript @@ -34,9 +34,3 @@ if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'x86': # Main device SimObject('SouthBridge.py') Source('south_bridge.cc') - - # Sub devices - Source('i8254.cc') - Source('speaker.cc') - - TraceFlag('PCSpeaker') diff --git a/src/dev/x86/south_bridge/SouthBridge.py b/src/dev/x86/south_bridge/SouthBridge.py index bec3c4223..2f4b8438a 100644 --- a/src/dev/x86/south_bridge/SouthBridge.py +++ b/src/dev/x86/south_bridge/SouthBridge.py @@ -28,8 +28,42 @@ from m5.params import * from m5.proxy import * -from Device import PioDevice +from Cmos import Cmos +from I8254 import I8254 +from I8259 import I8259 +from PcSpeaker import PcSpeaker +from m5.SimObject import SimObject -class SouthBridge(PioDevice): +def x86IOAddress(port): + IO_address_space_base = 0x8000000000000000 + return IO_address_space_base + port; + +class SouthBridge(SimObject): type = 'SouthBridge' pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") + platform = Param.Platform(Parent.any, "Platform this device is part of") + + _pic1 = I8259(pio_addr=x86IOAddress(0x20), mode='I8259Master') + _pic2 = I8259(pio_addr=x86IOAddress(0xA0), mode='I8259Slave') + _cmos = Cmos(pio_addr=x86IOAddress(0x70)) + _pit = I8254(pio_addr=x86IOAddress(0x40)) + _speaker = PcSpeaker(pio_addr=x86IOAddress(0x61)) + + pic1 = Param.I8259(_pic1, "Master PIC") + pic2 = Param.I8259(_pic2, "Slave PIC") + cmos = Param.Cmos(_cmos, "CMOS memory and real time clock device") + pit = Param.I8254(_pit, "Programmable interval timer") + speaker = Param.PcSpeaker(_speaker, "PC speaker") + + def attachIO(self, bus): + # Make internal connections + self.pic2.output = self.pic1.pin(2) + self.cmos.int_pin = self.pic2.pin(0) + self.pit.int_pin = self.pic1.pin(0) + self.speaker.i8254 = self.pit + # Connect to the bus + self.cmos.pio = bus.port + self.pic1.pio = bus.port + self.pic2.pio = bus.port + self.pit.pio = bus.port + self.speaker.pio = bus.port diff --git a/src/dev/x86/south_bridge/i8254.cc b/src/dev/x86/south_bridge/i8254.cc deleted file mode 100644 index c9c0d625a..000000000 --- a/src/dev/x86/south_bridge/i8254.cc +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2008 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#include "dev/x86/south_bridge/i8254.hh" -#include "mem/packet_access.hh" - -Tick -X86ISA::I8254::read(PacketPtr pkt) -{ - assert(pkt->getSize() == 1); - switch(pkt->getAddr() - addrRange.start) - { - case 0x0: - pkt->set(pit.readCounter(0)); - break; - case 0x1: - pkt->set(pit.readCounter(1)); - break; - case 0x2: - pkt->set(pit.readCounter(2)); - break; - case 0x3: - pkt->set(uint8_t(-1)); - break; - default: - panic("Read from undefined i8254 register.\n"); - } - return latency; -} - -Tick -X86ISA::I8254::write(PacketPtr pkt) -{ - assert(pkt->getSize() == 1); - switch(pkt->getAddr() - addrRange.start) - { - case 0x0: - pit.writeCounter(0, pkt->get()); - break; - case 0x1: - pit.writeCounter(1, pkt->get()); - break; - case 0x2: - pit.writeCounter(2, pkt->get()); - break; - case 0x3: - pit.writeControl(pkt->get()); - break; - default: - panic("Write to undefined i8254 register.\n"); - } - return latency; -} diff --git a/src/dev/x86/south_bridge/i8254.hh b/src/dev/x86/south_bridge/i8254.hh deleted file mode 100644 index b6dd388a7..000000000 --- a/src/dev/x86/south_bridge/i8254.hh +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2008 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#ifndef __DEV_X86_SOUTH_BRIDGE_I8254_HH__ -#define __DEV_X86_SOUTH_BRIDGE_I8254_HH__ - -#include "arch/x86/x86_traits.hh" -#include "base/range.hh" -#include "dev/intel_8254_timer.hh" -#include "dev/x86/south_bridge/sub_device.hh" - -#include - -namespace X86ISA -{ - -class I8254 : public SubDevice -{ - public: - Intel8254Timer pit; - - I8254(EventManager *em, const std::string &name) : pit(em, name) - {} - I8254(EventManager *em, const std::string &name, Tick _latency) : - SubDevice(_latency), pit(em, name) - {} - I8254(EventManager *em, const std::string &name, - Addr start, Addr size, Tick _latency) : - SubDevice(start, size, _latency), pit(em, name) - {} - - Tick read(PacketPtr pkt); - - Tick write(PacketPtr pkt); -}; - -}; // namespace X86ISA - -#endif //__DEV_X86_SOUTH_BRIDGE_I8254_HH__ diff --git a/src/dev/x86/south_bridge/south_bridge.cc b/src/dev/x86/south_bridge/south_bridge.cc index 0e9a63a74..12f4657b0 100644 --- a/src/dev/x86/south_bridge/south_bridge.cc +++ b/src/dev/x86/south_bridge/south_bridge.cc @@ -28,51 +28,17 @@ * Authors: Gabe Black */ -#include "arch/x86/x86_traits.hh" -#include "base/range.hh" +#include + #include "dev/x86/pc.hh" #include "dev/x86/south_bridge/south_bridge.hh" using namespace X86ISA; -void -SouthBridge::addDevice(X86ISA::SubDevice & sub) -{ - rangeList.push_back(sub.addrRange); - rangeMap.insert(sub.addrRange, &sub); -} - -void -SouthBridge::addressRanges(AddrRangeList &range_list) -{ - range_list = rangeList; -} - -Tick -SouthBridge::read(PacketPtr pkt) +SouthBridge::SouthBridge(const Params *p) : SimObject(p), + platform(p->platform), pit(p->pit), pic1(p->pic1), pic2(p->pic2), + cmos(p->cmos), speaker(p->speaker) { - RangeMapIt sub = - rangeMap.find(RangeSize(pkt->getAddr(), 1)); - assert(sub != rangeMap.end()); - return sub->second->read(pkt); -} - -Tick -SouthBridge::write(PacketPtr pkt) -{ - RangeMapIt sub = - rangeMap.find(RangeSize(pkt->getAddr(), 1)); - assert(sub != rangeMap.end()); - return sub->second->write(pkt); -} - -SouthBridge::SouthBridge(const Params *p) : PioDevice(p), - pit(this, p->name + ".pit", 0x40, 4, p->pio_latency), - speaker(&pit, 0x61, 1, p->pio_latency) -{ - addDevice(pit); - addDevice(speaker); - // Let the platform know where we are PC * pc = dynamic_cast(platform); assert(pc); diff --git a/src/dev/x86/south_bridge/south_bridge.hh b/src/dev/x86/south_bridge/south_bridge.hh index 171589cf3..9e7963a7b 100644 --- a/src/dev/x86/south_bridge/south_bridge.hh +++ b/src/dev/x86/south_bridge/south_bridge.hh @@ -31,39 +31,30 @@ #ifndef __DEV_X86_SOUTH_BRIDGE_SOUTH_BRIDGE_HH__ #define __DEV_X86_SOUTH_BRIDGE_SOUTH_BRIDGE_HH__ -#include "base/range_map.hh" -#include "dev/io_device.hh" -#include "dev/x86/south_bridge/i8254.hh" -#include "dev/x86/south_bridge/speaker.hh" -#include "dev/x86/south_bridge/sub_device.hh" +#include "sim/sim_object.hh" #include "params/SouthBridge.hh" -class SouthBridge : public PioDevice +namespace X86ISA { - protected: - AddrRangeList rangeList; - - typedef range_map RangeMap; - typedef RangeMap::iterator RangeMapIt; - RangeMap rangeMap; - + class I8254; + class I8259; + class Cmos; + class Speaker; +} - void addDevice(X86ISA::SubDevice &); +class SouthBridge : public SimObject +{ + protected: + Platform * platform; public: - // I8254 Programmable Interval Timer - X86ISA::I8254 pit; - - // PC speaker - X86ISA::Speaker speaker; + X86ISA::I8254 * pit; + X86ISA::I8259 * pic1; + X86ISA::I8259 * pic2; + X86ISA::Cmos * cmos; + X86ISA::Speaker * speaker; public: - - void addressRanges(AddrRangeList &range_list); - - Tick read(PacketPtr pkt); - Tick write(PacketPtr pkt); - typedef SouthBridgeParams Params; SouthBridge(const Params *p); diff --git a/src/dev/x86/south_bridge/speaker.cc b/src/dev/x86/south_bridge/speaker.cc deleted file mode 100644 index 59a86c634..000000000 --- a/src/dev/x86/south_bridge/speaker.cc +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2008 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#include "base/bitunion.hh" -#include "base/trace.hh" -#include "dev/x86/south_bridge/i8254.hh" -#include "dev/x86/south_bridge/speaker.hh" -#include "mem/packet_access.hh" - -Tick -X86ISA::Speaker::read(PacketPtr pkt) -{ - assert(pkt->getAddr() == addrRange.start); - assert(pkt->getSize() == 1); - controlVal.timer = timer->pit.outputHigh(2) ? 1 : 0; - DPRINTF(PCSpeaker, - "Reading from speaker device: gate %s, speaker %s, output %s.\n", - controlVal.gate ? "on" : "off", - controlVal.speaker ? "on" : "off", - controlVal.timer ? "on" : "off"); - pkt->set((uint8_t)controlVal); - return latency; -} - -Tick -X86ISA::Speaker::write(PacketPtr pkt) -{ - assert(pkt->getAddr() == addrRange.start); - assert(pkt->getSize() == 1); - SpeakerControl val = pkt->get(); - controlVal.gate = val.gate; - //Change the gate value in the timer. - if (!val.gate) - warn("The gate bit of the pc speaker isn't implemented and " - "is always on.\n"); - //This would control whether the timer output is hooked up to a physical - //speaker. Since M5 can't make noise, it's value doesn't actually do - //anything. - controlVal.speaker = val.speaker; - DPRINTF(PCSpeaker, "Writing to speaker device: gate %s, speaker %s.\n", - controlVal.gate ? "on" : "off", controlVal.speaker ? "on" : "off"); - return latency; -} diff --git a/src/dev/x86/south_bridge/speaker.hh b/src/dev/x86/south_bridge/speaker.hh deleted file mode 100644 index 2385b80cc..000000000 --- a/src/dev/x86/south_bridge/speaker.hh +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2008 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#ifndef __DEV_X86_SOUTH_BRIDGE_SPEAKER_HH__ -#define __DEV_X86_SOUTH_BRIDGE_SPEAKER_HH__ - -#include "arch/x86/x86_traits.hh" -#include "base/range.hh" -#include "dev/x86/south_bridge/sub_device.hh" - -namespace X86ISA -{ - -class I8254; - -class Speaker : public SubDevice -{ - protected: - BitUnion8(SpeakerControl) - Bitfield<0> gate; - Bitfield<1> speaker; - Bitfield<5> timer; - EndBitUnion(SpeakerControl) - - SpeakerControl controlVal; - - I8254 * timer; - - public: - - Speaker(I8254 * _timer) : timer(_timer) - {} - Speaker(I8254 * _timer, Tick _latency) : - SubDevice(_latency), timer(_timer) - {} - Speaker(I8254 * _timer, Addr start, Addr size, Tick _latency) : - SubDevice(start, size, _latency), timer(_timer) - {} - - Tick read(PacketPtr pkt); - - Tick write(PacketPtr pkt); -}; - -}; // namespace X86ISA - -#endif //__DEV_X86_SOUTH_BRIDGE_SPEAKER_HH__ diff --git a/src/dev/x86/south_bridge/sub_device.hh b/src/dev/x86/south_bridge/sub_device.hh deleted file mode 100644 index 3cc51bdd9..000000000 --- a/src/dev/x86/south_bridge/sub_device.hh +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#ifndef __DEV_X86_SOUTH_BRIDGE_SUB_DEVICE_HH__ -#define __DEV_X86_SOUTH_BRIDGE_SUB_DEVICE_HH__ - -#include "arch/x86/x86_traits.hh" -#include "base/range.hh" -#include "mem/packet.hh" - -namespace X86ISA -{ - -class SubDevice -{ - public: - - Range addrRange; - Tick latency; - - virtual - ~SubDevice() - {} - - SubDevice() - {} - SubDevice(Tick _latency) : latency(_latency) - {} - SubDevice(Addr start, Addr size, Tick _latency) : - addrRange(RangeSize(x86IOAddress(start), size)), latency(_latency) - {} - - virtual Tick - read(PacketPtr pkt) - { - assert(pkt->getSize() <= 4); - pkt->allocate(); - const uint32_t neg1 = -1; - pkt->setData((uint8_t *)(&neg1)); - return latency; - } - - virtual Tick - write(PacketPtr pkt) - { - return latency; - } -}; - -}; // namespace X86ISA - -#endif //__DEV_X86_SOUTH_BRIDGE_SUB_DEVICE_HH__ diff --git a/src/dev/x86/speaker.cc b/src/dev/x86/speaker.cc new file mode 100644 index 000000000..25014d0c6 --- /dev/null +++ b/src/dev/x86/speaker.cc @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "base/bitunion.hh" +#include "base/trace.hh" +#include "dev/x86/i8254.hh" +#include "dev/x86/speaker.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" + +Tick +X86ISA::Speaker::read(PacketPtr pkt) +{ + assert(pkt->getAddr() == pioAddr); + assert(pkt->getSize() == 1); + controlVal.timer = timer->outputHigh(2) ? 1 : 0; + DPRINTF(PcSpeaker, + "Reading from speaker device: gate %s, speaker %s, output %s.\n", + controlVal.gate ? "on" : "off", + controlVal.speaker ? "on" : "off", + controlVal.timer ? "on" : "off"); + pkt->set((uint8_t)controlVal); + return latency; +} + +Tick +X86ISA::Speaker::write(PacketPtr pkt) +{ + assert(pkt->getAddr() == pioAddr); + assert(pkt->getSize() == 1); + SpeakerControl val = pkt->get(); + controlVal.gate = val.gate; + //Change the gate value in the timer. + if (!val.gate) + warn("The gate bit of the pc speaker isn't implemented and " + "is always on.\n"); + //This would control whether the timer output is hooked up to a physical + //speaker. Since M5 can't make noise, it's value doesn't actually do + //anything. + controlVal.speaker = val.speaker; + DPRINTF(PcSpeaker, "Writing to speaker device: gate %s, speaker %s.\n", + controlVal.gate ? "on" : "off", controlVal.speaker ? "on" : "off"); + return latency; +} + +X86ISA::Speaker * +PcSpeakerParams::create() +{ + return new X86ISA::Speaker(this); +} diff --git a/src/dev/x86/speaker.hh b/src/dev/x86/speaker.hh new file mode 100644 index 000000000..7d28d6cf7 --- /dev/null +++ b/src/dev/x86/speaker.hh @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __DEV_X86_SPEAKER_HH__ +#define __DEV_X86_SPEAKER_HH__ + +#include "base/bitunion.hh" +#include "params/PcSpeaker.hh" + +namespace X86ISA +{ + +class I8254; + +class Speaker : public BasicPioDevice +{ + protected: + Tick latency; + + BitUnion8(SpeakerControl) + Bitfield<0> gate; + Bitfield<1> speaker; + Bitfield<5> timer; + EndBitUnion(SpeakerControl) + + SpeakerControl controlVal; + + I8254 * timer; + + public: + typedef PcSpeakerParams Params; + + const Params * + params() const + { + return dynamic_cast(_params); + } + + Speaker(Params *p) : BasicPioDevice(p), + latency(p->pio_latency), timer(p->i8254) + { + pioSize = 1; + } + + Tick read(PacketPtr pkt); + + Tick write(PacketPtr pkt); +}; + +}; // namespace X86ISA + +#endif //__DEV_X86_SPEAKER_HH__ -- cgit v1.2.3 From 826621eb1722eb557d4c24f79e110fbed09e5fb5 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 11 Oct 2008 02:21:44 -0700 Subject: X86: Bring the South Bridge device into dev/x86 and get rid of south_bridge directory. --HG-- rename : src/dev/x86/south_bridge/SouthBridge.py => src/dev/x86/SouthBridge.py rename : src/dev/x86/south_bridge/south_bridge.cc => src/dev/x86/south_bridge.cc rename : src/dev/x86/south_bridge/south_bridge.hh => src/dev/x86/south_bridge.hh --- src/dev/x86/SConscript | 3 ++ src/dev/x86/SouthBridge.py | 69 ++++++++++++++++++++++++++++++++ src/dev/x86/pc.cc | 2 +- src/dev/x86/south_bridge.cc | 52 ++++++++++++++++++++++++ src/dev/x86/south_bridge.hh | 68 +++++++++++++++++++++++++++++++ src/dev/x86/south_bridge/SConscript | 36 ----------------- src/dev/x86/south_bridge/SouthBridge.py | 69 -------------------------------- src/dev/x86/south_bridge/south_bridge.cc | 52 ------------------------ src/dev/x86/south_bridge/south_bridge.hh | 68 ------------------------------- 9 files changed, 193 insertions(+), 226 deletions(-) create mode 100644 src/dev/x86/SouthBridge.py create mode 100644 src/dev/x86/south_bridge.cc create mode 100644 src/dev/x86/south_bridge.hh delete mode 100644 src/dev/x86/south_bridge/SConscript delete mode 100644 src/dev/x86/south_bridge/SouthBridge.py delete mode 100644 src/dev/x86/south_bridge/south_bridge.cc delete mode 100644 src/dev/x86/south_bridge/south_bridge.hh (limited to 'src') diff --git a/src/dev/x86/SConscript b/src/dev/x86/SConscript index 0e2bf0be6..b71649fdd 100644 --- a/src/dev/x86/SConscript +++ b/src/dev/x86/SConscript @@ -34,6 +34,9 @@ if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'x86': SimObject('PC.py') Source('pc.cc') + SimObject('SouthBridge.py') + Source('south_bridge.cc') + SimObject('Cmos.py') Source('cmos.cc') TraceFlag('CMOS', 'Accesses to CMOS devices') diff --git a/src/dev/x86/SouthBridge.py b/src/dev/x86/SouthBridge.py new file mode 100644 index 000000000..2f4b8438a --- /dev/null +++ b/src/dev/x86/SouthBridge.py @@ -0,0 +1,69 @@ +# Copyright (c) 2008 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +from m5.params import * +from m5.proxy import * +from Cmos import Cmos +from I8254 import I8254 +from I8259 import I8259 +from PcSpeaker import PcSpeaker +from m5.SimObject import SimObject + +def x86IOAddress(port): + IO_address_space_base = 0x8000000000000000 + return IO_address_space_base + port; + +class SouthBridge(SimObject): + type = 'SouthBridge' + pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") + platform = Param.Platform(Parent.any, "Platform this device is part of") + + _pic1 = I8259(pio_addr=x86IOAddress(0x20), mode='I8259Master') + _pic2 = I8259(pio_addr=x86IOAddress(0xA0), mode='I8259Slave') + _cmos = Cmos(pio_addr=x86IOAddress(0x70)) + _pit = I8254(pio_addr=x86IOAddress(0x40)) + _speaker = PcSpeaker(pio_addr=x86IOAddress(0x61)) + + pic1 = Param.I8259(_pic1, "Master PIC") + pic2 = Param.I8259(_pic2, "Slave PIC") + cmos = Param.Cmos(_cmos, "CMOS memory and real time clock device") + pit = Param.I8254(_pit, "Programmable interval timer") + speaker = Param.PcSpeaker(_speaker, "PC speaker") + + def attachIO(self, bus): + # Make internal connections + self.pic2.output = self.pic1.pin(2) + self.cmos.int_pin = self.pic2.pin(0) + self.pit.int_pin = self.pic1.pin(0) + self.speaker.i8254 = self.pit + # Connect to the bus + self.cmos.pio = bus.port + self.pic1.pio = bus.port + self.pic2.pio = bus.port + self.pit.pio = bus.port + self.speaker.pio = bus.port diff --git a/src/dev/x86/pc.cc b/src/dev/x86/pc.cc index 0cfd2b0f9..7c35aebf2 100644 --- a/src/dev/x86/pc.cc +++ b/src/dev/x86/pc.cc @@ -41,7 +41,7 @@ #include "dev/terminal.hh" #include "dev/x86/i8254.hh" #include "dev/x86/pc.hh" -#include "dev/x86/south_bridge/south_bridge.hh" +#include "dev/x86/south_bridge.hh" #include "sim/system.hh" using namespace std; diff --git a/src/dev/x86/south_bridge.cc b/src/dev/x86/south_bridge.cc new file mode 100644 index 000000000..3f68fee18 --- /dev/null +++ b/src/dev/x86/south_bridge.cc @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include + +#include "dev/x86/pc.hh" +#include "dev/x86/south_bridge.hh" + +using namespace X86ISA; + +SouthBridge::SouthBridge(const Params *p) : SimObject(p), + platform(p->platform), pit(p->pit), pic1(p->pic1), pic2(p->pic2), + cmos(p->cmos), speaker(p->speaker) +{ + // Let the platform know where we are + PC * pc = dynamic_cast(platform); + assert(pc); + pc->southBridge = this; +} + +SouthBridge * +SouthBridgeParams::create() +{ + return new SouthBridge(this); +} diff --git a/src/dev/x86/south_bridge.hh b/src/dev/x86/south_bridge.hh new file mode 100644 index 000000000..5677aa8a0 --- /dev/null +++ b/src/dev/x86/south_bridge.hh @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __DEV_X86_SOUTH_BRIDGE_HH__ +#define __DEV_X86_SOUTH_BRIDGE_HH__ + +#include "sim/sim_object.hh" +#include "params/SouthBridge.hh" + +namespace X86ISA +{ + class I8254; + class I8259; + class Cmos; + class Speaker; +} + +class SouthBridge : public SimObject +{ + protected: + Platform * platform; + + public: + X86ISA::I8254 * pit; + X86ISA::I8259 * pic1; + X86ISA::I8259 * pic2; + X86ISA::Cmos * cmos; + X86ISA::Speaker * speaker; + + public: + typedef SouthBridgeParams Params; + SouthBridge(const Params *p); + + const Params * + params() const + { + return dynamic_cast(_params); + } +}; + +#endif //__DEV_X86_SOUTH_BRIDGE_HH__ diff --git a/src/dev/x86/south_bridge/SConscript b/src/dev/x86/south_bridge/SConscript deleted file mode 100644 index 639298ca1..000000000 --- a/src/dev/x86/south_bridge/SConscript +++ /dev/null @@ -1,36 +0,0 @@ -# -*- mode:python -*- - -# Copyright (c) 2008 The Regents of The University of Michigan -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer; -# redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution; -# neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Authors: Gabe Black - -Import('*') - -if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'x86': - # Main device - SimObject('SouthBridge.py') - Source('south_bridge.cc') diff --git a/src/dev/x86/south_bridge/SouthBridge.py b/src/dev/x86/south_bridge/SouthBridge.py deleted file mode 100644 index 2f4b8438a..000000000 --- a/src/dev/x86/south_bridge/SouthBridge.py +++ /dev/null @@ -1,69 +0,0 @@ -# Copyright (c) 2008 The Regents of The University of Michigan -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer; -# redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution; -# neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Authors: Gabe Black - -from m5.params import * -from m5.proxy import * -from Cmos import Cmos -from I8254 import I8254 -from I8259 import I8259 -from PcSpeaker import PcSpeaker -from m5.SimObject import SimObject - -def x86IOAddress(port): - IO_address_space_base = 0x8000000000000000 - return IO_address_space_base + port; - -class SouthBridge(SimObject): - type = 'SouthBridge' - pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") - platform = Param.Platform(Parent.any, "Platform this device is part of") - - _pic1 = I8259(pio_addr=x86IOAddress(0x20), mode='I8259Master') - _pic2 = I8259(pio_addr=x86IOAddress(0xA0), mode='I8259Slave') - _cmos = Cmos(pio_addr=x86IOAddress(0x70)) - _pit = I8254(pio_addr=x86IOAddress(0x40)) - _speaker = PcSpeaker(pio_addr=x86IOAddress(0x61)) - - pic1 = Param.I8259(_pic1, "Master PIC") - pic2 = Param.I8259(_pic2, "Slave PIC") - cmos = Param.Cmos(_cmos, "CMOS memory and real time clock device") - pit = Param.I8254(_pit, "Programmable interval timer") - speaker = Param.PcSpeaker(_speaker, "PC speaker") - - def attachIO(self, bus): - # Make internal connections - self.pic2.output = self.pic1.pin(2) - self.cmos.int_pin = self.pic2.pin(0) - self.pit.int_pin = self.pic1.pin(0) - self.speaker.i8254 = self.pit - # Connect to the bus - self.cmos.pio = bus.port - self.pic1.pio = bus.port - self.pic2.pio = bus.port - self.pit.pio = bus.port - self.speaker.pio = bus.port diff --git a/src/dev/x86/south_bridge/south_bridge.cc b/src/dev/x86/south_bridge/south_bridge.cc deleted file mode 100644 index 12f4657b0..000000000 --- a/src/dev/x86/south_bridge/south_bridge.cc +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2008 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#include - -#include "dev/x86/pc.hh" -#include "dev/x86/south_bridge/south_bridge.hh" - -using namespace X86ISA; - -SouthBridge::SouthBridge(const Params *p) : SimObject(p), - platform(p->platform), pit(p->pit), pic1(p->pic1), pic2(p->pic2), - cmos(p->cmos), speaker(p->speaker) -{ - // Let the platform know where we are - PC * pc = dynamic_cast(platform); - assert(pc); - pc->southBridge = this; -} - -SouthBridge * -SouthBridgeParams::create() -{ - return new SouthBridge(this); -} diff --git a/src/dev/x86/south_bridge/south_bridge.hh b/src/dev/x86/south_bridge/south_bridge.hh deleted file mode 100644 index 9e7963a7b..000000000 --- a/src/dev/x86/south_bridge/south_bridge.hh +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2008 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#ifndef __DEV_X86_SOUTH_BRIDGE_SOUTH_BRIDGE_HH__ -#define __DEV_X86_SOUTH_BRIDGE_SOUTH_BRIDGE_HH__ - -#include "sim/sim_object.hh" -#include "params/SouthBridge.hh" - -namespace X86ISA -{ - class I8254; - class I8259; - class Cmos; - class Speaker; -} - -class SouthBridge : public SimObject -{ - protected: - Platform * platform; - - public: - X86ISA::I8254 * pit; - X86ISA::I8259 * pic1; - X86ISA::I8259 * pic2; - X86ISA::Cmos * cmos; - X86ISA::Speaker * speaker; - - public: - typedef SouthBridgeParams Params; - SouthBridge(const Params *p); - - const Params * - params() const - { - return dynamic_cast(_params); - } -}; - -#endif //__DEV_X86_SOUTH_BRIDGE_SOUTH_BRIDGE_HH__ -- cgit v1.2.3 From 3af428606ad35e2cd40d5d1d39010ff732bfee4f Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 11 Oct 2008 02:23:40 -0700 Subject: X86: Rename the PC device to Pc. --HG-- rename : src/dev/x86/PC.py => src/dev/x86/Pc.py --- src/dev/x86/PC.py | 71 --------------------------------------------- src/dev/x86/Pc.py | 71 +++++++++++++++++++++++++++++++++++++++++++++ src/dev/x86/SConscript | 2 +- src/dev/x86/pc.cc | 24 +++++++-------- src/dev/x86/pc.hh | 8 ++--- src/dev/x86/south_bridge.cc | 2 +- 6 files changed, 89 insertions(+), 89 deletions(-) delete mode 100644 src/dev/x86/PC.py create mode 100644 src/dev/x86/Pc.py (limited to 'src') diff --git a/src/dev/x86/PC.py b/src/dev/x86/PC.py deleted file mode 100644 index 28a722be9..000000000 --- a/src/dev/x86/PC.py +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright (c) 2008 The Regents of The University of Michigan -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer; -# redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution; -# neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Authors: Gabe Black - -from m5.params import * -from m5.proxy import * - -from Device import IsaFake -from Pci import PciConfigAll -from Platform import Platform -from SouthBridge import SouthBridge -from Terminal import Terminal -from Uart import Uart8250 - -def x86IOAddress(port): - IO_address_space_base = 0x8000000000000000 - return IO_address_space_base + port; - -class PC(Platform): - type = 'PC' - system = Param.System(Parent.any, "system") - - pciconfig = PciConfigAll() - - south_bridge = SouthBridge() - - # "Non-existant" port used for timing purposes by the linux kernel - i_dont_exist = IsaFake(pio_addr=x86IOAddress(0x80), pio_size=1) - - # Ports behind the pci config and data regsiters. These don't do anything, - # but the linux kernel fiddles with them anway. - behind_pci = IsaFake(pio_addr=x86IOAddress(0xcf8), pio_size=8) - - # Serial port and terminal - terminal = Terminal() - com_1 = Uart8250() - com_1.pio_addr = x86IOAddress(0x3f8) - com_1.terminal = terminal - - def attachIO(self, bus): - self.south_bridge.attachIO(bus) - self.i_dont_exist.pio = bus.port - self.behind_pci.pio = bus.port - self.com_1.pio = bus.port - self.pciconfig.pio = bus.default - bus.responder_set = True - bus.responder = self.pciconfig diff --git a/src/dev/x86/Pc.py b/src/dev/x86/Pc.py new file mode 100644 index 000000000..080844e4a --- /dev/null +++ b/src/dev/x86/Pc.py @@ -0,0 +1,71 @@ +# Copyright (c) 2008 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +from m5.params import * +from m5.proxy import * + +from Device import IsaFake +from Pci import PciConfigAll +from Platform import Platform +from SouthBridge import SouthBridge +from Terminal import Terminal +from Uart import Uart8250 + +def x86IOAddress(port): + IO_address_space_base = 0x8000000000000000 + return IO_address_space_base + port; + +class Pc(Platform): + type = 'Pc' + system = Param.System(Parent.any, "system") + + pciconfig = PciConfigAll() + + south_bridge = SouthBridge() + + # "Non-existant" port used for timing purposes by the linux kernel + i_dont_exist = IsaFake(pio_addr=x86IOAddress(0x80), pio_size=1) + + # Ports behind the pci config and data regsiters. These don't do anything, + # but the linux kernel fiddles with them anway. + behind_pci = IsaFake(pio_addr=x86IOAddress(0xcf8), pio_size=8) + + # Serial port and terminal + terminal = Terminal() + com_1 = Uart8250() + com_1.pio_addr = x86IOAddress(0x3f8) + com_1.terminal = terminal + + def attachIO(self, bus): + self.south_bridge.attachIO(bus) + self.i_dont_exist.pio = bus.port + self.behind_pci.pio = bus.port + self.com_1.pio = bus.port + self.pciconfig.pio = bus.default + bus.responder_set = True + bus.responder = self.pciconfig diff --git a/src/dev/x86/SConscript b/src/dev/x86/SConscript index b71649fdd..ae270aa90 100644 --- a/src/dev/x86/SConscript +++ b/src/dev/x86/SConscript @@ -31,7 +31,7 @@ Import('*') if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'x86': - SimObject('PC.py') + SimObject('Pc.py') Source('pc.cc') SimObject('SouthBridge.py') diff --git a/src/dev/x86/pc.cc b/src/dev/x86/pc.cc index 7c35aebf2..0dc8d6cd5 100644 --- a/src/dev/x86/pc.cc +++ b/src/dev/x86/pc.cc @@ -47,7 +47,7 @@ using namespace std; using namespace TheISA; -PC::PC(const Params *p) +Pc::Pc(const Params *p) : Platform(p), system(p->system) { southBridge = NULL; @@ -56,7 +56,7 @@ PC::PC(const Params *p) } void -PC::init() +Pc::init() { assert(southBridge); I8254 & timer = *southBridge->pit; @@ -70,40 +70,40 @@ PC::init() } Tick -PC::intrFrequency() +Pc::intrFrequency() { panic("Need implementation\n"); M5_DUMMY_RETURN } void -PC::postConsoleInt() +Pc::postConsoleInt() { warn_once("Don't know what interrupt to post for console.\n"); //panic("Need implementation\n"); } void -PC::clearConsoleInt() +Pc::clearConsoleInt() { warn_once("Don't know what interrupt to clear for console.\n"); //panic("Need implementation\n"); } void -PC::postPciInt(int line) +Pc::postPciInt(int line) { panic("Need implementation\n"); } void -PC::clearPciInt(int line) +Pc::clearPciInt(int line) { panic("Need implementation\n"); } Addr -PC::pciToDma(Addr pciAddr) const +Pc::pciToDma(Addr pciAddr) const { panic("Need implementation\n"); M5_DUMMY_RETURN @@ -111,7 +111,7 @@ PC::pciToDma(Addr pciAddr) const Addr -PC::calcConfigAddr(int bus, int dev, int func) +Pc::calcConfigAddr(int bus, int dev, int func) { assert(func < 8); assert(dev < 32); @@ -119,8 +119,8 @@ PC::calcConfigAddr(int bus, int dev, int func) return (PhysAddrPrefixPciConfig | (func << 8) | (dev << 11)); } -PC * -PCParams::create() +Pc * +PcParams::create() { - return new PC(this); + return new Pc(this); } diff --git a/src/dev/x86/pc.hh b/src/dev/x86/pc.hh index 418a2e830..21055a566 100644 --- a/src/dev/x86/pc.hh +++ b/src/dev/x86/pc.hh @@ -38,13 +38,13 @@ #define __DEV_PC_HH__ #include "dev/platform.hh" -#include "params/PC.hh" +#include "params/Pc.hh" class IdeController; class System; class SouthBridge; -class PC : public Platform +class Pc : public Platform { public: /** Pointer to the system */ @@ -52,14 +52,14 @@ class PC : public Platform SouthBridge *southBridge; public: - typedef PCParams Params; + typedef PcParams Params; /** * Do platform initialization stuff */ void init(); - PC(const Params *p); + Pc(const Params *p); /** * Return the interrupting frequency to AlphaAccess diff --git a/src/dev/x86/south_bridge.cc b/src/dev/x86/south_bridge.cc index 3f68fee18..d366de4ad 100644 --- a/src/dev/x86/south_bridge.cc +++ b/src/dev/x86/south_bridge.cc @@ -40,7 +40,7 @@ SouthBridge::SouthBridge(const Params *p) : SimObject(p), cmos(p->cmos), speaker(p->speaker) { // Let the platform know where we are - PC * pc = dynamic_cast(platform); + Pc * pc = dynamic_cast(platform); assert(pc); pc->southBridge = this; } -- cgit v1.2.3 From da7209ec93f3cdad11c02906357f06fa29652996 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 11 Oct 2008 02:27:21 -0700 Subject: CPU: Eliminate the hwrei function. --- src/arch/alpha/ev5.cc | 17 ----------------- src/arch/alpha/isa/decoder.isa | 11 ++++++++++- src/arch/alpha/isa/main.isa | 2 ++ src/cpu/checker/cpu.hh | 1 - src/cpu/exec_context.hh | 4 ---- src/cpu/o3/cpu.cc | 15 --------------- src/cpu/o3/cpu.hh | 3 --- src/cpu/o3/dyn_inst.hh | 2 -- src/cpu/o3/dyn_inst_impl.hh | 22 ---------------------- src/cpu/ozone/cpu.hh | 1 - src/cpu/ozone/cpu_impl.hh | 15 --------------- src/cpu/ozone/dyn_inst.hh | 1 - src/cpu/ozone/dyn_inst_impl.hh | 15 --------------- src/cpu/simple/base.hh | 1 - src/cpu/simple_thread.hh | 2 -- 15 files changed, 12 insertions(+), 100 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/ev5.cc b/src/arch/alpha/ev5.cc index 7dc02a611..eefe86bff 100644 --- a/src/arch/alpha/ev5.cc +++ b/src/arch/alpha/ev5.cc @@ -552,23 +552,6 @@ copyIprs(ThreadContext *src, ThreadContext *dest) using namespace AlphaISA; -Fault -SimpleThread::hwrei() -{ - if (!(readPC() & 0x3)) - return new UnimplementedOpcodeFault; - - setNextPC(readMiscRegNoEffect(IPR_EXC_ADDR)); - - if (!misspeculating()) { - if (kernelStats) - kernelStats->hwrei(); - } - - // FIXME: XXX check for interrupts? XXX - return NoFault; -} - /** * Check for special simulator handling of specific PAL calls. * If return value is false, actual PAL call will be suppressed. diff --git a/src/arch/alpha/isa/decoder.isa b/src/arch/alpha/isa/decoder.isa index 270940df2..8025ba69f 100644 --- a/src/arch/alpha/isa/decoder.isa +++ b/src/arch/alpha/isa/decoder.isa @@ -786,7 +786,16 @@ decode OPCODE default Unknown::unknown() { format BasicOperate { 0x1e: decode PALMODE { 0: OpcdecFault::hw_rei(); - 1:hw_rei({{ xc->hwrei(); }}, IsSerializing, IsSerializeBefore); + 1: hw_rei({{ + NPC = ExcAddr; + ThreadContext * tc = xc->tcBase(); + if (!tc->misspeculating()) { + AlphaISA::Kernel::Statistics * kernelStats = + tc->getKernelStats(); + if (kernelStats) + kernelStats->hwrei(); + } + }}, IsSerializing, IsSerializeBefore); } // M5 special opcodes use the reserved 0x01 opcode space diff --git a/src/arch/alpha/isa/main.isa b/src/arch/alpha/isa/main.isa index 5231712c8..078982697 100644 --- a/src/arch/alpha/isa/main.isa +++ b/src/arch/alpha/isa/main.isa @@ -69,6 +69,7 @@ output exec {{ #include #if FULL_SYSTEM +#include "arch/alpha/kernel_stats.hh" #include "sim/pseudo_inst.hh" #endif #include "arch/alpha/ipr.hh" @@ -187,6 +188,7 @@ def operands {{ 'Runiq': ('ControlReg', 'uq', 'MISCREG_UNIQ', None, 1), 'FPCR': ('ControlReg', 'uq', 'MISCREG_FPCR', None, 1), 'IntrFlag': ('ControlReg', 'uq', 'MISCREG_INTR', None, 1), + 'ExcAddr': ('ControlReg', 'uq', 'IPR_EXC_ADDR', None, 1), # The next two are hacks for non-full-system call-pal emulation 'R0': ('IntReg', 'uq', '0', None, 1), 'R16': ('IntReg', 'uq', '16', None, 1), diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh index 5b3c4582c..b234bf23f 100644 --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@ -336,7 +336,6 @@ class CheckerCPU : public BaseCPU void translateDataReadReq(Request *req); #if FULL_SYSTEM - Fault hwrei() { return thread->hwrei(); } void ev5_trap(Fault fault) { fault->invoke(tc); } bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); } #else diff --git a/src/cpu/exec_context.hh b/src/cpu/exec_context.hh index 2b9fe4bcf..93192246c 100644 --- a/src/cpu/exec_context.hh +++ b/src/cpu/exec_context.hh @@ -144,10 +144,6 @@ class ExecContext { void writeHint(Addr addr, int size, unsigned flags); #if FULL_SYSTEM - /** Somewhat Alpha-specific function that handles returning from - * an error or interrupt. */ - Fault hwrei(); - /** * Check for special simulator handling of specific PAL calls. If * return value is false, actual PAL call will be suppressed. diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index eb1115565..174f4a98d 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -905,21 +905,6 @@ FullO3CPU::post_interrupt(int int_num, int index) } } -template -Fault -FullO3CPU::hwrei(unsigned tid) -{ -#if THE_ISA == ALPHA_ISA - // Need to clear the lock flag upon returning from an interrupt. - this->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, false, tid); - - this->thread[tid]->kernelStats->hwrei(); - - // FIXME: XXX check for interrupts? XXX -#endif - return NoFault; -} - template bool FullO3CPU::simPalCheck(int palFunc, unsigned tid) diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 406d965be..cdc1d2e58 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -414,9 +414,6 @@ class FullO3CPU : public BaseO3CPU /** Posts an interrupt. */ void post_interrupt(int int_num, int index); - /** HW return from error interrupt. */ - Fault hwrei(unsigned tid); - bool simPalCheck(int palFunc, unsigned tid); /** Returns the Fault for any valid interrupt. */ diff --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh index 292547b6b..ce59d802b 100644 --- a/src/cpu/o3/dyn_inst.hh +++ b/src/cpu/o3/dyn_inst.hh @@ -168,8 +168,6 @@ class BaseO3DynInst : public BaseDynInst } #if FULL_SYSTEM - /** Calls hardware return from error interrupt. */ - Fault hwrei(); /** Traps to handle specified fault. */ void trap(Fault fault); bool simPalCheck(int palFunc); diff --git a/src/cpu/o3/dyn_inst_impl.hh b/src/cpu/o3/dyn_inst_impl.hh index 6398a3afe..f85527f22 100644 --- a/src/cpu/o3/dyn_inst_impl.hh +++ b/src/cpu/o3/dyn_inst_impl.hh @@ -124,28 +124,6 @@ BaseO3DynInst::completeAcc(PacketPtr pkt) } #if FULL_SYSTEM -template -Fault -BaseO3DynInst::hwrei() -{ -#if THE_ISA == ALPHA_ISA - // Can only do a hwrei when in pal mode. - if (!(this->readPC() & 0x3)) - return new AlphaISA::UnimplementedOpcodeFault; - - // Set the next PC based on the value of the EXC_ADDR IPR. - this->setNextPC(this->cpu->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR, - this->threadNumber)); - - // Tell CPU to clear any state it needs to if a hwrei is taken. - this->cpu->hwrei(this->threadNumber); -#else - -#endif - // FIXME: XXX check for interrupts? XXX - return NoFault; -} - template void BaseO3DynInst::trap(Fault fault) diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index c3ea33673..e95accdfd 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -510,7 +510,6 @@ class OzoneCPU : public BaseCPU void dumpInsts() { frontEnd->dumpInsts(); } #if FULL_SYSTEM - Fault hwrei(); bool simPalCheck(int palFunc); void processInterrupts(); #else diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index ceb980d4c..eb7b1a13f 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -668,21 +668,6 @@ OzoneCPU::setSyscallReturn(SyscallReturn return_value, int tid) } } #else -template -Fault -OzoneCPU::hwrei() -{ - // Need to move this to ISA code - // May also need to make this per thread - - lockFlag = false; - lockAddrList.clear(); - thread.kernelStats->hwrei(); - - // FIXME: XXX check for interrupts? XXX - return NoFault; -} - template void OzoneCPU::processInterrupts() diff --git a/src/cpu/ozone/dyn_inst.hh b/src/cpu/ozone/dyn_inst.hh index e138cbe13..deade9397 100644 --- a/src/cpu/ozone/dyn_inst.hh +++ b/src/cpu/ozone/dyn_inst.hh @@ -240,7 +240,6 @@ class OzoneDynInst : public BaseDynInst void setMiscReg(int misc_reg, const MiscReg &val); #if FULL_SYSTEM - Fault hwrei(); void trap(Fault fault); bool simPalCheck(int palFunc); #else diff --git a/src/cpu/ozone/dyn_inst_impl.hh b/src/cpu/ozone/dyn_inst_impl.hh index 8519917f5..8fc5077a6 100644 --- a/src/cpu/ozone/dyn_inst_impl.hh +++ b/src/cpu/ozone/dyn_inst_impl.hh @@ -248,21 +248,6 @@ OzoneDynInst::setMiscReg(int misc_reg, const MiscReg &val) #if FULL_SYSTEM -template -Fault -OzoneDynInst::hwrei() -{ - if (!(this->readPC() & 0x3)) - return new AlphaISA::UnimplementedOpcodeFault; - - this->setNextPC(this->thread->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR)); - - this->cpu->hwrei(); - - // FIXME: XXX check for interrupts? XXX - return NoFault; -} - template void OzoneDynInst::trap(Fault fault) diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index b7fcf1708..b28a690bb 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -413,7 +413,6 @@ class BaseSimpleCPU : public BaseCPU //Fault CacheOp(uint8_t Op, Addr EA); #if FULL_SYSTEM - Fault hwrei() { return thread->hwrei(); } void ev5_trap(Fault fault) { fault->invoke(tc); } bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); } #else diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index 377bfcd79..89d5ba99f 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -185,8 +185,6 @@ class SimpleThread : public ThreadState void dumpFuncProfile(); - Fault hwrei(); - bool simPalCheck(int palFunc); #endif -- cgit v1.2.3 From f621b7b81f0913612381d5dc4993f52bb2116902 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 11 Oct 2008 12:17:24 -0700 Subject: CPU: Eliminate the simPalCheck funciton. --- src/arch/alpha/ev5.cc | 33 --------------------------------- src/arch/alpha/isa/decoder.isa | 23 ++++++++++++++++++++++- src/arch/alpha/isa/main.isa | 1 + src/cpu/checker/cpu.hh | 1 - src/cpu/exec_context.hh | 8 +------- src/cpu/o3/cpu.cc | 30 ------------------------------ src/cpu/o3/cpu.hh | 2 -- src/cpu/o3/dyn_inst.hh | 1 - src/cpu/o3/dyn_inst_impl.hh | 10 ---------- src/cpu/ozone/cpu.hh | 1 - src/cpu/ozone/cpu_impl.hh | 25 ------------------------- src/cpu/ozone/dyn_inst.hh | 1 - src/cpu/ozone/dyn_inst_impl.hh | 7 ------- src/cpu/simple/base.hh | 1 - src/cpu/simple_thread.hh | 2 -- 15 files changed, 24 insertions(+), 122 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/ev5.cc b/src/arch/alpha/ev5.cc index eefe86bff..c11b3632e 100644 --- a/src/arch/alpha/ev5.cc +++ b/src/arch/alpha/ev5.cc @@ -547,36 +547,3 @@ copyIprs(ThreadContext *src, ThreadContext *dest) } } // namespace AlphaISA - -#if FULL_SYSTEM - -using namespace AlphaISA; - -/** - * Check for special simulator handling of specific PAL calls. - * If return value is false, actual PAL call will be suppressed. - */ -bool -SimpleThread::simPalCheck(int palFunc) -{ - if (kernelStats) - kernelStats->callpal(palFunc, tc); - - switch (palFunc) { - case PAL::halt: - halt(); - if (--System::numSystemsRunning == 0) - exitSimLoop("all cpus halted"); - break; - - case PAL::bpt: - case PAL::bugchk: - if (system->breakpoint()) - return false; - break; - } - - return true; -} - -#endif // FULL_SYSTEM diff --git a/src/arch/alpha/isa/decoder.isa b/src/arch/alpha/isa/decoder.isa index 8025ba69f..06676ae87 100644 --- a/src/arch/alpha/isa/decoder.isa +++ b/src/arch/alpha/isa/decoder.isa @@ -698,7 +698,28 @@ decode OPCODE default Unknown::unknown() { else { // check to see if simulator wants to do something special // on this PAL call (including maybe suppress it) - bool dopal = xc->simPalCheck(palFunc); + + bool dopal = true; + + ThreadContext * tc = xc->tcBase(); + AlphaISA::Kernel::Statistics * kernelStats = tc->getKernelStats(); + System * system = tc->getSystemPtr(); + if (kernelStats) + kernelStats->callpal(palFunc, tc); + + switch (palFunc) { + case PAL::halt: + tc->halt(); + if (--System::numSystemsRunning == 0) + exitSimLoop("all cpus halted"); + break; + + case PAL::bpt: + case PAL::bugchk: + if (system->breakpoint()) + dopal = false; + break; + } if (dopal) { xc->setMiscReg(IPR_EXC_ADDR, NPC); diff --git a/src/arch/alpha/isa/main.isa b/src/arch/alpha/isa/main.isa index 078982697..0f7f74359 100644 --- a/src/arch/alpha/isa/main.isa +++ b/src/arch/alpha/isa/main.isa @@ -70,6 +70,7 @@ output exec {{ #if FULL_SYSTEM #include "arch/alpha/kernel_stats.hh" +#include "arch/alpha/osfpal.hh" #include "sim/pseudo_inst.hh" #endif #include "arch/alpha/ipr.hh" diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh index b234bf23f..0f01f17c5 100644 --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@ -337,7 +337,6 @@ class CheckerCPU : public BaseCPU #if FULL_SYSTEM void ev5_trap(Fault fault) { fault->invoke(tc); } - bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); } #else // Assume that the normal CPU's call to syscall was successful. // The checker's state would have already been updated by the syscall. diff --git a/src/cpu/exec_context.hh b/src/cpu/exec_context.hh index 93192246c..836cf4352 100644 --- a/src/cpu/exec_context.hh +++ b/src/cpu/exec_context.hh @@ -143,13 +143,7 @@ class ExecContext { * given flags. */ void writeHint(Addr addr, int size, unsigned flags); -#if FULL_SYSTEM - /** - * Check for special simulator handling of specific PAL calls. If - * return value is false, actual PAL call will be suppressed. - */ - bool simPalCheck(int palFunc); -#else +#if !FULL_SYSTEM /** Executes a syscall specified by the callnum. */ void syscall(int64_t callnum); #endif diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 174f4a98d..ac816fc18 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -53,10 +53,6 @@ #include "cpu/checker/cpu.hh" #endif -#if THE_ISA == ALPHA_ISA -#include "arch/alpha/osfpal.hh" -#endif - class BaseCPUParams; using namespace TheISA; @@ -905,32 +901,6 @@ FullO3CPU::post_interrupt(int int_num, int index) } } -template -bool -FullO3CPU::simPalCheck(int palFunc, unsigned tid) -{ -#if THE_ISA == ALPHA_ISA - if (this->thread[tid]->kernelStats) - this->thread[tid]->kernelStats->callpal(palFunc, - this->threadContexts[tid]); - - switch (palFunc) { - case PAL::halt: - halt(); - if (--System::numSystemsRunning == 0) - exitSimLoop("all cpus halted"); - break; - - case PAL::bpt: - case PAL::bugchk: - if (this->system->breakpoint()) - return false; - break; - } -#endif - return true; -} - template Fault FullO3CPU::getInterrupts() diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index cdc1d2e58..07ba8d701 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -414,8 +414,6 @@ class FullO3CPU : public BaseO3CPU /** Posts an interrupt. */ void post_interrupt(int int_num, int index); - bool simPalCheck(int palFunc, unsigned tid); - /** Returns the Fault for any valid interrupt. */ Fault getInterrupts(); diff --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh index ce59d802b..28dd60f5f 100644 --- a/src/cpu/o3/dyn_inst.hh +++ b/src/cpu/o3/dyn_inst.hh @@ -170,7 +170,6 @@ class BaseO3DynInst : public BaseDynInst #if FULL_SYSTEM /** Traps to handle specified fault. */ void trap(Fault fault); - bool simPalCheck(int palFunc); #else /** Calls a syscall. */ void syscall(int64_t callnum); diff --git a/src/cpu/o3/dyn_inst_impl.hh b/src/cpu/o3/dyn_inst_impl.hh index f85527f22..3b713ea8f 100644 --- a/src/cpu/o3/dyn_inst_impl.hh +++ b/src/cpu/o3/dyn_inst_impl.hh @@ -130,16 +130,6 @@ BaseO3DynInst::trap(Fault fault) { this->cpu->trap(fault, this->threadNumber); } - -template -bool -BaseO3DynInst::simPalCheck(int palFunc) -{ -#if THE_ISA != ALPHA_ISA - panic("simPalCheck called, but PAL only exists in Alpha!\n"); -#endif - return this->cpu->simPalCheck(palFunc, this->threadNumber); -} #else template void diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index e95accdfd..aeafb603a 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -510,7 +510,6 @@ class OzoneCPU : public BaseCPU void dumpInsts() { frontEnd->dumpInsts(); } #if FULL_SYSTEM - bool simPalCheck(int palFunc); void processInterrupts(); #else void syscall(uint64_t &callnum); diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index eb7b1a13f..9c0b95a1a 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -685,31 +685,6 @@ OzoneCPU::processInterrupts() interrupt->invoke(thread.getTC()); } } - -template -bool -OzoneCPU::simPalCheck(int palFunc) -{ - // Need to move this to ISA code - // May also need to make this per thread - thread.kernelStats->callpal(palFunc, tc); - - switch (palFunc) { - case PAL::halt: - haltContext(thread.readTid()); - if (--System::numSystemsRunning == 0) - exitSimLoop("all cpus halted"); - break; - - case PAL::bpt: - case PAL::bugchk: - if (system->breakpoint()) - return false; - break; - } - - return true; -} #endif template diff --git a/src/cpu/ozone/dyn_inst.hh b/src/cpu/ozone/dyn_inst.hh index deade9397..12a19e70d 100644 --- a/src/cpu/ozone/dyn_inst.hh +++ b/src/cpu/ozone/dyn_inst.hh @@ -241,7 +241,6 @@ class OzoneDynInst : public BaseDynInst #if FULL_SYSTEM void trap(Fault fault); - bool simPalCheck(int palFunc); #else void syscall(uint64_t &callnum); #endif diff --git a/src/cpu/ozone/dyn_inst_impl.hh b/src/cpu/ozone/dyn_inst_impl.hh index 8fc5077a6..396007687 100644 --- a/src/cpu/ozone/dyn_inst_impl.hh +++ b/src/cpu/ozone/dyn_inst_impl.hh @@ -254,13 +254,6 @@ OzoneDynInst::trap(Fault fault) { fault->invoke(this->thread->getTC()); } - -template -bool -OzoneDynInst::simPalCheck(int palFunc) -{ - return this->cpu->simPalCheck(palFunc); -} #else template void diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index b28a690bb..03c20a6f2 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -414,7 +414,6 @@ class BaseSimpleCPU : public BaseCPU #if FULL_SYSTEM void ev5_trap(Fault fault) { fault->invoke(tc); } - bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); } #else void syscall(int64_t callnum) { thread->syscall(callnum); } #endif diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index 89d5ba99f..69d7b2548 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -185,8 +185,6 @@ class SimpleThread : public ThreadState void dumpFuncProfile(); - bool simPalCheck(int palFunc); - #endif /******************************************* -- cgit v1.2.3 From 526933e5d03f5d7963bc5a244294ddbb068c4770 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 11 Oct 2008 15:14:37 -0700 Subject: X86: Add an Intel MP table to the simulation. --- src/arch/x86/bios/IntelMP.py | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/arch/x86/bios/IntelMP.py b/src/arch/x86/bios/IntelMP.py index 70e7963fa..758932180 100644 --- a/src/arch/x86/bios/IntelMP.py +++ b/src/arch/x86/bios/IntelMP.py @@ -86,6 +86,15 @@ class X86IntelMPConfigTable(SimObject): ext_entries = VectorParam.X86IntelMPExtConfigEntry([], 'extended configuration table entries') + def add_entry(self, entry): + if isinstance(entry, X86IntelMPBaseConfigEntry): + self.base_entries.append(entry) + elif isinstance(entry, X86IntelMPExtConfigEntry): + self.base_entries.append(entry) + else: + panic("Don't know what type of Intel MP entry %s is." \ + % entry.__class__.__name__) + class X86IntelMPBaseConfigEntry(SimObject): type = 'X86IntelMPBaseConfigEntry' cxx_class = 'X86ISA::IntelMP::BaseConfigEntry' -- cgit v1.2.3 From a2599e4fc1272e4c1fdf5cff90da88653579b62f Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 11 Oct 2008 15:15:34 -0700 Subject: X86: Set up a mechanism for the I8254 timer to cause interrupts. --- src/dev/intel_8254_timer.cc | 19 ++++++++++--------- src/dev/intel_8254_timer.hh | 16 ++++++++++++++-- src/dev/x86/SConscript | 1 + src/dev/x86/i8254.cc | 9 +++++++++ src/dev/x86/i8254.hh | 24 ++++++++++++++++++++++-- 5 files changed, 56 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/dev/intel_8254_timer.cc b/src/dev/intel_8254_timer.cc index 35fbd9c38..d5dd043e1 100644 --- a/src/dev/intel_8254_timer.cc +++ b/src/dev/intel_8254_timer.cc @@ -47,9 +47,9 @@ Intel8254Timer::Intel8254Timer(EventManager *em, const string &name, Intel8254Timer::Intel8254Timer(EventManager *em, const string &name) : EventManager(em), _name(name) { - counter[0] = new Counter(this, name + ".counter0"); - counter[1] = new Counter(this, name + ".counter1"); - counter[2] = new Counter(this, name + ".counter2"); + counter[0] = new Counter(this, name + ".counter0", 0); + counter[1] = new Counter(this, name + ".counter1", 1); + counter[2] = new Counter(this, name + ".counter2", 2); } void @@ -88,10 +88,11 @@ Intel8254Timer::unserialize(const string &base, Checkpoint *cp, counter[2]->unserialize(base + ".counter2", cp, section); } -Intel8254Timer::Counter::Counter(Intel8254Timer *p, const string &name) - : _name(name), event(this), count(0), latched_count(0), period(0), - mode(0), output_high(false), latch_on(false), read_byte(LSB), - write_byte(LSB), parent(p) +Intel8254Timer::Counter::Counter(Intel8254Timer *p, + const string &name, unsigned int _num) + : _name(name), num(_num), event(this), count(0), + latched_count(0), period(0), mode(0), output_high(false), + latch_on(false), read_byte(LSB), write_byte(LSB), parent(p) { } @@ -246,7 +247,6 @@ Intel8254Timer::Counter::CounterEvent::CounterEvent(Counter* c_ptr) void Intel8254Timer::Counter::CounterEvent::process() { - DPRINTF(Intel8254Timer, "Timer Interrupt\n"); switch (counter->mode) { case InitTc: counter->output_high = true; @@ -258,6 +258,7 @@ Intel8254Timer::Counter::CounterEvent::process() default: panic("Unimplemented PITimer mode.\n"); } + counter->parent->counterInterrupt(counter->num); } void @@ -273,5 +274,5 @@ Intel8254Timer::Counter::CounterEvent::setTo(int clocks) const char * Intel8254Timer::Counter::CounterEvent::description() const { - return "tsunami 8254 Interval timer"; + return "Intel 8254 Interval timer"; } diff --git a/src/dev/intel_8254_timer.hh b/src/dev/intel_8254_timer.hh index 9391b0f9e..bb650d33b 100644 --- a/src/dev/intel_8254_timer.hh +++ b/src/dev/intel_8254_timer.hh @@ -90,7 +90,7 @@ class Intel8254Timer : public EventManager CounterEvent(Counter*); /** Event process */ - virtual void process(); + void process(); /** Event description */ virtual const char *description() const; @@ -104,6 +104,8 @@ class Intel8254Timer : public EventManager std::string _name; const std::string &name() const { return _name; } + unsigned int num; + CounterEvent event; /** Current count value */ @@ -134,7 +136,7 @@ class Intel8254Timer : public EventManager Intel8254Timer *parent; public: - Counter(Intel8254Timer *p, const std::string &name); + Counter(Intel8254Timer *p, const std::string &name, unsigned int num); /** Latch the current count (if one is not already latched) */ void latchCount(); @@ -181,8 +183,18 @@ class Intel8254Timer : public EventManager /** PIT has three seperate counters */ Counter *counter[3]; + virtual void + counterInterrupt(unsigned int num) + { + DPRINTF(Intel8254Timer, "Timer interrupt from counter %d.\n", num); + } + public: + virtual + ~Intel8254Timer() + {} + Intel8254Timer(EventManager *em, const std::string &name, Counter *counter0, Counter *counter1, Counter *counter2); diff --git a/src/dev/x86/SConscript b/src/dev/x86/SConscript index ae270aa90..7e3cc6eff 100644 --- a/src/dev/x86/SConscript +++ b/src/dev/x86/SConscript @@ -47,6 +47,7 @@ if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'x86': SimObject('I8254.py') Source('i8254.cc') + TraceFlag('I8254', 'Interrupts from the I8254 timer'); SimObject('PcSpeaker.py') Source('speaker.cc') diff --git a/src/dev/x86/i8254.cc b/src/dev/x86/i8254.cc index cc7c48980..ac3847cd6 100644 --- a/src/dev/x86/i8254.cc +++ b/src/dev/x86/i8254.cc @@ -29,9 +29,18 @@ */ #include "dev/x86/i8254.hh" +#include "dev/x86/intdev.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" +void +X86ISA::I8254::counterInterrupt(unsigned int num) +{ + DPRINTF(I8254, "Interrupt from counter %d.\n", num); + if (num == 0) + intPin->signalInterrupt(); +} + Tick X86ISA::I8254::read(PacketPtr pkt) { diff --git a/src/dev/x86/i8254.hh b/src/dev/x86/i8254.hh index 9528013c8..e6860b2c4 100644 --- a/src/dev/x86/i8254.hh +++ b/src/dev/x86/i8254.hh @@ -44,9 +44,29 @@ class I8254 : public BasicPioDevice { protected: Tick latency; - Intel8254Timer pit; + class X86Intel8254Timer : public Intel8254Timer + { + protected: + I8254 * parent; + + void + counterInterrupt(unsigned int num) + { + parent->counterInterrupt(num); + } + + public: + X86Intel8254Timer(const std::string &name, I8254 * _parent) : + Intel8254Timer(_parent, name), parent(_parent) + {} + }; + + + X86Intel8254Timer pit; IntPin *intPin; + + void counterInterrupt(unsigned int num); public: typedef I8254Params Params; @@ -58,7 +78,7 @@ class I8254 : public BasicPioDevice } I8254(Params *p) : BasicPioDevice(p), latency(p->pio_latency), - pit(this, p->name), intPin(p->int_pin) + pit(p->name, this), intPin(p->int_pin) { pioSize = 4; } -- cgit v1.2.3 From 168e524b9bfc9a53465562e2901c65ef388a237b Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 11 Oct 2008 16:08:14 -0700 Subject: X86: Create an IO APIC device. --- src/dev/x86/I82094AA.py | 41 ++++++++++ src/dev/x86/SConscript | 4 + src/dev/x86/SouthBridge.py | 5 ++ src/dev/x86/i82094aa.cc | 195 ++++++++++++++++++++++++++++++++++++++++++++ src/dev/x86/i82094aa.hh | 106 ++++++++++++++++++++++++ src/dev/x86/pc.cc | 15 ++++ src/dev/x86/south_bridge.cc | 2 +- src/dev/x86/south_bridge.hh | 2 + 8 files changed, 369 insertions(+), 1 deletion(-) create mode 100644 src/dev/x86/I82094AA.py create mode 100644 src/dev/x86/i82094aa.cc create mode 100644 src/dev/x86/i82094aa.hh (limited to 'src') diff --git a/src/dev/x86/I82094AA.py b/src/dev/x86/I82094AA.py new file mode 100644 index 000000000..731d831f0 --- /dev/null +++ b/src/dev/x86/I82094AA.py @@ -0,0 +1,41 @@ +# Copyright (c) 2008 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +from m5.params import * +from m5.proxy import * +from Device import BasicPioDevice +from X86IntPin import X86IntPin + +class I82094AA(BasicPioDevice): + type = 'I82094AA' + cxx_class = 'X86ISA::I82094AA' + pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") + pio_addr = Param.Addr("Device address") + + def pin(self, line): + return X86IntPin(device=self, line=line) diff --git a/src/dev/x86/SConscript b/src/dev/x86/SConscript index 7e3cc6eff..3481235c6 100644 --- a/src/dev/x86/SConscript +++ b/src/dev/x86/SConscript @@ -53,5 +53,9 @@ if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'x86': Source('speaker.cc') TraceFlag('PcSpeaker') + SimObject('I82094AA.py') + Source('i82094aa.cc') + TraceFlag('I82094AA') + SimObject('X86IntPin.py') Source('intdev.cc') diff --git a/src/dev/x86/SouthBridge.py b/src/dev/x86/SouthBridge.py index 2f4b8438a..15ffe153f 100644 --- a/src/dev/x86/SouthBridge.py +++ b/src/dev/x86/SouthBridge.py @@ -29,6 +29,7 @@ from m5.params import * from m5.proxy import * from Cmos import Cmos +from I82094AA import I82094AA from I8254 import I8254 from I8259 import I8259 from PcSpeaker import PcSpeaker @@ -48,15 +49,18 @@ class SouthBridge(SimObject): _cmos = Cmos(pio_addr=x86IOAddress(0x70)) _pit = I8254(pio_addr=x86IOAddress(0x40)) _speaker = PcSpeaker(pio_addr=x86IOAddress(0x61)) + _io_apic = I82094AA(pio_addr=0xFEC00000) pic1 = Param.I8259(_pic1, "Master PIC") pic2 = Param.I8259(_pic2, "Slave PIC") cmos = Param.Cmos(_cmos, "CMOS memory and real time clock device") pit = Param.I8254(_pit, "Programmable interval timer") speaker = Param.PcSpeaker(_speaker, "PC speaker") + io_apic = Param.I82094AA(_io_apic, "I/O APIC") def attachIO(self, bus): # Make internal connections + self.pic1.output = self.io_apic.pin(0) self.pic2.output = self.pic1.pin(2) self.cmos.int_pin = self.pic2.pin(0) self.pit.int_pin = self.pic1.pin(0) @@ -67,3 +71,4 @@ class SouthBridge(SimObject): self.pic2.pio = bus.port self.pit.pio = bus.port self.speaker.pio = bus.port + self.io_apic.pio = bus.port diff --git a/src/dev/x86/i82094aa.cc b/src/dev/x86/i82094aa.cc new file mode 100644 index 000000000..713f59592 --- /dev/null +++ b/src/dev/x86/i82094aa.cc @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "dev/x86/i82094aa.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" +#include "sim/system.hh" + +X86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), + latency(p->pio_latency), pioAddr(p->pio_addr) +{ + // This assumes there's only one I/O APIC in the system + id = sys->getNumCPUs(); + assert(id <= 0xf); + arbId = id; + regSel = 0; + memset(redirTable, 0, sizeof(RedirTableEntry) * TableSize); +} + +Tick +X86ISA::I82094AA::read(PacketPtr pkt) +{ + assert(pkt->getSize() == 4); + Addr offset = pkt->getAddr() - pioAddr; + switch(offset) { + case 0: + pkt->set(regSel); + break; + case 16: + pkt->set(readReg(regSel)); + break; + default: + panic("Illegal read from I/O APIC.\n"); + } + return latency; +} + +Tick +X86ISA::I82094AA::write(PacketPtr pkt) +{ + assert(pkt->getSize() == 4); + Addr offset = pkt->getAddr() - pioAddr; + switch(offset) { + case 0: + regSel = pkt->get(); + break; + case 16: + writeReg(regSel, pkt->get()); + break; + default: + panic("Illegal write to I/O APIC.\n"); + } + return latency; +} + +void +X86ISA::I82094AA::writeReg(uint8_t offset, uint32_t value) +{ + if (offset == 0x0) { + id = bits(value, 27, 24); + } else if (offset == 0x1) { + // The IOAPICVER register is read only. + } else if (offset == 0x2) { + arbId = bits(value, 27, 24); + } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) { + int index = (offset - 0x10) / 2; + if (offset % 2) { + redirTable[index].topDW = value; + redirTable[index].topReserved = 0; + } else { + redirTable[index].bottomDW = value; + redirTable[index].bottomReserved = 0; + } + } else { + warn("Access to undefined I/O APIC register %#x.\n", offset); + } + DPRINTF(I82094AA, + "Wrote %#x to I/O APIC register %#x .\n", value, offset); +} + +uint32_t +X86ISA::I82094AA::readReg(uint8_t offset) +{ + uint32_t result = 0; + if (offset == 0x0) { + result = id << 24; + } else if (offset == 0x1) { + result = ((TableSize - 1) << 16) | APICVersion; + } else if (offset == 0x2) { + result = arbId << 24; + } else if (offset >= 0x10 && offset <= (0x10 + TableSize * 2)) { + int index = (offset - 0x10) / 2; + if (offset % 2) { + result = redirTable[index].topDW; + } else { + result = redirTable[index].bottomDW; + } + } else { + warn("Access to undefined I/O APIC register %#x.\n", offset); + } + DPRINTF(I82094AA, + "Read %#x from I/O APIC register %#x.\n", result, offset); + return result; +} + +void +X86ISA::I82094AA::signalInterrupt(int line) +{ + DPRINTF(I82094AA, "Received interrupt %d.\n", line); + assert(line < TableSize); + RedirTableEntry entry = redirTable[line]; + if (entry.mask) { + DPRINTF(I82094AA, "Entry was masked.\n"); + return; + } else { + if (entry.destMode == 0) { + DPRINTF(I82094AA, + "Would send interrupt to APIC ID %d.\n", entry.dest); + } else { + DPRINTF(I82094AA, "Would send interrupts to APIC IDs:" + "%s%s%s%s%s%s%s%s\n", + bits((int)entry.dest, 0) ? " 0": "", + bits((int)entry.dest, 1) ? " 1": "", + bits((int)entry.dest, 2) ? " 2": "", + bits((int)entry.dest, 3) ? " 3": "", + bits((int)entry.dest, 4) ? " 4": "", + bits((int)entry.dest, 5) ? " 5": "", + bits((int)entry.dest, 6) ? " 6": "", + bits((int)entry.dest, 7) ? " 7": "" + ); + } + switch(entry.deliveryMode) { + case 0: + DPRINTF(I82094AA, "Delivery mode is: Fixed.\n"); + break; + case 1: + DPRINTF(I82094AA, "Delivery mode is: Lowest Priority.\n"); + break; + case 2: + DPRINTF(I82094AA, "Delivery mode is: SMI.\n"); + break; + case 3: + fatal("Tried to use reserved delivery mode " + "for IO APIC entry %d.\n", line); + break; + case 4: + DPRINTF(I82094AA, "Delivery mode is: NMI.\n"); + break; + case 5: + DPRINTF(I82094AA, "Delivery mode is: INIT.\n"); + break; + case 6: + fatal("Tried to use reserved delivery mode " + "for IO APIC entry %d.\n", line); + break; + case 7: + DPRINTF(I82094AA, "Delivery mode is: ExtINT.\n"); + break; + } + DPRINTF(I82094AA, "Vector is %#x.\n", entry.vector); + } +} + +X86ISA::I82094AA * +I82094AAParams::create() +{ + return new X86ISA::I82094AA(this); +} diff --git a/src/dev/x86/i82094aa.hh b/src/dev/x86/i82094aa.hh new file mode 100644 index 000000000..b442e3e92 --- /dev/null +++ b/src/dev/x86/i82094aa.hh @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __DEV_X86_I82094AA_HH__ +#define __DEV_X86_I82094AA_HH__ + +#include "base/bitunion.hh" +#include "base/range_map.hh" +#include "dev/io_device.hh" +#include "dev/x86/intdev.hh" +#include "params/I82094AA.hh" + +namespace X86ISA +{ + +class I82094AA : public PioDevice, public IntDev +{ + public: + BitUnion64(RedirTableEntry) + Bitfield<63, 32> topDW; + Bitfield<55, 32> topReserved; + Bitfield<31, 0> bottomDW; + Bitfield<31, 17> bottomReserved; + Bitfield<63, 56> dest; + Bitfield<16> mask; + Bitfield<15> trigger; + Bitfield<14> remoteIRR; + Bitfield<13> polarity; + Bitfield<12> deliveryStatus; + Bitfield<11> destMode; + Bitfield<10, 8> deliveryMode; + Bitfield<7, 0> vector; + EndBitUnion(RedirTableEntry) + + protected: + Tick latency; + Addr pioAddr; + + uint8_t regSel; + uint8_t id; + uint8_t arbId; + + static const uint8_t TableSize = 24; + // This implementation is based on version 0x11, but 0x14 avoids having + // to deal with the arbitration and APIC bus guck. + static const uint8_t APICVersion = 0x14; + + RedirTableEntry redirTable[TableSize]; + + public: + typedef I82094AAParams Params; + + const Params * + params() const + { + return dynamic_cast(_params); + } + + I82094AA(Params *p); + + Tick read(PacketPtr pkt); + Tick write(PacketPtr pkt); + + void addressRanges(AddrRangeList &range_list) + { + range_list.clear(); + range_list.push_back(RangeEx(pioAddr, pioAddr + 4)); + range_list.push_back(RangeEx(pioAddr + 16, pioAddr + 20)); + } + + void writeReg(uint8_t offset, uint32_t value); + uint32_t readReg(uint8_t offset); + + void signalInterrupt(int line); +}; + +}; // namespace X86ISA + +#endif //__DEV_X86_SOUTH_BRIDGE_I8254_HH__ diff --git a/src/dev/x86/pc.cc b/src/dev/x86/pc.cc index 0dc8d6cd5..4cd81dd50 100644 --- a/src/dev/x86/pc.cc +++ b/src/dev/x86/pc.cc @@ -39,6 +39,7 @@ #include "arch/x86/x86_traits.hh" #include "cpu/intr_control.hh" #include "dev/terminal.hh" +#include "dev/x86/i82094aa.hh" #include "dev/x86/i8254.hh" #include "dev/x86/pc.hh" #include "dev/x86/south_bridge.hh" @@ -59,6 +60,10 @@ void Pc::init() { assert(southBridge); + + /* + * Initialize the timer. + */ I8254 & timer = *southBridge->pit; //Timer 0, mode 2, no bcd, 16 bit count timer.writeControl(0x34); @@ -67,6 +72,16 @@ Pc::init() //Write a 16 bit count of 0 timer.writeCounter(0, 0); timer.writeCounter(0, 0); + + /* + * Initialize the I/O APIC. + */ + I82094AA & ioApic = *southBridge->ioApic; + I82094AA::RedirTableEntry entry = 0; + entry.deliveryMode = 0x7; + entry.vector = 0x20; + ioApic.writeReg(0x10, entry.bottomDW); + ioApic.writeReg(0x11, entry.topDW); } Tick diff --git a/src/dev/x86/south_bridge.cc b/src/dev/x86/south_bridge.cc index d366de4ad..c456f478d 100644 --- a/src/dev/x86/south_bridge.cc +++ b/src/dev/x86/south_bridge.cc @@ -37,7 +37,7 @@ using namespace X86ISA; SouthBridge::SouthBridge(const Params *p) : SimObject(p), platform(p->platform), pit(p->pit), pic1(p->pic1), pic2(p->pic2), - cmos(p->cmos), speaker(p->speaker) + cmos(p->cmos), speaker(p->speaker), ioApic(p->io_apic) { // Let the platform know where we are Pc * pc = dynamic_cast(platform); diff --git a/src/dev/x86/south_bridge.hh b/src/dev/x86/south_bridge.hh index 5677aa8a0..61d6d387a 100644 --- a/src/dev/x86/south_bridge.hh +++ b/src/dev/x86/south_bridge.hh @@ -40,6 +40,7 @@ namespace X86ISA class I8259; class Cmos; class Speaker; + class I82094AA; } class SouthBridge : public SimObject @@ -53,6 +54,7 @@ class SouthBridge : public SimObject X86ISA::I8259 * pic2; X86ISA::Cmos * cmos; X86ISA::Speaker * speaker; + X86ISA::I82094AA * ioApic; public: typedef SouthBridgeParams Params; -- cgit v1.2.3 From 0c3848732ee33cf14a80129f6cf7ee84d51c8bfb Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 11 Oct 2008 16:13:58 -0700 Subject: CPU: Add a getInterruptController function --- src/cpu/base.hh | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/cpu/base.hh b/src/cpu/base.hh index c2b78a675..7b7ad9be0 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -110,6 +110,12 @@ class BaseCPU : public MemObject TheISA::Interrupts interrupts; public: + TheISA::Interrupts * + getInterruptController() + { + return &interrupts; + } + virtual void post_interrupt(int int_num, int index); virtual void clear_interrupt(int int_num, int index); virtual void clear_interrupts(); -- cgit v1.2.3 From c4f1cc3b482311f878be44259125c9a5b90c0569 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 08:24:09 -0700 Subject: CPU: Eliminate the get_vec function. --- src/arch/alpha/interrupts.hh | 7 ------- src/arch/mips/interrupts.cc | 12 ------------ src/arch/mips/interrupts.hh | 4 ---- src/arch/sparc/tlb.cc | 33 ++++++++++++++++++++++++--------- src/arch/x86/interrupts.hh | 6 ------ src/cpu/base.cc | 6 ------ src/cpu/base.hh | 1 - 7 files changed, 24 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/interrupts.hh b/src/arch/alpha/interrupts.hh index abfecfb5b..6ae4e4b1d 100644 --- a/src/arch/alpha/interrupts.hh +++ b/src/arch/alpha/interrupts.hh @@ -171,13 +171,6 @@ class Interrupts tc->setMiscRegNoEffect(IPR_INTID, newIpl); newInfoSet = false; } - - uint64_t - get_vec(int int_num) - { - panic("Shouldn't be called for Alpha\n"); - M5_DUMMY_RETURN; - } }; } // namespace AlphaISA diff --git a/src/arch/mips/interrupts.cc b/src/arch/mips/interrupts.cc index c91ee1e99..e04d22631 100755 --- a/src/arch/mips/interrupts.cc +++ b/src/arch/mips/interrupts.cc @@ -156,12 +156,6 @@ static inline void setCauseIP_(ThreadContext *tc, uint8_t val) { return false; } - - uint64_t Interrupts::get_vec(int int_num) - { - panic("MipsISA::Interrupts::get_vec() is not implemented. \n"); - M5_DUMMY_RETURN - } */ void Interrupts::post(int int_num, ThreadContext* tc) { @@ -252,12 +246,6 @@ void Interrupts::updateIntrInfo(ThreadContext *tc) const ; } -uint64_t Interrupts::get_vec(int int_num) -{ - panic("MipsISA::Interrupts::get_vec() is not implemented. \n"); - M5_DUMMY_RETURN - } - bool Interrupts::interruptsPending(ThreadContext *tc) const { //if there is a on cpu timer interrupt (i.e. Compare == Count) diff --git a/src/arch/mips/interrupts.hh b/src/arch/mips/interrupts.hh index f0e928088..99a8f6fa0 100755 --- a/src/arch/mips/interrupts.hh +++ b/src/arch/mips/interrupts.hh @@ -91,8 +91,6 @@ class Interrupts void updateIntrInfoCpuTimerIntr(ThreadContext *tc) const; bool onCpuTimerInterrupt(ThreadContext *tc) const; - uint64_t get_vec(int int_num); - bool check_interrupts(ThreadContext * tc) const{ //return (intstatus != 0) && !(tc->readPC() & 0x3); if (oncputimerintr == false){ @@ -160,8 +158,6 @@ class Interrupts bool interruptsPending(ThreadContext *tc) const; bool onCpuTimerInterrupt(ThreadContext *tc) const; - uint64_t get_vec(int int_num); - bool check_interrupts(ThreadContext * tc) const{ return interruptsPending(tc); } diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc index 125ceba69..61f0985db 100644 --- a/src/arch/sparc/tlb.cc +++ b/src/arch/sparc/tlb.cc @@ -1008,12 +1008,22 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) itb->cx_config)); break; case ASI_SWVR_INTR_RECEIVE: - pkt->set(tc->getCpuPtr()->get_interrupts(IT_INT_VEC)); + { + SparcISA::Interrupts * interrupts = + dynamic_cast( + tc->getCpuPtr()->getInterruptController()); + pkt->set(interrupts->get_vec(IT_INT_VEC)); + } break; case ASI_SWVR_UDB_INTR_R: - temp = findMsbSet(tc->getCpuPtr()->get_interrupts(IT_INT_VEC)); - tc->getCpuPtr()->clear_interrupt(IT_INT_VEC, temp); - pkt->set(temp); + { + SparcISA::Interrupts * interrupts = + dynamic_cast( + tc->getCpuPtr()->getInterruptController()); + temp = findMsbSet(interrupts->get_vec(IT_INT_VEC)); + tc->getCpuPtr()->clear_interrupt(IT_INT_VEC, temp); + pkt->set(temp); + } break; default: doMmuReadError: @@ -1252,11 +1262,16 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) } break; case ASI_SWVR_INTR_RECEIVE: - int msb; - // clear all the interrupts that aren't set in the write - while(tc->getCpuPtr()->get_interrupts(IT_INT_VEC) & data) { - msb = findMsbSet(tc->getCpuPtr()->get_interrupts(IT_INT_VEC) & data); - tc->getCpuPtr()->clear_interrupt(IT_INT_VEC, msb); + { + int msb; + // clear all the interrupts that aren't set in the write + SparcISA::Interrupts * interrupts = + dynamic_cast( + tc->getCpuPtr()->getInterruptController()); + while(interrupts->get_vec(IT_INT_VEC) & data) { + msb = findMsbSet(interrupts->get_vec(IT_INT_VEC) & data); + tc->getCpuPtr()->clear_interrupt(IT_INT_VEC, msb); + } } break; case ASI_SWVR_UDB_INTR_W: diff --git a/src/arch/x86/interrupts.hh b/src/arch/x86/interrupts.hh index cf9109e22..43675294e 100644 --- a/src/arch/x86/interrupts.hh +++ b/src/arch/x86/interrupts.hh @@ -108,12 +108,6 @@ class Interrupts panic("Interrupts::updateIntrInfo unimplemented!\n"); } - uint64_t get_vec(int int_num) - { - panic("Interrupts::get_vec unimplemented!\n"); - return 0; - } - void serialize(std::ostream & os) { panic("Interrupts::serialize unimplemented!\n"); diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 5a0359e53..1ca0dc14b 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -396,12 +396,6 @@ BaseCPU::clear_interrupts() interrupts.clear_all(); } -uint64_t -BaseCPU::get_interrupts(int int_num) -{ - return interrupts.get_vec(int_num); -} - void BaseCPU::serialize(std::ostream &os) { diff --git a/src/cpu/base.hh b/src/cpu/base.hh index 7b7ad9be0..c99efa834 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -119,7 +119,6 @@ class BaseCPU : public MemObject virtual void post_interrupt(int int_num, int index); virtual void clear_interrupt(int int_num, int index); virtual void clear_interrupts(); - virtual uint64_t get_interrupts(int int_num); bool check_interrupts(ThreadContext * tc) const { return interrupts.check_interrupts(tc); } -- cgit v1.2.3 From d9f9c967fbe651e09d444e460a9b1c5a450b1cd2 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 09:09:56 -0700 Subject: Turn Interrupts objects into SimObjects. Also, move local APIC state into x86's Interrupts object. --- src/arch/alpha/AlphaInterrupts.py | 33 ++++++ src/arch/alpha/SConscript | 2 + src/arch/alpha/interrupts.cc | 37 +++++++ src/arch/alpha/interrupts.hh | 15 ++- src/arch/mips/MipsInterrupts.py | 33 ++++++ src/arch/mips/SConscript | 1 + src/arch/sparc/SConscript | 2 + src/arch/sparc/SparcInterrupts.py | 33 ++++++ src/arch/sparc/interrupts.cc | 37 +++++++ src/arch/sparc/interrupts.hh | 14 ++- src/arch/x86/SConscript | 2 + src/arch/x86/X86LocalApic.py | 35 ++++++ src/arch/x86/apicregs.hh | 91 +++++++++++++++ src/arch/x86/interrupts.cc | 227 ++++++++++++++++++++++++++++++++++++++ src/arch/x86/interrupts.hh | 44 +++++++- src/arch/x86/miscregfile.cc | 172 +++++------------------------ src/arch/x86/miscregfile.hh | 21 +--- src/arch/x86/miscregs.hh | 59 ++-------- src/arch/x86/mmaped_ipr.hh | 7 +- src/arch/x86/regfile.cc | 8 +- src/arch/x86/tlb.cc | 52 +++++---- src/arch/x86/utility.cc | 14 ++- src/cpu/BaseCPU.py | 25 +++++ src/cpu/base.cc | 12 +- src/cpu/base.hh | 6 +- src/cpu/o3/cpu.cc | 4 +- src/cpu/ozone/cpu_impl.hh | 4 +- src/cpu/simple/base.cc | 4 +- 28 files changed, 729 insertions(+), 265 deletions(-) create mode 100644 src/arch/alpha/AlphaInterrupts.py create mode 100644 src/arch/alpha/interrupts.cc create mode 100644 src/arch/mips/MipsInterrupts.py create mode 100644 src/arch/sparc/SparcInterrupts.py create mode 100644 src/arch/sparc/interrupts.cc create mode 100644 src/arch/x86/X86LocalApic.py create mode 100644 src/arch/x86/apicregs.hh create mode 100644 src/arch/x86/interrupts.cc (limited to 'src') diff --git a/src/arch/alpha/AlphaInterrupts.py b/src/arch/alpha/AlphaInterrupts.py new file mode 100644 index 000000000..ecfcf5c21 --- /dev/null +++ b/src/arch/alpha/AlphaInterrupts.py @@ -0,0 +1,33 @@ +# Copyright (c) 2008 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +from m5.SimObject import SimObject + +class AlphaInterrupts(SimObject): + type = 'AlphaInterrupts' + cxx_class = 'AlphaISA::Interrupts' diff --git a/src/arch/alpha/SConscript b/src/arch/alpha/SConscript index 04bac3996..069db2551 100644 --- a/src/arch/alpha/SConscript +++ b/src/arch/alpha/SConscript @@ -47,9 +47,11 @@ if env['TARGET_ISA'] == 'alpha': SimObject('AlphaTLB.py') if env['FULL_SYSTEM']: + SimObject('AlphaInterrupts.py') SimObject('AlphaSystem.py') Source('idle_event.cc') + Source('interrupts.cc') Source('kernel_stats.cc') Source('osfpal.cc') Source('stacktrace.cc') diff --git a/src/arch/alpha/interrupts.cc b/src/arch/alpha/interrupts.cc new file mode 100644 index 000000000..4b5dc5661 --- /dev/null +++ b/src/arch/alpha/interrupts.cc @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/alpha/interrupts.hh" + +AlphaISA::Interrupts * +AlphaInterruptsParams::create() +{ + return new AlphaISA::Interrupts(this); +} diff --git a/src/arch/alpha/interrupts.hh b/src/arch/alpha/interrupts.hh index 6ae4e4b1d..e7a451d4d 100644 --- a/src/arch/alpha/interrupts.hh +++ b/src/arch/alpha/interrupts.hh @@ -35,11 +35,14 @@ #include "arch/alpha/faults.hh" #include "arch/alpha/isa_traits.hh" #include "base/compiler.hh" +#include "base/trace.hh" #include "cpu/thread_context.hh" +#include "params/AlphaInterrupts.hh" +#include "sim/sim_object.hh" namespace AlphaISA { -class Interrupts +class Interrupts : public SimObject { private: bool newInfoSet; @@ -51,7 +54,15 @@ class Interrupts uint64_t intstatus; public: - Interrupts() + typedef AlphaInterruptsParams Params; + + const Params * + params() const + { + return dynamic_cast(_params); + } + + Interrupts(Params * p) : SimObject(p) { memset(interrupts, 0, sizeof(interrupts)); intstatus = 0; diff --git a/src/arch/mips/MipsInterrupts.py b/src/arch/mips/MipsInterrupts.py new file mode 100644 index 000000000..06cd54263 --- /dev/null +++ b/src/arch/mips/MipsInterrupts.py @@ -0,0 +1,33 @@ +# Copyright (c) 2008 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +from m5.SimObject import SimObject + +class MipsInterrupts(SimObject): + type = 'MipsInterrupts' + cxx_class = 'MipsISA::Interrupts' diff --git a/src/arch/mips/SConscript b/src/arch/mips/SConscript index 844e7ba15..0368e68bc 100644 --- a/src/arch/mips/SConscript +++ b/src/arch/mips/SConscript @@ -51,6 +51,7 @@ if env['TARGET_ISA'] == 'mips': if env['FULL_SYSTEM']: SimObject('MipsSystem.py') + SimObject('MipsInterrupts.py') Source('idle_event.cc') Source('mips_core_specific.cc') Source('vtophys.cc') diff --git a/src/arch/sparc/SConscript b/src/arch/sparc/SConscript index d4d68a6bd..126587835 100644 --- a/src/arch/sparc/SConscript +++ b/src/arch/sparc/SConscript @@ -52,7 +52,9 @@ if env['TARGET_ISA'] == 'sparc': if env['FULL_SYSTEM']: SimObject('SparcSystem.py') + SimObject('SparcInterrupts.py') + Source('interrupts.cc') Source('stacktrace.cc') Source('system.cc') Source('ua2005.cc') diff --git a/src/arch/sparc/SparcInterrupts.py b/src/arch/sparc/SparcInterrupts.py new file mode 100644 index 000000000..2cc964c2d --- /dev/null +++ b/src/arch/sparc/SparcInterrupts.py @@ -0,0 +1,33 @@ +# Copyright (c) 2008 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +from m5.SimObject import SimObject + +class SparcInterrupts(SimObject): + type = 'SparcInterrupts' + cxx_class = 'SparcISA::Interrupts' diff --git a/src/arch/sparc/interrupts.cc b/src/arch/sparc/interrupts.cc new file mode 100644 index 000000000..96d61e559 --- /dev/null +++ b/src/arch/sparc/interrupts.cc @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/sparc/interrupts.hh" + +SparcISA::Interrupts * +SparcInterruptsParams::create() +{ + return new SparcISA::Interrupts(this); +} diff --git a/src/arch/sparc/interrupts.hh b/src/arch/sparc/interrupts.hh index 4ad3385fb..7d1496d8e 100644 --- a/src/arch/sparc/interrupts.hh +++ b/src/arch/sparc/interrupts.hh @@ -35,11 +35,13 @@ #include "arch/sparc/faults.hh" #include "arch/sparc/isa_traits.hh" #include "cpu/thread_context.hh" +#include "params/SparcInterrupts.hh" +#include "sim/sim_object.hh" namespace SparcISA { -class Interrupts +class Interrupts : public SimObject { private: @@ -48,7 +50,15 @@ class Interrupts uint64_t intStatus; public: - Interrupts() + typedef SparcInterruptsParams Params; + + const Params * + params() const + { + return dynamic_cast(_params); + } + + Interrupts(Params * p) : SimObject(p) { clear_all(); } diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript index 0d8760fdc..e019b77c9 100644 --- a/src/arch/x86/SConscript +++ b/src/arch/x86/SConscript @@ -109,9 +109,11 @@ if env['TARGET_ISA'] == 'x86': TraceFlag('X86') if env['FULL_SYSTEM']: + SimObject('X86LocalApic.py') SimObject('X86System.py') # Full-system sources + Source('interrupts.cc') Source('linux/system.cc') Source('pagetable_walker.cc') Source('system.cc') diff --git a/src/arch/x86/X86LocalApic.py b/src/arch/x86/X86LocalApic.py new file mode 100644 index 000000000..94e32ae50 --- /dev/null +++ b/src/arch/x86/X86LocalApic.py @@ -0,0 +1,35 @@ +# Copyright (c) 2008 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +from m5.params import * +from Device import BasicPioDevice + +class X86LocalApic(BasicPioDevice): + type = 'X86LocalApic' + cxx_class = 'X86ISA::Interrupts' + pio_latency = Param.Latency('1ns', 'Programmed IO latency in simticks') diff --git a/src/arch/x86/apicregs.hh b/src/arch/x86/apicregs.hh new file mode 100644 index 000000000..464c3af2d --- /dev/null +++ b/src/arch/x86/apicregs.hh @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_APICREGS_HH__ +#define __ARCH_X86_APICREGS_HH__ + +namespace X86ISA +{ + enum ApicRegIndex + { + APIC_ID, + APIC_VERSION, + APIC_TASK_PRIORITY, + APIC_ARBITRATION_PRIORITY, + APIC_PROCESSOR_PRIORITY, + APIC_EOI, + APIC_LOGICAL_DESTINATION, + APIC_DESTINATION_FORMAT, + APIC_SPURIOUS_INTERRUPT_VECTOR, + + APIC_IN_SERVICE_BASE, + + APIC_TRIGGER_MODE_BASE = APIC_IN_SERVICE_BASE + 16, + + APIC_INTERRUPT_REQUEST_BASE = APIC_TRIGGER_MODE_BASE + 16, + + APIC_ERROR_STATUS = APIC_INTERRUPT_REQUEST_BASE + 16, + APIC_INTERRUPT_COMMAND_LOW, + APIC_INTERRUPT_COMMAND_HIGH, + APIC_LVT_TIMER, + APIC_LVT_THERMAL_SENSOR, + APIC_LVT_PERFORMANCE_MONITORING_COUNTERS, + APIC_LVT_LINT0, + APIC_LVT_LINT1, + APIC_LVT_ERROR, + APIC_INITIAL_COUNT, + APIC_CURRENT_COUNT, + APIC_DIVIDE_CONFIGURATION, + + APIC_INTERNAL_STATE, + + NUM_APIC_REGS + }; + + static inline ApicRegIndex + APIC_IN_SERVICE(int index) + { + return (ApicRegIndex)(APIC_IN_SERVICE_BASE + index); + } + + static inline ApicRegIndex + APIC_TRIGGER_MODE(int index) + { + return (ApicRegIndex)(APIC_TRIGGER_MODE_BASE + index); + } + + static inline ApicRegIndex + APIC_INTERRUPT_REQUEST(int index) + { + return (ApicRegIndex)(APIC_INTERRUPT_REQUEST_BASE + index); + } +} + +#endif diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc new file mode 100644 index 000000000..73536f2b4 --- /dev/null +++ b/src/arch/x86/interrupts.cc @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2008 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * 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: Gabe Black + */ + +#include "arch/x86/interrupts.hh" +#include "cpu/base.hh" + +int divideFromConf(uint32_t conf) +{ + // This figures out what division we want from the division configuration + // register in the local APIC. The encoding is a little odd but it can + // be deciphered fairly easily. + int shift = ((conf & 0x8) >> 1) | (conf & 0x3); + shift = (shift + 1) % 8; + return 1 << shift; +} + +uint32_t +X86ISA::Interrupts::readRegNoEffect(ApicRegIndex reg) +{ + return regs[reg]; +} + +uint32_t +X86ISA::Interrupts::readReg(ApicRegIndex reg, ThreadContext * tc) +{ + if (reg >= APIC_TRIGGER_MODE(0) && + reg <= APIC_TRIGGER_MODE(15)) { + panic("Local APIC Trigger Mode registers are unimplemented.\n"); + } + switch (reg) { + case APIC_ARBITRATION_PRIORITY: + panic("Local APIC Arbitration Priority register unimplemented.\n"); + break; + case APIC_PROCESSOR_PRIORITY: + panic("Local APIC Processor Priority register unimplemented.\n"); + break; + case APIC_EOI: + panic("Local APIC EOI register unimplemented.\n"); + break; + case APIC_ERROR_STATUS: + regs[APIC_INTERNAL_STATE] &= ~ULL(0x1); + break; + case APIC_INTERRUPT_COMMAND_LOW: + panic("Local APIC Interrupt Command low" + " register unimplemented.\n"); + break; + case APIC_INTERRUPT_COMMAND_HIGH: + panic("Local APIC Interrupt Command high" + " register unimplemented.\n"); + break; + case APIC_CURRENT_COUNT: + { + uint32_t val = regs[reg] - tc->getCpuPtr()->curCycle(); + val /= (16 * divideFromConf(regs[APIC_DIVIDE_CONFIGURATION])); + return val; + } + default: + break; + } + return readRegNoEffect(reg); +} + +void +X86ISA::Interrupts::setRegNoEffect(ApicRegIndex reg, uint32_t val) +{ + regs[reg] = val; +} + +void +X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val, ThreadContext *tc) +{ + uint32_t newVal = val; + if (reg >= APIC_IN_SERVICE(0) && + reg <= APIC_IN_SERVICE(15)) { + panic("Local APIC In-Service registers are unimplemented.\n"); + } + if (reg >= APIC_TRIGGER_MODE(0) && + reg <= APIC_TRIGGER_MODE(15)) { + panic("Local APIC Trigger Mode registers are unimplemented.\n"); + } + if (reg >= APIC_INTERRUPT_REQUEST(0) && + reg <= APIC_INTERRUPT_REQUEST(15)) { + panic("Local APIC Interrupt Request registers " + "are unimplemented.\n"); + } + switch (reg) { + case APIC_ID: + newVal = val & 0xFF; + break; + case APIC_VERSION: + // The Local APIC Version register is read only. + return; + case APIC_TASK_PRIORITY: + newVal = val & 0xFF; + break; + case APIC_ARBITRATION_PRIORITY: + panic("Local APIC Arbitration Priority register unimplemented.\n"); + break; + case APIC_PROCESSOR_PRIORITY: + panic("Local APIC Processor Priority register unimplemented.\n"); + break; + case APIC_EOI: + panic("Local APIC EOI register unimplemented.\n"); + break; + case APIC_LOGICAL_DESTINATION: + newVal = val & 0xFF000000; + break; + case APIC_DESTINATION_FORMAT: + newVal = val | 0x0FFFFFFF; + break; + case APIC_SPURIOUS_INTERRUPT_VECTOR: + regs[APIC_INTERNAL_STATE] &= ~ULL(1 << 1); + regs[APIC_INTERNAL_STATE] |= val & (1 << 8); + if (val & (1 << 9)) + warn("Focus processor checking not implemented.\n"); + break; + case APIC_ERROR_STATUS: + { + if (regs[APIC_INTERNAL_STATE] & 0x1) { + regs[APIC_INTERNAL_STATE] &= ~ULL(0x1); + newVal = 0; + } else { + regs[APIC_INTERNAL_STATE] |= ULL(0x1); + return; + } + + } + break; + case APIC_INTERRUPT_COMMAND_LOW: + panic("Local APIC Interrupt Command low" + " register unimplemented.\n"); + break; + case APIC_INTERRUPT_COMMAND_HIGH: + panic("Local APIC Interrupt Command high" + " register unimplemented.\n"); + break; + case APIC_LVT_TIMER: + case APIC_LVT_THERMAL_SENSOR: + case APIC_LVT_PERFORMANCE_MONITORING_COUNTERS: + case APIC_LVT_LINT0: + case APIC_LVT_LINT1: + case APIC_LVT_ERROR: + { + uint64_t readOnlyMask = (1 << 12) | (1 << 14); + newVal = (val & ~readOnlyMask) | + (regs[reg] & readOnlyMask); + } + break; + case APIC_INITIAL_COUNT: + newVal = bits(val, 31, 0); + regs[APIC_CURRENT_COUNT] = + tc->getCpuPtr()->curCycle() + + (16 * divideFromConf(regs[APIC_DIVIDE_CONFIGURATION])) * newVal; + //FIXME This should schedule the timer event. + break; + case APIC_CURRENT_COUNT: + //Local APIC Current Count register is read only. + return; + case APIC_DIVIDE_CONFIGURATION: + newVal = val & 0xB; + break; + default: + break; + } + setRegNoEffect(reg, newVal); + return; +} + +X86ISA::Interrupts * +X86LocalApicParams::create() +{ + return new X86ISA::Interrupts(this); +} diff --git a/src/arch/x86/interrupts.hh b/src/arch/x86/interrupts.hh index 43675294e..68bb2e07d 100644 --- a/src/arch/x86/interrupts.hh +++ b/src/arch/x86/interrupts.hh @@ -58,17 +58,57 @@ #ifndef __ARCH_X86_INTERRUPTS_HH__ #define __ARCH_X86_INTERRUPTS_HH__ +#include "arch/x86/apicregs.hh" #include "arch/x86/faults.hh" #include "cpu/thread_context.hh" +#include "params/X86LocalApic.hh" +#include "sim/eventq.hh" +#include "sim/sim_object.hh" + +class ThreadContext; namespace X86ISA { -class Interrupts +class Interrupts : public SimObject { + protected: + uint32_t regs[NUM_APIC_REGS]; + + class ApicTimerEvent : public Event + { + public: + ApicTimerEvent() : Event() + {} + + void process() + { + warn("Local APIC timer event doesn't do anything!\n"); + } + }; + + ApicTimerEvent apicTimerEvent; + public: - Interrupts() + typedef X86LocalApicParams Params; + + const Params * + params() const + { + return dynamic_cast(_params); + } + + uint32_t readRegNoEffect(ApicRegIndex reg); + uint32_t readReg(ApicRegIndex miscReg, ThreadContext *tc); + + void setRegNoEffect(ApicRegIndex reg, uint32_t val); + void setReg(ApicRegIndex reg, uint32_t val, ThreadContext *tc); + + Interrupts(Params * p) : SimObject(p) { + //Set the local apic DFR to the flat model. + regs[APIC_DESTINATION_FORMAT] = (uint32_t)(-1); + memset(regs, 0, sizeof(regs)); clear_all(); } diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc index f40b1adf5..aba498616 100644 --- a/src/arch/x86/miscregfile.cc +++ b/src/arch/x86/miscregfile.cc @@ -106,21 +106,9 @@ void MiscRegFile::clear() { // Blank everything. 0 might not be an appropriate value for some things. memset(regVal, 0, NumMiscRegs * sizeof(MiscReg)); - //Set the local apic DFR to the flat model. - regVal[MISCREG_APIC_DESTINATION_FORMAT] = (MiscReg)(-1); } -int divideFromConf(MiscReg conf) -{ - // This figures out what division we want from the division configuration - // register in the local APIC. The encoding is a little odd but it can - // be deciphered fairly easily. - int shift = ((conf & 0x8) >> 1) | (conf & 0x3); - shift = (shift + 1) % 8; - return 1 << shift; -}; - -MiscReg MiscRegFile::readRegNoEffect(int miscReg) +MiscReg MiscRegFile::readRegNoEffect(MiscRegIndex miscReg) { // Make sure we're not dealing with an illegal control register. // Instructions should filter out these indexes, and nothing else should @@ -131,52 +119,30 @@ MiscReg MiscRegFile::readRegNoEffect(int miscReg) !(miscReg > MISCREG_CR8 && miscReg <= MISCREG_CR15)); + if (isApicReg(miscReg)) { + panic("Can't readRegNoEffect from the local APIC.\n"); + } return regVal[miscReg]; } -MiscReg MiscRegFile::readReg(int miscReg, ThreadContext * tc) +MiscReg MiscRegFile::readReg(MiscRegIndex miscReg, ThreadContext * tc) { - if (miscReg >= MISCREG_APIC_START && miscReg <= MISCREG_APIC_END) { - if (miscReg >= MISCREG_APIC_TRIGGER_MODE(0) && - miscReg <= MISCREG_APIC_TRIGGER_MODE(15)) { - panic("Local APIC Trigger Mode registers are unimplemented.\n"); - } - switch (miscReg) { - case MISCREG_APIC_ARBITRATION_PRIORITY: - panic("Local APIC Arbitration Priority register unimplemented.\n"); - break; - case MISCREG_APIC_PROCESSOR_PRIORITY: - panic("Local APIC Processor Priority register unimplemented.\n"); - break; - case MISCREG_APIC_EOI: - panic("Local APIC EOI register unimplemented.\n"); - break; - case MISCREG_APIC_ERROR_STATUS: - regVal[MISCREG_APIC_INTERNAL_STATE] &= ~ULL(0x1); - break; - case MISCREG_APIC_INTERRUPT_COMMAND_LOW: - panic("Local APIC Interrupt Command low" - " register unimplemented.\n"); - break; - case MISCREG_APIC_INTERRUPT_COMMAND_HIGH: - panic("Local APIC Interrupt Command high" - " register unimplemented.\n"); - break; - case MISCREG_APIC_CURRENT_COUNT: - return (regVal[miscReg] - tc->getCpuPtr()->curCycle()) / - (16 * divideFromConf( - regVal[MISCREG_APIC_DIVIDE_CONFIGURATION])); - break; - } +#if FULL_SYSTEM + if (isApicReg(miscReg)) { + Interrupts * interrupts = dynamic_cast( + tc->getCpuPtr()->getInterruptController()); + assert(interrupts); + return interrupts->readReg( + (ApicRegIndex)(miscReg - MISCREG_APIC_START), tc); } - switch (miscReg) { - case MISCREG_TSC: +#endif + if (miscReg == MISCREG_TSC) { return regVal[MISCREG_TSC] + tc->getCpuPtr()->curCycle(); } return readRegNoEffect(miscReg); } -void MiscRegFile::setRegNoEffect(int miscReg, const MiscReg &val) +void MiscRegFile::setRegNoEffect(MiscRegIndex miscReg, const MiscReg &val) { // Make sure we're not dealing with an illegal control register. // Instructions should filter out these indexes, and nothing else should @@ -186,108 +152,26 @@ void MiscRegFile::setRegNoEffect(int miscReg, const MiscReg &val) miscReg < MISCREG_CR8) && !(miscReg > MISCREG_CR8 && miscReg <= MISCREG_CR15)); + if (isApicReg(miscReg)) { + panic("Can't setRegNoEffect from the local APIC.\n"); + } regVal[miscReg] = val; } -void MiscRegFile::setReg(int miscReg, +void MiscRegFile::setReg(MiscRegIndex miscReg, const MiscReg &val, ThreadContext * tc) { MiscReg newVal = val; - if (miscReg >= MISCREG_APIC_START && miscReg <= MISCREG_APIC_END) { - if (miscReg >= MISCREG_APIC_IN_SERVICE(0) && - miscReg <= MISCREG_APIC_IN_SERVICE(15)) { - panic("Local APIC In-Service registers are unimplemented.\n"); - } - if (miscReg >= MISCREG_APIC_TRIGGER_MODE(0) && - miscReg <= MISCREG_APIC_TRIGGER_MODE(15)) { - panic("Local APIC Trigger Mode registers are unimplemented.\n"); - } - if (miscReg >= MISCREG_APIC_INTERRUPT_REQUEST(0) && - miscReg <= MISCREG_APIC_INTERRUPT_REQUEST(15)) { - panic("Local APIC Interrupt Request registers " - "are unimplemented.\n"); - } - switch (miscReg) { - case MISCREG_APIC_ID: - newVal = val & 0xFF; - break; - case MISCREG_APIC_VERSION: - // The Local APIC Version register is read only. - return; - case MISCREG_APIC_TASK_PRIORITY: - newVal = val & 0xFF; - break; - case MISCREG_APIC_ARBITRATION_PRIORITY: - panic("Local APIC Arbitration Priority register unimplemented.\n"); - break; - case MISCREG_APIC_PROCESSOR_PRIORITY: - panic("Local APIC Processor Priority register unimplemented.\n"); - break; - case MISCREG_APIC_EOI: - panic("Local APIC EOI register unimplemented.\n"); - break; - case MISCREG_APIC_LOGICAL_DESTINATION: - newVal = val & 0xFF000000; - break; - case MISCREG_APIC_DESTINATION_FORMAT: - newVal = val | 0x0FFFFFFF; - break; - case MISCREG_APIC_SPURIOUS_INTERRUPT_VECTOR: - regVal[MISCREG_APIC_INTERNAL_STATE] &= ~ULL(1 << 1); - regVal[MISCREG_APIC_INTERNAL_STATE] |= val & (1 << 8); - if (val & (1 << 9)) - warn("Focus processor checking not implemented.\n"); - break; - case MISCREG_APIC_ERROR_STATUS: - { - if (regVal[MISCREG_APIC_INTERNAL_STATE] & 0x1) { - regVal[MISCREG_APIC_INTERNAL_STATE] &= ~ULL(0x1); - newVal = 0; - } else { - regVal[MISCREG_APIC_INTERNAL_STATE] |= ULL(0x1); - return; - } - - } - break; - case MISCREG_APIC_INTERRUPT_COMMAND_LOW: - panic("Local APIC Interrupt Command low" - " register unimplemented.\n"); - break; - case MISCREG_APIC_INTERRUPT_COMMAND_HIGH: - panic("Local APIC Interrupt Command high" - " register unimplemented.\n"); - break; - case MISCREG_APIC_LVT_TIMER: - case MISCREG_APIC_LVT_THERMAL_SENSOR: - case MISCREG_APIC_LVT_PERFORMANCE_MONITORING_COUNTERS: - case MISCREG_APIC_LVT_LINT0: - case MISCREG_APIC_LVT_LINT1: - case MISCREG_APIC_LVT_ERROR: - { - uint64_t readOnlyMask = (1 << 12) | (1 << 14); - newVal = (val & ~readOnlyMask) | - (regVal[miscReg] & readOnlyMask); - } - break; - case MISCREG_APIC_INITIAL_COUNT: - newVal = bits(val, 31, 0); - regVal[MISCREG_APIC_CURRENT_COUNT] = - tc->getCpuPtr()->curCycle() + - (16 * divideFromConf( - regVal[MISCREG_APIC_DIVIDE_CONFIGURATION])) * newVal; - //FIXME This should schedule the timer event. - break; - case MISCREG_APIC_CURRENT_COUNT: - //Local APIC Current Count register is read only. - return; - case MISCREG_APIC_DIVIDE_CONFIGURATION: - newVal = val & 0xB; - break; - } - setRegNoEffect(miscReg, newVal); +#if FULL_SYSTEM + if (isApicReg(miscReg)) { + Interrupts * interrupts = dynamic_cast( + tc->getCpuPtr()->getInterruptController()); + assert(interrupts); + interrupts->setReg( + ApicRegIndex(miscReg - MISCREG_APIC_START), val, tc); return; } +#endif switch(miscReg) { case MISCREG_CR0: @@ -408,6 +292,8 @@ void MiscRegFile::setReg(int miscReg, case MISCREG_TSC: regVal[MISCREG_TSC] = val - tc->getCpuPtr()->curCycle(); return; + default: + break; } setRegNoEffect(miscReg, newVal); } diff --git a/src/arch/x86/miscregfile.hh b/src/arch/x86/miscregfile.hh index 21caf3aa1..e59b8d3b1 100644 --- a/src/arch/x86/miscregfile.hh +++ b/src/arch/x86/miscregfile.hh @@ -91,7 +91,6 @@ #include "arch/x86/faults.hh" #include "arch/x86/miscregs.hh" #include "arch/x86/types.hh" -#include "sim/eventq.hh" #include "sim/host.hh" #include @@ -112,18 +111,6 @@ namespace X86ISA protected: MiscReg regVal[NumMiscRegs]; - class ApicTimerEvent : public Event - { - public: - void - process() - { - warn("Local APIC timer event doesn't do anything!\n"); - } - }; - - ApicTimerEvent apicTimerEvent; - public: void clear(); @@ -132,13 +119,13 @@ namespace X86ISA clear(); } - MiscReg readRegNoEffect(int miscReg); + MiscReg readRegNoEffect(MiscRegIndex miscReg); - MiscReg readReg(int miscReg, ThreadContext *tc); + MiscReg readReg(MiscRegIndex miscReg, ThreadContext *tc); - void setRegNoEffect(int miscReg, const MiscReg &val); + void setRegNoEffect(MiscRegIndex miscReg, const MiscReg &val); - void setReg(int miscReg, + void setReg(MiscRegIndex miscReg, const MiscReg &val, ThreadContext *tc); void serialize(std::ostream & os); diff --git a/src/arch/x86/miscregs.hh b/src/arch/x86/miscregs.hh index 5a6ee752d..dbf08ec5d 100644 --- a/src/arch/x86/miscregs.hh +++ b/src/arch/x86/miscregs.hh @@ -58,6 +58,7 @@ #ifndef __ARCH_X86_MISCREGS_HH__ #define __ARCH_X86_MISCREGS_HH__ +#include "arch/x86/apicregs.hh" #include "arch/x86/segmentregs.hh" #include "arch/x86/x86_traits.hh" #include "base/bitunion.hh" @@ -368,39 +369,9 @@ namespace X86ISA MISCREG_APIC_BASE, + // Space for the APIC registers MISCREG_APIC_START, - MISCREG_APIC_ID = MISCREG_APIC_START, - MISCREG_APIC_VERSION, - MISCREG_APIC_TASK_PRIORITY, - MISCREG_APIC_ARBITRATION_PRIORITY, - MISCREG_APIC_PROCESSOR_PRIORITY, - MISCREG_APIC_EOI, - MISCREG_APIC_LOGICAL_DESTINATION, - MISCREG_APIC_DESTINATION_FORMAT, - MISCREG_APIC_SPURIOUS_INTERRUPT_VECTOR, - - MISCREG_APIC_IN_SERVICE_BASE, - - MISCREG_APIC_TRIGGER_MODE_BASE = MISCREG_APIC_IN_SERVICE_BASE + 16, - - MISCREG_APIC_INTERRUPT_REQUEST_BASE = - MISCREG_APIC_TRIGGER_MODE_BASE + 16, - - MISCREG_APIC_ERROR_STATUS = MISCREG_APIC_INTERRUPT_REQUEST_BASE + 16, - MISCREG_APIC_INTERRUPT_COMMAND_LOW, - MISCREG_APIC_INTERRUPT_COMMAND_HIGH, - MISCREG_APIC_LVT_TIMER, - MISCREG_APIC_LVT_THERMAL_SENSOR, - MISCREG_APIC_LVT_PERFORMANCE_MONITORING_COUNTERS, - MISCREG_APIC_LVT_LINT0, - MISCREG_APIC_LVT_LINT1, - MISCREG_APIC_LVT_ERROR, - MISCREG_APIC_INITIAL_COUNT, - MISCREG_APIC_CURRENT_COUNT, - MISCREG_APIC_DIVIDE_CONFIGURATION, - MISCREG_APIC_END = MISCREG_APIC_DIVIDE_CONFIGURATION, - - MISCREG_APIC_INTERNAL_STATE, + MISCREG_APIC_END = MISCREG_APIC_START + NUM_APIC_REGS - 1, // "Fake" MSRs for internally implemented devices MISCREG_PCI_CONFIG_ADDRESS, @@ -408,6 +379,12 @@ namespace X86ISA NUM_MISCREGS }; + static inline bool + isApicReg(MiscRegIndex index) + { + return index >= MISCREG_APIC_START && index <= MISCREG_APIC_END; + } + static inline MiscRegIndex MISCREG_CR(int index) { @@ -510,24 +487,6 @@ namespace X86ISA return (MiscRegIndex)(MISCREG_SEG_ATTR_BASE + index); } - static inline MiscRegIndex - MISCREG_APIC_IN_SERVICE(int index) - { - return (MiscRegIndex)(MISCREG_APIC_IN_SERVICE_BASE + index); - } - - static inline MiscRegIndex - MISCREG_APIC_TRIGGER_MODE(int index) - { - return (MiscRegIndex)(MISCREG_APIC_TRIGGER_MODE_BASE + index); - } - - static inline MiscRegIndex - MISCREG_APIC_INTERRUPT_REQUEST(int index) - { - return (MiscRegIndex)(MISCREG_APIC_INTERRUPT_REQUEST_BASE + index); - } - /** * A type to describe the condition code bits of the RFLAGS register, * plus two flags, EZF and ECF, which are only visible to microcode. diff --git a/src/arch/x86/mmaped_ipr.hh b/src/arch/x86/mmaped_ipr.hh index cf3eba5e9..67a0b239e 100644 --- a/src/arch/x86/mmaped_ipr.hh +++ b/src/arch/x86/mmaped_ipr.hh @@ -96,7 +96,12 @@ namespace X86ISA #else Addr offset = pkt->getAddr() & mask(3); MiscRegIndex index = (MiscRegIndex)(pkt->getAddr() / sizeof(MiscReg)); - MiscReg data = htog(xc->readMiscRegNoEffect(index)); + MiscReg data; + if (isApicReg(index)) { + data = htog(xc->readMiscReg(index)); + } else { + data = htog(xc->readMiscRegNoEffect(index)); + } // Make sure we don't trot off the end of data. assert(offset + pkt->getSize() <= sizeof(MiscReg)); pkt->writeData(((uint8_t *)&data) + offset); diff --git a/src/arch/x86/regfile.cc b/src/arch/x86/regfile.cc index c8ec2a957..78fde7474 100644 --- a/src/arch/x86/regfile.cc +++ b/src/arch/x86/regfile.cc @@ -135,23 +135,23 @@ void RegFile::clear() MiscReg RegFile::readMiscRegNoEffect(int miscReg) { - return miscRegFile.readRegNoEffect(miscReg); + return miscRegFile.readRegNoEffect((MiscRegIndex)miscReg); } MiscReg RegFile::readMiscReg(int miscReg, ThreadContext *tc) { - return miscRegFile.readReg(miscReg, tc); + return miscRegFile.readReg((MiscRegIndex)miscReg, tc); } void RegFile::setMiscRegNoEffect(int miscReg, const MiscReg &val) { - miscRegFile.setRegNoEffect(miscReg, val); + miscRegFile.setRegNoEffect((MiscRegIndex)miscReg, val); } void RegFile::setMiscReg(int miscReg, const MiscReg &val, ThreadContext * tc) { - miscRegFile.setReg(miscReg, val, tc); + miscRegFile.setReg((MiscRegIndex)miscReg, val, tc); } FloatReg RegFile::readFloatReg(int floatReg, int width) diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index 692d6d022..616f026cf 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -663,31 +663,31 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) switch (paddr - baseAddr) { case 0x20: - regNum = MISCREG_APIC_ID; + regNum = APIC_ID; break; case 0x30: - regNum = MISCREG_APIC_VERSION; + regNum = APIC_VERSION; break; case 0x80: - regNum = MISCREG_APIC_TASK_PRIORITY; + regNum = APIC_TASK_PRIORITY; break; case 0x90: - regNum = MISCREG_APIC_ARBITRATION_PRIORITY; + regNum = APIC_ARBITRATION_PRIORITY; break; case 0xA0: - regNum = MISCREG_APIC_PROCESSOR_PRIORITY; + regNum = APIC_PROCESSOR_PRIORITY; break; case 0xB0: - regNum = MISCREG_APIC_EOI; + regNum = APIC_EOI; break; case 0xD0: - regNum = MISCREG_APIC_LOGICAL_DESTINATION; + regNum = APIC_LOGICAL_DESTINATION; break; case 0xE0: - regNum = MISCREG_APIC_DESTINATION_FORMAT; + regNum = APIC_DESTINATION_FORMAT; break; case 0xF0: - regNum = MISCREG_APIC_SPURIOUS_INTERRUPT_VECTOR; + regNum = APIC_SPURIOUS_INTERRUPT_VECTOR; break; case 0x100: case 0x108: @@ -705,8 +705,7 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) case 0x168: case 0x170: case 0x178: - regNum = MISCREG_APIC_IN_SERVICE( - (paddr - baseAddr - 0x100) / 0x8); + regNum = APIC_IN_SERVICE((paddr - baseAddr - 0x100) / 0x8); break; case 0x180: case 0x188: @@ -724,8 +723,7 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) case 0x1E8: case 0x1F0: case 0x1F8: - regNum = MISCREG_APIC_TRIGGER_MODE( - (paddr - baseAddr - 0x180) / 0x8); + regNum = APIC_TRIGGER_MODE((paddr - baseAddr - 0x180) / 0x8); break; case 0x200: case 0x208: @@ -743,50 +741,50 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) case 0x268: case 0x270: case 0x278: - regNum = MISCREG_APIC_INTERRUPT_REQUEST( - (paddr - baseAddr - 0x200) / 0x8); + regNum = APIC_INTERRUPT_REQUEST((paddr - baseAddr - 0x200) / 0x8); break; case 0x280: - regNum = MISCREG_APIC_ERROR_STATUS; + regNum = APIC_ERROR_STATUS; break; case 0x300: - regNum = MISCREG_APIC_INTERRUPT_COMMAND_LOW; + regNum = APIC_INTERRUPT_COMMAND_LOW; break; case 0x310: - regNum = MISCREG_APIC_INTERRUPT_COMMAND_HIGH; + regNum = APIC_INTERRUPT_COMMAND_HIGH; break; case 0x320: - regNum = MISCREG_APIC_LVT_TIMER; + regNum = APIC_LVT_TIMER; break; case 0x330: - regNum = MISCREG_APIC_LVT_THERMAL_SENSOR; + regNum = APIC_LVT_THERMAL_SENSOR; break; case 0x340: - regNum = MISCREG_APIC_LVT_PERFORMANCE_MONITORING_COUNTERS; + regNum = APIC_LVT_PERFORMANCE_MONITORING_COUNTERS; break; case 0x350: - regNum = MISCREG_APIC_LVT_LINT0; + regNum = APIC_LVT_LINT0; break; case 0x360: - regNum = MISCREG_APIC_LVT_LINT1; + regNum = APIC_LVT_LINT1; break; case 0x370: - regNum = MISCREG_APIC_LVT_ERROR; + regNum = APIC_LVT_ERROR; break; case 0x380: - regNum = MISCREG_APIC_INITIAL_COUNT; + regNum = APIC_INITIAL_COUNT; break; case 0x390: - regNum = MISCREG_APIC_CURRENT_COUNT; + regNum = APIC_CURRENT_COUNT; break; case 0x3E0: - regNum = MISCREG_APIC_DIVIDE_CONFIGURATION; + regNum = APIC_DIVIDE_CONFIGURATION; break; default: // A reserved register field. return new GeneralProtection(0); break; } + regNum += MISCREG_APIC_START; req->setPaddr(regNum * sizeof(MiscReg) + offset); } #endif diff --git a/src/arch/x86/utility.cc b/src/arch/x86/utility.cc index 5fe5bf8c3..852d72a2e 100644 --- a/src/arch/x86/utility.cc +++ b/src/arch/x86/utility.cc @@ -55,11 +55,17 @@ * Authors: Gabe Black */ +#include "config/full_system.hh" + +#if FULL_SYSTEM +#include "arch/x86/interrupts.hh" +#endif #include "arch/x86/intregs.hh" #include "arch/x86/miscregs.hh" #include "arch/x86/segmentregs.hh" #include "arch/x86/utility.hh" #include "arch/x86/x86_traits.hh" +#include "cpu/base.hh" #include "sim/system.hh" namespace X86ISA { @@ -254,9 +260,13 @@ void initCPU(ThreadContext *tc, int cpuId) lApicBase.bsp = (cpuId == 0); tc->setMiscReg(MISCREG_APIC_BASE, lApicBase); - tc->setMiscRegNoEffect(MISCREG_APIC_ID, cpuId << 24); + Interrupts * interrupts = dynamic_cast( + tc->getCpuPtr()->getInterruptController()); + assert(interrupts); + + interrupts->setRegNoEffect(APIC_ID, cpuId << 24); - tc->setMiscRegNoEffect(MISCREG_APIC_VERSION, (5 << 16) | 0x14); + interrupts->setRegNoEffect(APIC_VERSION, (5 << 16) | 0x14); // TODO Set the SMRAM base address (SMBASE) to 0x00030000 diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py index 1e3f0dbbc..c2385f6d0 100644 --- a/src/cpu/BaseCPU.py +++ b/src/cpu/BaseCPU.py @@ -39,14 +39,24 @@ default_tracer = ExeTracer() if build_env['TARGET_ISA'] == 'alpha': from AlphaTLB import AlphaDTB, AlphaITB + if build_env['FULL_SYSTEM']: + from AlphaInterrupts import AlphaInterrupts elif build_env['TARGET_ISA'] == 'sparc': from SparcTLB import SparcDTB, SparcITB + if build_env['FULL_SYSTEM']: + from SparcInterrupts import SparcInterrupts elif build_env['TARGET_ISA'] == 'x86': from X86TLB import X86DTB, X86ITB + if build_env['FULL_SYSTEM']: + from X86LocalApic import X86LocalApic elif build_env['TARGET_ISA'] == 'mips': from MipsTLB import MipsTLB,MipsDTB, MipsITB, MipsUTB + if build_env['FULL_SYSTEM']: + from MipsInterrupts import MipsInterrupts elif build_env['TARGET_ISA'] == 'arm': from ArmTLB import ArmTLB, ArmDTB, ArmITB, ArmUTB + if build_env['FULL_SYSTEM']: + from ArmInterrupts import ArmInterrupts class BaseCPU(MemObject): type = 'BaseCPU' @@ -74,22 +84,37 @@ class BaseCPU(MemObject): if build_env['TARGET_ISA'] == 'sparc': dtb = Param.SparcDTB(SparcDTB(), "Data TLB") itb = Param.SparcITB(SparcITB(), "Instruction TLB") + if build_env['FULL_SYSTEM']: + interrupts = Param.SparcInterrupts( + SparcInterrupts(), "Interrupt Controller") elif build_env['TARGET_ISA'] == 'alpha': dtb = Param.AlphaDTB(AlphaDTB(), "Data TLB") itb = Param.AlphaITB(AlphaITB(), "Instruction TLB") + if build_env['FULL_SYSTEM']: + interrupts = Param.AlphaInterrupts( + AlphaInterrupts(), "Interrupt Controller") elif build_env['TARGET_ISA'] == 'x86': dtb = Param.X86DTB(X86DTB(), "Data TLB") itb = Param.X86ITB(X86ITB(), "Instruction TLB") + if build_env['FULL_SYSTEM']: + interrupts = Param.X86LocalApic( + X86LocalApic(), "Interrupt Controller") elif build_env['TARGET_ISA'] == 'mips': UnifiedTLB = Param.Bool(True, "Is this a Unified TLB?") dtb = Param.MipsDTB(MipsDTB(), "Data TLB") itb = Param.MipsITB(MipsITB(), "Instruction TLB") tlb = Param.MipsUTB(MipsUTB(), "Unified TLB") + if build_env['FULL_SYSTEM']: + interrupts = Param.MipsInterrupts( + MipsInterrupts(), "Interrupt Controller") elif build_env['TARGET_ISA'] == 'arm': UnifiedTLB = Param.Bool(True, "Is this a Unified TLB?") dtb = Param.ArmDTB(ArmDTB(), "Data TLB") itb = Param.ArmITB(ArmITB(), "Instruction TLB") tlb = Param.ArmUTB(ArmUTB(), "Unified TLB") + if build_env['FULL_SYSTEM']: + interrupts = Param.ArmInterrupts( + ArmInterrupts(), "Interrupt Controller") else: print "Don't know what TLB to use for ISA %s" % \ build_env['TARGET_ISA'] diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 1ca0dc14b..def1e9920 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -94,7 +94,7 @@ CPUProgressEvent::description() const #if FULL_SYSTEM BaseCPU::BaseCPU(Params *p) - : MemObject(p), clock(p->clock), instCnt(0), + : MemObject(p), clock(p->clock), instCnt(0), interrupts(p->interrupts), number_of_threads(p->numThreads), system(p->system), phase(p->phase) #else @@ -381,33 +381,33 @@ BaseCPU::ProfileEvent::process() void BaseCPU::post_interrupt(int int_num, int index) { - interrupts.post(int_num, index); + interrupts->post(int_num, index); } void BaseCPU::clear_interrupt(int int_num, int index) { - interrupts.clear(int_num, index); + interrupts->clear(int_num, index); } void BaseCPU::clear_interrupts() { - interrupts.clear_all(); + interrupts->clear_all(); } void BaseCPU::serialize(std::ostream &os) { SERIALIZE_SCALAR(instCnt); - interrupts.serialize(os); + interrupts->serialize(os); } void BaseCPU::unserialize(Checkpoint *cp, const std::string §ion) { UNSERIALIZE_SCALAR(instCnt); - interrupts.unserialize(cp, section); + interrupts->unserialize(cp, section); } #endif // FULL_SYSTEM diff --git a/src/cpu/base.hh b/src/cpu/base.hh index c99efa834..a12c98ab0 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -107,13 +107,13 @@ class BaseCPU : public MemObject protected: // uint64_t interrupts[TheISA::NumInterruptLevels]; // uint64_t intstatus; - TheISA::Interrupts interrupts; + TheISA::Interrupts * interrupts; public: TheISA::Interrupts * getInterruptController() { - return &interrupts; + return interrupts; } virtual void post_interrupt(int int_num, int index); @@ -121,7 +121,7 @@ class BaseCPU : public MemObject virtual void clear_interrupts(); bool check_interrupts(ThreadContext * tc) const - { return interrupts.check_interrupts(tc); } + { return interrupts->check_interrupts(tc); } class ProfileEvent : public Event { diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index ac816fc18..c110bbd50 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -906,7 +906,7 @@ Fault FullO3CPU::getInterrupts() { // Check if there are any outstanding interrupts - return this->interrupts.getInterrupt(this->threadContexts[0]); + return this->interrupts->getInterrupt(this->threadContexts[0]); } template @@ -920,7 +920,7 @@ FullO3CPU::processInterrupts(Fault interrupt) // @todo: Allow other threads to handle interrupts. assert(interrupt != NoFault); - this->interrupts.updateIntrInfo(this->threadContexts[0]); + this->interrupts->updateIntrInfo(this->threadContexts[0]); DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name()); this->trap(interrupt, 0); diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index 9c0b95a1a..94af07525 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -678,10 +678,10 @@ OzoneCPU::processInterrupts() // Check if there are any outstanding interrupts //Handle the interrupts - Fault interrupt = this->interrupts.getInterrupt(thread.getTC()); + Fault interrupt = this->interrupts->getInterrupt(thread.getTC()); if (interrupt != NoFault) { - this->interrupts.updateIntrInfo(thread.getTC()); + this->interrupts->updateIntrInfo(thread.getTC()); interrupt->invoke(thread.getTC()); } } diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index 3fd699868..48e5db347 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -319,10 +319,10 @@ BaseSimpleCPU::checkForInterrupts() { #if FULL_SYSTEM if (check_interrupts(tc)) { - Fault interrupt = interrupts.getInterrupt(tc); + Fault interrupt = interrupts->getInterrupt(tc); if (interrupt != NoFault) { - interrupts.updateIntrInfo(tc); + interrupts->updateIntrInfo(tc); interrupt->invoke(tc); } } -- cgit v1.2.3 From 42ebebf99a7d6ce2358b152f643b52c7946f9202 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 11:08:00 -0700 Subject: X86: Make the local APIC accessible through the memory system directly, and make the timer work. --- src/arch/x86/interrupts.cc | 207 +++++++++++++++++++++++++++++++++++++++----- src/arch/x86/interrupts.hh | 33 +++++-- src/arch/x86/miscregfile.cc | 25 ------ src/arch/x86/miscregs.hh | 11 --- src/arch/x86/mmaped_ipr.hh | 6 +- src/arch/x86/tlb.cc | 141 ++---------------------------- src/arch/x86/utility.cc | 2 + src/arch/x86/x86_traits.hh | 17 +++- src/cpu/BaseCPU.py | 9 +- 9 files changed, 243 insertions(+), 208 deletions(-) (limited to 'src') diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc index 73536f2b4..5814859b3 100644 --- a/src/arch/x86/interrupts.cc +++ b/src/arch/x86/interrupts.cc @@ -55,10 +55,12 @@ * Authors: Gabe Black */ +#include "arch/x86/apicregs.hh" #include "arch/x86/interrupts.hh" #include "cpu/base.hh" -int divideFromConf(uint32_t conf) +int +divideFromConf(uint32_t conf) { // This figures out what division we want from the division configuration // register in the local APIC. The encoding is a little odd but it can @@ -68,14 +70,171 @@ int divideFromConf(uint32_t conf) return 1 << shift; } -uint32_t -X86ISA::Interrupts::readRegNoEffect(ApicRegIndex reg) +namespace X86ISA { - return regs[reg]; + +ApicRegIndex +decodeAddr(Addr paddr) +{ + ApicRegIndex regNum; + paddr &= ~mask(3); + switch (paddr) + { + case 0x20: + regNum = APIC_ID; + break; + case 0x30: + regNum = APIC_VERSION; + break; + case 0x80: + regNum = APIC_TASK_PRIORITY; + break; + case 0x90: + regNum = APIC_ARBITRATION_PRIORITY; + break; + case 0xA0: + regNum = APIC_PROCESSOR_PRIORITY; + break; + case 0xB0: + regNum = APIC_EOI; + break; + case 0xD0: + regNum = APIC_LOGICAL_DESTINATION; + break; + case 0xE0: + regNum = APIC_DESTINATION_FORMAT; + break; + case 0xF0: + regNum = APIC_SPURIOUS_INTERRUPT_VECTOR; + break; + case 0x100: + case 0x108: + case 0x110: + case 0x118: + case 0x120: + case 0x128: + case 0x130: + case 0x138: + case 0x140: + case 0x148: + case 0x150: + case 0x158: + case 0x160: + case 0x168: + case 0x170: + case 0x178: + regNum = APIC_IN_SERVICE((paddr - 0x100) / 0x8); + break; + case 0x180: + case 0x188: + case 0x190: + case 0x198: + case 0x1A0: + case 0x1A8: + case 0x1B0: + case 0x1B8: + case 0x1C0: + case 0x1C8: + case 0x1D0: + case 0x1D8: + case 0x1E0: + case 0x1E8: + case 0x1F0: + case 0x1F8: + regNum = APIC_TRIGGER_MODE((paddr - 0x180) / 0x8); + break; + case 0x200: + case 0x208: + case 0x210: + case 0x218: + case 0x220: + case 0x228: + case 0x230: + case 0x238: + case 0x240: + case 0x248: + case 0x250: + case 0x258: + case 0x260: + case 0x268: + case 0x270: + case 0x278: + regNum = APIC_INTERRUPT_REQUEST((paddr - 0x200) / 0x8); + break; + case 0x280: + regNum = APIC_ERROR_STATUS; + break; + case 0x300: + regNum = APIC_INTERRUPT_COMMAND_LOW; + break; + case 0x310: + regNum = APIC_INTERRUPT_COMMAND_HIGH; + break; + case 0x320: + regNum = APIC_LVT_TIMER; + break; + case 0x330: + regNum = APIC_LVT_THERMAL_SENSOR; + break; + case 0x340: + regNum = APIC_LVT_PERFORMANCE_MONITORING_COUNTERS; + break; + case 0x350: + regNum = APIC_LVT_LINT0; + break; + case 0x360: + regNum = APIC_LVT_LINT1; + break; + case 0x370: + regNum = APIC_LVT_ERROR; + break; + case 0x380: + regNum = APIC_INITIAL_COUNT; + break; + case 0x390: + regNum = APIC_CURRENT_COUNT; + break; + case 0x3E0: + regNum = APIC_DIVIDE_CONFIGURATION; + break; + default: + // A reserved register field. + panic("Accessed reserved register field %#x.\n", paddr); + break; + } + return regNum; +} +} + +Tick +X86ISA::Interrupts::read(PacketPtr pkt) +{ + Addr offset = pkt->getAddr() - pioAddr; + //Make sure we're at least only accessing one register. + if ((offset & ~mask(3)) != ((offset + pkt->getSize()) & ~mask(3))) + panic("Accessed more than one register at a time in the APIC!\n"); + ApicRegIndex reg = decodeAddr(offset); + uint32_t val = htog(readReg(reg)); + pkt->setData(((uint8_t *)&val) + (offset & mask(3))); + return latency; +} + +Tick +X86ISA::Interrupts::write(PacketPtr pkt) +{ + Addr offset = pkt->getAddr() - pioAddr; + //Make sure we're at least only accessing one register. + if ((offset & ~mask(3)) != ((offset + pkt->getSize()) & ~mask(3))) + panic("Accessed more than one register at a time in the APIC!\n"); + ApicRegIndex reg = decodeAddr(offset); + uint32_t val = regs[reg]; + pkt->writeData(((uint8_t *)&val) + (offset & mask(3))); + setReg(reg, gtoh(val)); + return latency; } uint32_t -X86ISA::Interrupts::readReg(ApicRegIndex reg, ThreadContext * tc) +X86ISA::Interrupts::readReg(ApicRegIndex reg) { if (reg >= APIC_TRIGGER_MODE(0) && reg <= APIC_TRIGGER_MODE(15)) { @@ -104,24 +263,19 @@ X86ISA::Interrupts::readReg(ApicRegIndex reg, ThreadContext * tc) break; case APIC_CURRENT_COUNT: { - uint32_t val = regs[reg] - tc->getCpuPtr()->curCycle(); + assert(clock); + uint32_t val = regs[reg] - curTick / clock; val /= (16 * divideFromConf(regs[APIC_DIVIDE_CONFIGURATION])); return val; } default: break; } - return readRegNoEffect(reg); -} - -void -X86ISA::Interrupts::setRegNoEffect(ApicRegIndex reg, uint32_t val) -{ - regs[reg] = val; + return regs[reg]; } void -X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val, ThreadContext *tc) +X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val) { uint32_t newVal = val; if (reg >= APIC_IN_SERVICE(0) && @@ -201,11 +355,24 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val, ThreadContext *tc) } break; case APIC_INITIAL_COUNT: - newVal = bits(val, 31, 0); - regs[APIC_CURRENT_COUNT] = - tc->getCpuPtr()->curCycle() + - (16 * divideFromConf(regs[APIC_DIVIDE_CONFIGURATION])) * newVal; - //FIXME This should schedule the timer event. + { + assert(clock); + newVal = bits(val, 31, 0); + uint32_t newCount = newVal * + (divideFromConf(regs[APIC_DIVIDE_CONFIGURATION]) * 16); + regs[APIC_CURRENT_COUNT] = newCount + curTick / clock; + // Find out how long a "tick" of the timer should take. + Tick timerTick = 16 * clock; + // Schedule on the edge of the next tick plus the new count. + Tick offset = curTick % timerTick; + if (offset) { + reschedule(apicTimerEvent, + curTick + (newCount + 1) * timerTick - offset, true); + } else { + reschedule(apicTimerEvent, + curTick + newCount * timerTick, true); + } + } break; case APIC_CURRENT_COUNT: //Local APIC Current Count register is read only. @@ -216,7 +383,7 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val, ThreadContext *tc) default: break; } - setRegNoEffect(reg, newVal); + regs[reg] = newVal; return; } diff --git a/src/arch/x86/interrupts.hh b/src/arch/x86/interrupts.hh index 68bb2e07d..1d5f600bd 100644 --- a/src/arch/x86/interrupts.hh +++ b/src/arch/x86/interrupts.hh @@ -61,6 +61,7 @@ #include "arch/x86/apicregs.hh" #include "arch/x86/faults.hh" #include "cpu/thread_context.hh" +#include "dev/io_device.hh" #include "params/X86LocalApic.hh" #include "sim/eventq.hh" #include "sim/sim_object.hh" @@ -70,10 +71,12 @@ class ThreadContext; namespace X86ISA { -class Interrupts : public SimObject +class Interrupts : public BasicPioDevice { protected: uint32_t regs[NUM_APIC_REGS]; + Tick latency; + Tick clock; class ApicTimerEvent : public Event { @@ -92,20 +95,38 @@ class Interrupts : public SimObject public: typedef X86LocalApicParams Params; + void setClock(Tick newClock) + { + clock = newClock; + } + const Params * params() const { return dynamic_cast(_params); } - uint32_t readRegNoEffect(ApicRegIndex reg); - uint32_t readReg(ApicRegIndex miscReg, ThreadContext *tc); + Tick read(PacketPtr pkt); + Tick write(PacketPtr pkt); + + void addressRanges(AddrRangeList &range_list) + { + range_list.clear(); + range_list.push_back(RangeEx(x86LocalAPICAddress(0, 0), + x86LocalAPICAddress(0, 0) + PageBytes)); + } - void setRegNoEffect(ApicRegIndex reg, uint32_t val); - void setReg(ApicRegIndex reg, uint32_t val, ThreadContext *tc); + uint32_t readReg(ApicRegIndex miscReg); + void setReg(ApicRegIndex reg, uint32_t val); + void setRegNoEffect(ApicRegIndex reg, uint32_t val) + { + regs[reg] = val; + } - Interrupts(Params * p) : SimObject(p) + Interrupts(Params * p) : BasicPioDevice(p), + latency(p->pio_latency), clock(0) { + pioSize = PageBytes; //Set the local apic DFR to the flat model. regs[APIC_DESTINATION_FORMAT] = (uint32_t)(-1); memset(regs, 0, sizeof(regs)); diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc index aba498616..388a83e8d 100644 --- a/src/arch/x86/miscregfile.cc +++ b/src/arch/x86/miscregfile.cc @@ -119,23 +119,11 @@ MiscReg MiscRegFile::readRegNoEffect(MiscRegIndex miscReg) !(miscReg > MISCREG_CR8 && miscReg <= MISCREG_CR15)); - if (isApicReg(miscReg)) { - panic("Can't readRegNoEffect from the local APIC.\n"); - } return regVal[miscReg]; } MiscReg MiscRegFile::readReg(MiscRegIndex miscReg, ThreadContext * tc) { -#if FULL_SYSTEM - if (isApicReg(miscReg)) { - Interrupts * interrupts = dynamic_cast( - tc->getCpuPtr()->getInterruptController()); - assert(interrupts); - return interrupts->readReg( - (ApicRegIndex)(miscReg - MISCREG_APIC_START), tc); - } -#endif if (miscReg == MISCREG_TSC) { return regVal[MISCREG_TSC] + tc->getCpuPtr()->curCycle(); } @@ -152,9 +140,6 @@ void MiscRegFile::setRegNoEffect(MiscRegIndex miscReg, const MiscReg &val) miscReg < MISCREG_CR8) && !(miscReg > MISCREG_CR8 && miscReg <= MISCREG_CR15)); - if (isApicReg(miscReg)) { - panic("Can't setRegNoEffect from the local APIC.\n"); - } regVal[miscReg] = val; } @@ -162,16 +147,6 @@ void MiscRegFile::setReg(MiscRegIndex miscReg, const MiscReg &val, ThreadContext * tc) { MiscReg newVal = val; -#if FULL_SYSTEM - if (isApicReg(miscReg)) { - Interrupts * interrupts = dynamic_cast( - tc->getCpuPtr()->getInterruptController()); - assert(interrupts); - interrupts->setReg( - ApicRegIndex(miscReg - MISCREG_APIC_START), val, tc); - return; - } -#endif switch(miscReg) { case MISCREG_CR0: diff --git a/src/arch/x86/miscregs.hh b/src/arch/x86/miscregs.hh index dbf08ec5d..a536d9e3b 100644 --- a/src/arch/x86/miscregs.hh +++ b/src/arch/x86/miscregs.hh @@ -58,7 +58,6 @@ #ifndef __ARCH_X86_MISCREGS_HH__ #define __ARCH_X86_MISCREGS_HH__ -#include "arch/x86/apicregs.hh" #include "arch/x86/segmentregs.hh" #include "arch/x86/x86_traits.hh" #include "base/bitunion.hh" @@ -369,22 +368,12 @@ namespace X86ISA MISCREG_APIC_BASE, - // Space for the APIC registers - MISCREG_APIC_START, - MISCREG_APIC_END = MISCREG_APIC_START + NUM_APIC_REGS - 1, - // "Fake" MSRs for internally implemented devices MISCREG_PCI_CONFIG_ADDRESS, NUM_MISCREGS }; - static inline bool - isApicReg(MiscRegIndex index) - { - return index >= MISCREG_APIC_START && index <= MISCREG_APIC_END; - } - static inline MiscRegIndex MISCREG_CR(int index) { diff --git a/src/arch/x86/mmaped_ipr.hh b/src/arch/x86/mmaped_ipr.hh index 67a0b239e..7056c0902 100644 --- a/src/arch/x86/mmaped_ipr.hh +++ b/src/arch/x86/mmaped_ipr.hh @@ -97,11 +97,7 @@ namespace X86ISA Addr offset = pkt->getAddr() & mask(3); MiscRegIndex index = (MiscRegIndex)(pkt->getAddr() / sizeof(MiscReg)); MiscReg data; - if (isApicReg(index)) { - data = htog(xc->readMiscReg(index)); - } else { - data = htog(xc->readMiscRegNoEffect(index)); - } + data = htog(xc->readMiscRegNoEffect(index)); // Make sure we don't trot off the end of data. assert(offset + pkt->getSize() <= sizeof(MiscReg)); pkt->writeData(((uint8_t *)&data) + offset); diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index 616f026cf..5db678919 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -638,10 +638,9 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) // Check for an access to the local APIC #if FULL_SYSTEM LocalApicBase localApicBase = tc->readMiscRegNoEffect(MISCREG_APIC_BASE); - Addr baseAddr = localApicBase.base << 12; + Addr baseAddr = localApicBase.base * PageBytes; Addr paddr = req->getPaddr(); - if (baseAddr <= paddr && baseAddr + (1 << 12) > paddr) { - req->setMmapedIpr(true); + if (baseAddr <= paddr && baseAddr + PageBytes > paddr) { // The Intel developer's manuals say the below restrictions apply, // but the linux kernel, because of a compiler optimization, breaks // them. @@ -653,139 +652,9 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) if (req->getSize() != (32/8)) return new GeneralProtection(0); */ - - //Make sure we're at least only accessing one register. - if ((paddr & ~mask(3)) != ((paddr + req->getSize()) & ~mask(3))) - panic("Accessed more than one register at a time in the APIC!\n"); - MiscReg regNum; - Addr offset = paddr & mask(3); - paddr &= ~mask(3); - switch (paddr - baseAddr) - { - case 0x20: - regNum = APIC_ID; - break; - case 0x30: - regNum = APIC_VERSION; - break; - case 0x80: - regNum = APIC_TASK_PRIORITY; - break; - case 0x90: - regNum = APIC_ARBITRATION_PRIORITY; - break; - case 0xA0: - regNum = APIC_PROCESSOR_PRIORITY; - break; - case 0xB0: - regNum = APIC_EOI; - break; - case 0xD0: - regNum = APIC_LOGICAL_DESTINATION; - break; - case 0xE0: - regNum = APIC_DESTINATION_FORMAT; - break; - case 0xF0: - regNum = APIC_SPURIOUS_INTERRUPT_VECTOR; - break; - case 0x100: - case 0x108: - case 0x110: - case 0x118: - case 0x120: - case 0x128: - case 0x130: - case 0x138: - case 0x140: - case 0x148: - case 0x150: - case 0x158: - case 0x160: - case 0x168: - case 0x170: - case 0x178: - regNum = APIC_IN_SERVICE((paddr - baseAddr - 0x100) / 0x8); - break; - case 0x180: - case 0x188: - case 0x190: - case 0x198: - case 0x1A0: - case 0x1A8: - case 0x1B0: - case 0x1B8: - case 0x1C0: - case 0x1C8: - case 0x1D0: - case 0x1D8: - case 0x1E0: - case 0x1E8: - case 0x1F0: - case 0x1F8: - regNum = APIC_TRIGGER_MODE((paddr - baseAddr - 0x180) / 0x8); - break; - case 0x200: - case 0x208: - case 0x210: - case 0x218: - case 0x220: - case 0x228: - case 0x230: - case 0x238: - case 0x240: - case 0x248: - case 0x250: - case 0x258: - case 0x260: - case 0x268: - case 0x270: - case 0x278: - regNum = APIC_INTERRUPT_REQUEST((paddr - baseAddr - 0x200) / 0x8); - break; - case 0x280: - regNum = APIC_ERROR_STATUS; - break; - case 0x300: - regNum = APIC_INTERRUPT_COMMAND_LOW; - break; - case 0x310: - regNum = APIC_INTERRUPT_COMMAND_HIGH; - break; - case 0x320: - regNum = APIC_LVT_TIMER; - break; - case 0x330: - regNum = APIC_LVT_THERMAL_SENSOR; - break; - case 0x340: - regNum = APIC_LVT_PERFORMANCE_MONITORING_COUNTERS; - break; - case 0x350: - regNum = APIC_LVT_LINT0; - break; - case 0x360: - regNum = APIC_LVT_LINT1; - break; - case 0x370: - regNum = APIC_LVT_ERROR; - break; - case 0x380: - regNum = APIC_INITIAL_COUNT; - break; - case 0x390: - regNum = APIC_CURRENT_COUNT; - break; - case 0x3E0: - regNum = APIC_DIVIDE_CONFIGURATION; - break; - default: - // A reserved register field. - return new GeneralProtection(0); - break; - } - regNum += MISCREG_APIC_START; - req->setPaddr(regNum * sizeof(MiscReg) + offset); + // Force the access to be uncacheable. + req->setFlags(req->getFlags() | UNCACHEABLE); + req->setPaddr(x86LocalAPICAddress(tc->readCpuId(), paddr - baseAddr)); } #endif return NoFault; diff --git a/src/arch/x86/utility.cc b/src/arch/x86/utility.cc index 852d72a2e..43a5ca1a9 100644 --- a/src/arch/x86/utility.cc +++ b/src/arch/x86/utility.cc @@ -267,6 +267,8 @@ void initCPU(ThreadContext *tc, int cpuId) interrupts->setRegNoEffect(APIC_ID, cpuId << 24); interrupts->setRegNoEffect(APIC_VERSION, (5 << 16) | 0x14); + + interrupts->setClock(tc->getCpuPtr()->ticks(16)); // TODO Set the SMRAM base address (SMBASE) to 0x00030000 diff --git a/src/arch/x86/x86_traits.hh b/src/arch/x86/x86_traits.hh index f46279c81..6b4671a08 100644 --- a/src/arch/x86/x86_traits.hh +++ b/src/arch/x86/x86_traits.hh @@ -55,11 +55,13 @@ * Authors: Gabe Black */ -#include "sim/host.hh" - #ifndef __ARCH_X86_X86TRAITS_HH__ #define __ARCH_X86_X86TRAITS_HH__ +#include + +#include "sim/host.hh" + namespace X86ISA { const int NumMicroIntRegs = 16; @@ -90,6 +92,10 @@ namespace X86ISA const Addr PhysAddrPrefixIO = ULL(0x8000000000000000); const Addr PhysAddrPrefixPciConfig = ULL(0xC000000000000000); + const Addr PhysAddrPrefixLocalAPIC = ULL(0xA000000000000000); + // Each APIC gets two pages. One page is used for local apics to field + // accesses from the CPU, and the other is for all APICs to communicate. + const Addr PhysAddrAPICRangeSize = 1 << 12; static inline Addr x86IOAddress(const uint32_t port) @@ -102,6 +108,13 @@ namespace X86ISA { return PhysAddrPrefixPciConfig | addr; } + + static inline Addr + x86LocalAPICAddress(const uint8_t id, const uint16_t addr) + { + assert(addr < (1 << 12)); + return PhysAddrPrefixLocalAPIC | (id * (1 << 12)) | addr; + } } #endif //__ARCH_X86_X86TRAITS_HH__ diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py index c2385f6d0..78b9ae944 100644 --- a/src/cpu/BaseCPU.py +++ b/src/cpu/BaseCPU.py @@ -97,8 +97,9 @@ class BaseCPU(MemObject): dtb = Param.X86DTB(X86DTB(), "Data TLB") itb = Param.X86ITB(X86ITB(), "Instruction TLB") if build_env['FULL_SYSTEM']: - interrupts = Param.X86LocalApic( - X86LocalApic(), "Interrupt Controller") + _localApic = X86LocalApic(pio_addr=0xa000000000000000) + interrupts = \ + Param.X86LocalApic(_localApic, "Interrupt Controller") elif build_env['TARGET_ISA'] == 'mips': UnifiedTLB = Param.Bool(True, "Is this a Unified TLB?") dtb = Param.MipsDTB(MipsDTB(), "Data TLB") @@ -141,7 +142,9 @@ class BaseCPU(MemObject): _mem_ports = [] if build_env['TARGET_ISA'] == 'x86' and build_env['FULL_SYSTEM']: - _mem_ports = ["itb.walker.port", "dtb.walker.port"] + _mem_ports = ["itb.walker.port", + "dtb.walker.port", + "interrupts.pio"] def connectMemPorts(self, bus): for p in self._mem_ports: -- cgit v1.2.3 From e0f137a87c21eca5faa35cf0b9b529c4243d3ff3 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 12:07:25 -0700 Subject: X86: Add a LocalApic trace flag. --- src/arch/x86/SConscript | 2 ++ src/arch/x86/interrupts.cc | 6 ++++++ 2 files changed, 8 insertions(+) (limited to 'src') diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript index e019b77c9..c1a1b9ba3 100644 --- a/src/arch/x86/SConscript +++ b/src/arch/x86/SConscript @@ -109,6 +109,8 @@ if env['TARGET_ISA'] == 'x86': TraceFlag('X86') if env['FULL_SYSTEM']: + TraceFlag('LocalApic') + SimObject('X86LocalApic.py') SimObject('X86System.py') diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc index 5814859b3..6f1920de0 100644 --- a/src/arch/x86/interrupts.cc +++ b/src/arch/x86/interrupts.cc @@ -215,6 +215,9 @@ X86ISA::Interrupts::read(PacketPtr pkt) panic("Accessed more than one register at a time in the APIC!\n"); ApicRegIndex reg = decodeAddr(offset); uint32_t val = htog(readReg(reg)); + DPRINTF(LocalApic, + "Reading Local APIC register %d at offset %#x as %#x.\n", + reg, offset, val); pkt->setData(((uint8_t *)&val) + (offset & mask(3))); return latency; } @@ -229,6 +232,9 @@ X86ISA::Interrupts::write(PacketPtr pkt) ApicRegIndex reg = decodeAddr(offset); uint32_t val = regs[reg]; pkt->writeData(((uint8_t *)&val) + (offset & mask(3))); + DPRINTF(LocalApic, + "Writing Local APIC register %d at offset %#x as %#x.\n", + reg, offset, gtoh(val)); setReg(reg, gtoh(val)); return latency; } -- cgit v1.2.3 From e4590131825d27293d9642d2ac118ff03cc894f4 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 12:08:51 -0700 Subject: Create a message port for sending messages as apposed to reading/writing a memory range. --- src/mem/SConscript | 1 + src/mem/mport.cc | 60 ++++++++++++++++++++++++++++++++++++++++ src/mem/mport.hh | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/mem/packet.cc | 5 ++++ src/mem/packet.hh | 2 ++ src/mem/tport.cc | 2 +- 6 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 src/mem/mport.cc create mode 100644 src/mem/mport.hh (limited to 'src') diff --git a/src/mem/SConscript b/src/mem/SConscript index d391fbd5c..c181c88c6 100644 --- a/src/mem/SConscript +++ b/src/mem/SConscript @@ -47,6 +47,7 @@ Source('packet.cc') Source('physical.cc') Source('port.cc') Source('tport.cc') +Source('mport.cc') if env['FULL_SYSTEM']: Source('vport.cc') diff --git a/src/mem/mport.cc b/src/mem/mport.cc new file mode 100644 index 000000000..72bcfc7fd --- /dev/null +++ b/src/mem/mport.cc @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "mem/mport.hh" + +Tick +MessagePort::recvAtomic(PacketPtr pkt) +{ + if (pkt->cmd == MemCmd::MessageReq) { + // We received a message. + return recvMessage(pkt); + } else if (pkt->cmd == MemCmd::MessageResp) { + return recvResponse(pkt); + } else if (pkt->wasNacked()) { + return recvNack(pkt); + } else if (pkt->isError()) { + panic("Packet is error.\n"); + } else { + panic("Unexpected memory command %s.\n", pkt->cmd.toString()); + } +} + +void +MessagePort::sendMessageTiming(PacketPtr pkt, Tick latency) +{ + schedSendTiming(pkt, curTick + latency); +} + +Tick +MessagePort::sendMessageAtomic(PacketPtr pkt) +{ + return sendAtomic(pkt); +} diff --git a/src/mem/mport.hh b/src/mem/mport.hh new file mode 100644 index 000000000..5975f89f0 --- /dev/null +++ b/src/mem/mport.hh @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __MEM_MPORT_HH__ +#define __MEM_MPORT_HH__ + +#include "mem/tport.hh" + +/* + * This file defines a port class which is used for sending and receiving + * messages. These messages are atomic units which don't interact and + * should be smaller than a cache block. This class is based on + * the underpinnings of SimpleTimingPort, but it tweaks some of the external + * functions. + */ + +class MessagePort : public SimpleTimingPort +{ + public: + MessagePort(std::string pname, MemObject *_owner = NULL) : + SimpleTimingPort(pname, _owner) + {} + + virtual ~MessagePort() + {} + + void + recvFunctional(PacketPtr pkt) + { + recvAtomic(pkt); + } + + Tick recvAtomic(PacketPtr pkt); + + virtual Tick recvMessage(PacketPtr pkt) = 0; + + // Accept and ignore responses. + virtual Tick recvResponse(PacketPtr pkt) + { + return 0; + } + + // Since by default we're assuming everything we send is accepted, panic. + virtual Tick recvNack(PacketPtr pkt) + { + panic("Unhandled message nack.\n"); + } + + void sendMessageTiming(PacketPtr pkt, Tick latency); + Tick sendMessageAtomic(PacketPtr pkt); +}; + +#endif diff --git a/src/mem/packet.cc b/src/mem/packet.cc index 35fd44e5b..f27bd9dbf 100644 --- a/src/mem/packet.cc +++ b/src/mem/packet.cc @@ -118,6 +118,11 @@ MemCmd::commandInfo[] = /* SwapResp -- for Swap ldstub type operations */ { SET5(IsRead, IsWrite, NeedsExclusive, IsResponse, HasData), InvalidCmd, "SwapResp" }, + /* IntReq -- for interrupts */ + { SET4(IsWrite, IsRequest, NeedsResponse, HasData), + MessageReq, "MessageReq" }, + /* IntResp -- for interrupts */ + { SET2(IsWrite, IsResponse), MessageResp, "MessageResp" }, /* NetworkNackError -- nacked at network layer (not by protocol) */ { SET2(IsResponse, IsError), InvalidCmd, "NetworkNackError" }, /* InvalidDestError -- packet dest field invalid */ diff --git a/src/mem/packet.hh b/src/mem/packet.hh index 36aff5b42..1227cec89 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -85,6 +85,8 @@ class MemCmd StoreCondResp, SwapReq, SwapResp, + MessageReq, + MessageResp, // Error responses // @TODO these should be classified as responses rather than // requests; coding them as requests initially for backwards diff --git a/src/mem/tport.cc b/src/mem/tport.cc index 254487af8..f8850df6c 100644 --- a/src/mem/tport.cc +++ b/src/mem/tport.cc @@ -65,7 +65,7 @@ SimpleTimingPort::recvTiming(PacketPtr pkt) // code to hanldle nacks here, but I'm pretty sure it didn't work // correctly with the drain code, so that would need to be fixed // if we ever added it back. - assert(pkt->isRequest()); + //assert(pkt->isRequest()); if (pkt->memInhibitAsserted()) { // snooper will supply based on copy of packet -- cgit v1.2.3 From 557bde43c331024eb5cecf4093a24a5b7a9cc266 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 13:28:54 -0700 Subject: X86: Make APICs communicate through the memory system. --- src/arch/x86/X86LocalApic.py | 1 + src/arch/x86/interrupts.cc | 21 ++++++++++ src/arch/x86/interrupts.hh | 21 ++++++++-- src/arch/x86/intmessage.hh | 84 ++++++++++++++++++++++++++++++++++++++ src/arch/x86/x86_traits.hh | 8 ++++ src/cpu/BaseCPU.py | 3 +- src/dev/x86/I82094AA.py | 1 + src/dev/x86/SouthBridge.py | 1 + src/dev/x86/i82094aa.cc | 96 +++++++++++++++++++++++++++++--------------- src/dev/x86/i82094aa.hh | 15 +++++++ src/dev/x86/i8259.hh | 6 +-- src/dev/x86/intdev.hh | 68 ++++++++++++++++++++++++++++++- 12 files changed, 285 insertions(+), 40 deletions(-) create mode 100644 src/arch/x86/intmessage.hh (limited to 'src') diff --git a/src/arch/x86/X86LocalApic.py b/src/arch/x86/X86LocalApic.py index 94e32ae50..483c65ef8 100644 --- a/src/arch/x86/X86LocalApic.py +++ b/src/arch/x86/X86LocalApic.py @@ -33,3 +33,4 @@ class X86LocalApic(BasicPioDevice): type = 'X86LocalApic' cxx_class = 'X86ISA::Interrupts' pio_latency = Param.Latency('1ns', 'Programmed IO latency in simticks') + int_port = Port("Port for sending and receiving interrupt messages") diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc index 6f1920de0..5614a37eb 100644 --- a/src/arch/x86/interrupts.cc +++ b/src/arch/x86/interrupts.cc @@ -239,6 +239,27 @@ X86ISA::Interrupts::write(PacketPtr pkt) return latency; } +Tick +X86ISA::Interrupts::recvMessage(PacketPtr pkt) +{ + Addr offset = pkt->getAddr() - x86InterruptAddress(0, 0); + assert(pkt->cmd == MemCmd::MessageReq); + switch(offset) + { + case 0: + DPRINTF(LocalApic, "Got Trigger Interrupt message.\n"); + break; + default: + panic("Local apic got unknown interrupt message at offset %#x.\n", + offset); + break; + } + delete pkt->req; + delete pkt; + return latency; +} + + uint32_t X86ISA::Interrupts::readReg(ApicRegIndex reg) { diff --git a/src/arch/x86/interrupts.hh b/src/arch/x86/interrupts.hh index 1d5f600bd..c4760dc0f 100644 --- a/src/arch/x86/interrupts.hh +++ b/src/arch/x86/interrupts.hh @@ -62,16 +62,16 @@ #include "arch/x86/faults.hh" #include "cpu/thread_context.hh" #include "dev/io_device.hh" +#include "dev/x86/intdev.hh" #include "params/X86LocalApic.hh" #include "sim/eventq.hh" -#include "sim/sim_object.hh" class ThreadContext; namespace X86ISA { -class Interrupts : public BasicPioDevice +class Interrupts : public BasicPioDevice, IntDev { protected: uint32_t regs[NUM_APIC_REGS]; @@ -108,6 +108,7 @@ class Interrupts : public BasicPioDevice Tick read(PacketPtr pkt); Tick write(PacketPtr pkt); + Tick recvMessage(PacketPtr pkt); void addressRanges(AddrRangeList &range_list) { @@ -116,6 +117,13 @@ class Interrupts : public BasicPioDevice x86LocalAPICAddress(0, 0) + PageBytes)); } + void getIntAddrRange(AddrRangeList &range_list) + { + range_list.clear(); + range_list.push_back(RangeEx(x86InterruptAddress(0, 0), + x86InterruptAddress(0, 0) + PhysAddrAPICRangeSize)); + } + uint32_t readReg(ApicRegIndex miscReg); void setReg(ApicRegIndex reg, uint32_t val); void setRegNoEffect(ApicRegIndex reg, uint32_t val) @@ -123,7 +131,7 @@ class Interrupts : public BasicPioDevice regs[reg] = val; } - Interrupts(Params * p) : BasicPioDevice(p), + Interrupts(Params * p) : BasicPioDevice(p), IntDev(this), latency(p->pio_latency), clock(0) { pioSize = PageBytes; @@ -133,6 +141,13 @@ class Interrupts : public BasicPioDevice clear_all(); } + Port *getPort(const std::string &if_name, int idx = -1) + { + if (if_name == "int_port") + return intPort; + return BasicPioDevice::getPort(if_name, idx); + } + int InterruptLevel(uint64_t softint) { panic("Interrupts::InterruptLevel unimplemented!\n"); diff --git a/src/arch/x86/intmessage.hh b/src/arch/x86/intmessage.hh new file mode 100644 index 000000000..64e821a41 --- /dev/null +++ b/src/arch/x86/intmessage.hh @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_INTMESSAGE_HH__ +#define __ARCH_X86_INTMESSAGE_HH__ + +#include "arch/x86/x86_traits.hh" +#include "base/bitunion.hh" +#include "mem/packet.hh" +#include "mem/request.hh" +#include "sim/host.hh" + +namespace X86ISA +{ + BitUnion32(TriggerIntMessage) + Bitfield<7, 0> destination; + Bitfield<15, 8> vector; + Bitfield<18, 16> deliveryMode; + Bitfield<19> destMode; + EndBitUnion(TriggerIntMessage) + + static const Addr TriggerIntOffset = 0; + + static inline PacketPtr + prepIntRequest(const uint8_t id, Addr offset, Addr size) + { + RequestPtr req = new Request(x86InterruptAddress(id, offset), + size, UNCACHEABLE); + PacketPtr pkt = new Packet(req, MemCmd::MessageReq, Packet::Broadcast); + pkt->allocate(); + return pkt; + } + + template + PacketPtr + buildIntRequest(const uint8_t id, T payload, Addr offset, Addr size) + { + PacketPtr pkt = prepIntRequest(id, offset, size); + pkt->set(payload); + return pkt; + } + + static inline PacketPtr + buildIntRequest(const uint8_t id, TriggerIntMessage payload) + { + return buildIntRequest(id, payload, TriggerIntOffset, + sizeof(TriggerIntMessage)); + } + + static inline PacketPtr + buildIntResponse() + { + panic("buildIntResponse not implemented.\n"); + } +} + +#endif diff --git a/src/arch/x86/x86_traits.hh b/src/arch/x86/x86_traits.hh index 6b4671a08..be7572517 100644 --- a/src/arch/x86/x86_traits.hh +++ b/src/arch/x86/x86_traits.hh @@ -93,6 +93,7 @@ namespace X86ISA const Addr PhysAddrPrefixIO = ULL(0x8000000000000000); const Addr PhysAddrPrefixPciConfig = ULL(0xC000000000000000); const Addr PhysAddrPrefixLocalAPIC = ULL(0xA000000000000000); + const Addr PhysAddrPrefixInterrupts = ULL(0x2000000000000000); // Each APIC gets two pages. One page is used for local apics to field // accesses from the CPU, and the other is for all APICs to communicate. const Addr PhysAddrAPICRangeSize = 1 << 12; @@ -115,6 +116,13 @@ namespace X86ISA assert(addr < (1 << 12)); return PhysAddrPrefixLocalAPIC | (id * (1 << 12)) | addr; } + + static inline Addr + x86InterruptAddress(const uint8_t id, const uint16_t addr) + { + assert(addr < PhysAddrAPICRangeSize); + return PhysAddrPrefixInterrupts | (id * PhysAddrAPICRangeSize) | addr; + } } #endif //__ARCH_X86_X86TRAITS_HH__ diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py index 78b9ae944..51d447f0b 100644 --- a/src/cpu/BaseCPU.py +++ b/src/cpu/BaseCPU.py @@ -144,7 +144,8 @@ class BaseCPU(MemObject): if build_env['TARGET_ISA'] == 'x86' and build_env['FULL_SYSTEM']: _mem_ports = ["itb.walker.port", "dtb.walker.port", - "interrupts.pio"] + "interrupts.pio", + "interrupts.int_port"] def connectMemPorts(self, bus): for p in self._mem_ports: diff --git a/src/dev/x86/I82094AA.py b/src/dev/x86/I82094AA.py index 731d831f0..b4ad96a9f 100644 --- a/src/dev/x86/I82094AA.py +++ b/src/dev/x86/I82094AA.py @@ -36,6 +36,7 @@ class I82094AA(BasicPioDevice): cxx_class = 'X86ISA::I82094AA' pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") pio_addr = Param.Addr("Device address") + int_port = Port("Port for sending and receiving interrupt messages") def pin(self, line): return X86IntPin(device=self, line=line) diff --git a/src/dev/x86/SouthBridge.py b/src/dev/x86/SouthBridge.py index 15ffe153f..8a9bea01b 100644 --- a/src/dev/x86/SouthBridge.py +++ b/src/dev/x86/SouthBridge.py @@ -72,3 +72,4 @@ class SouthBridge(SimObject): self.pit.pio = bus.port self.speaker.pio = bus.port self.io_apic.pio = bus.port + self.io_apic.int_port = bus.port diff --git a/src/dev/x86/i82094aa.cc b/src/dev/x86/i82094aa.cc index 713f59592..f944e7171 100644 --- a/src/dev/x86/i82094aa.cc +++ b/src/dev/x86/i82094aa.cc @@ -28,12 +28,13 @@ * Authors: Gabe Black */ +#include "arch/x86/intmessage.hh" #include "dev/x86/i82094aa.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" #include "sim/system.hh" -X86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), +X86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), IntDev(this), latency(p->pio_latency), pioAddr(p->pio_addr) { // This assumes there's only one I/O APIC in the system @@ -140,11 +141,56 @@ X86ISA::I82094AA::signalInterrupt(int line) DPRINTF(I82094AA, "Entry was masked.\n"); return; } else { + if (DTRACE(I82094AA)) { + switch(entry.deliveryMode) { + case 0: + DPRINTF(I82094AA, "Delivery mode is: Fixed.\n"); + break; + case 1: + DPRINTF(I82094AA, "Delivery mode is: Lowest Priority.\n"); + break; + case 2: + DPRINTF(I82094AA, "Delivery mode is: SMI.\n"); + break; + case 3: + fatal("Tried to use reserved delivery mode " + "for IO APIC entry %d.\n", line); + break; + case 4: + DPRINTF(I82094AA, "Delivery mode is: NMI.\n"); + break; + case 5: + DPRINTF(I82094AA, "Delivery mode is: INIT.\n"); + break; + case 6: + fatal("Tried to use reserved delivery mode " + "for IO APIC entry %d.\n", line); + break; + case 7: + DPRINTF(I82094AA, "Delivery mode is: ExtINT.\n"); + break; + } + DPRINTF(I82094AA, "Vector is %#x.\n", entry.vector); + } + + TriggerIntMessage message; + message.destination = entry.dest; + message.vector = entry.vector; + message.deliveryMode = entry.deliveryMode; + message.destMode = entry.destMode; + if (entry.destMode == 0) { DPRINTF(I82094AA, - "Would send interrupt to APIC ID %d.\n", entry.dest); + "Sending interrupt to APIC ID %d.\n", entry.dest); + PacketPtr pkt = buildIntRequest(entry.dest, message); + if (sys->getMemoryMode() == Enums::timing) + intPort->sendMessageTiming(pkt, latency); + else if (sys->getMemoryMode() == Enums::atomic) + intPort->sendMessageAtomic(pkt); + else + panic("Unrecognized memory mode.\n"); } else { - DPRINTF(I82094AA, "Would send interrupts to APIC IDs:" + DPRINTF(I82094AA, "Sending interrupts to APIC IDs:" "%s%s%s%s%s%s%s%s\n", bits((int)entry.dest, 0) ? " 0": "", bits((int)entry.dest, 1) ? " 1": "", @@ -155,36 +201,22 @@ X86ISA::I82094AA::signalInterrupt(int line) bits((int)entry.dest, 6) ? " 6": "", bits((int)entry.dest, 7) ? " 7": "" ); + uint8_t dests = entry.dest; + uint8_t id = 0; + while(dests) { + if (dests & 0x1) { + PacketPtr pkt = buildIntRequest(id, message); + if (sys->getMemoryMode() == Enums::timing) + intPort->sendMessageTiming(pkt, latency); + else if (sys->getMemoryMode() == Enums::atomic) + intPort->sendMessageAtomic(pkt); + else + panic("Unrecognized memory mode.\n"); + } + dests >>= 1; + id++; + } } - switch(entry.deliveryMode) { - case 0: - DPRINTF(I82094AA, "Delivery mode is: Fixed.\n"); - break; - case 1: - DPRINTF(I82094AA, "Delivery mode is: Lowest Priority.\n"); - break; - case 2: - DPRINTF(I82094AA, "Delivery mode is: SMI.\n"); - break; - case 3: - fatal("Tried to use reserved delivery mode " - "for IO APIC entry %d.\n", line); - break; - case 4: - DPRINTF(I82094AA, "Delivery mode is: NMI.\n"); - break; - case 5: - DPRINTF(I82094AA, "Delivery mode is: INIT.\n"); - break; - case 6: - fatal("Tried to use reserved delivery mode " - "for IO APIC entry %d.\n", line); - break; - case 7: - DPRINTF(I82094AA, "Delivery mode is: ExtINT.\n"); - break; - } - DPRINTF(I82094AA, "Vector is %#x.\n", entry.vector); } } diff --git a/src/dev/x86/i82094aa.hh b/src/dev/x86/i82094aa.hh index b442e3e92..6c874a5f9 100644 --- a/src/dev/x86/i82094aa.hh +++ b/src/dev/x86/i82094aa.hh @@ -60,6 +60,7 @@ class I82094AA : public PioDevice, public IntDev EndBitUnion(RedirTableEntry) protected: + System * system; Tick latency; Addr pioAddr; @@ -95,9 +96,23 @@ class I82094AA : public PioDevice, public IntDev range_list.push_back(RangeEx(pioAddr + 16, pioAddr + 20)); } + void getIntAddrRange(AddrRangeList &range_list) + { + range_list.clear(); + range_list.push_back(RangeEx(x86InterruptAddress(1, 0), + x86InterruptAddress(1, 0) + PhysAddrAPICRangeSize)); + } + void writeReg(uint8_t offset, uint32_t value); uint32_t readReg(uint8_t offset); + Port *getPort(const std::string &if_name, int idx = -1) + { + if (if_name == "int_port") + return intPort; + return PioDevice::getPort(if_name, idx); + } + void signalInterrupt(int line); }; diff --git a/src/dev/x86/i8259.hh b/src/dev/x86/i8259.hh index f38644222..1c14e5397 100644 --- a/src/dev/x86/i8259.hh +++ b/src/dev/x86/i8259.hh @@ -74,9 +74,9 @@ class I8259 : public BasicPioDevice, public IntDev return dynamic_cast(_params); } - I8259(Params * p) : BasicPioDevice(p), latency(p->pio_latency), - output(p->output), mode(p->mode), readIRR(true), - initControlWord(0) + I8259(Params * p) : BasicPioDevice(p), IntDev(this), + latency(p->pio_latency), output(p->output), + mode(p->mode), readIRR(true), initControlWord(0) { pioSize = 2; } diff --git a/src/dev/x86/intdev.hh b/src/dev/x86/intdev.hh index 7a369f8fa..d36ed462a 100644 --- a/src/dev/x86/intdev.hh +++ b/src/dev/x86/intdev.hh @@ -32,7 +32,11 @@ #define __DEV_X86_INTDEV_HH__ #include +#include +#include "arch/x86/x86_traits.hh" +#include "mem/mem_object.hh" +#include "mem/mport.hh" #include "sim/sim_object.hh" #include "params/X86IntPin.hh" @@ -40,11 +44,73 @@ namespace X86ISA { class IntDev { + protected: + class IntPort : public MessagePort + { + IntDev * device; + Tick latency; + Addr intAddr; + public: + IntPort(const std::string &_name, MemObject * _parent, + IntDev *dev, Tick _latency) : + MessagePort(_name, _parent), device(dev), latency(_latency) + { + } + + void getDeviceAddressRanges(AddrRangeList &resp, bool &snoop) + { + snoop = false; + device->getIntAddrRange(resp); + } + + Tick recvMessage(PacketPtr pkt) + { + return device->recvMessage(pkt); + } + + void recvStatusChange(Status status) + { + if (status == RangeChange) { + sendStatusChange(Port::RangeChange); + } + } + + }; + + IntPort * intPort; + public: + IntDev(MemObject * parent, Tick latency = 0) + { + if (parent != NULL) { + intPort = new IntPort(parent->name() + ".int_port", + parent, this, latency); + } else { + intPort = NULL; + } + } + virtual ~IntDev() {} + + virtual void + signalInterrupt(int line) + { + panic("signalInterrupt not implemented.\n"); + } + + virtual Tick + recvMessage(PacketPtr pkt) + { + panic("recvMessage not implemented.\n"); + return 0; + } + virtual void - signalInterrupt(int line) = 0; + getIntAddrRange(AddrRangeList &range_list) + { + panic("intAddrRange not implemented.\n"); + } }; class IntPin : public SimObject -- cgit v1.2.3 From 3420ad7644b0f2e5dab9f99dfb4407be78e25305 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 13:29:26 -0700 Subject: X86: Make the bases for x86 fault class public. --- src/arch/x86/faults.hh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/arch/x86/faults.hh b/src/arch/x86/faults.hh index 78a55d0e1..a54bc8ee9 100644 --- a/src/arch/x86/faults.hh +++ b/src/arch/x86/faults.hh @@ -317,7 +317,7 @@ namespace X86ISA {} }; - class AlignmentCheck : X86Fault + class AlignmentCheck : public X86Fault { public: AlignmentCheck() : @@ -325,7 +325,7 @@ namespace X86ISA {} }; - class MachineCheck : X86Abort + class MachineCheck : public X86Abort { public: MachineCheck() : @@ -333,7 +333,7 @@ namespace X86ISA {} }; - class SIMDFloatingPointFault : X86Fault + class SIMDFloatingPointFault : public X86Fault { public: SIMDFloatingPointFault() : @@ -341,7 +341,7 @@ namespace X86ISA {} }; - class SecurityException : X86FaultBase + class SecurityException : public X86FaultBase { public: SecurityException() : @@ -349,7 +349,7 @@ namespace X86ISA {} }; - class ExternalInterrupt : X86Interrupt + class ExternalInterrupt : public X86Interrupt { public: ExternalInterrupt() : @@ -357,7 +357,7 @@ namespace X86ISA {} }; - class SoftwareInterrupt : X86Interrupt + class SoftwareInterrupt : public X86Interrupt { public: SoftwareInterrupt() : -- cgit v1.2.3 From 4d5c7f70389b8911e37d391b09023dbf6a6ab0d9 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 13:35:26 -0700 Subject: X86: Change the default value for the IO APIC redirection table. --- src/dev/x86/i82094aa.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/dev/x86/i82094aa.cc b/src/dev/x86/i82094aa.cc index f944e7171..1ae3b01cf 100644 --- a/src/dev/x86/i82094aa.cc +++ b/src/dev/x86/i82094aa.cc @@ -42,7 +42,11 @@ X86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), IntDev(this), assert(id <= 0xf); arbId = id; regSel = 0; - memset(redirTable, 0, sizeof(RedirTableEntry) * TableSize); + RedirTableEntry entry = 0; + entry.mask = 1; + for (int i = 0; i < TableSize; i++) { + redirTable[i] = entry; + } } Tick -- cgit v1.2.3 From 876f4845f258ed09d348135d8af8cf4a17de1b8a Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 13:44:24 -0700 Subject: X86: Make the local APIC handle interrupt messages from the IO APIC. --- src/arch/x86/faults.hh | 5 +- src/arch/x86/interrupts.cc | 67 +++++++++++++++++++++- src/arch/x86/interrupts.hh | 136 +++++++++++++++++++++++++++++++++------------ src/arch/x86/intmessage.hh | 39 +++++++++++++ src/dev/x86/i82094aa.cc | 31 ++--------- src/dev/x86/i8259.hh | 3 +- src/dev/x86/pc.cc | 3 +- 7 files changed, 217 insertions(+), 67 deletions(-) (limited to 'src') diff --git a/src/arch/x86/faults.hh b/src/arch/x86/faults.hh index a54bc8ee9..8fe90299d 100644 --- a/src/arch/x86/faults.hh +++ b/src/arch/x86/faults.hh @@ -351,9 +351,10 @@ namespace X86ISA class ExternalInterrupt : public X86Interrupt { + uint8_t vector; public: - ExternalInterrupt() : - X86Interrupt("External Interrupt", "#INTR") + ExternalInterrupt(uint8_t _vector) : + X86Interrupt("External Interrupt", "#INTR"), vector(_vector) {} }; diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc index 5614a37eb..a7c238ace 100644 --- a/src/arch/x86/interrupts.cc +++ b/src/arch/x86/interrupts.cc @@ -57,7 +57,9 @@ #include "arch/x86/apicregs.hh" #include "arch/x86/interrupts.hh" +#include "arch/x86/intmessage.hh" #include "cpu/base.hh" +#include "mem/packet_access.hh" int divideFromConf(uint32_t conf) @@ -242,12 +244,43 @@ X86ISA::Interrupts::write(PacketPtr pkt) Tick X86ISA::Interrupts::recvMessage(PacketPtr pkt) { - Addr offset = pkt->getAddr() - x86InterruptAddress(0, 0); + uint8_t id = 0; + Addr offset = pkt->getAddr() - x86InterruptAddress(id, 0); assert(pkt->cmd == MemCmd::MessageReq); switch(offset) { case 0: - DPRINTF(LocalApic, "Got Trigger Interrupt message.\n"); + { + TriggerIntMessage message = pkt->get(); + uint8_t vector = message.vector; + DPRINTF(LocalApic, + "Got Trigger Interrupt message with vector %#x.\n", + vector); + // Make sure we're really supposed to get this. + assert((message.destMode == 0 && message.destination == id) || + (bits((int)message.destination, id))); + if (DeliveryMode::isUnmaskable(message.deliveryMode)) { + DPRINTF(LocalApic, "Interrupt is an %s and unmaskable.\n", + DeliveryMode::names[message.deliveryMode]); + panic("Unmaskable interrupts aren't implemented.\n"); + } else if (DeliveryMode::isMaskable(message.deliveryMode)) { + DPRINTF(LocalApic, "Interrupt is an %s and maskable.\n", + DeliveryMode::names[message.deliveryMode]); + // Queue up the interrupt in the IRR. + if (vector > IRRV) + IRRV = vector; + if (!getRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, vector)) { + setRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, vector); + if (message.trigger) { + // Level triggered. + setRegArrayBit(APIC_TRIGGER_MODE_BASE, vector); + } else { + // Edge triggered. + clearRegArrayBit(APIC_TRIGGER_MODE_BASE, vector); + } + } + } + } break; default: panic("Local apic got unknown interrupt message at offset %#x.\n", @@ -414,6 +447,36 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val) return; } +bool +X86ISA::Interrupts::check_interrupts(ThreadContext * tc) const +{ + RFLAGS rflags = tc->readMiscRegNoEffect(MISCREG_RFLAGS); + if (IRRV > ISRV && rflags.intf && + bits(IRRV, 7, 4) > bits(regs[APIC_TASK_PRIORITY], 7, 4)) { + return true; + } + return false; +} + +Fault +X86ISA::Interrupts::getInterrupt(ThreadContext * tc) +{ + assert(check_interrupts(tc)); + return new ExternalInterrupt(IRRV); +} + +void +X86ISA::Interrupts::updateIntrInfo(ThreadContext * tc) +{ + assert(check_interrupts(tc)); + // Mark the interrupt as "in service". + ISRV = IRRV; + setRegArrayBit(APIC_IN_SERVICE_BASE, ISRV); + // Clear it out of the IRR. + clearRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, IRRV); + updateIRRV(); +} + X86ISA::Interrupts * X86LocalApicParams::create() { diff --git a/src/arch/x86/interrupts.hh b/src/arch/x86/interrupts.hh index c4760dc0f..cfc1ada9d 100644 --- a/src/arch/x86/interrupts.hh +++ b/src/arch/x86/interrupts.hh @@ -60,6 +60,7 @@ #include "arch/x86/apicregs.hh" #include "arch/x86/faults.hh" +#include "base/bitfield.hh" #include "cpu/thread_context.hh" #include "dev/io_device.hh" #include "dev/x86/intdev.hh" @@ -74,7 +75,12 @@ namespace X86ISA class Interrupts : public BasicPioDevice, IntDev { protected: + // Storage for the APIC registers uint32_t regs[NUM_APIC_REGS]; + + /* + * Timing related stuff. + */ Tick latency; Tick clock; @@ -92,7 +98,58 @@ class Interrupts : public BasicPioDevice, IntDev ApicTimerEvent apicTimerEvent; + /* + * IRR and ISR maintenance. + */ + uint8_t IRRV; + uint8_t ISRV; + + int + findRegArrayMSB(ApicRegIndex base) + { + int offset = 7; + do { + if (regs[base + offset] != 0) { + return offset * 32 + findMsbSet(regs[base + offset]); + } + } while (offset--); + return 0; + } + + void + updateIRRV() + { + IRRV = findRegArrayMSB(APIC_INTERRUPT_REQUEST_BASE); + } + + void + updateISRV() + { + ISRV = findRegArrayMSB(APIC_IN_SERVICE_BASE); + } + + void + setRegArrayBit(ApicRegIndex base, uint8_t vector) + { + regs[base + (vector % 32)] |= (1 << (vector >> 5)); + } + + void + clearRegArrayBit(ApicRegIndex base, uint8_t vector) + { + regs[base + (vector % 32)] &= ~(1 << (vector >> 5)); + } + + bool + getRegArrayBit(ApicRegIndex base, uint8_t vector) + { + return bits(regs[base + (vector % 32)], vector >> 5); + } + public: + /* + * Params stuff. + */ typedef X86LocalApicParams Params; void setClock(Tick newClock) @@ -106,6 +163,9 @@ class Interrupts : public BasicPioDevice, IntDev return dynamic_cast(_params); } + /* + * Functions to interact with the interrupt port from IntDev. + */ Tick read(PacketPtr pkt); Tick write(PacketPtr pkt); Tick recvMessage(PacketPtr pkt); @@ -124,6 +184,17 @@ class Interrupts : public BasicPioDevice, IntDev x86InterruptAddress(0, 0) + PhysAddrAPICRangeSize)); } + Port *getPort(const std::string &if_name, int idx = -1) + { + if (if_name == "int_port") + return intPort; + return BasicPioDevice::getPort(if_name, idx); + } + + /* + * Functions to access and manipulate the APIC's registers. + */ + uint32_t readReg(ApicRegIndex miscReg); void setReg(ApicRegIndex reg, uint32_t val); void setRegNoEffect(ApicRegIndex reg, uint32_t val) @@ -131,29 +202,47 @@ class Interrupts : public BasicPioDevice, IntDev regs[reg] = val; } + /* + * Constructor. + */ + Interrupts(Params * p) : BasicPioDevice(p), IntDev(this), latency(p->pio_latency), clock(0) { pioSize = PageBytes; + memset(regs, 0, sizeof(regs)); //Set the local apic DFR to the flat model. regs[APIC_DESTINATION_FORMAT] = (uint32_t)(-1); - memset(regs, 0, sizeof(regs)); - clear_all(); + ISRV = 0; + IRRV = 0; } - Port *getPort(const std::string &if_name, int idx = -1) + /* + * Functions for retrieving interrupts for the CPU to handle. + */ + + bool check_interrupts(ThreadContext * tc) const; + Fault getInterrupt(ThreadContext * tc); + void updateIntrInfo(ThreadContext * tc); + + /* + * Serialization. + */ + + void serialize(std::ostream & os) { - if (if_name == "int_port") - return intPort; - return BasicPioDevice::getPort(if_name, idx); + panic("Interrupts::serialize unimplemented!\n"); } - int InterruptLevel(uint64_t softint) + void unserialize(Checkpoint * cp, const std::string & section) { - panic("Interrupts::InterruptLevel unimplemented!\n"); - return 0; + panic("Interrupts::unserialize unimplemented!\n"); } + /* + * Old functions needed for compatability but which will be phased out + * eventually. + */ void post(int int_num, int index) { panic("Interrupts::post unimplemented!\n"); @@ -161,37 +250,12 @@ class Interrupts : public BasicPioDevice, IntDev void clear(int int_num, int index) { - warn("Interrupts::clear unimplemented!\n"); + panic("Interrupts::clear unimplemented!\n"); } void clear_all() { - warn("Interrupts::clear_all unimplemented!\n"); - } - - bool check_interrupts(ThreadContext * tc) const - { - return false; - } - - Fault getInterrupt(ThreadContext * tc) - { - return NoFault; - } - - void updateIntrInfo(ThreadContext * tc) - { - panic("Interrupts::updateIntrInfo unimplemented!\n"); - } - - void serialize(std::ostream & os) - { - panic("Interrupts::serialize unimplemented!\n"); - } - - void unserialize(Checkpoint * cp, const std::string & section) - { - panic("Interrupts::unserialize unimplemented!\n"); + panic("Interrupts::clear_all unimplemented!\n"); } }; diff --git a/src/arch/x86/intmessage.hh b/src/arch/x86/intmessage.hh index 64e821a41..a018a997b 100644 --- a/src/arch/x86/intmessage.hh +++ b/src/arch/x86/intmessage.hh @@ -44,8 +44,47 @@ namespace X86ISA Bitfield<15, 8> vector; Bitfield<18, 16> deliveryMode; Bitfield<19> destMode; + Bitfield<20> level; + Bitfield<21> trigger; EndBitUnion(TriggerIntMessage) + namespace DeliveryMode + { + enum IntDeliveryMode { + Fixed = 0, + LowestPriority = 1, + SMI = 2, + NMI = 4, + INIT = 5, + ExtInt = 7, + NumModes + }; + + static const char * const names[NumModes] = { + "Fixed", "LowestPriority", "SMI", "Reserved", + "NMI", "INIT", "Reserved", "ExtInt" + }; + + static inline bool + isUnmaskable(int mode) + { + return (mode == SMI || mode == NMI || + mode == INIT || mode == ExtInt); + } + + static inline bool + isMaskable(int mode) + { + return (mode == Fixed || mode == LowestPriority); + } + + static inline bool + isReserved(int mode) + { + return !(isMaskable(mode) || isUnmaskable(mode)); + } + } + static const Addr TriggerIntOffset = 0; static inline PacketPtr diff --git a/src/dev/x86/i82094aa.cc b/src/dev/x86/i82094aa.cc index 1ae3b01cf..d7f479106 100644 --- a/src/dev/x86/i82094aa.cc +++ b/src/dev/x86/i82094aa.cc @@ -146,33 +146,12 @@ X86ISA::I82094AA::signalInterrupt(int line) return; } else { if (DTRACE(I82094AA)) { - switch(entry.deliveryMode) { - case 0: - DPRINTF(I82094AA, "Delivery mode is: Fixed.\n"); - break; - case 1: - DPRINTF(I82094AA, "Delivery mode is: Lowest Priority.\n"); - break; - case 2: - DPRINTF(I82094AA, "Delivery mode is: SMI.\n"); - break; - case 3: + if (DeliveryMode::isReserved(entry.deliveryMode)) { fatal("Tried to use reserved delivery mode " "for IO APIC entry %d.\n", line); - break; - case 4: - DPRINTF(I82094AA, "Delivery mode is: NMI.\n"); - break; - case 5: - DPRINTF(I82094AA, "Delivery mode is: INIT.\n"); - break; - case 6: - fatal("Tried to use reserved delivery mode " - "for IO APIC entry %d.\n", line); - break; - case 7: - DPRINTF(I82094AA, "Delivery mode is: ExtINT.\n"); - break; + } else { + DPRINTF(I82094AA, "Delivery mode is: %s.\n", + DeliveryMode::names[entry.deliveryMode]); } DPRINTF(I82094AA, "Vector is %#x.\n", entry.vector); } @@ -182,6 +161,8 @@ X86ISA::I82094AA::signalInterrupt(int line) message.vector = entry.vector; message.deliveryMode = entry.deliveryMode; message.destMode = entry.destMode; + message.level = entry.polarity; + message.trigger = entry.trigger; if (entry.destMode == 0) { DPRINTF(I82094AA, diff --git a/src/dev/x86/i8259.hh b/src/dev/x86/i8259.hh index 1c14e5397..7804fe3b7 100644 --- a/src/dev/x86/i8259.hh +++ b/src/dev/x86/i8259.hh @@ -76,7 +76,8 @@ class I8259 : public BasicPioDevice, public IntDev I8259(Params * p) : BasicPioDevice(p), IntDev(this), latency(p->pio_latency), output(p->output), - mode(p->mode), readIRR(true), initControlWord(0) + mode(p->mode), IRR(0), ISR(0), IMR(0), + readIRR(true), initControlWord(0) { pioSize = 2; } diff --git a/src/dev/x86/pc.cc b/src/dev/x86/pc.cc index 4cd81dd50..94fb23e21 100644 --- a/src/dev/x86/pc.cc +++ b/src/dev/x86/pc.cc @@ -36,6 +36,7 @@ #include #include +#include "arch/x86/intmessage.hh" #include "arch/x86/x86_traits.hh" #include "cpu/intr_control.hh" #include "dev/terminal.hh" @@ -78,7 +79,7 @@ Pc::init() */ I82094AA & ioApic = *southBridge->ioApic; I82094AA::RedirTableEntry entry = 0; - entry.deliveryMode = 0x7; + entry.deliveryMode = DeliveryMode::ExtInt; entry.vector = 0x20; ioApic.writeReg(0x10, entry.bottomDW); ioApic.writeReg(0x11, entry.topDW); -- cgit v1.2.3 From ec9d3aad71ec75b3f7b5ea96dd41f067a9261392 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 13:45:21 -0700 Subject: X86: Make the local APIC process interrupts and send them to the CPU. --- src/arch/x86/faults.hh | 22 ++++++++++- src/arch/x86/interrupts.cc | 93 ++++++++++++++++++++++++++++++++++++++-------- src/arch/x86/interrupts.hh | 24 +++++++++++- src/arch/x86/intmessage.hh | 15 +------- 4 files changed, 121 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/arch/x86/faults.hh b/src/arch/x86/faults.hh index 8fe90299d..b15ad15d1 100644 --- a/src/arch/x86/faults.hh +++ b/src/arch/x86/faults.hh @@ -215,9 +215,10 @@ namespace X86ISA class NonMaskableInterrupt : public X86Interrupt { + uint8_t vector; public: - NonMaskableInterrupt() : - X86Interrupt("Non-Maskable-Interrupt", "#NMI") + NonMaskableInterrupt(uint8_t _vector) : + X86Interrupt("Non Maskable Interrupt", "#NMI"), vector(_vector) {} }; @@ -358,6 +359,23 @@ namespace X86ISA {} }; + class SystemManagementInterrupt : public X86Interrupt + { + public: + SystemManagementInterrupt() : + X86Interrupt("System Management Interrupt", "#SMI") + {} + }; + + class InitInterrupt : public X86Interrupt + { + uint8_t vector; + public: + InitInterrupt(uint8_t _vector) : + X86Interrupt("INIT Interrupt", "#INIT"), vector(_vector) + {} + }; + class SoftwareInterrupt : public X86Interrupt { public: diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc index a7c238ace..280fa5dd1 100644 --- a/src/arch/x86/interrupts.cc +++ b/src/arch/x86/interrupts.cc @@ -259,12 +259,15 @@ X86ISA::Interrupts::recvMessage(PacketPtr pkt) // Make sure we're really supposed to get this. assert((message.destMode == 0 && message.destination == id) || (bits((int)message.destination, id))); - if (DeliveryMode::isUnmaskable(message.deliveryMode)) { - DPRINTF(LocalApic, "Interrupt is an %s and unmaskable.\n", - DeliveryMode::names[message.deliveryMode]); - panic("Unmaskable interrupts aren't implemented.\n"); - } else if (DeliveryMode::isMaskable(message.deliveryMode)) { - DPRINTF(LocalApic, "Interrupt is an %s and maskable.\n", + + /* + * Fixed and lowest-priority delivery mode interrupts are handled + * using the IRR/ISR registers, checking against the TPR, etc. + * The SMI, NMI, ExtInt, INIT, etc interrupts go straight through. + */ + if (message.deliveryMode == DeliveryMode::Fixed || + message.deliveryMode == DeliveryMode::LowestPriority) { + DPRINTF(LocalApic, "Interrupt is an %s.\n", DeliveryMode::names[message.deliveryMode]); // Queue up the interrupt in the IRR. if (vector > IRRV) @@ -279,7 +282,27 @@ X86ISA::Interrupts::recvMessage(PacketPtr pkt) clearRegArrayBit(APIC_TRIGGER_MODE_BASE, vector); } } - } + } else if (!DeliveryMode::isReserved(message.deliveryMode)) { + DPRINTF(LocalApic, "Interrupt is an %s.\n", + DeliveryMode::names[message.deliveryMode]); + if (message.deliveryMode == DeliveryMode::SMI && + !pendingSmi) { + pendingUnmaskableInt = pendingSmi = true; + smiMessage = message; + } else if (message.deliveryMode == DeliveryMode::NMI && + !pendingNmi) { + pendingUnmaskableInt = pendingNmi = true; + nmiMessage = message; + } else if (message.deliveryMode == DeliveryMode::ExtInt && + !pendingExtInt) { + pendingExtInt = true; + extIntMessage = message; + } else if (message.deliveryMode == DeliveryMode::INIT && + !pendingInit) { + pendingUnmaskableInt = pendingInit = true; + initMessage = message; + } + } } break; default: @@ -451,9 +474,14 @@ bool X86ISA::Interrupts::check_interrupts(ThreadContext * tc) const { RFLAGS rflags = tc->readMiscRegNoEffect(MISCREG_RFLAGS); - if (IRRV > ISRV && rflags.intf && - bits(IRRV, 7, 4) > bits(regs[APIC_TASK_PRIORITY], 7, 4)) { + if (pendingUnmaskableInt) return true; + if (rflags.intf) { + if (pendingExtInt) + return true; + if (IRRV > ISRV && bits(IRRV, 7, 4) > + bits(regs[APIC_TASK_PRIORITY], 7, 4)) + return true; } return false; } @@ -462,19 +490,52 @@ Fault X86ISA::Interrupts::getInterrupt(ThreadContext * tc) { assert(check_interrupts(tc)); - return new ExternalInterrupt(IRRV); + // These are all probably fairly uncommon, so we'll make them easier to + // check for. + if (pendingUnmaskableInt) { + if (pendingSmi) { + return new SystemManagementInterrupt(); + } else if (pendingNmi) { + return new NonMaskableInterrupt(nmiMessage.vector); + } else if (pendingInit) { + return new InitInterrupt(initMessage.vector); + } else { + panic("pendingUnmaskableInt set, but no unmaskable " + "ints were pending.\n"); + return NoFault; + } + } else if (pendingExtInt) { + return new ExternalInterrupt(extIntMessage.vector); + } else { + // The only thing left are fixed and lowest priority interrupts. + return new ExternalInterrupt(IRRV); + } } void X86ISA::Interrupts::updateIntrInfo(ThreadContext * tc) { assert(check_interrupts(tc)); - // Mark the interrupt as "in service". - ISRV = IRRV; - setRegArrayBit(APIC_IN_SERVICE_BASE, ISRV); - // Clear it out of the IRR. - clearRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, IRRV); - updateIRRV(); + if (pendingUnmaskableInt) { + if (pendingSmi) { + pendingSmi = false; + } else if (pendingNmi) { + pendingNmi = false; + } else if (pendingInit) { + pendingInit = false; + } + if (!(pendingSmi || pendingNmi || pendingInit)) + pendingUnmaskableInt = false; + } else if (pendingExtInt) { + pendingExtInt = false; + } else { + // Mark the interrupt as "in service". + ISRV = IRRV; + setRegArrayBit(APIC_IN_SERVICE_BASE, ISRV); + // Clear it out of the IRR. + clearRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, IRRV); + updateIRRV(); + } } X86ISA::Interrupts * diff --git a/src/arch/x86/interrupts.hh b/src/arch/x86/interrupts.hh index cfc1ada9d..85a0f6478 100644 --- a/src/arch/x86/interrupts.hh +++ b/src/arch/x86/interrupts.hh @@ -60,6 +60,7 @@ #include "arch/x86/apicregs.hh" #include "arch/x86/faults.hh" +#include "arch/x86/intmessage.hh" #include "base/bitfield.hh" #include "cpu/thread_context.hh" #include "dev/io_device.hh" @@ -98,6 +99,22 @@ class Interrupts : public BasicPioDevice, IntDev ApicTimerEvent apicTimerEvent; + /* + * A set of variables to keep track of interrupts that don't go through + * the IRR. + */ + bool pendingSmi; + TriggerIntMessage smiMessage; + bool pendingNmi; + TriggerIntMessage nmiMessage; + bool pendingExtInt; + TriggerIntMessage extIntMessage; + bool pendingInit; + TriggerIntMessage initMessage; + + // This is a quick check whether any of the above (except ExtInt) are set. + bool pendingUnmaskableInt; + /* * IRR and ISR maintenance. */ @@ -207,7 +224,12 @@ class Interrupts : public BasicPioDevice, IntDev */ Interrupts(Params * p) : BasicPioDevice(p), IntDev(this), - latency(p->pio_latency), clock(0) + latency(p->pio_latency), clock(0), + pendingSmi(false), smiMessage(0), + pendingNmi(false), nmiMessage(0), + pendingExtInt(false), extIntMessage(0), + pendingInit(false), initMessage(0), + pendingUnmaskableInt(false) { pioSize = PageBytes; memset(regs, 0, sizeof(regs)); diff --git a/src/arch/x86/intmessage.hh b/src/arch/x86/intmessage.hh index a018a997b..6a5b3aa30 100644 --- a/src/arch/x86/intmessage.hh +++ b/src/arch/x86/intmessage.hh @@ -65,23 +65,10 @@ namespace X86ISA "NMI", "INIT", "Reserved", "ExtInt" }; - static inline bool - isUnmaskable(int mode) - { - return (mode == SMI || mode == NMI || - mode == INIT || mode == ExtInt); - } - - static inline bool - isMaskable(int mode) - { - return (mode == Fixed || mode == LowestPriority); - } - static inline bool isReserved(int mode) { - return !(isMaskable(mode) || isUnmaskable(mode)); + return mode == 3 || mode == 6; } } -- cgit v1.2.3 From c35da8e495e9f2697a252e8e828e6d7760a8a2db Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 13:51:48 -0700 Subject: X86: Actually use the extra vector bits we get from ICW2. --- src/dev/x86/i8259.cc | 3 ++- src/dev/x86/i8259.hh | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/dev/x86/i8259.cc b/src/dev/x86/i8259.cc index dbc8ab768..a67baa8e2 100644 --- a/src/dev/x86/i8259.cc +++ b/src/dev/x86/i8259.cc @@ -128,8 +128,9 @@ X86ISA::I8259::write(PacketPtr pkt) break; case 0x1: DPRINTF(I8259, "Received initialization command word 2.\n"); + vectorOffset = val & ~mask(3); DPRINTF(I8259, "Responsible for vectors %#x-%#x.\n", - val & ~mask(3), val | mask(3)); + vectorOffset, vectorOffset | mask(3)); if (cascadeMode) { initControlWord++; } else { diff --git a/src/dev/x86/i8259.hh b/src/dev/x86/i8259.hh index 7804fe3b7..107cd015c 100644 --- a/src/dev/x86/i8259.hh +++ b/src/dev/x86/i8259.hh @@ -53,6 +53,9 @@ class I8259 : public BasicPioDevice, public IntDev // Interrupt Mask Register uint8_t IMR; + // The higher order bits of the vector to return + uint8_t vectorOffset; + bool cascadeMode; // A bit vector of lines with slaves attached, or the slave id, depending // on if this is a master or slave PIC. @@ -77,7 +80,7 @@ class I8259 : public BasicPioDevice, public IntDev I8259(Params * p) : BasicPioDevice(p), IntDev(this), latency(p->pio_latency), output(p->output), mode(p->mode), IRR(0), ISR(0), IMR(0), - readIRR(true), initControlWord(0) + vectorOffset(0), readIRR(true), initControlWord(0) { pioSize = 2; } -- cgit v1.2.3 From 3a1905157eec2ed80eaf2ddb8be69cb2f509dfee Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 13:54:57 -0700 Subject: X86: Create a mechanism for the IO APIC to access I8259 vectors. --- src/dev/x86/i82094aa.cc | 30 +++++++++++++----------- src/dev/x86/i82094aa.hh | 11 ++++++++- src/dev/x86/i8259.cc | 61 ++++++++++++++++++++++++++++++++++++++++++------- src/dev/x86/i8259.hh | 17 +++++++++----- src/dev/x86/intdev.hh | 6 +++++ 5 files changed, 97 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/dev/x86/i82094aa.cc b/src/dev/x86/i82094aa.cc index d7f479106..0ae7c56f3 100644 --- a/src/dev/x86/i82094aa.cc +++ b/src/dev/x86/i82094aa.cc @@ -30,12 +30,13 @@ #include "arch/x86/intmessage.hh" #include "dev/x86/i82094aa.hh" +#include "dev/x86/i8259.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" #include "sim/system.hh" X86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), IntDev(this), - latency(p->pio_latency), pioAddr(p->pio_addr) + latency(p->pio_latency), pioAddr(p->pio_addr), extIntPic(NULL) { // This assumes there's only one I/O APIC in the system id = sys->getNumCPUs(); @@ -145,25 +146,28 @@ X86ISA::I82094AA::signalInterrupt(int line) DPRINTF(I82094AA, "Entry was masked.\n"); return; } else { - if (DTRACE(I82094AA)) { - if (DeliveryMode::isReserved(entry.deliveryMode)) { - fatal("Tried to use reserved delivery mode " - "for IO APIC entry %d.\n", line); - } else { - DPRINTF(I82094AA, "Delivery mode is: %s.\n", - DeliveryMode::names[entry.deliveryMode]); - } - DPRINTF(I82094AA, "Vector is %#x.\n", entry.vector); - } - TriggerIntMessage message; message.destination = entry.dest; - message.vector = entry.vector; + if (entry.deliveryMode == DeliveryMode::ExtInt) { + assert(extIntPic); + message.vector = extIntPic->getVector(); + } else { + message.vector = entry.vector; + } message.deliveryMode = entry.deliveryMode; message.destMode = entry.destMode; message.level = entry.polarity; message.trigger = entry.trigger; + if (DeliveryMode::isReserved(entry.deliveryMode)) { + fatal("Tried to use reserved delivery mode " + "for IO APIC entry %d.\n", line); + } else if (DTRACE(I82094AA)) { + DPRINTF(I82094AA, "Delivery mode is: %s.\n", + DeliveryMode::names[entry.deliveryMode]); + DPRINTF(I82094AA, "Vector is %#x.\n", message.vector); + } + if (entry.destMode == 0) { DPRINTF(I82094AA, "Sending interrupt to APIC ID %d.\n", entry.dest); diff --git a/src/dev/x86/i82094aa.hh b/src/dev/x86/i82094aa.hh index 6c874a5f9..6a8873d45 100644 --- a/src/dev/x86/i82094aa.hh +++ b/src/dev/x86/i82094aa.hh @@ -40,6 +40,8 @@ namespace X86ISA { +class I8259; + class I82094AA : public PioDevice, public IntDev { public: @@ -60,10 +62,11 @@ class I82094AA : public PioDevice, public IntDev EndBitUnion(RedirTableEntry) protected: - System * system; Tick latency; Addr pioAddr; + I8259 * extIntPic; + uint8_t regSel; uint8_t id; uint8_t arbId; @@ -86,6 +89,12 @@ class I82094AA : public PioDevice, public IntDev I82094AA(Params *p); + void + setExtIntPic(I8259 * pic) + { + extIntPic = pic; + } + Tick read(PacketPtr pkt); Tick write(PacketPtr pkt); diff --git a/src/dev/x86/i8259.cc b/src/dev/x86/i8259.cc index a67baa8e2..be0bfbe4d 100644 --- a/src/dev/x86/i8259.cc +++ b/src/dev/x86/i8259.cc @@ -29,8 +29,28 @@ */ #include "base/bitfield.hh" +#include "dev/x86/i82094aa.hh" #include "dev/x86/i8259.hh" +X86ISA::I8259::I8259(Params * p) : BasicPioDevice(p), IntDev(this), + latency(p->pio_latency), output(p->output), + mode(p->mode), slave(NULL), + IRR(0), ISR(0), IMR(0), + readIRR(true), initControlWord(0) +{ + if (output) { + I8259 * master; + master = dynamic_cast(output->getDevice()); + if (master) + master->setSlave(this); + I82094AA * ioApic; + ioApic = dynamic_cast(output->getDevice()); + if (ioApic) + ioApic->setExtIntPic(this); + } + pioSize = 2; +} + Tick X86ISA::I8259::read(PacketPtr pkt) { @@ -189,21 +209,46 @@ void X86ISA::I8259::signalInterrupt(int line) { DPRINTF(I8259, "Interrupt raised on line %d.\n", line); - if (line > 7) - fatal("Line number %d doesn't exist. The max is 7.\n"); + if (line >= NumLines) + fatal("Line number %d doesn't exist. The max is %d.\n", + line, NumLines - 1); if (bits(IMR, line)) { DPRINTF(I8259, "Interrupt %d was masked.\n", line); } else { - if (output) { - DPRINTF(I8259, "Propogating interrupt.\n"); - output->signalInterrupt(); - } else { - warn("Received interrupt but didn't have " - "anyone to tell about it.\n"); + IRR |= 1 << line; + if (bits(ISR, 7, line) == 0) { + if (output) { + DPRINTF(I8259, "Propogating interrupt.\n"); + output->signalInterrupt(); + } else { + warn("Received interrupt but didn't have " + "anyone to tell about it.\n"); + } } } } +int +X86ISA::I8259::getVector() +{ + /* + * This code only handles one slave. Since that's how the PC platform + * always uses the 8259 PIC, there shouldn't be any need for more. If + * there -is- a need for more for some reason, "slave" can become a + * vector of slaves. + */ + int line = findMsbSet(IRR); + IRR &= ~(1 << line); + DPRINTF(I8259, "Interrupt %d was accepted.\n", line); + ISR |= 1 << line; + if (slave && bits(cascadeBits, line)) { + DPRINTF(I8259, "Interrupt was from slave who will " + "provide the vector.\n"); + return slave->getVector(); + } + return line | vectorOffset; +} + X86ISA::I8259 * I8259Params::create() { diff --git a/src/dev/x86/i8259.hh b/src/dev/x86/i8259.hh index 107cd015c..371a27874 100644 --- a/src/dev/x86/i8259.hh +++ b/src/dev/x86/i8259.hh @@ -39,12 +39,17 @@ namespace X86ISA { +class I82094AA; + class I8259 : public BasicPioDevice, public IntDev { protected: + static const int NumLines = 8; + Tick latency; IntPin *output; Enums::X86I8259CascadeMode mode; + I8259 * slave; // Interrupt Request Register uint8_t IRR; @@ -77,19 +82,19 @@ class I8259 : public BasicPioDevice, public IntDev return dynamic_cast(_params); } - I8259(Params * p) : BasicPioDevice(p), IntDev(this), - latency(p->pio_latency), output(p->output), - mode(p->mode), IRR(0), ISR(0), IMR(0), - vectorOffset(0), readIRR(true), initControlWord(0) + I8259(Params * p); + + void + setSlave(I8259 * _slave) { - pioSize = 2; + slave = _slave; } Tick read(PacketPtr pkt); - Tick write(PacketPtr pkt); void signalInterrupt(int line); + int getVector(); }; }; // namespace X86ISA diff --git a/src/dev/x86/intdev.hh b/src/dev/x86/intdev.hh index d36ed462a..ba9a073a4 100644 --- a/src/dev/x86/intdev.hh +++ b/src/dev/x86/intdev.hh @@ -122,6 +122,12 @@ class IntPin : public SimObject public: typedef X86IntPinParams Params; + IntDev * + getDevice() const + { + return device; + } + const Params * params() const { -- cgit v1.2.3 From d0a43ce2b29da1640248a756dcd07f0f28561df0 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 14:01:06 -0700 Subject: X86: Fix the ordering of special physical address ranges. --- src/arch/x86/x86_traits.hh | 4 ++-- src/cpu/BaseCPU.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/arch/x86/x86_traits.hh b/src/arch/x86/x86_traits.hh index be7572517..0347a7099 100644 --- a/src/arch/x86/x86_traits.hh +++ b/src/arch/x86/x86_traits.hh @@ -92,8 +92,8 @@ namespace X86ISA const Addr PhysAddrPrefixIO = ULL(0x8000000000000000); const Addr PhysAddrPrefixPciConfig = ULL(0xC000000000000000); - const Addr PhysAddrPrefixLocalAPIC = ULL(0xA000000000000000); - const Addr PhysAddrPrefixInterrupts = ULL(0x2000000000000000); + const Addr PhysAddrPrefixLocalAPIC = ULL(0x2000000000000000); + const Addr PhysAddrPrefixInterrupts = ULL(0xA000000000000000); // Each APIC gets two pages. One page is used for local apics to field // accesses from the CPU, and the other is for all APICs to communicate. const Addr PhysAddrAPICRangeSize = 1 << 12; diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py index 51d447f0b..ef9b54f3f 100644 --- a/src/cpu/BaseCPU.py +++ b/src/cpu/BaseCPU.py @@ -97,7 +97,7 @@ class BaseCPU(MemObject): dtb = Param.X86DTB(X86DTB(), "Data TLB") itb = Param.X86ITB(X86ITB(), "Instruction TLB") if build_env['FULL_SYSTEM']: - _localApic = X86LocalApic(pio_addr=0xa000000000000000) + _localApic = X86LocalApic(pio_addr=0x2000000000000000) interrupts = \ Param.X86LocalApic(_localApic, "Interrupt Controller") elif build_env['TARGET_ISA'] == 'mips': -- cgit v1.2.3 From a76c4b8ca101c0c89659a536da6271d4116850de Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 15:31:28 -0700 Subject: X86: Implement CPUID with a magical function instead of microcode. --- src/arch/x86/SConscript | 2 +- src/arch/x86/cpuid.cc | 160 ++++++++ src/arch/x86/cpuid.hh | 61 ++++ src/arch/x86/isa/decoder/two_byte_opcodes.isa | 11 +- src/arch/x86/isa/formats/cpuid.isa | 110 ++++++ src/arch/x86/isa/formats/formats.isa | 3 + src/arch/x86/isa/includes.isa | 1 + src/arch/x86/isa/insts/general_purpose/__init__.py | 1 - .../insts/general_purpose/processor_information.py | 402 --------------------- src/arch/x86/isa/operands.isa | 5 +- 10 files changed, 349 insertions(+), 407 deletions(-) create mode 100644 src/arch/x86/cpuid.cc create mode 100644 src/arch/x86/cpuid.hh create mode 100644 src/arch/x86/isa/formats/cpuid.isa delete mode 100644 src/arch/x86/isa/insts/general_purpose/processor_information.py (limited to 'src') diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript index c1a1b9ba3..cd2445c7e 100644 --- a/src/arch/x86/SConscript +++ b/src/arch/x86/SConscript @@ -86,6 +86,7 @@ Import('*') if env['TARGET_ISA'] == 'x86': + Source('cpuid.cc') Source('emulenv.cc') Source('floatregfile.cc') Source('faults.cc') @@ -173,7 +174,6 @@ if env['TARGET_ISA'] == 'x86': 'general_purpose/load_segment_registers.py', 'general_purpose/logical.py', 'general_purpose/no_operation.py', - 'general_purpose/processor_information.py', 'general_purpose/rotate_and_shift/__init__.py', 'general_purpose/rotate_and_shift/rotate.py', 'general_purpose/rotate_and_shift/shift.py', diff --git a/src/arch/x86/cpuid.cc b/src/arch/x86/cpuid.cc new file mode 100644 index 000000000..247965df4 --- /dev/null +++ b/src/arch/x86/cpuid.cc @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/x86/cpuid.hh" +#include "base/bitfield.hh" +#include "cpu/thread_context.hh" + +namespace X86ISA { + enum StandardCpuidFunction { + VendorAndLargestStdFunc, + FamilyModelStepping, + NumStandardCpuidFuncs + }; + + enum ExtendedCpuidFunctions { + VendorAndLargestExtFunc, + FamilyModelSteppingBrandFeatures, + NameString1, + NameString2, + NameString3, + L1CacheAndTLB, + L2L3CacheAndL2TLB, + APMInfo, + + /* + * The following are defined by the spec but not yet implemented + */ +/* LongModeAddressSize, + // Function 9 is reserved + SVMInfo = 10, + // Functions 11-24 are reserved + TLB1GBPageInfo = 25, + PerformanceInfo,*/ + + NumExtendedCpuidFuncs + }; + + static const int vendorStringSize = 13; + static const char vendorString[vendorStringSize] = "AuthenticAMD"; + static const int nameStringSize = 48; + static const char nameString[nameStringSize] = "Fake M5 x86_64 CPU"; + + uint64_t + stringToRegister(const char *str) + { + uint64_t reg = 0; + for (int pos = 3; pos >=0; pos--) { + reg <<= 8; + reg |= str[pos]; + } + return reg; + } + + bool + doCpuid(ThreadContext * tc, uint32_t function, CpuidResult &result) + { + uint16_t family = bits(function, 31, 16); + uint16_t funcNum = bits(function, 15, 0); + if (family == 0x8000) { + // The extended functions + switch (funcNum) { + case VendorAndLargestExtFunc: + assert(vendorStringSize >= 12); + result = CpuidResult( + NumExtendedCpuidFuncs - 1, + stringToRegister(vendorString), + stringToRegister(vendorString + 4), + stringToRegister(vendorString + 8)); + break; + case FamilyModelSteppingBrandFeatures: + result = CpuidResult(0x00020f51, 0x00000405, + 0xe3d3fbff, 0x00000001); + break; + case NameString1: + case NameString2: + case NameString3: + { + // Zero fill anything beyond the end of the string. This + // should go away once the string is a vetted parameter. + char cleanName[nameStringSize]; + memset(cleanName, '\0', nameStringSize); + strncpy(cleanName, nameString, nameStringSize); + + int offset = (funcNum - NameString1) * 16; + assert(nameStringSize >= offset + 16); + result = CpuidResult( + stringToRegister(cleanName + offset + 0), + stringToRegister(cleanName + offset + 4), + stringToRegister(cleanName + offset + 8), + stringToRegister(cleanName + offset + 12)); + } + break; + case L1CacheAndTLB: + result = CpuidResult(0xff08ff08, 0xff20ff20, + 0x40020140, 0x40020140); + break; + case L2L3CacheAndL2TLB: + result = CpuidResult(0x00000000, 0x42004200, + 0x00000000, 0x04008140); + break; + case APMInfo: + result = CpuidResult(0x80000018, 0x68747541, + 0x69746e65, 0x444d4163); + break; +/* case LongModeAddressSize: + case SVMInfo: + case TLB1GBPageInfo: + case PerformanceInfo:*/ + default: + return false; + } + } else if(family == 0x0000) { + // The standard functions + switch (funcNum) { + case VendorAndLargestStdFunc: + assert(vendorStringSize >= 12); + result = CpuidResult( + NumStandardCpuidFuncs - 1, + stringToRegister(vendorString), + stringToRegister(vendorString + 4), + stringToRegister(vendorString + 8)); + break; + case FamilyModelStepping: + result = CpuidResult(0x00020f51, 0000000405, + 0xe3d3fbff, 0x00000001); + break; + default: + return false; + } + } + return true; + } +} //namespace X86ISA diff --git a/src/arch/x86/cpuid.hh b/src/arch/x86/cpuid.hh new file mode 100644 index 000000000..5cb4c7972 --- /dev/null +++ b/src/arch/x86/cpuid.hh @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_CPUID_HH__ +#define __ARCH_X86_CPUID_HH__ + +#include + +class ThreadContext; + +namespace X86ISA +{ + struct CpuidResult + { + uint64_t rax; + uint64_t rbx; + uint64_t rcx; + uint64_t rdx; + + // These are not in alphebetical order on purpose. The order reflects + // how the CPUID orders the registers when it returns results. + CpuidResult(uint64_t _rax, uint64_t _rbx, + uint64_t _rdx, uint64_t _rcx) : + rax(_rax), rbx(_rbx), rcx(_rcx), rdx(_rdx) + {} + + CpuidResult() + {} + }; + + bool doCpuid(ThreadContext * tc, uint32_t function, CpuidResult &result); +} // namespace X86ISA + +#endif diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index 5ada6fd4f..bceb0595e 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -168,7 +168,7 @@ #if FULL_SYSTEM 0x05: syscall(); #else - 0x05: SyscallInst::syscall('xc->syscall(rax)', IsSyscall); + 0x05: SyscallInst::syscall('xc->syscall(Rax)', IsSyscall); #endif 0x06: clts(); //sandpile.org says (AMD) after sysret, so I might want to check @@ -707,7 +707,14 @@ 0x14: decode OPCODE_OP_BOTTOM3 { 0x0: push_fs(); 0x1: pop_fs(); - 0x2: Inst::CPUID(rAd); + 0x2: CPUIDInst::CPUID({{ + CpuidResult result; + success = doCpuid(xc->tcBase(), Rax, result); + Rax = result.rax; + Rbx = result.rbx; + Rcx = result.rcx; + Rdx = result.rdx; + }}); 0x3: Inst::BT(Ev,Gv); 0x4: shld_Ev_Gv_Ib(); 0x5: shld_Ev_Gv_rCl(); diff --git a/src/arch/x86/isa/formats/cpuid.isa b/src/arch/x86/isa/formats/cpuid.isa new file mode 100644 index 000000000..204270556 --- /dev/null +++ b/src/arch/x86/isa/formats/cpuid.isa @@ -0,0 +1,110 @@ +// Copyright (c) 2008 The Hewlett-Packard Development Company +// All rights reserved. +// +// Redistribution and use of this software in source and binary forms, +// with or without modification, are permitted provided that the +// following conditions are met: +// +// The software must be used only for Non-Commercial Use which means any +// use which is NOT directed to receiving any direct monetary +// compensation for, or commercial advantage from such use. Illustrative +// examples of non-commercial use are academic research, personal study, +// teaching, education and corporate research & development. +// Illustrative examples of commercial use are distributing products for +// commercial advantage and providing services using the software for +// commercial advantage. +// +// If you wish to use this software or functionality therein that may be +// covered by patents for commercial use, please contact: +// Director of Intellectual Property Licensing +// Office of Strategy and Technology +// Hewlett-Packard Company +// 1501 Page Mill Road +// Palo Alto, California 94304 +// +// 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. No right of +// sublicense is granted herewith. Derivatives of the software and +// output created using the software may be prepared, but only for +// Non-Commercial Uses. Derivatives of the software may be shared with +// others provided: (i) the others agree to abide by the list of +// conditions herein which includes the Non-Commercial Use restrictions; +// and (ii) such Derivatives of the software include the above copyright +// notice to acknowledge the contribution from this software where +// applicable, this list of conditions and the disclaimer below. +// +// 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: Gabe Black + +output header {{ + class CPUIDInst : public X86ISA::X86StaticInst + { + public: + static const RegIndex foldOBit = 0; + /// Constructor + CPUIDInst(const char *_mnemonic, ExtMachInst _machInst, + OpClass __opClass) : + X86ISA::X86StaticInst(_mnemonic, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string CPUIDInst::generateDisassembly(Addr PC, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, mnemonic); + ccprintf(response, " "); + printReg(response, _srcRegIdx[0], machInst.opSize); + return response.str(); + } +}}; + +def template CPUIDExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + // If the CPUID instruction used a valid function number, this will + // be set to true. Otherwise, the instruction does nothing. + bool success; + %(op_decl)s; + %(op_rd)s; + %(code)s; + if (success) { + %(op_wb)s; + } + return NoFault; + } +}}; + +def format CPUIDInst(code, *opt_flags) {{ + iop = InstObjParams(name, Name, 'CPUIDInst', code, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = CPUIDExecute.subst(iop) +}}; + diff --git a/src/arch/x86/isa/formats/formats.isa b/src/arch/x86/isa/formats/formats.isa index 6906413c0..81179ab45 100644 --- a/src/arch/x86/isa/formats/formats.isa +++ b/src/arch/x86/isa/formats/formats.isa @@ -85,6 +85,9 @@ //Templates from this format are used later ##include "basic.isa" +//Include a format to generate a CPUID instruction. +##include "cpuid.isa" + //Include the "unknown" format ##include "unknown.isa" diff --git a/src/arch/x86/isa/includes.isa b/src/arch/x86/isa/includes.isa index 6d0fe6d86..926e9185a 100644 --- a/src/arch/x86/isa/includes.isa +++ b/src/arch/x86/isa/includes.isa @@ -145,6 +145,7 @@ output exec {{ #include #include +#include "arch/x86/cpuid.hh" #include "arch/x86/miscregs.hh" #include "arch/x86/tlb.hh" #include "base/bigint.hh" diff --git a/src/arch/x86/isa/insts/general_purpose/__init__.py b/src/arch/x86/isa/insts/general_purpose/__init__.py index 4f77cb233..23f955f08 100644 --- a/src/arch/x86/isa/insts/general_purpose/__init__.py +++ b/src/arch/x86/isa/insts/general_purpose/__init__.py @@ -65,7 +65,6 @@ categories = ["arithmetic", "load_segment_registers", "logical", "no_operation", - "processor_information", "rotate_and_shift", "semaphores", "string", diff --git a/src/arch/x86/isa/insts/general_purpose/processor_information.py b/src/arch/x86/isa/insts/general_purpose/processor_information.py deleted file mode 100644 index 4b73789af..000000000 --- a/src/arch/x86/isa/insts/general_purpose/processor_information.py +++ /dev/null @@ -1,402 +0,0 @@ -# Copyright (c) 2007-2008 The Hewlett-Packard Development Company -# All rights reserved. -# -# Redistribution and use of this software in source and binary forms, -# with or without modification, are permitted provided that the -# following conditions are met: -# -# The software must be used only for Non-Commercial Use which means any -# use which is NOT directed to receiving any direct monetary -# compensation for, or commercial advantage from such use. Illustrative -# examples of non-commercial use are academic research, personal study, -# teaching, education and corporate research & development. -# Illustrative examples of commercial use are distributing products for -# commercial advantage and providing services using the software for -# commercial advantage. -# -# If you wish to use this software or functionality therein that may be -# covered by patents for commercial use, please contact: -# Director of Intellectual Property Licensing -# Office of Strategy and Technology -# Hewlett-Packard Company -# 1501 Page Mill Road -# Palo Alto, California 94304 -# -# 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. No right of -# sublicense is granted herewith. Derivatives of the software and -# output created using the software may be prepared, but only for -# Non-Commercial Uses. Derivatives of the software may be shared with -# others provided: (i) the others agree to abide by the list of -# conditions herein which includes the Non-Commercial Use restrictions; -# and (ii) such Derivatives of the software include the above copyright -# notice to acknowledge the contribution from this software where -# applicable, this list of conditions and the disclaimer below. -# -# 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: Gabe Black - -microcode = ''' -def macroop CPUID_R { - -# -# Find which type of cpuid function it is by checking bit 31. Also clear that -# bit to form an offset into the functions of that type. -# - limm t1, 0x80000000, dataSize=4 - and t2, t1, rax, flags=(EZF,) - # clear the bit - xor t1, t2, rax - -# -# Do range checking on the offset -# - # If EZF is set, the function is standard and the max is 0x1. - movi t2, t2, 0x1, flags=(CEZF,) - # If EZF is cleared, the function is extended and the max is 0x18. - movi t2, t2, 0x18, flags=(nCEZF,) - subi t0, t1, t2, flags=(ECF,) - # ECF will be set if the offset is too large. - bri t0, label("end"), flags=(nCECF,) - - -# -# Jump to the right portion -# - movi t2, t2, label("standardStart"), flags=(CEZF,) - movi t2, t2, label("extendedStart"), flags=(nCEZF,) - # This gives each function 8 microops to use. It's wasteful because only - # 5 will be needed, but a multiply would be expensive. In the system - # described in the RISC86 patent, the fifth instruction would really be - # the sequencing field on an op quad, so each function would be implemented - # by -exactly- one op quad. Since we're approximating, this should be ok. - slli t1, t1, 3 - br t2, t1 - -############################################################################# -############################################################################# - -# -# Standard functions. -# - -standardStart: - -# 0x00000000 -- Processor Vendor and Largest Standard Function Number - limm rax, 0x00000001, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x00000001 -- Family, Model, Stepping Identifiers - limm rax, 0x00020f51, dataSize=4 - limm rbx, 0x00000405, dataSize=4 - limm rdx, 0xe3d3fbff, dataSize=4 - limm rcx, 0x00000001, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# -# Extended functions. -# - -extendedStart: - -# 0x80000000 -- Processor Vendor and Largest Extended Function Number - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000001 -- EAX: AMD Family, Model, Stepping -# EBX: BrandId Identifier -# ECX: Feature Identifiers -# EDX: Feature Identifiers - limm rax, 0x00020f51, dataSize=4 - limm rbx, 0x00000405, dataSize=4 - limm rdx, 0xe3d3fbff, dataSize=4 - limm rcx, 0x00000001, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000002 -- Processor Name String Identifier - limm rax, 0x656B6146, dataSize=4 - limm rbx, 0x20354D20, dataSize=4 - limm rcx, 0x5F363878, dataSize=4 - limm rdx, 0x43203436, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000003 -- Processor Name String Identifier - limm rax, 0x00005550, dataSize=4 - limm rbx, 0x00000000, dataSize=4 - limm rdx, 0x00000000, dataSize=4 - limm rcx, 0x00000000, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000004 -- Processor Name String Identifier - limm rax, 0x00000000, dataSize=4 - limm rbx, 0x00000000, dataSize=4 - limm rdx, 0x00000000, dataSize=4 - limm rcx, 0x00000000, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000005 -- L1 Cache and TLB Identifiers - limm rax, 0xff08ff08, dataSize=4 - limm rbx, 0xff20ff20, dataSize=4 - limm rdx, 0x40020140, dataSize=4 - limm rcx, 0x40020140, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000006 -- L2/L3 Cache and L2 TLB Identifiers - limm rax, 0x00000000, dataSize=4 - limm rbx, 0x42004200, dataSize=4 - limm rdx, 0x00000000, dataSize=4 - limm rcx, 0x04008140, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000007 -- Advanced Power Management Information - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000008 -- Long Mode Address Size Identification - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000009 -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x8000000A -- SVM Revision and Feature Identification - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x8000000B -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x8000000C -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x8000000D -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x8000000E -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x8000000F -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000010 -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000011 -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000012 -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000013 -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000014 -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000015 -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000016 -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000017 -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -# 0x80000018 -- Reserved - # JUNK VALUES - limm rax, 0x80000018, dataSize=4 - limm rbx, 0x68747541, dataSize=4 - limm rdx, 0x69746e65, dataSize=4 - limm rcx, 0x444d4163, dataSize=4 - bri t0, label("end") - fault "NoFault" - fault "NoFault" - fault "NoFault" - -end: - fault "NoFault" -}; -''' diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa index 446580c1b..8bb7c5bb1 100644 --- a/src/arch/x86/isa/operands.isa +++ b/src/arch/x86/isa/operands.isa @@ -109,7 +109,10 @@ def operands {{ 'Quotient': ('IntReg', 'uqw', 'INTREG_IMPLICIT(2)', 'IsInteger', 9), 'Remainder': ('IntReg', 'uqw', 'INTREG_IMPLICIT(3)', 'IsInteger', 10), 'Divisor': ('IntReg', 'uqw', 'INTREG_IMPLICIT(4)', 'IsInteger', 11), - 'rax': ('IntReg', 'uqw', '(INTREG_RAX)', 'IsInteger', 12), + 'Rax': ('IntReg', 'uqw', '(INTREG_RAX)', 'IsInteger', 12), + 'Rbx': ('IntReg', 'uqw', '(INTREG_RBX)', 'IsInteger', 13), + 'Rcx': ('IntReg', 'uqw', '(INTREG_RCX)', 'IsInteger', 14), + 'Rdx': ('IntReg', 'uqw', '(INTREG_RDX)', 'IsInteger', 15), 'FpSrcReg1': ('FloatReg', 'df', 'src1', 'IsFloating', 20), 'FpSrcReg2': ('FloatReg', 'df', 'src2', 'IsFloating', 21), 'FpDestReg': ('FloatReg', 'df', 'dest', 'IsFloating', 22), -- cgit v1.2.3 From 77c0e1d1102af4c023bcd4609022b1600cadfea5 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 15:33:17 -0700 Subject: X86: Create a SeqOp class of microops and make Br one of them. --- .../arithmetic/multiply_and_divide.py | 24 +-- .../general_purpose/compare_and_test/bit_scan.py | 12 +- .../control_transfer/interrupts_and_exceptions.py | 28 +-- .../general_purpose/control_transfer/xreturn.py | 8 +- .../insts/general_purpose/data_transfer/move.py | 36 ++-- .../data_transfer/stack_operations.py | 6 +- .../general_purpose/input_output/string_io.py | 8 +- .../general_purpose/string/compare_strings.py | 8 +- .../insts/general_purpose/string/load_string.py | 4 +- .../insts/general_purpose/string/move_string.py | 4 +- .../insts/general_purpose/string/scan_string.py | 8 +- .../insts/general_purpose/string/store_string.py | 4 +- src/arch/x86/isa/microops/microops.isa | 3 + src/arch/x86/isa/microops/regop.isa | 4 - src/arch/x86/isa/microops/seqop.isa | 208 +++++++++++++++++++++ 15 files changed, 286 insertions(+), 79 deletions(-) create mode 100644 src/arch/x86/isa/microops/seqop.isa (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/arithmetic/multiply_and_divide.py b/src/arch/x86/isa/insts/general_purpose/arithmetic/multiply_and_divide.py index a9b53acac..19d1c7789 100644 --- a/src/arch/x86/isa/insts/general_purpose/arithmetic/multiply_and_divide.py +++ b/src/arch/x86/isa/insts/general_purpose/arithmetic/multiply_and_divide.py @@ -246,7 +246,7 @@ def macroop DIV_B_R divLoopTop: div2 t1, rax, t1, dataSize=1 div2 t1, rax, t1, flags=(EZF,), dataSize=1 - bri t0, label("divLoopTop"), flags=(nCEZF,) + br label("divLoopTop"), flags=(nCEZF,) #Unload the answer divq rax, dataSize=1 @@ -269,7 +269,7 @@ def macroop DIV_B_M divLoopTop: div2 t1, rax, t1, dataSize=1 div2 t1, rax, t1, flags=(EZF,), dataSize=1 - bri t0, label("divLoopTop"), flags=(nCEZF,) + br label("divLoopTop"), flags=(nCEZF,) #Unload the answer divq rax, dataSize=1 @@ -293,7 +293,7 @@ def macroop DIV_B_P divLoopTop: div2 t1, rax, t1, dataSize=1 div2 t1, rax, t1, flags=(EZF,), dataSize=1 - bri t0, label("divLoopTop"), flags=(nCEZF,) + br label("divLoopTop"), flags=(nCEZF,) #Unload the answer divq rax, dataSize=1 @@ -321,7 +321,7 @@ divLoopTop: div2 t1, rax, t1 div2 t1, rax, t1 div2 t1, rax, t1, flags=(EZF,) - bri t0, label("divLoopTop"), flags=(nCEZF,) + br label("divLoopTop"), flags=(nCEZF,) #Unload the answer divq rax @@ -347,7 +347,7 @@ divLoopTop: div2 t1, rax, t1 div2 t1, rax, t1 div2 t1, rax, t1, flags=(EZF,) - bri t0, label("divLoopTop"), flags=(nCEZF,) + br label("divLoopTop"), flags=(nCEZF,) #Unload the answer divq rax @@ -374,7 +374,7 @@ divLoopTop: div2 t1, rax, t1 div2 t1, rax, t1 div2 t1, rax, t1, flags=(EZF,) - bri t0, label("divLoopTop"), flags=(nCEZF,) + br label("divLoopTop"), flags=(nCEZF,) #Unload the answer divq rax @@ -422,7 +422,7 @@ def macroop IDIV_B_R divLoopTop: div2 t4, t1, t4, dataSize=1 div2 t4, t1, t4, flags=(EZF,), dataSize=1 - bri t0, label("divLoopTop"), flags=(nCEZF,) + br label("divLoopTop"), flags=(nCEZF,) #Unload the answer divq t5, dataSize=1 @@ -495,7 +495,7 @@ def macroop IDIV_B_M divLoopTop: div2 t4, t1, t4, dataSize=1 div2 t4, t1, t4, flags=(EZF,), dataSize=1 - bri t0, label("divLoopTop"), flags=(nCEZF,) + br label("divLoopTop"), flags=(nCEZF,) #Unload the answer divq t5, dataSize=1 @@ -569,7 +569,7 @@ def macroop IDIV_B_P divLoopTop: div2 t4, t1, t4, dataSize=1 div2 t4, t1, t4, flags=(EZF,), dataSize=1 - bri t0, label("divLoopTop"), flags=(nCEZF,) + br label("divLoopTop"), flags=(nCEZF,) #Unload the answer divq t5, dataSize=1 @@ -646,7 +646,7 @@ divLoopTop: div2 t4, t1, t4 div2 t4, t1, t4 div2 t4, t1, t4, flags=(EZF,) - bri t0, label("divLoopTop"), flags=(nCEZF,) + br label("divLoopTop"), flags=(nCEZF,) #Unload the answer divq t5 @@ -721,7 +721,7 @@ divLoopTop: div2 t4, t1, t4 div2 t4, t1, t4 div2 t4, t1, t4, flags=(EZF,) - bri t0, label("divLoopTop"), flags=(nCEZF,) + br label("divLoopTop"), flags=(nCEZF,) #Unload the answer divq t5 @@ -797,7 +797,7 @@ divLoopTop: div2 t4, t1, t4 div2 t4, t1, t4 div2 t4, t1, t4, flags=(EZF,) - bri t0, label("divLoopTop"), flags=(nCEZF,) + br label("divLoopTop"), flags=(nCEZF,) #Unload the answer divq t5 diff --git a/src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py b/src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py index bfc0af900..22364e038 100644 --- a/src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py +++ b/src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py @@ -86,7 +86,7 @@ def macroop BSR_R_R { # Determine if the input was zero, and also move it to a temp reg. movi t1, t1, t0, dataSize=8 and t1, regm, regm, flags=(ZF,) - bri t0, label("end"), flags=(CZF,) + br label("end"), flags=(CZF,) # Zero out the result register movi reg, reg, 0x0 @@ -137,7 +137,7 @@ def macroop BSR_R_M { # Determine if the input was zero, and also move it to a temp reg. and t1, t1, t1, flags=(ZF,) - bri t0, label("end"), flags=(CZF,) + br label("end"), flags=(CZF,) # Zero out the result register movi reg, reg, 0x0 @@ -189,7 +189,7 @@ def macroop BSR_R_P { # Determine if the input was zero, and also move it to a temp reg. and t1, t1, t1, flags=(ZF,) - bri t0, label("end"), flags=(CZF,) + br label("end"), flags=(CZF,) # Zero out the result register movi reg, reg, 0x0 @@ -237,7 +237,7 @@ def macroop BSF_R_R { # Determine if the input was zero, and also move it to a temp reg. mov t1, t1, t0, dataSize=8 and t1, regm, regm, flags=(ZF,) - bri t0, label("end"), flags=(CZF,) + br label("end"), flags=(CZF,) # Zero out the result register movi reg, reg, 0 @@ -292,7 +292,7 @@ def macroop BSF_R_M { # Determine if the input was zero, and also move it to a temp reg. and t1, t1, t1, flags=(ZF,) - bri t0, label("end"), flags=(CZF,) + br label("end"), flags=(CZF,) # Zero out the result register mov reg, reg, t0 @@ -348,7 +348,7 @@ def macroop BSF_R_P { # Determine if the input was zero, and also move it to a temp reg. and t1, t1, t1, flags=(ZF,) - bri t0, label("end"), flags=(CZF,) + br label("end"), flags=(CZF,) # Zero out the result register mov reg, reg, t0 diff --git a/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py b/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py index be562b424..125866ce5 100644 --- a/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py +++ b/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py @@ -86,16 +86,16 @@ def macroop IRET_PROT { #temp_RFLAGS.VM != 1 rcri t0, t3, 18, flags=(ECF,) - bri t0, label("protToVirtFallThrough"), flags=(nCECF,) + br label("protToVirtFallThrough"), flags=(nCECF,) #CPL=0 rdm5reg t4 andi t0, t4, 0x30, flags=(EZF,) - bri t0, label("protToVirtFallThrough"), flags=(nCEZF,) + br label("protToVirtFallThrough"), flags=(nCEZF,) #(LEGACY_MODE) rcri t0, t4, 1, flags=(ECF,) - bri t0, label("protToVirtFallThrough"), flags=(nCECF,) + br label("protToVirtFallThrough"), flags=(nCECF,) panic "iret to virtual mode not supported" @@ -113,12 +113,12 @@ protToVirtFallThrough: #CS = READ_DESCRIPTOR (temp_CS, iret_chk) andi t0, t2, 0xFC, flags=(EZF,), dataSize=2 - bri t0, label("processCSDescriptor"), flags=(CEZF,) + br label("processCSDescriptor"), flags=(CEZF,) andi t6, t2, 0xF8, dataSize=8 andi t0, t2, 0x4, flags=(EZF,), dataSize=2 - bri t0, label("globalCSDescriptor"), flags=(CEZF,) + br label("globalCSDescriptor"), flags=(CEZF,) ld t6, tsl, [1, t0, t6], dataSize=8 - bri t0, label("processCSDescriptor") + br label("processCSDescriptor") globalCSDescriptor: ld t6, tsg, [1, t0, t6], dataSize=8 processCSDescriptor: @@ -143,7 +143,7 @@ processCSDescriptor: andi t0, t4, 0xE, flags=(EZF,) # Since we just found out we're in 64 bit mode, take advantage and # do the appropriate RIP checks. - bri t0, label("doPopStackStuffAndCheckRIP"), flags=(CEZF,) + br label("doPopStackStuffAndCheckRIP"), flags=(CEZF,) # Here, we know we're -not- in 64 bit mode, so we should do the # appropriate/other RIP checks. @@ -156,17 +156,17 @@ processCSDescriptor: srli t7, t4, 4 xor t7, t7, t5 andi t0, t7, 0x3, flags=(EZF,) - bri t0, label("doPopStackStuff"), flags=(nCEZF,) + br label("doPopStackStuff"), flags=(nCEZF,) # We can modify user visible state here because we're know # we're done with things that can fault. addi rsp, rsp, "3 * env.stackSize" - bri t0, label("fallThroughPopStackStuff") + br label("fallThroughPopStackStuff") doPopStackStuffAndCheckRIP: # Check if the RIP is canonical. sra t7, t1, 47, flags=(EZF,), dataSize=ssz # if t7 isn't 0 or -1, it wasn't canonical. - bri t0, label("doPopStackStuff"), flags=(CEZF,) + br label("doPopStackStuff"), flags=(CEZF,) addi t0, t7, 1, flags=(EZF,), dataSize=ssz fault "new GeneralProtection(0)", flags=(nCEZF,) @@ -177,12 +177,12 @@ doPopStackStuff: ld t2, ss, [1, t0, rsp], "4 * env.dataSize", dataSize=ssz # SS = READ_DESCRIPTOR (temp_SS, ss_chk) andi t0, t2, 0xFC, flags=(EZF,), dataSize=2 - bri t0, label("processSSDescriptor"), flags=(CEZF,) + br label("processSSDescriptor"), flags=(CEZF,) andi t7, t2, 0xF8, dataSize=8 andi t0, t2, 0x4, flags=(EZF,), dataSize=2 - bri t0, label("globalSSDescriptor"), flags=(CEZF,) + br label("globalSSDescriptor"), flags=(CEZF,) ld t7, tsl, [1, t0, t7], dataSize=8 - bri t0, label("processSSDescriptor") + br label("processSSDescriptor") globalSSDescriptor: ld t7, tsg, [1, t0, t7], dataSize=8 processSSDescriptor: @@ -208,7 +208,7 @@ fallThroughPopStackStuff: srli t7, t4, 4 xor t7, t7, t5 andi t0, t7, 0x3, flags=(EZF,) - bri t0, label("skipSegmentSquashing"), flags=(CEZF,) + br label("skipSegmentSquashing"), flags=(CEZF,) # The attribute register needs to keep track of more info before this will # work the way it needs to. diff --git a/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py b/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py index d1a8245e6..57ec9da26 100644 --- a/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py +++ b/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py @@ -97,12 +97,12 @@ def macroop RET_FAR { # Do stuff if they're equal andi t0, t2, 0xFC, flags=(EZF,), dataSize=2 - bri t0, label("processDescriptor"), flags=(CEZF,) + br label("processDescriptor"), flags=(CEZF,) andi t3, t2, 0xF8, dataSize=8 andi t0, t2, 0x4, flags=(EZF,), dataSize=2 - bri t0, label("globalDescriptor"), flags=(CEZF,) + br label("globalDescriptor"), flags=(CEZF,) ld t3, tsl, [1, t0, t3], dataSize=8 - bri t0, label("processDescriptor") + br label("processDescriptor") globalDescriptor: ld t3, tsg, [1, t0, t3], dataSize=8 processDescriptor: @@ -112,7 +112,7 @@ processDescriptor: wrdl cs, t3, t2 wrsel cs, t2 wrip t0, t1 - bri t0, label("end") + br label("end") # Do other stuff if they're not. end: diff --git a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py index d965735f5..1e2c0c42f 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py +++ b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py @@ -240,12 +240,12 @@ def macroop MOV_REAL_S_P { def macroop MOV_S_R { andi t0, regm, 0xFC, flags=(EZF,), dataSize=2 - bri t0, label("processDescriptor"), flags=(CEZF,) + br label("processDescriptor"), flags=(CEZF,) andi t2, regm, 0xF8, dataSize=8 andi t0, regm, 0x4, flags=(EZF,), dataSize=2 - bri t0, label("globalDescriptor"), flags=(CEZF,) + br label("globalDescriptor"), flags=(CEZF,) ld t3, tsl, [1, t0, t2], dataSize=8 - bri t0, label("processDescriptor") + br label("processDescriptor") globalDescriptor: ld t3, tsg, [1, t0, t2], dataSize=8 processDescriptor: @@ -257,12 +257,12 @@ processDescriptor: def macroop MOV_S_M { ld t1, seg, sib, disp, dataSize=2 andi t0, t1, 0xFC, flags=(EZF,), dataSize=2 - bri t0, label("processDescriptor"), flags=(CEZF,) + br label("processDescriptor"), flags=(CEZF,) andi t2, t1, 0xF8, dataSize=8 andi t0, t1, 0x4, flags=(EZF,), dataSize=2 - bri t0, label("globalDescriptor"), flags=(CEZF,) + br label("globalDescriptor"), flags=(CEZF,) ld t3, tsl, [1, t0, t2], dataSize=8 - bri t0, label("processDescriptor") + br label("processDescriptor") globalDescriptor: ld t3, tsg, [1, t0, t2], dataSize=8 processDescriptor: @@ -275,12 +275,12 @@ def macroop MOV_S_P { rdip t7 ld t1, seg, riprel, disp, dataSize=2 andi t0, t1, 0xFC, flags=(EZF,), dataSize=2 - bri t0, label("processDescriptor"), flags=(CEZF,) + br label("processDescriptor"), flags=(CEZF,) andi t2, t1, 0xF8, dataSize=8 andi t0, t1, 0x4, flags=(EZF,), dataSize=2 - bri t0, label("globalDescriptor"), flags=(CEZF,) + br label("globalDescriptor"), flags=(CEZF,) ld t3, tsl, [1, t0, t2], dataSize=8 - bri t0, label("processDescriptor") + br label("processDescriptor") globalDescriptor: ld t3, tsg, [1, t0, t2], dataSize=8 processDescriptor: @@ -291,12 +291,12 @@ processDescriptor: def macroop MOVSS_S_R { andi t0, regm, 0xFC, flags=(EZF,), dataSize=2 - bri t0, label("processDescriptor"), flags=(CEZF,) + br label("processDescriptor"), flags=(CEZF,) andi t2, regm, 0xF8, dataSize=8 andi t0, regm, 0x4, flags=(EZF,), dataSize=2 - bri t0, label("globalDescriptor"), flags=(CEZF,) + br label("globalDescriptor"), flags=(CEZF,) ld t3, tsl, [1, t0, t2], dataSize=8 - bri t0, label("processDescriptor") + br label("processDescriptor") globalDescriptor: ld t3, tsg, [1, t0, t2], dataSize=8 processDescriptor: @@ -308,12 +308,12 @@ processDescriptor: def macroop MOVSS_S_M { ld t1, seg, sib, disp, dataSize=2 andi t0, t1, 0xFC, flags=(EZF,), dataSize=2 - bri t0, label("processDescriptor"), flags=(CEZF,) + br label("processDescriptor"), flags=(CEZF,) andi t2, t1, 0xF8, dataSize=8 andi t0, t1, 0x4, flags=(EZF,), dataSize=2 - bri t0, label("globalDescriptor"), flags=(CEZF,) + br label("globalDescriptor"), flags=(CEZF,) ld t3, tsl, [1, t0, t2], dataSize=8 - bri t0, label("processDescriptor") + br label("processDescriptor") globalDescriptor: ld t3, tsg, [1, t0, t2], dataSize=8 processDescriptor: @@ -326,12 +326,12 @@ def macroop MOVSS_S_P { rdip t7 ld t1, seg, riprel, disp, dataSize=2 andi t0, t1, 0xFC, flags=(EZF,), dataSize=2 - bri t0, label("processDescriptor"), flags=(CEZF,) + br label("processDescriptor"), flags=(CEZF,) andi t2, t1, 0xF8, dataSize=8 andi t0, t1, 0x4, flags=(EZF,), dataSize=2 - bri t0, label("globalDescriptor"), flags=(CEZF,) + br label("globalDescriptor"), flags=(CEZF,) ld t3, tsl, [1, t0, t2], dataSize=8 - bri t0, label("processDescriptor") + br label("processDescriptor") globalDescriptor: ld t3, tsg, [1, t0, t2], dataSize=8 processDescriptor: diff --git a/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py b/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py index 64efd7dc9..8ec957d11 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py +++ b/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py @@ -175,11 +175,11 @@ def macroop ENTER_I_I { # If the nesting level is zero, skip all this stuff. subi t0, t1, t0, flags=(EZF,), dataSize=2 - bri t0, label("skipLoop"), flags=(CEZF,) + br label("skipLoop"), flags=(CEZF,) # If the level was 1, only push the saved rbp subi t0, t1, 1, flags=(EZF,) - bri t0, label("bottomOfLoop"), flags=(CEZF,) + br label("bottomOfLoop"), flags=(CEZF,) limm t4, "ULL(-1)", dataSize=8 topOfLoop: @@ -189,7 +189,7 @@ topOfLoop: # If we're not done yet, loop subi t4, t4, 1, dataSize=8 add t0, t4, t1, flags=(EZF,) - bri t0, label("topOfLoop"), flags=(nCEZF,) + br label("topOfLoop"), flags=(nCEZF,) bottomOfLoop: # Push the old rbp onto the stack diff --git a/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py b/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py index 29b722d66..9d1d4e724 100644 --- a/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py +++ b/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py @@ -71,7 +71,7 @@ def macroop INS_M_R { def macroop INS_E_M_R { and t0, rcx, rcx, flags=(EZF,), dataSize=asz - bri t0, label("end"), flags=(CEZF,) + br label("end"), flags=(CEZF,) # Find the constant we need to either add or subtract from rdi ruflag t0, 10 movi t3, t3, dsz, flags=(CEZF,), dataSize=asz @@ -86,7 +86,7 @@ topOfLoop: subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rdi, rdi, t3, dataSize=asz - bri t0, label("topOfLoop"), flags=(nCEZF,) + br label("topOfLoop"), flags=(nCEZF,) end: fault "NoFault" }; @@ -108,7 +108,7 @@ def macroop OUTS_R_M { def macroop OUTS_E_R_M { and t0, rcx, rcx, flags=(EZF,), dataSize=asz - bri t0, label("end"), flags=(CEZF,) + br label("end"), flags=(CEZF,) # Find the constant we need to either add or subtract from rdi ruflag t0, 10 movi t3, t3, dsz, flags=(CEZF,), dataSize=asz @@ -123,7 +123,7 @@ topOfLoop: subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rsi, rsi, t3, dataSize=asz - bri t0, label("topOfLoop"), flags=(nCEZF,) + br label("topOfLoop"), flags=(nCEZF,) end: fault "NoFault" }; diff --git a/src/arch/x86/isa/insts/general_purpose/string/compare_strings.py b/src/arch/x86/isa/insts/general_purpose/string/compare_strings.py index 9810fe3c2..561b8a415 100644 --- a/src/arch/x86/isa/insts/general_purpose/string/compare_strings.py +++ b/src/arch/x86/isa/insts/general_purpose/string/compare_strings.py @@ -76,7 +76,7 @@ def macroop CMPS_M_M { def macroop CMPS_E_M_M { and t0, rcx, rcx, flags=(EZF,), dataSize=asz - bri t0, label("end"), flags=(CEZF,) + br label("end"), flags=(CEZF,) # Find the constant we need to either add or subtract from rdi ruflag t0, 10 @@ -92,14 +92,14 @@ topOfLoop: subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rdi, rdi, t3, dataSize=asz add rsi, rsi, t3, dataSize=asz - bri t0, label("topOfLoop"), flags=(CSTRZnEZF,) + br label("topOfLoop"), flags=(CSTRZnEZF,) end: fault "NoFault" }; def macroop CMPS_N_M_M { and t0, rcx, rcx, flags=(EZF,), dataSize=asz - bri t0, label("end"), flags=(CEZF,) + br label("end"), flags=(CEZF,) # Find the constant we need to either add or subtract from rdi ruflag t0, 10 @@ -115,7 +115,7 @@ topOfLoop: subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rdi, rdi, t3, dataSize=asz add rsi, rsi, t3, dataSize=asz - bri t0, label("topOfLoop"), flags=(CSTRnZnEZF,) + br label("topOfLoop"), flags=(CSTRnZnEZF,) end: fault "NoFault" }; diff --git a/src/arch/x86/isa/insts/general_purpose/string/load_string.py b/src/arch/x86/isa/insts/general_purpose/string/load_string.py index 8cf07fea6..8d144dc4d 100644 --- a/src/arch/x86/isa/insts/general_purpose/string/load_string.py +++ b/src/arch/x86/isa/insts/general_purpose/string/load_string.py @@ -68,7 +68,7 @@ def macroop LODS_M { def macroop LODS_E_M { and t0, rcx, rcx, flags=(EZF,), dataSize=asz - bri t0, label("end"), flags=(CEZF,) + br label("end"), flags=(CEZF,) # Find the constant we need to either add or subtract from rdi ruflag t0, 10 movi t3, t3, dsz, flags=(CEZF,), dataSize=asz @@ -80,7 +80,7 @@ topOfLoop: subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rdi, rdi, t3, dataSize=asz - bri t0, label("topOfLoop"), flags=(nCEZF,) + br label("topOfLoop"), flags=(nCEZF,) end: fault "NoFault" }; diff --git a/src/arch/x86/isa/insts/general_purpose/string/move_string.py b/src/arch/x86/isa/insts/general_purpose/string/move_string.py index 1d7dd75ad..18faa38e2 100644 --- a/src/arch/x86/isa/insts/general_purpose/string/move_string.py +++ b/src/arch/x86/isa/insts/general_purpose/string/move_string.py @@ -70,7 +70,7 @@ def macroop MOVS_M_M { def macroop MOVS_E_M_M { and t0, rcx, rcx, flags=(EZF,), dataSize=asz - bri t0, label("end"), flags=(CEZF,) + br label("end"), flags=(CEZF,) # Find the constant we need to either add or subtract from rdi ruflag t0, 10 movi t3, t3, dsz, flags=(CEZF,), dataSize=asz @@ -84,7 +84,7 @@ topOfLoop: subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rdi, rdi, t3, dataSize=asz add rsi, rsi, t3, dataSize=asz - bri t0, label("topOfLoop"), flags=(nCEZF,) + br label("topOfLoop"), flags=(nCEZF,) end: fault "NoFault" }; diff --git a/src/arch/x86/isa/insts/general_purpose/string/scan_string.py b/src/arch/x86/isa/insts/general_purpose/string/scan_string.py index b37e367be..5b0e74aad 100644 --- a/src/arch/x86/isa/insts/general_purpose/string/scan_string.py +++ b/src/arch/x86/isa/insts/general_purpose/string/scan_string.py @@ -74,7 +74,7 @@ def macroop SCAS_M { def macroop SCAS_E_M { and t0, rcx, rcx, flags=(EZF,), dataSize=asz - bri t0, label("end"), flags=(CEZF,) + br label("end"), flags=(CEZF,) # Find the constant we need to either add or subtract from rdi ruflag t0, 10 @@ -88,14 +88,14 @@ topOfLoop: subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rdi, rdi, t2, dataSize=asz - bri t0, label("topOfLoop"), flags=(CSTRZnEZF,) + br label("topOfLoop"), flags=(CSTRZnEZF,) end: fault "NoFault" }; def macroop SCAS_N_M { and t0, rcx, rcx, flags=(EZF,), dataSize=asz - bri t0, label("end"), flags=(CEZF,) + br label("end"), flags=(CEZF,) # Find the constant we need to either add or subtract from rdi ruflag t0, 10 @@ -109,7 +109,7 @@ topOfLoop: subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rdi, rdi, t2, dataSize=asz - bri t0, label("topOfLoop"), flags=(CSTRnZnEZF,) + br label("topOfLoop"), flags=(CSTRnZnEZF,) end: fault "NoFault" }; diff --git a/src/arch/x86/isa/insts/general_purpose/string/store_string.py b/src/arch/x86/isa/insts/general_purpose/string/store_string.py index b52b1f1fb..fe9917ce6 100644 --- a/src/arch/x86/isa/insts/general_purpose/string/store_string.py +++ b/src/arch/x86/isa/insts/general_purpose/string/store_string.py @@ -68,7 +68,7 @@ def macroop STOS_M { def macroop STOS_E_M { and t0, rcx, rcx, flags=(EZF,), dataSize=asz - bri t0, label("end"), flags=(CEZF,) + br label("end"), flags=(CEZF,) # Find the constant we need to either add or subtract from rdi ruflag t0, 10 movi t3, t3, dsz, flags=(CEZF,), dataSize=asz @@ -80,7 +80,7 @@ topOfLoop: subi rcx, rcx, 1, flags=(EZF,), dataSize=asz add rdi, rdi, t3, dataSize=asz - bri t0, label("topOfLoop"), flags=(nCEZF,) + br label("topOfLoop"), flags=(nCEZF,) end: fault "NoFault" }; diff --git a/src/arch/x86/isa/microops/microops.isa b/src/arch/x86/isa/microops/microops.isa index 1c9e8358a..19266f6d6 100644 --- a/src/arch/x86/isa/microops/microops.isa +++ b/src/arch/x86/isa/microops/microops.isa @@ -68,6 +68,9 @@ //Load/store microop definitions ##include "ldstop.isa" +//Control flow microop definitions +##include "seqop.isa" + //Miscellaneous microop definitions ##include "specop.isa" diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index b751b9b4f..d0d7062ff 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -843,10 +843,6 @@ let {{ code = 'RIP = psrc1 + sop2 + CSBase' else_code="RIP = RIP;" - class Br(WrRegOp, CondRegOp): - code = 'nuIP = psrc1 + op2;' - else_code='nuIP = nuIP;' - class Wruflags(WrRegOp): code = 'ccFlagBits = psrc1 ^ op2' diff --git a/src/arch/x86/isa/microops/seqop.isa b/src/arch/x86/isa/microops/seqop.isa new file mode 100644 index 000000000..821afbe83 --- /dev/null +++ b/src/arch/x86/isa/microops/seqop.isa @@ -0,0 +1,208 @@ +// Copyright (c) 2008 The Hewlett-Packard Development Company +// All rights reserved. +// +// Redistribution and use of this software in source and binary forms, +// with or without modification, are permitted provided that the +// following conditions are met: +// +// The software must be used only for Non-Commercial Use which means any +// use which is NOT directed to receiving any direct monetary +// compensation for, or commercial advantage from such use. Illustrative +// examples of non-commercial use are academic research, personal study, +// teaching, education and corporate research & development. +// Illustrative examples of commercial use are distributing products for +// commercial advantage and providing services using the software for +// commercial advantage. +// +// If you wish to use this software or functionality therein that may be +// covered by patents for commercial use, please contact: +// Director of Intellectual Property Licensing +// Office of Strategy and Technology +// Hewlett-Packard Company +// 1501 Page Mill Road +// Palo Alto, California 94304 +// +// 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. No right of +// sublicense is granted herewith. Derivatives of the software and +// output created using the software may be prepared, but only for +// Non-Commercial Uses. Derivatives of the software may be shared with +// others provided: (i) the others agree to abide by the list of +// conditions herein which includes the Non-Commercial Use restrictions; +// and (ii) such Derivatives of the software include the above copyright +// notice to acknowledge the contribution from this software where +// applicable, this list of conditions and the disclaimer below. +// +// 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: Gabe Black + +output header {{ + class SeqOpBase : public X86ISA::X86MicroopBase + { + protected: + uint16_t target; + uint8_t cc; + + public: + SeqOpBase(ExtMachInst _machInst, const char * instMnem, + const char * mnemonic, + bool isMicro, bool isDelayed, bool isFirst, bool isLast, + uint16_t _target, uint8_t _cc); + + SeqOpBase(ExtMachInst _machInst, const char * instMnem, + const char * mnemonic, + uint16_t _target, uint8_t _cc); + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + }; +}}; + +def template SeqOpDeclare {{ + class %(class_name)s : public %(base_class)s + { + private: + void buildMe(); + public: + %(class_name)s(ExtMachInst _machInst, const char * instMnem, + bool isMicro, bool isDelayed, bool isFirst, bool isLast, + uint16_t _target, uint8_t _cc); + + %(class_name)s(ExtMachInst _machInst, const char * instMnem, + uint16_t _target, uint8_t _cc); + + %(BasicExecDeclare)s + }; +}}; + +def template SeqOpExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + %(op_decl)s; + %(op_rd)s; + if (%(cond_test)s) { + %(code)s; + } else { + %(else_code)s; + } + %(op_wb)s; + return NoFault; + } +}}; + +output decoder {{ + inline SeqOpBase::SeqOpBase( + ExtMachInst machInst, const char * mnemonic, const char * instMnem, + uint16_t _target, uint8_t _cc) : + X86MicroopBase(machInst, mnemonic, instMnem, + false, false, false, false, No_OpClass), + target(_target), cc(_cc) + { + } + + inline SeqOpBase::SeqOpBase( + ExtMachInst machInst, const char * mnemonic, const char * instMnem, + bool isMicro, bool isDelayed, bool isFirst, bool isLast, + uint16_t _target, uint8_t _cc) : + X86MicroopBase(machInst, mnemonic, instMnem, + isMicro, isDelayed, isFirst, isLast, No_OpClass), + target(_target), cc(_cc) + { + } +}}; + +def template SeqOpConstructor {{ + + inline void %(class_name)s::buildMe() + { + %(constructor)s; + } + + inline %(class_name)s::%(class_name)s( + ExtMachInst machInst, const char * instMnem, + uint16_t _target, uint8_t _cc) : + %(base_class)s(machInst, "%(mnemonic)s", instMnem, _target, _cc) + { + buildMe(); + } + + inline %(class_name)s::%(class_name)s( + ExtMachInst machInst, const char * instMnem, + bool isMicro, bool isDelayed, bool isFirst, bool isLast, + uint16_t _target, uint8_t _cc) : + %(base_class)s(machInst, "%(mnemonic)s", instMnem, + isMicro, isDelayed, isFirst, isLast, _target, _cc) + { + buildMe(); + } +}}; + +output decoder {{ + std::string SeqOpBase::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, instMnem, mnemonic); + ccprintf(response, "%#x", target); + + return response.str(); + } +}}; + +let {{ + class Br(X86Microop): + className = "MicroBranch" + def __init__(self, target, flags=None): + self.target = target + if flags: + if not isinstance(flags, (list, tuple)): + raise Exception, "flags must be a list or tuple of flags" + self.cond = " | ".join(flags) + self.className += "Flags" + else: + self.cond = "0" + + def getAllocator(self, *microFlags): + allocator = '''new %(class_name)s(machInst, mnemonic + %(flags)s, %(target)s, %(cc)s)''' % { + "class_name" : self.className, + "flags" : self.microFlagsText(microFlags), + "target" : self.target, + "cc" : self.cond} + return allocator + + iop = InstObjParams("br", "MicroBranchFlags", "SeqOpBase", + {"code": "nuIP = target", + "else_code": "nuIP = nuIP", + "cond_test": "checkCondition(ccFlagBits, cc)"}) + exec_output += SeqOpExecute.subst(iop) + header_output += SeqOpDeclare.subst(iop) + decoder_output += SeqOpConstructor.subst(iop) + iop = InstObjParams("br", "MicroBranch", "SeqOpBase", + {"code": "nuIP = target", + "else_code": "nuIP = nuIP", + "cond_test": "true"}) + exec_output += SeqOpExecute.subst(iop) + header_output += SeqOpDeclare.subst(iop) + decoder_output += SeqOpConstructor.subst(iop) + microopClasses["br"] = Br +}}; -- cgit v1.2.3 From 4aa18aa80022d9e4125faab8ff1f5123e159137d Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 15:43:35 -0700 Subject: X86: Make Br never report itself as the last microop. --- src/arch/x86/isa/microops/seqop.isa | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/microops/seqop.isa b/src/arch/x86/isa/microops/seqop.isa index 821afbe83..603f4458b 100644 --- a/src/arch/x86/isa/microops/seqop.isa +++ b/src/arch/x86/isa/microops/seqop.isa @@ -169,8 +169,7 @@ output decoder {{ }}; let {{ - class Br(X86Microop): - className = "MicroBranch" + class SeqOp(X86Microop): def __init__(self, target, flags=None): self.target = target if flags: @@ -190,6 +189,15 @@ let {{ "cc" : self.cond} return allocator + class Br(SeqOp): + className = "MicroBranch" + + def getAllocator(self, *microFlags): + (is_micro, is_delayed, is_first, is_last) = microFlags + is_last = False + microFlags = (is_micro, is_delayed, is_first, is_last) + return super(Br, self).getAllocator(*microFlags) + iop = InstObjParams("br", "MicroBranchFlags", "SeqOpBase", {"code": "nuIP = target", "else_code": "nuIP = nuIP", -- cgit v1.2.3 From 6fd4eff68f53ec1cd9194581bfa223bfbaa2d83d Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 15:53:04 -0700 Subject: X86: Create an eret microop which returns from ROM to combinational decoding. --- src/arch/x86/isa/microops/seqop.isa | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'src') diff --git a/src/arch/x86/isa/microops/seqop.isa b/src/arch/x86/isa/microops/seqop.isa index 603f4458b..d3c7bf096 100644 --- a/src/arch/x86/isa/microops/seqop.isa +++ b/src/arch/x86/isa/microops/seqop.isa @@ -198,6 +198,25 @@ let {{ microFlags = (is_micro, is_delayed, is_first, is_last) return super(Br, self).getAllocator(*microFlags) + class Eret(SeqOp): + target = "normalMicroPC(0)" + className = "Eret" + + def __init__(self, flags=None): + if flags: + if not isinstance(flags, (list, tuple)): + raise Exception, "flags must be a list or tuple of flags" + self.cond = " | ".join(flags) + self.className += "Flags" + else: + self.cond = "0" + + def getAllocator(self, *microFlags): + (is_micro, is_delayed, is_first, is_last) = microFlags + is_last = True + microFlags = (is_micro, is_delayed, is_first, is_last) + return super(Eret, self).getAllocator(*microFlags) + iop = InstObjParams("br", "MicroBranchFlags", "SeqOpBase", {"code": "nuIP = target", "else_code": "nuIP = nuIP", @@ -213,4 +232,18 @@ let {{ header_output += SeqOpDeclare.subst(iop) decoder_output += SeqOpConstructor.subst(iop) microopClasses["br"] = Br + + iop = InstObjParams("eret", "EretFlags", "SeqOpBase", + {"code": "", "else_code": "", + "cond_test": "checkCondition(ccFlagBits, cc)"}) + exec_output += SeqOpExecute.subst(iop) + header_output += SeqOpDeclare.subst(iop) + decoder_output += SeqOpConstructor.subst(iop) + iop = InstObjParams("eret", "Eret", "SeqOpBase", + {"code": "", "else_code": "", + "cond_test": "true"}) + exec_output += SeqOpExecute.subst(iop) + header_output += SeqOpDeclare.subst(iop) + decoder_output += SeqOpConstructor.subst(iop) + microopClasses["eret"] = Eret }}; -- cgit v1.2.3 From 2736086d7c67a24d9eb87827a22a2b352e342ba2 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 15:59:21 -0700 Subject: CPU: Create a microcode ROM object in the CPU which is defined by the ISA. --- src/arch/SConscript | 1 + src/arch/alpha/microcode_rom.hh | 41 ++++++++++++++++++++++++++++++++ src/arch/mips/microcode_rom.hh | 41 ++++++++++++++++++++++++++++++++ src/arch/sparc/microcode_rom.hh | 41 ++++++++++++++++++++++++++++++++ src/arch/x86/microcode_rom.hh | 41 ++++++++++++++++++++++++++++++++ src/cpu/base.hh | 3 +++ src/sim/microcode_rom.hh | 52 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 220 insertions(+) create mode 100644 src/arch/alpha/microcode_rom.hh create mode 100644 src/arch/mips/microcode_rom.hh create mode 100644 src/arch/sparc/microcode_rom.hh create mode 100644 src/arch/x86/microcode_rom.hh create mode 100644 src/sim/microcode_rom.hh (limited to 'src') diff --git a/src/arch/SConscript b/src/arch/SConscript index 66f93870e..932cf7509 100644 --- a/src/arch/SConscript +++ b/src/arch/SConscript @@ -49,6 +49,7 @@ isa_switch_hdrs = Split(''' isa_traits.hh kernel_stats.hh locked_mem.hh + microcode_rom.hh mmaped_ipr.hh process.hh predecoder.hh diff --git a/src/arch/alpha/microcode_rom.hh b/src/arch/alpha/microcode_rom.hh new file mode 100644 index 000000000..ef0602580 --- /dev/null +++ b/src/arch/alpha/microcode_rom.hh @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_ALPHA_MICROCODE_ROM_HH__ +#define __ARCH_ALPHA_MICROCODE_ROM_HH__ + +#include "sim/microcode_rom.hh" + +namespace AlphaISA +{ + using ::MicrocodeRom; +} + +#endif // __ARCH_ALPHA_MICROCODE_ROM_HH__ diff --git a/src/arch/mips/microcode_rom.hh b/src/arch/mips/microcode_rom.hh new file mode 100644 index 000000000..a5be81e2a --- /dev/null +++ b/src/arch/mips/microcode_rom.hh @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_MIPS_MICROCODE_ROM_HH__ +#define __ARCH_MIPS_MICROCODE_ROM_HH__ + +#include "sim/microcode_rom.hh" + +namespace MipsISA +{ + using ::MicrocodeRom; +} + +#endif // __ARCH_MIPS_MICROCODE_ROM_HH__ diff --git a/src/arch/sparc/microcode_rom.hh b/src/arch/sparc/microcode_rom.hh new file mode 100644 index 000000000..e46000dcc --- /dev/null +++ b/src/arch/sparc/microcode_rom.hh @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_SPARC_MICROCODE_ROM_HH__ +#define __ARCH_SPARC_MICROCODE_ROM_HH__ + +#include "sim/microcode_rom.hh" + +namespace SparcISA +{ + using ::MicrocodeRom; +} + +#endif // __ARCH_SPARC_MICROCODE_ROM_HH__ diff --git a/src/arch/x86/microcode_rom.hh b/src/arch/x86/microcode_rom.hh new file mode 100644 index 000000000..1495ff699 --- /dev/null +++ b/src/arch/x86/microcode_rom.hh @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_MICROCODE_ROM_HH__ +#define __ARCH_X86_MICROCODE_ROM_HH__ + +#include "sim/microcode_rom.hh" + +namespace X86ISA +{ + using ::MicrocodeRom; +} + +#endif // __ARCH_X86_MICROCODE_ROM_HH__ diff --git a/src/cpu/base.hh b/src/cpu/base.hh index a12c98ab0..b0eece2a1 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -35,6 +35,7 @@ #include #include "arch/isa_traits.hh" +#include "arch/microcode_rom.hh" #include "base/statistics.hh" #include "config/full_system.hh" #include "sim/eventq.hh" @@ -103,6 +104,8 @@ class BaseCPU : public MemObject */ Tick nextCycle(Tick begin_tick); + TheISA::MicrocodeRom microcodeRom; + #if FULL_SYSTEM protected: // uint64_t interrupts[TheISA::NumInterruptLevels]; diff --git a/src/sim/microcode_rom.hh b/src/sim/microcode_rom.hh new file mode 100644 index 000000000..be10de86b --- /dev/null +++ b/src/sim/microcode_rom.hh @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __SIM_MICROCODE_ROM_HH__ +#define __SIM_MICROCODE_ROM_HH__ + +/* + * This is a generic stub microcode ROM ISAs can use if they don't need + * anything more. + */ + +#include "base/misc.hh" +#include "cpu/static_inst.hh" + +class MicrocodeRom +{ + public: + StaticInstPtr + fetchMicroop(MicroPC micropc, StaticInstPtr curMacroop) + { + panic("ROM based microcode isn't implemented.\n"); + } +}; + +#endif // __SIM_MICROCODE_ROM_HH__ -- cgit v1.2.3 From c9ea0b73492bf116c836c54199898f29d9664bc0 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 16:59:55 -0700 Subject: CPU: Make the highest order bit in the micro pc determine if it's combinational or from the ROM. --- src/cpu/simple/base.cc | 29 ++++++++++++++++------------- src/cpu/static_inst.hh | 20 ++++++++++++++++++++ 2 files changed, 36 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index 48e5db347..d207bda14 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -368,9 +368,13 @@ BaseSimpleCPU::preExecute() // decode the instruction inst = gtoh(inst); - //If we're not in the middle of a macro instruction - if (!curMacroStaticInst) { + MicroPC upc = thread->readMicroPC(); + if (isRomMicroPC(upc)) { + stayAtPC = false; + curStaticInst = microcodeRom.fetchMicroop(upc, curMacroStaticInst); + } else if (!curMacroStaticInst) { + //We're not in the middle of a macro instruction StaticInstPtr instPtr = NULL; //Predecode, ie bundle up an ExtMachInst @@ -401,15 +405,13 @@ BaseSimpleCPU::preExecute() //out micro ops if (instPtr && instPtr->isMacroop()) { curMacroStaticInst = instPtr; - curStaticInst = curMacroStaticInst-> - fetchMicroop(thread->readMicroPC()); + curStaticInst = curMacroStaticInst->fetchMicroop(upc); } else { curStaticInst = instPtr; } } else { //Read the next micro op from the macro op - curStaticInst = curMacroStaticInst-> - fetchMicroop(thread->readMicroPC()); + curStaticInst = curMacroStaticInst->fetchMicroop(upc); } //If we decoded an instruction this "tick", record information about it. @@ -469,22 +471,23 @@ BaseSimpleCPU::advancePC(Fault fault) if (fault != NoFault) { curMacroStaticInst = StaticInst::nullStaticInstPtr; predecoder.reset(); - thread->setMicroPC(0); - thread->setNextMicroPC(1); + thread->setMicroPC(normalMicroPC(0)); + thread->setNextMicroPC(normalMicroPC(1)); fault->invoke(tc); } else { //If we're at the last micro op for this instruction if (curStaticInst && curStaticInst->isLastMicroop()) { - //We should be working with a macro op - assert(curMacroStaticInst); + //We should be working with a macro op or be in the ROM + assert(curMacroStaticInst || + isRomMicroPC(thread->readMicroPC())); //Close out this macro op, and clean up the //microcode state curMacroStaticInst = StaticInst::nullStaticInstPtr; - thread->setMicroPC(0); - thread->setNextMicroPC(1); + thread->setMicroPC(normalMicroPC(0)); + thread->setNextMicroPC(normalMicroPC(1)); } //If we're still in a macro op - if (curMacroStaticInst) { + if (curMacroStaticInst || isRomMicroPC(thread->readMicroPC())) { //Advance the micro pc thread->setMicroPC(thread->readNextMicroPC()); //Advance the "next" micro pc. Note that there are no delay diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index 8a1b3e749..c9eb6ff24 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -74,6 +74,26 @@ namespace Trace { typedef uint32_t MicroPC; +static const MicroPC MicroPCRomBit = 1 << (sizeof(MicroPC) * 8 - 1); + +static inline MicroPC +romMicroPC(MicroPC upc) +{ + return upc | MicroPCRomBit; +} + +static inline MicroPC +normalMicroPC(MicroPC upc) +{ + return upc & ~MicroPCRomBit; +} + +static inline bool +isRomMicroPC(MicroPC upc) +{ + return MicroPCRomBit & upc; +} + /** * Base, ISA-independent static instruction class. * -- cgit v1.2.3 From e5f80924671bf0cfaf02c51f4b98d529631733f1 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 17:48:44 -0700 Subject: X86: Make X86's microcode ROM actually do something. --- src/arch/x86/isa/includes.isa | 1 + src/arch/x86/isa/macroop.isa | 20 +++++++-- src/arch/x86/isa/microasm.isa | 10 ++++- src/arch/x86/isa/microops/base.isa | 30 +++++++++++++ src/arch/x86/isa/rom.isa | 90 ++++++++++++++++++++++++++++++++++++++ src/arch/x86/microcode_rom.hh | 37 +++++++++++++++- 6 files changed, 181 insertions(+), 7 deletions(-) create mode 100644 src/arch/x86/isa/rom.isa (limited to 'src') diff --git a/src/arch/x86/isa/includes.isa b/src/arch/x86/isa/includes.isa index 926e9185a..e523b7e32 100644 --- a/src/arch/x86/isa/includes.isa +++ b/src/arch/x86/isa/includes.isa @@ -113,6 +113,7 @@ output header {{ output decoder {{ #include "arch/x86/faults.hh" #include "arch/x86/floatregs.hh" +#include "arch/x86/microcode_rom.hh" #include "arch/x86/miscregs.hh" #include "arch/x86/segmentregs.hh" #include "base/cprintf.hh" diff --git a/src/arch/x86/isa/macroop.isa b/src/arch/x86/isa/macroop.isa index 4818b926c..b851a92c7 100644 --- a/src/arch/x86/isa/macroop.isa +++ b/src/arch/x86/isa/macroop.isa @@ -76,12 +76,13 @@ output header {{ { protected: const uint32_t numMicroops; + X86ISA::EmulEnv emulEnv; //Constructor. Macroop(const char *mnem, ExtMachInst _machInst, - uint32_t _numMicroops) + uint32_t _numMicroops, X86ISA::EmulEnv _emulEnv) : StaticInst(mnem, _machInst, No_OpClass), - numMicroops(_numMicroops) + numMicroops(_numMicroops), emulEnv(_emulEnv) { assert(numMicroops); microops = new StaticInstPtr[numMicroops]; @@ -107,7 +108,20 @@ output header {{ return mnemonic; } + public: %(MacroExecPanic)s + + ExtMachInst + getExtMachInst() + { + return machInst; + } + + X86ISA::EmulEnv + getEmulEnv() + { + return emulEnv; + } }; }}; @@ -139,7 +153,7 @@ def template MacroDeclare {{ def template MacroConstructor {{ inline X86Macroop::%(class_name)s::%(class_name)s( ExtMachInst machInst, EmulEnv env) - : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s) + : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s, env) { %(adjust_env)s; %(adjust_imm)s; diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa index 735a7722c..9a5019f10 100644 --- a/src/arch/x86/isa/microasm.isa +++ b/src/arch/x86/isa/microasm.isa @@ -64,13 +64,16 @@ //Include code to build macroops in both C++ and python. ##include "macroop.isa" +//Include code to fill out the microcode ROM in both C++ and python. +##include "rom.isa" + let {{ import sys sys.path[0:0] = ["src/arch/x86/isa/"] from insts import microcode # print microcode - from micro_asm import MicroAssembler, Rom_Macroop, Rom - mainRom = Rom('main ROM') + from micro_asm import MicroAssembler, Rom_Macroop + mainRom = X86MicrocodeRom('main ROM') assembler = MicroAssembler(X86Macroop, microopClasses, mainRom, Rom_Macroop) # Add in symbols for the microcode registers for num in range(15): @@ -186,4 +189,7 @@ let {{ assembler.symbols["st"] = stack_index macroopDict = assembler.assemble(microcode) + + decoder_output += mainRom.getDefinition() + header_output += mainRom.getDeclaration() }}; diff --git a/src/arch/x86/isa/microops/base.isa b/src/arch/x86/isa/microops/base.isa index 75658a26c..994e997d8 100644 --- a/src/arch/x86/isa/microops/base.isa +++ b/src/arch/x86/isa/microops/base.isa @@ -69,6 +69,28 @@ let {{ let {{ class X86Microop(object): + + generatorNameTemplate = "generate_%s_%d" + + generatorTemplate = ''' + StaticInstPtr + ''' + generatorNameTemplate + '''(StaticInstPtr curMacroop) + { + static const char * mnemonic = romMnemonic; + static const ExtMachInst dummyExtMachInst; + static const EmulEnv dummyEmulEnv(0, 0, 1, 1, 1); + + Macroop * macroop = dynamic_cast(curMacroop.get()); + const ExtMachInst &machInst = + macroop ? macroop->getExtMachInst() : dummyExtMachInst; + const EmulEnv &env = + macroop ? macroop->getEmulEnv() : dummyEmulEnv; + // env may not be used in the microop's constructor. + RegIndex reg = env.reg; + reg = reg; + return %s; + } + ''' def __init__(self, name): self.name = name @@ -91,4 +113,12 @@ let {{ def getAllocator(self, mnemonic, *microFlags): return 'new %s(machInst, %s)' % \ (self.className, mnemonic, self.microFlagsText(microFlags)) + + def getGeneratorDef(self, micropc): + return self.generatorTemplate % \ + (self.className, micropc, \ + self.getAllocator(True, False, False, False)) + + def getGenerator(self, micropc): + return self.generatorNameTemplate % (self.className, micropc) }}; diff --git a/src/arch/x86/isa/rom.isa b/src/arch/x86/isa/rom.isa new file mode 100644 index 000000000..7d3eb8670 --- /dev/null +++ b/src/arch/x86/isa/rom.isa @@ -0,0 +1,90 @@ +// Copyright (c) 2008 The Regents of The University of Michigan +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Gabe Black + +def template MicroRomConstructor {{ + + %(define_generators)s + const MicroPC X86ISA::MicrocodeRom::numMicroops = %(num_microops)s; + + X86ISA::MicrocodeRom::MicrocodeRom() + { + using namespace RomLabels; + genFuncs = new GenFunc[numMicroops]; + %(alloc_generators)s; + } +}}; + +let {{ + from micro_asm import Rom + + class X86MicrocodeRom(Rom): + def __init__(self, name): + super(X86MicrocodeRom, self).__init__(name) + self.directives = {} + + def add_microop(self, mnemonic, microop): + microop.mnemonic = mnemonic + microop.micropc = len(self.microops) + self.microops.append(microop) + + + def getDeclaration(self): + declareLabels = "namespace RomLabels {\n" + for (label, microop) in self.labels.items(): + declareLabels += "const static uint64_t label_%s = %d;\n" \ + % (label, microop.micropc) + for (label, microop) in self.externs.items(): + declareLabels += \ + "const static MicroPC extern_label_%s = %d;\n" \ + % (label, microop.micropc) + declareLabels += "}\n" + return declareLabels; + + def getDefinition(self): + numMicroops = len(self.microops) + allocGenerators = '' + micropc = 0 + define_generators = ''' + namespace + { + static const char romMnemonic[] = "Microcode_ROM"; + ''' + for op in self.microops: + define_generators += op.getGeneratorDef(micropc) + allocGenerators += "genFuncs[%d] = %s;\n" % \ + (micropc, op.getGenerator(micropc)) + micropc += 1 + define_generators += "}\n" + iop = InstObjParams(self.name, self.name, "MicrocodeRom", + {"code" : "", + "define_generators" : define_generators, + "num_microops" : numMicroops, + "alloc_generators" : allocGenerators + }) + return MicroRomConstructor.subst(iop); +}}; diff --git a/src/arch/x86/microcode_rom.hh b/src/arch/x86/microcode_rom.hh index 1495ff699..f8ad410ce 100644 --- a/src/arch/x86/microcode_rom.hh +++ b/src/arch/x86/microcode_rom.hh @@ -31,11 +31,44 @@ #ifndef __ARCH_X86_MICROCODE_ROM_HH__ #define __ARCH_X86_MICROCODE_ROM_HH__ -#include "sim/microcode_rom.hh" +#include "arch/x86/emulenv.hh" +#include "cpu/static_inst.hh" + +namespace X86ISAInst +{ + class MicrocodeRom + { + protected: + + typedef StaticInstPtr (*GenFunc)(StaticInstPtr); + + static const MicroPC numMicroops; + + GenFunc * genFuncs; + + public: + //Constructor. + MicrocodeRom(); + + //Destructor. + ~MicrocodeRom() + { + delete [] genFuncs; + } + + StaticInstPtr + fetchMicroop(MicroPC microPC, StaticInstPtr curMacroop) + { + microPC = normalMicroPC(microPC); + assert(microPC < numMicroops); + return genFuncs[microPC](curMacroop); + } + }; +} namespace X86ISA { - using ::MicrocodeRom; + using X86ISAInst::MicrocodeRom; } #endif // __ARCH_X86_MICROCODE_ROM_HH__ -- cgit v1.2.3 From cefb768131b1d0582c5cbe83feaa97060dfe15af Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 17:52:51 -0700 Subject: X86: Create a handy way to access labels from the ROM in microcode. --- src/arch/x86/isa/microasm.isa | 5 +++++ src/arch/x86/isa/microops/base.isa | 1 + src/arch/x86/isa/rom.isa | 3 --- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa index 9a5019f10..d7b008145 100644 --- a/src/arch/x86/isa/microasm.isa +++ b/src/arch/x86/isa/microasm.isa @@ -183,6 +183,11 @@ let {{ assembler.symbols["label"] = labeler + def rom_labeler(labelStr): + return "romMicroPC(RomLabels::extern_label_%s)" % labelStr + + assembler.symbols["rom_label"] = rom_labeler + def stack_index(index): return "(NUM_FLOATREGS + (((%s) + 8) %% 8))" % index diff --git a/src/arch/x86/isa/microops/base.isa b/src/arch/x86/isa/microops/base.isa index 994e997d8..057d237ad 100644 --- a/src/arch/x86/isa/microops/base.isa +++ b/src/arch/x86/isa/microops/base.isa @@ -88,6 +88,7 @@ let {{ // env may not be used in the microop's constructor. RegIndex reg = env.reg; reg = reg; + using namespace RomLabels; return %s; } ''' diff --git a/src/arch/x86/isa/rom.isa b/src/arch/x86/isa/rom.isa index 7d3eb8670..59b280056 100644 --- a/src/arch/x86/isa/rom.isa +++ b/src/arch/x86/isa/rom.isa @@ -55,9 +55,6 @@ let {{ def getDeclaration(self): declareLabels = "namespace RomLabels {\n" - for (label, microop) in self.labels.items(): - declareLabels += "const static uint64_t label_%s = %d;\n" \ - % (label, microop.micropc) for (label, microop) in self.externs.items(): declareLabels += \ "const static MicroPC extern_label_%s = %d;\n" \ -- cgit v1.2.3 From f245358343fb26ac976d15b8f2a023caa0f9ba0d Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 17:57:46 -0700 Subject: Get rid of old RegContext code. --- src/arch/alpha/regfile.hh | 7 ------- src/arch/alpha/types.hh | 7 ------- src/arch/mips/regfile.cc | 6 ------ src/arch/mips/regfile/regfile.hh | 4 ---- src/arch/mips/types.hh | 3 --- src/arch/sparc/miscregfile.cc | 3 --- src/arch/sparc/regfile.cc | 15 --------------- src/arch/sparc/regfile.hh | 2 -- src/arch/sparc/types.hh | 8 -------- src/arch/x86/regfile.cc | 5 ----- src/arch/x86/regfile.hh | 2 -- src/arch/x86/types.hh | 11 ----------- src/cpu/checker/thread_context.hh | 6 ------ src/cpu/o3/thread_context.hh | 9 --------- src/cpu/ozone/cpu.hh | 3 --- src/cpu/simple_thread.hh | 6 ------ src/cpu/thread_context.hh | 9 --------- 17 files changed, 106 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/regfile.hh b/src/arch/alpha/regfile.hh index d6d2f587e..e431e7570 100644 --- a/src/arch/alpha/regfile.hh +++ b/src/arch/alpha/regfile.hh @@ -206,13 +206,6 @@ class RegFile { void serialize(EventManager *em, std::ostream &os); void unserialize(EventManager *em, Checkpoint *cp, const std::string §ion); - - void - changeContext(RegContextParam param, RegContextVal val) - { - //This would be an alternative place to call/implement - //the swapPALShadow function - } }; static inline int diff --git a/src/arch/alpha/types.hh b/src/arch/alpha/types.hh index 94a4cb0e9..7905114b8 100644 --- a/src/arch/alpha/types.hh +++ b/src/arch/alpha/types.hh @@ -57,13 +57,6 @@ union AnyReg MiscReg ctrlreg; }; -enum RegContextParam -{ - CONTEXT_PALMODE -}; - -typedef bool RegContextVal; - enum annotes { ANNOTE_NONE = 0, diff --git a/src/arch/mips/regfile.cc b/src/arch/mips/regfile.cc index 0c670af6d..e05bfe2df 100644 --- a/src/arch/mips/regfile.cc +++ b/src/arch/mips/regfile.cc @@ -188,12 +188,6 @@ RegFile::unserialize(Checkpoint *cp, const std::string §ion) } - -void RegFile::changeContext(RegContextParam param, RegContextVal val) -{ - panic("Change Context Not Implemented for MipsISA"); -} - static inline int flattenIntIndex(ThreadContext * tc, int reg) { return reg; diff --git a/src/arch/mips/regfile/regfile.hh b/src/arch/mips/regfile/regfile.hh index 076cf45f5..ebf793396 100644 --- a/src/arch/mips/regfile/regfile.hh +++ b/src/arch/mips/regfile/regfile.hh @@ -104,10 +104,6 @@ namespace MipsISA void unserialize(EventManager *em, Checkpoint *cp, const std::string §ion); - void changeContext(RegContextParam param, RegContextVal val) - { - } - }; } // namespace MipsISA diff --git a/src/arch/mips/types.hh b/src/arch/mips/types.hh index 4208cb2d8..b459d9e14 100644 --- a/src/arch/mips/types.hh +++ b/src/arch/mips/types.hh @@ -60,9 +60,6 @@ namespace MipsISA MiscReg ctrlreg; } AnyReg; - typedef int RegContextParam; - typedef int RegContextVal; - //used in FP convert & round function enum ConvertType{ SINGLE_TO_DOUBLE, diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc index d66cefa7a..b0c5dbda9 100644 --- a/src/arch/sparc/miscregfile.cc +++ b/src/arch/sparc/miscregfile.cc @@ -551,11 +551,8 @@ void MiscRegFile::setReg(int miscReg, new_val = val >= NWindows ? NWindows - 1 : val; if (val >= NWindows) new_val = NWindows - 1; - - tc->changeRegFileContext(CONTEXT_CWP, new_val); break; case MISCREG_GL: - tc->changeRegFileContext(CONTEXT_GLOBALS, val); break; case MISCREG_PIL: case MISCREG_SOFTINT: diff --git a/src/arch/sparc/regfile.cc b/src/arch/sparc/regfile.cc index 8815b094c..f390be508 100644 --- a/src/arch/sparc/regfile.cc +++ b/src/arch/sparc/regfile.cc @@ -241,21 +241,6 @@ RegFile::unserialize(EventManager *em, Checkpoint *cp, const string §ion) UNSERIALIZE_SCALAR(nnpc); } -void RegFile::changeContext(RegContextParam param, RegContextVal val) -{ - switch(param) - { - case CONTEXT_CWP: - intRegFile.setCWP(val); - break; - case CONTEXT_GLOBALS: - intRegFile.setGlobals(val); - break; - default: - panic("Tried to set illegal context parameter in the SPARC regfile.\n"); - } -} - void SparcISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest) { diff --git a/src/arch/sparc/regfile.hh b/src/arch/sparc/regfile.hh index da7e022e9..dd4e1f684 100644 --- a/src/arch/sparc/regfile.hh +++ b/src/arch/sparc/regfile.hh @@ -117,8 +117,6 @@ namespace SparcISA const std::string §ion); public: - - void changeContext(RegContextParam param, RegContextVal val); }; int flattenIntIndex(ThreadContext * tc, int reg); diff --git a/src/arch/sparc/types.hh b/src/arch/sparc/types.hh index d19e2a99f..dd369cc26 100644 --- a/src/arch/sparc/types.hh +++ b/src/arch/sparc/types.hh @@ -51,14 +51,6 @@ namespace SparcISA MiscReg ctrlreg; } AnyReg; - enum RegContextParam - { - CONTEXT_CWP, - CONTEXT_GLOBALS - }; - - typedef int RegContextVal; - typedef uint16_t RegIndex; struct CoreSpecific { diff --git a/src/arch/x86/regfile.cc b/src/arch/x86/regfile.cc index 78fde7474..7d01c4bb4 100644 --- a/src/arch/x86/regfile.cc +++ b/src/arch/x86/regfile.cc @@ -248,11 +248,6 @@ RegFile::unserialize(EventManager *em, Checkpoint *cp, const string §ion) UNSERIALIZE_SCALAR(nextRip); } -void RegFile::changeContext(RegContextParam param, RegContextVal val) -{ - panic("changeContext not implemented for x86!\n"); -} - void X86ISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest) { panic("copyMiscRegs not implemented for x86!\n"); diff --git a/src/arch/x86/regfile.hh b/src/arch/x86/regfile.hh index 3c2387346..75c0290d3 100644 --- a/src/arch/x86/regfile.hh +++ b/src/arch/x86/regfile.hh @@ -145,8 +145,6 @@ namespace X86ISA const std::string §ion); public: - - void changeContext(RegContextParam param, RegContextVal val); }; int flattenIntIndex(ThreadContext * tc, int reg); diff --git a/src/arch/x86/types.hh b/src/arch/x86/types.hh index 90df38d13..29420352b 100644 --- a/src/arch/x86/types.hh +++ b/src/arch/x86/types.hh @@ -246,17 +246,6 @@ namespace X86ISA MiscReg ctrlReg; } AnyReg; - //XXX This is very hypothetical. X87 instructions would need to - //change their "context" constantly. It's also not clear how - //this would be handled as far as out of order execution. - //Maybe x87 instructions are in order? - enum RegContextParam - { - CONTEXT_X87_TOP - }; - - typedef int RegContextVal; - typedef uint16_t RegIndex; struct CoreSpecific { diff --git a/src/cpu/checker/thread_context.hh b/src/cpu/checker/thread_context.hh index 4ede74c64..75ac959db 100644 --- a/src/cpu/checker/thread_context.hh +++ b/src/cpu/checker/thread_context.hh @@ -294,12 +294,6 @@ class CheckerThreadContext : public ThreadContext Counter readFuncExeInst() { return actualTC->readFuncExeInst(); } #endif - void changeRegFileContext(TheISA::RegContextParam param, - TheISA::RegContextVal val) - { - actualTC->changeRegFileContext(param, val); - checkerTC->changeRegFileContext(param, val); - } }; #endif // __CPU_CHECKER_EXEC_CONTEXT_HH__ diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index d92f85317..c529b002b 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -281,15 +281,6 @@ class O3ThreadContext : public ThreadContext this->cpu->setNextNPC(val, this->thread->readTid()); } - virtual void changeRegFileContext(TheISA::RegContextParam param, - TheISA::RegContextVal val) - { -#if THE_ISA != SPARC_ISA - panic("changeRegFileContext not implemented."); -#endif - } - - /** This function exits the thread context in the CPU and returns * 1 if the CPU has no more active threads (meaning it's OK to exit); * Used in syscall-emulation mode when a thread executes the 'exit' diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index aeafb603a..ee5e9e668 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -271,9 +271,6 @@ class OzoneCPU : public BaseCPU void setFuncExeInst(Counter new_val) { thread->funcExeInst = new_val; } #endif - void changeRegFileContext(TheISA::RegContextParam param, - TheISA::RegContextVal val) - { panic("Not supported on Alpha!"); } }; // Ozone specific thread context diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index 69d7b2548..d26e984a3 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -405,12 +405,6 @@ class SimpleThread : public ThreadState process->syscall(callnum, tc); } #endif - - void changeRegFileContext(TheISA::RegContextParam param, - TheISA::RegContextVal val) - { - regs.changeContext(param, val); - } }; diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index 9dffbd8c6..2b9f41b70 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -272,9 +272,6 @@ class ThreadContext virtual int exit() { return 1; }; #endif - virtual void changeRegFileContext(TheISA::RegContextParam param, - TheISA::RegContextVal val) = 0; - /** function to compare two thread contexts (for debugging) */ static void compare(ThreadContext *one, ThreadContext *two); }; @@ -467,12 +464,6 @@ class ProxyThreadContext : public ThreadContext Counter readFuncExeInst() { return actualTC->readFuncExeInst(); } #endif - - void changeRegFileContext(TheISA::RegContextParam param, - TheISA::RegContextVal val) - { - actualTC->changeRegFileContext(param, val); - } }; #endif -- cgit v1.2.3 From 0756dbb37a432b895b019e49862fcd7f42e1bd00 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 19:32:06 -0700 Subject: X86: Don't fetch in the simple CPU if you're in the ROM. --- src/cpu/simple/atomic.cc | 40 +++++++++++++++++++--------------- src/cpu/simple/timing.cc | 56 +++++++++++++++++++++++++++++------------------- 2 files changed, 57 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 154a66162..878f69f0c 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -718,31 +718,37 @@ AtomicSimpleCPU::tick() checkPcEventQueue(); - Fault fault = setupFetchRequest(&ifetch_req); + Fault fault = NoFault; + + bool fromRom = isRomMicroPC(thread->readMicroPC()); + if (!fromRom) + fault = setupFetchRequest(&ifetch_req); if (fault == NoFault) { Tick icache_latency = 0; bool icache_access = false; dcache_access = false; // assume no dcache access - //Fetch more instruction memory if necessary - //if(predecoder.needMoreBytes()) - //{ - icache_access = true; - Packet ifetch_pkt = Packet(&ifetch_req, MemCmd::ReadReq, - Packet::Broadcast); - ifetch_pkt.dataStatic(&inst); - - if (hasPhysMemPort && ifetch_pkt.getAddr() == physMemAddr) - icache_latency = physmemPort.sendAtomic(&ifetch_pkt); - else - icache_latency = icachePort.sendAtomic(&ifetch_pkt); + if (!fromRom) { + //Fetch more instruction memory if necessary + //if(predecoder.needMoreBytes()) + //{ + icache_access = true; + Packet ifetch_pkt = Packet(&ifetch_req, MemCmd::ReadReq, + Packet::Broadcast); + ifetch_pkt.dataStatic(&inst); + + if (hasPhysMemPort && ifetch_pkt.getAddr() == physMemAddr) + icache_latency = physmemPort.sendAtomic(&ifetch_pkt); + else + icache_latency = icachePort.sendAtomic(&ifetch_pkt); - assert(!ifetch_pkt.isError()); + assert(!ifetch_pkt.isError()); - // ifetch_req is initialized to read the instruction directly - // into the CPU object's inst field. - //} + // ifetch_req is initialized to read the instruction directly + // into the CPU object's inst field. + //} + } preExecute(); diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index c4635d6a3..0cda9a0a3 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -531,28 +531,35 @@ TimingSimpleCPU::fetch() checkPcEventQueue(); - Request *ifetch_req = new Request(); - ifetch_req->setThreadContext(cpuId, /* thread ID */ 0); - Fault fault = setupFetchRequest(ifetch_req); + bool fromRom = isRomMicroPC(thread->readMicroPC()); - ifetch_pkt = new Packet(ifetch_req, MemCmd::ReadReq, Packet::Broadcast); - ifetch_pkt->dataStatic(&inst); + if (!fromRom) { + Request *ifetch_req = new Request(); + ifetch_req->setThreadContext(cpuId, /* thread ID */ 0); + Fault fault = setupFetchRequest(ifetch_req); - if (fault == NoFault) { - if (!icachePort.sendTiming(ifetch_pkt)) { - // Need to wait for retry - _status = IcacheRetry; + ifetch_pkt = new Packet(ifetch_req, MemCmd::ReadReq, Packet::Broadcast); + ifetch_pkt->dataStatic(&inst); + + if (fault == NoFault) { + if (!icachePort.sendTiming(ifetch_pkt)) { + // Need to wait for retry + _status = IcacheRetry; + } else { + // Need to wait for cache to respond + _status = IcacheWaitResponse; + // ownership of packet transferred to memory system + ifetch_pkt = NULL; + } } else { - // Need to wait for cache to respond - _status = IcacheWaitResponse; - // ownership of packet transferred to memory system - ifetch_pkt = NULL; + delete ifetch_req; + delete ifetch_pkt; + // fetch fault: advance directly to next instruction (fault handler) + advanceInst(fault); } } else { - delete ifetch_req; - delete ifetch_pkt; - // fetch fault: advance directly to next instruction (fault handler) - advanceInst(fault); + _status = IcacheWaitResponse; + completeIfetch(NULL); } numCycles += tickToCycles(curTick - previousTick); @@ -581,7 +588,8 @@ TimingSimpleCPU::completeIfetch(PacketPtr pkt) // received a response from the icache: execute the received // instruction - assert(!pkt->isError()); + + assert(!pkt || !pkt->isError()); assert(_status == IcacheWaitResponse); _status = Running; @@ -590,8 +598,10 @@ TimingSimpleCPU::completeIfetch(PacketPtr pkt) previousTick = curTick; if (getState() == SimObject::Draining) { - delete pkt->req; - delete pkt; + if (pkt) { + delete pkt->req; + delete pkt; + } completeDrain(); return; @@ -658,8 +668,10 @@ TimingSimpleCPU::completeIfetch(PacketPtr pkt) advanceInst(fault); } - delete pkt->req; - delete pkt; + if (pkt) { + delete pkt->req; + delete pkt; + } } void -- cgit v1.2.3 From 223fc41c076fe53d21bc3e8b951baff7e01468fa Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 20:07:46 -0700 Subject: X86: Fix the rdbase microop --- src/arch/x86/isa/microops/regop.isa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index d0d7062ff..dfb0abeae 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -1001,7 +1001,7 @@ let {{ class Rdbase(SegOp): code = ''' - DestReg = SegBaseDest; + DestReg = SegBaseSrc1; ''' class Rdlimit(SegOp): -- cgit v1.2.3 From e9158d763a34d96147d62d08f6ccc4e8ba3308e5 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 20:17:38 -0700 Subject: X86: Let the microassembler know about the microcode only H segment. --- src/arch/x86/isa/microasm.isa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa index d7b008145..75e1dc524 100644 --- a/src/arch/x86/isa/microasm.isa +++ b/src/arch/x86/isa/microasm.isa @@ -81,7 +81,7 @@ let {{ for num in range(7): assembler.symbols["ufp%d" % num] = "FLOATREG_MICROFP(%d)" % num # Add in symbols for the segment descriptor registers - for letter in ("C", "D", "E", "F", "G", "S"): + for letter in ("C", "D", "E", "F", "G", "H", "S"): assembler.symbols["%ss" % letter.lower()] = "SEGMENT_REG_%sS" % letter # Add in symbols for the various checks of segment selectors. -- cgit v1.2.3 From 9e1fe2050ac55c28b6601770014193321a4013d0 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 20:25:06 -0700 Subject: X86: Let segment manipulation microops be conditional. --- src/arch/x86/isa/microops/regop.isa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index dfb0abeae..4f93fad80 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -978,7 +978,7 @@ let {{ ''' # Microops for manipulating segmentation registers - class SegOp(RegOp): + class SegOp(CondRegOp): abstract = True def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): super(SegOp, self).__init__(dest, \ -- cgit v1.2.3 From 15f5bb3055b70a43ba8b504b1453f51b2a6e1ee3 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 20:29:52 -0700 Subject: X86: Fix chks checking the submode for stack segments. --- src/arch/x86/isa/microops/regop.isa | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 4f93fad80..b7883b2e2 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -1048,7 +1048,8 @@ let {{ return new StackFault; } } else { - if ((m5reg.mode != SixtyFourBitMode || m5reg.cpl == 3) || + if ((m5reg.submode != SixtyFourBitMode || + m5reg.cpl == 3) || !(desc.s == 1 && desc.type.codeOrData == 0 && desc.type.w) || (desc.dpl != m5reg.cpl) || -- cgit v1.2.3 From 30feb90c1cba922a7dac38204900e29b4788b935 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 20:33:37 -0700 Subject: X86: Add a check type for interrupt gates. --- src/arch/x86/isa/microasm.isa | 2 +- src/arch/x86/isa/microops/regop.isa | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa index 75e1dc524..29ec6dc94 100644 --- a/src/arch/x86/isa/microasm.isa +++ b/src/arch/x86/isa/microasm.isa @@ -85,7 +85,7 @@ let {{ assembler.symbols["%ss" % letter.lower()] = "SEGMENT_REG_%sS" % letter # Add in symbols for the various checks of segment selectors. - for check in ("NoCheck", "CSCheck", "CallGateCheck", + for check in ("NoCheck", "CSCheck", "CallGateCheck", "IntGateCheck", "SSCheck", "IretCheck", "IntCSCheck"): assembler.symbols[check] = "Seg%s" % check diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index b7883b2e2..0d019729f 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -233,7 +233,7 @@ output header {{ uint64_t "ient, uint64_t &remainder); enum SegmentSelectorCheck { - SegNoCheck, SegCSCheck, SegCallGateCheck, + SegNoCheck, SegCSCheck, SegCallGateCheck, SegIntGateCheck, SegSSCheck, SegIretCheck, SegIntCSCheck }; }}; @@ -1041,6 +1041,11 @@ let {{ panic("CS checks for far calls/jumps through call gates" "not implemented.\\n"); break; + case SegIntGateCheck: + if (desc.dpl < m5reg.cpl) { + return new GeneralProtection((uint16_t)selector); + } + break; case SegSSCheck: if (selector.si || selector.ti) { if (!desc.p) { -- cgit v1.2.3 From 6b46e5204d52c8e46b48541d5112f7e9a1cadc43 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 20:38:22 -0700 Subject: X86: Implement the chks check of interrupt gate target code segments. --- src/arch/x86/isa/microops/regop.isa | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 0d019729f..ba996060c 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -1076,8 +1076,14 @@ let {{ break; } case SegIntCSCheck: - panic("CS selector checks for interrupts and exceptions" - "not implemented.\\n"); + if (m5reg.mode == LongMode) { + if (desc.l != 1 || desc.d != 0) { + return new GeneralProtection(selector); + } + } else { + panic("Interrupt CS checks not implemented " + "in legacy mode.\\n"); + } break; default: panic("Undefined segment check type.\\n"); -- cgit v1.2.3 From 6074b1abf2e235f9a5d3ad78879a805ca335dc0e Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 20:44:11 -0700 Subject: X86: Implement local labels for the ROM that actually refer into the ROM. --- src/arch/x86/isa/microasm.isa | 5 +++++ src/arch/x86/isa/rom.isa | 3 +++ 2 files changed, 8 insertions(+) (limited to 'src') diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa index 29ec6dc94..81aa1dafe 100644 --- a/src/arch/x86/isa/microasm.isa +++ b/src/arch/x86/isa/microasm.isa @@ -188,6 +188,11 @@ let {{ assembler.symbols["rom_label"] = rom_labeler + def rom_local_labeler(labelStr): + return "romMicroPC(RomLabels::label_%s)" % labelStr + + assembler.symbols["rom_local_label"] = rom_local_labeler + def stack_index(index): return "(NUM_FLOATREGS + (((%s) + 8) %% 8))" % index diff --git a/src/arch/x86/isa/rom.isa b/src/arch/x86/isa/rom.isa index 59b280056..7d3eb8670 100644 --- a/src/arch/x86/isa/rom.isa +++ b/src/arch/x86/isa/rom.isa @@ -55,6 +55,9 @@ let {{ def getDeclaration(self): declareLabels = "namespace RomLabels {\n" + for (label, microop) in self.labels.items(): + declareLabels += "const static uint64_t label_%s = %d;\n" \ + % (label, microop.micropc) for (label, microop) in self.externs.items(): declareLabels += \ "const static MicroPC extern_label_%s = %d;\n" \ -- cgit v1.2.3 From 989fa4fc0fa95906f2986deec99cfb8e6e49cc1a Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 20:48:24 -0700 Subject: X86: Make the MicroPC type 16 bit. --- src/cpu/static_inst.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index c9eb6ff24..032a304ad 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -72,7 +72,7 @@ namespace Trace { class InstRecord; } -typedef uint32_t MicroPC; +typedef uint16_t MicroPC; static const MicroPC MicroPCRomBit = 1 << (sizeof(MicroPC) * 8 - 1); -- cgit v1.2.3 From 961b40cdb537382f6463479e3707e7d04a223f38 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 22:16:53 -0700 Subject: X86: Implement an wrdh microop which loads bases/offsets from 16 byte descriptors. --- src/arch/x86/isa/microops/regop.isa | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'src') diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index ba996060c..d7d1e3063 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -236,6 +236,15 @@ output header {{ SegNoCheck, SegCSCheck, SegCallGateCheck, SegIntGateCheck, SegSSCheck, SegIretCheck, SegIntCSCheck }; + + enum LongModeDescriptorType { + LDT64 = 2, + AvailableTSS64 = 9, + BusyTSS64 = 0xb, + CallGate64 = 0xc, + IntGate64 = 0xe, + TrapGate64 = 0xf + }; }}; output decoder {{ @@ -1098,7 +1107,26 @@ let {{ class Wrdh(RegOp): code = ''' + SegDescriptor desc = SrcReg1; + uint64_t target = bits(SrcReg2, 31, 0) << 32; + switch(desc.type) { + case LDT64: + case AvailableTSS64: + case BusyTSS64: + replaceBits(target, 23, 0, desc.baseLow); + replaceBits(target, 31, 24, desc.baseHigh); + break; + case CallGate64: + case IntGate64: + case TrapGate64: + replaceBits(target, 15, 0, bits(desc, 15, 0)); + replaceBits(target, 31, 16, bits(desc, 63, 48)); + break; + default: + panic("Wrdh used with wrong descriptor type!\\n"); + } + DestReg = target; ''' class Wrtsc(WrRegOp): -- cgit v1.2.3 From f813a4be4954bfedb95747b4635b38b1a13ee8a6 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 22:24:06 -0700 Subject: X86: Make sure register microops set fault rather than returning one. --- src/arch/x86/isa/microops/regop.isa | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index d7d1e3063..439116145 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -1052,14 +1052,14 @@ let {{ break; case SegIntGateCheck: if (desc.dpl < m5reg.cpl) { - return new GeneralProtection((uint16_t)selector); + fault = new GeneralProtection((uint16_t)selector); } break; case SegSSCheck: if (selector.si || selector.ti) { if (!desc.p) { //FIXME This needs to also push the selector. - return new StackFault; + fault = new StackFault; } } else { if ((m5reg.submode != SixtyFourBitMode || @@ -1068,7 +1068,7 @@ let {{ desc.type.codeOrData == 0 && desc.type.w) || (desc.dpl != m5reg.cpl) || (selector.rpl != m5reg.cpl)) { - return new GeneralProtection(psrc1 & 0xFFFF); + fault = new GeneralProtection(psrc1 & 0xFFFF); } } break; @@ -1078,16 +1078,17 @@ let {{ (selector.rpl < m5reg.cpl) || !(desc.s == 1 && desc.type.codeOrData == 1) || (!desc.type.c && desc.dpl != selector.rpl) || - (desc.type.c && desc.dpl > selector.rpl)) - return new GeneralProtection(psrc1 & 0xFFFF); - if (!desc.p) - return new SegmentNotPresent; + (desc.type.c && desc.dpl > selector.rpl)) { + fault = new GeneralProtection(psrc1 & 0xFFFF); + } else if (!desc.p) { + fault = new SegmentNotPresent; + } break; } case SegIntCSCheck: if (m5reg.mode == LongMode) { if (desc.l != 1 || desc.d != 0) { - return new GeneralProtection(selector); + fault = new GeneralProtection(selector); } } else { panic("Interrupt CS checks not implemented " -- cgit v1.2.3 From 4c19c56a7706c7382f46c4f8c7dd10c2b2c8746a Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 22:42:03 -0700 Subject: X86: Implement entering an interrupt in microcode. --- src/arch/x86/SConscript | 1 + src/arch/x86/isa/insts/__init__.py | 3 +- src/arch/x86/isa/insts/romutil.py | 201 +++++++++++++++++++++++++++++++++++++ 3 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 src/arch/x86/isa/insts/romutil.py (limited to 'src') diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript index cd2445c7e..c2081156d 100644 --- a/src/arch/x86/SConscript +++ b/src/arch/x86/SConscript @@ -185,6 +185,7 @@ if env['TARGET_ISA'] == 'x86': 'general_purpose/string/scan_string.py', 'general_purpose/string/store_string.py', 'general_purpose/system_calls.py', + 'romutil.py', 'system/__init__.py', 'system/halt.py', 'system/invlpg.py', diff --git a/src/arch/x86/isa/insts/__init__.py b/src/arch/x86/isa/insts/__init__.py index 0ef617a87..d7a8bde19 100644 --- a/src/arch/x86/isa/insts/__init__.py +++ b/src/arch/x86/isa/insts/__init__.py @@ -53,7 +53,8 @@ # # Authors: Gabe Black -categories = ["general_purpose", +categories = ["romutil", + "general_purpose", "simd128", "simd64", "system", diff --git a/src/arch/x86/isa/insts/romutil.py b/src/arch/x86/isa/insts/romutil.py new file mode 100644 index 000000000..9645ee85d --- /dev/null +++ b/src/arch/x86/isa/insts/romutil.py @@ -0,0 +1,201 @@ +# Copyright (c) 2008 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +microcode = ''' +def rom +{ + # This vectors the CPU into an interrupt handler in long mode. + # On entry, t1 is set to the vector of the interrupt and t7 is the current + # ip. We need that because rdip returns the next ip. + extern longModeInterrupt: + + # + # Get the 64 bit interrupt or trap gate descriptor from the IDT + # + + # Load the gate descriptor from the IDT + slli t4, t1, 4, dataSize=8 + ld t2, idtr, [1, t0, t4], 8, dataSize=8, addressSize=8 + ld t4, idtr, [1, t0, t4], dataSize=8, addressSize=8 + + # Check permissions + chks t1, t4, IntGateCheck + + mov t1, t1, t4, dataSize=8 + + # Check that it's the right type + srli t4, t1, 40, dataSize=8 + andi t4, t4, 0xe, dataSize=8 + xori t4, t4, 0xe, flags=(EZF,), dataSize=8 + fault "new GeneralProtection(0)", flags=(nCEZF,) + + + # + # Get the target CS descriptor using the selector in the gate + # descriptor. + # + srli t4, t1, 16, dataSize=8 + andi t5, t4, 0xF8, dataSize=8 + andi t0, t4, 0x4, flags=(EZF,), dataSize=2 + br rom_local_label("globalDescriptor"), flags=(CEZF,) + ld t3, tsl, [1, t0, t5], dataSize=8, addressSize=8 + br rom_local_label("processDescriptor") +globalDescriptor: + ld t3, tsg, [1, t0, t5], dataSize=8, addressSize=8 +processDescriptor: + chks t4, t3, IntCSCheck, dataSize=8 + wrdl hs, t3, t4, dataSize=8 + + # Check that the target offset is in canonical form + wrdh t4, t1, t2, dataSize=8 + srli t4, t4, 47, dataSize=8 + addi t4, t4, 1, dataSize=8 + srli t4, t4, 1, dataSize=8 + or t4, t4, t4, flags=(EZF,), dataSize=2 + fault "new GeneralProtection(0)", flags=(nCEZF,) + + + # + # Figure out where the stack should be + # + + # Record what we might set the stack selector to. + rdsel t6, ss + wrsel hs, t6 + + # Check if we're changing privelege level. At this point we can assume + # we're going to a DPL that's less than or equal to the CPL. + rdattr t4, hs, dataSize=8 + srli t4, t4, 3, dataSize=8 + andi t4, t4, 3, dataSize=8 + rdattr t5, cs, dataSize=8 + srli t5, t5, 3, dataSize=8 + sub t5, t5, t4, dataSize=8 + andi t0, t5, 0x3, flags=(EZF,), dataSize=8 + # We're going to change priviledge, so zero out the stack selector. We + # need to let the IST have priority so we don't branch yet. + limm t4, 0 + wrsel hs, t4, flags=(nCEZF,) + + # Check the IST field of the gate descriptor + srli t4, t1, 32, dataSize=8 + andi t4, t4, 0x7, dataSize=8 + subi t0, t4, 1, flags=(ECF,), dataSize=8 + br rom_local_label("istStackSwitch"), flags=(nCECF,) + br rom_local_label("cplStackSwitch"), flags=(nCEZF,) + + # If we're here, it's because the stack isn't being switched. + # Set t6 to the new rsp. + subi t6, rsp, 40, dataSize=8 + + # Align the stack + andi t6, t6, 0xF0, dataSize=1 + + # Check that we can access everything we need to on the stack + ldst t0, hs, [1, t0, t6], dataSize=8, addressSize=8 + ldst t0, hs, [1, t0, t6], 32, dataSize=8, addressSize=8 + br rom_local_label("stackSwitched") + +istStackSwitch: + panic "IST based stack switching isn't implemented" + br rom_local_label("stackSwitched") + +cplStackSwitch: + panic "CPL change initiated stack switching isn't implemented" + +stackSwitched: + + + ## + ## Point of no return. + ## We're now going to irrevocably modify visible state. + ## Anything bad that's going to happen should have happened by now. + ## + + + # + # Build up the interrupt stack frame + # + + # Write out the contents of memory + st t7, hs, [1, t0, t6], dataSize=8 + limm t5, 0, dataSize=8 + rdsel t5, cs, dataSize=2 + st t5, hs, [1, t0, t6], 8, dataSize=8 + rflags t4, dataSize=8 + st t4, hs, [1, t0, t6], 16, dataSize=8 + st rsp, hs, [1, t0, t6], 24, dataSize=8 + rdsel t5, ss, dataSize=2 + st t5, hs, [1, t0, t6], 32, dataSize=8 + + # Set the stack segment + mov rsp, rsp, t6, dataSize=8 + rdsel t7, hs, dataSize=2 + wrsel ss, t7, dataSize=2 + + # + # Set up the target code segment + # + srli t5, t1, 16, dataSize=8 + andi t5, t5, 0xFF, dataSize=8 + wrdl cs, t3, t5, dataSize=8 + wrsel cs, t5, dataSize=2 + wrdh t7, t1, t2, dataSize=8 + wrip t0, t7, dataSize=8 + + # + # Adjust rflags which is still in t4 from above + # + + # Set IF to the lowest bit of the original gate type. + # The type field of the original gate starts at bit 40. + + # Set the TF, NT, and RF bits. We'll flip them at the end. + limm t6, (1 << 8) | (1 << 14) | (1 << 16) + or t4, t4, t6 + srli t5, t1, 40, dataSize=8 + srli t7, t4, 9, dataSize=8 + xor t5, t7, t5, dataSize=8 + andi t5, t5, 1, dataSize=8 + slli t5, t5, 9, dataSize=8 + or t6, t5, t6, dataSize=8 + + # Put the results into rflags + wrflags t6, t4 + + eret +}; + +def rom +{ + # This vectors the CPU into an interrupt handler in legacy mode. + extern legacyModeInterrupt: + panic "Legacy mode interrupts not implemented (in microcode)" + eret +}; +''' -- cgit v1.2.3 From 9e8e2f9ec6ae4ea3be8f5280a1ca4cb734e3e068 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 22:42:10 -0700 Subject: X86: Make the x86 interrupt fault kick off the interrupt microcode. --- src/arch/x86/faults.cc | 14 +++++++++++++- src/arch/x86/faults.hh | 19 +++++++++---------- 2 files changed, 22 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/arch/x86/faults.cc b/src/arch/x86/faults.cc index 1c94a1251..18680899e 100644 --- a/src/arch/x86/faults.cc +++ b/src/arch/x86/faults.cc @@ -85,6 +85,7 @@ * Authors: Gabe Black */ +#include "arch/x86/decoder.hh" #include "arch/x86/faults.hh" #include "base/trace.hh" #include "config/full_system.hh" @@ -112,7 +113,18 @@ namespace X86ISA void X86Interrupt::invoke(ThreadContext * tc) { - panic("X86 faults are not implemented!"); + using namespace X86ISAInst::RomLabels; + HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); + MicroPC entry; + if (m5reg.mode == LongMode) { + entry = extern_label_longModeInterrupt; + } else { + entry = extern_label_legacyModeInterrupt; + } + tc->setIntReg(INTREG_MICRO(1), vector); + tc->setIntReg(INTREG_MICRO(7), tc->readPC()); + tc->setMicroPC(romMicroPC(entry)); + tc->setNextMicroPC(romMicroPC(entry) + 1); } void FakeITLBFault::invoke(ThreadContext * tc) diff --git a/src/arch/x86/faults.hh b/src/arch/x86/faults.hh index b15ad15d1..b7948a638 100644 --- a/src/arch/x86/faults.hh +++ b/src/arch/x86/faults.hh @@ -137,9 +137,10 @@ namespace X86ISA class X86Interrupt : public X86FaultBase { protected: - X86Interrupt(const char * name, const char * mnem, + uint8_t vector; + X86Interrupt(const char * name, const char * mnem, uint8_t _vector, uint64_t _errorCode = 0) : - X86FaultBase(name, mnem, _errorCode) + X86FaultBase(name, mnem, _errorCode), vector(_vector) {} #if FULL_SYSTEM @@ -215,10 +216,9 @@ namespace X86ISA class NonMaskableInterrupt : public X86Interrupt { - uint8_t vector; public: NonMaskableInterrupt(uint8_t _vector) : - X86Interrupt("Non Maskable Interrupt", "#NMI"), vector(_vector) + X86Interrupt("Non Maskable Interrupt", "#NMI", _vector) {} }; @@ -352,10 +352,9 @@ namespace X86ISA class ExternalInterrupt : public X86Interrupt { - uint8_t vector; public: ExternalInterrupt(uint8_t _vector) : - X86Interrupt("External Interrupt", "#INTR"), vector(_vector) + X86Interrupt("External Interrupt", "#INTR", _vector) {} }; @@ -363,7 +362,7 @@ namespace X86ISA { public: SystemManagementInterrupt() : - X86Interrupt("System Management Interrupt", "#SMI") + X86Interrupt("System Management Interrupt", "#SMI", 0) {} }; @@ -372,15 +371,15 @@ namespace X86ISA uint8_t vector; public: InitInterrupt(uint8_t _vector) : - X86Interrupt("INIT Interrupt", "#INIT"), vector(_vector) + X86Interrupt("INIT Interrupt", "#INIT", _vector) {} }; class SoftwareInterrupt : public X86Interrupt { public: - SoftwareInterrupt() : - X86Interrupt("Software Interrupt", "INTn") + SoftwareInterrupt(uint8_t _vector) : + X86Interrupt("Software Interrupt", "INTn", _vector) {} }; -- cgit v1.2.3 From a2e0d539d89643ce5243be9b8a0be4c3bcee7520 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 22:55:55 -0700 Subject: X86: Add wrval/rdval microops for reading significant miscregs. --- src/arch/x86/isa/microasm.isa | 5 +++++ src/arch/x86/isa/microops/regop.isa | 16 ++++++++++++++++ src/arch/x86/isa/operands.isa | 6 ++++-- 3 files changed, 25 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa index 81aa1dafe..f9e0a2fa8 100644 --- a/src/arch/x86/isa/microasm.isa +++ b/src/arch/x86/isa/microasm.isa @@ -159,6 +159,11 @@ let {{ assembler.symbols["CTrue"] = "ConditionTests::True" assembler.symbols["CFalse"] = "ConditionTests::False" + for reg in ('sysenter_cs', 'sysenter_esp', 'sysenter_eip', + 'star', 'lstar', 'cstar', 'sf_mask', + 'kernel_gs_base'): + assembler.symbols[reg] = "MISCREG_%s" % reg.upper() + # Code literal which forces a default 64 bit operand size in 64 bit mode. assembler.symbols["oszIn64Override"] = ''' if (machInst.mode.submode == SixtyFourBitMode && diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 439116145..944d5e9ec 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -1028,6 +1028,22 @@ let {{ DestReg = SegSelSrc1; ''' + class Rdval(RegOp): + def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): + super(Rdval, self).__init__(dest, \ + src1, "NUM_INTREGS", flags, dataSize) + code = ''' + DestReg = MiscRegSrc1; + ''' + + class Wrval(RegOp): + def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): + super(Wrval, self).__init__(dest, \ + src1, "NUM_INTREGS", flags, dataSize) + code = ''' + MiscRegDest = SrcReg1; + ''' + class Chks(RegOp): def __init__(self, dest, src1, src2=0, flags=None, dataSize="env.dataSize"): diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa index 8bb7c5bb1..343b37d41 100644 --- a/src/arch/x86/isa/operands.isa +++ b/src/arch/x86/isa/operands.isa @@ -153,7 +153,9 @@ def operands {{ 'GDTRLimit': ('ControlReg', 'uqw', 'MISCREG_TSG_LIMIT', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 206), 'CSBase': ('ControlReg', 'udw', 'MISCREG_CS_EFF_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 207), 'CSAttr': ('ControlReg', 'udw', 'MISCREG_CS_ATTR', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 208), - 'TscOp': ('ControlReg', 'udw', 'MISCREG_TSC', (None, None, ['IsSerializeAfter', 'IsSerializing', 'IsNonSpeculative']), 209), - 'M5Reg': ('ControlReg', 'udw', 'MISCREG_M5_REG', (None, None, None), 210), + 'MiscRegDest': ('ControlReg', 'uqw', 'dest', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 209), + 'MiscRegSrc1': ('ControlReg', 'uqw', 'src1', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 210), + 'TscOp': ('ControlReg', 'udw', 'MISCREG_TSC', (None, None, ['IsSerializeAfter', 'IsSerializing', 'IsNonSpeculative']), 211), + 'M5Reg': ('ControlReg', 'udw', 'MISCREG_M5_REG', (None, None, None), 212), 'Mem': ('Mem', 'uqw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 300) }}; -- cgit v1.2.3 From 564eda827bc9ebe3bacfb9a44838e4abc1deb61b Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 23:00:07 -0700 Subject: X86: Implement the swapgs instruction. --- src/arch/x86/isa/decoder/two_byte_opcodes.isa | 2 +- src/arch/x86/isa/insts/system/segmentation.py | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index bceb0595e..b8013165e 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -128,7 +128,7 @@ 0x4: smsw_Rv(); 0x6: lmsw_Rv(); 0x7: decode MODRM_RM { - 0x0: swapgs(); + 0x0: Inst::SWAPGS(); 0x1: rdtscp(); default: Inst::UD2(); } diff --git a/src/arch/x86/isa/insts/system/segmentation.py b/src/arch/x86/isa/insts/system/segmentation.py index 97846f79c..49d8eb110 100644 --- a/src/arch/x86/isa/insts/system/segmentation.py +++ b/src/arch/x86/isa/insts/system/segmentation.py @@ -167,4 +167,12 @@ def macroop LIDT_16_P wrbase idtr, t2 wrlimit idtr, t1 }; + +def macroop SWAPGS +{ + rdval t1, kernel_gs_base, dataSize=8 + rdbase t2, gs, dataSize=8 + wrbase gs, t1, dataSize=8 + wrval kernel_gs_base, t2, dataSize=8 +}; ''' -- cgit v1.2.3 From 349a155b6e38c128f155b1c83d9f11e73f6e8673 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 23:00:28 -0700 Subject: X86: Panic when an unimplemented fault is invoked, rather than spinning forever --- src/arch/x86/faults.hh | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/arch/x86/faults.hh b/src/arch/x86/faults.hh index b7948a638..3bcacffe2 100644 --- a/src/arch/x86/faults.hh +++ b/src/arch/x86/faults.hh @@ -91,6 +91,12 @@ namespace X86ISA { return mnem; } + + void + invoke(ThreadContext * tc) + { + panic("Unimplemented fault %s.\n", name()); + } }; // Base class for x86 faults which behave as if the underlying instruction -- cgit v1.2.3 From e3004c579fcd7c3f34dfcbd90169c5aa9218a65b Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 23:05:22 -0700 Subject: X86: Fix the segment setting code in IRET, and make it restore the flags. --- .../general_purpose/control_transfer/interrupts_and_exceptions.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py b/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py index 125866ce5..57bc13698 100644 --- a/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py +++ b/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py @@ -190,8 +190,8 @@ processSSDescriptor: # This actually updates state which is wrong. It should wait until we know # we're not going to fault. Unfortunately, that's hard to do. - wrdl cs, t7, t2 - wrsel cs, t2 + wrdl ss, t7, t2 + wrsel ss, t2 ### ### From this point downwards, we can't fault. We can update user visible state. @@ -224,6 +224,7 @@ skipSegmentSquashing: # Ignore this for now. #RFLAGS.v = temp_RFLAGS + wrflags t0, t3 # VIF,VIP,IOPL only changed if (old_CPL = 0) # IF only changed if (old_CPL <= old_RFLAGS.IOPL) # VM unchanged -- cgit v1.2.3 From 8e664f395965b7ff5945d7665eda28cf5592a10a Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 23:22:58 -0700 Subject: X86: Make the I8259 PIC accept a specific EOI command. --- src/dev/x86/i8259.cc | 42 +++++++++++++++++++++++++++++++----------- src/dev/x86/i8259.hh | 3 +++ 2 files changed, 34 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/dev/x86/i8259.cc b/src/dev/x86/i8259.cc index be0bfbe4d..3b0053ee9 100644 --- a/src/dev/x86/i8259.cc +++ b/src/dev/x86/i8259.cc @@ -107,8 +107,12 @@ X86ISA::I8259::write(PacketPtr pkt) DPRINTF(I8259, "Subcommand: No operation.\n"); break; case 0x3: - DPRINTF(I8259, "Subcommand: Specific EIO."); - DPRINTF(I8259, "Reset In-Service bit %d.\n", bits(val, 2, 0)); + { + int line = bits(val, 2, 0); + DPRINTF(I8259, "Subcommand: Specific EIO on line %d.\n", + line); + handleEOI(line); + } break; case 0x4: DPRINTF(I8259, "Subcommand: Rotate in auto-EOI mode (set).\n"); @@ -205,6 +209,30 @@ X86ISA::I8259::write(PacketPtr pkt) return latency; } +void +X86ISA::I8259::handleEOI(int line) +{ + ISR &= ~(1 << line); + // There may be an interrupt that was waiting which can + // now be sent. + if (IRR) + requestInterrupt(findMsbSet(IRR)); +} + +void +X86ISA::I8259::requestInterrupt(int line) +{ + if (bits(ISR, 7, line) == 0) { + if (output) { + DPRINTF(I8259, "Propogating interrupt.\n"); + output->signalInterrupt(); + } else { + warn("Received interrupt but didn't have " + "anyone to tell about it.\n"); + } + } +} + void X86ISA::I8259::signalInterrupt(int line) { @@ -216,15 +244,7 @@ X86ISA::I8259::signalInterrupt(int line) DPRINTF(I8259, "Interrupt %d was masked.\n", line); } else { IRR |= 1 << line; - if (bits(ISR, 7, line) == 0) { - if (output) { - DPRINTF(I8259, "Propogating interrupt.\n"); - output->signalInterrupt(); - } else { - warn("Received interrupt but didn't have " - "anyone to tell about it.\n"); - } - } + requestInterrupt(line); } } diff --git a/src/dev/x86/i8259.hh b/src/dev/x86/i8259.hh index 371a27874..6f6d3f038 100644 --- a/src/dev/x86/i8259.hh +++ b/src/dev/x86/i8259.hh @@ -73,6 +73,9 @@ class I8259 : public BasicPioDevice, public IntDev bool expectICW4; int initControlWord; + void requestInterrupt(int line); + void handleEOI(int line); + public: typedef I8259Params Params; -- cgit v1.2.3 From fb5bb434a9e8471e2d9e7b2a9fa7f61a2a10b6b2 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 23:25:48 -0700 Subject: X86: Make non-specific EOI commands work. --- src/dev/x86/i8259.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/dev/x86/i8259.cc b/src/dev/x86/i8259.cc index 3b0053ee9..dfaea571b 100644 --- a/src/dev/x86/i8259.cc +++ b/src/dev/x86/i8259.cc @@ -101,7 +101,12 @@ X86ISA::I8259::write(PacketPtr pkt) "Subcommand: Rotate in auto-EOI mode (clear).\n"); break; case 0x1: - DPRINTF(I8259, "Subcommand: Nonspecific EOI.\n"); + { + int line = findMsbSet(ISR); + DPRINTF(I8259, "Subcommand: Nonspecific EOI on line %d.\n", + line); + handleEOI(line); + } break; case 0x2: DPRINTF(I8259, "Subcommand: No operation.\n"); -- cgit v1.2.3 From be6055e0f2fc55de9c4fd08815cdb50e3c4af78d Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 23:27:08 -0700 Subject: X86: Make auto eoi mode work in the I8259 PIC. --- src/dev/x86/i8259.cc | 15 ++++++++++++--- src/dev/x86/i8259.hh | 3 +++ 2 files changed, 15 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/dev/x86/i8259.cc b/src/dev/x86/i8259.cc index dfaea571b..2d460b96d 100644 --- a/src/dev/x86/i8259.cc +++ b/src/dev/x86/i8259.cc @@ -36,7 +36,7 @@ X86ISA::I8259::I8259(Params * p) : BasicPioDevice(p), IntDev(this), latency(p->pio_latency), output(p->output), mode(p->mode), slave(NULL), IRR(0), ISR(0), IMR(0), - readIRR(true), initControlWord(0) + readIRR(true), initControlWord(0), autoEOI(false) { if (output) { I8259 * master; @@ -91,6 +91,9 @@ X86ISA::I8259::write(PacketPtr pkt) DPRINTF(I8259, "%s mode.\n", cascadeMode ? "Cascade" : "Single"); expectICW4 = bits(val, 0); + if (!expectICW4) { + autoEOI = false; + } initControlWord = 1; DPRINTF(I8259, "Expecting %d more bytes.\n", expectICW4 ? 3 : 2); } else if (bits(val, 4, 3) == 0) { @@ -203,8 +206,10 @@ X86ISA::I8259::write(PacketPtr pkt) } else { DPRINTF(I8259, "Unrecognized buffer mode.\n"); } + autoEOI = bits(val, 1); DPRINTF(I8259, "%s End Of Interrupt.\n", - bits(val, 1) ? "Automatic" : "Normal"); + autoEOI ? "Automatic" : "Normal"); + DPRINTF(I8259, "%s mode.\n", bits(val, 0) ? "80x86" : "MCX-80/85"); initControlWord = 0; break; @@ -265,7 +270,11 @@ X86ISA::I8259::getVector() int line = findMsbSet(IRR); IRR &= ~(1 << line); DPRINTF(I8259, "Interrupt %d was accepted.\n", line); - ISR |= 1 << line; + if (autoEOI) { + handleEOI(line); + } else { + ISR |= 1 << line; + } if (slave && bits(cascadeBits, line)) { DPRINTF(I8259, "Interrupt was from slave who will " "provide the vector.\n"); diff --git a/src/dev/x86/i8259.hh b/src/dev/x86/i8259.hh index 6f6d3f038..5a2cf72e8 100644 --- a/src/dev/x86/i8259.hh +++ b/src/dev/x86/i8259.hh @@ -73,6 +73,9 @@ class I8259 : public BasicPioDevice, public IntDev bool expectICW4; int initControlWord; + // Whether or not the PIC is in auto EOI mode. + bool autoEOI; + void requestInterrupt(int line); void handleEOI(int line); -- cgit v1.2.3 From fd376882940db45bdf7abf2fff8758b162828b83 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 23:27:45 -0700 Subject: X86: Add some DPRINTFs to the local APIC. --- src/arch/x86/interrupts.cc | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc index 280fa5dd1..148b26157 100644 --- a/src/arch/x86/interrupts.cc +++ b/src/arch/x86/interrupts.cc @@ -474,14 +474,20 @@ bool X86ISA::Interrupts::check_interrupts(ThreadContext * tc) const { RFLAGS rflags = tc->readMiscRegNoEffect(MISCREG_RFLAGS); - if (pendingUnmaskableInt) + if (pendingUnmaskableInt) { + DPRINTF(LocalApic, "Reported pending unmaskable interrupt.\n"); return true; + } if (rflags.intf) { - if (pendingExtInt) + if (pendingExtInt) { + DPRINTF(LocalApic, "Reported pending external interrupt.\n"); return true; + } if (IRRV > ISRV && bits(IRRV, 7, 4) > - bits(regs[APIC_TASK_PRIORITY], 7, 4)) + bits(regs[APIC_TASK_PRIORITY], 7, 4)) { + DPRINTF(LocalApic, "Reported pending regular interrupt.\n"); return true; + } } return false; } @@ -494,10 +500,13 @@ X86ISA::Interrupts::getInterrupt(ThreadContext * tc) // check for. if (pendingUnmaskableInt) { if (pendingSmi) { + DPRINTF(LocalApic, "Generated SMI fault object.\n"); return new SystemManagementInterrupt(); } else if (pendingNmi) { + DPRINTF(LocalApic, "Generated NMI fault object.\n"); return new NonMaskableInterrupt(nmiMessage.vector); } else if (pendingInit) { + DPRINTF(LocalApic, "Generated INIT fault object.\n"); return new InitInterrupt(initMessage.vector); } else { panic("pendingUnmaskableInt set, but no unmaskable " @@ -505,8 +514,10 @@ X86ISA::Interrupts::getInterrupt(ThreadContext * tc) return NoFault; } } else if (pendingExtInt) { + DPRINTF(LocalApic, "Generated external interrupt fault object.\n"); return new ExternalInterrupt(extIntMessage.vector); } else { + DPRINTF(LocalApic, "Generated regular interrupt fault object.\n"); // The only thing left are fixed and lowest priority interrupts. return new ExternalInterrupt(IRRV); } @@ -518,10 +529,13 @@ X86ISA::Interrupts::updateIntrInfo(ThreadContext * tc) assert(check_interrupts(tc)); if (pendingUnmaskableInt) { if (pendingSmi) { + DPRINTF(LocalApic, "SMI sent to core.\n"); pendingSmi = false; } else if (pendingNmi) { + DPRINTF(LocalApic, "NMI sent to core.\n"); pendingNmi = false; } else if (pendingInit) { + DPRINTF(LocalApic, "Init sent to core.\n"); pendingInit = false; } if (!(pendingSmi || pendingNmi || pendingInit)) @@ -529,6 +543,7 @@ X86ISA::Interrupts::updateIntrInfo(ThreadContext * tc) } else if (pendingExtInt) { pendingExtInt = false; } else { + DPRINTF(LocalApic, "Interrupt %d sent to core.\n", IRRV); // Mark the interrupt as "in service". ISRV = IRRV; setRegArrayBit(APIC_IN_SERVICE_BASE, ISRV); -- cgit v1.2.3 From bdc28d793dd9b3407c513fba5c24917aa423f7ca Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 23:28:11 -0700 Subject: X86: Implement the EOI register in the local APIC. --- src/arch/x86/interrupts.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc index 148b26157..df1b40e5b 100644 --- a/src/arch/x86/interrupts.cc +++ b/src/arch/x86/interrupts.cc @@ -330,9 +330,6 @@ X86ISA::Interrupts::readReg(ApicRegIndex reg) case APIC_PROCESSOR_PRIORITY: panic("Local APIC Processor Priority register unimplemented.\n"); break; - case APIC_EOI: - panic("Local APIC EOI register unimplemented.\n"); - break; case APIC_ERROR_STATUS: regs[APIC_INTERNAL_STATE] &= ~ULL(0x1); break; @@ -391,8 +388,10 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val) panic("Local APIC Processor Priority register unimplemented.\n"); break; case APIC_EOI: - panic("Local APIC EOI register unimplemented.\n"); - break; + // Remove the interrupt that just completed from the local apic state. + clearRegArrayBit(APIC_IN_SERVICE_BASE, ISRV); + updateISRV(); + return; case APIC_LOGICAL_DESTINATION: newVal = val & 0xFF000000; break; -- cgit v1.2.3 From 33ebd04474a1042e5cce585802481b6e95a4e92e Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 23:28:49 -0700 Subject: X86: Make the local APIC timer event generate an interrupt. --- src/arch/x86/interrupts.cc | 93 +++++++++++++++++++++++----------------------- src/arch/x86/interrupts.hh | 50 ++++++++++++++++++++----- 2 files changed, 87 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc index df1b40e5b..bbc651378 100644 --- a/src/arch/x86/interrupts.cc +++ b/src/arch/x86/interrupts.cc @@ -240,6 +240,48 @@ X86ISA::Interrupts::write(PacketPtr pkt) setReg(reg, gtoh(val)); return latency; } +void +X86ISA::Interrupts::requestInterrupt(uint8_t vector, + uint8_t deliveryMode, bool level) +{ + /* + * Fixed and lowest-priority delivery mode interrupts are handled + * using the IRR/ISR registers, checking against the TPR, etc. + * The SMI, NMI, ExtInt, INIT, etc interrupts go straight through. + */ + if (deliveryMode == DeliveryMode::Fixed || + deliveryMode == DeliveryMode::LowestPriority) { + DPRINTF(LocalApic, "Interrupt is an %s.\n", + DeliveryMode::names[deliveryMode]); + // Queue up the interrupt in the IRR. + if (vector > IRRV) + IRRV = vector; + if (!getRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, vector)) { + setRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, vector); + if (level) { + setRegArrayBit(APIC_TRIGGER_MODE_BASE, vector); + } else { + clearRegArrayBit(APIC_TRIGGER_MODE_BASE, vector); + } + } + } else if (!DeliveryMode::isReserved(deliveryMode)) { + DPRINTF(LocalApic, "Interrupt is an %s.\n", + DeliveryMode::names[deliveryMode]); + if (deliveryMode == DeliveryMode::SMI && !pendingSmi) { + pendingUnmaskableInt = pendingSmi = true; + smiVector = vector; + } else if (deliveryMode == DeliveryMode::NMI && !pendingNmi) { + pendingUnmaskableInt = pendingNmi = true; + nmiVector = vector; + } else if (deliveryMode == DeliveryMode::ExtInt && !pendingExtInt) { + pendingExtInt = true; + extIntVector = vector; + } else if (deliveryMode == DeliveryMode::INIT && !pendingInit) { + pendingUnmaskableInt = pendingInit = true; + initVector = vector; + } + } +} Tick X86ISA::Interrupts::recvMessage(PacketPtr pkt) @@ -260,49 +302,8 @@ X86ISA::Interrupts::recvMessage(PacketPtr pkt) assert((message.destMode == 0 && message.destination == id) || (bits((int)message.destination, id))); - /* - * Fixed and lowest-priority delivery mode interrupts are handled - * using the IRR/ISR registers, checking against the TPR, etc. - * The SMI, NMI, ExtInt, INIT, etc interrupts go straight through. - */ - if (message.deliveryMode == DeliveryMode::Fixed || - message.deliveryMode == DeliveryMode::LowestPriority) { - DPRINTF(LocalApic, "Interrupt is an %s.\n", - DeliveryMode::names[message.deliveryMode]); - // Queue up the interrupt in the IRR. - if (vector > IRRV) - IRRV = vector; - if (!getRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, vector)) { - setRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, vector); - if (message.trigger) { - // Level triggered. - setRegArrayBit(APIC_TRIGGER_MODE_BASE, vector); - } else { - // Edge triggered. - clearRegArrayBit(APIC_TRIGGER_MODE_BASE, vector); - } - } - } else if (!DeliveryMode::isReserved(message.deliveryMode)) { - DPRINTF(LocalApic, "Interrupt is an %s.\n", - DeliveryMode::names[message.deliveryMode]); - if (message.deliveryMode == DeliveryMode::SMI && - !pendingSmi) { - pendingUnmaskableInt = pendingSmi = true; - smiMessage = message; - } else if (message.deliveryMode == DeliveryMode::NMI && - !pendingNmi) { - pendingUnmaskableInt = pendingNmi = true; - nmiMessage = message; - } else if (message.deliveryMode == DeliveryMode::ExtInt && - !pendingExtInt) { - pendingExtInt = true; - extIntMessage = message; - } else if (message.deliveryMode == DeliveryMode::INIT && - !pendingInit) { - pendingUnmaskableInt = pendingInit = true; - initMessage = message; - } - } + requestInterrupt(message.vector, + message.deliveryMode, message.trigger); } break; default: @@ -503,10 +504,10 @@ X86ISA::Interrupts::getInterrupt(ThreadContext * tc) return new SystemManagementInterrupt(); } else if (pendingNmi) { DPRINTF(LocalApic, "Generated NMI fault object.\n"); - return new NonMaskableInterrupt(nmiMessage.vector); + return new NonMaskableInterrupt(nmiVector); } else if (pendingInit) { DPRINTF(LocalApic, "Generated INIT fault object.\n"); - return new InitInterrupt(initMessage.vector); + return new InitInterrupt(initVector); } else { panic("pendingUnmaskableInt set, but no unmaskable " "ints were pending.\n"); @@ -514,7 +515,7 @@ X86ISA::Interrupts::getInterrupt(ThreadContext * tc) } } else if (pendingExtInt) { DPRINTF(LocalApic, "Generated external interrupt fault object.\n"); - return new ExternalInterrupt(extIntMessage.vector); + return new ExternalInterrupt(extIntVector); } else { DPRINTF(LocalApic, "Generated regular interrupt fault object.\n"); // The only thing left are fixed and lowest priority interrupts. diff --git a/src/arch/x86/interrupts.hh b/src/arch/x86/interrupts.hh index 85a0f6478..a998e2b12 100644 --- a/src/arch/x86/interrupts.hh +++ b/src/arch/x86/interrupts.hh @@ -79,6 +79,17 @@ class Interrupts : public BasicPioDevice, IntDev // Storage for the APIC registers uint32_t regs[NUM_APIC_REGS]; + BitUnion32(LVTEntry) + Bitfield<7, 0> vector; + Bitfield<10, 8> deliveryMode; + Bitfield<12> status; + Bitfield<13> polarity; + Bitfield<14> remoteIRR; + Bitfield<15> trigger; + Bitfield<16> masked; + Bitfield<17> periodic; + EndBitUnion(LVTEntry) + /* * Timing related stuff. */ @@ -87,13 +98,20 @@ class Interrupts : public BasicPioDevice, IntDev class ApicTimerEvent : public Event { + private: + Interrupts *localApic; public: - ApicTimerEvent() : Event() + ApicTimerEvent(Interrupts *_localApic) : + Event(), localApic(_localApic) {} void process() { - warn("Local APIC timer event doesn't do anything!\n"); + assert(localApic); + if (localApic->triggerTimerInterrupt()) { + localApic->setReg(APIC_INITIAL_COUNT, + localApic->readReg(APIC_INITIAL_COUNT)); + } } }; @@ -104,13 +122,13 @@ class Interrupts : public BasicPioDevice, IntDev * the IRR. */ bool pendingSmi; - TriggerIntMessage smiMessage; + uint8_t smiVector; bool pendingNmi; - TriggerIntMessage nmiMessage; + uint8_t nmiVector; bool pendingExtInt; - TriggerIntMessage extIntMessage; + uint8_t extIntVector; bool pendingInit; - TriggerIntMessage initMessage; + uint8_t initVector; // This is a quick check whether any of the above (except ExtInt) are set. bool pendingUnmaskableInt; @@ -163,6 +181,8 @@ class Interrupts : public BasicPioDevice, IntDev return bits(regs[base + (vector % 32)], vector >> 5); } + void requestInterrupt(uint8_t vector, uint8_t deliveryMode, bool level); + public: /* * Params stuff. @@ -187,6 +207,15 @@ class Interrupts : public BasicPioDevice, IntDev Tick write(PacketPtr pkt); Tick recvMessage(PacketPtr pkt); + bool + triggerTimerInterrupt() + { + LVTEntry entry = regs[APIC_LVT_TIMER]; + if (!entry.masked) + requestInterrupt(entry.vector, entry.deliveryMode, entry.trigger); + return entry.periodic; + } + void addressRanges(AddrRangeList &range_list) { range_list.clear(); @@ -225,10 +254,11 @@ class Interrupts : public BasicPioDevice, IntDev Interrupts(Params * p) : BasicPioDevice(p), IntDev(this), latency(p->pio_latency), clock(0), - pendingSmi(false), smiMessage(0), - pendingNmi(false), nmiMessage(0), - pendingExtInt(false), extIntMessage(0), - pendingInit(false), initMessage(0), + apicTimerEvent(this), + pendingSmi(false), smiVector(0), + pendingNmi(false), nmiVector(0), + pendingExtInt(false), extIntVector(0), + pendingInit(false), initVector(0), pendingUnmaskableInt(false) { pioSize = PageBytes; -- cgit v1.2.3 From 3c4567f2a65e0809d84d85a3fd82a294a1b0cb96 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 23:29:10 -0700 Subject: X86: Set the delayed commit flag in x86 microops appropriately. --- src/arch/x86/isa/macroop.isa | 6 +++--- src/arch/x86/isa/microops/base.isa | 2 +- src/arch/x86/isa/microops/seqop.isa | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/macroop.isa b/src/arch/x86/isa/macroop.isa index b851a92c7..7d94dd95c 100644 --- a/src/arch/x86/isa/macroop.isa +++ b/src/arch/x86/isa/macroop.isa @@ -220,11 +220,11 @@ let {{ allocMicroops = '' micropc = 0 for op in self.microops: + isLast = (micropc == numMicroops - 1) allocMicroops += \ "microops[%d] = %s;\n" % \ - (micropc, op.getAllocator(True, False, - micropc == 0, - micropc == numMicroops - 1)) + (micropc, op.getAllocator(True, not isLast, + micropc == 0, isLast)) micropc += 1 iop = InstObjParams(self.name, self.name, "Macroop", {"code" : "", "num_microops" : numMicroops, diff --git a/src/arch/x86/isa/microops/base.isa b/src/arch/x86/isa/microops/base.isa index 057d237ad..2b73cf563 100644 --- a/src/arch/x86/isa/microops/base.isa +++ b/src/arch/x86/isa/microops/base.isa @@ -118,7 +118,7 @@ let {{ def getGeneratorDef(self, micropc): return self.generatorTemplate % \ (self.className, micropc, \ - self.getAllocator(True, False, False, False)) + self.getAllocator(True, True, False, False)) def getGenerator(self, micropc): return self.generatorNameTemplate % (self.className, micropc) diff --git a/src/arch/x86/isa/microops/seqop.isa b/src/arch/x86/isa/microops/seqop.isa index d3c7bf096..f03094f66 100644 --- a/src/arch/x86/isa/microops/seqop.isa +++ b/src/arch/x86/isa/microops/seqop.isa @@ -195,6 +195,7 @@ let {{ def getAllocator(self, *microFlags): (is_micro, is_delayed, is_first, is_last) = microFlags is_last = False + is_delayed = True microFlags = (is_micro, is_delayed, is_first, is_last) return super(Br, self).getAllocator(*microFlags) @@ -214,6 +215,7 @@ let {{ def getAllocator(self, *microFlags): (is_micro, is_delayed, is_first, is_last) = microFlags is_last = True + is_delayed = False microFlags = (is_micro, is_delayed, is_first, is_last) return super(Eret, self).getAllocator(*microFlags) -- cgit v1.2.3 From 34ca72d16d50586763dbffa01ec7f16b555ac402 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 23:50:22 -0700 Subject: Get rid of some commented out code. --- src/mem/tport.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/mem/tport.cc b/src/mem/tport.cc index f8850df6c..0656f6d82 100644 --- a/src/mem/tport.cc +++ b/src/mem/tport.cc @@ -65,7 +65,6 @@ SimpleTimingPort::recvTiming(PacketPtr pkt) // code to hanldle nacks here, but I'm pretty sure it didn't work // correctly with the drain code, so that would need to be fixed // if we ever added it back. - //assert(pkt->isRequest()); if (pkt->memInhibitAsserted()) { // snooper will supply based on copy of packet -- cgit v1.2.3 From 809f6cb6d1c199563664305fe3b0b286c54dbea7 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 12 Oct 2008 23:52:02 -0700 Subject: CPU: Explain why some code is commented out. --- src/cpu/simple/atomic.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 878f69f0c..30f4a5c5e 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -730,6 +730,10 @@ AtomicSimpleCPU::tick() dcache_access = false; // assume no dcache access if (!fromRom) { + // This is commented out because the predecoder would act like + // a tiny cache otherwise. It wouldn't be flushed when needed + // like the I cache. It should be flushed, and when that works + // this code should be uncommented. //Fetch more instruction memory if necessary //if(predecoder.needMoreBytes()) //{ -- cgit v1.2.3 From ff2eea1ba3b8716f259075654c7463f9395264d7 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Tue, 14 Oct 2008 09:33:52 -0700 Subject: eventq: revert code for unserializing events. Since I never implemented a proper solution, put it back to something that at least works for now. Once I add more event queues, I'll have to really fix this though --- src/sim/eventq.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/sim/eventq.cc b/src/sim/eventq.cc index f4fa0ac8b..dfff760a0 100644 --- a/src/sim/eventq.cc +++ b/src/sim/eventq.cc @@ -209,7 +209,8 @@ Event::serialize(std::ostream &os) void Event::unserialize(Checkpoint *cp, const string §ion) { - assert(!scheduled() && "we used to deschedule these events"); + if (scheduled()) + mainEventQueue.deschedule(this); UNSERIALIZE_SCALAR(_when); UNSERIALIZE_SCALAR(_priority); @@ -223,8 +224,7 @@ Event::unserialize(Checkpoint *cp, const string §ion) if (wasScheduled) { DPRINTF(Config, "rescheduling at %d\n", _when); - panic("need to figure out how to unserialize scheduled events"); - //schedule(_when); + mainEventQueue.schedule(this, _when); } } -- cgit v1.2.3 From 5b07448cf12460090af588b332e813af3419d645 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Tue, 14 Oct 2008 09:34:11 -0700 Subject: eventq: make python events actually work --- src/python/m5/event.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/python/m5/event.py b/src/python/m5/event.py index 5d50448e7..2b43e578e 100644 --- a/src/python/m5/event.py +++ b/src/python/m5/event.py @@ -26,6 +26,7 @@ # # Authors: Nathan Binkert +import m5 import internal.event from internal.event import PythonEvent, SimLoopExitEvent as SimExit @@ -41,7 +42,7 @@ class Event(PythonEvent): def __init__(self, priority=None): if priority is None: priority = internal.event.Event.Default_Pri - super(PythonEvent, self).__init__(self, priority) + super(Event, self).__init__(self, priority) class ProgressEvent(Event): def __init__(self, eventq, period): -- cgit v1.2.3 From 90e40ca982ea99c3abb7bdebffaed48f467ff0e3 Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Tue, 14 Oct 2008 17:22:03 -0400 Subject: This function declaration isn't used anywhere. HG: user: Lisa Hsu HG: branch default HG: changed src/mem/cache/cache.hh --- src/mem/cache/cache.hh | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'src') diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh index 88c9deb7b..cff3fd28b 100644 --- a/src/mem/cache/cache.hh +++ b/src/mem/cache/cache.hh @@ -143,16 +143,6 @@ class Cache : public BaseCache const bool prefetchMiss; - /** - * Handle a replacement for the given request. - * @param blk A pointer to the block, usually NULL - * @param pkt The memory request to satisfy. - * @param new_state The new state of the block. - * @param writebacks A list to store any generated writebacks. - */ - BlkType* doReplacement(BlkType *blk, PacketPtr pkt, - CacheBlk::State new_state, PacketList &writebacks); - /** * Does all the processing necessary to perform the provided request. * @param pkt The memory request to perform. -- cgit v1.2.3 From 81f5da1e89c94fb0e4e56c80cad77561163d85d8 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 16 Oct 2008 22:22:17 -0700 Subject: get rid of local variable that's only used in an assert so fast compiles --- src/arch/x86/interrupts.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc index bbc651378..bfb4d5b9c 100644 --- a/src/arch/x86/interrupts.cc +++ b/src/arch/x86/interrupts.cc @@ -294,10 +294,9 @@ X86ISA::Interrupts::recvMessage(PacketPtr pkt) case 0: { TriggerIntMessage message = pkt->get(); - uint8_t vector = message.vector; DPRINTF(LocalApic, "Got Trigger Interrupt message with vector %#x.\n", - vector); + message.vector); // Make sure we're really supposed to get this. assert((message.destMode == 0 && message.destination == id) || (bits((int)message.destination, id))); -- cgit v1.2.3 From 9b8011e255ee419a689706704b92e5a816fd8d34 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 16 Oct 2008 22:22:47 -0700 Subject: need to add packet_access.hh in order to get tempalte definition --- src/dev/x86/i8259.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/dev/x86/i8259.cc b/src/dev/x86/i8259.cc index 2d460b96d..b3d3a5aa2 100644 --- a/src/dev/x86/i8259.cc +++ b/src/dev/x86/i8259.cc @@ -31,6 +31,8 @@ #include "base/bitfield.hh" #include "dev/x86/i82094aa.hh" #include "dev/x86/i8259.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" X86ISA::I8259::I8259(Params * p) : BasicPioDevice(p), IntDev(this), latency(p->pio_latency), output(p->output), -- cgit v1.2.3 From b760b99f4d9f5469d88c67ae8a06e5f9543a43e7 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Mon, 20 Oct 2008 16:22:59 -0400 Subject: O3CPU: Undo Gabe's changes to remove hwrei and simpalcheck from O3 CPU. Removing hwrei causes the instruction after the hwrei to be fetched before the ITB/DTB_CM register is updated in a call pal call sys and thus the translation fails because the user is attempting to access a super page address. Minimally, it seems as though some sort of fetch stall or refetch after a hwrei is required. I think this works currently because the hwrei uses the exec context interface, and the o3 stalls when that occurs. Additionally, these changes don't update the LOCK register and probably break ll/sc. Both o3 changes were removed since a great deal of manual patching would be required to only remove the hwrei change. --- src/arch/alpha/ev5.cc | 50 ++++++++++++++++++++++++++++++++++++++++++ src/arch/alpha/isa/decoder.isa | 34 ++-------------------------- src/arch/alpha/isa/main.isa | 3 --- src/arch/x86/bios/IntelMP.py | 9 -------- src/cpu/checker/cpu.hh | 2 ++ src/cpu/exec_context.hh | 12 +++++++++- src/cpu/o3/cpu.cc | 45 +++++++++++++++++++++++++++++++++++++ src/cpu/o3/cpu.hh | 5 +++++ src/cpu/o3/dyn_inst.hh | 3 +++ src/cpu/o3/dyn_inst_impl.hh | 32 +++++++++++++++++++++++++++ src/cpu/ozone/cpu.hh | 2 ++ src/cpu/ozone/cpu_impl.hh | 40 +++++++++++++++++++++++++++++++++ src/cpu/ozone/dyn_inst.hh | 2 ++ src/cpu/ozone/dyn_inst_impl.hh | 22 +++++++++++++++++++ src/cpu/simple/base.hh | 2 ++ src/cpu/simple_thread.hh | 4 ++++ 16 files changed, 222 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/ev5.cc b/src/arch/alpha/ev5.cc index c11b3632e..7dc02a611 100644 --- a/src/arch/alpha/ev5.cc +++ b/src/arch/alpha/ev5.cc @@ -547,3 +547,53 @@ copyIprs(ThreadContext *src, ThreadContext *dest) } } // namespace AlphaISA + +#if FULL_SYSTEM + +using namespace AlphaISA; + +Fault +SimpleThread::hwrei() +{ + if (!(readPC() & 0x3)) + return new UnimplementedOpcodeFault; + + setNextPC(readMiscRegNoEffect(IPR_EXC_ADDR)); + + if (!misspeculating()) { + if (kernelStats) + kernelStats->hwrei(); + } + + // FIXME: XXX check for interrupts? XXX + return NoFault; +} + +/** + * Check for special simulator handling of specific PAL calls. + * If return value is false, actual PAL call will be suppressed. + */ +bool +SimpleThread::simPalCheck(int palFunc) +{ + if (kernelStats) + kernelStats->callpal(palFunc, tc); + + switch (palFunc) { + case PAL::halt: + halt(); + if (--System::numSystemsRunning == 0) + exitSimLoop("all cpus halted"); + break; + + case PAL::bpt: + case PAL::bugchk: + if (system->breakpoint()) + return false; + break; + } + + return true; +} + +#endif // FULL_SYSTEM diff --git a/src/arch/alpha/isa/decoder.isa b/src/arch/alpha/isa/decoder.isa index 06676ae87..270940df2 100644 --- a/src/arch/alpha/isa/decoder.isa +++ b/src/arch/alpha/isa/decoder.isa @@ -698,28 +698,7 @@ decode OPCODE default Unknown::unknown() { else { // check to see if simulator wants to do something special // on this PAL call (including maybe suppress it) - - bool dopal = true; - - ThreadContext * tc = xc->tcBase(); - AlphaISA::Kernel::Statistics * kernelStats = tc->getKernelStats(); - System * system = tc->getSystemPtr(); - if (kernelStats) - kernelStats->callpal(palFunc, tc); - - switch (palFunc) { - case PAL::halt: - tc->halt(); - if (--System::numSystemsRunning == 0) - exitSimLoop("all cpus halted"); - break; - - case PAL::bpt: - case PAL::bugchk: - if (system->breakpoint()) - dopal = false; - break; - } + bool dopal = xc->simPalCheck(palFunc); if (dopal) { xc->setMiscReg(IPR_EXC_ADDR, NPC); @@ -807,16 +786,7 @@ decode OPCODE default Unknown::unknown() { format BasicOperate { 0x1e: decode PALMODE { 0: OpcdecFault::hw_rei(); - 1: hw_rei({{ - NPC = ExcAddr; - ThreadContext * tc = xc->tcBase(); - if (!tc->misspeculating()) { - AlphaISA::Kernel::Statistics * kernelStats = - tc->getKernelStats(); - if (kernelStats) - kernelStats->hwrei(); - } - }}, IsSerializing, IsSerializeBefore); + 1:hw_rei({{ xc->hwrei(); }}, IsSerializing, IsSerializeBefore); } // M5 special opcodes use the reserved 0x01 opcode space diff --git a/src/arch/alpha/isa/main.isa b/src/arch/alpha/isa/main.isa index 0f7f74359..5231712c8 100644 --- a/src/arch/alpha/isa/main.isa +++ b/src/arch/alpha/isa/main.isa @@ -69,8 +69,6 @@ output exec {{ #include #if FULL_SYSTEM -#include "arch/alpha/kernel_stats.hh" -#include "arch/alpha/osfpal.hh" #include "sim/pseudo_inst.hh" #endif #include "arch/alpha/ipr.hh" @@ -189,7 +187,6 @@ def operands {{ 'Runiq': ('ControlReg', 'uq', 'MISCREG_UNIQ', None, 1), 'FPCR': ('ControlReg', 'uq', 'MISCREG_FPCR', None, 1), 'IntrFlag': ('ControlReg', 'uq', 'MISCREG_INTR', None, 1), - 'ExcAddr': ('ControlReg', 'uq', 'IPR_EXC_ADDR', None, 1), # The next two are hacks for non-full-system call-pal emulation 'R0': ('IntReg', 'uq', '0', None, 1), 'R16': ('IntReg', 'uq', '16', None, 1), diff --git a/src/arch/x86/bios/IntelMP.py b/src/arch/x86/bios/IntelMP.py index 758932180..70e7963fa 100644 --- a/src/arch/x86/bios/IntelMP.py +++ b/src/arch/x86/bios/IntelMP.py @@ -86,15 +86,6 @@ class X86IntelMPConfigTable(SimObject): ext_entries = VectorParam.X86IntelMPExtConfigEntry([], 'extended configuration table entries') - def add_entry(self, entry): - if isinstance(entry, X86IntelMPBaseConfigEntry): - self.base_entries.append(entry) - elif isinstance(entry, X86IntelMPExtConfigEntry): - self.base_entries.append(entry) - else: - panic("Don't know what type of Intel MP entry %s is." \ - % entry.__class__.__name__) - class X86IntelMPBaseConfigEntry(SimObject): type = 'X86IntelMPBaseConfigEntry' cxx_class = 'X86ISA::IntelMP::BaseConfigEntry' diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh index 0f01f17c5..5b3c4582c 100644 --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@ -336,7 +336,9 @@ class CheckerCPU : public BaseCPU void translateDataReadReq(Request *req); #if FULL_SYSTEM + Fault hwrei() { return thread->hwrei(); } void ev5_trap(Fault fault) { fault->invoke(tc); } + bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); } #else // Assume that the normal CPU's call to syscall was successful. // The checker's state would have already been updated by the syscall. diff --git a/src/cpu/exec_context.hh b/src/cpu/exec_context.hh index 836cf4352..2b9fe4bcf 100644 --- a/src/cpu/exec_context.hh +++ b/src/cpu/exec_context.hh @@ -143,7 +143,17 @@ class ExecContext { * given flags. */ void writeHint(Addr addr, int size, unsigned flags); -#if !FULL_SYSTEM +#if FULL_SYSTEM + /** Somewhat Alpha-specific function that handles returning from + * an error or interrupt. */ + Fault hwrei(); + + /** + * Check for special simulator handling of specific PAL calls. If + * return value is false, actual PAL call will be suppressed. + */ + bool simPalCheck(int palFunc); +#else /** Executes a syscall specified by the callnum. */ void syscall(int64_t callnum); #endif diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index c110bbd50..41b7e8b14 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -53,6 +53,10 @@ #include "cpu/checker/cpu.hh" #endif +#if THE_ISA == ALPHA_ISA +#include "arch/alpha/osfpal.hh" +#endif + class BaseCPUParams; using namespace TheISA; @@ -901,6 +905,47 @@ FullO3CPU::post_interrupt(int int_num, int index) } } +template +Fault +FullO3CPU::hwrei(unsigned tid) +{ +#if THE_ISA == ALPHA_ISA + // Need to clear the lock flag upon returning from an interrupt. + this->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, false, tid); + + this->thread[tid]->kernelStats->hwrei(); + + // FIXME: XXX check for interrupts? XXX +#endif + return NoFault; +} + +template +bool +FullO3CPU::simPalCheck(int palFunc, unsigned tid) +{ +#if THE_ISA == ALPHA_ISA + if (this->thread[tid]->kernelStats) + this->thread[tid]->kernelStats->callpal(palFunc, + this->threadContexts[tid]); + + switch (palFunc) { + case PAL::halt: + halt(); + if (--System::numSystemsRunning == 0) + exitSimLoop("all cpus halted"); + break; + + case PAL::bpt: + case PAL::bugchk: + if (this->system->breakpoint()) + return false; + break; + } +#endif + return true; +} + template Fault FullO3CPU::getInterrupts() diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 07ba8d701..406d965be 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -414,6 +414,11 @@ class FullO3CPU : public BaseO3CPU /** Posts an interrupt. */ void post_interrupt(int int_num, int index); + /** HW return from error interrupt. */ + Fault hwrei(unsigned tid); + + bool simPalCheck(int palFunc, unsigned tid); + /** Returns the Fault for any valid interrupt. */ Fault getInterrupts(); diff --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh index 28dd60f5f..292547b6b 100644 --- a/src/cpu/o3/dyn_inst.hh +++ b/src/cpu/o3/dyn_inst.hh @@ -168,8 +168,11 @@ class BaseO3DynInst : public BaseDynInst } #if FULL_SYSTEM + /** Calls hardware return from error interrupt. */ + Fault hwrei(); /** Traps to handle specified fault. */ void trap(Fault fault); + bool simPalCheck(int palFunc); #else /** Calls a syscall. */ void syscall(int64_t callnum); diff --git a/src/cpu/o3/dyn_inst_impl.hh b/src/cpu/o3/dyn_inst_impl.hh index 3b713ea8f..6398a3afe 100644 --- a/src/cpu/o3/dyn_inst_impl.hh +++ b/src/cpu/o3/dyn_inst_impl.hh @@ -124,12 +124,44 @@ BaseO3DynInst::completeAcc(PacketPtr pkt) } #if FULL_SYSTEM +template +Fault +BaseO3DynInst::hwrei() +{ +#if THE_ISA == ALPHA_ISA + // Can only do a hwrei when in pal mode. + if (!(this->readPC() & 0x3)) + return new AlphaISA::UnimplementedOpcodeFault; + + // Set the next PC based on the value of the EXC_ADDR IPR. + this->setNextPC(this->cpu->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR, + this->threadNumber)); + + // Tell CPU to clear any state it needs to if a hwrei is taken. + this->cpu->hwrei(this->threadNumber); +#else + +#endif + // FIXME: XXX check for interrupts? XXX + return NoFault; +} + template void BaseO3DynInst::trap(Fault fault) { this->cpu->trap(fault, this->threadNumber); } + +template +bool +BaseO3DynInst::simPalCheck(int palFunc) +{ +#if THE_ISA != ALPHA_ISA + panic("simPalCheck called, but PAL only exists in Alpha!\n"); +#endif + return this->cpu->simPalCheck(palFunc, this->threadNumber); +} #else template void diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index ee5e9e668..845cbbd95 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -507,6 +507,8 @@ class OzoneCPU : public BaseCPU void dumpInsts() { frontEnd->dumpInsts(); } #if FULL_SYSTEM + Fault hwrei(); + bool simPalCheck(int palFunc); void processInterrupts(); #else void syscall(uint64_t &callnum); diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index 94af07525..c8e0dfe3d 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -668,6 +668,21 @@ OzoneCPU::setSyscallReturn(SyscallReturn return_value, int tid) } } #else +template +Fault +OzoneCPU::hwrei() +{ + // Need to move this to ISA code + // May also need to make this per thread + + lockFlag = false; + lockAddrList.clear(); + thread.kernelStats->hwrei(); + + // FIXME: XXX check for interrupts? XXX + return NoFault; +} + template void OzoneCPU::processInterrupts() @@ -685,6 +700,31 @@ OzoneCPU::processInterrupts() interrupt->invoke(thread.getTC()); } } + +template +bool +OzoneCPU::simPalCheck(int palFunc) +{ + // Need to move this to ISA code + // May also need to make this per thread + thread.kernelStats->callpal(palFunc, tc); + + switch (palFunc) { + case PAL::halt: + haltContext(thread.readTid()); + if (--System::numSystemsRunning == 0) + exitSimLoop("all cpus halted"); + break; + + case PAL::bpt: + case PAL::bugchk: + if (system->breakpoint()) + return false; + break; + } + + return true; +} #endif template diff --git a/src/cpu/ozone/dyn_inst.hh b/src/cpu/ozone/dyn_inst.hh index 12a19e70d..e138cbe13 100644 --- a/src/cpu/ozone/dyn_inst.hh +++ b/src/cpu/ozone/dyn_inst.hh @@ -240,7 +240,9 @@ class OzoneDynInst : public BaseDynInst void setMiscReg(int misc_reg, const MiscReg &val); #if FULL_SYSTEM + Fault hwrei(); void trap(Fault fault); + bool simPalCheck(int palFunc); #else void syscall(uint64_t &callnum); #endif diff --git a/src/cpu/ozone/dyn_inst_impl.hh b/src/cpu/ozone/dyn_inst_impl.hh index 396007687..8519917f5 100644 --- a/src/cpu/ozone/dyn_inst_impl.hh +++ b/src/cpu/ozone/dyn_inst_impl.hh @@ -248,12 +248,34 @@ OzoneDynInst::setMiscReg(int misc_reg, const MiscReg &val) #if FULL_SYSTEM +template +Fault +OzoneDynInst::hwrei() +{ + if (!(this->readPC() & 0x3)) + return new AlphaISA::UnimplementedOpcodeFault; + + this->setNextPC(this->thread->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR)); + + this->cpu->hwrei(); + + // FIXME: XXX check for interrupts? XXX + return NoFault; +} + template void OzoneDynInst::trap(Fault fault) { fault->invoke(this->thread->getTC()); } + +template +bool +OzoneDynInst::simPalCheck(int palFunc) +{ + return this->cpu->simPalCheck(palFunc); +} #else template void diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index 03c20a6f2..b7fcf1708 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -413,7 +413,9 @@ class BaseSimpleCPU : public BaseCPU //Fault CacheOp(uint8_t Op, Addr EA); #if FULL_SYSTEM + Fault hwrei() { return thread->hwrei(); } void ev5_trap(Fault fault) { fault->invoke(tc); } + bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); } #else void syscall(int64_t callnum) { thread->syscall(callnum); } #endif diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index d26e984a3..189cbeec5 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -185,6 +185,10 @@ class SimpleThread : public ThreadState void dumpFuncProfile(); + Fault hwrei(); + + bool simPalCheck(int palFunc); + #endif /******************************************* -- cgit v1.2.3 From 9836d81c2bba97e36c43ca22feee1d51a12ce6ac Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Tue, 21 Oct 2008 07:12:53 -0700 Subject: style: Use the correct m5 style for things relating to interrupts. --- src/arch/alpha/interrupts.hh | 4 +-- src/arch/mips/interrupts.cc | 6 ++-- src/arch/mips/interrupts.hh | 28 ++++++++++--------- src/arch/sparc/interrupts.hh | 37 +++++++++++++++---------- src/arch/sparc/miscregfile.cc | 4 +-- src/arch/sparc/tlb.cc | 8 +++--- src/arch/sparc/ua2005.cc | 32 +++++++++++----------- src/arch/x86/interrupts.cc | 10 +++---- src/arch/x86/interrupts.hh | 50 +++++++++++++++++++--------------- src/cpu/base.cc | 8 +++--- src/cpu/base.hh | 17 ++++++------ src/cpu/intr_control.cc | 4 +-- src/cpu/o3/commit_impl.hh | 4 +-- src/cpu/o3/cpu.cc | 4 +-- src/cpu/o3/cpu.hh | 2 +- src/cpu/o3/thread_context_impl.hh | 2 +- src/cpu/ozone/cpu.hh | 2 +- src/cpu/ozone/cpu_impl.hh | 4 +-- src/cpu/ozone/inorder_back_end_impl.hh | 3 +- src/cpu/ozone/lw_back_end_impl.hh | 5 +--- src/cpu/simple/base.cc | 6 ++-- src/cpu/simple/base.hh | 2 +- src/cpu/simple_thread.cc | 2 +- 23 files changed, 129 insertions(+), 115 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/interrupts.hh b/src/arch/alpha/interrupts.hh index e7a451d4d..89db134ff 100644 --- a/src/arch/alpha/interrupts.hh +++ b/src/arch/alpha/interrupts.hh @@ -101,7 +101,7 @@ class Interrupts : public SimObject } void - clear_all() + clearAll() { DPRINTF(Interrupt, "Interrupts all cleared\n"); @@ -124,7 +124,7 @@ class Interrupts : public SimObject } bool - check_interrupts(ThreadContext *tc) const + checkInterrupts(ThreadContext *tc) const { return (intstatus != 0) && !(tc->readPC() & 0x3); } diff --git a/src/arch/mips/interrupts.cc b/src/arch/mips/interrupts.cc index e04d22631..99f96fafc 100755 --- a/src/arch/mips/interrupts.cc +++ b/src/arch/mips/interrupts.cc @@ -76,7 +76,7 @@ static inline void setCauseIP_(ThreadContext *tc, uint8_t val) { intstatus &= ~(1 << int_num); } - void Interrupts::clear_all() + void Interrupts::clearAll() { DPRINTF(Interrupt, "Interrupts all cleared\n"); intstatus = 0; @@ -189,14 +189,14 @@ void Interrupts::clear(int int_num, int index) fatal("Must use Thread COntext when clearing MIPS Interrupts in M5"); } -void Interrupts::clear_all(ThreadContext *tc) +void Interrupts::clearAll(ThreadContext *tc) { DPRINTF(Interrupt, "Interrupts all cleared\n"); uint8_t intstatus = 0; setCauseIP_(tc, intstatus); } -void Interrupts::clear_all() +void Interrupts::clearAll() { fatal("Must use Thread COntext when clearing MIPS Interrupts in M5"); } diff --git a/src/arch/mips/interrupts.hh b/src/arch/mips/interrupts.hh index 99a8f6fa0..af71e4636 100755 --- a/src/arch/mips/interrupts.hh +++ b/src/arch/mips/interrupts.hh @@ -57,23 +57,23 @@ class Interrupts // for posting an interrupt. It sets a bit // in intstatus corresponding to Cause IP*. The // MIPS register Cause is updated by updateIntrInfo - // which is called by check_interrupts + // which is called by checkInterrupts // void post(int int_num, int index); // clear(int int_num, int index) is responsible // for clearing an interrupt. It clear a bit // in intstatus corresponding to Cause IP*. The // MIPS register Cause is updated by updateIntrInfo - // which is called by check_interrupts + // which is called by checkInterrupts // void clear(int int_num, int index); - // clear_all() is responsible + // clearAll() is responsible // for clearing all interrupts. It clears all bits // in intstatus corresponding to Cause IP*. The // MIPS register Cause is updated by updateIntrInfo - // which is called by check_interrupts + // which is called by checkInterrupts // - void clear_all(); + void clearAll(); // getInterrupt(ThreadContext * tc) checks if an interrupt // should be returned. It ands the interrupt mask and @@ -91,7 +91,7 @@ class Interrupts void updateIntrInfoCpuTimerIntr(ThreadContext *tc) const; bool onCpuTimerInterrupt(ThreadContext *tc) const; - bool check_interrupts(ThreadContext * tc) const{ + bool checkInterrupts(ThreadContext *tc) const { //return (intstatus != 0) && !(tc->readPC() & 0x3); if (oncputimerintr == false){ updateIntrInfo(tc); @@ -119,7 +119,7 @@ class Interrupts // for posting an interrupt. It sets a bit // in intstatus corresponding to Cause IP*. The // MIPS register Cause is updated by updateIntrInfo - // which is called by check_interrupts + // which is called by checkInterrupts // void post(int int_num, ThreadContext* tc); void post(int int_num, int index); @@ -128,19 +128,19 @@ class Interrupts // for clearing an interrupt. It clear a bit // in intstatus corresponding to Cause IP*. The // MIPS register Cause is updated by updateIntrInfo - // which is called by check_interrupts + // which is called by checkInterrupts // void clear(int int_num, ThreadContext* tc); void clear(int int_num, int index); - // clear_all() is responsible + // clearAll() is responsible // for clearing all interrupts. It clears all bits // in intstatus corresponding to Cause IP*. The // MIPS register Cause is updated by updateIntrInfo - // which is called by check_interrupts + // which is called by checkInterrupts // - void clear_all(ThreadContext* tc); - void clear_all(); + void clearAll(ThreadContext* tc); + void clearAll(); // getInterrupt(ThreadContext * tc) checks if an interrupt // should be returned. It ands the interrupt mask and @@ -158,7 +158,9 @@ class Interrupts bool interruptsPending(ThreadContext *tc) const; bool onCpuTimerInterrupt(ThreadContext *tc) const; - bool check_interrupts(ThreadContext * tc) const{ + bool + checkInterrupts(ThreadContext *tc) const + { return interruptsPending(tc); } diff --git a/src/arch/sparc/interrupts.hh b/src/arch/sparc/interrupts.hh index 7d1496d8e..66b3792b5 100644 --- a/src/arch/sparc/interrupts.hh +++ b/src/arch/sparc/interrupts.hh @@ -45,7 +45,6 @@ class Interrupts : public SimObject { private: - uint64_t interrupts[NumInterruptTypes]; uint64_t intStatus; @@ -60,10 +59,11 @@ class Interrupts : public SimObject Interrupts(Params * p) : SimObject(p) { - clear_all(); + clearAll(); } - int InterruptLevel(uint64_t softint) + int + InterruptLevel(uint64_t softint) { if (softint & 0x10000 || softint & 0x1) return 14; @@ -76,7 +76,8 @@ class Interrupts : public SimObject return 0; } - void post(int int_num, int index) + void + post(int int_num, int index) { DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); assert(int_num >= 0 && int_num < NumInterruptTypes); @@ -86,7 +87,8 @@ class Interrupts : public SimObject intStatus |= ULL(1) << int_num; } - void clear(int int_num, int index) + void + clear(int int_num, int index) { DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); assert(int_num >= 0 && int_num < NumInterruptTypes); @@ -97,7 +99,8 @@ class Interrupts : public SimObject intStatus &= ~(ULL(1) << int_num); } - void clear_all() + void + clearAll() { for (int i = 0; i < NumInterruptTypes; ++i) { interrupts[i] = 0; @@ -105,12 +108,14 @@ class Interrupts : public SimObject intStatus = 0; } - bool check_interrupts(ThreadContext * tc) const + bool + checkInterrupts(ThreadContext *tc) const { return intStatus; } - Fault getInterrupt(ThreadContext * tc) + Fault + getInterrupt(ThreadContext *tc) { int hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE); int pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE); @@ -153,8 +158,8 @@ class Interrupts : public SimObject return new DevMondo; } if (interrupts[IT_SOFT_INT]) { - return new - InterruptLevelN(InterruptLevel(interrupts[IT_SOFT_INT])); + int level = InterruptLevel(interrupts[IT_SOFT_INT]); + return new InterruptLevelN(level); } if (interrupts[IT_RES_ERROR]) { @@ -165,24 +170,28 @@ class Interrupts : public SimObject return NoFault; } - void updateIntrInfo(ThreadContext * tc) + void + updateIntrInfo(ThreadContext *tc) { } - uint64_t get_vec(int int_num) + uint64_t + get_vec(int int_num) { assert(int_num >= 0 && int_num < NumInterruptTypes); return interrupts[int_num]; } - void serialize(std::ostream &os) + void + serialize(std::ostream &os) { SERIALIZE_ARRAY(interrupts,NumInterruptTypes); SERIALIZE_SCALAR(intStatus); } - void unserialize(Checkpoint *cp, const std::string §ion) + void + unserialize(Checkpoint *cp, const std::string §ion) { UNSERIALIZE_ARRAY(interrupts,NumInterruptTypes); UNSERIALIZE_SCALAR(intStatus); diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc index b0c5dbda9..b22ceb657 100644 --- a/src/arch/sparc/miscregfile.cc +++ b/src/arch/sparc/miscregfile.cc @@ -542,9 +542,9 @@ void MiscRegFile::setReg(int miscReg, tl = val; #if FULL_SYSTEM if (hpstate & HPSTATE::tlz && tl == 0 && !(hpstate & HPSTATE::hpriv)) - tc->getCpuPtr()->post_interrupt(IT_TRAP_LEVEL_ZERO,0); + tc->getCpuPtr()->postInterrupt(IT_TRAP_LEVEL_ZERO, 0); else - tc->getCpuPtr()->clear_interrupt(IT_TRAP_LEVEL_ZERO,0); + tc->getCpuPtr()->clearInterrupt(IT_TRAP_LEVEL_ZERO, 0); #endif return; case MISCREG_CWP: diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc index 61f0985db..b6a450ffe 100644 --- a/src/arch/sparc/tlb.cc +++ b/src/arch/sparc/tlb.cc @@ -1021,7 +1021,7 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) dynamic_cast( tc->getCpuPtr()->getInterruptController()); temp = findMsbSet(interrupts->get_vec(IT_INT_VEC)); - tc->getCpuPtr()->clear_interrupt(IT_INT_VEC, temp); + tc->getCpuPtr()->clearInterrupt(IT_INT_VEC, temp); pkt->set(temp); } break; @@ -1268,15 +1268,15 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) SparcISA::Interrupts * interrupts = dynamic_cast( tc->getCpuPtr()->getInterruptController()); - while(interrupts->get_vec(IT_INT_VEC) & data) { + while (interrupts->get_vec(IT_INT_VEC) & data) { msb = findMsbSet(interrupts->get_vec(IT_INT_VEC) & data); - tc->getCpuPtr()->clear_interrupt(IT_INT_VEC, msb); + tc->getCpuPtr()->clearInterrupt(IT_INT_VEC, msb); } } break; case ASI_SWVR_UDB_INTR_W: tc->getSystemPtr()->threadContexts[bits(data,12,8)]->getCpuPtr()-> - post_interrupt(bits(data,5,0),0); + postInterrupt(bits(data, 5, 0), 0); break; default: doMmuWriteError: diff --git a/src/arch/sparc/ua2005.cc b/src/arch/sparc/ua2005.cc index 7b8524703..e1276b812 100644 --- a/src/arch/sparc/ua2005.cc +++ b/src/arch/sparc/ua2005.cc @@ -44,20 +44,20 @@ MiscRegFile::checkSoftInt(ThreadContext *tc) // If PIL < 14, copy over the tm and sm bits if (pil < 14 && softint & 0x10000) - cpu->post_interrupt(IT_SOFT_INT, 16); + cpu->postInterrupt(IT_SOFT_INT, 16); else - cpu->clear_interrupt(IT_SOFT_INT, 16); + cpu->clearInterrupt(IT_SOFT_INT, 16); if (pil < 14 && softint & 0x1) - cpu->post_interrupt(IT_SOFT_INT, 0); + cpu->postInterrupt(IT_SOFT_INT, 0); else - cpu->clear_interrupt(IT_SOFT_INT, 0); + cpu->clearInterrupt(IT_SOFT_INT, 0); // Copy over any of the other bits that are set for (int bit = 15; bit > 0; --bit) { if (1 << bit & softint && bit > pil) - cpu->post_interrupt(IT_SOFT_INT, bit); + cpu->postInterrupt(IT_SOFT_INT, bit); else - cpu->clear_interrupt(IT_SOFT_INT, bit); + cpu->clearInterrupt(IT_SOFT_INT, bit); } } @@ -124,9 +124,9 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc) case MISCREG_HINTP: setRegNoEffect(miscReg, val); if (hintp) - cpu->post_interrupt(IT_HINTP, 0); + cpu->postInterrupt(IT_HINTP, 0); else - cpu->clear_interrupt(IT_HINTP, 0); + cpu->clearInterrupt(IT_HINTP, 0); break; case MISCREG_HTBA: @@ -138,25 +138,25 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc) case MISCREG_QUEUE_CPU_MONDO_TAIL: setRegNoEffect(miscReg, val); if (cpu_mondo_head != cpu_mondo_tail) - cpu->post_interrupt(IT_CPU_MONDO, 0); + cpu->postInterrupt(IT_CPU_MONDO, 0); else - cpu->clear_interrupt(IT_CPU_MONDO, 0); + cpu->clearInterrupt(IT_CPU_MONDO, 0); break; case MISCREG_QUEUE_DEV_MONDO_HEAD: case MISCREG_QUEUE_DEV_MONDO_TAIL: setRegNoEffect(miscReg, val); if (dev_mondo_head != dev_mondo_tail) - cpu->post_interrupt(IT_DEV_MONDO, 0); + cpu->postInterrupt(IT_DEV_MONDO, 0); else - cpu->clear_interrupt(IT_DEV_MONDO, 0); + cpu->clearInterrupt(IT_DEV_MONDO, 0); break; case MISCREG_QUEUE_RES_ERROR_HEAD: case MISCREG_QUEUE_RES_ERROR_TAIL: setRegNoEffect(miscReg, val); if (res_error_head != res_error_tail) - cpu->post_interrupt(IT_RES_ERROR, 0); + cpu->postInterrupt(IT_RES_ERROR, 0); else - cpu->clear_interrupt(IT_RES_ERROR, 0); + cpu->clearInterrupt(IT_RES_ERROR, 0); break; case MISCREG_QUEUE_NRES_ERROR_HEAD: case MISCREG_QUEUE_NRES_ERROR_TAIL: @@ -185,9 +185,9 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc) setRegNoEffect(miscReg, val | HPSTATE::id); #if FULL_SYSTEM if (hpstate & HPSTATE::tlz && tl == 0 && !(hpstate & HPSTATE::hpriv)) - cpu->post_interrupt(IT_TRAP_LEVEL_ZERO, 0); + cpu->postInterrupt(IT_TRAP_LEVEL_ZERO, 0); else - cpu->clear_interrupt(IT_TRAP_LEVEL_ZERO, 0); + cpu->clearInterrupt(IT_TRAP_LEVEL_ZERO, 0); #endif break; case MISCREG_HTSTATE: diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc index bfb4d5b9c..a16ea5360 100644 --- a/src/arch/x86/interrupts.cc +++ b/src/arch/x86/interrupts.cc @@ -470,7 +470,7 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val) } bool -X86ISA::Interrupts::check_interrupts(ThreadContext * tc) const +X86ISA::Interrupts::checkInterrupts(ThreadContext *tc) const { RFLAGS rflags = tc->readMiscRegNoEffect(MISCREG_RFLAGS); if (pendingUnmaskableInt) { @@ -492,9 +492,9 @@ X86ISA::Interrupts::check_interrupts(ThreadContext * tc) const } Fault -X86ISA::Interrupts::getInterrupt(ThreadContext * tc) +X86ISA::Interrupts::getInterrupt(ThreadContext *tc) { - assert(check_interrupts(tc)); + assert(checkInterrupts(tc)); // These are all probably fairly uncommon, so we'll make them easier to // check for. if (pendingUnmaskableInt) { @@ -523,9 +523,9 @@ X86ISA::Interrupts::getInterrupt(ThreadContext * tc) } void -X86ISA::Interrupts::updateIntrInfo(ThreadContext * tc) +X86ISA::Interrupts::updateIntrInfo(ThreadContext *tc) { - assert(check_interrupts(tc)); + assert(checkInterrupts(tc)); if (pendingUnmaskableInt) { if (pendingSmi) { DPRINTF(LocalApic, "SMI sent to core.\n"); diff --git a/src/arch/x86/interrupts.hh b/src/arch/x86/interrupts.hh index a998e2b12..8c7316217 100644 --- a/src/arch/x86/interrupts.hh +++ b/src/arch/x86/interrupts.hh @@ -70,8 +70,7 @@ class ThreadContext; -namespace X86ISA -{ +namespace X86ISA { class Interrupts : public BasicPioDevice, IntDev { @@ -189,7 +188,8 @@ class Interrupts : public BasicPioDevice, IntDev */ typedef X86LocalApicParams Params; - void setClock(Tick newClock) + void + setClock(Tick newClock) { clock = newClock; } @@ -243,7 +243,8 @@ class Interrupts : public BasicPioDevice, IntDev uint32_t readReg(ApicRegIndex miscReg); void setReg(ApicRegIndex reg, uint32_t val); - void setRegNoEffect(ApicRegIndex reg, uint32_t val) + void + setRegNoEffect(ApicRegIndex reg, uint32_t val) { regs[reg] = val; } @@ -252,14 +253,14 @@ class Interrupts : public BasicPioDevice, IntDev * Constructor. */ - Interrupts(Params * p) : BasicPioDevice(p), IntDev(this), - latency(p->pio_latency), clock(0), - apicTimerEvent(this), - pendingSmi(false), smiVector(0), - pendingNmi(false), nmiVector(0), - pendingExtInt(false), extIntVector(0), - pendingInit(false), initVector(0), - pendingUnmaskableInt(false) + Interrupts(Params * p) + : BasicPioDevice(p), IntDev(this), latency(p->pio_latency), clock(0), + apicTimerEvent(this), + pendingSmi(false), smiVector(0), + pendingNmi(false), nmiVector(0), + pendingExtInt(false), extIntVector(0), + pendingInit(false), initVector(0), + pendingUnmaskableInt(false) { pioSize = PageBytes; memset(regs, 0, sizeof(regs)); @@ -273,20 +274,22 @@ class Interrupts : public BasicPioDevice, IntDev * Functions for retrieving interrupts for the CPU to handle. */ - bool check_interrupts(ThreadContext * tc) const; - Fault getInterrupt(ThreadContext * tc); - void updateIntrInfo(ThreadContext * tc); + bool checkInterrupts(ThreadContext *tc) const; + Fault getInterrupt(ThreadContext *tc); + void updateIntrInfo(ThreadContext *tc); /* * Serialization. */ - void serialize(std::ostream & os) + void + serialize(std::ostream &os) { panic("Interrupts::serialize unimplemented!\n"); } - void unserialize(Checkpoint * cp, const std::string & section) + void + unserialize(Checkpoint *cp, const std::string §ion) { panic("Interrupts::unserialize unimplemented!\n"); } @@ -295,22 +298,25 @@ class Interrupts : public BasicPioDevice, IntDev * Old functions needed for compatability but which will be phased out * eventually. */ - void post(int int_num, int index) + void + post(int int_num, int index) { panic("Interrupts::post unimplemented!\n"); } - void clear(int int_num, int index) + void + clear(int int_num, int index) { panic("Interrupts::clear unimplemented!\n"); } - void clear_all() + void + clearAll() { - panic("Interrupts::clear_all unimplemented!\n"); + panic("Interrupts::clearAll unimplemented!\n"); } }; -}; +} // namespace X86ISA #endif // __ARCH_X86_INTERRUPTS_HH__ diff --git a/src/cpu/base.cc b/src/cpu/base.cc index def1e9920..8c461cccb 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -379,21 +379,21 @@ BaseCPU::ProfileEvent::process() } void -BaseCPU::post_interrupt(int int_num, int index) +BaseCPU::postInterrupt(int int_num, int index) { interrupts->post(int_num, index); } void -BaseCPU::clear_interrupt(int int_num, int index) +BaseCPU::clearInterrupt(int int_num, int index) { interrupts->clear(int_num, index); } void -BaseCPU::clear_interrupts() +BaseCPU::clearInterrupts() { - interrupts->clear_all(); + interrupts->clearAll(); } void diff --git a/src/cpu/base.hh b/src/cpu/base.hh index b0eece2a1..2d25c9e56 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -108,9 +108,7 @@ class BaseCPU : public MemObject #if FULL_SYSTEM protected: -// uint64_t interrupts[TheISA::NumInterruptLevels]; -// uint64_t intstatus; - TheISA::Interrupts * interrupts; + TheISA::Interrupts *interrupts; public: TheISA::Interrupts * @@ -119,12 +117,15 @@ class BaseCPU : public MemObject return interrupts; } - virtual void post_interrupt(int int_num, int index); - virtual void clear_interrupt(int int_num, int index); - virtual void clear_interrupts(); + virtual void postInterrupt(int int_num, int index); + virtual void clearInterrupt(int int_num, int index); + virtual void clearInterrupts(); - bool check_interrupts(ThreadContext * tc) const - { return interrupts->check_interrupts(tc); } + bool + checkInterrupts(ThreadContext *tc) const + { + return interrupts->checkInterrupts(tc); + } class ProfileEvent : public Event { diff --git a/src/cpu/intr_control.cc b/src/cpu/intr_control.cc index c3a11ad91..de7f9245e 100644 --- a/src/cpu/intr_control.cc +++ b/src/cpu/intr_control.cc @@ -50,7 +50,7 @@ IntrControl::post(int cpu_id, int int_num, int index) DPRINTF(IntrControl, "post %d:%d (cpu %d)\n", int_num, index, cpu_id); std::vector &tcvec = sys->threadContexts; BaseCPU *cpu = tcvec[cpu_id]->getCpuPtr(); - cpu->post_interrupt(int_num, index); + cpu->postInterrupt(int_num, index); } void @@ -59,7 +59,7 @@ IntrControl::clear(int cpu_id, int int_num, int index) DPRINTF(IntrControl, "clear %d:%d (cpu %d)\n", int_num, index, cpu_id); std::vector &tcvec = sys->threadContexts; BaseCPU *cpu = tcvec[cpu_id]->getCpuPtr(); - cpu->clear_interrupt(int_num, index); + cpu->clearInterrupt(int_num, index); } IntrControl * diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index 68fc6ef3b..46c4158f6 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -665,7 +665,7 @@ DefaultCommit::handleInterrupt() DPRINTF(Commit, "Interrupt pending, waiting for ROB to empty.\n"); } } else if (commitStatus[0] != TrapPending && - cpu->check_interrupts(cpu->tcBase(0)) && + cpu->checkInterrupts(cpu->tcBase(0)) && !trapSquash[0] && !tcSquash[0]) { // Process interrupts if interrupts are enabled, not in PAL @@ -695,7 +695,7 @@ DefaultCommit::commit() // Check for any interrupt, and start processing it. Or if we // have an outstanding interrupt and are at a point when it is // valid to take an interrupt, process it. - if (cpu->check_interrupts(cpu->tcBase(0))) { + if (cpu->checkInterrupts(cpu->tcBase(0))) { handleInterrupt(); } #endif // FULL_SYSTEM diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 41b7e8b14..04f344930 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -895,9 +895,9 @@ FullO3CPU::activateWhenReady(int tid) #if FULL_SYSTEM template void -FullO3CPU::post_interrupt(int int_num, int index) +FullO3CPU::postInterrupt(int int_num, int index) { - BaseCPU::post_interrupt(int_num, index); + BaseCPU::postInterrupt(int_num, index); if (this->thread[0]->status() == ThreadContext::Suspended) { DPRINTF(IPI,"Suspended Processor awoke\n"); diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 406d965be..8cfc9affa 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -412,7 +412,7 @@ class FullO3CPU : public BaseO3CPU #if FULL_SYSTEM /** Posts an interrupt. */ - void post_interrupt(int int_num, int index); + void postInterrupt(int int_num, int index); /** HW return from error interrupt. */ Fault hwrei(unsigned tid); diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index a521c3636..d8ec70bb8 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -132,7 +132,7 @@ O3ThreadContext::suspend(int delay) /* #if FULL_SYSTEM // Don't change the status from active if there are pending interrupts - if (cpu->check_interrupts()) { + if (cpu->checkInterrupts()) { assert(status() == ThreadContext::Active); return; } diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index 845cbbd95..491e6ba93 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -332,7 +332,7 @@ class OzoneCPU : public BaseCPU Status _status; public: - void post_interrupt(int int_num, int index); + void postInterrupt(int int_num, int index); void zero_fill_64(Addr addr) { static int warned = 0; diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index c8e0dfe3d..a7efa3596 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -579,9 +579,9 @@ OzoneCPU::dbg_vtophys(Addr addr) #if FULL_SYSTEM template void -OzoneCPU::post_interrupt(int int_num, int index) +OzoneCPU::postInterrupt(int int_num, int index) { - BaseCPU::post_interrupt(int_num, index); + BaseCPU::postInterrupt(int_num, index); if (_status == Idle) { DPRINTF(IPI,"Suspended Processor awoke\n"); diff --git a/src/cpu/ozone/inorder_back_end_impl.hh b/src/cpu/ozone/inorder_back_end_impl.hh index cf8634a42..798b628d6 100644 --- a/src/cpu/ozone/inorder_back_end_impl.hh +++ b/src/cpu/ozone/inorder_back_end_impl.hh @@ -149,8 +149,7 @@ InorderBackEnd::tick() // if (interrupt) then set thread PC, stall front end, record that // I'm waiting for it to drain. (for now just squash) #if FULL_SYSTEM - if (interruptBlocked || - cpu->check_interrupts(tc)) { + if (interruptBlocked || cpu->checkInterrupts(tc)) { if (!robEmpty()) { interruptBlocked = true; //AlphaDep diff --git a/src/cpu/ozone/lw_back_end_impl.hh b/src/cpu/ozone/lw_back_end_impl.hh index a5d79a789..60c42edd3 100644 --- a/src/cpu/ozone/lw_back_end_impl.hh +++ b/src/cpu/ozone/lw_back_end_impl.hh @@ -525,10 +525,7 @@ template void LWBackEnd::checkInterrupts() { - if (cpu->checkInterrupts && - cpu->check_interrupts(tc) && - !trapSquash && - !tcSquash) { + if (cpu->checkInterrupts(tc) && !trapSquash && !tcSquash) { frontEnd->interruptPending = true; if (robEmpty() && !LSQ.hasStoresToWB()) { // Will need to squash all instructions currently in flight and have diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index d207bda14..b3379cddb 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -303,9 +303,9 @@ BaseSimpleCPU::dbg_vtophys(Addr addr) #if FULL_SYSTEM void -BaseSimpleCPU::post_interrupt(int int_num, int index) +BaseSimpleCPU::postInterrupt(int int_num, int index) { - BaseCPU::post_interrupt(int_num, index); + BaseCPU::postInterrupt(int_num, index); if (thread->status() == ThreadContext::Suspended) { DPRINTF(Quiesce,"Suspended Processor awoke\n"); @@ -318,7 +318,7 @@ void BaseSimpleCPU::checkForInterrupts() { #if FULL_SYSTEM - if (check_interrupts(tc)) { + if (checkInterrupts(tc)) { Fault interrupt = interrupts->getInterrupt(tc); if (interrupt != NoFault) { diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index b7fcf1708..dc736c22e 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -98,7 +98,7 @@ class BaseSimpleCPU : public BaseCPU } public: - void post_interrupt(int int_num, int index); + void postInterrupt(int int_num, int index); void zero_fill_64(Addr addr) { static int warned = 0; diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index 42da659f2..68683e568 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -241,7 +241,7 @@ SimpleThread::suspend() /* #if FULL_SYSTEM // Don't change the status from active if there are pending interrupts - if (cpu->check_interrupts()) { + if (cpu->checkInterrupts()) { assert(status() == ThreadContext::Active); return; } -- cgit v1.2.3 From 7a28ab2d1898153660fbc01413fcfcd30685a987 Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Thu, 23 Oct 2008 16:11:28 -0400 Subject: remove the totally obsolete split cache --- src/mem/cache/BaseCache.py | 5 - src/mem/cache/builder.cc | 36 +--- src/mem/cache/cache.cc | 16 -- src/mem/cache/tags/SConscript | 4 - src/mem/cache/tags/split.cc | 419 --------------------------------------- src/mem/cache/tags/split.hh | 308 ---------------------------- src/mem/cache/tags/split_blk.hh | 68 ------- src/mem/cache/tags/split_lifo.cc | 331 ------------------------------- src/mem/cache/tags/split_lifo.hh | 312 ----------------------------- src/mem/cache/tags/split_lru.cc | 260 ------------------------ src/mem/cache/tags/split_lru.hh | 295 --------------------------- src/mem/config/cache.hh | 3 - 12 files changed, 1 insertion(+), 2056 deletions(-) delete mode 100644 src/mem/cache/tags/split.cc delete mode 100644 src/mem/cache/tags/split.hh delete mode 100644 src/mem/cache/tags/split_blk.hh delete mode 100644 src/mem/cache/tags/split_lifo.cc delete mode 100644 src/mem/cache/tags/split_lifo.hh delete mode 100644 src/mem/cache/tags/split_lru.cc delete mode 100644 src/mem/cache/tags/split_lru.hh (limited to 'src') diff --git a/src/mem/cache/BaseCache.py b/src/mem/cache/BaseCache.py index f6d42b1ef..936107b7f 100644 --- a/src/mem/cache/BaseCache.py +++ b/src/mem/cache/BaseCache.py @@ -38,8 +38,6 @@ class BaseCache(MemObject): block_size = Param.Int("block size in bytes") latency = Param.Latency("Latency") hash_delay = Param.Int(1, "time in cycles of hash access") - lifo = Param.Bool(False, - "whether this NIC partition should use LIFO repl. policy") max_miss_count = Param.Counter(0, "number of misses to handle before calling exit") mshrs = Param.Int("number of MSHRs (max outstanding requests)") @@ -47,9 +45,6 @@ class BaseCache(MemObject): "always service demand misses first") repl = Param.Repl(NULL, "replacement policy") size = Param.MemorySize("capacity in bytes") - split = Param.Bool(False, "whether or not this cache is split") - split_size = Param.Int(0, - "How many ways of the cache belong to CPU/LRU partition") subblock_size = Param.Int(0, "Size of subblock in IIC used for compression") tgts_per_mshr = Param.Int("max number of accesses per MSHR") diff --git a/src/mem/cache/builder.cc b/src/mem/cache/builder.cc index 97930fe60..27daa4025 100644 --- a/src/mem/cache/builder.cc +++ b/src/mem/cache/builder.cc @@ -57,14 +57,6 @@ #include "mem/cache/tags/iic.hh" #endif -#if defined(USE_CACHE_SPLIT) -#include "mem/cache/tags/split.hh" -#endif - -#if defined(USE_CACHE_SPLIT_LIFO) -#include "mem/cache/tags/split_lifo.hh" -#endif - //Prefetcher Headers #if defined(USE_GHB) #include "mem/cache/prefetch/ghb.hh" @@ -122,26 +114,6 @@ using namespace TheISA; #define BUILD_LRU_CACHE BUILD_CACHE_PANIC("lru cache") #endif -#if defined(USE_CACHE_SPLIT) -#define BUILD_SPLIT_CACHE do { \ - Split *tags = new Split(numSets, block_size, assoc, split_size, lifo, \ - two_queue, latency); \ - BUILD_CACHE(Split, tags); \ - } while (0) -#else -#define BUILD_SPLIT_CACHE BUILD_CACHE_PANIC("split cache") -#endif - -#if defined(USE_CACHE_SPLIT_LIFO) -#define BUILD_SPLIT_LIFO_CACHE do { \ - SplitLIFO *tags = new SplitLIFO(block_size, size, assoc, \ - latency, two_queue, -1); \ - BUILD_CACHE(SplitLIFO, tags); \ - } while (0) -#else -#define BUILD_SPLIT_LIFO_CACHE BUILD_CACHE_PANIC("lifo cache") -#endif - #if defined(USE_CACHE_IIC) #define BUILD_IIC_CACHE do { \ IIC *tags = new IIC(iic_params); \ @@ -156,13 +128,7 @@ using namespace TheISA; if (numSets == 1) { \ BUILD_FALRU_CACHE; \ } else { \ - if (split == true) { \ - BUILD_SPLIT_CACHE; \ - } else if (lifo == true) { \ - BUILD_SPLIT_LIFO_CACHE; \ - } else { \ - BUILD_LRU_CACHE; \ - } \ + BUILD_LRU_CACHE; \ } \ } else { \ BUILD_IIC_CACHE; \ diff --git a/src/mem/cache/cache.cc b/src/mem/cache/cache.cc index c640d4a60..d403535fc 100644 --- a/src/mem/cache/cache.cc +++ b/src/mem/cache/cache.cc @@ -50,14 +50,6 @@ #include "mem/cache/tags/iic.hh" #endif -#if defined(USE_CACHE_SPLIT) -#include "mem/cache/tags/split.hh" -#endif - -#if defined(USE_CACHE_SPLIT_LIFO) -#include "mem/cache/tags/split_lifo.hh" -#endif - #include "mem/cache/cache_impl.hh" // Template Instantiations @@ -76,12 +68,4 @@ template class Cache; template class Cache; #endif -#if defined(USE_CACHE_SPLIT) -template class Cache; -#endif - -#if defined(USE_CACHE_SPLIT_LIFO) -template class Cache; -#endif - #endif //DOXYGEN_SHOULD_SKIP_THIS diff --git a/src/mem/cache/tags/SConscript b/src/mem/cache/tags/SConscript index 9153d97e7..7255e0b7e 100644 --- a/src/mem/cache/tags/SConscript +++ b/src/mem/cache/tags/SConscript @@ -34,13 +34,9 @@ Source('base.cc') Source('fa_lru.cc') Source('iic.cc') Source('lru.cc') -Source('split.cc') -Source('split_lifo.cc') -Source('split_lru.cc') SimObject('iic_repl/Repl.py') Source('iic_repl/gen.cc') TraceFlag('IIC') TraceFlag('IICMore') -TraceFlag('Split') diff --git a/src/mem/cache/tags/split.cc b/src/mem/cache/tags/split.cc deleted file mode 100644 index 5bed44bd3..000000000 --- a/src/mem/cache/tags/split.cc +++ /dev/null @@ -1,419 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Lisa Hsu - */ - -/** - * @file - * Definitions of split cache tag store. - */ - -#include -#include -#include - -#include "base/cprintf.hh" -#include "base/intmath.hh" -#include "base/output.hh" -#include "base/trace.hh" -#include "mem/cache/base.hh" -#include "mem/cache/tags/split.hh" -#include "mem/cache/tags/split_lifo.hh" -#include "mem/cache/tags/split_lru.hh" - - -using namespace std; -using namespace TheISA; - -// create and initialize a partitioned cache structure -Split::Split(int _numSets, int _blkSize, int total_ways, int LRU1_assoc, - bool _lifo, bool _two_queue, int _hit_latency) : - numSets(_numSets), blkSize(_blkSize), lifo(_lifo), hitLatency(_hit_latency) -{ - DPRINTF(Split, "new split cache!!\n"); - - DPRINTF(Split, "lru has %d numSets, %d blkSize, %d assoc, and %d hit_latency\n", - numSets, blkSize, LRU1_assoc, hitLatency); - - lru = new SplitLRU(_numSets, _blkSize, LRU1_assoc, _hit_latency, 1); - - if (total_ways - LRU1_assoc == 0) { - lifo_net = NULL; - lru_net = NULL; - } else { - if (lifo) { - DPRINTF(Split, "Other partition is a LIFO with size %d in bytes. it gets %d ways\n", - (total_ways - LRU1_assoc)*_numSets*_blkSize, (total_ways - LRU1_assoc)); - lifo_net = new SplitLIFO(_blkSize, (total_ways - LRU1_assoc)*_numSets*_blkSize, - (total_ways - LRU1_assoc), _hit_latency, _two_queue, 2); - lru_net = NULL; - } - else { - DPRINTF(Split, "other LRU gets %d ways\n", total_ways - LRU1_assoc); - lru_net = new SplitLRU(_numSets, _blkSize, total_ways - LRU1_assoc, _hit_latency, 2); - lifo_net = NULL; - } - } - - blkMask = blkSize - 1; - - if (!isPowerOf2(total_ways)) - warn("total cache ways/columns %d should be power of 2", - total_ways); - - warmedUp = false; - /** @todo Make warmup percentage a parameter. */ - warmupBound = numSets * total_ways; - -} - -Split::~Split() -{ - delete lru; - if (lifo) - delete lifo_net; - else - delete lru_net; -} - -void -Split::regStats(const string &name) -{ - using namespace Stats; - - BaseTags::regStats(name); - - usedEvictDist.init(0,3000,40); - unusedEvictDist.init(0,3000,40); - useByCPUCycleDist.init(0,35,1); - - nic_repl - .name(name + ".nic_repl") - .desc("number of replacements in the nic partition") - .precision(0) - ; - - cpu_repl - .name(name + ".cpu_repl") - .desc("number of replacements in the cpu partition") - .precision(0) - ; - - lru->regStats(name + ".lru"); - - if (lifo && lifo_net) { - lifo_net->regStats(name + ".lifo_net"); - } else if (lru_net) { - lru_net->regStats(name + ".lru_net"); - } - - nicUsedWhenEvicted - .name(name + ".nicUsedWhenEvicted") - .desc("number of NIC blks that were used before evicted") - ; - - nicUsedTotLatency - .name(name + ".nicUsedTotLatency") - .desc("total cycles before eviction of used NIC blks") - ; - - nicUsedTotEvicted - .name(name + ".nicUsedTotEvicted") - .desc("total number of used NIC blks evicted") - ; - - nicUsedAvgLatency - .name(name + ".nicUsedAvgLatency") - .desc("avg number of cycles a used NIC blk is in cache") - .precision(0) - ; - nicUsedAvgLatency = nicUsedTotLatency / nicUsedTotEvicted; - - usedEvictDist - .name(name + ".usedEvictDist") - .desc("distribution of used NIC blk eviction times") - .flags(pdf | cdf) - ; - - nicUnusedWhenEvicted - .name(name + ".nicUnusedWhenEvicted") - .desc("number of NIC blks that were unused when evicted") - ; - - nicUnusedTotLatency - .name(name + ".nicUnusedTotLatency") - .desc("total cycles before eviction of unused NIC blks") - ; - - nicUnusedTotEvicted - .name(name + ".nicUnusedTotEvicted") - .desc("total number of unused NIC blks evicted") - ; - - nicUnusedAvgLatency - .name(name + ".nicUnusedAvgLatency") - .desc("avg number of cycles an unused NIC blk is in cache") - .precision(0) - ; - nicUnusedAvgLatency = nicUnusedTotLatency / nicUnusedTotEvicted; - - unusedEvictDist - .name(name + ".unusedEvictDist") - .desc("distribution of unused NIC blk eviction times") - .flags(pdf | cdf) - ; - - nicUseByCPUCycleTotal - .name(name + ".nicUseByCPUCycleTotal") - .desc("total latency of NIC blks til usage time") - ; - - nicBlksUsedByCPU - .name(name + ".nicBlksUsedByCPU") - .desc("total number of NIC blks used") - ; - - nicAvgUsageByCPULatency - .name(name + ".nicAvgUsageByCPULatency") - .desc("average number of cycles before a NIC blk that is used gets used") - .precision(0) - ; - nicAvgUsageByCPULatency = nicUseByCPUCycleTotal / nicBlksUsedByCPU; - - useByCPUCycleDist - .name(name + ".useByCPUCycleDist") - .desc("the distribution of cycle time in cache before NIC blk is used") - .flags(pdf | cdf) - ; - - cpuUsedBlks - .name(name + ".cpuUsedBlks") - .desc("number of cpu blks that were used before evicted") - ; - - cpuUnusedBlks - .name(name + ".cpuUnusedBlks") - .desc("number of cpu blks that were unused before evicted") - ; - - nicAvgLatency - .name(name + ".nicAvgLatency") - .desc("avg number of cycles a NIC blk is in cache before evicted") - .precision(0) - ; - nicAvgLatency = (nicUnusedTotLatency + nicUsedTotLatency) / - (nicUnusedTotEvicted + nicUsedTotEvicted); - - NR_CP_hits - .name(name + ".NR_CP_hits") - .desc("NIC requests hitting in CPU Partition") - ; - - NR_NP_hits - .name(name + ".NR_NP_hits") - .desc("NIC requests hitting in NIC Partition") - ; - - CR_CP_hits - .name(name + ".CR_CP_hits") - .desc("CPU requests hitting in CPU partition") - ; - - CR_NP_hits - .name(name + ".CR_NP_hits") - .desc("CPU requests hitting in NIC partition") - ; - -} - -// probe cache for presence of given block. -bool -Split::probe(Addr addr) const -{ - bool success = lru->probe(addr); - if (!success) { - if (lifo && lifo_net) - success = lifo_net->probe(addr); - else if (lru_net) - success = lru_net->probe(addr); - } - - return success; -} - - -SplitBlk* -Split::findBlock(Addr addr, int &lat) -{ - SplitBlk *blk = lru->findBlock(addr, lat); - if (!blk) { - if (lifo && lifo_net) { - blk = lifo_net->findBlock(addr, lat); - } else if (lru_net) { - blk = lru_net->findBlock(addr, lat); - } - } - - return blk; -} - -SplitBlk* -Split::findBlock(Addr addr) const -{ - SplitBlk *blk = lru->findBlock(addr); - if (!blk) { - if (lifo && lifo_net) { - blk = lifo_net->findBlock(addr); - } else if (lru_net) { - blk = lru_net->findBlock(addr); - } - } - - return blk; -} - -SplitBlk* -Split::findReplacement(Addr addr, PacketList &writebacks) -{ - SplitBlk *blk = NULL; - - assert(0); -#if 0 - if (pkt->nic_pkt()) { - DPRINTF(Split, "finding a replacement for nic_req\n"); - nic_repl++; - if (lifo && lifo_net) - blk = lifo_net->findReplacement(addr, writebacks); - else if (lru_net) - blk = lru_net->findReplacement(addr, writebacks); - // in this case, this is an LRU only cache, it's non partitioned - else - blk = lru->findReplacement(addr, writebacks); - } else { - DPRINTF(Split, "finding replacement for cpu_req\n"); - blk = lru->findReplacement(addr, writebacks); - cpu_repl++; - } - - Tick latency = curTick - blk->ts; - if (blk->isNIC) { - if (blk->isUsed) { - nicUsedWhenEvicted++; - usedEvictDist.sample(latency); - nicUsedTotLatency += latency; - nicUsedTotEvicted++; - } else { - nicUnusedWhenEvicted++; - unusedEvictDist.sample(latency); - nicUnusedTotLatency += latency; - nicUnusedTotEvicted++; - } - } else { - if (blk->isUsed) { - cpuUsedBlks++; - } else { - cpuUnusedBlks++; - } - } - - // blk attributes for the new blk coming IN - blk->ts = curTick; - blk->isNIC = (pkt->nic_pkt()) ? true : false; -#endif - - return blk; -} - -void -Split::invalidateBlk(Split::BlkType *blk) -{ - if (!blk) { - fatal("FIXME!\n"); -#if 0 - if (lifo && lifo_net) - blk = lifo_net->findBlock(addr); - else if (lru_net) - blk = lru_net->findBlock(addr); -#endif - - if (!blk) - return; - } - - blk->status = 0; - blk->isTouched = false; - tagsInUse--; -} - -void -Split::cleanupRefs() -{ - lru->cleanupRefs(); - if (lifo && lifo_net) - lifo_net->cleanupRefs(); - else if (lru_net) - lru_net->cleanupRefs(); - - ostream *memPrint = simout.create("memory_footprint.txt"); - - // this shouldn't be here but it happens at the end, which is what i want - memIter end = memHash.end(); - for (memIter iter = memHash.begin(); iter != end; ++iter) { - ccprintf(*memPrint, "%8x\t%d\n", (*iter).first, (*iter).second); - } -} - -Addr -Split::regenerateBlkAddr(Addr tag, int set) const -{ - if (lifo_net) - return lifo_net->regenerateBlkAddr(tag, set); - else - return lru->regenerateBlkAddr(tag, set); -} - -Addr -Split::extractTag(Addr addr) const -{ - // need to fix this if we want to use it... old interface of - // passing in blk was too weird - assert(0); - return 0; -/* - if (blk->part == 2) { - if (lifo_net) - return lifo_net->extractTag(addr); - else if (lru_net) - return lru_net->extractTag(addr); - else - panic("this shouldn't happen"); - } else - return lru->extractTag(addr); -*/ -} - diff --git a/src/mem/cache/tags/split.hh b/src/mem/cache/tags/split.hh deleted file mode 100644 index e8954f791..000000000 --- a/src/mem/cache/tags/split.hh +++ /dev/null @@ -1,308 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Lisa Hsu - */ - -/** - * @file - * Declaration of a split/partitioned tag store. - */ - -#ifndef __SPLIT_HH__ -#define __SPLIT_HH__ - -#include -#include - -#include "mem/cache/blk.hh" // base class -#include "mem/cache/tags/split_blk.hh" -#include "mem/packet.hh" // for inlined functions -#include -#include "mem/cache/tags/base.hh" -#include "base/hashmap.hh" - -class BaseCache; -class SplitLRU; -class SplitLIFO; - -/** - * A cache tag store. - */ -class Split : public BaseTags -{ - public: - /** Typedef the block type used in this tag store. */ - typedef SplitBlk BlkType; - /** Typedef for a list of pointers to the local block class. */ - typedef std::list BlkList; - protected: - /** The number of sets in the cache. */ - const int numSets; - /** The number of bytes in a block. */ - const int blkSize; - /** Whether the 2nd partition (for the nic) is LIFO or not */ - const bool lifo; - /** The hit latency. */ - const int hitLatency; - - Addr blkMask; - - /** Number of NIC requests that hit in the NIC partition */ - Stats::Scalar<> NR_NP_hits; - /** Number of NIC requests that hit in the CPU partition */ - Stats::Scalar<> NR_CP_hits; - /** Number of CPU requests that hit in the NIC partition */ - Stats::Scalar<> CR_NP_hits; - /** Number of CPU requests that hit in the CPU partition */ - Stats::Scalar<> CR_CP_hits; - /** The number of nic replacements (i.e. misses) */ - Stats::Scalar<> nic_repl; - /** The number of cpu replacements (i.e. misses) */ - Stats::Scalar<> cpu_repl; - - //For latency studies - /** the number of NIC blks that were used before evicted */ - Stats::Scalar<> nicUsedWhenEvicted; - /** the total latency of used NIC blocks in the cache */ - Stats::Scalar<> nicUsedTotLatency; - /** the total number of used NIC blocks evicted */ - Stats::Scalar<> nicUsedTotEvicted; - /** the average number of cycles a used NIC blk is in the cache */ - Stats::Formula nicUsedAvgLatency; - /** the Distribution of used NIC blk eviction times */ - Stats::Distribution<> usedEvictDist; - - /** the number of NIC blks that were unused before evicted */ - Stats::Scalar<> nicUnusedWhenEvicted; - /** the total latency of unused NIC blks in the cache */ - Stats::Scalar<> nicUnusedTotLatency; - /** the total number of unused NIC blocks evicted */ - Stats::Scalar<> nicUnusedTotEvicted; - /** the average number of cycles an unused NIC blk is in the cache */ - Stats::Formula nicUnusedAvgLatency; - /** the Distribution of unused NIC blk eviction times */ - Stats::Distribution<> unusedEvictDist; - - /** The total latency of NIC blocks to 1st usage time by CPU */ - Stats::Scalar<> nicUseByCPUCycleTotal; - /** The total number of NIC blocks used */ - Stats::Scalar<> nicBlksUsedByCPU; - /** the average number of cycles before a NIC blk that is used gets used by CPU */ - Stats::Formula nicAvgUsageByCPULatency; - /** the Distribution of cycles time before a NIC blk is used by CPU*/ - Stats::Distribution<> useByCPUCycleDist; - - /** the number of CPU blks that were used before evicted */ - Stats::Scalar<> cpuUsedBlks; - /** the number of CPU blks that were unused before evicted */ - Stats::Scalar<> cpuUnusedBlks; - - /** the avg number of cycles before a NIC blk is evicted */ - Stats::Formula nicAvgLatency; - - typedef m5::hash_map > hash_t; - typedef hash_t::const_iterator memIter; - hash_t memHash; - - - private: - SplitLRU *lru; - SplitLRU *lru_net; - SplitLIFO *lifo_net; - - public: - /** - * Construct and initialize this tag store. - * @param _numSets The number of sets in the cache. - * @param _blkSize The number of bytes in a block. - * @param _assoc The associativity of the cache. - * @param _hit_latency The latency in cycles for a hit. - */ - Split(int _numSets, int _blkSize, int total_ways, int LRU1_assoc, - bool _lifo, bool _two_queue, int _hit_latency); - - /** - * Destructor - */ - virtual ~Split(); - - /** - * Register the stats for this object - * @param name The name to prepend to the stats name. - */ - void regStats(const std::string &name); - - /** - * Return the block size. - * @return the block size. - */ - int getBlockSize() - { - return blkSize; - } - - /** - * Return the subblock size. In the case of Split it is always the block - * size. - * @return The block size. - */ - int getSubBlockSize() - { - return blkSize; - } - - /** - * Search for the address in the cache. - * @param asid The address space ID. - * @param addr The address to find. - * @return True if the address is in the cache. - */ - bool probe(Addr addr) const; - - /** - * Invalidate the given block. - * @param blk The block to invalidate. - */ - void invalidateBlk(BlkType *blk); - - /** - * Finds the given address in the cache and update replacement data. - * Returns the access latency as a side effect. - * @param addr The address to find. - * @param asid The address space ID. - * @param lat The access latency. - * @return Pointer to the cache block if found. - */ - SplitBlk* findBlock(Addr addr, int &lat); - - /** - * Finds the given address in the cache, do not update replacement data. - * @param addr The address to find. - * @param asid The address space ID. - * @return Pointer to the cache block if found. - */ - SplitBlk* findBlock(Addr addr) const; - - /** - * Find a replacement block for the address provided. - * @param pkt The request to a find a replacement candidate for. - * @param writebacks List for any writebacks to be performed. - * @return The block to place the replacement in. - */ - SplitBlk* findReplacement(Addr addr, PacketList &writebacks); - - - /** - * Generate the tag from the given address. - * @param addr The address to get the tag from. - * @return The tag of the address. - */ - Addr extractTag(Addr addr) const; - - /** - * Calculate the set index from the address. - * @param addr The address to get the set from. - * @return The set index of the address. - */ - int extractSet(Addr addr) const - { - panic("should never call this!\n"); - M5_DUMMY_RETURN - } - - /** - * Get the block offset from an address. - * @param addr The address to get the offset of. - * @return The block offset. - */ - int extractBlkOffset(Addr addr) const - { - return (addr & blkMask); - } - - /** - * Align an address to the block size. - * @param addr the address to align. - * @return The block address. - */ - Addr blkAlign(Addr addr) const - { - return (addr & ~(Addr) (blkMask)); - } - - /** - * Regenerate the block address from the tag. - * @param tag The tag of the block. - * @param set The set of the block. - * @return The block address. - */ - Addr regenerateBlkAddr(Addr tag, int set) const; - - /** - * Return the hit latency. - * @return the hit latency. - */ - int getHitLatency() const - { - return hitLatency; - } - - /** - * Read the data out of the internal storage of the given cache block. - * @param blk The cache block to read. - * @param data The buffer to read the data into. - * @return The cache block's data. - */ - void readData(SplitBlk *blk, uint8_t *data) - { - std::memcpy(data, blk->data, blk->size); - } - - /** - * Write data into the internal storage of the given cache block. Since in - * Split does not store data differently this just needs to update the size. - * @param blk The cache block to write. - * @param data The data to write. - * @param size The number of bytes to write. - * @param writebacks A list for any writebacks to be performed. May be - * needed when writing to a compressed block. - */ - void writeData(SplitBlk *blk, uint8_t *data, int size, - PacketList & writebacks) - { - assert(size <= blkSize); - blk->size = size; - } - - /** - * Called at end of simulation to complete average block reference stats. - */ - virtual void cleanupRefs(); -}; - -#endif diff --git a/src/mem/cache/tags/split_blk.hh b/src/mem/cache/tags/split_blk.hh deleted file mode 100644 index d2efe08df..000000000 --- a/src/mem/cache/tags/split_blk.hh +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Lisa Hsu - */ - -/** - * @file - * Declaration of partitioned tag store cache block class. - */ - -#ifndef __SPLIT_BLK_HH__ -#define __SPLIT_BLK_HH__ - -#include "mem/cache/blk.hh" // base class - -/** - * Split cache block. - */ -class SplitBlk : public CacheBlk { - public: - /** Has this block been touched? Used to aid calculation of warmup time. */ - bool isTouched; - /** Has this block been used after being brought in? (for LIFO partition) */ - bool isUsed; - /** is this blk a NIC block? (i.e. requested by the NIC) */ - bool isNIC; - /** timestamp of the arrival of this block into the cache */ - Tick ts; - /** the previous block in the LIFO partition (brought in before than me) */ - SplitBlk *prev; - /** the next block in the LIFO partition (brought in later than me) */ - SplitBlk *next; - /** which partition this block is in */ - int part; - - SplitBlk() - : isTouched(false), isUsed(false), isNIC(false), ts(0), prev(NULL), next(NULL), - part(0) - {} -}; - -#endif - diff --git a/src/mem/cache/tags/split_lifo.cc b/src/mem/cache/tags/split_lifo.cc deleted file mode 100644 index 3bdc7cae9..000000000 --- a/src/mem/cache/tags/split_lifo.cc +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Lisa Hsu - */ - -/** - * @file - * Definitions of LIFO tag store usable in a partitioned cache. - */ - -#include - -#include "mem/cache/base.hh" -#include "base/intmath.hh" -#include "mem/cache/tags/split_lifo.hh" -#include "sim/core.hh" -#include "base/trace.hh" - -using namespace std; - -SplitBlk* -LIFOSet::findBlk(Addr tag) const -{ - for (SplitBlk *blk = firstIn; blk != NULL; blk = blk->next) { - if (blk->tag == tag && blk->isValid()) { - return blk; - } - } - return NULL; -} - -void -LIFOSet::moveToLastIn(SplitBlk *blk) -{ - if (blk == lastIn) - return; - - if (blk == firstIn) { - blk->next->prev = NULL; - } else { - blk->prev->next = blk->next; - blk->next->prev = blk->prev; - } - blk->next = NULL; - blk->prev = lastIn; - lastIn->next = blk; - - lastIn = blk; -} - -void -LIFOSet::moveToFirstIn(SplitBlk *blk) -{ - if (blk == firstIn) - return; - - if (blk == lastIn) { - blk->prev->next = NULL; - } else { - blk->next->prev = blk->prev; - blk->prev->next = blk->next; - } - - blk->prev = NULL; - blk->next = firstIn; - firstIn->prev = blk; - - firstIn = blk; -} - -// create and initialize a LIFO cache structure -SplitLIFO::SplitLIFO(int _blkSize, int _size, int _ways, int _hit_latency, bool two_Queue, int _part) : - blkSize(_blkSize), size(_size), numBlks(_size/_blkSize), numSets((_size/_ways)/_blkSize), ways(_ways), - hitLatency(_hit_latency), twoQueue(two_Queue), part(_part) -{ - if (!isPowerOf2(blkSize)) - fatal("cache block size (in bytes) must be a power of 2"); - if (!(hitLatency > 0)) - fatal("access latency in cycles must be at least on cycle"); - if (_ways == 0) - fatal("if instantiating a splitLIFO, needs non-zero size!"); - - - SplitBlk *blk; - int i, j, blkIndex; - - setShift = floorLog2(blkSize); - blkMask = blkSize - 1; - setMask = numSets - 1; - tagShift = setShift + floorLog2(numSets); - - warmedUp = false; - /** @todo Make warmup percentage a parameter. */ - warmupBound = size/blkSize; - - // allocate data blocks - blks = new SplitBlk[numBlks]; - sets = new LIFOSet[numSets]; - dataBlks = new uint8_t[size]; - -/* - // these start off point to same blk - top = &(blks[0]); - head = top; -*/ - - blkIndex = 0; - for (i=0; i < numSets; ++i) { - sets[i].ways = ways; - sets[i].lastIn = &blks[blkIndex]; - sets[i].firstIn = &blks[blkIndex + ways - 1]; - - /* 3 cases: if there is 1 way, if there are 2 ways, or if there are 3+. - in the case of 1 way, last in and first out point to the same blocks, - and the next and prev pointers need to be assigned specially. and so on - */ - /* deal with the first way */ - blk = &blks[blkIndex]; - blk->prev = &blks[blkIndex + 1]; - blk->next = NULL; - blk->data = &dataBlks[blkSize*blkIndex]; - blk->size = blkSize; - blk->part = part; - blk->set = i; - ++blkIndex; - - /* if there are "middle" ways, do them here */ - if (ways > 2) { - for (j=1; j < ways-1; ++j) { - blk = &blks[blkIndex]; - blk->data = &dataBlks[blkSize*blkIndex]; - blk->prev = &blks[blkIndex+1]; - blk->next = &blks[blkIndex-1]; - blk->data = &(dataBlks[blkSize*blkIndex]); - blk->size = blkSize; - blk->part = part; - blk->set = i; - ++blkIndex; - } - } - - /* do the final way here, depending on whether the final way is the only - way or not - */ - if (ways > 1) { - blk = &blks[blkIndex]; - blk->prev = NULL; - blk->next = &blks[blkIndex - 1]; - blk->data = &dataBlks[blkSize*blkIndex]; - blk->size = blkSize; - blk->part = part; - blk->set = i; - ++blkIndex; - } else { - blk->prev = NULL; - } - } - assert(blkIndex == numBlks); -} - -SplitLIFO::~SplitLIFO() -{ - delete [] blks; - delete [] sets; - delete [] dataBlks; -} - -void -SplitLIFO::regStats(const std::string &name) -{ - BaseTags::regStats(name); - - hits - .name(name + ".hits") - .desc("number of hits on this partition") - .precision(0) - ; - - misses - .name(name + ".misses") - .desc("number of misses in this partition") - .precision(0) - ; - - invalidations - .name(name + ".invalidations") - .desc("number of invalidations in this partition") - .precision(0) - ; -} - -// probe cache for presence of given block. -bool -SplitLIFO::probe(Addr addr) const -{ - Addr tag = extractTag(addr); - unsigned myset = extractSet(addr); - - SplitBlk* blk = sets[myset].findBlk(tag); - return (blk != NULL); -} - -SplitBlk* -SplitLIFO::findBlock(Addr addr, int &lat) -{ - Addr tag = extractTag(addr); - unsigned set = extractSet(addr); - SplitBlk *blk = sets[set].findBlk(tag); - - lat = hitLatency; - - if (blk) { - DPRINTF(Split, "Found LIFO blk %#x in set %d, with tag %#x\n", - addr, set, tag); - hits++; - - if (blk->whenReady > curTick && blk->whenReady - curTick > hitLatency) - lat = blk->whenReady - curTick; - blk->refCount +=1; - - if (twoQueue) { - blk->isUsed = true; - sets[set].moveToFirstIn(blk); - } else { - sets[set].moveToLastIn(blk); - } - } - - return blk; -} - - -SplitBlk* -SplitLIFO::findBlock(Addr addr) const -{ - Addr tag = extractTag(addr); - unsigned set = extractSet(addr); - SplitBlk *blk = sets[set].findBlk(tag); - - return blk; -} - -SplitBlk* -SplitLIFO::findReplacement(Addr addr, PacketList &writebacks) -{ - unsigned set = extractSet(addr); - - SplitBlk *firstIn = sets[set].firstIn; - SplitBlk *lastIn = sets[set].lastIn; - - SplitBlk *blk; - if (twoQueue && firstIn->isUsed) { - blk = firstIn; - blk->isUsed = false; - sets[set].moveToLastIn(blk); - } else { - int withValue = sets[set].withValue; - if (withValue == ways) { - blk = lastIn; - } else { - blk = &(sets[set].firstIn[ways - ++withValue]); - } - } - - DPRINTF(Split, "just assigned %#x addr into LIFO, replacing %#x status %#x\n", - addr, regenerateBlkAddr(blk->tag, set), blk->status); - if (blk->isValid()) { - replacements[0]++; - totalRefs += blk->refCount; - ++sampledRefs; - blk->refCount = 0; - } else { - tagsInUse++; - blk->isTouched = true; - if (!warmedUp && tagsInUse.value() >= warmupBound) { - warmedUp = true; - warmupCycle = curTick; - } - } - - misses++; - - return blk; -} - -void -SplitLIFO::invalidateBlk(SplitLIFO::BlkType *blk) -{ - if (blk) { - blk->status = 0; - blk->isTouched = false; - tagsInUse--; - invalidations++; - } -} - -void -SplitLIFO::cleanupRefs() -{ - for (int i = 0; i < numBlks; ++i) { - if (blks[i].isValid()) { - totalRefs += blks[i].refCount; - ++sampledRefs; - } - } -} diff --git a/src/mem/cache/tags/split_lifo.hh b/src/mem/cache/tags/split_lifo.hh deleted file mode 100644 index 0fd5f5c3c..000000000 --- a/src/mem/cache/tags/split_lifo.hh +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Lisa Hsu - */ - -/** - * @file - * Declaration of a LIFO tag store usable in a partitioned cache. - */ - -#ifndef __SPLIT_LIFO_HH__ -#define __SPLIT_LIFO_HH__ - -#include -#include - -#include "mem/cache/blk.hh" // base class -#include "mem/cache/tags/split_blk.hh" -#include "mem/packet.hh" // for inlined functions -#include "base/hashmap.hh" -#include -#include "mem/cache/tags/base.hh" - -class BaseCache; - -/** - * A LIFO set of cache blks - */ -class LIFOSet { - public: - /** the number of blocks in this set */ - int ways; - - /** Cache blocks in this set, maintained in LIFO order where - 0 = Last in (head) */ - SplitBlk *lastIn; - SplitBlk *firstIn; - - /** has the initial "filling" of this set finished? i.e., have you had - * 'ways' number of compulsory misses in this set yet? if withValue == ways, - * then yes. withValue is meant to be the number of blocks in the set that have - * gone through their first compulsory miss. - */ - int withValue; - - /** - * Find a block matching the tag in this set. - * @param asid The address space ID. - * @param tag the Tag you are looking for - * @return Pointer to the block, if found, NULL otherwise - */ - SplitBlk* findBlk(Addr tag) const; - - void moveToLastIn(SplitBlk *blk); - void moveToFirstIn(SplitBlk *blk); - - LIFOSet() - : ways(-1), lastIn(NULL), firstIn(NULL), withValue(0) - {} -}; - -/** - * A LIFO cache tag store. - */ -class SplitLIFO : public BaseTags -{ - public: - /** Typedef the block type used in this tag store. */ - typedef SplitBlk BlkType; - /** Typedef for a list of pointers to the local block class. */ - typedef std::list BlkList; - protected: - /** The number of bytes in a block. */ - const int blkSize; - /** the size of the cache in bytes */ - const int size; - /** the number of blocks in the cache */ - const int numBlks; - /** the number of sets in the cache */ - const int numSets; - /** the number of ways in the cache */ - const int ways; - /** The hit latency. */ - const int hitLatency; - /** whether this is a "2 queue" replacement @sa moveToLastIn @sa moveToFirstIn */ - const bool twoQueue; - /** indicator for which partition this is */ - const int part; - - /** The cache blocks. */ - SplitBlk *blks; - /** The Cache sets */ - LIFOSet *sets; - /** The data blocks, 1 per cache block. */ - uint8_t *dataBlks; - - /** The amount to shift the address to get the set. */ - int setShift; - /** The amount to shift the address to get the tag. */ - int tagShift; - /** Mask out all bits that aren't part of the set index. */ - unsigned setMask; - /** Mask out all bits that aren't part of the block offset. */ - unsigned blkMask; - - - /** the number of hit in this partition */ - Stats::Scalar<> hits; - /** the number of blocks brought into this partition (i.e. misses) */ - Stats::Scalar<> misses; - /** the number of invalidations in this partition */ - Stats::Scalar<> invalidations; - -public: - /** - * Construct and initialize this tag store. - * @param _numSets The number of sets in the cache. - * @param _blkSize The number of bytes in a block. - * @param _assoc The associativity of the cache. - * @param _hit_latency The latency in cycles for a hit. - */ - SplitLIFO(int _blkSize, int _size, int _ways, int _hit_latency, bool twoQueue, int _part); - - /** - * Destructor - */ - virtual ~SplitLIFO(); - - /** - * Register the statistics for this object - * @param name The name to precede the stat - */ - void regStats(const std::string &name); - - /** - * Return the block size. - * @return the block size. - */ - int getBlockSize() - { - return blkSize; - } - - /** - * Return the subblock size. In the case of LIFO it is always the block - * size. - * @return The block size. - */ - int getSubBlockSize() - { - return blkSize; - } - - /** - * Search for the address in the cache. - * @param asid The address space ID. - * @param addr The address to find. - * @return True if the address is in the cache. - */ - bool probe( Addr addr) const; - - /** - * Invalidate the given block. - * @param blk The block to invalidate. - */ - void invalidateBlk(BlkType *blk); - - /** - * Finds the given address in the cache and update replacement data. - * Returns the access latency as a side effect. - * @param addr The address to find. - * @param asid The address space ID. - * @param lat The access latency. - * @return Pointer to the cache block if found. - */ - SplitBlk* findBlock(Addr addr, int &lat); - - /** - * Finds the given address in the cache, do not update replacement data. - * @param addr The address to find. - * @param asid The address space ID. - * @return Pointer to the cache block if found. - */ - SplitBlk* findBlock(Addr addr) const; - - /** - * Find a replacement block for the address provided. - * @param pkt The request to a find a replacement candidate for. - * @param writebacks List for any writebacks to be performed. - * @return The block to place the replacement in. - */ - SplitBlk* findReplacement(Addr addr, PacketList &writebacks); - - /** - * Generate the tag from the given address. - * @param addr The address to get the tag from. - * @return The tag of the address. - */ - Addr extractTag(Addr addr) const - { - return (addr >> tagShift); - } - - /** - * Calculate the set index from the address. - * @param addr The address to get the set from. - * @return The set index of the address. - */ - int extractSet(Addr addr) const - { - return ((addr >> setShift) & setMask); - } - - /** - * Get the block offset from an address. - * @param addr The address to get the offset of. - * @return The block offset. - */ - int extractBlkOffset(Addr addr) const - { - return (addr & blkMask); - } - - /** - * Align an address to the block size. - * @param addr the address to align. - * @return The block address. - */ - Addr blkAlign(Addr addr) const - { - return (addr & ~(Addr)blkMask); - } - - /** - * Regenerate the block address from the tag. - * @param tag The tag of the block. - * @param set The set of the block. - * @return The block address. - */ - Addr regenerateBlkAddr(Addr tag, unsigned set) const - { - return ((tag << tagShift) | ((Addr)set << setShift)); - } - - /** - * Return the hit latency. - * @return the hit latency. - */ - int getHitLatency() const - { - return hitLatency; - } - - /** - * Read the data out of the internal storage of the given cache block. - * @param blk The cache block to read. - * @param data The buffer to read the data into. - * @return The cache block's data. - */ - void readData(SplitBlk *blk, uint8_t *data) - { - std::memcpy(data, blk->data, blk->size); - } - - /** - * Write data into the internal storage of the given cache block. Since in - * LIFO does not store data differently this just needs to update the size. - * @param blk The cache block to write. - * @param data The data to write. - * @param size The number of bytes to write. - * @param writebacks A list for any writebacks to be performed. May be - * needed when writing to a compressed block. - */ - void writeData(SplitBlk *blk, uint8_t *data, int size, - PacketList & writebacks) - { - assert(size <= blkSize); - blk->size = size; - } - - /** - * Called at end of simulation to complete average block reference stats. - */ - virtual void cleanupRefs(); -}; - -#endif diff --git a/src/mem/cache/tags/split_lru.cc b/src/mem/cache/tags/split_lru.cc deleted file mode 100644 index 2b01b07cd..000000000 --- a/src/mem/cache/tags/split_lru.cc +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Lisa Hsu - */ - -/** - * @file - * Definitions of LRU tag store for a partitioned cache. - */ - -#include - -#include "mem/cache/base.hh" -#include "base/intmath.hh" -#include "mem/cache/tags/split_lru.hh" -#include "sim/core.hh" - -using namespace std; - -SplitBlk* -SplitCacheSet::findBlk(Addr tag) const -{ - for (int i = 0; i < assoc; ++i) { - if (blks[i]->tag == tag && blks[i]->isValid()) { - return blks[i]; - } - } - return 0; -} - - -void -SplitCacheSet::moveToHead(SplitBlk *blk) -{ - // nothing to do if blk is already head - if (blks[0] == blk) - return; - - // write 'next' block into blks[i], moving up from MRU toward LRU - // until we overwrite the block we moved to head. - - // start by setting up to write 'blk' into blks[0] - int i = 0; - SplitBlk *next = blk; - - do { - assert(i < assoc); - // swap blks[i] and next - SplitBlk *tmp = blks[i]; - blks[i] = next; - next = tmp; - ++i; - } while (next != blk); -} - - -// create and initialize a LRU/MRU cache structure -SplitLRU::SplitLRU(int _numSets, int _blkSize, int _assoc, int _hit_latency, int _part) : - numSets(_numSets), blkSize(_blkSize), assoc(_assoc), hitLatency(_hit_latency), part(_part) -{ - // Check parameters - if (blkSize < 4 || !isPowerOf2(blkSize)) { - fatal("Block size must be at least 4 and a power of 2"); - } - if (numSets <= 0 || !isPowerOf2(numSets)) { - fatal("# of sets must be non-zero and a power of 2"); - } - if (assoc <= 0) { - fatal("associativity must be greater than zero"); - } - if (hitLatency <= 0) { - fatal("access latency must be greater than zero"); - } - - SplitBlk *blk; - int i, j, blkIndex; - - blkMask = blkSize - 1; - setShift = floorLog2(blkSize); - setMask = numSets - 1; - tagShift = setShift + floorLog2(numSets); - warmedUp = false; - /** @todo Make warmup percentage a parameter. */ - warmupBound = numSets * assoc; - - sets = new SplitCacheSet[numSets]; - blks = new SplitBlk[numSets * assoc]; - // allocate data storage in one big chunk - dataBlks = new uint8_t[numSets*assoc*blkSize]; - - blkIndex = 0; // index into blks array - for (i = 0; i < numSets; ++i) { - sets[i].assoc = assoc; - - sets[i].blks = new SplitBlk*[assoc]; - - // link in the data blocks - for (j = 0; j < assoc; ++j) { - // locate next cache block - blk = &blks[blkIndex]; - blk->data = &dataBlks[blkSize*blkIndex]; - ++blkIndex; - - // invalidate new cache block - blk->status = 0; - - //EGH Fix Me : do we need to initialize blk? - - // Setting the tag to j is just to prevent long chains in the hash - // table; won't matter because the block is invalid - blk->tag = j; - blk->whenReady = 0; - blk->isTouched = false; - blk->size = blkSize; - sets[i].blks[j]=blk; - blk->set = i; - blk->part = part; - } - } -} - -SplitLRU::~SplitLRU() -{ - delete [] dataBlks; - delete [] blks; - delete [] sets; -} - -void -SplitLRU::regStats(const std::string &name) -{ - BaseTags::regStats(name); - - hits - .name(name + ".hits") - .desc("number of hits on this partition") - .precision(0) - ; - - misses - .name(name + ".misses") - .desc("number of misses in this partition") - .precision(0) - ; -} - -// probe cache for presence of given block. -bool -SplitLRU::probe(Addr addr) const -{ - // return(findBlock(Read, addr, asid) != 0); - Addr tag = extractTag(addr); - unsigned myset = extractSet(addr); - - SplitBlk *blk = sets[myset].findBlk(tag); - - return (blk != NULL); // true if in cache -} - -SplitBlk* -SplitLRU::findBlock(Addr addr, int &lat) -{ - Addr tag = extractTag(addr); - unsigned set = extractSet(addr); - SplitBlk *blk = sets[set].findBlk(tag); - lat = hitLatency; - if (blk != NULL) { - // move this block to head of the MRU list - sets[set].moveToHead(blk); - if (blk->whenReady > curTick && blk->whenReady - curTick > hitLatency){ - lat = blk->whenReady - curTick; - } - blk->refCount += 1; - hits++; - } - - return blk; -} - - -SplitBlk* -SplitLRU::findBlock(Addr addr) const -{ - Addr tag = extractTag(addr); - unsigned set = extractSet(addr); - SplitBlk *blk = sets[set].findBlk(tag); - return blk; -} - -SplitBlk* -SplitLRU::findReplacement(Addr addr, PacketList &writebacks) -{ - unsigned set = extractSet(addr); - // grab a replacement candidate - SplitBlk *blk = sets[set].blks[assoc-1]; - sets[set].moveToHead(blk); - if (blk->isValid()) { - replacements[0]++; - totalRefs += blk->refCount; - ++sampledRefs; - blk->refCount = 0; - } else if (!blk->isTouched) { - tagsInUse++; - blk->isTouched = true; - if (!warmedUp && tagsInUse.value() >= warmupBound) { - warmedUp = true; - warmupCycle = curTick; - } - } - - misses++; - - return blk; -} - -void -SplitLRU::invalidateBlk(SplitLRU::BlkType *blk) -{ - if (blk) { - blk->status = 0; - blk->isTouched = false; - tagsInUse--; - } -} - -void -SplitLRU::cleanupRefs() -{ - for (int i = 0; i < numSets*assoc; ++i) { - if (blks[i].isValid()) { - totalRefs += blks[i].refCount; - ++sampledRefs; - } - } -} diff --git a/src/mem/cache/tags/split_lru.hh b/src/mem/cache/tags/split_lru.hh deleted file mode 100644 index d41b6efa7..000000000 --- a/src/mem/cache/tags/split_lru.hh +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Lisa Hsu - */ - -/** - * @file - * Declaration of a LRU tag store for a partitioned cache. - */ - -#ifndef __SPLIT_LRU_HH__ -#define __SPLIT_LRU_HH__ - -#include -#include - -#include "mem/cache/blk.hh" // base class -#include "mem/cache/tags/split_blk.hh" -#include "mem/packet.hh" // for inlined functions -#include -#include "mem/cache/tags/base.hh" - -class BaseCache; - -/** - * An associative set of cache blocks. - */ - -class SplitCacheSet -{ - public: - /** The associativity of this set. */ - int assoc; - - /** Cache blocks in this set, maintained in LRU order 0 = MRU. */ - SplitBlk **blks; - - /** - * Find a block matching the tag in this set. - * @param asid The address space ID. - * @param tag The Tag to find. - * @return Pointer to the block if found. - */ - SplitBlk* findBlk(Addr tag) const; - - /** - * Move the given block to the head of the list. - * @param blk The block to move. - */ - void moveToHead(SplitBlk *blk); -}; - -/** - * A LRU cache tag store. - */ -class SplitLRU : public BaseTags -{ - public: - /** Typedef the block type used in this tag store. */ - typedef SplitBlk BlkType; - /** Typedef for a list of pointers to the local block class. */ - typedef std::list BlkList; - protected: - /** The number of sets in the cache. */ - const int numSets; - /** The number of bytes in a block. */ - const int blkSize; - /** The associativity of the cache. */ - const int assoc; - /** The hit latency. */ - const int hitLatency; - /** indicator for which partition this is */ - const int part; - - /** The cache sets. */ - SplitCacheSet *sets; - - /** The cache blocks. */ - SplitBlk *blks; - /** The data blocks, 1 per cache block. */ - uint8_t *dataBlks; - - /** The amount to shift the address to get the set. */ - int setShift; - /** The amount to shift the address to get the tag. */ - int tagShift; - /** Mask out all bits that aren't part of the set index. */ - unsigned setMask; - /** Mask out all bits that aren't part of the block offset. */ - unsigned blkMask; - - /** number of hits in this partition */ - Stats::Scalar<> hits; - /** number of blocks brought into this partition (i.e. misses) */ - Stats::Scalar<> misses; - -public: - /** - * Construct and initialize this tag store. - * @param _numSets The number of sets in the cache. - * @param _blkSize The number of bytes in a block. - * @param _assoc The associativity of the cache. - * @param _hit_latency The latency in cycles for a hit. - */ - SplitLRU(int _numSets, int _blkSize, int _assoc, int _hit_latency, int _part); - - /** - * Destructor - */ - virtual ~SplitLRU(); - - /** - * Register the statistics for this object - * @param name The name to precede the stat - */ - void regStats(const std::string &name); - - /** - * Return the block size. - * @return the block size. - */ - int getBlockSize() - { - return blkSize; - } - - /** - * Return the subblock size. In the case of LRU it is always the block - * size. - * @return The block size. - */ - int getSubBlockSize() - { - return blkSize; - } - - /** - * Search for the address in the cache. - * @param asid The address space ID. - * @param addr The address to find. - * @return True if the address is in the cache. - */ - bool probe(Addr addr) const; - - /** - * Invalidate the given block. - * @param blk The block to invalidate. - */ - void invalidateBlk(BlkType *blk); - - /** - * Finds the given address in the cache and update replacement data. - * Returns the access latency as a side effect. - * @param addr The address to find. - * @param asid The address space ID. - * @param lat The access latency. - * @return Pointer to the cache block if found. - */ - SplitBlk* findBlock(Addr addr, int &lat); - - /** - * Finds the given address in the cache, do not update replacement data. - * @param addr The address to find. - * @param asid The address space ID. - * @return Pointer to the cache block if found. - */ - SplitBlk* findBlock(Addr addr) const; - - /** - * Find a replacement block for the address provided. - * @param pkt The request to a find a replacement candidate for. - * @param writebacks List for any writebacks to be performed. - * @return The block to place the replacement in. - */ - SplitBlk* findReplacement(Addr addr, PacketList &writebacks); - - /** - * Generate the tag from the given address. - * @param addr The address to get the tag from. - * @return The tag of the address. - */ - Addr extractTag(Addr addr) const - { - return (addr >> tagShift); - } - - /** - * Calculate the set index from the address. - * @param addr The address to get the set from. - * @return The set index of the address. - */ - int extractSet(Addr addr) const - { - return ((addr >> setShift) & setMask); - } - - /** - * Get the block offset from an address. - * @param addr The address to get the offset of. - * @return The block offset. - */ - int extractBlkOffset(Addr addr) const - { - return (addr & blkMask); - } - - /** - * Align an address to the block size. - * @param addr the address to align. - * @return The block address. - */ - Addr blkAlign(Addr addr) const - { - return (addr & ~(Addr)blkMask); - } - - /** - * Regenerate the block address from the tag. - * @param tag The tag of the block. - * @param set The set of the block. - * @return The block address. - */ - Addr regenerateBlkAddr(Addr tag, unsigned set) const - { - return ((tag << tagShift) | ((Addr)set << setShift)); - } - - /** - * Return the hit latency. - * @return the hit latency. - */ - int getHitLatency() const - { - return hitLatency; - } - - /** - * Read the data out of the internal storage of the given cache block. - * @param blk The cache block to read. - * @param data The buffer to read the data into. - * @return The cache block's data. - */ - void readData(SplitBlk *blk, uint8_t *data) - { - std::memcpy(data, blk->data, blk->size); - } - - /** - * Write data into the internal storage of the given cache block. Since in - * LRU does not store data differently this just needs to update the size. - * @param blk The cache block to write. - * @param data The data to write. - * @param size The number of bytes to write. - * @param writebacks A list for any writebacks to be performed. May be - * needed when writing to a compressed block. - */ - void writeData(SplitBlk *blk, uint8_t *data, int size, - PacketList & writebacks) - { - assert(size <= blkSize); - blk->size = size; - } - - /** - * Called at end of simulation to complete average block reference stats. - */ - virtual void cleanupRefs(); -}; - -#endif diff --git a/src/mem/config/cache.hh b/src/mem/config/cache.hh index 24da04021..946ed444f 100644 --- a/src/mem/config/cache.hh +++ b/src/mem/config/cache.hh @@ -36,7 +36,4 @@ */ #define USE_CACHE_LRU 1 #define USE_CACHE_FALRU 1 -// #define USE_CACHE_SPLIT 1 -// #define USE_CACHE_SPLIT_LIFO 1 #define USE_CACHE_IIC 1 - -- cgit v1.2.3 From 546a6c0c1b6dfc23bac1f74c6adec413931c6608 Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Thu, 23 Oct 2008 16:49:13 -0400 Subject: probe function no longer used anywhere. --- src/mem/cache/cache.hh | 1 - src/mem/cache/tags/fa_lru.cc | 8 -------- src/mem/cache/tags/fa_lru.hh | 8 -------- src/mem/cache/tags/iic.cc | 6 ------ src/mem/cache/tags/iic.hh | 8 -------- src/mem/cache/tags/lru.cc | 13 ------------- src/mem/cache/tags/lru.hh | 8 -------- 7 files changed, 52 deletions(-) (limited to 'src') diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh index cff3fd28b..510e67ba6 100644 --- a/src/mem/cache/cache.hh +++ b/src/mem/cache/cache.hh @@ -172,7 +172,6 @@ class Cache : public BaseCache * Populates a cache block and handles all outstanding requests for the * satisfied fill request. This version takes two memory requests. One * contains the fill data, the other is an optional target to satisfy. - * Used for Cache::probe. * @param pkt The memory request with the fill data. * @param blk The cache block if it already exists. * @param writebacks List for any writebacks that need to be performed. diff --git a/src/mem/cache/tags/fa_lru.cc b/src/mem/cache/tags/fa_lru.cc index 607e89a75..8a2f4eb13 100644 --- a/src/mem/cache/tags/fa_lru.cc +++ b/src/mem/cache/tags/fa_lru.cc @@ -144,14 +144,6 @@ FALRU::hashLookup(Addr addr) const return NULL; } -bool -FALRU::probe(Addr addr) const -{ - Addr blkAddr = blkAlign(addr); - FALRUBlk* blk = hashLookup(blkAddr); - return blk && blk->tag == blkAddr && blk->isValid(); -} - void FALRU::invalidateBlk(FALRU::BlkType *blk) { diff --git a/src/mem/cache/tags/fa_lru.hh b/src/mem/cache/tags/fa_lru.hh index cabcf18b4..43b3b5832 100644 --- a/src/mem/cache/tags/fa_lru.hh +++ b/src/mem/cache/tags/fa_lru.hh @@ -164,14 +164,6 @@ public: */ void regStats(const std::string &name); - /** - * Return true if the address is found in the cache. - * @param asid The address space ID. - * @param addr The address to look for. - * @return True if the address is in the cache. - */ - bool probe(Addr addr) const; - /** * Invalidate a cache block. * @param blk The block to invalidate. diff --git a/src/mem/cache/tags/iic.cc b/src/mem/cache/tags/iic.cc index af9a75d43..31fd87df6 100644 --- a/src/mem/cache/tags/iic.cc +++ b/src/mem/cache/tags/iic.cc @@ -219,12 +219,6 @@ IIC::regStats(const string &name) ; } -// probe cache for presence of given block. -bool -IIC::probe(Addr addr) const -{ - return (findBlock(addr) != NULL); -} IICTag* IIC::findBlock(Addr addr, int &lat) diff --git a/src/mem/cache/tags/iic.hh b/src/mem/cache/tags/iic.hh index c9d080683..0d513cf92 100644 --- a/src/mem/cache/tags/iic.hh +++ b/src/mem/cache/tags/iic.hh @@ -384,14 +384,6 @@ class IIC : public BaseTags return (addr & ~(Addr)blkMask); } - /** - * Check for the address in the tagstore. - * @param asid The address space ID. - * @param addr The address to find. - * @return true if it is found. - */ - bool probe(Addr addr) const; - /** * Swap the position of two tags. * @param index1 The first tag location. diff --git a/src/mem/cache/tags/lru.cc b/src/mem/cache/tags/lru.cc index 7fb5318a0..2a82202e0 100644 --- a/src/mem/cache/tags/lru.cc +++ b/src/mem/cache/tags/lru.cc @@ -150,19 +150,6 @@ LRU::~LRU() delete [] sets; } -// probe cache for presence of given block. -bool -LRU::probe(Addr addr) const -{ - // return(findBlock(Read, addr, asid) != 0); - Addr tag = extractTag(addr); - unsigned myset = extractSet(addr); - - LRUBlk *blk = sets[myset].findBlk(tag); - - return (blk != NULL); // true if in cache -} - LRUBlk* LRU::findBlock(Addr addr, int &lat) { diff --git a/src/mem/cache/tags/lru.hh b/src/mem/cache/tags/lru.hh index 65be492de..39b547f57 100644 --- a/src/mem/cache/tags/lru.hh +++ b/src/mem/cache/tags/lru.hh @@ -153,14 +153,6 @@ public: return blkSize; } - /** - * Search for the address in the cache. - * @param asid The address space ID. - * @param addr The address to find. - * @return True if the address is in the cache. - */ - bool probe(Addr addr) const; - /** * Invalidate the given block. * @param blk The block to invalidate. -- cgit v1.2.3 From 8788d703f81cef20916ffd2c7e0d28031cf65df8 Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Thu, 23 Oct 2008 16:49:17 -0400 Subject: s/cpu_id/cpuId in o3 (to be consistent and match style), also fix some typos in comments. --- src/cpu/o3/cpu.cc | 2 +- src/cpu/o3/cpu.hh | 6 +++--- src/mem/cache/cache.hh | 5 ++--- 3 files changed, 6 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 04f344930..1b7a3a17c 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -62,7 +62,7 @@ class BaseCPUParams; using namespace TheISA; BaseO3CPU::BaseO3CPU(BaseCPUParams *params) - : BaseCPU(params), cpu_id(0) + : BaseCPU(params), cpuId(0) { } diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 8cfc9affa..d1cc8bea5 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -76,13 +76,13 @@ class BaseO3CPU : public BaseCPU void regStats(); /** Sets this CPU's ID. */ - void setCpuId(int id) { cpu_id = id; } + void setCpuId(int id) { cpuId = id; } /** Reads this CPU's ID. */ - int readCpuId() { return cpu_id; } + int readCpuId() { return cpuId; } protected: - int cpu_id; + int cpuId; }; /** diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh index 510e67ba6..4db5230f8 100644 --- a/src/mem/cache/cache.hh +++ b/src/mem/cache/cache.hh @@ -137,7 +137,7 @@ class Cache : public BaseCache BlkType *tempBlock; /** - * Can this cache should allocate a block on a line-sized write miss. + * This cache should allocate a block on a line-sized write miss. */ const bool doFastWrites; @@ -149,8 +149,7 @@ class Cache : public BaseCache * @param lat The latency of the access. * @param writebacks List for any writebacks that need to be performed. * @param update True if the replacement data should be updated. - * @return Pointer to the cache block touched by the request. NULL if it - * was a miss. + * @return Boolean indicating whether the request was satisfied. */ bool access(PacketPtr pkt, BlkType *&blk, int &lat, PacketList &writebacks); -- cgit v1.2.3 From cfa32d8de737847f04bfa6e5e89375c870c3869b Mon Sep 17 00:00:00 2001 From: Clint Smullen Date: Mon, 27 Oct 2008 19:46:01 -0400 Subject: Checkpointing: createCountedDrain function, it was only returning an Event, which does not expose a setCount method to Python. Signed-off By: Ali Saidi --- src/python/swig/pyevent.cc | 2 +- src/python/swig/pyevent.hh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/python/swig/pyevent.cc b/src/python/swig/pyevent.cc index bf993bc3e..a201e0185 100644 --- a/src/python/swig/pyevent.cc +++ b/src/python/swig/pyevent.cc @@ -67,7 +67,7 @@ PythonEvent::process() } } -Event * +CountedDrainEvent * createCountedDrain() { return new CountedDrainEvent(); diff --git a/src/python/swig/pyevent.hh b/src/python/swig/pyevent.hh index c6d6ac993..22b562de1 100644 --- a/src/python/swig/pyevent.hh +++ b/src/python/swig/pyevent.hh @@ -46,7 +46,7 @@ class PythonEvent : public Event virtual void process(); }; -Event *createCountedDrain(); +CountedDrainEvent *createCountedDrain(); void cleanupCountedDrain(Event *counted_drain); #endif // __PYTHON_SWIG_PYEVENT_HH__ -- cgit v1.2.3 From 95af120e601671e6819ca97b78a1879d4ab0d853 Mon Sep 17 00:00:00 2001 From: Clint Smullen Date: Mon, 27 Oct 2008 18:18:04 -0400 Subject: CPU: The API change to EventWrapper did not get propagated to the entirety of TimingSimpleCPU. The constructor no-longer schedules an event at construction and the implict conversion between int and bool was allowing the old code to compile without warning. Signed-off By: Ali Saidi --- src/cpu/simple/timing.cc | 17 +++++------------ src/cpu/simple/timing.hh | 2 +- 2 files changed, 6 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 0cda9a0a3..a6059f55f 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -105,7 +105,7 @@ TimingSimpleCPU::CpuPort::TickEvent::schedule(PacketPtr _pkt, Tick t) } TimingSimpleCPU::TimingSimpleCPU(TimingSimpleCPUParams *p) - : BaseSimpleCPU(p), icachePort(this, p->clock), dcachePort(this, p->clock) + : BaseSimpleCPU(p), icachePort(this, p->clock), dcachePort(this, p->clock), fetchEvent(this) { _status = Idle; @@ -114,7 +114,6 @@ TimingSimpleCPU::TimingSimpleCPU(TimingSimpleCPUParams *p) ifetch_pkt = dcache_pkt = NULL; drainEvent = NULL; - fetchEvent = NULL; previousTick = 0; changeState(SimObject::Running); } @@ -162,15 +161,10 @@ TimingSimpleCPU::resume() if (_status != SwitchedOut && _status != Idle) { assert(system->getMemoryMode() == Enums::timing); - // Delete the old event if it existed. - if (fetchEvent) { - if (fetchEvent->scheduled()) - deschedule(fetchEvent); + if (fetchEvent.scheduled()) + deschedule(fetchEvent); - delete fetchEvent; - } - - fetchEvent = new FetchEvent(this, nextCycle()); + schedule(fetchEvent, nextCycle()); } changeState(SimObject::Running); @@ -185,7 +179,7 @@ TimingSimpleCPU::switchOut() // If we've been scheduled to resume but are then told to switch out, // we'll need to cancel it. - if (fetchEvent && fetchEvent->scheduled()) + if (fetchEvent.scheduled()) deschedule(fetchEvent); } @@ -228,7 +222,6 @@ TimingSimpleCPU::activateContext(int thread_num, int delay) _status = Running; // kick things off by initiating the fetch of the next instruction - fetchEvent = new FetchEvent(this); schedule(fetchEvent, nextCycle(curTick + ticks(delay))); } diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index 081051ea7..0fc9b3152 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -192,7 +192,7 @@ class TimingSimpleCPU : public BaseSimpleCPU private: typedef EventWrapper FetchEvent; - FetchEvent *fetchEvent; + FetchEvent fetchEvent; struct IprEvent : Event { Packet *pkt; -- cgit v1.2.3 From c55a467a06eaa59c47c52a2adddc266b8e545589 Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Sun, 2 Nov 2008 21:56:57 -0500 Subject: make BaseCPU the provider of _cpuId, and cpuId() instead of being scattered across the subclasses. generally make it so that member data is _cpuId and accessor functions are cpuId(). The ID val comes from the python (default -1 if none provided), and if it is -1, the index of cpuList will be given. this has passed util/regress quick and se.py -n4 and fs.py -n4 as well as standard switch. --- src/arch/alpha/locked_mem.hh | 2 +- src/arch/mips/locked_mem.hh | 2 +- src/arch/sparc/ua2005.cc | 6 +++--- src/arch/x86/tlb.cc | 2 +- src/cpu/BaseCPU.py | 2 +- src/cpu/base.cc | 28 +++++++++++++++++----------- src/cpu/base.hh | 8 ++++++++ src/cpu/base_dyn_inst.hh | 10 +++++----- src/cpu/checker/cpu_impl.hh | 2 +- src/cpu/checker/thread_context.hh | 2 +- src/cpu/o3/cpu.cc | 5 ++--- src/cpu/o3/cpu.hh | 9 --------- src/cpu/o3/fetch_impl.hh | 2 +- src/cpu/o3/thread_context.hh | 5 +---- src/cpu/o3/thread_context_impl.hh | 1 - src/cpu/o3/thread_state.hh | 4 ++-- src/cpu/ozone/cpu.hh | 10 ---------- src/cpu/ozone/cpu_impl.hh | 4 ++-- src/cpu/ozone/front_end_impl.hh | 2 +- src/cpu/simple/atomic.cc | 16 +++++++--------- src/cpu/simple/base.hh | 1 - src/cpu/simple/timing.cc | 15 +++++++-------- src/cpu/simple_thread.cc | 9 ++++----- src/cpu/thread_context.cc | 4 ++-- src/cpu/thread_context.hh | 8 ++------ src/cpu/thread_state.cc | 8 ++++---- src/cpu/thread_state.hh | 14 ++++---------- src/sim/system.cc | 11 +++++------ src/sim/system.hh | 2 +- 29 files changed, 84 insertions(+), 110 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/locked_mem.hh b/src/arch/alpha/locked_mem.hh index f629d982a..6f4f5a748 100644 --- a/src/arch/alpha/locked_mem.hh +++ b/src/arch/alpha/locked_mem.hh @@ -87,7 +87,7 @@ handleLockedWrite(XC *xc, Request *req) if (stCondFailures % 100000 == 0) { warn("cpu %d: %d consecutive " "store conditional failures\n", - xc->readCpuId(), stCondFailures); + xc->cpuId(), stCondFailures); } // store conditional failed already, so don't issue it to mem diff --git a/src/arch/mips/locked_mem.hh b/src/arch/mips/locked_mem.hh index 07dc9d588..5877b1439 100644 --- a/src/arch/mips/locked_mem.hh +++ b/src/arch/mips/locked_mem.hh @@ -85,7 +85,7 @@ handleLockedWrite(XC *xc, Request *req) if (stCondFailures % 10 == 0) { warn("%i: cpu %d: %d consecutive " "store conditional failures\n", - curTick, xc->readCpuId(), stCondFailures); + curTick, xc->cpuId(), stCondFailures); } if (stCondFailures == 5000) { diff --git a/src/arch/sparc/ua2005.cc b/src/arch/sparc/ua2005.cc index e1276b812..6961a24e9 100644 --- a/src/arch/sparc/ua2005.cc +++ b/src/arch/sparc/ua2005.cc @@ -257,11 +257,11 @@ MiscRegFile::readFSReg(int miscReg, ThreadContext * tc) temp = readRegNoEffect(miscReg) & (STS::active | STS::speculative); // Check that the CPU array is fully populated // (by calling getNumCPus()) - assert(sys->getNumCPUs() > tc->readCpuId()); + assert(sys->getNumCPUs() > tc->cpuId()); - temp |= tc->readCpuId() << STS::shft_id; + temp |= tc->cpuId() << STS::shft_id; - for (x = tc->readCpuId() & ~3; x < sys->threadContexts.size(); x++) { + for (x = tc->cpuId() & ~3; x < sys->threadContexts.size(); x++) { switch (sys->threadContexts[x]->status()) { case ThreadContext::Active: temp |= STS::st_run << (STS::shft_fsm0 - diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index 5db678919..17374fa0c 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -654,7 +654,7 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) */ // Force the access to be uncacheable. req->setFlags(req->getFlags() | UNCACHEABLE); - req->setPaddr(x86LocalAPICAddress(tc->readCpuId(), paddr - baseAddr)); + req->setPaddr(x86LocalAPICAddress(tc->cpuId(), paddr - baseAddr)); } #endif return NoFault; diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py index ef9b54f3f..f98c6af8e 100644 --- a/src/cpu/BaseCPU.py +++ b/src/cpu/BaseCPU.py @@ -63,7 +63,7 @@ class BaseCPU(MemObject): abstract = True system = Param.System(Parent.any, "system object") - cpu_id = Param.Int("CPU identifier") + cpu_id = Param.Int(-1, "CPU identifier") numThreads = Param.Unsigned(1, "number of HW thread contexts") function_trace = Param.Bool(False, "Enable function trace") diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 8c461cccb..3e899d993 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -94,21 +94,29 @@ CPUProgressEvent::description() const #if FULL_SYSTEM BaseCPU::BaseCPU(Params *p) - : MemObject(p), clock(p->clock), instCnt(0), interrupts(p->interrupts), + : MemObject(p), clock(p->clock), instCnt(0), _cpuId(p->cpu_id), + interrupts(p->interrupts), number_of_threads(p->numThreads), system(p->system), phase(p->phase) #else BaseCPU::BaseCPU(Params *p) - : MemObject(p), clock(p->clock), + : MemObject(p), clock(p->clock), _cpuId(p->cpu_id), number_of_threads(p->numThreads), system(p->system), phase(p->phase) #endif { // currentTick = curTick; + // if Python did not provide a valid ID, do it here + if (_cpuId == -1 ) { + _cpuId = cpuList.size(); + } + // add self to global list of CPUs cpuList.push_back(this); + DPRINTF(SyscallVerbose, "Constructing CPU with id %d\n", _cpuId); + if (number_of_threads > maxThreadsPerCPU) maxThreadsPerCPU = number_of_threads; @@ -278,13 +286,9 @@ BaseCPU::registerThreadContexts() ThreadContext *tc = threadContexts[i]; #if FULL_SYSTEM - int id = params()->cpu_id; - if (id != -1) - id += i; - - tc->setCpuId(system->registerThreadContext(tc, id)); + system->registerThreadContext(tc); #else - tc->setCpuId(tc->getProcessPtr()->registerThreadContext(tc)); + tc->getProcessPtr()->registerThreadContext(tc); #endif } } @@ -315,6 +319,8 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc) { assert(threadContexts.size() == oldCPU->threadContexts.size()); + _cpuId = oldCPU->cpuId(); + for (int i = 0; i < threadContexts.size(); ++i) { ThreadContext *newTC = threadContexts[i]; ThreadContext *oldTC = oldCPU->threadContexts[i]; @@ -323,12 +329,12 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc) CpuEvent::replaceThreadContext(oldTC, newTC); - assert(newTC->readCpuId() == oldTC->readCpuId()); + assert(newTC->cpuId() == oldTC->cpuId()); #if FULL_SYSTEM - system->replaceThreadContext(newTC, newTC->readCpuId()); + system->replaceThreadContext(newTC, newTC->cpuId()); #else assert(newTC->getProcessPtr() == oldTC->getProcessPtr()); - newTC->getProcessPtr()->replaceThreadContext(newTC, newTC->readCpuId()); + newTC->getProcessPtr()->replaceThreadContext(newTC, newTC->cpuId()); #endif if (DTRACE(Context)) diff --git a/src/cpu/base.hh b/src/cpu/base.hh index 2d25c9e56..f39759605 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -80,8 +80,16 @@ class BaseCPU : public MemObject Tick clock; // @todo remove me after debugging with legion done Tick instCnt; + // every cpu has an id, put it in the base cpu + // Set at initialization, only time a cpuId might change is during a + // takeover (which should be done from within the BaseCPU anyway, + // therefore no setCpuId() method is provided + int _cpuId; public: + /** Reads this CPU's ID. */ + int cpuId() { return _cpuId; } + // Tick currentTick; inline Tick frequency() const { return Clock::Frequency / clock; } inline Tick ticks(int numCycles) const { return clock * numCycles; } diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index b03a2f63e..e0de3a372 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -412,7 +412,7 @@ class BaseDynInst : public FastAlloc, public RefCounted void dump(std::string &outstring); /** Read this CPU's ID. */ - int readCpuId() { return cpu->readCpuId(); } + int cpuId() { return cpu->cpuId(); } /** Returns the fault type. */ Fault getFault() { return fault; } @@ -868,7 +868,7 @@ BaseDynInst::translateDataReadAddr(Addr vaddr, Addr &paddr, reqMade = true; Request *req = new Request(); req->setVirt(asid, vaddr, size, flags, PC); - req->setThreadContext(thread->readCpuId(), threadNumber); + req->setThreadContext(thread->cpuId(), threadNumber); fault = cpu->translateDataReadReq(req, thread); @@ -887,7 +887,7 @@ BaseDynInst::read(Addr addr, T &data, unsigned flags) reqMade = true; Request *req = new Request(); req->setVirt(asid, addr, sizeof(T), flags, this->PC); - req->setThreadContext(thread->readCpuId(), threadNumber); + req->setThreadContext(thread->cpuId(), threadNumber); fault = cpu->translateDataReadReq(req, thread); @@ -942,7 +942,7 @@ BaseDynInst::translateDataWriteAddr(Addr vaddr, Addr &paddr, reqMade = true; Request *req = new Request(); req->setVirt(asid, vaddr, size, flags, PC); - req->setThreadContext(thread->readCpuId(), threadNumber); + req->setThreadContext(thread->cpuId(), threadNumber); fault = cpu->translateDataWriteReq(req, thread); @@ -966,7 +966,7 @@ BaseDynInst::write(T data, Addr addr, unsigned flags, uint64_t *res) reqMade = true; Request *req = new Request(); req->setVirt(asid, addr, sizeof(T), flags, this->PC); - req->setThreadContext(thread->readCpuId(), threadNumber); + req->setThreadContext(thread->cpuId(), threadNumber); fault = cpu->translateDataWriteReq(req, thread); diff --git a/src/cpu/checker/cpu_impl.hh b/src/cpu/checker/cpu_impl.hh index 33c70569a..9f6fa2b6d 100644 --- a/src/cpu/checker/cpu_impl.hh +++ b/src/cpu/checker/cpu_impl.hh @@ -152,7 +152,7 @@ Checker::verify(DynInstPtr &completed_inst) memReq = new Request(inst->threadNumber, fetch_PC, sizeof(uint32_t), IFETCH_FLAGS(thread->readPC()), - fetch_PC, thread->readCpuId(), inst->threadNumber); + fetch_PC, thread->cpuId(), inst->threadNumber); bool succeeded = translateInstReq(memReq); diff --git a/src/cpu/checker/thread_context.hh b/src/cpu/checker/thread_context.hh index 75ac959db..a74de20b9 100644 --- a/src/cpu/checker/thread_context.hh +++ b/src/cpu/checker/thread_context.hh @@ -82,7 +82,7 @@ class CheckerThreadContext : public ThreadContext checkerTC->setCpuId(id); } - int readCpuId() { return actualTC->readCpuId(); } + int cpuId() { return actualTC->cpuId(); } TheISA::ITB *getITBPtr() { return actualTC->getITBPtr(); } diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 1b7a3a17c..b7cf4f1c0 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -62,7 +62,7 @@ class BaseCPUParams; using namespace TheISA; BaseO3CPU::BaseO3CPU(BaseCPUParams *params) - : BaseCPU(params), cpuId(0) + : BaseCPU(params) { } @@ -404,7 +404,6 @@ FullO3CPU::FullO3CPU(DerivO3CPUParams *params) #endif // Give the thread the TC. this->thread[i]->tc = tc; - this->thread[i]->setCpuId(params->cpu_id); // Add the TC to the CPU's list of TC's. this->threadContexts.push_back(tc); @@ -611,7 +610,7 @@ FullO3CPU::init() } #if FULL_SYSTEM - TheISA::initCPU(src_tc, src_tc->readCpuId()); + TheISA::initCPU(src_tc, src_tc->cpuId()); #endif } diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index d1cc8bea5..c60c20d55 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -74,15 +74,6 @@ class BaseO3CPU : public BaseCPU BaseO3CPU(BaseCPUParams *params); void regStats(); - - /** Sets this CPU's ID. */ - void setCpuId(int id) { cpuId = id; } - - /** Reads this CPU's ID. */ - int readCpuId() { return cpuId; } - - protected: - int cpuId; }; /** diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 0b5ce9380..35031663e 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -593,7 +593,7 @@ DefaultFetch::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid // Set the appropriate read size and flags as well. // Build request here. RequestPtr mem_req = new Request(tid, block_PC, cacheBlkSize, 0, - fetch_PC, cpu->readCpuId(), tid); + fetch_PC, cpu->cpuId(), tid); memReq[tid] = mem_req; diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index c529b002b..d571d25db 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -75,11 +75,8 @@ class O3ThreadContext : public ThreadContext /** Returns a pointer to this CPU. */ virtual BaseCPU *getCpuPtr() { return cpu; } - /** Sets this CPU's ID. */ - virtual void setCpuId(int id) { cpu->setCpuId(id); } - /** Reads this CPU's ID. */ - virtual int readCpuId() { return cpu->readCpuId(); } + virtual int cpuId() { return cpu->cpuId(); } #if FULL_SYSTEM /** Returns a pointer to the system. */ diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index d8ec70bb8..853ee2c63 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -63,7 +63,6 @@ O3ThreadContext::takeOverFrom(ThreadContext *old_context) // copy over functional state setStatus(old_context->status()); copyArchRegs(old_context); - setCpuId(old_context->readCpuId()); #if !FULL_SYSTEM thread->funcExeInst = old_context->readFuncExeInst(); diff --git a/src/cpu/o3/thread_state.hh b/src/cpu/o3/thread_state.hh index 8c634f67e..1f0e7a3bb 100644 --- a/src/cpu/o3/thread_state.hh +++ b/src/cpu/o3/thread_state.hh @@ -77,7 +77,7 @@ struct O3ThreadState : public ThreadState { #if FULL_SYSTEM O3ThreadState(O3CPU *_cpu, int _thread_num) - : ThreadState(_cpu, -1, _thread_num), + : ThreadState(_cpu, _thread_num), cpu(_cpu), inSyscall(0), trapPending(0) { if (cpu->params()->profile) { @@ -96,7 +96,7 @@ struct O3ThreadState : public ThreadState { } #else O3ThreadState(O3CPU *_cpu, int _thread_num, Process *_process, int _asid) - : ThreadState(_cpu, -1, _thread_num, _process, _asid), + : ThreadState(_cpu, _thread_num, _process, _asid), cpu(_cpu), inSyscall(0), trapPending(0) { } #endif diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index 491e6ba93..8fce61d4f 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -116,10 +116,6 @@ class OzoneCPU : public BaseCPU BaseCPU *getCpuPtr(); - void setCpuId(int id); - - int readCpuId() { return thread->readCpuId(); } - TheISA::ITB *getITBPtr() { return cpu->itb; } TheISA::DTB * getDTBPtr() { return cpu->dtb; } @@ -353,12 +349,6 @@ class OzoneCPU : public BaseCPU public: BaseCPU *getCpuPtr() { return this; } - void setCpuId(int id) { cpuId = id; } - - int readCpuId() { return cpuId; } - - int cpuId; - void switchOut(); void signalSwitched(); void takeOverFrom(BaseCPU *oldCPU); diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index a7efa3596..52376afd8 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -417,7 +417,7 @@ OzoneCPU::init() ThreadContext *tc = threadContexts[i]; // initialize CPU, including PC - TheISA::initCPU(tc, tc->readCpuId()); + TheISA::initCPU(tc, tc->cpuId()); } #endif frontEnd->renameTable.copyFrom(thread.renameTable); @@ -803,7 +803,7 @@ OzoneCPU::OzoneTC::takeOverFrom(ThreadContext *old_context) // copy over functional state setStatus(old_context->status()); copyArchRegs(old_context); - setCpuId(old_context->readCpuId()); + setCpuId(old_context->cpuId()); thread->setInst(old_context->getInst()); #if !FULL_SYSTEM diff --git a/src/cpu/ozone/front_end_impl.hh b/src/cpu/ozone/front_end_impl.hh index 198ce0308..df3609e27 100644 --- a/src/cpu/ozone/front_end_impl.hh +++ b/src/cpu/ozone/front_end_impl.hh @@ -477,7 +477,7 @@ FrontEnd::fetchCacheLine() // Setup the memReq to do a read of the first isntruction's address. // Set the appropriate read size and flags as well. memReq = new Request(0, fetch_PC, cacheBlkSize, 0, - PC, cpu->readCpuId(), 0); + PC, cpu->cpuId(), 0); // Translate the instruction request. fault = cpu->translateInstReq(memReq, thread); diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 30f4a5c5e..5e8ab9443 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -79,13 +79,12 @@ void AtomicSimpleCPU::init() { BaseCPU::init(); - cpuId = tc->readCpuId(); #if FULL_SYSTEM for (int i = 0; i < threadContexts.size(); ++i) { ThreadContext *tc = threadContexts[i]; // initialize CPU, including PC - TheISA::initCPU(tc, cpuId); + TheISA::initCPU(tc, _cpuId); } #endif if (hasPhysMemPort) { @@ -94,9 +93,9 @@ AtomicSimpleCPU::init() physmemPort.getPeerAddressRanges(pmAddrList, snoop); physMemAddr = *pmAddrList.begin(); } - ifetch_req.setThreadContext(cpuId, 0); // Add thread ID if we add MT - data_read_req.setThreadContext(cpuId, 0); // Add thread ID here too - data_write_req.setThreadContext(cpuId, 0); // Add thread ID here too + ifetch_req.setThreadContext(_cpuId, 0); // Add thread ID if we add MT + data_read_req.setThreadContext(_cpuId, 0); // Add thread ID here too + data_write_req.setThreadContext(_cpuId, 0); // Add thread ID here too } bool @@ -237,10 +236,9 @@ AtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU) _status = Idle; } assert(threadContexts.size() == 1); - cpuId = tc->readCpuId(); - ifetch_req.setThreadContext(cpuId, 0); // Add thread ID if we add MT - data_read_req.setThreadContext(cpuId, 0); // Add thread ID here too - data_write_req.setThreadContext(cpuId, 0); // Add thread ID here too + ifetch_req.setThreadContext(_cpuId, 0); // Add thread ID if we add MT + data_read_req.setThreadContext(_cpuId, 0); // Add thread ID here too + data_write_req.setThreadContext(_cpuId, 0); // Add thread ID here too } diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index dc736c22e..6e72b8f6c 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -121,7 +121,6 @@ class BaseSimpleCPU : public BaseCPU */ ThreadContext *tc; protected: - int cpuId; enum Status { Idle, diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index a6059f55f..247899ca8 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -57,13 +57,12 @@ void TimingSimpleCPU::init() { BaseCPU::init(); - cpuId = tc->readCpuId(); #if FULL_SYSTEM for (int i = 0; i < threadContexts.size(); ++i) { ThreadContext *tc = threadContexts[i]; // initialize CPU, including PC - TheISA::initCPU(tc, cpuId); + TheISA::initCPU(tc, _cpuId); } #endif } @@ -203,7 +202,7 @@ TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU) _status = Idle; } assert(threadContexts.size() == 1); - cpuId = tc->readCpuId(); + _cpuId = tc->cpuId(); previousTick = curTick; } @@ -250,7 +249,7 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) { Request *req = new Request(/* asid */ 0, addr, sizeof(T), flags, thread->readPC(), - cpuId, /* thread ID */ 0); + _cpuId, /* thread ID */ 0); if (traceData) { traceData->setAddr(req->getVaddr()); @@ -301,7 +300,7 @@ TimingSimpleCPU::translateDataReadAddr(Addr vaddr, Addr &paddr, int size, unsigned flags) { Request *req = - new Request(0, vaddr, size, flags, thread->readPC(), cpuId, 0); + new Request(0, vaddr, size, flags, thread->readPC(), _cpuId, 0); if (traceData) { traceData->setAddr(vaddr); @@ -373,7 +372,7 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) { Request *req = new Request(/* asid */ 0, addr, sizeof(T), flags, thread->readPC(), - cpuId, /* thread ID */ 0); + _cpuId, /* thread ID */ 0); if (traceData) { traceData->setAddr(req->getVaddr()); @@ -442,7 +441,7 @@ TimingSimpleCPU::translateDataWriteAddr(Addr vaddr, Addr &paddr, int size, unsigned flags) { Request *req = - new Request(0, vaddr, size, flags, thread->readPC(), cpuId, 0); + new Request(0, vaddr, size, flags, thread->readPC(), _cpuId, 0); if (traceData) { traceData->setAddr(vaddr); @@ -528,7 +527,7 @@ TimingSimpleCPU::fetch() if (!fromRom) { Request *ifetch_req = new Request(); - ifetch_req->setThreadContext(cpuId, /* thread ID */ 0); + ifetch_req->setThreadContext(_cpuId, /* thread ID */ 0); Fault fault = setupFetchRequest(ifetch_req); ifetch_pkt = new Packet(ifetch_req, MemCmd::ReadReq, Packet::Broadcast); diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index 68683e568..6034ca120 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -63,7 +63,7 @@ using namespace std; SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys, TheISA::ITB *_itb, TheISA::DTB *_dtb, bool use_kernel_stats) - : ThreadState(_cpu, -1, _thread_num), cpu(_cpu), system(_sys), itb(_itb), + : ThreadState(_cpu, _thread_num), cpu(_cpu), system(_sys), itb(_itb), dtb(_dtb) { @@ -93,7 +93,7 @@ SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys, #else SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, Process *_process, TheISA::ITB *_itb, TheISA::DTB *_dtb, int _asid) - : ThreadState(_cpu, -1, _thread_num, _process, _asid), + : ThreadState(_cpu, _thread_num, _process, _asid), cpu(_cpu), itb(_itb), dtb(_dtb) { regs.clear(); @@ -104,9 +104,9 @@ SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, Process *_process, SimpleThread::SimpleThread() #if FULL_SYSTEM - : ThreadState(NULL, -1, -1) + : ThreadState(NULL, -1) #else - : ThreadState(NULL, -1, -1, NULL, -1) + : ThreadState(NULL, -1, NULL, -1) #endif { tc = new ProxyThreadContext(this); @@ -178,7 +178,6 @@ SimpleThread::copyState(ThreadContext *oldContext) // copy over functional state _status = oldContext->status(); copyArchRegs(oldContext); - cpuId = oldContext->readCpuId(); #if !FULL_SYSTEM funcExeInst = oldContext->readFuncExeInst(); #endif diff --git a/src/cpu/thread_context.cc b/src/cpu/thread_context.cc index 10c94027d..58912c564 100644 --- a/src/cpu/thread_context.cc +++ b/src/cpu/thread_context.cc @@ -74,8 +74,8 @@ ThreadContext::compare(ThreadContext *one, ThreadContext *two) if (npc1 != npc2) panic("NPCs doesn't match, one: %#x, two: %#x", npc1, npc2); - int id1 = one->readCpuId(); - int id2 = two->readCpuId(); + int id1 = one->cpuId(); + int id2 = two->cpuId(); if (id1 != id2) panic("CPU ids don't match, one: %d, two: %d", id1, id2); } diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index 2b9f41b70..d06194012 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -115,9 +115,7 @@ class ThreadContext virtual BaseCPU *getCpuPtr() = 0; - virtual void setCpuId(int id) = 0; - - virtual int readCpuId() = 0; + virtual int cpuId() = 0; virtual TheISA::ITB *getITBPtr() = 0; @@ -300,9 +298,7 @@ class ProxyThreadContext : public ThreadContext BaseCPU *getCpuPtr() { return actualTC->getCpuPtr(); } - void setCpuId(int id) { actualTC->setCpuId(id); } - - int readCpuId() { return actualTC->readCpuId(); } + int cpuId() { return actualTC->cpuId(); } TheISA::ITB *getITBPtr() { return actualTC->getITBPtr(); } diff --git a/src/cpu/thread_state.cc b/src/cpu/thread_state.cc index 8d519c563..47841922e 100644 --- a/src/cpu/thread_state.cc +++ b/src/cpu/thread_state.cc @@ -43,15 +43,15 @@ #endif #if FULL_SYSTEM -ThreadState::ThreadState(BaseCPU *cpu, int _cpuId, int _tid) - : baseCpu(cpu), cpuId(_cpuId), tid(_tid), lastActivate(0), lastSuspend(0), +ThreadState::ThreadState(BaseCPU *cpu, int _tid) + : baseCpu(cpu), tid(_tid), lastActivate(0), lastSuspend(0), profile(NULL), profileNode(NULL), profilePC(0), quiesceEvent(NULL), kernelStats(NULL), physPort(NULL), virtPort(NULL), microPC(0), nextMicroPC(1), funcExeInst(0), storeCondFailures(0) #else -ThreadState::ThreadState(BaseCPU *cpu, int _cpuId, int _tid, Process *_process, +ThreadState::ThreadState(BaseCPU *cpu, int _tid, Process *_process, short _asid) - : baseCpu(cpu), cpuId(_cpuId), tid(_tid), lastActivate(0), lastSuspend(0), + : baseCpu(cpu), tid(_tid), lastActivate(0), lastSuspend(0), port(NULL), process(_process), asid(_asid), microPC(0), nextMicroPC(1), funcExeInst(0), storeCondFailures(0) #endif diff --git a/src/cpu/thread_state.hh b/src/cpu/thread_state.hh index 1b667f72a..f3f154de3 100644 --- a/src/cpu/thread_state.hh +++ b/src/cpu/thread_state.hh @@ -34,6 +34,7 @@ #include "arch/types.hh" #include "cpu/profile.hh" #include "cpu/thread_context.hh" +#include "cpu/base.hh" #if !FULL_SYSTEM #include "mem/mem_object.hh" @@ -51,7 +52,6 @@ namespace TheISA { }; #endif -class BaseCPU; class Checkpoint; class Port; class TranslatingPort; @@ -66,9 +66,9 @@ struct ThreadState { typedef ThreadContext::Status Status; #if FULL_SYSTEM - ThreadState(BaseCPU *cpu, int _cpuId, int _tid); + ThreadState(BaseCPU *cpu, int _tid); #else - ThreadState(BaseCPU *cpu, int _cpuId, int _tid, Process *_process, + ThreadState(BaseCPU *cpu, int _tid, Process *_process, short _asid); #endif @@ -78,9 +78,7 @@ struct ThreadState { void unserialize(Checkpoint *cp, const std::string §ion); - void setCpuId(int id) { cpuId = id; } - - int readCpuId() { return cpuId; } + int cpuId() { return baseCpu->cpuId(); } void setTid(int id) { tid = id; } @@ -171,10 +169,6 @@ struct ThreadState { // Pointer to the base CPU. BaseCPU *baseCpu; - // ID of this context w.r.t. the System or Process object to which - // it belongs. For full-system mode, this is the system CPU ID. - int cpuId; - // Index of hardware thread context on the CPU that this represents. int tid; diff --git a/src/sim/system.cc b/src/sim/system.cc index 7b830d0f7..41075e9d0 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -166,13 +166,12 @@ bool System::breakpoint() } int -System::registerThreadContext(ThreadContext *tc, int id) +System::registerThreadContext(ThreadContext *tc) { - if (id == -1) { - for (id = 0; id < threadContexts.size(); id++) { - if (!threadContexts[id]) - break; - } + int id; + for (id = 0; id < threadContexts.size(); id++) { + if (!threadContexts[id]) + break; } if (threadContexts.size() <= id) diff --git a/src/sim/system.hh b/src/sim/system.hh index cdd5bebb0..f67d39c67 100644 --- a/src/sim/system.hh +++ b/src/sim/system.hh @@ -219,7 +219,7 @@ class System : public SimObject #endif // FULL_SYSTEM - int registerThreadContext(ThreadContext *tc, int tcIndex); + int registerThreadContext(ThreadContext *tc); void replaceThreadContext(ThreadContext *tc, int tcIndex); void serialize(std::ostream &os); -- cgit v1.2.3 From 67fda02dda290d614de233846fee434b3713b1dc Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Sun, 2 Nov 2008 21:57:06 -0500 Subject: Make it so that all thread contexts are registered with the System, even in SE. Process still keeps track of the tc's it owns, but registration occurs with the System, this eases the way for system-wide context Ids based on registration. --- src/arch/alpha/process.cc | 11 +++++---- src/arch/sparc/process.cc | 54 ++++++++++++++++++++++-------------------- src/arch/x86/process.cc | 11 +++++---- src/cpu/base.cc | 10 ++------ src/kern/tru64/tru64.hh | 27 ++++++++++----------- src/sim/process.cc | 60 ++++++++++++++++++----------------------------- src/sim/process.hh | 17 ++++++++------ src/sim/system.cc | 14 ++++++----- src/sim/system.hh | 7 +++++- 9 files changed, 102 insertions(+), 109 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/process.cc b/src/arch/alpha/process.cc index 380e0e18e..28e8df308 100644 --- a/src/arch/alpha/process.cc +++ b/src/arch/alpha/process.cc @@ -67,12 +67,13 @@ AlphaLiveProcess::startup() argsInit(MachineBytes, VMPageSize); - threadContexts[0]->setIntReg(GlobalPointerReg, objFile->globalPointer()); - //Opperate in user mode - threadContexts[0]->setMiscRegNoEffect(IPR_ICM, 0x18); + ThreadContext *tc = system->getThreadContext(contextIds[0]); + tc->setIntReg(GlobalPointerReg, objFile->globalPointer()); + //Operate in user mode + tc->setMiscRegNoEffect(IPR_ICM, 0x18); //No super page mapping - threadContexts[0]->setMiscRegNoEffect(IPR_MCSR, 0); + tc->setMiscRegNoEffect(IPR_MCSR, 0); //Set this to 0 for now, but it should be unique for each process - threadContexts[0]->setMiscRegNoEffect(IPR_DTB_ASN, M5_pid << 57); + tc->setMiscRegNoEffect(IPR_DTB_ASN, M5_pid << 57); } diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index a8fda04eb..987e0465e 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -112,44 +112,45 @@ SparcLiveProcess::startup() { Process::startup(); + ThreadContext *tc = system->getThreadContext(contextIds[0]); //From the SPARC ABI //Setup default FP state - threadContexts[0]->setMiscRegNoEffect(MISCREG_FSR, 0); + tc->setMiscRegNoEffect(MISCREG_FSR, 0); - threadContexts[0]->setMiscRegNoEffect(MISCREG_TICK, 0); + tc->setMiscRegNoEffect(MISCREG_TICK, 0); /* * Register window management registers */ //No windows contain info from other programs - //threadContexts[0]->setMiscRegNoEffect(MISCREG_OTHERWIN, 0); - threadContexts[0]->setIntReg(NumIntArchRegs + 6, 0); + //tc->setMiscRegNoEffect(MISCREG_OTHERWIN, 0); + tc->setIntReg(NumIntArchRegs + 6, 0); //There are no windows to pop - //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANRESTORE, 0); - threadContexts[0]->setIntReg(NumIntArchRegs + 4, 0); + //tc->setMiscRegNoEffect(MISCREG_CANRESTORE, 0); + tc->setIntReg(NumIntArchRegs + 4, 0); //All windows are available to save into - //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANSAVE, NWindows - 2); - threadContexts[0]->setIntReg(NumIntArchRegs + 3, NWindows - 2); + //tc->setMiscRegNoEffect(MISCREG_CANSAVE, NWindows - 2); + tc->setIntReg(NumIntArchRegs + 3, NWindows - 2); //All windows are "clean" - //threadContexts[0]->setMiscRegNoEffect(MISCREG_CLEANWIN, NWindows); - threadContexts[0]->setIntReg(NumIntArchRegs + 5, NWindows); + //tc->setMiscRegNoEffect(MISCREG_CLEANWIN, NWindows); + tc->setIntReg(NumIntArchRegs + 5, NWindows); //Start with register window 0 - threadContexts[0]->setMiscRegNoEffect(MISCREG_CWP, 0); + tc->setMiscRegNoEffect(MISCREG_CWP, 0); //Always use spill and fill traps 0 - //threadContexts[0]->setMiscRegNoEffect(MISCREG_WSTATE, 0); - threadContexts[0]->setIntReg(NumIntArchRegs + 7, 0); + //tc->setMiscRegNoEffect(MISCREG_WSTATE, 0); + tc->setIntReg(NumIntArchRegs + 7, 0); //Set the trap level to 0 - threadContexts[0]->setMiscRegNoEffect(MISCREG_TL, 0); + tc->setMiscRegNoEffect(MISCREG_TL, 0); //Set the ASI register to something fixed - threadContexts[0]->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY); + tc->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY); /* * T1 specific registers */ //Turn on the icache, dcache, dtb translation, and itb translation. - threadContexts[0]->setMiscRegNoEffect(MISCREG_MMU_LSU_CTRL, 15); + tc->setMiscRegNoEffect(MISCREG_MMU_LSU_CTRL, 15); } void @@ -160,8 +161,9 @@ Sparc32LiveProcess::startup() SparcLiveProcess::startup(); + ThreadContext *tc = system->getThreadContext(contextIds[0]); //The process runs in user mode with 32 bit addresses - threadContexts[0]->setMiscReg(MISCREG_PSTATE, 0x0a); + tc->setMiscReg(MISCREG_PSTATE, 0x0a); argsInit(32 / 8, VMPageSize); } @@ -174,8 +176,9 @@ Sparc64LiveProcess::startup() SparcLiveProcess::startup(); + ThreadContext *tc = system->getThreadContext(contextIds[0]); //The process runs in user mode - threadContexts[0]->setMiscReg(MISCREG_PSTATE, 0x02); + tc->setMiscReg(MISCREG_PSTATE, 0x02); argsInit(sizeof(IntReg), VMPageSize); } @@ -391,20 +394,21 @@ SparcLiveProcess::argsInit(int pageSize) fillStart = stack_base; spillStart = fillStart + sizeof(MachInst) * numFillInsts; + ThreadContext *tc = system->getThreadContext(contextIds[0]); //Set up the thread context to start running the process //assert(NumArgumentRegs >= 2); - //threadContexts[0]->setIntReg(ArgumentReg[0], argc); - //threadContexts[0]->setIntReg(ArgumentReg[1], argv_array_base); - threadContexts[0]->setIntReg(StackPointerReg, stack_min - StackBias); + //tc->setIntReg(ArgumentReg[0], argc); + //tc->setIntReg(ArgumentReg[1], argv_array_base); + tc->setIntReg(StackPointerReg, stack_min - StackBias); // %g1 is a pointer to a function that should be run at exit. Since we // don't have anything like that, it should be set to 0. - threadContexts[0]->setIntReg(1, 0); + tc->setIntReg(1, 0); Addr prog_entry = objFile->entryPoint(); - threadContexts[0]->setPC(prog_entry); - threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst)); - threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst))); + tc->setPC(prog_entry); + tc->setNextPC(prog_entry + sizeof(MachInst)); + tc->setNextNPC(prog_entry + (2 * sizeof(MachInst))); //Align the "stack_min" to a page boundary. stack_min = roundDown(stack_min, pageSize); diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index b62efd3cd..52933b7f4 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -146,8 +146,8 @@ X86LiveProcess::startup() argsInit(sizeof(IntReg), VMPageSize); - for (int i = 0; i < threadContexts.size(); i++) { - ThreadContext * tc = threadContexts[i]; + for (int i = 0; i < contextIds.size(); i++) { + ThreadContext * tc = system->getThreadContext(contextIds[i]); SegAttr dataAttr = 0; dataAttr.writable = 1; @@ -458,14 +458,15 @@ X86LiveProcess::argsInit(int intSize, int pageSize) initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize); + ThreadContext *tc = system->getThreadContext(contextIds[0]); //Set the stack pointer register - threadContexts[0]->setIntReg(StackPointerReg, stack_min); + tc->setIntReg(StackPointerReg, stack_min); Addr prog_entry = objFile->entryPoint(); // There doesn't need to be any segment base added in since we're dealing // with the flat segmentation model. - threadContexts[0]->setPC(prog_entry); - threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst)); + tc->setPC(prog_entry); + tc->setNextPC(prog_entry + sizeof(MachInst)); //Align the "stack_min" to a page boundary. stack_min = roundDown(stack_min, pageSize); diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 3e899d993..4845cbfaf 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -285,10 +285,9 @@ BaseCPU::registerThreadContexts() for (int i = 0; i < threadContexts.size(); ++i) { ThreadContext *tc = threadContexts[i]; -#if FULL_SYSTEM system->registerThreadContext(tc); -#else - tc->getProcessPtr()->registerThreadContext(tc); +#if !FULL_SYSTEM + tc->getProcessPtr()->assignThreadContext(tc->cpuId()); #endif } } @@ -330,12 +329,7 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc) CpuEvent::replaceThreadContext(oldTC, newTC); assert(newTC->cpuId() == oldTC->cpuId()); -#if FULL_SYSTEM system->replaceThreadContext(newTC, newTC->cpuId()); -#else - assert(newTC->getProcessPtr() == oldTC->getProcessPtr()); - newTC->getProcessPtr()->replaceThreadContext(newTC, newTC->cpuId()); -#endif if (DTRACE(Context)) ThreadContext::compare(oldTC, newTC); diff --git a/src/kern/tru64/tru64.hh b/src/kern/tru64/tru64.hh index dfdb8524d..5f8307cd2 100644 --- a/src/kern/tru64/tru64.hh +++ b/src/kern/tru64/tru64.hh @@ -789,21 +789,18 @@ class Tru64 : public OperatingSystem slot_state.copyOut(tc->getMemPort()); // Find a free simulator thread context. - for (int i = 0; i < process->numCpus(); ++i) { - ThreadContext *tc = process->threadContexts[i]; - - if (tc->status() == ThreadContext::Unallocated) { - // inactive context... grab it - init_thread_context(tc, attrp, uniq_val); - - // This is supposed to be a port number, but we'll try - // and get away with just sticking the thread index - // here. - *kidp = htog(thread_index); - kidp.copyOut(tc->getMemPort()); - - return 0; - } + ThreadContext *tc = process->findFreeContext(); + if (tc) { + // inactive context... grab it + init_thread_context(tc, attrp, uniq_val); + + // This is supposed to be a port number, but we'll try + // and get away with just sticking the thread index + // here. + *kidp = htog(thread_index); + kidp.copyOut(tc->getMemPort()); + + return 0; } // fell out of loop... no available inactive context diff --git a/src/sim/process.cc b/src/sim/process.cc index 23e890b06..50bc5e034 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -204,35 +204,29 @@ Process::openOutputFile(const string &filename) return fd; } - -int -Process::registerThreadContext(ThreadContext *tc) +ThreadContext * +Process::findFreeContext() { - // add to list - int myIndex = threadContexts.size(); - threadContexts.push_back(tc); - - int port = getRemoteGDBPort(); - if (port) { - RemoteGDB *rgdb = new RemoteGDB(system, tc); - GDBListener *gdbl = new GDBListener(rgdb, port + myIndex); - gdbl->listen(); - - remoteGDB.push_back(rgdb); + int size = contextIds.size(); + ThreadContext *tc; + for (int i = 0; i < size; ++i) { + tc = system->getThreadContext(contextIds[i]); + if (tc->status() == ThreadContext::Unallocated) { + // inactive context, free to use + return tc; + } } - - // return CPU number to caller - return myIndex; + return NULL; } void Process::startup() { - if (threadContexts.empty()) - fatal("Process %s is not associated with any CPUs!\n", name()); + if (contextIds.empty()) + fatal("Process %s is not associated with any HW contexts!\n", name()); // first thread context for this process... initialize & enable - ThreadContext *tc = threadContexts[0]; + ThreadContext *tc = system->getThreadContext(contextIds[0]); // mark this context as active so it will start ticking. tc->activate(0); @@ -245,17 +239,6 @@ Process::startup() initVirtMem->setPeer(mem_port); } -void -Process::replaceThreadContext(ThreadContext *tc, int tcIndex) -{ - if (tcIndex >= threadContexts.size()) { - panic("replaceThreadContext: bad tcIndex, %d >= %d\n", - tcIndex, threadContexts.size()); - } - - threadContexts[tcIndex] = tc; -} - // map simulator fd sim_fd to target fd tgt_fd void Process::dup_fd(int sim_fd, int tgt_fd) @@ -624,16 +607,19 @@ LiveProcess::argsInit(int intSize, int pageSize) copyStringArray(envp, envp_array_base, env_data_base, initVirtMem); assert(NumArgumentRegs >= 2); - threadContexts[0]->setIntReg(ArgumentReg[0], argc); - threadContexts[0]->setIntReg(ArgumentReg[1], argv_array_base); - threadContexts[0]->setIntReg(StackPointerReg, stack_min); + + ThreadContext *tc = system->getThreadContext(contextIds[0]); + + tc->setIntReg(ArgumentReg[0], argc); + tc->setIntReg(ArgumentReg[1], argv_array_base); + tc->setIntReg(StackPointerReg, stack_min); Addr prog_entry = objFile->entryPoint(); - threadContexts[0]->setPC(prog_entry); - threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst)); + tc->setPC(prog_entry); + tc->setNextPC(prog_entry + sizeof(MachInst)); #if THE_ISA != ALPHA_ISA //e.g. MIPS or Sparc - threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst))); + tc->setNextNPC(prog_entry + (2 * sizeof(MachInst))); #endif num_processes++; diff --git a/src/sim/process.hh b/src/sim/process.hh index cb59fed64..d6ed59ced 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -77,7 +77,7 @@ class Process : public SimObject bool checkpointRestored; // thread contexts associated with this process - std::vector threadContexts; + std::vector contextIds; // remote gdb objects std::vector remoteGDB; @@ -85,7 +85,7 @@ class Process : public SimObject bool breakpoint(); // number of CPUs (esxec contexts, really) assigned to this process. - unsigned int numCpus() { return threadContexts.size(); } + unsigned int numCpus() { return contextIds.size(); } // record of blocked context struct WaitRec @@ -187,12 +187,15 @@ class Process : public SimObject // override of virtual SimObject method: register statistics virtual void regStats(); - // register a thread context for this process. - // returns tc's cpu number (index into threadContexts[]) - int registerThreadContext(ThreadContext *tc); - + // After getting registered with system object, tell process which + // system-wide context id it is assigned. + void assignThreadContext(int context_id) + { + contextIds.push_back(context_id); + } - void replaceThreadContext(ThreadContext *tc, int tcIndex); + // Find a free context to use + ThreadContext * findFreeContext(); // map simulator fd sim_fd to target fd tgt_fd void dup_fd(int sim_fd, int tgt_fd); diff --git a/src/sim/system.cc b/src/sim/system.cc index 41075e9d0..8f25b4bb8 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -208,22 +208,24 @@ System::registerThreadContext(ThreadContext *tc) void System::startup() { +#if FULL_SYSTEM int i; for (i = 0; i < threadContexts.size(); i++) TheISA::startupCPU(threadContexts[i], i); +#endif } void -System::replaceThreadContext(ThreadContext *tc, int id) +System::replaceThreadContext(ThreadContext *tc, int context_id) { - if (id >= threadContexts.size()) { + if (context_id >= threadContexts.size()) { panic("replaceThreadContext: bad id, %d >= %d\n", - id, threadContexts.size()); + context_id, threadContexts.size()); } - threadContexts[id] = tc; - if (id < remoteGDB.size()) - remoteGDB[id]->replaceThreadContext(tc); + threadContexts[context_id] = tc; + if (context_id < remoteGDB.size()) + remoteGDB[context_id]->replaceThreadContext(tc); } #if !FULL_SYSTEM diff --git a/src/sim/system.hh b/src/sim/system.hh index f67d39c67..26cac714b 100644 --- a/src/sim/system.hh +++ b/src/sim/system.hh @@ -89,6 +89,11 @@ class System : public SimObject std::vector threadContexts; int numcpus; + ThreadContext * getThreadContext(int tid) + { + return threadContexts[tid]; + } + int getNumCPUs() { if (numcpus != threadContexts.size()) @@ -220,7 +225,7 @@ class System : public SimObject #endif // FULL_SYSTEM int registerThreadContext(ThreadContext *tc); - void replaceThreadContext(ThreadContext *tc, int tcIndex); + void replaceThreadContext(ThreadContext *tc, int context_id); void serialize(std::ostream &os); void unserialize(Checkpoint *cp, const std::string §ion); -- cgit v1.2.3 From d857faf073895dcfde97141bd6346fe5d4317f8e Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Sun, 2 Nov 2008 21:57:07 -0500 Subject: Add in Context IDs to the simulator. From now on, cpuId is almost never used, the primary identifier for a hardware context should be contextId(). The concept of threads within a CPU remains, in the form of threadId() because sometimes you need to know which context within a cpu to manipulate. --- src/arch/alpha/locked_mem.hh | 4 ++-- src/arch/mips/locked_mem.hh | 4 ++-- src/arch/sparc/ua2005.cc | 6 +++--- src/arch/x86/tlb.cc | 2 +- src/cpu/base.cc | 8 ++++---- src/cpu/base_dyn_inst.hh | 11 +++++++---- src/cpu/checker/cpu_impl.hh | 3 ++- src/cpu/o3/cpu.cc | 6 ++---- src/cpu/o3/fetch_impl.hh | 5 +++-- src/cpu/o3/lsq.hh | 4 ++-- src/cpu/o3/lsq_impl.hh | 2 +- src/cpu/o3/thread_context.hh | 4 ++++ src/cpu/o3/thread_context_impl.hh | 1 + src/cpu/ozone/cpu_impl.hh | 11 ++--------- src/cpu/ozone/front_end_impl.hh | 2 +- src/cpu/simple/atomic.cc | 3 ++- src/cpu/simple/timing.cc | 1 - src/cpu/simple_thread.cc | 2 ++ src/cpu/thread_context.cc | 7 +++++++ src/cpu/thread_context.hh | 17 ++++++++++++----- src/cpu/thread_state.hh | 7 +++++++ src/dev/alpha/backdoor.cc | 2 +- src/dev/alpha/tsunami_cchip.cc | 8 +++++++- src/dev/mips/malta_cchip.cc | 2 +- src/dev/sinic.cc | 4 ++-- src/dev/sparc/iob.cc | 4 ++-- src/mem/cache/blk.hh | 8 +++----- src/mem/cache/prefetch/base.cc | 4 ++-- src/mem/cache/prefetch/ghb.cc | 14 +++++++------- src/mem/cache/prefetch/ghb.hh | 4 ++-- src/mem/cache/prefetch/stride.cc | 10 +++++----- src/mem/cache/prefetch/stride.hh | 4 ++-- src/mem/physical.cc | 16 ++++++++-------- src/mem/physical.hh | 9 +++------ src/mem/request.hh | 36 ++++++++++++++++++------------------ src/sim/system.cc | 4 ++-- src/sim/system.hh | 8 ++++---- 37 files changed, 136 insertions(+), 111 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/locked_mem.hh b/src/arch/alpha/locked_mem.hh index 6f4f5a748..e8928ba08 100644 --- a/src/arch/alpha/locked_mem.hh +++ b/src/arch/alpha/locked_mem.hh @@ -85,9 +85,9 @@ handleLockedWrite(XC *xc, Request *req) stCondFailures++; xc->setStCondFailures(stCondFailures); if (stCondFailures % 100000 == 0) { - warn("cpu %d: %d consecutive " + warn("context %d: %d consecutive " "store conditional failures\n", - xc->cpuId(), stCondFailures); + xc->contextId(), stCondFailures); } // store conditional failed already, so don't issue it to mem diff --git a/src/arch/mips/locked_mem.hh b/src/arch/mips/locked_mem.hh index 5877b1439..9f41ba075 100644 --- a/src/arch/mips/locked_mem.hh +++ b/src/arch/mips/locked_mem.hh @@ -83,9 +83,9 @@ handleLockedWrite(XC *xc, Request *req) stCondFailures++; xc->setStCondFailures(stCondFailures); if (stCondFailures % 10 == 0) { - warn("%i: cpu %d: %d consecutive " + warn("%i: context %d: %d consecutive " "store conditional failures\n", - curTick, xc->cpuId(), stCondFailures); + curTick, xc->contextId(), stCondFailures); } if (stCondFailures == 5000) { diff --git a/src/arch/sparc/ua2005.cc b/src/arch/sparc/ua2005.cc index 6961a24e9..502033d97 100644 --- a/src/arch/sparc/ua2005.cc +++ b/src/arch/sparc/ua2005.cc @@ -257,11 +257,11 @@ MiscRegFile::readFSReg(int miscReg, ThreadContext * tc) temp = readRegNoEffect(miscReg) & (STS::active | STS::speculative); // Check that the CPU array is fully populated // (by calling getNumCPus()) - assert(sys->getNumCPUs() > tc->cpuId()); + assert(sys->getNumContexts() > tc->contextId()); - temp |= tc->cpuId() << STS::shft_id; + temp |= tc->contextId() << STS::shft_id; - for (x = tc->cpuId() & ~3; x < sys->threadContexts.size(); x++) { + for (x = tc->contextId() & ~3; x < sys->threadContexts.size(); x++) { switch (sys->threadContexts[x]->status()) { case ThreadContext::Active: temp |= STS::st_run << (STS::shft_fsm0 - diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index 17374fa0c..4980c5fe5 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -654,7 +654,7 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) */ // Force the access to be uncacheable. req->setFlags(req->getFlags() | UNCACHEABLE); - req->setPaddr(x86LocalAPICAddress(tc->cpuId(), paddr - baseAddr)); + req->setPaddr(x86LocalAPICAddress(tc->contextId(), paddr - baseAddr)); } #endif return NoFault; diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 4845cbfaf..6409255f6 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -285,9 +285,9 @@ BaseCPU::registerThreadContexts() for (int i = 0; i < threadContexts.size(); ++i) { ThreadContext *tc = threadContexts[i]; - system->registerThreadContext(tc); + tc->setContextId(system->registerThreadContext(tc)); #if !FULL_SYSTEM - tc->getProcessPtr()->assignThreadContext(tc->cpuId()); + tc->getProcessPtr()->assignThreadContext(tc->contextId()); #endif } } @@ -328,8 +328,8 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc) CpuEvent::replaceThreadContext(oldTC, newTC); - assert(newTC->cpuId() == oldTC->cpuId()); - system->replaceThreadContext(newTC, newTC->cpuId()); + assert(newTC->contextId() == oldTC->contextId()); + system->replaceThreadContext(newTC, newTC->contextId()); if (DTRACE(Context)) ThreadContext::compare(oldTC, newTC); diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index e0de3a372..3520fafaa 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -414,6 +414,9 @@ class BaseDynInst : public FastAlloc, public RefCounted /** Read this CPU's ID. */ int cpuId() { return cpu->cpuId(); } + /** Read this context's system-wide ID **/ + int contextId() { return thread->contextId(); } + /** Returns the fault type. */ Fault getFault() { return fault; } @@ -868,7 +871,7 @@ BaseDynInst::translateDataReadAddr(Addr vaddr, Addr &paddr, reqMade = true; Request *req = new Request(); req->setVirt(asid, vaddr, size, flags, PC); - req->setThreadContext(thread->cpuId(), threadNumber); + req->setThreadContext(thread->contextId(), threadNumber); fault = cpu->translateDataReadReq(req, thread); @@ -887,7 +890,7 @@ BaseDynInst::read(Addr addr, T &data, unsigned flags) reqMade = true; Request *req = new Request(); req->setVirt(asid, addr, sizeof(T), flags, this->PC); - req->setThreadContext(thread->cpuId(), threadNumber); + req->setThreadContext(thread->contextId(), threadNumber); fault = cpu->translateDataReadReq(req, thread); @@ -942,7 +945,7 @@ BaseDynInst::translateDataWriteAddr(Addr vaddr, Addr &paddr, reqMade = true; Request *req = new Request(); req->setVirt(asid, vaddr, size, flags, PC); - req->setThreadContext(thread->cpuId(), threadNumber); + req->setThreadContext(thread->contextId(), threadNumber); fault = cpu->translateDataWriteReq(req, thread); @@ -966,7 +969,7 @@ BaseDynInst::write(T data, Addr addr, unsigned flags, uint64_t *res) reqMade = true; Request *req = new Request(); req->setVirt(asid, addr, sizeof(T), flags, this->PC); - req->setThreadContext(thread->cpuId(), threadNumber); + req->setThreadContext(thread->contextId(), threadNumber); fault = cpu->translateDataWriteReq(req, thread); diff --git a/src/cpu/checker/cpu_impl.hh b/src/cpu/checker/cpu_impl.hh index 9f6fa2b6d..0428e8806 100644 --- a/src/cpu/checker/cpu_impl.hh +++ b/src/cpu/checker/cpu_impl.hh @@ -152,7 +152,8 @@ Checker::verify(DynInstPtr &completed_inst) memReq = new Request(inst->threadNumber, fetch_PC, sizeof(uint32_t), IFETCH_FLAGS(thread->readPC()), - fetch_PC, thread->cpuId(), inst->threadNumber); + fetch_PC, thread->contextId(), + inst->threadNumber); bool succeeded = translateInstReq(memReq); diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index b7cf4f1c0..26c155262 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -589,9 +589,7 @@ template void FullO3CPU::init() { - if (!deferRegistration) { - registerThreadContexts(); - } + BaseCPU::init(); // Set inSyscall so that the CPU doesn't squash when initially // setting up registers. @@ -610,7 +608,7 @@ FullO3CPU::init() } #if FULL_SYSTEM - TheISA::initCPU(src_tc, src_tc->cpuId()); + TheISA::initCPU(src_tc, src_tc->contextId()); #endif } diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 35031663e..cff6db299 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -362,7 +362,7 @@ template void DefaultFetch::processCacheCompletion(PacketPtr pkt) { - unsigned tid = pkt->req->getThreadNum(); + unsigned tid = pkt->req->threadId(); DPRINTF(Fetch, "[tid:%u] Waking up from cache miss.\n",tid); @@ -593,7 +593,8 @@ DefaultFetch::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid // Set the appropriate read size and flags as well. // Build request here. RequestPtr mem_req = new Request(tid, block_PC, cacheBlkSize, 0, - fetch_PC, cpu->cpuId(), tid); + fetch_PC, cpu->thread[tid]->contextId(), + tid); memReq[tid] = mem_req; diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh index f8a825726..cf27552d4 100644 --- a/src/cpu/o3/lsq.hh +++ b/src/cpu/o3/lsq.hh @@ -371,7 +371,7 @@ template Fault LSQ::read(RequestPtr req, T &data, int load_idx) { - unsigned tid = req->getThreadNum(); + unsigned tid = req->threadId(); return thread[tid].read(req, data, load_idx); } @@ -381,7 +381,7 @@ template Fault LSQ::write(RequestPtr req, T &data, int store_idx) { - unsigned tid = req->getThreadNum(); + unsigned tid = req->threadId(); return thread[tid].write(req, data, store_idx); } diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh index 5aea020a9..8f9f63081 100644 --- a/src/cpu/o3/lsq_impl.hh +++ b/src/cpu/o3/lsq_impl.hh @@ -85,7 +85,7 @@ LSQ::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->getThreadNum()].completeDataAccess(pkt); + lsq->thread[pkt->req->threadId()].completeDataAccess(pkt); } else { // must be a snoop diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index d571d25db..c237b9587 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -78,6 +78,10 @@ class O3ThreadContext : public ThreadContext /** Reads this CPU's ID. */ virtual int cpuId() { return cpu->cpuId(); } + virtual int contextId() { return thread->contextId(); } + + virtual void setContextId(int id) { thread->setContextId(id); } + #if FULL_SYSTEM /** Returns a pointer to the system. */ virtual System *getSystemPtr() { return cpu->system; } diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index 853ee2c63..50f6e58b3 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -63,6 +63,7 @@ O3ThreadContext::takeOverFrom(ThreadContext *old_context) // copy over functional state setStatus(old_context->status()); copyArchRegs(old_context); + setContextId(old_context->contextId()); #if !FULL_SYSTEM thread->funcExeInst = old_context->readFuncExeInst(); diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index 52376afd8..eef1a7b2f 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -417,7 +417,7 @@ OzoneCPU::init() ThreadContext *tc = threadContexts[i]; // initialize CPU, including PC - TheISA::initCPU(tc, tc->cpuId()); + TheISA::initCPU(tc, tc->contextId()); } #endif frontEnd->renameTable.copyFrom(thread.renameTable); @@ -734,14 +734,6 @@ OzoneCPU::OzoneTC::getCpuPtr() return cpu; } -template -void -OzoneCPU::OzoneTC::setCpuId(int id) -{ - cpu->cpuId = id; - thread->setCpuId(id); -} - template void OzoneCPU::OzoneTC::setStatus(Status new_status) @@ -804,6 +796,7 @@ OzoneCPU::OzoneTC::takeOverFrom(ThreadContext *old_context) setStatus(old_context->status()); copyArchRegs(old_context); setCpuId(old_context->cpuId()); + setContextId(old_context->contextId()); thread->setInst(old_context->getInst()); #if !FULL_SYSTEM diff --git a/src/cpu/ozone/front_end_impl.hh b/src/cpu/ozone/front_end_impl.hh index df3609e27..b1e131115 100644 --- a/src/cpu/ozone/front_end_impl.hh +++ b/src/cpu/ozone/front_end_impl.hh @@ -477,7 +477,7 @@ FrontEnd::fetchCacheLine() // Setup the memReq to do a read of the first isntruction's address. // Set the appropriate read size and flags as well. memReq = new Request(0, fetch_PC, cacheBlkSize, 0, - PC, cpu->cpuId(), 0); + PC, cpu->thread->contextId()); // Translate the instruction request. fault = cpu->translateInstReq(memReq, thread); diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 5e8ab9443..feb8a7fc5 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -84,7 +84,7 @@ AtomicSimpleCPU::init() ThreadContext *tc = threadContexts[i]; // initialize CPU, including PC - TheISA::initCPU(tc, _cpuId); + TheISA::initCPU(tc, tc->contextId()); } #endif if (hasPhysMemPort) { @@ -93,6 +93,7 @@ AtomicSimpleCPU::init() physmemPort.getPeerAddressRanges(pmAddrList, snoop); physMemAddr = *pmAddrList.begin(); } + // Atomic doesn't do MT right now, so contextId == threadId ifetch_req.setThreadContext(_cpuId, 0); // Add thread ID if we add MT data_read_req.setThreadContext(_cpuId, 0); // Add thread ID here too data_write_req.setThreadContext(_cpuId, 0); // Add thread ID here too diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 247899ca8..ca1f0283e 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -202,7 +202,6 @@ TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU) _status = Idle; } assert(threadContexts.size() == 1); - _cpuId = tc->cpuId(); previousTick = curTick; } diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index 6034ca120..5c6b729b6 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -182,6 +182,8 @@ SimpleThread::copyState(ThreadContext *oldContext) funcExeInst = oldContext->readFuncExeInst(); #endif inst = oldContext->getInst(); + + _contextId = oldContext->contextId(); } void diff --git a/src/cpu/thread_context.cc b/src/cpu/thread_context.cc index 58912c564..ab105a435 100644 --- a/src/cpu/thread_context.cc +++ b/src/cpu/thread_context.cc @@ -78,4 +78,11 @@ ThreadContext::compare(ThreadContext *one, ThreadContext *two) int id2 = two->cpuId(); if (id1 != id2) panic("CPU ids don't match, one: %d, two: %d", id1, id2); + + id1 = one->contextId(); + id2 = two->contextId(); + if (id1 != id2) + panic("Context ids don't match, one: %d, two: %d", id1, id2); + + } diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index d06194012..a94be7024 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -117,6 +117,12 @@ class ThreadContext virtual int cpuId() = 0; + virtual int getThreadNum() = 0; + + virtual int contextId() = 0; + + virtual void setContextId(int id) = 0; + virtual TheISA::ITB *getITBPtr() = 0; virtual TheISA::DTB *getDTBPtr() = 0; @@ -177,8 +183,6 @@ class ThreadContext virtual void profileSample() = 0; #endif - virtual int getThreadNum() = 0; - // Also somewhat obnoxious. Really only used for the TLB fault. // However, may be quite useful in SPARC. virtual TheISA::MachInst getInst() = 0; @@ -300,6 +304,12 @@ class ProxyThreadContext : public ThreadContext int cpuId() { return actualTC->cpuId(); } + int getThreadNum() { return actualTC->getThreadNum(); } + + int contextId() { return actualTC->contextId(); } + + void setContextId(int id) { actualTC->setContextId(id); } + TheISA::ITB *getITBPtr() { return actualTC->getITBPtr(); } TheISA::DTB *getDTBPtr() { return actualTC->getDTBPtr(); } @@ -360,9 +370,6 @@ class ProxyThreadContext : public ThreadContext void profileClear() { return actualTC->profileClear(); } void profileSample() { return actualTC->profileSample(); } #endif - - int getThreadNum() { return actualTC->getThreadNum(); } - // @todo: Do I need this? MachInst getInst() { return actualTC->getInst(); } diff --git a/src/cpu/thread_state.hh b/src/cpu/thread_state.hh index f3f154de3..fdb2ab0ab 100644 --- a/src/cpu/thread_state.hh +++ b/src/cpu/thread_state.hh @@ -80,6 +80,10 @@ struct ThreadState { int cpuId() { return baseCpu->cpuId(); } + int contextId() { return _contextId; } + + void setContextId(int id) { _contextId = id; } + void setTid(int id) { tid = id; } int readTid() { return tid; } @@ -169,6 +173,9 @@ struct ThreadState { // Pointer to the base CPU. BaseCPU *baseCpu; + // system wide HW context id + int _contextId; + // Index of hardware thread context on the CPU that this represents. int tid; diff --git a/src/dev/alpha/backdoor.cc b/src/dev/alpha/backdoor.cc index 3ba6cbd24..66f682e66 100644 --- a/src/dev/alpha/backdoor.cc +++ b/src/dev/alpha/backdoor.cc @@ -84,7 +84,7 @@ void AlphaBackdoor::startup() { system->setAlphaAccess(pioAddr); - alphaAccess->numCPUs = system->getNumCPUs(); + alphaAccess->numCPUs = system->numContexts(); alphaAccess->kernStart = system->getKernelStart(); alphaAccess->kernEnd = system->getKernelEnd(); alphaAccess->entryPoint = system->getKernelEntry(); diff --git a/src/dev/alpha/tsunami_cchip.cc b/src/dev/alpha/tsunami_cchip.cc index 4477b5adc..52a2aea14 100644 --- a/src/dev/alpha/tsunami_cchip.cc +++ b/src/dev/alpha/tsunami_cchip.cc @@ -110,7 +110,13 @@ TsunamiCChip::read(PacketPtr pkt) break; case TSDEV_CC_MISC: pkt->set(((ipint << 8) & 0xF) | ((itint << 4) & 0xF) | - (pkt->req->getCpuNum() & 0x3)); + (pkt->req->contextId() & 0x3)); + // currently, FS cannot handle MT so contextId and + // cpuId are effectively the same, don't know if it will + // matter if FS becomes MT enabled. I suspect no because + // we are currently able to boot up to 64 procs anyway + // which would render the CPUID of this register useless + // anyway break; case TSDEV_CC_AAR0: case TSDEV_CC_AAR1: diff --git a/src/dev/mips/malta_cchip.cc b/src/dev/mips/malta_cchip.cc index 5a4ea4585..265977665 100755 --- a/src/dev/mips/malta_cchip.cc +++ b/src/dev/mips/malta_cchip.cc @@ -103,7 +103,7 @@ MaltaCChip::read(PacketPtr pkt) break; case TSDEV_CC_MISC: pkt->set((ipint << 8) & 0xF | (itint << 4) & 0xF | - (pkt->req->getCpuNum() & 0x3)); + (pkt->req->contextId() & 0x3)); break; case TSDEV_CC_AAR0: case TSDEV_CC_AAR1: diff --git a/src/dev/sinic.cc b/src/dev/sinic.cc index 49806d37c..bf7398e62 100644 --- a/src/dev/sinic.cc +++ b/src/dev/sinic.cc @@ -379,7 +379,7 @@ Device::read(PacketPtr pkt) assert(config.command & PCI_CMD_MSE); assert(pkt->getAddr() >= BARAddrs[0] && pkt->getSize() < BARSize[0]); - int cpu = pkt->req->getCpuNum(); + int cpu = pkt->req->contextId(); Addr daddr = pkt->getAddr() - BARAddrs[0]; Addr index = daddr >> Regs::VirtualShift; Addr raddr = daddr & Regs::VirtualMask; @@ -466,7 +466,7 @@ Device::write(PacketPtr pkt) assert(config.command & PCI_CMD_MSE); assert(pkt->getAddr() >= BARAddrs[0] && pkt->getSize() < BARSize[0]); - int cpu = pkt->req->getCpuNum(); + int cpu = pkt->req->contextId(); Addr daddr = pkt->getAddr() - BARAddrs[0]; Addr index = daddr >> Regs::VirtualShift; Addr raddr = daddr & Regs::VirtualMask; diff --git a/src/dev/sparc/iob.cc b/src/dev/sparc/iob.cc index 6608fc64a..f99ee5804 100644 --- a/src/dev/sparc/iob.cc +++ b/src/dev/sparc/iob.cc @@ -120,7 +120,7 @@ void Iob::readJBus(PacketPtr pkt) { Addr accessAddr = pkt->getAddr() - iobJBusAddr; - int cpuid = pkt->req->getCpuNum(); + int cpuid = pkt->req->contextId(); int index; uint64_t data; @@ -235,7 +235,7 @@ void Iob::writeJBus(PacketPtr pkt) { Addr accessAddr = pkt->getAddr() - iobJBusAddr; - int cpuid = pkt->req->getCpuNum(); + int cpuid = pkt->req->contextId(); int index; uint64_t data; diff --git a/src/mem/cache/blk.hh b/src/mem/cache/blk.hh index 9bfbd646d..bdf323d87 100644 --- a/src/mem/cache/blk.hh +++ b/src/mem/cache/blk.hh @@ -108,18 +108,16 @@ class CacheBlk */ class Lock { public: - int cpuNum; // locking CPU - int threadNum; // locking thread ID within CPU + int contextId; // locking context // check for matching execution context bool matchesContext(Request *req) { - return (cpuNum == req->getCpuNum() && - threadNum == req->getThreadNum()); + return (contextId == req->contextId()); } Lock(Request *req) - : cpuNum(req->getCpuNum()), threadNum(req->getThreadNum()) + : contextId(req->contextId()) { } }; diff --git a/src/mem/cache/prefetch/base.cc b/src/mem/cache/prefetch/base.cc index fcc02ff28..a7e6cfdfc 100644 --- a/src/mem/cache/prefetch/base.cc +++ b/src/mem/cache/prefetch/base.cc @@ -203,8 +203,8 @@ BasePrefetcher::handleMiss(PacketPtr &pkt, Tick time) PacketPtr prefetch; prefetch = new Packet(prefetchReq, MemCmd::HardPFReq, -1); prefetch->allocate(); - prefetch->req->setThreadContext(pkt->req->getCpuNum(), - pkt->req->getThreadNum()); + prefetch->req->setThreadContext(pkt->req->contextId(), + pkt->req->threadId()); prefetch->time = time + (*delay); //@todo ADD LATENCY HERE //... initialize diff --git a/src/mem/cache/prefetch/ghb.cc b/src/mem/cache/prefetch/ghb.cc index f5b88e1a6..c8b87e99d 100644 --- a/src/mem/cache/prefetch/ghb.cc +++ b/src/mem/cache/prefetch/ghb.cc @@ -42,16 +42,16 @@ GHBPrefetcher::calculatePrefetch(PacketPtr &pkt, std::list &addresses, std::list &delays) { Addr blkAddr = pkt->getAddr() & ~(Addr)(this->blkSize-1); - int cpuID = pkt->req->getCpuNum(); - if (!useCPUId) cpuID = 0; + int contextId = pkt->req->contextId(); + if (!useContextId) contextId = 0; - int new_stride = blkAddr - last_miss_addr[cpuID]; - int old_stride = last_miss_addr[cpuID] - - second_last_miss_addr[cpuID]; + int new_stride = blkAddr - last_miss_addr[contextId]; + int old_stride = last_miss_addr[contextId] - + second_last_miss_addr[contextId]; - second_last_miss_addr[cpuID] = last_miss_addr[cpuID]; - last_miss_addr[cpuID] = blkAddr; + second_last_miss_addr[contextId] = last_miss_addr[contextId]; + last_miss_addr[contextId] = blkAddr; if (new_stride == old_stride) { for (int d=1; d <= degree; d++) { diff --git a/src/mem/cache/prefetch/ghb.hh b/src/mem/cache/prefetch/ghb.hh index 4fb692016..156a74afa 100644 --- a/src/mem/cache/prefetch/ghb.hh +++ b/src/mem/cache/prefetch/ghb.hh @@ -47,13 +47,13 @@ class GHBPrefetcher : public BasePrefetcher Tick latency; int degree; - bool useCPUId; + bool useContextId; public: GHBPrefetcher(const BaseCacheParams *p) : BasePrefetcher(p), latency(p->prefetch_latency), - degree(p->prefetch_degree), useCPUId(p->prefetch_use_cpu_id) + degree(p->prefetch_degree), useContextId(p->prefetch_use_cpu_id) { } diff --git a/src/mem/cache/prefetch/stride.cc b/src/mem/cache/prefetch/stride.cc index e93058d6e..ad5846daa 100644 --- a/src/mem/cache/prefetch/stride.cc +++ b/src/mem/cache/prefetch/stride.cc @@ -41,18 +41,18 @@ StridePrefetcher::calculatePrefetch(PacketPtr &pkt, std::list &addresses, std::list &delays) { // Addr blkAddr = pkt->paddr & ~(Addr)(this->blkSize-1); - int cpuID = pkt->req->getCpuNum(); - if (!useCPUId) cpuID = 0; + int contextId = pkt->req->contextId(); + if (!useContextId) contextId = 0; /* Scan Table for IAddr Match */ /* std::list::iterator iter; - for (iter=table[cpuID].begin(); - iter !=table[cpuID].end(); + for (iter=table[contextId].begin(); + iter !=table[contextId].end(); iter++) { if ((*iter)->IAddr == pkt->pc) break; } - if (iter != table[cpuID].end()) { + if (iter != table[contextId].end()) { //Hit in table int newStride = blkAddr - (*iter)->MAddr; diff --git a/src/mem/cache/prefetch/stride.hh b/src/mem/cache/prefetch/stride.hh index ca173277c..4738fd9bc 100644 --- a/src/mem/cache/prefetch/stride.hh +++ b/src/mem/cache/prefetch/stride.hh @@ -63,14 +63,14 @@ class StridePrefetcher : public BasePrefetcher std::list table[64/*MAX_CPUS*/]; Tick latency; int degree; - bool useCPUId; + bool useContextId; public: StridePrefetcher(const BaseCacheParams *p) : BasePrefetcher(p), latency(p->prefetch_latency), - degree(p->prefetch_degree), useCPUId(p->prefetch_use_cpu_id) + degree(p->prefetch_degree), useContextId(p->prefetch_use_cpu_id) { } diff --git a/src/mem/physical.cc b/src/mem/physical.cc index 20e19669c..16ff3de6d 100644 --- a/src/mem/physical.cc +++ b/src/mem/physical.cc @@ -139,16 +139,16 @@ PhysicalMemory::trackLoadLocked(PacketPtr pkt) for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) { if (i->matchesContext(req)) { - DPRINTF(LLSC, "Modifying lock record: cpu %d thread %d addr %#x\n", - req->getCpuNum(), req->getThreadNum(), paddr); + DPRINTF(LLSC, "Modifying lock record: context %d addr %#x\n", + req->contextId(), paddr); i->addr = paddr; return; } } // no record for this xc: need to allocate a new one - DPRINTF(LLSC, "Adding lock record: cpu %d thread %d addr %#x\n", - req->getCpuNum(), req->getThreadNum(), paddr); + DPRINTF(LLSC, "Adding lock record: context %d addr %#x\n", + req->contextId(), paddr); lockedAddrList.push_front(LockedAddr(req)); } @@ -183,14 +183,14 @@ PhysicalMemory::checkLockedAddrList(PacketPtr pkt) // it's a store conditional, and as far as the memory // system can tell, the requesting context's lock is // still valid. - DPRINTF(LLSC, "StCond success: cpu %d thread %d addr %#x\n", - req->getCpuNum(), req->getThreadNum(), paddr); + DPRINTF(LLSC, "StCond success: context %d addr %#x\n", + req->contextId(), paddr); success = true; } // Get rid of our record of this lock and advance to next - DPRINTF(LLSC, "Erasing lock record: cpu %d thread %d addr %#x\n", - i->cpuNum, i->threadNum, paddr); + DPRINTF(LLSC, "Erasing lock record: context %d addr %#x\n", + i->contextId, paddr); i = lockedAddrList.erase(i); } else { diff --git a/src/mem/physical.hh b/src/mem/physical.hh index 2a0086ba9..d18138ecd 100644 --- a/src/mem/physical.hh +++ b/src/mem/physical.hh @@ -90,20 +90,17 @@ class PhysicalMemory : public MemObject static Addr mask(Addr paddr) { return (paddr & ~Addr_Mask); } Addr addr; // locked address - int cpuNum; // locking CPU - int threadNum; // locking thread ID within CPU + int contextId; // locking hw context // check for matching execution context bool matchesContext(Request *req) { - return (cpuNum == req->getCpuNum() && - threadNum == req->getThreadNum()); + return (contextId == req->contextId()); } LockedAddr(Request *req) : addr(mask(req->getPaddr())), - cpuNum(req->getCpuNum()), - threadNum(req->getThreadNum()) + contextId(req->contextId()) { } }; diff --git a/src/mem/request.hh b/src/mem/request.hh index 613655ea4..da0d9c7e0 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -115,10 +115,10 @@ class Request : public FastAlloc * store conditional or the compare value for a CAS. */ uint64_t extraData; - /** The cpu number (for statistics, typically). */ - int cpuNum; - /** The requesting thread id (for statistics, typically). */ - int threadNum; + /** The context ID (for statistics, typically). */ + int _contextId; + /** The thread ID (id within this CPU) */ + int _threadId; /** program counter of initiating access; for tracing/debugging */ Addr pc; @@ -129,8 +129,8 @@ class Request : public FastAlloc bool validAsidVaddr; /** Whether or not the sc result is valid. */ bool validExData; - /** Whether or not the cpu number & thread ID are valid. */ - bool validCpuAndThreadNums; + /** Whether or not the context ID is valid. */ + bool validContextAndThreadIds; /** Whether or not the pc is valid. */ bool validPC; @@ -138,7 +138,7 @@ class Request : public FastAlloc /** Minimal constructor. No fields are initialized. */ Request() : validPaddr(false), validAsidVaddr(false), - validExData(false), validCpuAndThreadNums(false), validPC(false) + validExData(false), validContextAndThreadIds(false), validPC(false) {} /** @@ -146,13 +146,13 @@ class Request : public FastAlloc * just physical address, size, flags, and timestamp (to curTick). * These fields are adequate to perform a request. */ Request(Addr _paddr, int _size, int _flags) - : validCpuAndThreadNums(false) + : validContextAndThreadIds(false) { setPhys(_paddr, _size, _flags); } Request(int _asid, Addr _vaddr, int _size, int _flags, Addr _pc, - int _cpuNum, int _threadNum) + int _context_id, int _thread_id) { - setThreadContext(_cpuNum, _threadNum); + setThreadContext(_context_id, _thread_id); setVirt(_asid, _vaddr, _size, _flags, _pc); } @@ -160,11 +160,11 @@ class Request : public FastAlloc /** * Set up CPU and thread numbers. */ - void setThreadContext(int _cpuNum, int _threadNum) + void setThreadContext(int _context_id, int _thread_id) { - cpuNum = _cpuNum; - threadNum = _threadNum; - validCpuAndThreadNums = true; + _contextId = _context_id; + _threadId = _thread_id; + validContextAndThreadIds = true; } /** @@ -261,10 +261,10 @@ class Request : public FastAlloc void setExtraData(uint64_t _extraData) { extraData = _extraData; validExData = true; } - /** Accessor function for cpu number.*/ - int getCpuNum() { assert(validCpuAndThreadNums); return cpuNum; } - /** Accessor function for thread number.*/ - int getThreadNum() { assert(validCpuAndThreadNums); return threadNum; } + /** Accessor function for context ID.*/ + int contextId() { assert(validContextAndThreadIds); return _contextId; } + /** Accessor function for thread ID. */ + int threadId() { assert(validContextAndThreadIds); return _threadId; } /** Accessor function for pc.*/ Addr getPC() { assert(validPC); return pc; } diff --git a/src/sim/system.cc b/src/sim/system.cc index 8f25b4bb8..9704c83f0 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -58,7 +58,7 @@ vector System::systemList; int System::numSystemsRunning = 0; System::System(Params *p) - : SimObject(p), physmem(p->physmem), numcpus(0), + : SimObject(p), physmem(p->physmem), _numContexts(0), #if FULL_SYSTEM init_param(p->init_param), functionalPort(p->name + "-fport"), @@ -181,7 +181,7 @@ System::registerThreadContext(ThreadContext *tc) panic("Cannot have two CPUs with the same id (%d)\n", id); threadContexts[id] = tc; - numcpus++; + _numContexts++; int port = getRemoteGDBPort(); if (rgdb_enable && port) { diff --git a/src/sim/system.hh b/src/sim/system.hh index 26cac714b..e993a7a50 100644 --- a/src/sim/system.hh +++ b/src/sim/system.hh @@ -87,19 +87,19 @@ class System : public SimObject PCEventQueue pcEventQueue; std::vector threadContexts; - int numcpus; + int _numContexts; ThreadContext * getThreadContext(int tid) { return threadContexts[tid]; } - int getNumCPUs() + int numContexts() { - if (numcpus != threadContexts.size()) + if (_numContexts != threadContexts.size()) panic("cpu array not fully populated!"); - return numcpus; + return _numContexts; } #if FULL_SYSTEM -- cgit v1.2.3 From dd99ff23c6a71f7173014b5008d0cf12b7ef223a Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Tue, 4 Nov 2008 11:35:42 -0500 Subject: get rid of all instances of readTid() and getThreadNum(). Unify and eliminate redundancies with threadId() as their replacement. --- src/arch/mips/isa/formats/mt.isa | 4 +- src/arch/mips/locked_mem.hh | 6 +-- src/arch/mips/mt.hh | 8 ++-- src/arch/mips/utility.cc | 2 +- src/cpu/base.cc | 1 + src/cpu/base.hh | 2 +- src/cpu/checker/thread_context.hh | 2 +- src/cpu/exetrace.cc | 2 +- src/cpu/o3/thread_context.hh | 25 ++++++------ src/cpu/o3/thread_context_impl.hh | 85 ++++++++++++++++++++------------------- src/cpu/ozone/cpu.hh | 4 +- src/cpu/ozone/cpu_impl.hh | 16 ++++---- src/cpu/simple_thread.cc | 11 ++--- src/cpu/simple_thread.hh | 2 - src/cpu/thread_context.hh | 8 +++- src/cpu/thread_state.cc | 10 ++--- src/cpu/thread_state.hh | 6 +-- src/mem/cache/base.hh | 2 +- src/mem/cache/cache_impl.hh | 20 ++++----- src/mem/cache/mshr_queue.cc | 2 +- 20 files changed, 112 insertions(+), 106 deletions(-) (limited to 'src') diff --git a/src/arch/mips/isa/formats/mt.isa b/src/arch/mips/isa/formats/mt.isa index 81fdc2898..1928ee903 100644 --- a/src/arch/mips/isa/formats/mt.isa +++ b/src/arch/mips/isa/formats/mt.isa @@ -196,7 +196,7 @@ def format MT_Control(code, *opt_flags) {{ def format MT_MFTR(code, *flags) {{ flags += ('IsNonSpeculative', ) -# code = 'std::cerr << curTick << \": T\" << xc->tcBase()->getThreadNum() << \": Executing MT INST: ' + name + '\" << endl;\n' + code +# code = 'std::cerr << curTick << \": T\" << xc->tcBase()->threadId() << \": Executing MT INST: ' + name + '\" << endl;\n' + code code += 'if (MT_H == 1) {\n' code += 'data = bits(data, top_bit, bottom_bit);\n' @@ -212,7 +212,7 @@ def format MT_MFTR(code, *flags) {{ def format MT_MTTR(code, *flags) {{ flags += ('IsNonSpeculative', ) -# code = 'std::cerr << curTick << \": T\" << xc->tcBase()->getThreadNum() << \": Executing MT INST: ' + name + '\" << endl;\n' + code +# code = 'std::cerr << curTick << \": T\" << xc->tcBase()->threadId() << \": Executing MT INST: ' + name + '\" << endl;\n' + code iop = InstObjParams(name, Name, 'MTOp', code, flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) diff --git a/src/arch/mips/locked_mem.hh b/src/arch/mips/locked_mem.hh index 9f41ba075..021b8cf73 100644 --- a/src/arch/mips/locked_mem.hh +++ b/src/arch/mips/locked_mem.hh @@ -52,7 +52,7 @@ handleLockedRead(XC *xc, Request *req) xc->setMiscRegNoEffect(LLAddr, req->getPaddr() & ~0xf); xc->setMiscRegNoEffect(LLFlag, true); DPRINTF(LLSC, "[tid:%i]: Load-Link Flag Set & Load-Link Address set to %x.\n", - req->getThreadNum(), req->getPaddr() & ~0xf); + req->threadId(), req->getPaddr() & ~0xf); } @@ -94,10 +94,10 @@ handleLockedWrite(XC *xc, Request *req) if (!lock_flag){ DPRINTF(LLSC, "[tid:%i]: Lock Flag Set, Store Conditional Failed.\n", - req->getThreadNum()); + req->threadId()); } else if ((req->getPaddr() & ~0xf) != lock_addr) { DPRINTF(LLSC, "[tid:%i]: Load-Link Address Mismatch, Store Conditional Failed.\n", - req->getThreadNum()); + req->threadId()); } // store conditional failed already, so don't issue it to mem return false; diff --git a/src/arch/mips/mt.hh b/src/arch/mips/mt.hh index 20658df28..8828a09a5 100755 --- a/src/arch/mips/mt.hh +++ b/src/arch/mips/mt.hh @@ -78,7 +78,7 @@ haltThread(TC *tc) // @TODO: Needs to check if this is a branch and if so, take previous instruction tc->setMiscReg(TCRestart, tc->readNextPC()); - warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x", curTick, tc->getThreadNum(), tc->getCpuPtr()->name(), + warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x", curTick, tc->threadId(), tc->getCpuPtr()->name(), tc->readPC(), tc->readNextPC()); } } @@ -98,7 +98,7 @@ restoreThread(TC *tc) tc->setNextNPC(pc + 8); tc->activate(0); - warn("%i: Restoring thread %i in %s @ PC %x", curTick, tc->getThreadNum(), tc->getCpuPtr()->name(), + warn("%i: Restoring thread %i in %s @ PC %x", curTick, tc->threadId(), tc->getCpuPtr()->name(), tc->readPC()); } } @@ -217,7 +217,7 @@ yieldThread(TC *tc, Fault &fault, int src_reg, uint32_t yield_mask) if (ok == 1) { unsigned tcstatus = tc->readMiscRegNoEffect(TCStatus); tc->setMiscReg(TCStatus, insertBits(tcstatus, TCS_A, TCS_A, 0)); - warn("%i: Deactivating Hardware Thread Context #%i", curTick, tc->getThreadNum()); + warn("%i: Deactivating Hardware Thread Context #%i", curTick, tc->threadId()); } } else if (src_reg > 0) { if (src_reg && !yield_mask != 0) { @@ -238,7 +238,7 @@ yieldThread(TC *tc, Fault &fault, int src_reg, uint32_t yield_mask) fault = new ThreadFault(); } else { //tc->ScheduleOtherThreads(); - //std::cerr << "T" << tc->getThreadNum() << "YIELD: Schedule Other Threads.\n" << std::endl; + //std::cerr << "T" << tc->threadId() << "YIELD: Schedule Other Threads.\n" << std::endl; //tc->suspend(); // Save last known PC in TCRestart // @TODO: Needs to check if this is a branch and if so, take previous instruction diff --git a/src/arch/mips/utility.cc b/src/arch/mips/utility.cc index 1985c0f43..5908caf68 100644 --- a/src/arch/mips/utility.cc +++ b/src/arch/mips/utility.cc @@ -259,7 +259,7 @@ zeroRegisters(CPU *cpu) void startupCPU(ThreadContext *tc, int cpuId) { - tc->activate(0/*tc->getThreadNum()*/); + tc->activate(0/*tc->threadId()*/); } } // namespace MipsISA diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 6409255f6..1fa7add65 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -329,6 +329,7 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc) CpuEvent::replaceThreadContext(oldTC, newTC); assert(newTC->contextId() == oldTC->contextId()); + assert(newTC->threadId() == oldTC->threadId()); system->replaceThreadContext(newTC, newTC->contextId()); if (DTRACE(Context)) diff --git a/src/cpu/base.hh b/src/cpu/base.hh index f39759605..83d73ede0 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -82,7 +82,7 @@ class BaseCPU : public MemObject Tick instCnt; // every cpu has an id, put it in the base cpu // Set at initialization, only time a cpuId might change is during a - // takeover (which should be done from within the BaseCPU anyway, + // takeover (which should be done from within the BaseCPU anyway, // therefore no setCpuId() method is provided int _cpuId; diff --git a/src/cpu/checker/thread_context.hh b/src/cpu/checker/thread_context.hh index a74de20b9..524e87cd4 100644 --- a/src/cpu/checker/thread_context.hh +++ b/src/cpu/checker/thread_context.hh @@ -153,7 +153,7 @@ class CheckerThreadContext : public ThreadContext void profileSample() { return actualTC->profileSample(); } #endif - int getThreadNum() { return actualTC->getThreadNum(); } + int threadId() { return actualTC->threadId(); } // @todo: Do I need this? MachInst getInst() { return actualTC->getInst(); } diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc index 0118dbde1..824fbb5f6 100644 --- a/src/cpu/exetrace.cc +++ b/src/cpu/exetrace.cc @@ -59,7 +59,7 @@ Trace::ExeTracerRecord::dump() outs << (misspeculating ? "-" : "+") << " "; if (IsOn(ExecThread)) - outs << "T" << thread->getThreadNum() << " : "; + outs << "T" << thread->threadId() << " : "; std::string sym_str; diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index c237b9587..8682e071e 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -82,6 +82,10 @@ class O3ThreadContext : public ThreadContext virtual void setContextId(int id) { thread->setContextId(id); } + /** Returns this thread's ID number. */ + virtual int threadId() { return thread->threadId(); } + virtual void setThreadId(int id) { return thread->setThreadId(id); } + #if FULL_SYSTEM /** Returns a pointer to the system. */ virtual System *getSystemPtr() { return cpu->system; } @@ -152,9 +156,6 @@ class O3ThreadContext : public ThreadContext /** Samples the function profiling information. */ virtual void profileSample(); #endif - /** Returns this thread's ID number. */ - virtual int getThreadNum() { return thread->readTid(); } - /** Returns the instruction this thread is currently committing. * Only used when an instruction faults. */ @@ -190,36 +191,36 @@ class O3ThreadContext : public ThreadContext /** Reads this thread's PC. */ virtual uint64_t readPC() - { return cpu->readPC(thread->readTid()); } + { return cpu->readPC(thread->threadId()); } /** Sets this thread's PC. */ virtual void setPC(uint64_t val); /** Reads this thread's next PC. */ virtual uint64_t readNextPC() - { return cpu->readNextPC(thread->readTid()); } + { return cpu->readNextPC(thread->threadId()); } /** Sets this thread's next PC. */ virtual void setNextPC(uint64_t val); virtual uint64_t readMicroPC() - { return cpu->readMicroPC(thread->readTid()); } + { return cpu->readMicroPC(thread->threadId()); } virtual void setMicroPC(uint64_t val); virtual uint64_t readNextMicroPC() - { return cpu->readNextMicroPC(thread->readTid()); } + { return cpu->readNextMicroPC(thread->threadId()); } virtual void setNextMicroPC(uint64_t val); /** Reads a miscellaneous register. */ virtual MiscReg readMiscRegNoEffect(int misc_reg) - { return cpu->readMiscRegNoEffect(misc_reg, thread->readTid()); } + { return cpu->readMiscRegNoEffect(misc_reg, thread->threadId()); } /** Reads a misc. register, including any side-effects the * read might have as defined by the architecture. */ virtual MiscReg readMiscReg(int misc_reg) - { return cpu->readMiscReg(misc_reg, thread->readTid()); } + { return cpu->readMiscReg(misc_reg, thread->threadId()); } /** Sets a misc. register. */ virtual void setMiscRegNoEffect(int misc_reg, const MiscReg &val); @@ -257,7 +258,7 @@ class O3ThreadContext : public ThreadContext /** Executes a syscall in SE mode. */ virtual void syscall(int64_t callnum) - { return cpu->syscall(callnum, thread->readTid()); } + { return cpu->syscall(callnum, thread->threadId()); } /** Reads the funcExeInst counter. */ virtual Counter readFuncExeInst() { return thread->funcExeInst; } @@ -271,7 +272,7 @@ class O3ThreadContext : public ThreadContext virtual uint64_t readNextNPC() { - return this->cpu->readNextNPC(this->thread->readTid()); + return this->cpu->readNextNPC(this->thread->threadId()); } virtual void setNextNPC(uint64_t val) @@ -279,7 +280,7 @@ class O3ThreadContext : public ThreadContext #if THE_ISA == ALPHA_ISA panic("Not supported on Alpha!"); #endif - this->cpu->setNextNPC(val, this->thread->readTid()); + this->cpu->setNextNPC(val, this->thread->threadId()); } /** This function exits the thread context in the CPU and returns diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index 50f6e58b3..735827ebc 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -64,6 +64,7 @@ O3ThreadContext::takeOverFrom(ThreadContext *old_context) setStatus(old_context->status()); copyArchRegs(old_context); setContextId(old_context->contextId()); + setThreadId(old_context->threadId()); #if !FULL_SYSTEM thread->funcExeInst = old_context->readFuncExeInst(); @@ -95,7 +96,7 @@ void O3ThreadContext::activate(int delay) { DPRINTF(O3CPU, "Calling activate on Thread Context %d\n", - getThreadNum()); + threadId()); if (thread->status() == ThreadContext::Active) return; @@ -105,14 +106,14 @@ O3ThreadContext::activate(int delay) #endif if (thread->status() == ThreadContext::Unallocated) { - cpu->activateWhenReady(thread->readTid()); + cpu->activateWhenReady(thread->threadId()); return; } thread->setStatus(ThreadContext::Active); // status() == Suspended - cpu->activateContext(thread->readTid(), delay); + cpu->activateContext(thread->threadId(), delay); } template @@ -120,7 +121,7 @@ void O3ThreadContext::suspend(int delay) { DPRINTF(O3CPU, "Calling suspend on Thread Context %d\n", - getThreadNum()); + threadId()); if (thread->status() == ThreadContext::Suspended) return; @@ -139,7 +140,7 @@ O3ThreadContext::suspend(int delay) #endif */ thread->setStatus(ThreadContext::Suspended); - cpu->suspendContext(thread->readTid()); + cpu->suspendContext(thread->threadId()); } template @@ -147,13 +148,13 @@ void O3ThreadContext::deallocate(int delay) { DPRINTF(O3CPU, "Calling deallocate on Thread Context %d delay %d\n", - getThreadNum(), delay); + threadId(), delay); if (thread->status() == ThreadContext::Unallocated) return; thread->setStatus(ThreadContext::Unallocated); - cpu->deallocateContext(thread->readTid(), true, delay); + cpu->deallocateContext(thread->threadId(), true, delay); } template @@ -161,13 +162,13 @@ void O3ThreadContext::halt(int delay) { DPRINTF(O3CPU, "Calling halt on Thread Context %d\n", - getThreadNum()); + threadId()); if (thread->status() == ThreadContext::Halted) return; thread->setStatus(ThreadContext::Halted); - cpu->haltContext(thread->readTid()); + cpu->haltContext(thread->threadId()); } template @@ -245,7 +246,7 @@ O3ThreadContext::copyArchRegs(ThreadContext *tc) { // This function will mess things up unless the ROB is empty and // there are no instructions in the pipeline. - unsigned tid = thread->readTid(); + unsigned tid = thread->threadId(); PhysRegIndex renamed_reg; // First loop through the integer registers. @@ -292,7 +293,7 @@ uint64_t O3ThreadContext::readIntReg(int reg_idx) { reg_idx = TheISA::flattenIntIndex(this, reg_idx); - return cpu->readArchIntReg(reg_idx, thread->readTid()); + return cpu->readArchIntReg(reg_idx, thread->threadId()); } template @@ -302,9 +303,9 @@ O3ThreadContext::readFloatReg(int reg_idx, int width) reg_idx = TheISA::flattenFloatIndex(this, reg_idx); switch(width) { case 32: - return cpu->readArchFloatRegSingle(reg_idx, thread->readTid()); + return cpu->readArchFloatRegSingle(reg_idx, thread->threadId()); case 64: - return cpu->readArchFloatRegDouble(reg_idx, thread->readTid()); + return cpu->readArchFloatRegDouble(reg_idx, thread->threadId()); default: panic("Unsupported width!"); return 0; @@ -316,7 +317,7 @@ TheISA::FloatReg O3ThreadContext::readFloatReg(int reg_idx) { reg_idx = TheISA::flattenFloatIndex(this, reg_idx); - return cpu->readArchFloatRegSingle(reg_idx, thread->readTid()); + return cpu->readArchFloatRegSingle(reg_idx, thread->threadId()); } template @@ -325,7 +326,7 @@ O3ThreadContext::readFloatRegBits(int reg_idx, int width) { DPRINTF(Fault, "Reading floatint register through the TC!\n"); reg_idx = TheISA::flattenFloatIndex(this, reg_idx); - return cpu->readArchFloatRegInt(reg_idx, thread->readTid()); + return cpu->readArchFloatRegInt(reg_idx, thread->threadId()); } template @@ -333,7 +334,7 @@ TheISA::FloatRegBits O3ThreadContext::readFloatRegBits(int reg_idx) { reg_idx = TheISA::flattenFloatIndex(this, reg_idx); - return cpu->readArchFloatRegInt(reg_idx, thread->readTid()); + return cpu->readArchFloatRegInt(reg_idx, thread->threadId()); } template @@ -341,11 +342,11 @@ void O3ThreadContext::setIntReg(int reg_idx, uint64_t val) { reg_idx = TheISA::flattenIntIndex(this, reg_idx); - cpu->setArchIntReg(reg_idx, val, thread->readTid()); + cpu->setArchIntReg(reg_idx, val, thread->threadId()); // Squash if we're not already in a state update mode. if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->readTid()); + cpu->squashFromTC(thread->threadId()); } } @@ -356,16 +357,16 @@ O3ThreadContext::setFloatReg(int reg_idx, FloatReg val, int width) reg_idx = TheISA::flattenFloatIndex(this, reg_idx); switch(width) { case 32: - cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid()); + cpu->setArchFloatRegSingle(reg_idx, val, thread->threadId()); break; case 64: - cpu->setArchFloatRegDouble(reg_idx, val, thread->readTid()); + cpu->setArchFloatRegDouble(reg_idx, val, thread->threadId()); break; } // Squash if we're not already in a state update mode. if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->readTid()); + cpu->squashFromTC(thread->threadId()); } } @@ -374,10 +375,10 @@ void O3ThreadContext::setFloatReg(int reg_idx, FloatReg val) { reg_idx = TheISA::flattenFloatIndex(this, reg_idx); - cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid()); + cpu->setArchFloatRegSingle(reg_idx, val, thread->threadId()); if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->readTid()); + cpu->squashFromTC(thread->threadId()); } } @@ -388,11 +389,11 @@ O3ThreadContext::setFloatRegBits(int reg_idx, FloatRegBits val, { DPRINTF(Fault, "Setting floatint register through the TC!\n"); reg_idx = TheISA::flattenFloatIndex(this, reg_idx); - cpu->setArchFloatRegInt(reg_idx, val, thread->readTid()); + cpu->setArchFloatRegInt(reg_idx, val, thread->threadId()); // Squash if we're not already in a state update mode. if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->readTid()); + cpu->squashFromTC(thread->threadId()); } } @@ -401,11 +402,11 @@ void O3ThreadContext::setFloatRegBits(int reg_idx, FloatRegBits val) { reg_idx = TheISA::flattenFloatIndex(this, reg_idx); - cpu->setArchFloatRegInt(reg_idx, val, thread->readTid()); + cpu->setArchFloatRegInt(reg_idx, val, thread->threadId()); // Squash if we're not already in a state update mode. if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->readTid()); + cpu->squashFromTC(thread->threadId()); } } @@ -413,11 +414,11 @@ template void O3ThreadContext::setPC(uint64_t val) { - cpu->setPC(val, thread->readTid()); + cpu->setPC(val, thread->threadId()); // Squash if we're not already in a state update mode. if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->readTid()); + cpu->squashFromTC(thread->threadId()); } } @@ -425,11 +426,11 @@ template void O3ThreadContext::setNextPC(uint64_t val) { - cpu->setNextPC(val, thread->readTid()); + cpu->setNextPC(val, thread->threadId()); // Squash if we're not already in a state update mode. if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->readTid()); + cpu->squashFromTC(thread->threadId()); } } @@ -437,11 +438,11 @@ template void O3ThreadContext::setMicroPC(uint64_t val) { - cpu->setMicroPC(val, thread->readTid()); + cpu->setMicroPC(val, thread->threadId()); // Squash if we're not already in a state update mode. if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->readTid()); + cpu->squashFromTC(thread->threadId()); } } @@ -449,11 +450,11 @@ template void O3ThreadContext::setNextMicroPC(uint64_t val) { - cpu->setNextMicroPC(val, thread->readTid()); + cpu->setNextMicroPC(val, thread->threadId()); // Squash if we're not already in a state update mode. if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->readTid()); + cpu->squashFromTC(thread->threadId()); } } @@ -461,11 +462,11 @@ template void O3ThreadContext::setMiscRegNoEffect(int misc_reg, const MiscReg &val) { - cpu->setMiscRegNoEffect(misc_reg, val, thread->readTid()); + cpu->setMiscRegNoEffect(misc_reg, val, thread->threadId()); // Squash if we're not already in a state update mode. if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->readTid()); + cpu->squashFromTC(thread->threadId()); } } @@ -474,11 +475,11 @@ void O3ThreadContext::setMiscReg(int misc_reg, const MiscReg &val) { - cpu->setMiscReg(misc_reg, val, thread->readTid()); + cpu->setMiscReg(misc_reg, val, thread->threadId()); // Squash if we're not already in a state update mode. if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->readTid()); + cpu->squashFromTC(thread->threadId()); } } @@ -488,21 +489,21 @@ template TheISA::IntReg O3ThreadContext::getSyscallArg(int i) { - return cpu->getSyscallArg(i, thread->readTid()); + return cpu->getSyscallArg(i, thread->threadId()); } template void O3ThreadContext::setSyscallArg(int i, IntReg val) { - cpu->setSyscallArg(i, val, thread->readTid()); + cpu->setSyscallArg(i, val, thread->threadId()); } template void O3ThreadContext::setSyscallReturn(SyscallReturn return_value) { - cpu->setSyscallReturn(return_value, thread->readTid()); + cpu->setSyscallReturn(return_value, thread->threadId()); } #endif // FULL_SYSTEM diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index 8fce61d4f..cc371ed93 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -176,7 +176,7 @@ class OzoneCPU : public BaseCPU void profileSample(); #endif - int getThreadNum(); + int threadId(); // Also somewhat obnoxious. Really only used for the TLB fault. TheISA::MachInst getInst(); @@ -260,7 +260,7 @@ class OzoneCPU : public BaseCPU } void setSyscallReturn(SyscallReturn return_value) - { cpu->setSyscallReturn(return_value, thread->readTid()); } + { cpu->setSyscallReturn(return_value, thread->threadId()); } Counter readFuncExeInst() { return thread->funcExeInst; } diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index eef1a7b2f..93848c03f 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -588,7 +588,7 @@ OzoneCPU::postInterrupt(int int_num, int index) // thread.activate(); // Hack for now. Otherwise might have to go through the tc, or // I need to figure out what's the right thing to call. - activateContext(thread.readTid(), 1); + activateContext(thread.threadId(), 1); } } #endif // FULL_SYSTEM @@ -711,7 +711,7 @@ OzoneCPU::simPalCheck(int palFunc) switch (palFunc) { case PAL::halt: - haltContext(thread.readTid()); + haltContext(thread.threadId()); if (--System::numSystemsRunning == 0) exitSimLoop("all cpus halted"); break; @@ -745,7 +745,7 @@ template void OzoneCPU::OzoneTC::activate(int delay) { - cpu->activateContext(thread->readTid(), delay); + cpu->activateContext(thread->threadId(), delay); } /// Set the status to Suspended. @@ -753,7 +753,7 @@ template void OzoneCPU::OzoneTC::suspend() { - cpu->suspendContext(thread->readTid()); + cpu->suspendContext(thread->threadId()); } /// Set the status to Unallocated. @@ -761,7 +761,7 @@ template void OzoneCPU::OzoneTC::deallocate(int delay) { - cpu->deallocateContext(thread->readTid(), delay); + cpu->deallocateContext(thread->threadId(), delay); } /// Set the status to Halted. @@ -769,7 +769,7 @@ template void OzoneCPU::OzoneTC::halt() { - cpu->haltContext(thread->readTid()); + cpu->haltContext(thread->threadId()); } #if FULL_SYSTEM @@ -884,9 +884,9 @@ OzoneCPU::OzoneTC::profileSample() template int -OzoneCPU::OzoneTC::getThreadNum() +OzoneCPU::OzoneTC::threadId() { - return thread->readTid(); + return thread->threadId(); } template diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index 5c6b729b6..af0bb4490 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -183,6 +183,7 @@ SimpleThread::copyState(ThreadContext *oldContext) #endif inst = oldContext->getInst(); + _threadId = oldContext->threadId(); _contextId = oldContext->contextId(); } @@ -221,14 +222,14 @@ SimpleThread::activate(int delay) lastActivate = curTick; // if (status() == ThreadContext::Unallocated) { -// cpu->activateWhenReady(tid); +// cpu->activateWhenReady(_threadId); // return; // } _status = ThreadContext::Active; // status() == Suspended - cpu->activateContext(tid, delay); + cpu->activateContext(_threadId, delay); } void @@ -249,7 +250,7 @@ SimpleThread::suspend() #endif */ _status = ThreadContext::Suspended; - cpu->suspendContext(tid); + cpu->suspendContext(_threadId); } void @@ -259,7 +260,7 @@ SimpleThread::deallocate() return; _status = ThreadContext::Unallocated; - cpu->deallocateContext(tid); + cpu->deallocateContext(_threadId); } void @@ -269,7 +270,7 @@ SimpleThread::halt() return; _status = ThreadContext::Halted; - cpu->haltContext(tid); + cpu->haltContext(_threadId); } diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index 189cbeec5..a503ab600 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -197,8 +197,6 @@ class SimpleThread : public ThreadState BaseCPU *getCpuPtr() { return cpu; } - int getThreadNum() { return tid; } - TheISA::ITB *getITBPtr() { return itb; } TheISA::DTB *getDTBPtr() { return dtb; } diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index a94be7024..9ee5250a3 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -117,7 +117,9 @@ class ThreadContext virtual int cpuId() = 0; - virtual int getThreadNum() = 0; + virtual int threadId() = 0; + + virtual void setThreadId(int id) = 0; virtual int contextId() = 0; @@ -304,7 +306,9 @@ class ProxyThreadContext : public ThreadContext int cpuId() { return actualTC->cpuId(); } - int getThreadNum() { return actualTC->getThreadNum(); } + int threadId() { return actualTC->threadId(); } + + void setThreadId(int id) { return actualTC->setThreadId(id); } int contextId() { return actualTC->contextId(); } diff --git a/src/cpu/thread_state.cc b/src/cpu/thread_state.cc index 47841922e..b0e719ddf 100644 --- a/src/cpu/thread_state.cc +++ b/src/cpu/thread_state.cc @@ -44,14 +44,14 @@ #if FULL_SYSTEM ThreadState::ThreadState(BaseCPU *cpu, int _tid) - : baseCpu(cpu), tid(_tid), lastActivate(0), lastSuspend(0), + : baseCpu(cpu), _threadId(_tid), lastActivate(0), lastSuspend(0), profile(NULL), profileNode(NULL), profilePC(0), quiesceEvent(NULL), kernelStats(NULL), physPort(NULL), virtPort(NULL), microPC(0), nextMicroPC(1), funcExeInst(0), storeCondFailures(0) #else ThreadState::ThreadState(BaseCPU *cpu, int _tid, Process *_process, short _asid) - : baseCpu(cpu), tid(_tid), lastActivate(0), lastSuspend(0), + : baseCpu(cpu), _threadId(_tid), lastActivate(0), lastSuspend(0), port(NULL), process(_process), asid(_asid), microPC(0), nextMicroPC(1), funcExeInst(0), storeCondFailures(0) #endif @@ -129,7 +129,7 @@ ThreadState::connectPhysPort() physPort->removeConn(); else physPort = new FunctionalPort(csprintf("%s-%d-funcport", - baseCpu->name(), tid)); + baseCpu->name(), _threadId)); connectToMemFunc(physPort); } @@ -143,7 +143,7 @@ ThreadState::connectVirtPort(ThreadContext *tc) virtPort->removeConn(); else virtPort = new VirtualPort(csprintf("%s-%d-vport", - baseCpu->name(), tid), tc); + baseCpu->name(), _threadId), tc); connectToMemFunc(virtPort); } @@ -169,7 +169,7 @@ ThreadState::getMemPort() return port; /* Use this port to for syscall emulation writes to memory. */ - port = new TranslatingPort(csprintf("%s-%d-funcport", baseCpu->name(), tid), + port = new TranslatingPort(csprintf("%s-%d-funcport", baseCpu->name(), _threadId), process, TranslatingPort::NextPage); connectToMemFunc(port); diff --git a/src/cpu/thread_state.hh b/src/cpu/thread_state.hh index fdb2ab0ab..4465ce635 100644 --- a/src/cpu/thread_state.hh +++ b/src/cpu/thread_state.hh @@ -84,9 +84,9 @@ struct ThreadState { void setContextId(int id) { _contextId = id; } - void setTid(int id) { tid = id; } + void setThreadId(int id) { _threadId = id; } - int readTid() { return tid; } + int threadId() { return _threadId; } Tick readLastActivate() { return lastActivate; } @@ -177,7 +177,7 @@ struct ThreadState { int _contextId; // Index of hardware thread context on the CPU that this represents. - int tid; + int _threadId; public: /** Last time activate was called on this thread. */ diff --git a/src/mem/cache/base.hh b/src/mem/cache/base.hh index d97021024..601e9bd48 100644 --- a/src/mem/cache/base.hh +++ b/src/mem/cache/base.hh @@ -481,7 +481,7 @@ class BaseCache : public MemObject void incMissCount(PacketPtr pkt) { - misses[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++; + misses[pkt->cmdToIndex()][0/*pkt->req->threadId()*/]++; if (missCount) { --missCount; diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index abe3f9b5f..45faa84ce 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -296,7 +296,7 @@ Cache::access(PacketPtr pkt, BlkType *&blk, if (pkt->needsExclusive() ? blk->isWritable() : blk->isReadable()) { // OK to satisfy access - hits[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++; + hits[pkt->cmdToIndex()][0/*pkt->req->threadId()*/]++; satisfyCpuSideRequest(pkt, blk); return true; } @@ -325,7 +325,7 @@ Cache::access(PacketPtr pkt, BlkType *&blk, blk->status |= BlkDirty; // nothing else to do; writeback doesn't expect response assert(!pkt->needsResponse()); - hits[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++; + hits[pkt->cmdToIndex()][0/*pkt->req->threadId()*/]++; return true; } @@ -467,8 +467,8 @@ Cache::timingAccess(PacketPtr pkt) if (mshr) { // MSHR hit //@todo remove hw_pf here - mshr_hits[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++; - if (mshr->threadNum != 0/*pkt->req->getThreadNum()*/) { + mshr_hits[pkt->cmdToIndex()][0/*pkt->req->threadId()*/]++; + if (mshr->threadNum != 0/*pkt->req->threadId()*/) { mshr->threadNum = -1; } mshr->allocateTarget(pkt, time, order++); @@ -482,7 +482,7 @@ Cache::timingAccess(PacketPtr pkt) } } else { // no MSHR - mshr_misses[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++; + mshr_misses[pkt->cmdToIndex()][0/*pkt->req->threadId()*/]++; // always mark as cache fill for now... if we implement // no-write-allocate or bypass accesses this will have to // be changed. @@ -740,10 +740,10 @@ Cache::handleResponse(PacketPtr pkt) PacketList writebacks; if (pkt->req->isUncacheable()) { - mshr_uncacheable_lat[stats_cmd_idx][0/*pkt->req->getThreadNum()*/] += + mshr_uncacheable_lat[stats_cmd_idx][0/*pkt->req->threadId()*/] += miss_latency; } else { - mshr_miss_latency[stats_cmd_idx][0/*pkt->req->getThreadNum()*/] += + mshr_miss_latency[stats_cmd_idx][0/*pkt->req->threadId()*/] += miss_latency; } @@ -784,7 +784,7 @@ Cache::handleResponse(PacketPtr pkt) (transfer_offset ? pkt->finishTime : pkt->firstWordTime); assert(!target->pkt->req->isUncacheable()); - missLatency[target->pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/] += + missLatency[target->pkt->cmdToIndex()][0/*pkt->req->threadId()*/] += completion_time - target->recvTime; } else { // not a cache fill, just forwarding response @@ -862,7 +862,7 @@ Cache::writebackBlk(BlkType *blk) { assert(blk && blk->isValid() && blk->isDirty()); - writebacks[0/*pkt->req->getThreadNum()*/]++; + writebacks[0/*pkt->req->threadId()*/]++; Request *writebackReq = new Request(tags->regenerateBlkAddr(blk->tag, blk->set), blkSize, 0); @@ -1261,7 +1261,7 @@ Cache::getNextMSHR() if (pkt) { // Update statistic on number of prefetches issued // (hwpf_mshr_misses) - mshr_misses[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++; + mshr_misses[pkt->cmdToIndex()][0/*pkt->req->threadId()*/]++; // Don't request bus, since we already have it return allocateMissBuffer(pkt, curTick, false); } diff --git a/src/mem/cache/mshr_queue.cc b/src/mem/cache/mshr_queue.cc index 45331c33d..b5c6cc7b8 100644 --- a/src/mem/cache/mshr_queue.cc +++ b/src/mem/cache/mshr_queue.cc @@ -230,7 +230,7 @@ MSHRQueue::squash(int threadNum) if (mshr->threadNum == threadNum) { while (mshr->hasTargets()) { mshr->popTarget(); - assert(0/*target->req->getThreadNum()*/ == threadNum); + assert(0/*target->req->threadId()*/ == threadNum); } assert(!mshr->hasTargets()); assert(mshr->ntargets==0); -- cgit v1.2.3 From 4ab52cb986962f7c0fb0fa07de10d8cdfb51458a Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Tue, 4 Nov 2008 11:35:57 -0500 Subject: Change the findBlock(addr, lat) to accessBlock, which I think has better connotations for what is really happening and how it should be used. --- src/mem/cache/cache_impl.hh | 2 +- src/mem/cache/tags/fa_lru.cc | 2 +- src/mem/cache/tags/fa_lru.hh | 8 +++++--- src/mem/cache/tags/iic.cc | 2 +- src/mem/cache/tags/iic.hh | 8 +++++--- src/mem/cache/tags/lru.cc | 2 +- src/mem/cache/tags/lru.hh | 8 +++++--- 7 files changed, 19 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 45faa84ce..af179ff91 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -269,7 +269,7 @@ Cache::access(PacketPtr pkt, BlkType *&blk, return false; } - blk = tags->findBlock(pkt->getAddr(), lat); + blk = tags->accessBlock(pkt->getAddr(), lat); if (prefetchAccess) { //We are determining prefetches on access stream, call prefetcher diff --git a/src/mem/cache/tags/fa_lru.cc b/src/mem/cache/tags/fa_lru.cc index 8a2f4eb13..aeb20aa4d 100644 --- a/src/mem/cache/tags/fa_lru.cc +++ b/src/mem/cache/tags/fa_lru.cc @@ -155,7 +155,7 @@ FALRU::invalidateBlk(FALRU::BlkType *blk) } FALRUBlk* -FALRU::findBlock(Addr addr, int &lat, int *inCache) +FALRU::accessBlock(Addr addr, int &lat, int *inCache) { accesses++; int tmp_in_cache = 0; diff --git a/src/mem/cache/tags/fa_lru.hh b/src/mem/cache/tags/fa_lru.hh index 43b3b5832..dfb21c08f 100644 --- a/src/mem/cache/tags/fa_lru.hh +++ b/src/mem/cache/tags/fa_lru.hh @@ -171,15 +171,17 @@ public: void invalidateBlk(BlkType *blk); /** - * Find the block in the cache and update the replacement data. Returns - * the access latency and the in cache flags as a side effect + * Access block and update replacement data. May not succeed, in which case + * NULL pointer is returned. This has all the implications of a cache + * access and should only be used as such. + * Returns the access latency and inCache flags as a side effect. * @param addr The address to look for. * @param asid The address space ID. * @param lat The latency of the access. * @param inCache The FALRUBlk::inCache flags. * @return Pointer to the cache block. */ - FALRUBlk* findBlock(Addr addr, int &lat, int *inCache = 0); + FALRUBlk* accessBlock(Addr addr, int &lat, int *inCache = 0); /** * Find the block in the cache, do not update the replacement data. diff --git a/src/mem/cache/tags/iic.cc b/src/mem/cache/tags/iic.cc index 31fd87df6..6abc0facf 100644 --- a/src/mem/cache/tags/iic.cc +++ b/src/mem/cache/tags/iic.cc @@ -221,7 +221,7 @@ IIC::regStats(const string &name) IICTag* -IIC::findBlock(Addr addr, int &lat) +IIC::accessBlock(Addr addr, int &lat) { Addr tag = extractTag(addr); unsigned set = hash(addr); diff --git a/src/mem/cache/tags/iic.hh b/src/mem/cache/tags/iic.hh index 0d513cf92..26f9858c4 100644 --- a/src/mem/cache/tags/iic.hh +++ b/src/mem/cache/tags/iic.hh @@ -410,14 +410,16 @@ class IIC : public BaseTags void invalidateBlk(BlkType *blk); /** - * Find the block and update the replacement data. This call also returns - * the access latency as a side effect. + * Access block and update replacement data. May not succeed, in which case + * NULL pointer is returned. This has all the implications of a cache + * access and should only be used as such. + * Returns the access latency and inCache flags as a side effect. * @param addr The address to find. * @param asid The address space ID. * @param lat The access latency. * @return A pointer to the block found, if any. */ - IICTag* findBlock(Addr addr, int &lat); + IICTag* accessBlock(Addr addr, int &lat); /** * Find the block, do not update the replacement data. diff --git a/src/mem/cache/tags/lru.cc b/src/mem/cache/tags/lru.cc index 2a82202e0..f5cf33696 100644 --- a/src/mem/cache/tags/lru.cc +++ b/src/mem/cache/tags/lru.cc @@ -151,7 +151,7 @@ LRU::~LRU() } LRUBlk* -LRU::findBlock(Addr addr, int &lat) +LRU::accessBlock(Addr addr, int &lat) { Addr tag = extractTag(addr); unsigned set = extractSet(addr); diff --git a/src/mem/cache/tags/lru.hh b/src/mem/cache/tags/lru.hh index 39b547f57..4f4c495f3 100644 --- a/src/mem/cache/tags/lru.hh +++ b/src/mem/cache/tags/lru.hh @@ -160,17 +160,19 @@ public: void invalidateBlk(BlkType *blk); /** - * Finds the given address in the cache and update replacement data. - * Returns the access latency as a side effect. + * Access block and update replacement data. May not succeed, in which case + * NULL pointer is returned. This has all the implications of a cache + * access and should only be used as such. Returns the access latency as a side effect. * @param addr The address to find. * @param asid The address space ID. * @param lat The access latency. * @return Pointer to the cache block if found. */ - LRUBlk* findBlock(Addr addr, int &lat); + LRUBlk* accessBlock(Addr addr, int &lat); /** * Finds the given address in the cache, do not update replacement data. + * i.e. This is a no-side-effect find of a block. * @param addr The address to find. * @param asid The address space ID. * @return Pointer to the cache block if found. -- cgit v1.2.3 From c68032ddcbf0aad10123710e7c7c932bf52061a0 Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Tue, 4 Nov 2008 11:35:58 -0500 Subject: decouple eviction from insertion in the cache. --- src/mem/cache/cache_impl.hh | 8 +++++--- src/mem/cache/tags/fa_lru.cc | 7 ++++++- src/mem/cache/tags/fa_lru.hh | 4 +++- src/mem/cache/tags/iic.cc | 7 ++++++- src/mem/cache/tags/iic.hh | 4 +++- src/mem/cache/tags/lru.cc | 18 ++++++++++++++---- src/mem/cache/tags/lru.hh | 16 ++++++++++++---- 7 files changed, 49 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index af179ff91..40d1c9c2f 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -319,6 +319,7 @@ Cache::access(PacketPtr pkt, BlkType *&blk, incMissCount(pkt); return false; } + tags->insertBlock(pkt->getAddr(), blk); blk->status = BlkValid | BlkReadable; } std::memcpy(blk->data, pkt->getPtr(), blkSize); @@ -879,7 +880,7 @@ template typename Cache::BlkType* Cache::allocateBlock(Addr addr, PacketList &writebacks) { - BlkType *blk = tags->findReplacement(addr, writebacks); + BlkType *blk = tags->findVictim(addr, writebacks); if (blk->isValid()) { Addr repl_addr = tags->regenerateBlkAddr(blk->tag, blk->set); @@ -890,6 +891,7 @@ Cache::allocateBlock(Addr addr, PacketList &writebacks) assert(!blk->isWritable()); assert(repl_mshr->needsExclusive()); // too hard to replace block with transient state + // allocation failed, block not inserted return NULL; } else { DPRINTF(Cache, "replacement: replacing %x with %x: %s\n", @@ -903,8 +905,6 @@ Cache::allocateBlock(Addr addr, PacketList &writebacks) } } - // Set tag for new block. Caller is responsible for setting status. - blk->tag = tags->extractTag(addr); return blk; } @@ -937,6 +937,8 @@ Cache::handleFill(PacketPtr pkt, BlkType *blk, tempBlock->set = tags->extractSet(addr); tempBlock->tag = tags->extractTag(addr); DPRINTF(Cache, "using temp block for %x\n", addr); + } else { + tags->insertBlock(addr, blk); } } else { // existing block... probably an upgrade diff --git a/src/mem/cache/tags/fa_lru.cc b/src/mem/cache/tags/fa_lru.cc index aeb20aa4d..f92d4cb37 100644 --- a/src/mem/cache/tags/fa_lru.cc +++ b/src/mem/cache/tags/fa_lru.cc @@ -207,7 +207,7 @@ FALRU::findBlock(Addr addr) const } FALRUBlk* -FALRU::findReplacement(Addr addr, PacketList &writebacks) +FALRU::findVictim(Addr addr, PacketList &writebacks) { FALRUBlk * blk = tail; assert(blk->inCache == 0); @@ -228,6 +228,11 @@ FALRU::findReplacement(Addr addr, PacketList &writebacks) return blk; } +void +FALRU::insertBlock(Addr addr, FALRU::BlkType *blk) +{ +} + void FALRU::moveToHead(FALRUBlk *blk) { diff --git a/src/mem/cache/tags/fa_lru.hh b/src/mem/cache/tags/fa_lru.hh index dfb21c08f..a740d962f 100644 --- a/src/mem/cache/tags/fa_lru.hh +++ b/src/mem/cache/tags/fa_lru.hh @@ -197,7 +197,9 @@ public: * @param writebacks List for any writebacks to be performed. * @return The block to place the replacement in. */ - FALRUBlk* findReplacement(Addr addr, PacketList & writebacks); + FALRUBlk* findVictim(Addr addr, PacketList & writebacks); + + void insertBlock(Addr addr, BlkType *blk); /** * Return the hit latency of this cache. diff --git a/src/mem/cache/tags/iic.cc b/src/mem/cache/tags/iic.cc index 6abc0facf..2b34634ab 100644 --- a/src/mem/cache/tags/iic.cc +++ b/src/mem/cache/tags/iic.cc @@ -297,7 +297,7 @@ IIC::findBlock(Addr addr) const IICTag* -IIC::findReplacement(Addr addr, PacketList &writebacks) +IIC::findVictim(Addr addr, PacketList &writebacks) { DPRINTF(IIC, "Finding Replacement for %x\n", addr); unsigned set = hash(addr); @@ -339,6 +339,11 @@ IIC::findReplacement(Addr addr, PacketList &writebacks) return tag_ptr; } +void +IIC::insertBlock(Addr addr, BlkType* blk) +{ +} + void IIC::freeReplacementBlock(PacketList & writebacks) { diff --git a/src/mem/cache/tags/iic.hh b/src/mem/cache/tags/iic.hh index 26f9858c4..984506a93 100644 --- a/src/mem/cache/tags/iic.hh +++ b/src/mem/cache/tags/iic.hh @@ -435,7 +435,9 @@ class IIC : public BaseTags * @param writebacks List for any writebacks to be performed. * @return The block to place the replacement in. */ - IICTag* findReplacement(Addr addr, PacketList &writebacks); + IICTag* findVictim(Addr addr, PacketList &writebacks); + + void insertBlock(Addr addr, BlkType *blk); /** * Read the data from the internal storage of the given cache block. diff --git a/src/mem/cache/tags/lru.cc b/src/mem/cache/tags/lru.cc index f5cf33696..ff353ff6a 100644 --- a/src/mem/cache/tags/lru.cc +++ b/src/mem/cache/tags/lru.cc @@ -183,12 +183,11 @@ LRU::findBlock(Addr addr) const } LRUBlk* -LRU::findReplacement(Addr addr, PacketList &writebacks) +LRU::findVictim(Addr addr, PacketList &writebacks) { unsigned set = extractSet(addr); // grab a replacement candidate LRUBlk *blk = sets[set].blks[assoc-1]; - sets[set].moveToHead(blk); if (blk->isValid()) { replacements[0]++; totalRefs += blk->refCount; @@ -197,7 +196,14 @@ LRU::findReplacement(Addr addr, PacketList &writebacks) DPRINTF(CacheRepl, "set %x: selecting blk %x for replacement\n", set, regenerateBlkAddr(blk->tag, set)); - } else if (!blk->isTouched) { + } + return blk; +} + +void +LRU::insertBlock(Addr addr, LRU::BlkType *blk) +{ + if (!blk->isTouched) { tagsInUse++; blk->isTouched = true; if (!warmedUp && tagsInUse.value() >= warmupBound) { @@ -206,7 +212,11 @@ LRU::findReplacement(Addr addr, PacketList &writebacks) } } - return blk; + // Set tag for new block. Caller is responsible for setting status. + blk->tag = extractTag(addr); + + unsigned set = extractSet(addr); + sets[set].moveToHead(blk); } void diff --git a/src/mem/cache/tags/lru.hh b/src/mem/cache/tags/lru.hh index 4f4c495f3..79af973a0 100644 --- a/src/mem/cache/tags/lru.hh +++ b/src/mem/cache/tags/lru.hh @@ -180,12 +180,20 @@ public: LRUBlk* findBlock(Addr addr) const; /** - * Find a replacement block for the address provided. - * @param pkt The request to a find a replacement candidate for. + * Find a block to evict for the address provided. + * @param addr The addr to a find a replacement candidate for. * @param writebacks List for any writebacks to be performed. - * @return The block to place the replacement in. + * @return The candidate block. */ - LRUBlk* findReplacement(Addr addr, PacketList &writebacks); + LRUBlk* findVictim(Addr addr, PacketList &writebacks); + + /** + * Insert the new block into the cache. For LRU this means inserting into + * the MRU position of the set. + * @param addr The address to update. + * @param blk The block to update. + */ + void insertBlock(Addr addr, BlkType *blk); /** * Generate the tag from the given address. -- cgit v1.2.3 From 07969dbbf1a737e666b5ba6d34cd7cf2b403a9ad Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Wed, 5 Nov 2008 15:30:49 -0500 Subject: Right now a single thread cpu 1 could get assigned context Id != 1, depending on the order in which it's registered with the system. To make them match, here is a little change. --- src/cpu/base.cc | 12 +++++++++++- src/sim/system.cc | 20 +++++++++++++------- src/sim/system.hh | 2 +- 3 files changed, 25 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 1fa7add65..167606135 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -285,7 +285,17 @@ BaseCPU::registerThreadContexts() for (int i = 0; i < threadContexts.size(); ++i) { ThreadContext *tc = threadContexts[i]; - tc->setContextId(system->registerThreadContext(tc)); + /** This is so that contextId and cpuId match where there is a + * 1cpu:1context relationship. Otherwise, the order of registration + * could affect the assignment and cpu 1 could have context id 3, for + * example. We may even want to do something like this for SMT so that + * cpu 0 has the lowest thread contexts and cpu N has the highest, but + * I'll just do this for now + */ + if (number_of_threads == 1) + tc->setContextId(system->registerThreadContext(tc, _cpuId)); + else + tc->setContextId(system->registerThreadContext(tc)); #if !FULL_SYSTEM tc->getProcessPtr()->assignThreadContext(tc->contextId()); #endif diff --git a/src/sim/system.cc b/src/sim/system.cc index 9704c83f0..29b1d1f61 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -166,16 +166,22 @@ bool System::breakpoint() } int -System::registerThreadContext(ThreadContext *tc) +System::registerThreadContext(ThreadContext *tc, int assigned) { int id; - for (id = 0; id < threadContexts.size(); id++) { - if (!threadContexts[id]) - break; - } + if (assigned == -1) { + for (id = 0; id < threadContexts.size(); id++) { + if (!threadContexts[id]) + break; + } - if (threadContexts.size() <= id) - threadContexts.resize(id + 1); + if (threadContexts.size() <= id) + threadContexts.resize(id + 1); + } else { + if (threadContexts.size() <= assigned) + threadContexts.resize(assigned + 1); + id = assigned; + } if (threadContexts[id]) panic("Cannot have two CPUs with the same id (%d)\n", id); diff --git a/src/sim/system.hh b/src/sim/system.hh index e993a7a50..9715767b1 100644 --- a/src/sim/system.hh +++ b/src/sim/system.hh @@ -224,7 +224,7 @@ class System : public SimObject #endif // FULL_SYSTEM - int registerThreadContext(ThreadContext *tc); + int registerThreadContext(ThreadContext *tc, int assigned=-1); void replaceThreadContext(ThreadContext *tc, int context_id); void serialize(std::ostream &os); -- cgit v1.2.3 From 46b56bb7b6ac2a5f069aa1f79279f46d0395eb15 Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Wed, 5 Nov 2008 16:19:17 -0500 Subject: Fix SPARC_FS compile --- src/dev/sparc/iob.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/dev/sparc/iob.cc b/src/dev/sparc/iob.cc index f99ee5804..4543dd07b 100644 --- a/src/dev/sparc/iob.cc +++ b/src/dev/sparc/iob.cc @@ -276,7 +276,7 @@ void Iob::generateIpi(Type type, int cpu_id, int vector) { SparcISA::SparcFault *por = new SparcISA::PowerOnReset(); - if (cpu_id >= sys->getNumCPUs()) + if (cpu_id >= sys->numContexts()) return; switch (type) { -- cgit v1.2.3 From 44839d6b716f2eb25eabc57fe588a129e290e51c Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Wed, 5 Nov 2008 07:20:03 -0800 Subject: Fix a few more places where the context stuff wasn't changed --- src/arch/sparc/ua2005.cc | 2 +- src/dev/x86/i82094aa.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/arch/sparc/ua2005.cc b/src/arch/sparc/ua2005.cc index 502033d97..2389c963d 100644 --- a/src/arch/sparc/ua2005.cc +++ b/src/arch/sparc/ua2005.cc @@ -257,7 +257,7 @@ MiscRegFile::readFSReg(int miscReg, ThreadContext * tc) temp = readRegNoEffect(miscReg) & (STS::active | STS::speculative); // Check that the CPU array is fully populated // (by calling getNumCPus()) - assert(sys->getNumContexts() > tc->contextId()); + assert(sys->numContexts() > tc->contextId()); temp |= tc->contextId() << STS::shft_id; diff --git a/src/dev/x86/i82094aa.cc b/src/dev/x86/i82094aa.cc index 0ae7c56f3..a229fffc3 100644 --- a/src/dev/x86/i82094aa.cc +++ b/src/dev/x86/i82094aa.cc @@ -39,7 +39,7 @@ X86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), IntDev(this), latency(p->pio_latency), pioAddr(p->pio_addr), extIntPic(NULL) { // This assumes there's only one I/O APIC in the system - id = sys->getNumCPUs(); + id = sys->numContexts(); assert(id <= 0xf); arbId = id; regSel = 0; -- cgit v1.2.3 From 909380f3ee576f915f52c6245c59d41050a46f49 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 9 Nov 2008 21:55:01 -0800 Subject: X86: Make the timing simple CPU handle variable length instructions. --- src/cpu/simple/timing.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index ca1f0283e..f5eeeba60 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -561,7 +561,8 @@ TimingSimpleCPU::fetch() void TimingSimpleCPU::advanceInst(Fault fault) { - advancePC(fault); + if (fault != NoFault || !stayAtPC) + advancePC(fault); if (_status == Running) { // kick off fetch of next instruction... callback from icache @@ -599,7 +600,8 @@ TimingSimpleCPU::completeIfetch(PacketPtr pkt) } preExecute(); - if (curStaticInst->isMemRef() && !curStaticInst->isDataPrefetch()) { + if (curStaticInst && + curStaticInst->isMemRef() && !curStaticInst->isDataPrefetch()) { // load or store: just send to dcache Fault fault = curStaticInst->initiateAcc(this, traceData); if (_status != Running) { @@ -638,7 +640,7 @@ TimingSimpleCPU::completeIfetch(PacketPtr pkt) instCnt++; advanceInst(fault); } - } else { + } else if (curStaticInst) { // non-memory instruction: execute completely now Fault fault = curStaticInst->execute(this, traceData); @@ -657,6 +659,8 @@ TimingSimpleCPU::completeIfetch(PacketPtr pkt) curStaticInst->isFirstMicroop())) instCnt++; advanceInst(fault); + } else { + advanceInst(NoFault); } if (pkt) { -- cgit v1.2.3 From 8c15518f30a5e7ffe0f82acde714c11000bc3714 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 9 Nov 2008 21:55:43 -0800 Subject: X86: Fix completeAcc get call. --- src/arch/x86/insts/microldstop.hh | 20 ++++++++++++++++++++ src/arch/x86/isa/microops/ldstop.isa | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/insts/microldstop.hh b/src/arch/x86/insts/microldstop.hh index 5b1210d69..eccd37dc2 100644 --- a/src/arch/x86/insts/microldstop.hh +++ b/src/arch/x86/insts/microldstop.hh @@ -59,6 +59,7 @@ #define __ARCH_X86_INSTS_MICROLDSTOP_HH__ #include "arch/x86/insts/microop.hh" +#include "mem/packet.hh" namespace X86ISA { @@ -149,6 +150,25 @@ namespace X86ISA } return fault; } + + uint64_t + get(PacketPtr pkt) const + { + switch(dataSize) + { + case 1: + return pkt->get(); + case 2: + return pkt->get(); + case 4: + return pkt->get(); + case 8: + return pkt->get(); + default: + panic("Bad operand size %d for read at %#x.\n", + dataSize, pkt->getAddr()); + } + } }; } diff --git a/src/arch/x86/isa/microops/ldstop.isa b/src/arch/x86/isa/microops/ldstop.isa index cb63e7cd9..30a7c8801 100644 --- a/src/arch/x86/isa/microops/ldstop.isa +++ b/src/arch/x86/isa/microops/ldstop.isa @@ -194,7 +194,7 @@ def template MicroLoadCompleteAcc {{ %(op_decl)s; %(op_rd)s; - Mem = pkt->get(); + Mem = get(pkt); %(code)s; -- cgit v1.2.3 From 846cb450f985eb249a5fc50e97f9e643cb1ebfc5 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 9 Nov 2008 21:56:28 -0800 Subject: CPU: Make unaligned accesses work in the timing simple CPU. --- src/cpu/simple/timing.cc | 366 +++++++++++++++++++++++++++++++++++++---------- src/cpu/simple/timing.hh | 57 ++++++++ 2 files changed, 347 insertions(+), 76 deletions(-) (limited to 'src') diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index f5eeeba60..5d37fa620 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -241,57 +241,135 @@ TimingSimpleCPU::suspendContext(int thread_num) _status = Idle; } +bool +TimingSimpleCPU::handleReadPacket(PacketPtr pkt) +{ + RequestPtr req = pkt->req; + if (req->isMmapedIpr()) { + Tick delay; + delay = TheISA::handleIprRead(thread->getTC(), pkt); + new IprEvent(pkt, this, nextCycle(curTick + delay)); + _status = DcacheWaitResponse; + dcache_pkt = NULL; + } else if (!dcachePort.sendTiming(pkt)) { + _status = DcacheRetry; + dcache_pkt = pkt; + } else { + _status = DcacheWaitResponse; + // memory system takes ownership of packet + dcache_pkt = NULL; + } + return dcache_pkt == NULL; +} template Fault TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) { - Request *req = - new Request(/* asid */ 0, addr, sizeof(T), flags, thread->readPC(), - _cpuId, /* thread ID */ 0); - - if (traceData) { - traceData->setAddr(req->getVaddr()); - } + Fault fault; + const int asid = 0; + const int thread_id = 0; + const Addr pc = thread->readPC(); + + PacketPtr pkt; + RequestPtr req; + + int block_size = dcachePort.peerBlockSize(); + int data_size = sizeof(T); + + Addr second_addr = roundDown(addr + data_size - 1, block_size); + + if (second_addr > addr) { + Addr first_size = second_addr - addr; + Addr second_size = data_size - first_size; + // Make sure we'll only need two accesses. + assert(roundDown(second_addr + second_size - 1, block_size) == + second_addr); + + /* + * Do the translations. If something isn't going to work, find out + * before we waste time setting up anything else. + */ + req = new Request(asid, addr, first_size, + flags, pc, _cpuId, thread_id); + fault = thread->translateDataReadReq(req); + if (fault != NoFault) { + delete req; + return fault; + } + Request *second_req = + new Request(asid, second_addr, second_size, + flags, pc, _cpuId, thread_id); + fault = thread->translateDataReadReq(second_req); + if (fault != NoFault) { + delete req; + delete second_req; + return fault; + } - // translate to physical address - Fault fault = thread->translateDataReadReq(req); + T * data_ptr = new T; + + /* + * This is the big packet that will hold the data we've gotten so far, + * if any, and also act as the response we actually give to the + * instruction. + */ + Request *orig_req = + new Request(asid, addr, data_size, flags, pc, _cpuId, thread_id); + orig_req->setPhys(req->getPaddr(), data_size, flags); + PacketPtr big_pkt = + new Packet(orig_req, MemCmd::ReadResp, Packet::Broadcast); + big_pkt->dataDynamic(data_ptr); + SplitMainSenderState * main_send_state = new SplitMainSenderState; + big_pkt->senderState = main_send_state; + main_send_state->outstanding = 2; + + // This is the packet we'll process now. + pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast); + pkt->dataStatic((uint8_t *)data_ptr); + pkt->senderState = new SplitFragmentSenderState(big_pkt, 0); + + // This is the second half of the access we'll deal with later. + PacketPtr second_pkt = + new Packet(second_req, MemCmd::ReadReq, Packet::Broadcast); + second_pkt->dataStatic((uint8_t *)data_ptr + first_size); + second_pkt->senderState = new SplitFragmentSenderState(big_pkt, 1); + if (!handleReadPacket(pkt)) { + main_send_state->fragments[1] = second_pkt; + } else { + handleReadPacket(second_pkt); + } + } else { + req = new Request(asid, addr, data_size, + flags, pc, _cpuId, thread_id); - // Now do the access. - if (fault == NoFault) { - PacketPtr pkt = - new Packet(req, - (req->isLocked() ? - MemCmd::LoadLockedReq : MemCmd::ReadReq), - Packet::Broadcast); - pkt->dataDynamic(new T); + // translate to physical address + Fault fault = thread->translateDataReadReq(req); - if (req->isMmapedIpr()) { - Tick delay; - delay = TheISA::handleIprRead(thread->getTC(), pkt); - new IprEvent(pkt, this, nextCycle(curTick + delay)); - _status = DcacheWaitResponse; - dcache_pkt = NULL; - } else if (!dcachePort.sendTiming(pkt)) { - _status = DcacheRetry; - dcache_pkt = pkt; - } else { - _status = DcacheWaitResponse; - // memory system takes ownership of packet - dcache_pkt = NULL; + if (fault != NoFault) { + delete req; + return fault; } - // This will need a new way to tell if it has a dcache attached. - if (req->isUncacheable()) - recordEvent("Uncached Read"); - } else { - delete req; + pkt = new Packet(req, + (req->isLocked() ? + MemCmd::LoadLockedReq : MemCmd::ReadReq), + Packet::Broadcast); + pkt->dataDynamic(new T); + + handleReadPacket(pkt); } if (traceData) { traceData->setData(data); + traceData->setAddr(addr); } - return fault; + + // This will need a new way to tell if it has a dcache attached. + if (req->isUncacheable()) + recordEvent("Uncached Read"); + + return NoFault; } Fault @@ -364,26 +442,117 @@ TimingSimpleCPU::read(Addr addr, int32_t &data, unsigned flags) return read(addr, (uint32_t&)data, flags); } +bool +TimingSimpleCPU::handleWritePacket() +{ + RequestPtr req = dcache_pkt->req; + if (req->isMmapedIpr()) { + Tick delay; + delay = TheISA::handleIprWrite(thread->getTC(), dcache_pkt); + new IprEvent(dcache_pkt, this, nextCycle(curTick + delay)); + _status = DcacheWaitResponse; + dcache_pkt = NULL; + } else if (!dcachePort.sendTiming(dcache_pkt)) { + _status = DcacheRetry; + } else { + _status = DcacheWaitResponse; + // memory system takes ownership of packet + dcache_pkt = NULL; + } + return dcache_pkt == NULL; +} template Fault TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) { - Request *req = - new Request(/* asid */ 0, addr, sizeof(T), flags, thread->readPC(), - _cpuId, /* thread ID */ 0); + const int asid = 0; + const int thread_id = 0; + bool do_access = true; // flag to suppress cache access + const Addr pc = thread->readPC(); + + RequestPtr req; + + int block_size = dcachePort.peerBlockSize(); + int data_size = sizeof(T); + + Addr second_addr = roundDown(addr + data_size - 1, block_size); + + if (second_addr > addr) { + Fault fault; + Addr first_size = second_addr - addr; + Addr second_size = data_size - first_size; + // Make sure we'll only need two accesses. + assert(roundDown(second_addr + second_size - 1, block_size) == + second_addr); + + req = new Request(asid, addr, first_size, + flags, pc, _cpuId, thread_id); + fault = thread->translateDataWriteReq(req); + if (fault != NoFault) { + delete req; + return fault; + } + RequestPtr second_req = new Request(asid, second_addr, second_size, + flags, pc, _cpuId, thread_id); + fault = thread->translateDataWriteReq(second_req); + if (fault != NoFault) { + delete req; + delete second_req; + return fault; + } - if (traceData) { - traceData->setAddr(req->getVaddr()); - } + if (req->isLocked() || req->isSwap() || + second_req->isLocked() || second_req->isSwap()) { + panic("LL/SCs and swaps can't be split."); + } - // translate to physical address - Fault fault = thread->translateDataWriteReq(req); + T * data_ptr = new T; + + /* + * This is the big packet that will hold the data we've gotten so far, + * if any, and also act as the response we actually give to the + * instruction. + */ + RequestPtr orig_req = + new Request(asid, addr, data_size, flags, pc, _cpuId, thread_id); + orig_req->setPhys(req->getPaddr(), data_size, flags); + PacketPtr big_pkt = + new Packet(orig_req, MemCmd::WriteResp, Packet::Broadcast); + big_pkt->dataDynamic(data_ptr); + big_pkt->set(data); + SplitMainSenderState * main_send_state = new SplitMainSenderState; + big_pkt->senderState = main_send_state; + main_send_state->outstanding = 2; + + assert(dcache_pkt == NULL); + // This is the packet we'll process now. + dcache_pkt = new Packet(req, MemCmd::WriteReq, Packet::Broadcast); + dcache_pkt->dataStatic((uint8_t *)data_ptr); + dcache_pkt->senderState = new SplitFragmentSenderState(big_pkt, 0); + + // This is the second half of the access we'll deal with later. + PacketPtr second_pkt = + new Packet(second_req, MemCmd::WriteReq, Packet::Broadcast); + second_pkt->dataStatic((uint8_t *)data_ptr + first_size); + second_pkt->senderState = new SplitFragmentSenderState(big_pkt, 1); + if (!handleWritePacket()) { + main_send_state->fragments[1] = second_pkt; + } else { + dcache_pkt = second_pkt; + handleWritePacket(); + } + } else { + req = new Request(asid, addr, data_size, flags, pc, _cpuId, thread_id); + + // translate to physical address + Fault fault = thread->translateDataWriteReq(req); + if (fault != NoFault) { + delete req; + return fault; + } - // Now do the access. - if (fault == NoFault) { MemCmd cmd = MemCmd::WriteReq; // default - bool do_access = true; // flag to suppress cache access if (req->isLocked()) { cmd = MemCmd::StoreCondReq; @@ -401,38 +570,27 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) assert(dcache_pkt == NULL); dcache_pkt = new Packet(req, cmd, Packet::Broadcast); dcache_pkt->allocate(); - dcache_pkt->set(data); - - if (do_access) { - if (req->isMmapedIpr()) { - Tick delay; - dcache_pkt->set(htog(data)); - delay = TheISA::handleIprWrite(thread->getTC(), dcache_pkt); - new IprEvent(dcache_pkt, this, nextCycle(curTick + delay)); - _status = DcacheWaitResponse; - dcache_pkt = NULL; - } else if (!dcachePort.sendTiming(dcache_pkt)) { - _status = DcacheRetry; - } else { - _status = DcacheWaitResponse; - // memory system takes ownership of packet - dcache_pkt = NULL; - } - } - // This will need a new way to tell if it's hooked up to a cache or not. - if (req->isUncacheable()) - recordEvent("Uncached Write"); - } else { - delete req; + if (req->isMmapedIpr()) + dcache_pkt->set(htog(data)); + else + dcache_pkt->set(data); + + if (do_access) + handleWritePacket(); } if (traceData) { + traceData->setAddr(req->getVaddr()); traceData->setData(data); } + // This will need a new way to tell if it's hooked up to a cache or not. + if (req->isUncacheable()) + recordEvent("Uncached Write"); + // If the write needs to have a fault on the access, consider calling // changeStatus() and changing it to "bad addr write" or something. - return fault; + return NoFault; } Fault @@ -721,12 +879,38 @@ TimingSimpleCPU::completeDataAccess(PacketPtr pkt) // received a response from the dcache: complete the load or store // instruction assert(!pkt->isError()); - assert(_status == DcacheWaitResponse); - _status = Running; numCycles += tickToCycles(curTick - previousTick); previousTick = curTick; + if (pkt->senderState) { + SplitFragmentSenderState * send_state = + dynamic_cast(pkt->senderState); + assert(send_state); + delete pkt->req; + delete pkt; + PacketPtr big_pkt = send_state->bigPkt; + delete send_state; + + SplitMainSenderState * main_send_state = + dynamic_cast(big_pkt->senderState); + assert(main_send_state); + // Record the fact that this packet is no longer outstanding. + assert(main_send_state->outstanding != 0); + main_send_state->outstanding--; + + if (main_send_state->outstanding) { + return; + } else { + delete main_send_state; + big_pkt->senderState = NULL; + pkt = big_pkt; + } + } + + assert(_status == DcacheWaitResponse); + _status = Running; + Fault fault = curStaticInst->completeAcc(pkt, this, traceData); // keep an instruction count @@ -787,10 +971,11 @@ TimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt) // delay processing of returned data until next CPU clock edge Tick next_tick = cpu->nextCycle(curTick); - if (next_tick == curTick) + if (next_tick == curTick) { cpu->completeDataAccess(pkt); - else + } else { tickEvent.schedule(pkt, next_tick); + } return true; } @@ -820,7 +1005,36 @@ TimingSimpleCPU::DcachePort::recvRetry() assert(cpu->dcache_pkt != NULL); assert(cpu->_status == DcacheRetry); PacketPtr tmp = cpu->dcache_pkt; - if (sendTiming(tmp)) { + if (tmp->senderState) { + // This is a packet from a split access. + SplitFragmentSenderState * send_state = + dynamic_cast(tmp->senderState); + assert(send_state); + PacketPtr big_pkt = send_state->bigPkt; + + SplitMainSenderState * main_send_state = + dynamic_cast(big_pkt->senderState); + assert(main_send_state); + + if (sendTiming(tmp)) { + // If we were able to send without retrying, record that fact + // and try sending the other fragment. + send_state->clearFromParent(); + int other_index = main_send_state->getPendingFragment(); + if (other_index > 0) { + tmp = main_send_state->fragments[other_index]; + cpu->dcache_pkt = tmp; + if ((big_pkt->isRead() && cpu->handleReadPacket(tmp)) || + (big_pkt->isWrite() && cpu->handleWritePacket())) { + main_send_state->fragments[other_index] = NULL; + } + } else { + cpu->_status = DcacheWaitResponse; + // memory system takes ownership of packet + cpu->dcache_pkt = NULL; + } + } + } else if (sendTiming(tmp)) { cpu->_status = DcacheWaitResponse; // memory system takes ownership of packet cpu->dcache_pkt = NULL; diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index 0fc9b3152..b641b1302 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -49,6 +49,63 @@ class TimingSimpleCPU : public BaseSimpleCPU private: + /* + * If an access needs to be broken into fragments, currently at most two, + * the the following two classes are used as the sender state of the + * packets so the CPU can keep track of everything. In the main packet + * sender state, there's an array with a spot for each fragment. If a + * fragment has already been accepted by the CPU, aka isn't waiting for + * a retry, it's pointer is NULL. After each fragment has successfully + * been processed, the "outstanding" counter is decremented. Once the + * count is zero, the entire larger access is complete. + */ + class SplitMainSenderState : public Packet::SenderState + { + public: + int outstanding; + PacketPtr fragments[2]; + + SplitMainSenderState() + { + fragments[0] = NULL; + fragments[1] = NULL; + } + + int + getPendingFragment() + { + if (fragments[0]) { + return 0; + } else if (fragments[1]) { + return 1; + } else { + return -1; + } + } + }; + + class SplitFragmentSenderState : public Packet::SenderState + { + public: + SplitFragmentSenderState(PacketPtr _bigPkt, int _index) : + bigPkt(_bigPkt), index(_index) + {} + PacketPtr bigPkt; + int index; + + void + clearFromParent() + { + SplitMainSenderState * main_send_state = + dynamic_cast(bigPkt->senderState); + main_send_state->fragments[index] = NULL; + } + }; + + bool handleReadPacket(PacketPtr pkt); + // This function always implicitly uses dcache_pkt. + bool handleWritePacket(); + class CpuPort : public Port { protected: -- cgit v1.2.3 From 42bd460d7f91f4d0f76901a8d661d5fe6292b7f2 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Mon, 10 Nov 2008 14:10:28 -0800 Subject: Cache: Refactor packet forwarding a bit. Makes adding write-through operations easier. --- src/mem/cache/cache_impl.hh | 67 ++++++++++++++++++++++++++++----------------- src/mem/cache/mshr.cc | 7 +++-- src/mem/cache/mshr.hh | 16 +++++++---- 3 files changed, 56 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 40d1c9c2f..c4a19ad5c 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -613,38 +613,53 @@ Cache::atomicAccess(PacketPtr pkt) if (!access(pkt, blk, lat, writebacks)) { // MISS - PacketPtr busPkt = getBusPacket(pkt, blk, pkt->needsExclusive()); + PacketPtr bus_pkt = getBusPacket(pkt, blk, pkt->needsExclusive()); - bool isCacheFill = (busPkt != NULL); + bool is_forward = (bus_pkt == NULL); - if (busPkt == NULL) { + if (is_forward) { // just forwarding the same request to the next level // no local cache operation involved - busPkt = pkt; + bus_pkt = pkt; } DPRINTF(Cache, "Sending an atomic %s for %x\n", - busPkt->cmdString(), busPkt->getAddr()); + bus_pkt->cmdString(), bus_pkt->getAddr()); #if TRACING_ON CacheBlk::State old_state = blk ? blk->status : 0; #endif - lat += memSidePort->sendAtomic(busPkt); + lat += memSidePort->sendAtomic(bus_pkt); DPRINTF(Cache, "Receive response: %s for addr %x in state %i\n", - busPkt->cmdString(), busPkt->getAddr(), old_state); - - bool is_error = busPkt->isError(); - assert(!busPkt->wasNacked()); - - if (is_error && pkt->needsResponse()) { - pkt->makeAtomicResponse(); - pkt->copyError(busPkt); - } else if (isCacheFill && !is_error) { - blk = handleFill(busPkt, blk, writebacks); - satisfyCpuSideRequest(pkt, blk); - delete busPkt; + bus_pkt->cmdString(), bus_pkt->getAddr(), old_state); + + assert(!bus_pkt->wasNacked()); + + // If packet was a forward, the response (if any) is already + // in place in the bus_pkt == pkt structure, so we don't need + // to do anything. Otherwise, use the separate bus_pkt to + // generate response to pkt and then delete it. + if (!is_forward) { + if (pkt->needsResponse()) { + assert(bus_pkt->isResponse()); + if (bus_pkt->isError()) { + pkt->makeAtomicResponse(); + pkt->copyError(bus_pkt); + } else if (bus_pkt->isRead() || + bus_pkt->cmd == MemCmd::UpgradeResp) { + // we're updating cache state to allow us to + // satisfy the upstream request from the cache + blk = handleFill(bus_pkt, blk, writebacks); + satisfyCpuSideRequest(pkt, blk); + } else { + // we're satisfying the upstream request without + // modifying cache state, e.g., a write-through + pkt->makeAtomicResponse(); + } + } + delete bus_pkt; } } @@ -748,7 +763,10 @@ Cache::handleResponse(PacketPtr pkt) miss_latency; } - if (mshr->isCacheFill && !is_error) { + bool is_fill = !mshr->isForward && + (pkt->isRead() || pkt->cmd == MemCmd::UpgradeResp); + + if (is_fill && !is_error) { DPRINTF(Cache, "Block for addr %x being updated in Cache\n", pkt->getAddr()); @@ -771,7 +789,7 @@ Cache::handleResponse(PacketPtr pkt) if (target->isCpuSide()) { Tick completion_time; - if (blk != NULL) { + if (is_fill) { satisfyCpuSideRequest(target->pkt, blk); // How many bytes past the first request is this one int transfer_offset = @@ -1287,7 +1305,7 @@ Cache::getTimingPacket() PacketPtr tgt_pkt = mshr->getTarget()->pkt; PacketPtr pkt = NULL; - if (mshr->isSimpleForward()) { + if (mshr->isForwardNoResponse()) { // no response expected, just forward packet as it is assert(tags->findBlock(mshr->addr) == NULL); pkt = tgt_pkt; @@ -1295,11 +1313,10 @@ Cache::getTimingPacket() BlkType *blk = tags->findBlock(mshr->addr); pkt = getBusPacket(tgt_pkt, blk, mshr->needsExclusive()); - mshr->isCacheFill = (pkt != NULL); + mshr->isForward = (pkt == NULL); - if (pkt == NULL) { + if (mshr->isForward) { // not a cache block request, but a response is expected - assert(!mshr->isSimpleForward()); // make copy of current packet to forward, keep current // copy for response handling pkt = new Packet(tgt_pkt); @@ -1473,7 +1490,7 @@ Cache::MemSidePort::sendPacket() waitingOnRetry = !success; if (waitingOnRetry) { DPRINTF(CachePort, "now waiting on a retry\n"); - if (!mshr->isSimpleForward()) { + if (!mshr->isForwardNoResponse()) { delete pkt; } } else { diff --git a/src/mem/cache/mshr.cc b/src/mem/cache/mshr.cc index 6537f6343..04b2b8d77 100644 --- a/src/mem/cache/mshr.cc +++ b/src/mem/cache/mshr.cc @@ -156,7 +156,7 @@ MSHR::allocate(Addr _addr, int _size, PacketPtr target, readyTime = whenReady; order = _order; assert(target); - isCacheFill = false; + isForward = false; _isUncacheable = target->req->isUncacheable(); inService = false; downstreamPending = false; @@ -187,7 +187,7 @@ bool MSHR::markInService() { assert(!inService); - if (isSimpleForward()) { + if (isForwardNoResponse()) { // we just forwarded the request packet & don't expect a // response, so get rid of it assert(getNumTargets() == 1); @@ -403,7 +403,8 @@ MSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const { ccprintf(os, "%s[%x:%x] %s %s %s state: %s %s %s %s\n", prefix, addr, addr+size-1, - isCacheFill ? "Fill" : "", + isForward ? "Forward" : "", + isForwardNoResponse() ? "ForwNoResp" : "", needsExclusive() ? "Excl" : "", _isUncacheable ? "Unc" : "", inService ? "InSvc" : "", diff --git a/src/mem/cache/mshr.hh b/src/mem/cache/mshr.hh index fdb0485cb..2ff1c2489 100644 --- a/src/mem/cache/mshr.hh +++ b/src/mem/cache/mshr.hh @@ -118,8 +118,8 @@ class MSHR : public Packet::SenderState, public Printable /** True if the request has been sent to the bus. */ bool inService; - /** True if we will be putting the returned block in the cache */ - bool isCacheFill; + /** True if the request is just a simple forward from an upper level */ + bool isForward; /** True if we need to get an exclusive copy of the block. */ bool needsExclusive() const { return targets->needsExclusive; } @@ -200,7 +200,7 @@ public: * Returns the current number of allocated targets. * @return The current number of allocated targets. */ - int getNumTargets() { return ntargets; } + int getNumTargets() const { return ntargets; } /** * Returns a pointer to the target list. @@ -212,13 +212,17 @@ public: * Returns true if there are targets left. * @return true if there are targets */ - bool hasTargets() { return !targets->empty(); } + bool hasTargets() const { return !targets->empty(); } /** * Returns a reference to the first target. * @return A pointer to the first target. */ - Target *getTarget() { assert(hasTargets()); return &targets->front(); } + Target *getTarget() const + { + assert(hasTargets()); + return &targets->front(); + } /** * Pop first target. @@ -229,7 +233,7 @@ public: targets->pop_front(); } - bool isSimpleForward() + bool isForwardNoResponse() const { if (getNumTargets() != 1) return false; -- cgit v1.2.3 From 63127cbf37ac9b37096c5ede06c929069a5ceb49 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Mon, 10 Nov 2008 14:11:07 -0800 Subject: mem: Assert that requests have non-negative size. Would have saved me much debugging time if these had been in there previously. --- src/base/chunk_generator.hh | 1 + src/mem/request.hh | 2 ++ 2 files changed, 3 insertions(+) (limited to 'src') diff --git a/src/base/chunk_generator.hh b/src/base/chunk_generator.hh index e8238464b..d2ae45d1e 100644 --- a/src/base/chunk_generator.hh +++ b/src/base/chunk_generator.hh @@ -82,6 +82,7 @@ class ChunkGenerator { // chunkSize must be a power of two assert(chunkSize == 0 || isPowerOf2(chunkSize)); + assert(totalSize >= 0); // set up initial chunk. curAddr = startAddr; diff --git a/src/mem/request.hh b/src/mem/request.hh index da0d9c7e0..d1e011c7d 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -172,6 +172,7 @@ class Request : public FastAlloc * allocated Request object. */ void setPhys(Addr _paddr, int _size, int _flags) { + assert(_size >= 0); paddr = _paddr; size = _size; flags = _flags; @@ -188,6 +189,7 @@ class Request : public FastAlloc * allocated Request object. */ void setVirt(int _asid, Addr _vaddr, int _size, int _flags, Addr _pc) { + assert(_size >= 0); asid = _asid; vaddr = _vaddr; size = _size; -- cgit v1.2.3 From 27e8f3c98a4b1c56e16ce5f80c7ad992083ccef9 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Mon, 10 Nov 2008 14:45:31 -0800 Subject: DmaDevice: fix minor type in error message. --- src/dev/io_device.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh index e18489378..70af6093d 100644 --- a/src/dev/io_device.hh +++ b/src/dev/io_device.hh @@ -297,7 +297,7 @@ class DmaDevice : public PioDevice } else if (if_name == "dma") { if (dmaPort != NULL) fatal("%s: dma port already connected to %s", - name(), pioPort->getPeer()->name()); + name(), dmaPort->getPeer()->name()); dmaPort = new DmaPort(this, sys); return dmaPort; } else -- cgit v1.2.3 From 194f0310d3bad34f94f66289946f9d34f00d33e4 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 10 Nov 2008 11:51:17 -0800 Subject: safe_cast: add a new cast function for casts that should always succeed. In DEBUG mode, this does a dynamic_cast and asserts that the result is non null. Otherwise, it just does a static_cast. Again, this is only intended for cases where the cast should always succeed and what's desired is a debugging check to make sure. --- src/base/cast.hh | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/base/cast.hh (limited to 'src') diff --git a/src/base/cast.hh b/src/base/cast.hh new file mode 100644 index 000000000..30a065cd2 --- /dev/null +++ b/src/base/cast.hh @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2008 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +#ifndef __BASE_CAST_HH__ +#define __BASE_CAST_HH__ + +#include + +// This is designed for situations where we have a pointer to a base +// type, but in all cases when we cast it to a derived type, we know +// by construction that it should work correctly. + +#if defined(DEBUG) + +// In debug builds, do the dynamic cast and assert the result is good + +template +inline T +safe_cast(U ptr) +{ + T ret = dynamic_cast(ptr); + assert(ret); + return ret; +} + +#else + +// In non debug builds statically cast the result to the pointer we +// want to use. This is technically unsafe, but this is only for +// cases where we know that this should work by construction. + +template +inline T +safe_cast(U ptr) +{ + return static_cast(ptr); +} + +#endif + +#endif // __BASE_CAST_HH__ -- cgit v1.2.3 From 2dd699ed3d31b5aee8fbb88948c4ea6083b1c8b0 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 10 Nov 2008 11:51:17 -0800 Subject: flags: Provide an object for managing boolean flags for an object. In many cases it might be preferable to use bitset, but this object allows the user more easily manipulate groups of flags because the underlying type (e.g. uint64_t) is exposed. --- src/base/flags.hh | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 src/base/flags.hh (limited to 'src') diff --git a/src/base/flags.hh b/src/base/flags.hh new file mode 100644 index 000000000..7cf6ef9c6 --- /dev/null +++ b/src/base/flags.hh @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2008 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +#ifndef __BASE_FLAGS_HH__ +#define __BASE_FLAGS_HH__ + +template +class Flags +{ + private: + T _flags; + + public: + typedef T Type; + Flags() : _flags(0) {} + Flags(Type flags) : _flags(flags) {} + + operator const Type() const { return _flags; } + + template + const Flags & + operator=(const Flags &flags) + { + _flags = flags._flags; + return *this; + } + + const Flags & + operator=(T flags) + { + _flags = flags; + return *this; + } + + bool any() const { return _flags; } + bool any(Type flags) const { return (_flags & flags); } + bool all() const { return (~_flags); } + bool all(Type flags) const { return (_flags & flags) != flags; } + bool none() const { return _flags == 0; } + bool none(Type flags) const { return (_flags & flags) == 0; } + bool exact(Type flags) const { return _flags = flags; } + void clear() { _flags = 0; } + void clear(Type flags) { _flags &= ~flags; } + void reset(Type flags) { _flags = flags;} + void set(Type flags) { _flags |= flags; } + void set(Type f, bool val) { _flags = (_flags & f) | (val ? f : 0); } + void + update(Type flags, Type mask) + { + _flags = (_flags & ~mask) | (flags & mask); + } +}; + +#endif // __BASE_FLAGS_HH__ -- cgit v1.2.3 From 3535d746ab2adaef4c13fbf869ccc3a2e98279cd Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 10 Nov 2008 11:51:17 -0800 Subject: style: clean up the Packet stuff --- src/mem/packet.cc | 64 ++---- src/mem/packet.hh | 560 +++++++++++++++++++++++++++-------------------- src/mem/packet_access.hh | 3 +- src/mem/request.hh | 391 +++++++++++++++++++++++---------- 4 files changed, 609 insertions(+), 409 deletions(-) (limited to 'src') diff --git a/src/mem/packet.cc b/src/mem/packet.cc index f27bd9dbf..17e58859a 100644 --- a/src/mem/packet.cc +++ b/src/mem/packet.cc @@ -42,6 +42,8 @@ #include "base/trace.hh" #include "mem/packet.hh" +using namespace std; + // The one downside to bitsets is that static initializers can get ugly. #define SET1(a1) (1 << (a1)) #define SET2(a1, a2) (SET1(a1) | SET1(a2)) @@ -133,35 +135,6 @@ MemCmd::commandInfo[] = { SET2(IsRequest, IsPrint), InvalidCmd, "PrintReq" } }; - -/** delete the data pointed to in the data pointer. Ok to call to matter how - * data was allocted. */ -void -Packet::deleteData() -{ - assert(staticData || dynamicData); - if (staticData) - return; - - if (arrayData) - delete [] data; - else - delete data; -} - -/** If there isn't data in the packet, allocate some. */ -void -Packet::allocate() -{ - if (data) - return; - assert(!staticData); - dynamicData = true; - arrayData = true; - data = new uint8_t[getSize()]; -} - - bool Packet::checkFunctional(Printable *obj, Addr addr, int size, uint8_t *data) { @@ -193,7 +166,7 @@ Packet::checkFunctional(Printable *obj, Addr addr, int size, uint8_t *data) if (isRead()) { if (func_start >= val_start && func_end <= val_end) { allocate(); - std::memcpy(getPtr(), data + offset, getSize()); + memcpy(getPtr(), data + offset, getSize()); makeResponse(); return true; } else { @@ -208,11 +181,12 @@ Packet::checkFunctional(Printable *obj, Addr addr, int size, uint8_t *data) } } else if (isWrite()) { if (offset >= 0) { - std::memcpy(data + offset, getPtr(), - (std::min(func_end, val_end) - func_start) + 1); - } else { // val_start > func_start - std::memcpy(data, getPtr() - offset, - (std::min(func_end, val_end) - val_start) + 1); + memcpy(data + offset, getPtr(), + (min(func_end, val_end) - func_start) + 1); + } else { + // val_start > func_start + memcpy(data, getPtr() - offset, + (min(func_end, val_end) - val_start) + 1); } } else { panic("Don't know how to handle command %s\n", cmdString()); @@ -222,23 +196,19 @@ Packet::checkFunctional(Printable *obj, Addr addr, int size, uint8_t *data) return false; } - void -Packet::print(std::ostream &o, const int verbosity, - const std::string &prefix) const +Packet::print(ostream &o, const int verbosity, const string &prefix) const { ccprintf(o, "%s[%x:%x] %s\n", prefix, getAddr(), getAddr() + getSize() - 1, cmdString()); } - -Packet::PrintReqState::PrintReqState(std::ostream &_os, int _verbosity) - : curPrefixPtr(new std::string("")), os(_os), verbosity(_verbosity) +Packet::PrintReqState::PrintReqState(ostream &_os, int _verbosity) + : curPrefixPtr(new string("")), os(_os), verbosity(_verbosity) { labelStack.push_back(LabelStackEntry("", curPrefixPtr)); } - Packet::PrintReqState::~PrintReqState() { labelStack.pop_back(); @@ -246,21 +216,17 @@ Packet::PrintReqState::~PrintReqState() delete curPrefixPtr; } - Packet::PrintReqState:: -LabelStackEntry::LabelStackEntry(const std::string &_label, - std::string *_prefix) +LabelStackEntry::LabelStackEntry(const string &_label, string *_prefix) : label(_label), prefix(_prefix), labelPrinted(false) { } - void -Packet::PrintReqState::pushLabel(const std::string &lbl, - const std::string &prefix) +Packet::PrintReqState::pushLabel(const string &lbl, const string &prefix) { labelStack.push_back(LabelStackEntry(lbl, curPrefixPtr)); - curPrefixPtr = new std::string(*curPrefixPtr); + curPrefixPtr = new string(*curPrefixPtr); *curPrefixPtr += prefix; } diff --git a/src/mem/packet.hh b/src/mem/packet.hh index 1227cec89..38eb2e92b 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -42,8 +42,10 @@ #include #include +#include "base/cast.hh" #include "base/compiler.hh" #include "base/fast_alloc.hh" +#include "base/flags.hh" #include "base/misc.hh" #include "base/printable.hh" #include "mem/request.hh" @@ -58,9 +60,12 @@ typedef std::list PacketList; class MemCmd { - public: + friend class Packet; - /** List of all commands associated with a packet. */ + public: + /** + * List of all commands associated with a packet. + */ enum Command { InvalidCmd, @@ -100,7 +105,9 @@ class MemCmd }; private: - /** List of command attributes. */ + /** + * List of command attributes. + */ enum Attribute { IsRead, //!< Data flows from responder to requester @@ -120,26 +127,31 @@ class MemCmd NUM_COMMAND_ATTRIBUTES }; - /** Structure that defines attributes and other data associated - * with a Command. */ - struct CommandInfo { - /** Set of attribute flags. */ + /** + * Structure that defines attributes and other data associated + * with a Command. + */ + struct CommandInfo + { + /// Set of attribute flags. const std::bitset attributes; - /** Corresponding response for requests; InvalidCmd if no - * response is applicable. */ + /// Corresponding response for requests; InvalidCmd if no + /// response is applicable. const Command response; - /** String representation (for printing) */ + /// String representation (for printing) const std::string str; }; - /** Array to map Command enum to associated info. */ + /// Array to map Command enum to associated info. static const CommandInfo commandInfo[]; private: Command cmd; - bool testCmdAttrib(MemCmd::Attribute attrib) const { + bool + testCmdAttrib(MemCmd::Attribute attrib) const + { return commandInfo[cmd].attributes[attrib] != 0; } @@ -158,33 +170,22 @@ class MemCmd bool isError() const { return testCmdAttrib(IsError); } bool isPrint() const { return testCmdAttrib(IsPrint); } - const Command responseCommand() const { + const Command + responseCommand() const + { return commandInfo[cmd].response; } - /** Return the string to a cmd given by idx. */ - const std::string &toString() const { - return commandInfo[cmd].str; - } - + /// Return the string to a cmd given by idx. + const std::string &toString() const { return commandInfo[cmd].str; } int toInt() const { return (int)cmd; } - MemCmd(Command _cmd) - : cmd(_cmd) - { } - - MemCmd(int _cmd) - : cmd((Command)_cmd) - { } - - MemCmd() - : cmd(InvalidCmd) - { } + MemCmd(Command _cmd) : cmd(_cmd) { } + MemCmd(int _cmd) : cmd((Command)_cmd) { } + MemCmd() : cmd(InvalidCmd) { } - bool operator==(MemCmd c2) { return (cmd == c2.cmd); } - bool operator!=(MemCmd c2) { return (cmd != c2.cmd); } - - friend class Packet; + bool operator==(MemCmd c2) const { return (cmd == c2.cmd); } + bool operator!=(MemCmd c2) const { return (cmd != c2.cmd); } }; /** @@ -197,107 +198,118 @@ class MemCmd class Packet : public FastAlloc, public Printable { public: + typedef uint32_t FlagsType; + typedef ::Flags Flags; + typedef short NodeID; + + private: + static const FlagsType PUBLIC_FLAGS = 0x00000000; + static const FlagsType PRIVATE_FLAGS = 0x00007F0F; + static const FlagsType COPY_FLAGS = 0x0000000F; + + static const FlagsType SHARED = 0x00000001; + // Special control flags + /// Special timing-mode atomic snoop for multi-level coherence. + static const FlagsType EXPRESS_SNOOP = 0x00000002; + /// Does supplier have exclusive copy? + /// Useful for multi-level coherence. + static const FlagsType SUPPLY_EXCLUSIVE = 0x00000004; + // Snoop response flags + static const FlagsType MEM_INHIBIT = 0x00000008; + /// Are the 'addr' and 'size' fields valid? + static const FlagsType VALID_ADDR = 0x00000100; + static const FlagsType VALID_SIZE = 0x00000200; + /// Is the 'src' field valid? + static const FlagsType VALID_SRC = 0x00000400; + static const FlagsType VALID_DST = 0x00000800; + /// Is the data pointer set to a value that shouldn't be freed + /// when the packet is destroyed? + static const FlagsType STATIC_DATA = 0x00001000; + /// The data pointer points to a value that should be freed when + /// the packet is destroyed. + static const FlagsType DYNAMIC_DATA = 0x00002000; + /// the data pointer points to an array (thus delete []) needs to + /// be called on it rather than simply delete. + static const FlagsType ARRAY_DATA = 0x00004000; + + Flags flags; + public: typedef MemCmd::Command Command; - /** The command field of the packet. */ + /// The command field of the packet. MemCmd cmd; - /** A pointer to the original request. */ + /// A pointer to the original request. RequestPtr req; private: - /** A pointer to the data being transfered. It can be differnt - * sizes at each level of the heirarchy so it belongs in the - * packet, not request. This may or may not be populated when a - * responder recieves the packet. If not populated it memory - * should be allocated. + /** + * A pointer to the data being transfered. It can be differnt + * sizes at each level of the heirarchy so it belongs in the + * packet, not request. This may or may not be populated when a + * responder recieves the packet. If not populated it memory should + * be allocated. */ PacketDataPtr data; - /** Is the data pointer set to a value that shouldn't be freed - * when the packet is destroyed? */ - bool staticData; - /** The data pointer points to a value that should be freed when - * the packet is destroyed. */ - bool dynamicData; - /** the data pointer points to an array (thus delete [] ) needs to - * be called on it rather than simply delete.*/ - bool arrayData; - - /** The address of the request. This address could be virtual or - * physical, depending on the system configuration. */ + /// The address of the request. This address could be virtual or + /// physical, depending on the system configuration. Addr addr; - /** The size of the request or transfer. */ + /// The size of the request or transfer. int size; - /** Device address (e.g., bus ID) of the source of the - * transaction. The source is not responsible for setting this - * field; it is set implicitly by the interconnect when the - * packet is first sent. */ - short src; + /** + * Device address (e.g., bus ID) of the source of the + * transaction. The source is not responsible for setting this + * field; it is set implicitly by the interconnect when the packet + * is first sent. + */ + NodeID src; - /** Device address (e.g., bus ID) of the destination of the - * transaction. The special value Broadcast indicates that the - * packet should be routed based on its address. This field is - * initialized in the constructor and is thus always valid - * (unlike * addr, size, and src). */ - short dest; + /** + * Device address (e.g., bus ID) of the destination of the + * transaction. The special value Broadcast indicates that the + * packet should be routed based on its address. This field is + * initialized in the constructor and is thus always valid (unlike + * addr, size, and src). + */ + NodeID dest; - /** The original value of the command field. Only valid when the + /** + * The original value of the command field. Only valid when the * current command field is an error condition; in that case, the * previous contents of the command field are copied here. This * field is *not* set on non-error responses. */ MemCmd origCmd; - /** Are the 'addr' and 'size' fields valid? */ - bool addrSizeValid; - /** Is the 'src' field valid? */ - bool srcValid; - bool destValid; - - enum Flag { - // Snoop response flags - MemInhibit, - Shared, - // Special control flags - /// Special timing-mode atomic snoop for multi-level coherence. - ExpressSnoop, - /// Does supplier have exclusive copy? - /// Useful for multi-level coherence. - SupplyExclusive, - NUM_PACKET_FLAGS - }; - - /** Status flags */ - std::bitset flags; - public: - - /** Used to calculate latencies for each packet.*/ + /// Used to calculate latencies for each packet. Tick time; - /** The time at which the packet will be fully transmitted */ + /// The time at which the packet will be fully transmitted Tick finishTime; - /** The time at which the first chunk of the packet will be transmitted */ + /// The time at which the first chunk of the packet will be transmitted Tick firstWordTime; - /** The special destination address indicating that the packet - * should be routed based on its address. */ - static const short Broadcast = -1; - - /** A virtual base opaque structure used to hold state associated - * with the packet but specific to the sending device (e.g., an - * MSHR). A pointer to this state is returned in the packet's - * response so that the sender can quickly look up the state - * needed to process it. A specific subclass would be derived - * from this to carry state specific to a particular sending - * device. */ - class SenderState { - public: + /// The special destination address indicating that the packet + /// should be routed based on its address. + static const NodeID Broadcast = -1; + + /** + * A virtual base opaque structure used to hold state associated + * with the packet but specific to the sending device (e.g., an + * MSHR). A pointer to this state is returned in the packet's + * response so that the sender can quickly look up the state + * needed to process it. A specific subclass would be derived + * from this to carry state specific to a particular sending + * device. + */ + struct SenderState + { virtual ~SenderState() {} }; @@ -305,15 +317,18 @@ class Packet : public FastAlloc, public Printable * Object used to maintain state of a PrintReq. The senderState * field of a PrintReq should always be of this type. */ - class PrintReqState : public SenderState, public FastAlloc { - /** An entry in the label stack. */ - class LabelStackEntry { - public: + class PrintReqState : public SenderState, public FastAlloc + { + private: + /** + * An entry in the label stack. + */ + struct LabelStackEntry + { const std::string label; std::string *prefix; bool labelPrinted; - LabelStackEntry(const std::string &_label, - std::string *_prefix); + LabelStackEntry(const std::string &_label, std::string *_prefix); }; typedef std::list LabelStack; @@ -328,35 +343,53 @@ class Packet : public FastAlloc, public Printable PrintReqState(std::ostream &os, int verbosity = 0); ~PrintReqState(); - /** Returns the current line prefix. */ + /** + * Returns the current line prefix. + */ const std::string &curPrefix() { return *curPrefixPtr; } - /** Push a label onto the label stack, and prepend the given + /** + * Push a label onto the label stack, and prepend the given * prefix string onto the current prefix. Labels will only be - * printed if an object within the label's scope is - * printed. */ + * printed if an object within the label's scope is printed. + */ void pushLabel(const std::string &lbl, const std::string &prefix = " "); - /** Pop a label off the label stack. */ + + /** + * Pop a label off the label stack. + */ void popLabel(); - /** Print all of the pending unprinted labels on the + + /** + * Print all of the pending unprinted labels on the * stack. Called by printObj(), so normally not called by - * users unless bypassing printObj(). */ + * users unless bypassing printObj(). + */ void printLabels(); - /** Print a Printable object to os, because it matched the - * address on a PrintReq. */ + + /** + * Print a Printable object to os, because it matched the + * address on a PrintReq. + */ void printObj(Printable *obj); }; - /** This packet's sender state. Devices should use dynamic_cast<> - * to cast to the state appropriate to the sender. */ + /** + * This packet's sender state. Devices should use dynamic_cast<> + * to cast to the state appropriate to the sender. The intent of + * this variable is to allow a device to attach extra information + * to a request. A response packet must return the sender state + * that was attached to the original request (even if a new packet + * is created). + */ SenderState *senderState; - /** Return the string name of the cmd field (for debugging and - * tracing). */ + /// Return the string name of the cmd field (for debugging and + /// tracing). const std::string &cmdString() const { return cmd.toString(); } - /** Return the index of this command. */ + /// Return the index of this command. inline int cmdToIndex() const { return cmd.toInt(); } bool isRead() const { return cmd.isRead(); } @@ -373,88 +406,101 @@ class Packet : public FastAlloc, public Printable bool isPrint() const { return cmd.isPrint(); } // Snoop flags - void assertMemInhibit() { flags[MemInhibit] = true; } - bool memInhibitAsserted() { return flags[MemInhibit]; } - void assertShared() { flags[Shared] = true; } - bool sharedAsserted() { return flags[Shared]; } + void assertMemInhibit() { flags.set(MEM_INHIBIT); } + bool memInhibitAsserted() { return flags.any(MEM_INHIBIT); } + void assertShared() { flags.set(SHARED); } + bool sharedAsserted() { return flags.any(SHARED); } // Special control flags - void setExpressSnoop() { flags[ExpressSnoop] = true; } - bool isExpressSnoop() { return flags[ExpressSnoop]; } - void setSupplyExclusive() { flags[SupplyExclusive] = true; } - bool isSupplyExclusive() { return flags[SupplyExclusive]; } + void setExpressSnoop() { flags.set(EXPRESS_SNOOP); } + bool isExpressSnoop() { return flags.any(EXPRESS_SNOOP); } + void setSupplyExclusive() { flags.set(SUPPLY_EXCLUSIVE); } + bool isSupplyExclusive() { return flags.any(SUPPLY_EXCLUSIVE); } // Network error conditions... encapsulate them as methods since // their encoding keeps changing (from result field to command // field, etc.) - void setNacked() { assert(isResponse()); cmd = MemCmd::NetworkNackError; } - void setBadAddress() { assert(isResponse()); cmd = MemCmd::BadAddressError; } - bool wasNacked() { return cmd == MemCmd::NetworkNackError; } - bool hadBadAddress() { return cmd == MemCmd::BadAddressError; } + void + setNacked() + { + assert(isResponse()); + cmd = MemCmd::NetworkNackError; + } + + void + setBadAddress() + { + assert(isResponse()); + cmd = MemCmd::BadAddressError; + } + + bool wasNacked() const { return cmd == MemCmd::NetworkNackError; } + bool hadBadAddress() const { return cmd == MemCmd::BadAddressError; } void copyError(Packet *pkt) { assert(pkt->isError()); cmd = pkt->cmd; } - bool nic_pkt() { panic("Unimplemented"); M5_DUMMY_RETURN } - - /** Accessor function that returns the source index of the packet. */ - short getSrc() const { assert(srcValid); return src; } - void setSrc(short _src) { src = _src; srcValid = true; } - /** Reset source field, e.g. to retransmit packet on different bus. */ - void clearSrc() { srcValid = false; } - - /** Accessor function that returns the destination index of - the packet. */ - short getDest() const { assert(destValid); return dest; } - void setDest(short _dest) { dest = _dest; destValid = true; } - - Addr getAddr() const { assert(addrSizeValid); return addr; } - int getSize() const { assert(addrSizeValid); return size; } - Addr getOffset(int blkSize) const { return addr & (Addr)(blkSize - 1); } - - /** Constructor. Note that a Request object must be constructed - * first, but the Requests's physical address and size fields - * need not be valid. The command and destination addresses - * must be supplied. */ - Packet(Request *_req, MemCmd _cmd, short _dest) - : cmd(_cmd), req(_req), - data(NULL), staticData(false), dynamicData(false), arrayData(false), - addr(_req->paddr), size(_req->size), dest(_dest), - addrSizeValid(_req->validPaddr), srcValid(false), destValid(true), - flags(0), time(curTick), senderState(NULL) + /// Accessor function to get the source index of the packet. + NodeID getSrc() const { assert(flags.any(VALID_SRC)); return src; } + /// Accessor function to set the source index of the packet. + void setSrc(NodeID _src) { src = _src; flags.set(VALID_SRC); } + /// Reset source field, e.g. to retransmit packet on different bus. + void clearSrc() { flags.clear(VALID_SRC); } + + /// Accessor function for the destination index of the packet. + NodeID getDest() const { assert(flags.any(VALID_DST)); return dest; } + /// Accessor function to set the destination index of the packet. + void setDest(NodeID _dest) { dest = _dest; flags.set(VALID_DST); } + + Addr getAddr() const { assert(flags.all(VALID_ADDR)); return addr; } + int getSize() const { assert(flags.all(VALID_SIZE)); return size; } + Addr getOffset(int blkSize) const { return getAddr() & (Addr)(blkSize - 1); } + + /** + * Constructor. Note that a Request object must be constructed + * first, but the Requests's physical address and size fields need + * not be valid. The command and destination addresses must be + * supplied. + */ + Packet(Request *_req, MemCmd _cmd, NodeID _dest) + : cmd(_cmd), req(_req), data(NULL), addr(_req->paddr), + size(_req->size), dest(_dest), time(curTick), senderState(NULL) { } - /** Alternate constructor if you are trying to create a packet with - * a request that is for a whole block, not the address from the req. - * this allows for overriding the size/addr of the req.*/ - Packet(Request *_req, MemCmd _cmd, short _dest, int _blkSize) - : cmd(_cmd), req(_req), - data(NULL), staticData(false), dynamicData(false), arrayData(false), + /** + * Alternate constructor if you are trying to create a packet with + * a request that is for a whole block, not the address from the + * req. this allows for overriding the size/addr of the req. + */ + Packet(Request *_req, MemCmd _cmd, NodeID _dest, int _blkSize) + : cmd(_cmd), req(_req), data(NULL), addr(_req->paddr & ~(_blkSize - 1)), size(_blkSize), dest(_dest), - addrSizeValid(_req->validPaddr), srcValid(false), destValid(true), - flags(0), time(curTick), senderState(NULL) + time(curTick), senderState(NULL) { } - /** Alternate constructor for copying a packet. Copy all fields + /** + * Alternate constructor for copying a packet. Copy all fields * *except* if the original packet's data was dynamic, don't copy * that, as we can't guarantee that the new packet's lifetime is * less than that of the original packet. In this case the new - * packet should allocate its own data. */ - Packet(Packet *origPkt, bool clearFlags = false) - : cmd(origPkt->cmd), req(origPkt->req), - data(origPkt->staticData ? origPkt->data : NULL), - staticData(origPkt->staticData), - dynamicData(false), arrayData(false), - addr(origPkt->addr), size(origPkt->size), - src(origPkt->src), dest(origPkt->dest), - addrSizeValid(origPkt->addrSizeValid), - srcValid(origPkt->srcValid), destValid(origPkt->destValid), - flags(clearFlags ? 0 : origPkt->flags), - time(curTick), senderState(origPkt->senderState) + * packet should allocate its own data. + */ + Packet(Packet *pkt, bool clearFlags = false) + : cmd(pkt->cmd), req(pkt->req), + data(pkt->flags.any(STATIC_DATA) ? pkt->data : NULL), + addr(pkt->addr), size(pkt->size), src(pkt->src), dest(pkt->dest), + time(curTick), senderState(pkt->senderState) { + if (!clearFlags) + flags.set(pkt->flags & COPY_FLAGS); + + flags.set(pkt->flags & (VALID_ADDR|VALID_SIZE|VALID_SRC|VALID_DST)); + flags.set(pkt->flags & STATIC_DATA); } - /** Destructor. */ + /** + * clean up packet variables + */ ~Packet() { // If this is a request packet for which there's no response, @@ -462,27 +508,27 @@ class Packet : public FastAlloc, public Printable // never get the chance. if (req && isRequest() && !needsResponse()) delete req; - if (staticData || dynamicData) - deleteData(); + deleteData(); } - /** Reinitialize packet address and size from the associated - * Request object, and reset other fields that may have been - * modified by a previous transaction. Typically called when a - * statically allocated Request/Packet pair is reused for - * multiple transactions. */ - void reinitFromRequest() { - assert(req->validPaddr); + /** + * Reinitialize packet address and size from the associated + * Request object, and reset other fields that may have been + * modified by a previous transaction. Typically called when a + * statically allocated Request/Packet pair is reused for multiple + * transactions. + */ + void + reinitFromRequest() + { + assert(req->flags.any(Request::VALID_PADDR)); flags = 0; addr = req->paddr; size = req->size; time = req->time; - addrSizeValid = true; - if (dynamicData) { - deleteData(); - dynamicData = false; - arrayData = false; - } + + flags.set(VALID_ADDR|VALID_SIZE); + deleteData(); } /** @@ -491,23 +537,30 @@ class Packet : public FastAlloc, public Printable * destination fields are *not* modified, as is appropriate for * atomic accesses. */ - void makeResponse() + void + makeResponse() { assert(needsResponse()); assert(isRequest()); origCmd = cmd; cmd = cmd.responseCommand(); - dest = src; - destValid = srcValid; - srcValid = false; + if (flags.any(VALID_SRC)) { + dest = src; + flags.set(VALID_DST); + flags.clear(VALID_SRC); + } else { + flags.clear(VALID_DST); + } } - void makeAtomicResponse() + void + makeAtomicResponse() { makeResponse(); } - void makeTimingResponse() + void + makeTimingResponse() { makeResponse(); } @@ -535,10 +588,9 @@ class Packet : public FastAlloc, public Printable void dataStatic(T *p) { - if(dynamicData) - dynamicData = false; + assert(flags.none(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA)); data = (PacketDataPtr)p; - staticData = true; + flags.set(STATIC_DATA); } /** @@ -549,10 +601,9 @@ class Packet : public FastAlloc, public Printable void dataDynamicArray(T *p) { - assert(!staticData && !dynamicData); + assert(flags.none(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA)); data = (PacketDataPtr)p; - dynamicData = true; - arrayData = true; + flags.set(DYNAMIC_DATA|ARRAY_DATA); } /** @@ -563,33 +614,39 @@ class Packet : public FastAlloc, public Printable void dataDynamic(T *p) { - assert(!staticData && !dynamicData); + assert(flags.none(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA)); data = (PacketDataPtr)p; - dynamicData = true; - arrayData = false; + flags.set(DYNAMIC_DATA); } - /** get a pointer to the data ptr. */ + /** + * get a pointer to the data ptr. + */ template T* getPtr() { - assert(staticData || dynamicData); + assert(flags.any(STATIC_DATA|DYNAMIC_DATA)); return (T*)data; } - /** return the value of what is pointed to in the packet. */ + /** + * return the value of what is pointed to in the packet. + */ template T get(); - /** set the value in the data pointer to v. */ + /** + * set the value in the data pointer to v. + */ template void set(T v); /** * Copy data into the packet from the provided pointer. */ - void setData(uint8_t *p) + void + setData(uint8_t *p) { std::memcpy(getPtr(), p, getSize()); } @@ -598,7 +655,8 @@ class Packet : public FastAlloc, public Printable * Copy data into the packet from the provided block pointer, * which is aligned to the given block size. */ - void setDataFromBlock(uint8_t *blk_data, int blkSize) + void + setDataFromBlock(uint8_t *blk_data, int blkSize) { setData(blk_data + getOffset(blkSize)); } @@ -607,7 +665,8 @@ class Packet : public FastAlloc, public Printable * Copy data from the packet to the provided block pointer, which * is aligned to the given block size. */ - void writeData(uint8_t *p) + void + writeData(uint8_t *p) { std::memcpy(p, getPtr(), getSize()); } @@ -615,7 +674,8 @@ class Packet : public FastAlloc, public Printable /** * Copy data from the packet to the memory at the provided pointer. */ - void writeDataToBlock(uint8_t *blk_data, int blkSize) + void + writeDataToBlock(uint8_t *blk_data, int blkSize) { writeData(blk_data + getOffset(blkSize)); } @@ -624,10 +684,31 @@ class Packet : public FastAlloc, public Printable * delete the data pointed to in the data pointer. Ok to call to * matter how data was allocted. */ - void deleteData(); + void + deleteData() + { + if (flags.any(ARRAY_DATA)) + delete [] data; + else if (flags.any(DYNAMIC_DATA)) + + delete data; + + flags.clear(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA); + data = NULL; + } /** If there isn't data in the packet, allocate some. */ - void allocate(); + void + allocate() + { + if (data) { + assert(flags.none(STATIC_DATA|DYNAMIC_DATA)); + } else { + flags.set(DYNAMIC_DATA|ARRAY_DATA); + data = new uint8_t[getSize()]; + } + } + /** * Check a functional request against a memory value represented @@ -642,29 +723,32 @@ class Packet : public FastAlloc, public Printable * Check a functional request against a memory value stored in * another packet (i.e. an in-transit request or response). */ - bool checkFunctional(PacketPtr otherPkt) { - return checkFunctional(otherPkt, - otherPkt->getAddr(), otherPkt->getSize(), - otherPkt->hasData() ? - otherPkt->getPtr() : NULL); + bool + checkFunctional(PacketPtr other) + { + uint8_t *data = other->hasData() ? other->getPtr() : NULL; + return checkFunctional(other, other->getAddr(), other->getSize(), + data); } /** * Push label for PrintReq (safe to call unconditionally). */ - void pushLabel(const std::string &lbl) { - if (isPrint()) { - dynamic_cast(senderState)->pushLabel(lbl); - } + void + pushLabel(const std::string &lbl) + { + if (isPrint()) + safe_cast(senderState)->pushLabel(lbl); } /** * Pop label for PrintReq (safe to call unconditionally). */ - void popLabel() { - if (isPrint()) { - dynamic_cast(senderState)->popLabel(); - } + void + popLabel() + { + if (isPrint()) + safe_cast(senderState)->popLabel(); } void print(std::ostream &o, int verbosity = 0, diff --git a/src/mem/packet_access.hh b/src/mem/packet_access.hh index d1edd00aa..1e233ee57 100644 --- a/src/mem/packet_access.hh +++ b/src/mem/packet_access.hh @@ -46,7 +46,7 @@ template inline T Packet::get() { - assert(staticData || dynamicData); + assert(flags.any(STATIC_DATA|DYNAMIC_DATA)); assert(sizeof(T) <= size); return TheISA::gtoh(*(T*)data); } @@ -56,6 +56,7 @@ template inline void Packet::set(T v) { + assert(flags.any(STATIC_DATA|DYNAMIC_DATA)); assert(sizeof(T) <= size); *(T*)data = TheISA::htog(v); } diff --git a/src/mem/request.hh b/src/mem/request.hh index d1e011c7d..c3a523d9b 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -39,79 +39,103 @@ #ifndef __MEM_REQUEST_HH__ #define __MEM_REQUEST_HH__ +#include + #include "base/fast_alloc.hh" +#include "base/flags.hh" #include "sim/host.hh" #include "sim/core.hh" -#include - class Request; typedef Request* RequestPtr; +class Request : public FastAlloc +{ + public: + typedef uint32_t FlagsType; + typedef ::Flags Flags; + + /** ASI information for this request if it exists. */ + static const FlagsType ASI_BITS = 0x000000FF; + /** The request is a Load locked/store conditional. */ + static const FlagsType LOCKED = 0x00000100; + /** The virtual address is also the physical address. */ + static const FlagsType PHYSICAL = 0x00000200; + /** The request is an ALPHA VPTE pal access (hw_ld). */ + static const FlagsType VPTE = 0x00000400; + /** Use the alternate mode bits in ALPHA. */ + static const FlagsType ALTMODE = 0x00000800; + /** The request is to an uncacheable address. */ + static const FlagsType UNCACHEABLE = 0x00001000; + /** The request should not cause a page fault. */ + static const FlagsType NO_FAULT = 0x00002000; + /** The request should be prefetched into the exclusive state. */ + static const FlagsType PF_EXCLUSIVE = 0x00010000; + /** The request should be marked as LRU. */ + static const FlagsType EVICT_NEXT = 0x00020000; + /** The request should ignore unaligned access faults */ + static const FlagsType NO_ALIGN_FAULT = 0x00040000; + /** The request was an instruction read. */ + static const FlagsType INST_READ = 0x00080000; + /** This request is for a memory swap. */ + static const FlagsType MEM_SWAP = 0x00100000; + static const FlagsType MEM_SWAP_COND = 0x00200000; + /** The request should ignore unaligned access faults */ + static const FlagsType NO_HALF_WORD_ALIGN_FAULT = 0x00400000; + /** This request is to a memory mapped register. */ + static const FlagsType MMAPED_IPR = 0x00800000; -/** ASI information for this request if it exsits. */ -const uint32_t ASI_BITS = 0x000FF; -/** The request is a Load locked/store conditional. */ -const uint32_t LOCKED = 0x00100; -/** The virtual address is also the physical address. */ -const uint32_t PHYSICAL = 0x00200; -/** The request is an ALPHA VPTE pal access (hw_ld). */ -const uint32_t VPTE = 0x00400; -/** Use the alternate mode bits in ALPHA. */ -const uint32_t ALTMODE = 0x00800; -/** The request is to an uncacheable address. */ -const uint32_t UNCACHEABLE = 0x01000; -/** The request should not cause a page fault. */ -const uint32_t NO_FAULT = 0x02000; -/** The request should be prefetched into the exclusive state. */ -const uint32_t PF_EXCLUSIVE = 0x10000; -/** The request should be marked as LRU. */ -const uint32_t EVICT_NEXT = 0x20000; -/** The request should ignore unaligned access faults */ -const uint32_t NO_ALIGN_FAULT = 0x40000; -/** The request was an instruction read. */ -const uint32_t INST_READ = 0x80000; -/** This request is for a memory swap. */ -const uint32_t MEM_SWAP = 0x100000; -const uint32_t MEM_SWAP_COND = 0x200000; -/** The request should ignore unaligned access faults */ -const uint32_t NO_HALF_WORD_ALIGN_FAULT = 0x400000; + private: + static const FlagsType PUBLIC_FLAGS = 0x00FF3FFF; + static const FlagsType PRIVATE_FLAGS = 0xFF000000; + /** Whether or not the size is valid. */ + static const FlagsType VALID_SIZE = 0x01000000; + /** Whether or not paddr is valid (has been written yet). */ + static const FlagsType VALID_PADDR = 0x02000000; + /** Whether or not the vaddr & asid are valid. */ + static const FlagsType VALID_VADDR = 0x04000000; + /** Whether or not the pc is valid. */ + static const FlagsType VALID_PC = 0x10000000; + /** Whether or not the context ID is valid. */ + static const FlagsType VALID_CONTEXT_ID = 0x20000000; + static const FlagsType VALID_THREAD_ID = 0x40000000; + /** Whether or not the sc result is valid. */ + static const FlagsType VALID_EXTRA_DATA = 0x80000000; -class Request : public FastAlloc -{ private: /** * The physical address of the request. Valid only if validPaddr - * is set. */ + * is set. + */ Addr paddr; /** * The size of the request. This field must be set when vaddr or * paddr is written via setVirt() or setPhys(), so it is always - * valid as long as one of the address fields is valid. */ + * valid as long as one of the address fields is valid. + */ int size; /** Flag structure for the request. */ - uint32_t flags; + Flags flags; /** * The time this request was started. Used to calculate * latencies. This field is set to curTick any time paddr or vaddr - * is written. */ + * is written. + */ Tick time; /** The address space ID. */ int asid; - /** This request is to a memory mapped register. */ - bool mmapedIpr; - /** The virtual address of the request. */ Addr vaddr; - /** Extra data for the request, such as the return value of + /** + * Extra data for the request, such as the return value of * store conditional or the compare value for a CAS. */ uint64_t extraData; @@ -123,170 +147,295 @@ class Request : public FastAlloc /** program counter of initiating access; for tracing/debugging */ Addr pc; - /** Whether or not paddr is valid (has been written yet). */ - bool validPaddr; - /** Whether or not the asid & vaddr are valid. */ - bool validAsidVaddr; - /** Whether or not the sc result is valid. */ - bool validExData; - /** Whether or not the context ID is valid. */ - bool validContextAndThreadIds; - /** Whether or not the pc is valid. */ - bool validPC; - public: /** Minimal constructor. No fields are initialized. */ Request() - : validPaddr(false), validAsidVaddr(false), - validExData(false), validContextAndThreadIds(false), validPC(false) {} /** * Constructor for physical (e.g. device) requests. Initializes * just physical address, size, flags, and timestamp (to curTick). - * These fields are adequate to perform a request. */ - Request(Addr _paddr, int _size, int _flags) - : validContextAndThreadIds(false) - { setPhys(_paddr, _size, _flags); } + * These fields are adequate to perform a request. + */ + Request(Addr paddr, int size, Flags flags) + { + setPhys(paddr, size, flags); + } - Request(int _asid, Addr _vaddr, int _size, int _flags, Addr _pc, - int _context_id, int _thread_id) + Request(int asid, Addr vaddr, int size, Flags flags, Addr pc, + int cid, int tid) { - setThreadContext(_context_id, _thread_id); - setVirt(_asid, _vaddr, _size, _flags, _pc); + setThreadContext(cid, tid); + setVirt(asid, vaddr, size, flags, pc); } ~Request() {} // for FastAlloc /** - * Set up CPU and thread numbers. */ - void setThreadContext(int _context_id, int _thread_id) + * Set up CPU and thread numbers. + */ + void + setThreadContext(int context_id, int thread_id) { - _contextId = _context_id; - _threadId = _thread_id; - validContextAndThreadIds = true; + _contextId = context_id; + _threadId = thread_id; + flags.set(VALID_CONTEXT_ID|VALID_THREAD_ID); } /** * Set up a physical (e.g. device) request in a previously - * allocated Request object. */ - void setPhys(Addr _paddr, int _size, int _flags) + * allocated Request object. + */ + void + setPhys(Addr _paddr, int _size, Flags _flags) { assert(_size >= 0); paddr = _paddr; size = _size; - flags = _flags; time = curTick; - validPaddr = true; - validAsidVaddr = false; - validPC = false; - validExData = false; - mmapedIpr = false; + + flags.set(VALID_PADDR|VALID_SIZE); + flags.clear(VALID_VADDR|VALID_PC|VALID_EXTRA_DATA|MMAPED_IPR); + flags.update(_flags, PUBLIC_FLAGS); } /** * Set up a virtual (e.g., CPU) request in a previously - * allocated Request object. */ - void setVirt(int _asid, Addr _vaddr, int _size, int _flags, Addr _pc) + * allocated Request object. + */ + void + setVirt(int _asid, Addr _vaddr, int _size, Flags _flags, Addr _pc) { assert(_size >= 0); asid = _asid; vaddr = _vaddr; size = _size; - flags = _flags; pc = _pc; time = curTick; - validPaddr = false; - validAsidVaddr = true; - validPC = true; - validExData = false; - mmapedIpr = false; + + flags.set(VALID_VADDR|VALID_SIZE|VALID_PC); + flags.clear(VALID_PADDR|VALID_EXTRA_DATA|MMAPED_IPR); + flags.update(_flags, PUBLIC_FLAGS); } - /** Set just the physical address. This should only be used to + /** + * Set just the physical address. This should only be used to * record the result of a translation, and thus the vaddr must be * valid before this method is called. Otherwise, use setPhys() * to guarantee that the size and flags are also set. */ - void setPaddr(Addr _paddr) + void + setPaddr(Addr _paddr) { - assert(validAsidVaddr); + assert(flags.any(VALID_VADDR)); paddr = _paddr; - validPaddr = true; + flags.set(VALID_PADDR); + } + + /** + * Accessor for paddr. + */ + Addr + getPaddr() + { + assert(flags.any(VALID_PADDR)); + return paddr; } - /** Accessor for paddr. */ - Addr getPaddr() { assert(validPaddr); return paddr; } + /** + * Accessor for size. + */ + int + getSize() + { + assert(flags.any(VALID_SIZE)); + return size; + } - /** Accessor for size. */ - int getSize() { assert(validPaddr || validAsidVaddr); return size; } /** Accessor for time. */ - Tick getTime() { assert(validPaddr || validAsidVaddr); return time; } - void resetTime() { assert(validPaddr || validAsidVaddr); time = curTick; } + Tick + getTime() + { + assert(flags.any(VALID_PADDR|VALID_VADDR)); + return time; + } + void setTime(Tick when) { - assert(validPaddr || validAsidVaddr); + assert(flags.any(VALID_PADDR|VALID_VADDR)); time = when; } + void resetTime() { setTime(curTick); } + + /** Accessor for flags. */ + Flags + getFlags() + { + assert(flags.any(VALID_PADDR|VALID_VADDR)); + return flags & PUBLIC_FLAGS; + } + + Flags + anyFlags(Flags _flags) + { + assert(flags.any(VALID_PADDR|VALID_VADDR)); + assert(_flags.none(~PUBLIC_FLAGS)); + return flags.any(_flags); + } + + Flags + allFlags(Flags _flags) + { + assert(flags.any(VALID_PADDR|VALID_VADDR)); + assert(_flags.none(~PUBLIC_FLAGS)); + return flags.all(_flags); + } + /** Accessor for flags. */ - uint32_t getFlags() { assert(validPaddr || validAsidVaddr); return flags; } - /** Accessor for paddr. */ - void setFlags(uint32_t _flags) - { assert(validPaddr || validAsidVaddr); flags = _flags; } + void + setFlags(Flags _flags) + { + assert(flags.any(VALID_PADDR|VALID_VADDR)); + assert(_flags.none(~PUBLIC_FLAGS)); + flags.set(_flags); + } + + void + clearFlags(Flags _flags) + { + assert(flags.any(VALID_PADDR|VALID_VADDR)); + assert(_flags.none(~PUBLIC_FLAGS)); + flags.clear(_flags); + } + + void + clearFlags() + { + assert(flags.any(VALID_PADDR|VALID_VADDR)); + flags.clear(PUBLIC_FLAGS); + } /** Accessor function for vaddr.*/ - Addr getVaddr() { assert(validAsidVaddr); return vaddr; } + Addr + getVaddr() + { + assert(flags.any(VALID_VADDR)); + return vaddr; + } /** Accessor function for asid.*/ - int getAsid() { assert(validAsidVaddr); return asid; } + int + getAsid() + { + assert(flags.any(VALID_VADDR)); + return asid; + } /** Accessor function for asi.*/ - uint8_t getAsi() { assert(validAsidVaddr); return flags & ASI_BITS; } + uint8_t + getAsi() + { + assert(flags.any(VALID_VADDR)); + return flags & ASI_BITS; + } /** Accessor function for asi.*/ - void setAsi(uint8_t a) - { assert(validAsidVaddr); flags = (flags & ~ASI_BITS) | a; } + void + setAsi(uint8_t a) + { + assert(flags.any(VALID_VADDR)); + flags.update(a, ASI_BITS); + } /** Accessor function for asi.*/ - bool isMmapedIpr() { assert(validPaddr); return mmapedIpr; } + bool + isMmapedIpr() + { + assert(flags.any(VALID_PADDR)); + return flags.any(MMAPED_IPR); + } /** Accessor function for asi.*/ - void setMmapedIpr(bool r) { assert(validAsidVaddr); mmapedIpr = r; } + void + setMmapedIpr(bool r) + { + assert(VALID_VADDR); + flags.set(MMAPED_IPR); + } /** Accessor function to check if sc result is valid. */ - bool extraDataValid() { return validExData; } + bool + extraDataValid() + { + return flags.any(VALID_EXTRA_DATA); + } + /** Accessor function for store conditional return value.*/ - uint64_t getExtraData() { assert(validExData); return extraData; } + uint64_t + getExtraData() const + { + assert(flags.any(VALID_EXTRA_DATA)); + return extraData; + } + /** Accessor function for store conditional return value.*/ - void setExtraData(uint64_t _extraData) - { extraData = _extraData; validExData = true; } + void + setExtraData(uint64_t _extraData) + { + extraData = _extraData; + flags.set(VALID_EXTRA_DATA); + } /** Accessor function for context ID.*/ - int contextId() { assert(validContextAndThreadIds); return _contextId; } + int + contextId() const + { + assert(flags.any(VALID_CONTEXT_ID)); + return _contextId; + } + /** Accessor function for thread ID. */ - int threadId() { assert(validContextAndThreadIds); return _threadId; } + int + threadId() const + { + assert(flags.any(VALID_THREAD_ID)); + return _threadId; + } /** Accessor function for pc.*/ - Addr getPC() { assert(validPC); return pc; } + Addr + getPC() const + { + assert(flags.any(VALID_PC)); + return pc; + } /** Accessor Function to Check Cacheability. */ - bool isUncacheable() { return (getFlags() & UNCACHEABLE) != 0; } - - bool isInstRead() { return (getFlags() & INST_READ) != 0; } + bool isUncacheable() const { return flags.any(UNCACHEABLE); } + bool isInstRead() const { return flags.any(INST_READ); } + bool isLocked() const { return flags.any(LOCKED); } + bool isSwap() const { return flags.any(MEM_SWAP|MEM_SWAP_COND); } + bool isCondSwap() const { return flags.any(MEM_SWAP_COND); } + + bool + isMisaligned() const + { + if (flags.any(NO_ALIGN_FAULT)) + return false; - bool isLocked() { return (getFlags() & LOCKED) != 0; } + if ((vaddr & 0x1)) + return true; - bool isSwap() { return (getFlags() & MEM_SWAP || - getFlags() & MEM_SWAP_COND); } + if (flags.any(NO_HALF_WORD_ALIGN_FAULT)) + return false; - bool isCondSwap() { return (getFlags() & MEM_SWAP_COND) != 0; } + if ((vaddr & 0x2)) + return true; - bool inline isMisaligned() {return (!(getFlags() & NO_ALIGN_FAULT) && - ((vaddr & 1) || - (!(getFlags() & NO_HALF_WORD_ALIGN_FAULT) - && (vaddr & 0x2))));} + return false; + } friend class Packet; }; -- cgit v1.2.3 From 9c49bc7b00aa24b0488a83039ae8762d8f8094c5 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 10 Nov 2008 11:51:17 -0800 Subject: mem: update stuff for changes to Packet and Request --- src/arch/alpha/faults.cc | 2 +- src/arch/alpha/faults.hh | 14 +++++++------- src/arch/alpha/isa/mem.isa | 7 ++++--- src/arch/alpha/isa/pal.isa | 10 +++++----- src/arch/alpha/tlb.cc | 12 ++++++------ src/arch/mips/isa/formats/mem.isa | 6 +++--- src/arch/mips/isa/formats/util.isa | 3 ++- src/arch/mips/tlb.cc | 2 +- src/arch/sparc/isa/formats/mem/swap.isa | 3 +++ src/arch/sparc/tlb.cc | 6 +++--- src/arch/x86/intmessage.hh | 2 +- src/arch/x86/pagetable_walker.cc | 13 ++++++------- src/arch/x86/tlb.cc | 2 +- src/cpu/memtest/memtest.cc | 11 +++++------ 14 files changed, 48 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/faults.cc b/src/arch/alpha/faults.cc index dae188839..e89cf5c64 100644 --- a/src/arch/alpha/faults.cc +++ b/src/arch/alpha/faults.cc @@ -144,7 +144,7 @@ DtbFault::invoke(ThreadContext *tc) // read, like the EV5). The EV6 approach is cleaner and seems to // work with EV5 PAL code, but not the other way around. if (!tc->misspeculating() && - !(reqFlags & VPTE) && !(reqFlags & NO_FAULT)) { + reqFlags.none(Request::VPTE|Request::NO_FAULT)) { // set VA register with faulting address tc->setMiscRegNoEffect(IPR_VA, vaddr); diff --git a/src/arch/alpha/faults.hh b/src/arch/alpha/faults.hh index 4b107273b..9d90c7719 100644 --- a/src/arch/alpha/faults.hh +++ b/src/arch/alpha/faults.hh @@ -140,11 +140,11 @@ class DtbFault : public AlphaFault { protected: VAddr vaddr; - uint32_t reqFlags; + Request::Flags reqFlags; uint64_t flags; public: - DtbFault(VAddr _vaddr, uint32_t _reqFlags, uint64_t _flags) + DtbFault(VAddr _vaddr, Request::Flags _reqFlags, uint64_t _flags) : vaddr(_vaddr), reqFlags(_reqFlags), flags(_flags) { } FaultName name() const = 0; @@ -163,7 +163,7 @@ class NDtbMissFault : public DtbFault static FaultStat _count; public: - NDtbMissFault(VAddr vaddr, uint32_t reqFlags, uint64_t flags) + NDtbMissFault(VAddr vaddr, Request::Flags reqFlags, uint64_t flags) : DtbFault(vaddr, reqFlags, flags) { } FaultName name() const {return _name;} @@ -182,7 +182,7 @@ class PDtbMissFault : public DtbFault static FaultStat _count; public: - PDtbMissFault(VAddr vaddr, uint32_t reqFlags, uint64_t flags) + PDtbMissFault(VAddr vaddr, Request::Flags reqFlags, uint64_t flags) : DtbFault(vaddr, reqFlags, flags) { } FaultName name() const {return _name;} @@ -198,7 +198,7 @@ class DtbPageFault : public DtbFault static FaultStat _count; public: - DtbPageFault(VAddr vaddr, uint32_t reqFlags, uint64_t flags) + DtbPageFault(VAddr vaddr, Request::Flags reqFlags, uint64_t flags) : DtbFault(vaddr, reqFlags, flags) { } FaultName name() const {return _name;} @@ -214,7 +214,7 @@ class DtbAcvFault : public DtbFault static FaultStat _count; public: - DtbAcvFault(VAddr vaddr, uint32_t reqFlags, uint64_t flags) + DtbAcvFault(VAddr vaddr, Request::Flags reqFlags, uint64_t flags) : DtbFault(vaddr, reqFlags, flags) { } FaultName name() const {return _name;} @@ -230,7 +230,7 @@ class DtbAlignmentFault : public DtbFault static FaultStat _count; public: - DtbAlignmentFault(VAddr vaddr, uint32_t reqFlags, uint64_t flags) + DtbAlignmentFault(VAddr vaddr, Request::Flags reqFlags, uint64_t flags) : DtbFault(vaddr, reqFlags, flags) { } FaultName name() const {return _name;} diff --git a/src/arch/alpha/isa/mem.isa b/src/arch/alpha/isa/mem.isa index fe0daf772..b4e10e849 100644 --- a/src/arch/alpha/isa/mem.isa +++ b/src/arch/alpha/isa/mem.isa @@ -43,7 +43,7 @@ output header {{ protected: /// Memory request flags. See mem_req_base.hh. - unsigned memAccessFlags; + Request::Flags memAccessFlags; /// Pointer to EAComp object. const StaticInstPtr eaCompPtr; /// Pointer to MemAcc object. @@ -54,7 +54,7 @@ output header {{ StaticInstPtr _eaCompPtr = nullStaticInstPtr, StaticInstPtr _memAccPtr = nullStaticInstPtr) : AlphaStaticInst(mnem, _machInst, __opClass), - memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr) + eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr) { } @@ -677,7 +677,8 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, inst_flags) if mem_flags: - s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';' + mem_flags = [ 'Request::%s' % flag for flag in mem_flags ] + s = '\n\tmemAccessFlags.reset(' + string.join(mem_flags, '|') + ');' iop.constructor += s memacc_iop.constructor += s diff --git a/src/arch/alpha/isa/pal.isa b/src/arch/alpha/isa/pal.isa index 294b92e2f..3d3b81600 100644 --- a/src/arch/alpha/isa/pal.isa +++ b/src/arch/alpha/isa/pal.isa @@ -174,11 +174,11 @@ output decoder {{ : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr), disp(HW_LDST_DISP) { - memAccessFlags = 0; - if (HW_LDST_PHYS) memAccessFlags |= PHYSICAL; - if (HW_LDST_ALT) memAccessFlags |= ALTMODE; - if (HW_LDST_VPTE) memAccessFlags |= VPTE; - if (HW_LDST_LOCK) memAccessFlags |= LOCKED; + memAccessFlags.clear(); + if (HW_LDST_PHYS) memAccessFlags.set(Request::PHYSICAL); + if (HW_LDST_ALT) memAccessFlags.set(Request::ALTMODE); + if (HW_LDST_VPTE) memAccessFlags.set(Request::VPTE); + if (HW_LDST_LOCK) memAccessFlags.set(Request::LOCKED); } std::string diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc index 9266b8337..be02293d6 100644 --- a/src/arch/alpha/tlb.cc +++ b/src/arch/alpha/tlb.cc @@ -142,7 +142,7 @@ TLB::checkCacheability(RequestPtr &req, bool itb) return new UnimpFault("IPR memory space not implemented!"); } else { // mark request as uncacheable - req->setFlags(req->getFlags() | UNCACHEABLE); + req->setFlags(Request::UNCACHEABLE); #if !ALPHA_TLASER // Clear bits 42:35 of the physical address (10-2 in @@ -321,7 +321,7 @@ ITB::translate(RequestPtr &req, ThreadContext *tc) { //If this is a pal pc, then set PHYSICAL if (FULL_SYSTEM && PcPAL(req->getPC())) - req->setFlags(req->getFlags() | PHYSICAL); + req->setFlags(Request::PHYSICAL); if (PcPAL(req->getPC())) { // strip off PAL PC marker (lsb is 1) @@ -330,7 +330,7 @@ ITB::translate(RequestPtr &req, ThreadContext *tc) return NoFault; } - if (req->getFlags() & PHYSICAL) { + if (req->getFlags() & Request::PHYSICAL) { req->setPaddr(req->getVaddr()); } else { // verify that this is a good virtual address @@ -497,13 +497,13 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) } if (PcPAL(pc)) { - mode = (req->getFlags() & ALTMODE) ? + mode = (req->getFlags() & Request::ALTMODE) ? (mode_type)ALT_MODE_AM( tc->readMiscRegNoEffect(IPR_ALT_MODE)) : mode_kernel; } - if (req->getFlags() & PHYSICAL) { + if (req->getFlags() & Request::PHYSICAL) { req->setPaddr(req->getVaddr()); } else { // verify that this is a good virtual address @@ -560,7 +560,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) if (write) { write_misses++; } else { read_misses++; } uint64_t flags = (write ? MM_STAT_WR_MASK : 0) | MM_STAT_DTB_MISS_MASK; - return (req->getFlags() & VPTE) ? + return (req->getFlags() & Request::VPTE) ? (Fault)(new PDtbMissFault(req->getVaddr(), req->getFlags(), flags)) : (Fault)(new NDtbMissFault(req->getVaddr(), req->getFlags(), diff --git a/src/arch/mips/isa/formats/mem.isa b/src/arch/mips/isa/formats/mem.isa index f0210c29b..8596308e2 100644 --- a/src/arch/mips/isa/formats/mem.isa +++ b/src/arch/mips/isa/formats/mem.isa @@ -43,7 +43,7 @@ output header {{ protected: /// Memory request flags. See mem_req_base.hh. - unsigned memAccessFlags; + Request::Flags memAccessFlags; /// Pointer to EAComp object. const StaticInstPtr eaCompPtr; /// Pointer to MemAcc object. @@ -57,7 +57,7 @@ output header {{ StaticInstPtr _eaCompPtr = nullStaticInstPtr, StaticInstPtr _memAccPtr = nullStaticInstPtr) : MipsStaticInst(mnem, _machInst, __opClass), - memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr), + eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr), disp(sext<16>(OFFSET)) { } @@ -70,7 +70,7 @@ output header {{ const StaticInstPtr &eaCompInst() const { return eaCompPtr; } const StaticInstPtr &memAccInst() const { return memAccPtr; } - unsigned memAccFlags() { return memAccessFlags; } + Request::Flags memAccFlags() { return memAccessFlags; } }; /** diff --git a/src/arch/mips/isa/formats/util.isa b/src/arch/mips/isa/formats/util.isa index 0405aa5b3..786a964d4 100644 --- a/src/arch/mips/isa/formats/util.isa +++ b/src/arch/mips/isa/formats/util.isa @@ -61,7 +61,8 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, inst_flags) if mem_flags: - s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';' + mem_flags = [ 'Request::%s' % flag for flag in mem_flags ] + s = '\n\tmemAccessFlags.reset(' + string.join(mem_flags, '|') + ');' iop.constructor += s memacc_iop.constructor += s diff --git a/src/arch/mips/tlb.cc b/src/arch/mips/tlb.cc index 7c3b6aed5..e91da4eea 100644 --- a/src/arch/mips/tlb.cc +++ b/src/arch/mips/tlb.cc @@ -149,7 +149,7 @@ TLB::checkCacheability(RequestPtr &req) // or by the TLB entry if((req->getVaddr() & VAddrUncacheable) == VAddrUncacheable) { // mark request as uncacheable - req->setFlags(req->getFlags() | UNCACHEABLE); + req->setFlags(Request::UNCACHEABLE); } return NoFault; } diff --git a/src/arch/sparc/isa/formats/mem/swap.isa b/src/arch/sparc/isa/formats/mem/swap.isa index 2ebe9aa15..046f89822 100644 --- a/src/arch/sparc/isa/formats/mem/swap.isa +++ b/src/arch/sparc/isa/formats/mem/swap.isa @@ -133,6 +133,7 @@ let {{ def format Swap(code, postacc_code, mem_flags, *opt_flags) {{ mem_flags = makeList(mem_flags) + mem_flags = [ 'Request::%s' % flag for flag in mem_flags ] flags = string.join(mem_flags, '|') (header_output, @@ -144,6 +145,7 @@ def format Swap(code, postacc_code, mem_flags, *opt_flags) {{ def format SwapAlt(code, postacc_code, mem_flags, *opt_flags) {{ mem_flags = makeList(mem_flags) + mem_flags = [ 'Request::%s' % flag for flag in mem_flags ] mem_flags.append("EXT_ASI") flags = string.join(mem_flags, '|') (header_output, @@ -175,6 +177,7 @@ let {{ def format CasAlt(code, postacc_code, mem_flags, *opt_flags) {{ mem_flags = makeList(mem_flags) + mem_flags = [ 'Request::%s' % flag for flag in mem_flags ] mem_flags.append("EXT_ASI") flags = string.join(mem_flags, '|') (header_output, diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc index b6a450ffe..875ae1411 100644 --- a/src/arch/sparc/tlb.cc +++ b/src/arch/sparc/tlb.cc @@ -594,7 +594,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) (!write || ce->pte.writable())) { req->setPaddr(ce->pte.translate(vaddr)); if (ce->pte.sideffect() || (ce->pte.paddr() >> 39) & 1) - req->setFlags(req->getFlags() | UNCACHEABLE); + req->setFlags(Request::UNCACHEABLE); DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); return NoFault; } // if matched @@ -607,7 +607,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) (!write || ce->pte.writable())) { req->setPaddr(ce->pte.translate(vaddr)); if (ce->pte.sideffect() || (ce->pte.paddr() >> 39) & 1) - req->setFlags(req->getFlags() | UNCACHEABLE); + req->setFlags(Request::UNCACHEABLE); DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); return NoFault; } // if matched @@ -769,7 +769,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) } if (e->pte.sideffect() || (e->pte.paddr() >> 39) & 1) - req->setFlags(req->getFlags() | UNCACHEABLE); + req->setFlags(Request::UNCACHEABLE); // cache translation date for next translation cacheState = tlbdata; diff --git a/src/arch/x86/intmessage.hh b/src/arch/x86/intmessage.hh index 6a5b3aa30..f5f8519e2 100644 --- a/src/arch/x86/intmessage.hh +++ b/src/arch/x86/intmessage.hh @@ -78,7 +78,7 @@ namespace X86ISA prepIntRequest(const uint8_t id, Addr offset, Addr size) { RequestPtr req = new Request(x86InterruptAddress(id, offset), - size, UNCACHEABLE); + size, Request::UNCACHEABLE); PacketPtr pkt = new Packet(req, MemCmd::MessageReq, Packet::Broadcast); pkt->allocate(); return pkt; diff --git a/src/arch/x86/pagetable_walker.cc b/src/arch/x86/pagetable_walker.cc index e70c16b1d..564a04b38 100644 --- a/src/arch/x86/pagetable_walker.cc +++ b/src/arch/x86/pagetable_walker.cc @@ -298,11 +298,8 @@ Walker::doNext(PacketPtr &read, PacketPtr &write) } PacketPtr oldRead = read; //If we didn't return, we're setting up another read. - uint32_t flags = oldRead->req->getFlags(); - if (uncacheable) - flags |= UNCACHEABLE; - else - flags &= ~UNCACHEABLE; + Request::Flags flags = oldRead->req->getFlags(); + flags.set(Request::UNCACHEABLE, uncacheable); RequestPtr request = new Request(nextRead, oldRead->getSize(), flags); read = new Packet(request, MemCmd::ReadExReq, Packet::Broadcast); @@ -365,8 +362,10 @@ Walker::start(ThreadContext * _tc, Addr vaddr) enableNX = efer.nxe; - RequestPtr request = - new Request(top, size, PHYSICAL | cr3.pcd ? UNCACHEABLE : 0); + Request::Flags flags = Request::PHYSICAL; + if (cr3.pcd) + flags.set(Request::UNCACHEABLE); + RequestPtr request = new Request(top, size, flags); read = new Packet(request, MemCmd::ReadExReq, Packet::Broadcast); read->allocate(); Enums::MemoryMode memMode = sys->getMemoryMode(); diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index 4980c5fe5..6f1c1a03c 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -653,7 +653,7 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) return new GeneralProtection(0); */ // Force the access to be uncacheable. - req->setFlags(req->getFlags() | UNCACHEABLE); + req->setFlags(Request::UNCACHEABLE); req->setPaddr(x86LocalAPICAddress(tc->contextId(), paddr - baseAddr)); } #endif diff --git a/src/cpu/memtest/memtest.cc b/src/cpu/memtest/memtest.cc index 9e5b9d099..3c57f85b7 100644 --- a/src/cpu/memtest/memtest.cc +++ b/src/cpu/memtest/memtest.cc @@ -279,7 +279,7 @@ MemTest::tick() unsigned base = random() % 2; uint64_t data = random(); unsigned access_size = random() % 4; - unsigned cacheable = random() % 100; + bool uncacheable = (random() % 100) < percentUncacheable; //If we aren't doing copies, use id as offset, and do a false sharing //mem tester @@ -290,17 +290,16 @@ MemTest::tick() access_size = 0; Request *req = new Request(); - uint32_t flags = 0; + Request::Flags flags; Addr paddr; - if (cacheable < percentUncacheable) { - flags |= UNCACHEABLE; + if (uncacheable) { + flags.set(Request::UNCACHEABLE); paddr = uncacheAddr + offset; } else { paddr = ((base) ? baseAddr1 : baseAddr2) + offset; } - bool probe = (random() % 100 < percentFunctional) && !(flags & UNCACHEABLE); - //bool probe = false; + bool probe = (random() % 100 < percentFunctional) && !uncacheable; paddr &= ~((1 << access_size) - 1); req->setPhys(paddr, 1 << access_size, flags); -- cgit v1.2.3 From 1adfe5c7f3368c4225ff685ddcd66b6280c7599f Mon Sep 17 00:00:00 2001 From: Clint Smullen Date: Mon, 10 Nov 2008 11:51:18 -0800 Subject: O3CPU: Make the instcount debugging stuff per-cpu. This is to prevent the assertion from firing if you have a large multicore. Also make sure that it's not compiled in when NDEBUG is defined --- src/cpu/base_dyn_inst.hh | 3 --- src/cpu/base_dyn_inst_impl.hh | 22 ++++++++++++++-------- src/cpu/o3/base_dyn_inst.cc | 4 ---- src/cpu/o3/cpu.cc | 3 +++ src/cpu/o3/cpu.hh | 5 +++++ src/cpu/ozone/base_dyn_inst.cc | 4 ---- src/cpu/ozone/cpu.hh | 5 +++++ src/cpu/ozone/cpu_impl.hh | 3 +++ 8 files changed, 30 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index 3520fafaa..f40616e54 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -258,9 +258,6 @@ class BaseDynInst : public FastAlloc, public RefCounted public: - /** Count of total number of dynamic instructions. */ - static int instcount; - #ifdef DEBUG void dumpSNList(); #endif diff --git a/src/cpu/base_dyn_inst_impl.hh b/src/cpu/base_dyn_inst_impl.hh index 66075c60a..4ee7d2f2c 100644 --- a/src/cpu/base_dyn_inst_impl.hh +++ b/src/cpu/base_dyn_inst_impl.hh @@ -168,18 +168,21 @@ BaseDynInst::initVars() // Initialize the fault to be NoFault. fault = NoFault; - ++instcount; +#ifndef NDEBUG + ++cpu->instcount; - if (instcount > 1500) { + if (cpu->instcount > 1500) { #ifdef DEBUG cpu->dumpInsts(); dumpSNList(); #endif - assert(instcount <= 1500); + assert(cpu->instcount <= 1500); } - DPRINTF(DynInst, "DynInst: [sn:%lli] Instruction created. Instcount=%i\n", - seqNum, instcount); + DPRINTF(DynInst, + "DynInst: [sn:%lli] Instruction created. Instcount for %s = %i\n", + seqNum, cpu->name(), cpu->instcount); +#endif #ifdef DEBUG cpu->snList.insert(seqNum); @@ -199,10 +202,13 @@ BaseDynInst::~BaseDynInst() fault = NoFault; - --instcount; +#ifndef NDEBUG + --cpu->instcount; - DPRINTF(DynInst, "DynInst: [sn:%lli] Instruction destroyed. Instcount=%i\n", - seqNum, instcount); + DPRINTF(DynInst, + "DynInst: [sn:%lli] Instruction destroyed. Instcount for %s = %i\n", + seqNum, cpu->name(), cpu->instcount); +#endif #ifdef DEBUG cpu->snList.erase(seqNum); #endif diff --git a/src/cpu/o3/base_dyn_inst.cc b/src/cpu/o3/base_dyn_inst.cc index 3cf89e1b6..510109d8a 100644 --- a/src/cpu/o3/base_dyn_inst.cc +++ b/src/cpu/o3/base_dyn_inst.cc @@ -34,7 +34,3 @@ // Explicit instantiation template class BaseDynInst; - -template <> -int -BaseDynInst::instcount = 0; diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 26c155262..7320d5638 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -159,6 +159,9 @@ FullO3CPU::FullO3CPU(DerivO3CPUParams *params) itb(params->itb), dtb(params->dtb), tickEvent(this), +#ifndef NDEBUG + instcount(0), +#endif removeInstsThisCycle(false), fetch(this, params), decode(this, params), diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index c60c20d55..d24e8c383 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -576,6 +576,11 @@ class FullO3CPU : public BaseO3CPU void dumpInsts(); public: +#ifndef NDEBUG + /** Count of total number of dynamic instructions in flight. */ + int instcount; +#endif + /** List of all the instructions in flight. */ std::list instList; diff --git a/src/cpu/ozone/base_dyn_inst.cc b/src/cpu/ozone/base_dyn_inst.cc index 5a3a69dff..e0570fd16 100644 --- a/src/cpu/ozone/base_dyn_inst.cc +++ b/src/cpu/ozone/base_dyn_inst.cc @@ -33,7 +33,3 @@ // Explicit instantiation template class BaseDynInst; - -template <> -int -BaseDynInst::instcount = 0; diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index cc371ed93..6b5e7282d 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -287,6 +287,11 @@ class OzoneCPU : public BaseCPU // main simulation loop (one cycle) void tick(); +#ifndef NDEBUG + /** Count of total number of dynamic instructions in flight. */ + int instcount; +#endif + std::set snList; std::set lockAddrList; private: diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index 93848c03f..1402f4b72 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -94,6 +94,9 @@ OzoneCPU::OzoneCPU(Params *p) #else : BaseCPU(p), thread(this, 0, p->workload[0], 0), tickEvent(this, p->width), +#endif +#ifndef NDEBUG + instcount(0), #endif comm(5, 5) { -- cgit v1.2.3 From 4e02e7c217a1ee81dc16c378582697dd5a14de47 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 10 Nov 2008 11:51:18 -0800 Subject: python: Fix the reference counting for python events placed on the eventq. We need to add a reference when an object is put on the C++ queue, and remove a reference when the object is removed from the queue. This was not happening before and caused a memory problem. --- src/python/m5/event.py | 2 +- src/python/swig/event.i | 29 +++++++++++++++++++++++++++++ src/python/swig/pyevent.cc | 23 ++++------------------- src/python/swig/pyevent.hh | 3 +++ src/sim/eventq.hh | 6 +++--- 5 files changed, 40 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/python/m5/event.py b/src/python/m5/event.py index 2b43e578e..ce003defb 100644 --- a/src/python/m5/event.py +++ b/src/python/m5/event.py @@ -36,7 +36,7 @@ mainq = internal.event.cvar.mainEventQueue def create(obj, priority=None): if priority is None: priority = internal.event.Event.Default_Pri - return internal.event.PythonEvent(obj, priority) + return PythonEvent(obj, priority) class Event(PythonEvent): def __init__(self, priority=None): diff --git a/src/python/swig/event.i b/src/python/swig/event.i index 10d75d2de..b40e59a4b 100644 --- a/src/python/swig/event.i +++ b/src/python/swig/event.i @@ -41,6 +41,35 @@ #pragma SWIG nowarn=350,351 +%extend EventQueue { + void + schedule(Event *event, Tick when) + { + // Any python event that are scheduled must have their + // internal object's refcount incremented so that the object + // sticks around while it is in the event queue. + PythonEvent *pyevent = dynamic_cast(event); + if (pyevent) + pyevent->incref(); + $self->schedule(event, when); + } + + void + deschedule(Event *event) + { + $self->deschedule(event); + + // Now that we're removing the python object from the event + // queue, we need to decrement its reference count. + PythonEvent *pyevent = dynamic_cast(event); + if (pyevent) + pyevent->decref(); + } +} + +%ignore EventQueue::schedule; +%ignore EventQueue::deschedule; + %import "base/fast_alloc.hh" %import "sim/serialize.hh" diff --git a/src/python/swig/pyevent.cc b/src/python/swig/pyevent.cc index a201e0185..0695ed2d3 100644 --- a/src/python/swig/pyevent.cc +++ b/src/python/swig/pyevent.cc @@ -38,15 +38,10 @@ PythonEvent::PythonEvent(PyObject *obj, Priority priority) { if (object == NULL) panic("Passed in invalid object"); - - Py_INCREF(object); - - setFlags(AutoDelete); } PythonEvent::~PythonEvent() { - Py_DECREF(object); } void @@ -65,6 +60,10 @@ PythonEvent::process() async_event = true; async_exception = true; } + + // Since the object has been removed from the event queue, its + // reference count must be decremented. + Py_DECREF(object); } CountedDrainEvent * @@ -85,17 +84,3 @@ cleanupCountedDrain(Event *counted_drain) assert(event->getCount() == 0); delete event; } - -#if 0 -Event * -create(PyObject *object, Event::Priority priority) -{ - return new PythonEvent(object, priority); -} - -void -destroy(Event *event) -{ - delete event; -} -#endif diff --git a/src/python/swig/pyevent.hh b/src/python/swig/pyevent.hh index 22b562de1..9006a0404 100644 --- a/src/python/swig/pyevent.hh +++ b/src/python/swig/pyevent.hh @@ -43,6 +43,9 @@ class PythonEvent : public Event PythonEvent(PyObject *obj, Event::Priority priority); ~PythonEvent(); + void incref() { Py_INCREF(object); } + void decref() { Py_DECREF(object); } + virtual void process(); }; diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index 2db652b54..281df2dc3 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -299,9 +299,9 @@ class EventQueue : public Serializable virtual const std::string name() const { return objName; } // schedule the given event on this queue - void schedule(Event *ev, Tick when); - void deschedule(Event *ev); - void reschedule(Event *ev, Tick when, bool always = false); + void schedule(Event *event, Tick when); + void deschedule(Event *event); + void reschedule(Event *event, Tick when, bool always = false); Tick nextTick() const { return head->when(); } Event *serviceOne(); -- cgit v1.2.3 From ea70a44c9f18c895f920cc13bcaf7b3d7fa3c74d Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 10 Nov 2008 11:51:18 -0800 Subject: clean: Move some stuff from the hh file to the cc file. --- src/sim/serialize.cc | 18 ++++++++++++++++++ src/sim/serialize.hh | 11 +++++------ 2 files changed, 23 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/sim/serialize.cc b/src/sim/serialize.cc index a4851d3f6..ee9b04236 100644 --- a/src/sim/serialize.cc +++ b/src/sim/serialize.cc @@ -394,6 +394,24 @@ Globals::unserialize(Checkpoint *cp) mainEventQueue.unserialize(cp, "MainEventQueue"); } +Serializable::Serializable() +{ +} + +Serializable::~Serializable() +{ +} + +void +Serializable::serialize(std::ostream &os) +{ +} + +void +Serializable::unserialize(Checkpoint *cp, const std::string §ion) +{ +} + void Serializable::serializeAll(const std::string &cpt_dir) { diff --git a/src/sim/serialize.hh b/src/sim/serialize.hh index 4c5f399e6..c33633065 100644 --- a/src/sim/serialize.hh +++ b/src/sim/serialize.hh @@ -121,17 +121,16 @@ class Serializable void nameOut(std::ostream &os, const std::string &_name); public: - Serializable() {} - virtual ~Serializable() {} + Serializable(); + virtual ~Serializable(); // manditory virtual function, so objects must provide names virtual const std::string name() const = 0; - virtual void serialize(std::ostream &os) {} - virtual void unserialize(Checkpoint *cp, const std::string §ion) {} + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); - static Serializable *create(Checkpoint *cp, - const std::string §ion); + static Serializable *create(Checkpoint *cp, const std::string §ion); static int ckptCount; static int ckptMaxCount; -- cgit v1.2.3 From c25d966b06061402894b99a2362cb109275b73d1 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 10 Nov 2008 11:51:18 -0800 Subject: Clean up the SimpleTimingPort class a little bit. Move the constructor into the .cc file and get rid of the typedef for SendEvent. --- src/mem/tport.cc | 15 +++++++++++++++ src/mem/tport.hh | 14 ++------------ 2 files changed, 17 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/mem/tport.cc b/src/mem/tport.cc index 0656f6d82..f937eeb32 100644 --- a/src/mem/tport.cc +++ b/src/mem/tport.cc @@ -30,6 +30,21 @@ #include "mem/tport.hh" +using namespace std; + +SimpleTimingPort::SimpleTimingPort(string pname, MemObject *_owner) + : Port(pname, _owner), sendEvent(0), drainEvent(NULL), + waitingOnRetry(false) +{ + sendEvent = new EventWrapper(this); +} + +SimpleTimingPort::~SimpleTimingPort() +{ + delete sendEvent; +} + bool SimpleTimingPort::checkFunctional(PacketPtr pkt) { diff --git a/src/mem/tport.hh b/src/mem/tport.hh index f1cb5317d..7dfe60b72 100644 --- a/src/mem/tport.hh +++ b/src/mem/tport.hh @@ -85,9 +85,6 @@ class SimpleTimingPort : public Port * When the event time expires it attempts to send the packet. * If it cannot, the packet sent when recvRetry() is called. **/ - typedef EventWrapper - SendEvent; - Event *sendEvent; /** If we need to drain, keep the drain event around until we're done @@ -155,15 +152,8 @@ class SimpleTimingPort : public Port public: - - SimpleTimingPort(std::string pname, MemObject *_owner) - : Port(pname, _owner), - sendEvent(new SendEvent(this)), - drainEvent(NULL), - waitingOnRetry(false) - {} - - ~SimpleTimingPort() { delete sendEvent; } + SimpleTimingPort(std::string pname, MemObject *_owner); + ~SimpleTimingPort(); /** Hook for draining timing accesses from the system. The * associated SimObject's drain() functions should be implemented -- cgit v1.2.3 From eb5d9ba72b0309e7f98c382e3a80ce0601dbe084 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 10 Nov 2008 11:51:18 -0800 Subject: pseudo inst: Add rpns (read processor nanoseconds) instruction. This instruction basically returns the number of nanoseconds that the CPU has been running. --- src/arch/alpha/isa/decoder.isa | 3 +++ src/sim/pseudo_inst.cc | 6 ++++++ src/sim/pseudo_inst.hh | 1 + 3 files changed, 10 insertions(+) (limited to 'src') diff --git a/src/arch/alpha/isa/decoder.isa b/src/arch/alpha/isa/decoder.isa index 270940df2..115cf7fa7 100644 --- a/src/arch/alpha/isa/decoder.isa +++ b/src/arch/alpha/isa/decoder.isa @@ -806,6 +806,9 @@ decode OPCODE default Unknown::unknown() { 0x04: quiesceTime({{ R0 = PseudoInst::quiesceTime(xc->tcBase()); }}, IsNonSpeculative, IsUnverifiable); + 0x07: rpns({{ + R0 = PseudoInst::rpns(xc->tcBase()); + }}, IsNonSpeculative, IsUnverifiable); 0x10: deprecated_ivlb({{ warn_once("Obsolete M5 ivlb instruction encountered.\n"); }}); diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index 409a6e009..e43279376 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -125,6 +125,12 @@ quiesceTime(ThreadContext *tc) return (tc->readLastActivate() - tc->readLastSuspend()) / Clock::Int::ns; } +uint64_t +rpns(ThreadContext *tc) +{ + return curTick / Clock::Int::ns; +} + void m5exit(ThreadContext *tc, Tick delay) { diff --git a/src/sim/pseudo_inst.hh b/src/sim/pseudo_inst.hh index 40702fced..80f58f80d 100644 --- a/src/sim/pseudo_inst.hh +++ b/src/sim/pseudo_inst.hh @@ -47,6 +47,7 @@ void quiesce(ThreadContext *tc); void quiesceNs(ThreadContext *tc, uint64_t ns); void quiesceCycles(ThreadContext *tc, uint64_t cycles); uint64_t quiesceTime(ThreadContext *tc); +uint64_t rpns(ThreadContext *tc); void m5exit(ThreadContext *tc, Tick delay); void loadsymbol(ThreadContext *xc); void resetstats(ThreadContext *tc, Tick delay, Tick period); -- cgit v1.2.3 From 4d64d7664c9c9c99a2172785829058a0e751e39f Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 10 Nov 2008 11:51:18 -0800 Subject: SCons: Allow top level directory of EXTRAS able to contain SConscripts. The current EXTRAS will fail if the top level directory pointed to by EXTRAS has a SConscript file in it. We allow this by including the directory name of the EXTRA in the build directory which prevents a clash between src/SConscript and extra/SConscript. Maintain compatibility with older uses of EXTRAS by adding a -I for each top level extra directory. --- src/SConscript | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/SConscript b/src/SConscript index 2ea35b778..2da5830a9 100644 --- a/src/SConscript +++ b/src/SConscript @@ -36,7 +36,7 @@ import re import sys import zlib -from os.path import basename, exists, isdir, isfile, join as joinpath +from os.path import basename, dirname, exists, isdir, isfile, join as joinpath import SCons @@ -214,6 +214,9 @@ Export('CompoundFlag') # files. env.Append(CPPPATH=Dir('.')) +for extra_dir in extras_dir_list: + env.Append(CPPPATH=Dir(extra_dir)) + # Add a flag defining what THE_ISA should be for all compilation env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())]) @@ -222,15 +225,21 @@ env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())]) # Walk the tree and execute all SConscripts in subdirectories # -for base_dir in base_dir_list: - here = Dir('.').srcnode().abspath - for root, dirs, files in os.walk(base_dir, topdown=True): - if root == here: - # we don't want to recurse back into this SConscript - continue +here = Dir('.').srcnode().abspath +for root, dirs, files in os.walk(base_dir, topdown=True): + if root == here: + # we don't want to recurse back into this SConscript + continue + + if 'SConscript' in files: + build_dir = joinpath(env['BUILDDIR'], root[len(base_dir) + 1:]) + SConscript(joinpath(root, 'SConscript'), build_dir=build_dir) +for extra_dir in extras_dir_list: + prefix_len = len(dirname(extra_dir)) + 1 + for root, dirs, files in os.walk(extra_dir, topdown=True): if 'SConscript' in files: - build_dir = joinpath(env['BUILDDIR'], root[len(base_dir) + 1:]) + build_dir = joinpath(env['BUILDDIR'], root[prefix_len:]) SConscript(joinpath(root, 'SConscript'), build_dir=build_dir) for opt in env.ExportOptions: -- cgit v1.2.3 From 7a4d75bae31cfe2064fe0718c7f982f769659b3c Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 13 Nov 2008 23:30:37 -0800 Subject: CPU: Refactor read/write in the simple timing CPU. --- src/cpu/simple/timing.cc | 277 ++++++++++++++++++++--------------------------- src/cpu/simple/timing.hh | 10 +- src/mem/request.hh | 19 ++++ 3 files changed, 138 insertions(+), 168 deletions(-) (limited to 'src') diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 5d37fa620..5da08db47 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -262,6 +262,72 @@ TimingSimpleCPU::handleReadPacket(PacketPtr pkt) return dcache_pkt == NULL; } +Fault +TimingSimpleCPU::buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2, + RequestPtr &req, Addr split_addr, uint8_t *data, bool read) +{ + Fault fault; + RequestPtr req1, req2; + assert(!req->isLocked() && !req->isSwap()); + req->splitOnVaddr(split_addr, req1, req2); + + pkt1 = pkt2 = NULL; + if ((fault = buildPacket(pkt1, req1, read)) != NoFault || + (fault = buildPacket(pkt2, req2, read)) != NoFault) { + delete req; + delete pkt1; + req = NULL; + pkt1 = NULL; + return fault; + } + + assert(!req1->isMmapedIpr() && !req2->isMmapedIpr()); + + req->setPhys(req1->getPaddr(), req->getSize(), req1->getFlags()); + PacketPtr pkt = new Packet(req, pkt1->cmd.responseCommand(), + Packet::Broadcast); + + pkt->dataDynamic(data); + pkt1->dataStatic(data); + pkt2->dataStatic(data + req1->getSize()); + + SplitMainSenderState * main_send_state = new SplitMainSenderState; + pkt->senderState = main_send_state; + main_send_state->fragments[0] = pkt1; + main_send_state->fragments[1] = pkt2; + main_send_state->outstanding = 2; + pkt1->senderState = new SplitFragmentSenderState(pkt, 0); + pkt2->senderState = new SplitFragmentSenderState(pkt, 1); + return fault; +} + +Fault +TimingSimpleCPU::buildPacket(PacketPtr &pkt, RequestPtr &req, bool read) +{ + Fault fault = read ? thread->translateDataReadReq(req) : + thread->translateDataWriteReq(req); + MemCmd cmd; + if (fault != NoFault) { + delete req; + req = NULL; + pkt = NULL; + return fault; + } else if (read) { + cmd = MemCmd::ReadReq; + if (req->isLocked()) + cmd = MemCmd::LoadLockedReq; + } else { + cmd = MemCmd::WriteReq; + if (req->isLocked()) { + cmd = MemCmd::StoreCondReq; + } else if (req->isSwap()) { + cmd = MemCmd::SwapReq; + } + } + pkt = new Packet(req, cmd, Packet::Broadcast); + return NoFault; +} + template Fault TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) @@ -270,91 +336,35 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) const int asid = 0; const int thread_id = 0; const Addr pc = thread->readPC(); - - PacketPtr pkt; - RequestPtr req; - int block_size = dcachePort.peerBlockSize(); int data_size = sizeof(T); - Addr second_addr = roundDown(addr + data_size - 1, block_size); - - if (second_addr > addr) { - Addr first_size = second_addr - addr; - Addr second_size = data_size - first_size; - // Make sure we'll only need two accesses. - assert(roundDown(second_addr + second_size - 1, block_size) == - second_addr); - - /* - * Do the translations. If something isn't going to work, find out - * before we waste time setting up anything else. - */ - req = new Request(asid, addr, first_size, - flags, pc, _cpuId, thread_id); - fault = thread->translateDataReadReq(req); - if (fault != NoFault) { - delete req; - return fault; - } - Request *second_req = - new Request(asid, second_addr, second_size, - flags, pc, _cpuId, thread_id); - fault = thread->translateDataReadReq(second_req); - if (fault != NoFault) { - delete req; - delete second_req; - return fault; - } - - T * data_ptr = new T; - - /* - * This is the big packet that will hold the data we've gotten so far, - * if any, and also act as the response we actually give to the - * instruction. - */ - Request *orig_req = - new Request(asid, addr, data_size, flags, pc, _cpuId, thread_id); - orig_req->setPhys(req->getPaddr(), data_size, flags); - PacketPtr big_pkt = - new Packet(orig_req, MemCmd::ReadResp, Packet::Broadcast); - big_pkt->dataDynamic(data_ptr); - SplitMainSenderState * main_send_state = new SplitMainSenderState; - big_pkt->senderState = main_send_state; - main_send_state->outstanding = 2; - - // This is the packet we'll process now. - pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast); - pkt->dataStatic((uint8_t *)data_ptr); - pkt->senderState = new SplitFragmentSenderState(big_pkt, 0); - - // This is the second half of the access we'll deal with later. - PacketPtr second_pkt = - new Packet(second_req, MemCmd::ReadReq, Packet::Broadcast); - second_pkt->dataStatic((uint8_t *)data_ptr + first_size); - second_pkt->senderState = new SplitFragmentSenderState(big_pkt, 1); - if (!handleReadPacket(pkt)) { - main_send_state->fragments[1] = second_pkt; - } else { - handleReadPacket(second_pkt); + PacketPtr pkt; + RequestPtr req = new Request(asid, addr, data_size, + flags, pc, _cpuId, thread_id); + + Addr split_addr = roundDown(addr + data_size - 1, block_size); + assert(split_addr <= addr || split_addr - addr < block_size); + + if (split_addr > addr) { + PacketPtr pkt1, pkt2; + this->buildSplitPacket(pkt1, pkt2, req, + split_addr, (uint8_t *)(new T), true); + if (handleReadPacket(pkt1)) { + SplitFragmentSenderState * send_state = + dynamic_cast(pkt1->senderState); + send_state->clearFromParent(); + if (handleReadPacket(pkt2)) { + send_state = + dynamic_cast(pkt1->senderState); + send_state->clearFromParent(); + } } } else { - req = new Request(asid, addr, data_size, - flags, pc, _cpuId, thread_id); - - // translate to physical address - Fault fault = thread->translateDataReadReq(req); - + Fault fault = buildPacket(pkt, req, true); if (fault != NoFault) { - delete req; return fault; } - - pkt = new Packet(req, - (req->isLocked() ? - MemCmd::LoadLockedReq : MemCmd::ReadReq), - Packet::Broadcast); pkt->dataDynamic(new T); handleReadPacket(pkt); @@ -468,107 +478,50 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) { const int asid = 0; const int thread_id = 0; - bool do_access = true; // flag to suppress cache access const Addr pc = thread->readPC(); - - RequestPtr req; - int block_size = dcachePort.peerBlockSize(); int data_size = sizeof(T); - Addr second_addr = roundDown(addr + data_size - 1, block_size); + RequestPtr req = new Request(asid, addr, data_size, + flags, pc, _cpuId, thread_id); - if (second_addr > addr) { - Fault fault; - Addr first_size = second_addr - addr; - Addr second_size = data_size - first_size; - // Make sure we'll only need two accesses. - assert(roundDown(second_addr + second_size - 1, block_size) == - second_addr); + Addr split_addr = roundDown(addr + data_size - 1, block_size); + assert(split_addr <= addr || split_addr - addr < block_size); - req = new Request(asid, addr, first_size, - flags, pc, _cpuId, thread_id); - fault = thread->translateDataWriteReq(req); - if (fault != NoFault) { - delete req; - return fault; - } - RequestPtr second_req = new Request(asid, second_addr, second_size, - flags, pc, _cpuId, thread_id); - fault = thread->translateDataWriteReq(second_req); - if (fault != NoFault) { - delete req; - delete second_req; + if (split_addr > addr) { + PacketPtr pkt1, pkt2; + T *dataP = new T; + *dataP = data; + Fault fault = this->buildSplitPacket(pkt1, pkt2, req, split_addr, + (uint8_t *)dataP, false); + if (fault != NoFault) return fault; - } - - if (req->isLocked() || req->isSwap() || - second_req->isLocked() || second_req->isSwap()) { - panic("LL/SCs and swaps can't be split."); - } - - T * data_ptr = new T; - - /* - * This is the big packet that will hold the data we've gotten so far, - * if any, and also act as the response we actually give to the - * instruction. - */ - RequestPtr orig_req = - new Request(asid, addr, data_size, flags, pc, _cpuId, thread_id); - orig_req->setPhys(req->getPaddr(), data_size, flags); - PacketPtr big_pkt = - new Packet(orig_req, MemCmd::WriteResp, Packet::Broadcast); - big_pkt->dataDynamic(data_ptr); - big_pkt->set(data); - SplitMainSenderState * main_send_state = new SplitMainSenderState; - big_pkt->senderState = main_send_state; - main_send_state->outstanding = 2; - - assert(dcache_pkt == NULL); - // This is the packet we'll process now. - dcache_pkt = new Packet(req, MemCmd::WriteReq, Packet::Broadcast); - dcache_pkt->dataStatic((uint8_t *)data_ptr); - dcache_pkt->senderState = new SplitFragmentSenderState(big_pkt, 0); - - // This is the second half of the access we'll deal with later. - PacketPtr second_pkt = - new Packet(second_req, MemCmd::WriteReq, Packet::Broadcast); - second_pkt->dataStatic((uint8_t *)data_ptr + first_size); - second_pkt->senderState = new SplitFragmentSenderState(big_pkt, 1); - if (!handleWritePacket()) { - main_send_state->fragments[1] = second_pkt; - } else { - dcache_pkt = second_pkt; - handleWritePacket(); + dcache_pkt = pkt1; + if (handleWritePacket()) { + SplitFragmentSenderState * send_state = + dynamic_cast(pkt1->senderState); + send_state->clearFromParent(); + dcache_pkt = pkt2; + if (handleReadPacket(pkt2)) { + send_state = + dynamic_cast(pkt1->senderState); + send_state->clearFromParent(); + } } } else { - req = new Request(asid, addr, data_size, flags, pc, _cpuId, thread_id); + bool do_access = true; // flag to suppress cache access - // translate to physical address - Fault fault = thread->translateDataWriteReq(req); - if (fault != NoFault) { - delete req; + Fault fault = buildPacket(dcache_pkt, req, false); + if (fault != NoFault) return fault; - } - - MemCmd cmd = MemCmd::WriteReq; // default if (req->isLocked()) { - cmd = MemCmd::StoreCondReq; do_access = TheISA::handleLockedWrite(thread, req); - } else if (req->isSwap()) { - cmd = MemCmd::SwapReq; - if (req->isCondSwap()) { - assert(res); - req->setExtraData(*res); - } + } else if (req->isCondSwap()) { + assert(res); + req->setExtraData(*res); } - // Note: need to allocate dcache_pkt even if do_access is - // false, as it's used unconditionally to call completeAcc(). - assert(dcache_pkt == NULL); - dcache_pkt = new Packet(req, cmd, Packet::Broadcast); dcache_pkt->allocate(); if (req->isMmapedIpr()) dcache_pkt->set(htog(data)); diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index b641b1302..c305d0361 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -65,12 +65,6 @@ class TimingSimpleCPU : public BaseSimpleCPU int outstanding; PacketPtr fragments[2]; - SplitMainSenderState() - { - fragments[0] = NULL; - fragments[1] = NULL; - } - int getPendingFragment() { @@ -102,6 +96,10 @@ class TimingSimpleCPU : public BaseSimpleCPU } }; + Fault buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2, RequestPtr &req, + Addr split_addr, uint8_t *data, bool read); + Fault buildPacket(PacketPtr &pkt, RequestPtr &req, bool read); + bool handleReadPacket(PacketPtr pkt); // This function always implicitly uses dcache_pkt. bool handleWritePacket(); diff --git a/src/mem/request.hh b/src/mem/request.hh index c3a523d9b..007c33acf 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -43,6 +43,7 @@ #include "base/fast_alloc.hh" #include "base/flags.hh" +#include "base/misc.hh" #include "sim/host.hh" #include "sim/core.hh" @@ -232,6 +233,24 @@ class Request : public FastAlloc flags.set(VALID_PADDR); } + /** + * Generate two requests as if this request had been split into two + * pieces. The original request can't have been translated already. + */ + void splitOnVaddr(Addr split_addr, RequestPtr &req1, RequestPtr &req2) + { + assert(flags.any(VALID_VADDR)); + assert(flags.none(VALID_PADDR)); + assert(split_addr > vaddr && split_addr < vaddr + size); + req1 = new Request; + *req1 = *this; + req2 = new Request; + *req2 = *this; + req1->size = split_addr - vaddr; + req2->vaddr = split_addr; + req2->size = size - req1->size; + } + /** * Accessor for paddr. */ -- cgit v1.2.3 From 5711282f87afb609c79d657ed6aa8c9259b5b827 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 14 Nov 2008 04:55:30 -0800 Subject: Fix a bunch of bugs I introduced when I changed the flags stuff for packets. I did some of the flags and assertions wrong. Thanks to Brad Beckmann for pointing this out. I should have run the opt regressions instead of the fast. I also screwed up some of the logical functions in the Flags class. --- src/arch/alpha/isa/mem.isa | 2 +- src/arch/mips/isa/formats/util.isa | 2 +- src/base/flags.hh | 8 +++----- src/mem/packet.hh | 33 ++++++++++++++++++--------------- src/mem/request.hh | 4 ++-- 5 files changed, 25 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/isa/mem.isa b/src/arch/alpha/isa/mem.isa index b4e10e849..cd5e117ec 100644 --- a/src/arch/alpha/isa/mem.isa +++ b/src/arch/alpha/isa/mem.isa @@ -678,7 +678,7 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, if mem_flags: mem_flags = [ 'Request::%s' % flag for flag in mem_flags ] - s = '\n\tmemAccessFlags.reset(' + string.join(mem_flags, '|') + ');' + s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';' iop.constructor += s memacc_iop.constructor += s diff --git a/src/arch/mips/isa/formats/util.isa b/src/arch/mips/isa/formats/util.isa index 786a964d4..f729cbf63 100644 --- a/src/arch/mips/isa/formats/util.isa +++ b/src/arch/mips/isa/formats/util.isa @@ -62,7 +62,7 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, if mem_flags: mem_flags = [ 'Request::%s' % flag for flag in mem_flags ] - s = '\n\tmemAccessFlags.reset(' + string.join(mem_flags, '|') + ');' + s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';' iop.constructor += s memacc_iop.constructor += s diff --git a/src/base/flags.hh b/src/base/flags.hh index 7cf6ef9c6..712b65319 100644 --- a/src/base/flags.hh +++ b/src/base/flags.hh @@ -61,16 +61,14 @@ class Flags bool any() const { return _flags; } bool any(Type flags) const { return (_flags & flags); } - bool all() const { return (~_flags); } - bool all(Type flags) const { return (_flags & flags) != flags; } + bool all() const { return !(~_flags); } + bool all(Type flags) const { return (_flags & flags) == flags; } bool none() const { return _flags == 0; } bool none(Type flags) const { return (_flags & flags) == 0; } - bool exact(Type flags) const { return _flags = flags; } void clear() { _flags = 0; } void clear(Type flags) { _flags &= ~flags; } - void reset(Type flags) { _flags = flags;} void set(Type flags) { _flags |= flags; } - void set(Type f, bool val) { _flags = (_flags & f) | (val ? f : 0); } + void set(Type f, bool val) { _flags = (_flags & ~f) | (val ? f : 0); } void update(Type flags, Type mask) { diff --git a/src/mem/packet.hh b/src/mem/packet.hh index 38eb2e92b..b75490168 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -461,9 +461,12 @@ class Packet : public FastAlloc, public Printable * supplied. */ Packet(Request *_req, MemCmd _cmd, NodeID _dest) - : cmd(_cmd), req(_req), data(NULL), addr(_req->paddr), - size(_req->size), dest(_dest), time(curTick), senderState(NULL) + : flags(VALID_DST), cmd(_cmd), req(_req), data(NULL), + addr(_req->paddr), size(_req->size), dest(_dest), time(curTick), + senderState(NULL) { + if (req->flags.any(Request::VALID_PADDR)) + flags.set(VALID_ADDR|VALID_SIZE); } /** @@ -472,10 +475,12 @@ class Packet : public FastAlloc, public Printable * req. this allows for overriding the size/addr of the req. */ Packet(Request *_req, MemCmd _cmd, NodeID _dest, int _blkSize) - : cmd(_cmd), req(_req), data(NULL), + : flags(VALID_DST), cmd(_cmd), req(_req), data(NULL), addr(_req->paddr & ~(_blkSize - 1)), size(_blkSize), dest(_dest), time(curTick), senderState(NULL) { + if (req->flags.any(Request::VALID_PADDR)) + flags.set(VALID_ADDR|VALID_SIZE); } /** @@ -544,13 +549,10 @@ class Packet : public FastAlloc, public Printable assert(isRequest()); origCmd = cmd; cmd = cmd.responseCommand(); - if (flags.any(VALID_SRC)) { - dest = src; - flags.set(VALID_DST); - flags.clear(VALID_SRC); - } else { - flags.clear(VALID_DST); - } + + dest = src; + flags.set(VALID_DST, flags.any(VALID_SRC)); + flags.clear(VALID_SRC); } void @@ -690,7 +692,6 @@ class Packet : public FastAlloc, public Printable if (flags.any(ARRAY_DATA)) delete [] data; else if (flags.any(DYNAMIC_DATA)) - delete data; flags.clear(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA); @@ -702,11 +703,13 @@ class Packet : public FastAlloc, public Printable allocate() { if (data) { - assert(flags.none(STATIC_DATA|DYNAMIC_DATA)); - } else { - flags.set(DYNAMIC_DATA|ARRAY_DATA); - data = new uint8_t[getSize()]; + assert(flags.any(STATIC_DATA|DYNAMIC_DATA)); + return; } + + assert(flags.none(STATIC_DATA|DYNAMIC_DATA)); + flags.set(DYNAMIC_DATA|ARRAY_DATA); + data = new uint8_t[getSize()]; } diff --git a/src/mem/request.hh b/src/mem/request.hh index 007c33acf..c7cadaa03 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -53,6 +53,8 @@ typedef Request* RequestPtr; class Request : public FastAlloc { + friend class Packet; + public: typedef uint32_t FlagsType; typedef ::Flags Flags; @@ -455,8 +457,6 @@ class Request : public FastAlloc return false; } - - friend class Packet; }; #endif // __MEM_REQUEST_HH__ -- cgit v1.2.3 From 640b415688f8942ee61ac26f8bbc538596df00a4 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Fri, 14 Nov 2008 14:14:35 -0800 Subject: Cache: get rid of obsolete Tag methods. I think readData() and writeData() were used for Erik's compression work, but that code is gone, these aren't called anymore, and they don't even really do what their names imply. --- src/mem/cache/tags/fa_lru.hh | 25 ------------------ src/mem/cache/tags/iic.cc | 60 -------------------------------------------- src/mem/cache/tags/iic.hh | 20 +-------------- src/mem/cache/tags/lru.hh | 27 -------------------- 4 files changed, 1 insertion(+), 131 deletions(-) (limited to 'src') diff --git a/src/mem/cache/tags/fa_lru.hh b/src/mem/cache/tags/fa_lru.hh index a740d962f..7925e1870 100644 --- a/src/mem/cache/tags/fa_lru.hh +++ b/src/mem/cache/tags/fa_lru.hh @@ -279,31 +279,6 @@ public: { return (tag); } - - /** - * Read the data out of the internal storage of a cache block. FALRU - * currently doesn't support data storage. - * @param blk The cache block to read. - * @param data The buffer to read the data into. - * @return The data from the cache block. - */ - void readData(FALRUBlk *blk, uint8_t *data) - { - } - - /** - * Write data into the internal storage of a cache block. FALRU - * currently doesn't support data storage. - * @param blk The cache block to be written. - * @param data The data to write. - * @param size The number of bytes to write. - * @param writebacks A list for any writebacks to be performed. May be - * needed when writing to a compressed block. - */ - void writeData(FALRUBlk *blk, uint8_t *data, int size, - PacketList &writebacks) - { - } }; #endif diff --git a/src/mem/cache/tags/iic.cc b/src/mem/cache/tags/iic.cc index 2b34634ab..7bc2543c5 100644 --- a/src/mem/cache/tags/iic.cc +++ b/src/mem/cache/tags/iic.cc @@ -633,66 +633,6 @@ IIC::invalidateBlk(IIC::BlkType *tag_ptr) } } -void -IIC::readData(IICTag *blk, uint8_t *data) -{ - assert(blk->size <= trivialSize || blk->numData > 0); - int data_size = blk->size; - if (data_size > trivialSize) { - for (int i = 0; i < blk->numData; ++i){ - memcpy(data+i*subSize, - &(dataBlks[blk->data_ptr[i]][0]), - (data_size>subSize)?subSize:data_size); - data_size -= subSize; - } - } else { - memcpy(data,blk->trivialData,data_size); - } -} - -void -IIC::writeData(IICTag *blk, uint8_t *write_data, int size, - PacketList & writebacks) -{ - DPRINTF(IIC, "Writing %d bytes to %x\n", size, - blk->tag< blk->numData) { - // need to allocate more data blocks - for (int i = blk->numData; i < num_subs; ++i){ - blk->data_ptr[i] = getFreeDataBlock(writebacks); - dataReferenceCount[blk->data_ptr[i]] += 1; - } - } else if (num_subs < blk->numData){ - // can free data blocks - for (int i=num_subs; i < blk->numData; ++i){ - // decrement reference count and compare to zero - if (--dataReferenceCount[blk->data_ptr[i]] == 0) { - freeDataBlock(blk->data_ptr[i]); - } - } - } - - blk->numData = num_subs; - blk->size = size; - assert(size <= trivialSize || blk->numData > 0); - if (size > trivialSize){ - for (int i = 0; i < blk->numData; ++i){ - memcpy(&dataBlks[blk->data_ptr[i]][0], write_data + i*subSize, - (size>subSize)?subSize:size); - size -= subSize; - } - } else { - memcpy(blk->trivialData,write_data,size); - } -} - - void IIC::cleanupRefs() { diff --git a/src/mem/cache/tags/iic.hh b/src/mem/cache/tags/iic.hh index 984506a93..9e14dc119 100644 --- a/src/mem/cache/tags/iic.hh +++ b/src/mem/cache/tags/iic.hh @@ -439,29 +439,11 @@ class IIC : public BaseTags void insertBlock(Addr addr, BlkType *blk); - /** - * Read the data from the internal storage of the given cache block. - * @param blk The block to read the data from. - * @param data The buffer to read the data into. - * @return The cache block's data. - */ - void readData(IICTag *blk, uint8_t *data); - - /** - * Write the data into the internal storage of the given cache block. - * @param blk The block to write to. - * @param data The data to write. - * @param size The number of bytes to write. - * @param writebacks A list for any writebacks to be performed. May be - * needed when writing to a compressed block. - */ - void writeData(IICTag *blk, uint8_t *data, int size, - PacketList & writebacks); - /** * Called at end of simulation to complete average block reference stats. */ virtual void cleanupRefs(); + private: /** * Return the hash of the address. diff --git a/src/mem/cache/tags/lru.hh b/src/mem/cache/tags/lru.hh index 79af973a0..7b6e95e84 100644 --- a/src/mem/cache/tags/lru.hh +++ b/src/mem/cache/tags/lru.hh @@ -255,33 +255,6 @@ public: return hitLatency; } - /** - * Read the data out of the internal storage of the given cache block. - * @param blk The cache block to read. - * @param data The buffer to read the data into. - * @return The cache block's data. - */ - void readData(LRUBlk *blk, uint8_t *data) - { - std::memcpy(data, blk->data, blk->size); - } - - /** - * Write data into the internal storage of the given cache block. Since in - * LRU does not store data differently this just needs to update the size. - * @param blk The cache block to write. - * @param data The data to write. - * @param size The number of bytes to write. - * @param writebacks A list for any writebacks to be performed. May be - * needed when writing to a compressed block. - */ - void writeData(LRUBlk *blk, uint8_t *data, int size, - PacketList & writebacks) - { - assert(size <= blkSize); - blk->size = size; - } - /** * Called at end of simulation to complete average block reference stats. */ -- cgit v1.2.3 From 4514f565e3dfe1de41bbaec05f3f0074e5299bac Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Sat, 15 Nov 2008 09:30:10 -0800 Subject: syscalls: fix latent brk/obreak bug. Bogus calls to ChunkGenerator with negative size were triggering a new assertion that was added there. Also did a little renaming and cleanup in the process. --- src/arch/alpha/linux/process.cc | 2 +- src/arch/alpha/tru64/process.cc | 2 +- src/arch/mips/linux/process.cc | 4 ++-- src/arch/sparc/linux/syscalls.cc | 4 ++-- src/arch/sparc/solaris/process.cc | 2 +- src/arch/x86/linux/syscalls.cc | 2 +- src/mem/page_table.hh | 10 +++++++++- src/sim/syscall_emul.cc | 18 ++++++++++++------ src/sim/syscall_emul.hh | 6 +++--- 9 files changed, 32 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/linux/process.cc b/src/arch/alpha/linux/process.cc index 9527759ed..efcd6623e 100644 --- a/src/arch/alpha/linux/process.cc +++ b/src/arch/alpha/linux/process.cc @@ -136,7 +136,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = { /* 14 */ SyscallDesc("mknod", unimplementedFunc), /* 15 */ SyscallDesc("chmod", chmodFunc), /* 16 */ SyscallDesc("chown", chownFunc), - /* 17 */ SyscallDesc("brk", obreakFunc), + /* 17 */ SyscallDesc("brk", brkFunc), /* 18 */ SyscallDesc("osf_getfsstat", unimplementedFunc), /* 19 */ SyscallDesc("lseek", lseekFunc), /* 20 */ SyscallDesc("getxpid", getpidPseudoFunc), diff --git a/src/arch/alpha/tru64/process.cc b/src/arch/alpha/tru64/process.cc index 645cc6cf9..b84dfb286 100644 --- a/src/arch/alpha/tru64/process.cc +++ b/src/arch/alpha/tru64/process.cc @@ -215,7 +215,7 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = { /* 14 */ SyscallDesc("mknod", unimplementedFunc), /* 15 */ SyscallDesc("chmod", unimplementedFunc), /* 16 */ SyscallDesc("chown", unimplementedFunc), - /* 17 */ SyscallDesc("obreak", obreakFunc), + /* 17 */ SyscallDesc("obreak", brkFunc), /* 18 */ SyscallDesc("pre_F64_getfsstat", unimplementedFunc), /* 19 */ SyscallDesc("lseek", lseekFunc), /* 20 */ SyscallDesc("getpid", getpidPseudoFunc), diff --git a/src/arch/mips/linux/process.cc b/src/arch/mips/linux/process.cc index 8a13d0f18..56413484b 100644 --- a/src/arch/mips/linux/process.cc +++ b/src/arch/mips/linux/process.cc @@ -138,7 +138,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 14 */ SyscallDesc("mknod", unimplementedFunc), /* 15 */ SyscallDesc("chmod", chmodFunc), /* 16 */ SyscallDesc("lchown", chownFunc), - /* 17 */ SyscallDesc("break", obreakFunc), + /* 17 */ SyscallDesc("break", brkFunc), /* 18 */ SyscallDesc("unused#18", unimplementedFunc), /* 19 */ SyscallDesc("lseek", lseekFunc), /* 20 */ SyscallDesc("getpid", getpidFunc), @@ -166,7 +166,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 42 */ SyscallDesc("pipe", pipePseudoFunc), /* 43 */ SyscallDesc("times", unimplementedFunc), /* 44 */ SyscallDesc("prof", unimplementedFunc), - /* 45 */ SyscallDesc("brk", obreakFunc), + /* 45 */ SyscallDesc("brk", brkFunc), /* 46 */ SyscallDesc("setgid", unimplementedFunc), /* 47 */ SyscallDesc("getgid", getgidFunc), /* 48 */ SyscallDesc("signal", ignoreFunc), diff --git a/src/arch/sparc/linux/syscalls.cc b/src/arch/sparc/linux/syscalls.cc index 2964b3c1a..2845f7bec 100644 --- a/src/arch/sparc/linux/syscalls.cc +++ b/src/arch/sparc/linux/syscalls.cc @@ -106,7 +106,7 @@ SyscallDesc SparcLinuxProcess::syscall32Descs[] = { /* 14 */ SyscallDesc("mknod", unimplementedFunc), /* 15 */ SyscallDesc("chmod", unimplementedFunc), /* 16 */ SyscallDesc("lchown", unimplementedFunc), //32 bit - /* 17 */ SyscallDesc("brk", obreakFunc), + /* 17 */ SyscallDesc("brk", brkFunc), /* 18 */ SyscallDesc("perfctr", unimplementedFunc), //32 bit /* 19 */ SyscallDesc("lseek", lseekFunc), //32 bit /* 20 */ SyscallDesc("getpid", getpidFunc), @@ -409,7 +409,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = { /* 14 */ SyscallDesc("mknod", unimplementedFunc), /* 15 */ SyscallDesc("chmod", chmodFunc), /* 16 */ SyscallDesc("lchown", unimplementedFunc), - /* 17 */ SyscallDesc("brk", obreakFunc), + /* 17 */ SyscallDesc("brk", brkFunc), /* 18 */ SyscallDesc("perfctr", unimplementedFunc), /* 19 */ SyscallDesc("lseek", lseekFunc), /* 20 */ SyscallDesc("getpid", getpidFunc), diff --git a/src/arch/sparc/solaris/process.cc b/src/arch/sparc/solaris/process.cc index e0c3eaa4b..e4f6b23c8 100644 --- a/src/arch/sparc/solaris/process.cc +++ b/src/arch/sparc/solaris/process.cc @@ -80,7 +80,7 @@ SyscallDesc SparcSolarisProcess::syscallDescs[] = { /* 14 */ SyscallDesc("mknod", unimplementedFunc), /* 15 */ SyscallDesc("chmod", chmodFunc), /* 16 */ SyscallDesc("chown", chownFunc), - /* 17 */ SyscallDesc("brk", obreakFunc), + /* 17 */ SyscallDesc("brk", brkFunc), /* 18 */ SyscallDesc("stat", unimplementedFunc), /* 19 */ SyscallDesc("lseek", lseekFunc), /* 20 */ SyscallDesc("getpid", getpidFunc), diff --git a/src/arch/x86/linux/syscalls.cc b/src/arch/x86/linux/syscalls.cc index ae2ac243b..754fb2eaf 100644 --- a/src/arch/x86/linux/syscalls.cc +++ b/src/arch/x86/linux/syscalls.cc @@ -135,7 +135,7 @@ SyscallDesc X86LinuxProcess::syscallDescs[] = { /* 9 */ SyscallDesc("mmap", mmapFunc), /* 10 */ SyscallDesc("mprotect", unimplementedFunc), /* 11 */ SyscallDesc("munmap", munmapFunc), - /* 12 */ SyscallDesc("brk", obreakFunc), + /* 12 */ SyscallDesc("brk", brkFunc), /* 13 */ SyscallDesc("rt_sigaction", unimplementedFunc), /* 14 */ SyscallDesc("rt_sigprocmask", unimplementedFunc), /* 15 */ SyscallDesc("rt_sigreturn", unimplementedFunc), diff --git a/src/mem/page_table.hh b/src/mem/page_table.hh index b8b52174c..6ff0be082 100644 --- a/src/mem/page_table.hh +++ b/src/mem/page_table.hh @@ -91,10 +91,18 @@ class PageTable /** * Translate function * @param vaddr The virtual address. - * @return Physical address from translation. + * @param paddr Physical address from translation. + * @return True if translation exists */ bool translate(Addr vaddr, Addr &paddr); + /** + * Simplified translate function (just check for translation) + * @param vaddr The virtual address. + * @return True if translation exists + */ + bool translate(Addr vaddr) { Addr dummy; return translate(vaddr, dummy); } + /** * Perform a translation on the memory request, fills in paddr * field of req. diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index e0e703815..fb6af0b0c 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -107,21 +107,27 @@ getpagesizeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) SyscallReturn -obreakFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) +brkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { - Addr junk; - // change brk addr to first arg Addr new_brk = tc->getSyscallArg(0); - if (new_brk != 0) { + + // in Linux at least, brk(0) returns the current break value + // (note that the syscall and the glibc function have different behavior) + if (new_brk == 0) + return p->brk_point; + + if (new_brk > p->brk_point) { + // might need to allocate some new pages for (ChunkGenerator gen(p->brk_point, new_brk - p->brk_point, VMPageSize); !gen.done(); gen.next()) { - if (!p->pTable->translate(gen.addr(), junk)) + if (!p->pTable->translate(gen.addr())) p->pTable->allocate(roundDown(gen.addr(), VMPageSize), VMPageSize); } - p->brk_point = new_brk; } + + p->brk_point = new_brk; DPRINTF(SyscallVerbose, "Break Point changed to: %#X\n", p->brk_point); return p->brk_point; } diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index 2e8071196..57403ab27 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -191,9 +191,9 @@ SyscallReturn exitFunc(SyscallDesc *desc, int num, SyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc); -/// Target obreak() handler: set brk address. -SyscallReturn obreakFunc(SyscallDesc *desc, int num, - LiveProcess *p, ThreadContext *tc); +/// Target brk() handler: set brk address. +SyscallReturn brkFunc(SyscallDesc *desc, int num, + LiveProcess *p, ThreadContext *tc); /// Target close() handler. SyscallReturn closeFunc(SyscallDesc *desc, int num, -- cgit v1.2.3 From 3087be945d84031d7d6a9cd45bd90d5767d1b7cc Mon Sep 17 00:00:00 2001 From: Clint Smullen Date: Sat, 15 Nov 2008 23:42:11 -0500 Subject: Output: Include gzstream package to allow automatically-gzipped output The gzstream package provides an ostream-interface for writing gzipped files. The package comes from: http://www.cs.unc.edu/Research/compgeom/gzstream/ And is distributed under the LGPL license. Both the license and version information has been preservered, though all other files in the package have been purged. Minor modifications to the code have been made. The output module detects when a filename ends in .gz and constructs an ogzstream object instead of an ofstream object. This works for both the create(...) and find(...) commands. Additionally, since gzstream objects needs to be closed to ensure proper file termination, I have the output deconstructor deleting all ostream's that it manages on behalf of find(...). At the moment, the only output file that I know this functionality works for is stats, i.e. by specifying "--stats-file=m5stats.txt.gz" on the command line. --- src/base/output.cc | 77 ++++++++++++++++++++++++++++++++++++++---------------- src/base/output.hh | 11 +++++--- 2 files changed, 63 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/base/output.cc b/src/base/output.cc index 5a0f2ea70..ea13e23d4 100644 --- a/src/base/output.cc +++ b/src/base/output.cc @@ -36,6 +36,8 @@ #include +#include + #include "base/misc.hh" #include "base/output.hh" @@ -50,7 +52,45 @@ OutputDirectory::OutputDirectory() {} OutputDirectory::~OutputDirectory() -{} +{ + for (map_t::iterator i = files.begin(); i != files.end(); i++) { + if (i->second) + delete i->second; + } +} + +std::ostream * +OutputDirectory::checkForStdio(const string &name) const +{ + if (name == "cerr" || name == "stderr") + return &cerr; + + if (name == "cout" || name == "stdout") + return &cout; + + return NULL; +} + +ostream * +OutputDirectory::openFile(const string &filename, + ios_base::openmode mode) const +{ + if (filename.find(".gz", filename.length()-3) < filename.length()) { + ogzstream *file = new ogzstream(filename.c_str(), mode); + + if (!file->is_open()) + fatal("Cannot open file %s", filename); + + return file; + } else { + ofstream *file = new ofstream(filename.c_str(), mode); + + if (!file->is_open()) + fatal("Cannot open file %s", filename); + + return file; + } +} void OutputDirectory::setDirectory(const string &d) @@ -66,7 +106,7 @@ OutputDirectory::setDirectory(const string &d) } const string & -OutputDirectory::directory() +OutputDirectory::directory() const { if (dir.empty()) panic("Output directory not set!"); @@ -74,8 +114,8 @@ OutputDirectory::directory() return dir; } -string -OutputDirectory::resolve(const string &name) +inline string +OutputDirectory::resolve(const string &name) const { return (name[0] != '/') ? dir + name : name; } @@ -83,16 +123,14 @@ OutputDirectory::resolve(const string &name) ostream * OutputDirectory::create(const string &name, bool binary) { - if (name == "cerr" || name == "stderr") - return &cerr; - - if (name == "cout" || name == "stdout") - return &cout; + ostream *file = checkForStdio(name); + if (file) + return file; - ofstream *file = new ofstream(resolve(name).c_str(), - ios::trunc | binary ? ios::binary : (ios::openmode)0); - if (!file->is_open()) - fatal("Cannot open file %s", name); + string filename = resolve(name); + ios_base::openmode mode = + ios::trunc | binary ? ios::binary : (ios::openmode)0; + file = openFile(filename, mode); return file; } @@ -100,21 +138,16 @@ OutputDirectory::create(const string &name, bool binary) ostream * OutputDirectory::find(const string &name) { - if (name == "cerr" || name == "stderr") - return &cerr; - - if (name == "cout" || name == "stdout") - return &cout; + ostream *file = checkForStdio(name); + if (file) + return file; string filename = resolve(name); map_t::iterator i = files.find(filename); if (i != files.end()) return (*i).second; - ofstream *file = new ofstream(filename.c_str(), ios::trunc); - if (!file->is_open()) - fatal("Cannot open file %s", filename); - + file = openFile(filename); files[filename] = file; return file; } diff --git a/src/base/output.hh b/src/base/output.hh index b1d1d7e7d..38c63714c 100644 --- a/src/base/output.hh +++ b/src/base/output.hh @@ -31,7 +31,7 @@ #ifndef __BASE_OUTPUT_HH__ #define __BASE_OUTPUT_HH__ -#include +#include #include #include @@ -43,14 +43,19 @@ class OutputDirectory map_t files; std::string dir; - std::string resolve(const std::string &name); + std::string resolve(const std::string &name) const; + + protected: + std::ostream *checkForStdio(const std::string &name) const; + std::ostream *openFile(const std::string &filename, + std::ios_base::openmode mode = std::ios::trunc) const; public: OutputDirectory(); ~OutputDirectory(); void setDirectory(const std::string &dir); - const std::string &directory(); + const std::string &directory() const; std::ostream *create(const std::string &name, bool binary = false); std::ostream *find(const std::string &name); -- cgit v1.2.3 From ce4c9a7c10f9a2f91736592f32dcfeb317f17820 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Mon, 17 Nov 2008 12:41:50 -0800 Subject: Sort trace flags before printing them. --- src/python/m5/main.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/python/m5/main.py b/src/python/m5/main.py index a4324a1d6..e1403203d 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -220,9 +220,11 @@ def main(): done = True print "Base Flags:" + traceflags.baseFlags.sort() print_list(traceflags.baseFlags, indent=4) print print "Compound Flags:" + traceflags.compoundFlags.sort() for flag in traceflags.compoundFlags: if flag == 'All': continue -- cgit v1.2.3 From 041ca19edc7ebd905b3fe3e1b731c0b19a146896 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Thu, 20 Nov 2008 19:08:46 -0800 Subject: Assume files w/o obvious OS are Linux (with warning) instead of giving a fatal error. --- src/sim/process.cc | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/sim/process.cc b/src/sim/process.cc index 50bc5e034..dab374d84 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -655,18 +655,22 @@ LiveProcess::create(LiveProcessParams * params) "executable as a static binary and try again.\n"); #if THE_ISA == ALPHA_ISA + if (objFile->getArch() != ObjectFile::Alpha) + fatal("Object file architecture does not match compiled ISA (Alpha)."); + if (objFile->hasTLS()) fatal("Object file has a TLS section and single threaded TLS is not\n" " currently supported for Alpha! Please recompile your " "executable with \n a non-TLS toolchain.\n"); - if (objFile->getArch() != ObjectFile::Alpha) - fatal("Object file architecture does not match compiled ISA (Alpha)."); switch (objFile->getOpSys()) { case ObjectFile::Tru64: process = new AlphaTru64Process(params, objFile); break; + case ObjectFile::UnknownOpSys: + warn("Unknown operating system; assuming Linux."); + // fall through case ObjectFile::Linux: process = new AlphaLinuxProcess(params, objFile); break; @@ -675,9 +679,13 @@ LiveProcess::create(LiveProcessParams * params) fatal("Unknown/unsupported operating system."); } #elif THE_ISA == SPARC_ISA - if (objFile->getArch() != ObjectFile::SPARC64 && objFile->getArch() != ObjectFile::SPARC32) + if (objFile->getArch() != ObjectFile::SPARC64 && + objFile->getArch() != ObjectFile::SPARC32) fatal("Object file architecture does not match compiled ISA (SPARC)."); switch (objFile->getOpSys()) { + case ObjectFile::UnknownOpSys: + warn("Unknown operating system; assuming Linux."); + // fall through case ObjectFile::Linux: if (objFile->getArch() == ObjectFile::SPARC64) { process = new Sparc64LinuxProcess(params, objFile); @@ -690,6 +698,7 @@ LiveProcess::create(LiveProcessParams * params) case ObjectFile::Solaris: process = new SparcSolarisProcess(params, objFile); break; + default: fatal("Unknown/unsupported operating system."); } @@ -697,9 +706,13 @@ LiveProcess::create(LiveProcessParams * params) if (objFile->getArch() != ObjectFile::X86) fatal("Object file architecture does not match compiled ISA (x86)."); switch (objFile->getOpSys()) { + case ObjectFile::UnknownOpSys: + warn("Unknown operating system; assuming Linux."); + // fall through case ObjectFile::Linux: process = new X86LinuxProcess(params, objFile); break; + default: fatal("Unknown/unsupported operating system."); } @@ -707,6 +720,9 @@ LiveProcess::create(LiveProcessParams * params) if (objFile->getArch() != ObjectFile::Mips) fatal("Object file architecture does not match compiled ISA (MIPS)."); switch (objFile->getOpSys()) { + case ObjectFile::UnknownOpSys: + warn("Unknown operating system; assuming Linux."); + // fall through case ObjectFile::Linux: process = new MipsLinuxProcess(params, objFile); break; @@ -718,6 +734,9 @@ LiveProcess::create(LiveProcessParams * params) if (objFile->getArch() != ObjectFile::Arm) fatal("Object file architecture does not match compiled ISA (ARM)."); switch (objFile->getOpSys()) { + case ObjectFile::UnknownOpSys: + warn("Unknown operating system; assuming Linux."); + // fall through case ObjectFile::Linux: process = new ArmLinuxProcess(params, objFile); break; -- cgit v1.2.3 From 74f10be5266039fc9d2c1be14c551d1bcefed99c Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Wed, 3 Dec 2008 04:57:54 -0800 Subject: cprintf: support a configurable width and precision ("*" in printf) --- src/base/cprintf.cc | 17 +++++++++++++---- src/base/cprintf.hh | 35 ++++++++++++++++++++++++++++++++--- src/base/cprintf_formats.hh | 4 ++++ src/unittest/cprintftest.cc | 9 ++++++++- 4 files changed, 57 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/base/cprintf.cc b/src/base/cprintf.cc index d4ba9ca21..5c11e501c 100644 --- a/src/base/cprintf.cc +++ b/src/base/cprintf.cc @@ -40,7 +40,7 @@ using namespace std; namespace cp { Print::Print(std::ostream &stream, const std::string &format) - : stream(stream), format(format.c_str()), ptr(format.c_str()) + : stream(stream), format(format.c_str()), ptr(format.c_str()), cont(false) { saved_flags = stream.flags(); saved_fill = stream.fill(); @@ -48,7 +48,7 @@ Print::Print(std::ostream &stream, const std::string &format) } Print::Print(std::ostream &stream, const char *format) - : stream(stream), format(format), ptr(format) + : stream(stream), format(format), ptr(format), cont(false) { saved_flags = stream.flags(); saved_fill = stream.fill(); @@ -60,8 +60,10 @@ Print::~Print() } void -Print::process(Format &fmt) +Print::process() { + fmt.clear(); + size_t len; while (*ptr) { @@ -221,8 +223,15 @@ Print::process(Format &fmt) number = number * 10 + (*ptr - '0'); break; + case '*': + if (have_precision) + fmt.get_precision = true; + else + fmt.get_width = true; + break; + case '%': - assert("we shouldn't get here"); + assert(false && "we shouldn't get here"); break; default: diff --git a/src/base/cprintf.hh b/src/base/cprintf.hh index cff73a228..2920e210d 100644 --- a/src/base/cprintf.hh +++ b/src/base/cprintf.hh @@ -51,24 +51,53 @@ struct Print std::ostream &stream; const char *format; const char *ptr; + bool cont; std::ios::fmtflags saved_flags; char saved_fill; int saved_precision; - void process(Format &fmt); + Format fmt; + void process(); public: Print(std::ostream &stream, const std::string &format); Print(std::ostream &stream, const char *format); ~Print(); + int + get_number(int data) + { + return data; + } + + template + int + get_number(const T& data) + { + return 0; + } + template void add_arg(const T &data) { - Format fmt; - process(fmt); + if (!cont) + process(); + + if (fmt.get_width) { + fmt.get_width = false; + cont = true; + fmt.width = get_number(data); + return; + } + + if (fmt.get_precision) { + fmt.get_precision = false; + cont = true; + fmt.precision = get_number(data); + return; + } switch (fmt.format) { case Format::character: diff --git a/src/base/cprintf_formats.hh b/src/base/cprintf_formats.hh index 75157a540..6bf6b2b66 100644 --- a/src/base/cprintf_formats.hh +++ b/src/base/cprintf_formats.hh @@ -50,6 +50,8 @@ struct Format enum { best, fixed, scientific } float_format; int precision; int width; + bool get_precision; + bool get_width; Format() { clear(); } @@ -65,6 +67,8 @@ struct Format format = none; precision = -1; width = 0; + get_precision = false; + get_width = false; } }; diff --git a/src/unittest/cprintftest.cc b/src/unittest/cprintftest.cc index 1438f194b..6722ce6a3 100644 --- a/src/unittest/cprintftest.cc +++ b/src/unittest/cprintftest.cc @@ -167,6 +167,13 @@ main() cprintf("%c %c\n", 'c', 65); - cout << '9'; + cout << '9' << endl; + + cout << endl; + + cprintf("%08.4f\n", 99.99); + cprintf("%0*.*f\n", 8, 4, 99.99); + cprintf("%07.*f\n", 4, 1.234); + cprintf("%#0*x\n", 9, 123412); return 0; } -- cgit v1.2.3 From e2c7618e508c6e5c0cbbd091eabb336f3e259465 Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Thu, 4 Dec 2008 18:03:35 -0500 Subject: This patch pulls out the auxiliary vector struct from individual ISA LiveProcesses to the base LiveProcess definition so anyone can use them. --- src/arch/sparc/process.hh | 20 -------------------- src/arch/x86/process.cc | 9 +++------ src/arch/x86/process.hh | 16 ---------------- src/sim/process.cc | 10 ++++++++++ src/sim/process.hh | 16 ++++++++++++++++ 5 files changed, 29 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/arch/sparc/process.hh b/src/arch/sparc/process.hh index a37760139..95abb93d3 100644 --- a/src/arch/sparc/process.hh +++ b/src/arch/sparc/process.hh @@ -71,26 +71,6 @@ class SparcLiveProcess : public LiveProcess virtual void flushWindows(ThreadContext *tc) = 0; }; -template -struct M5_auxv_t -{ - IntType a_type; - union { - IntType a_val; - IntType a_ptr; - IntType a_fcn; - }; - - M5_auxv_t() - {} - - M5_auxv_t(IntType type, IntType val) - { - a_type = SparcISA::htog(type); - a_val = SparcISA::htog(val); - } -}; - class Sparc32LiveProcess : public SparcLiveProcess { protected: diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index 52933b7f4..8d0cd5038 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -103,11 +103,6 @@ using namespace std; using namespace X86ISA; -M5_64_auxv_t::M5_64_auxv_t(int64_t type, int64_t val) -{ - a_type = X86ISA::htog(type); - a_val = X86ISA::htog(val); -} X86LiveProcess::X86LiveProcess(LiveProcessParams * params, ObjectFile *objFile) @@ -205,7 +200,9 @@ X86LiveProcess::startup() void X86LiveProcess::argsInit(int intSize, int pageSize) { - typedef M5_64_auxv_t auxv_t; + typedef M5_auxv_t auxv_t; + std::vector auxv; + Process::startup(); string filename; diff --git a/src/arch/x86/process.hh b/src/arch/x86/process.hh index 5def9e13d..d034d990e 100644 --- a/src/arch/x86/process.hh +++ b/src/arch/x86/process.hh @@ -64,26 +64,10 @@ namespace X86ISA { - struct M5_64_auxv_t - { - int64_t a_type; - union { - int64_t a_val; - int64_t a_ptr; - int64_t a_fcn; - }; - - M5_64_auxv_t() - {} - - M5_64_auxv_t(int64_t type, int64_t val); - }; class X86LiveProcess : public LiveProcess { protected: - std::vector auxv; - X86LiveProcess(LiveProcessParams * params, ObjectFile *objFile); void startup(); diff --git a/src/sim/process.cc b/src/sim/process.cc index dab374d84..73adc96e3 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -86,6 +86,16 @@ using namespace TheISA; // current number of allocated processes int num_processes = 0; +template +M5_auxv_t::M5_auxv_t(IntType type, IntType val) +{ + a_type = TheISA::htog(type); + a_val = TheISA::htog(val); +} + +template class M5_auxv_t; +template class M5_auxv_t; + Process::Process(ProcessParams * params) : SimObject(params), system(params->system), checkpointRestored(false), max_stack_size(params->max_stack_size) diff --git a/src/sim/process.hh b/src/sim/process.hh index d6ed59ced..996663847 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -61,6 +61,22 @@ namespace TheISA class RemoteGDB; } +template +struct M5_auxv_t +{ + IntType a_type; + union { + IntType a_val; + IntType a_ptr; + IntType a_fcn; + }; + + M5_auxv_t() + {} + + M5_auxv_t(IntType type, IntType val); +}; + class Process : public SimObject { public: -- cgit v1.2.3 From f1430941cf17fc15a8b86eba41f9c856ad9347d8 Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Fri, 5 Dec 2008 12:09:29 -0500 Subject: This brings M5 closer to modernity - the kernel being advertised is newer so it won't die on binaries compiled with newer glibc's, and enables use of TLS-toolchain built binaries for ALPHA_SE by putting auxiliary vectors on the stack. There are some comments in the code to help. Finally, stats changes for ALPHA are from slight perturbations to the initial stack frame, all minimal diffs. --- src/arch/alpha/linux/process.cc | 2 +- src/arch/alpha/process.cc | 118 ++++++++++++++++++++++++++++++++++++++++ src/arch/alpha/process.hh | 5 +- src/base/loader/elf_object.cc | 2 + src/sim/process.cc | 5 -- 5 files changed, 123 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/linux/process.cc b/src/arch/alpha/linux/process.cc index efcd6623e..6684051af 100644 --- a/src/arch/alpha/linux/process.cc +++ b/src/arch/alpha/linux/process.cc @@ -52,7 +52,7 @@ unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, strcpy(name->sysname, "Linux"); strcpy(name->nodename, "m5.eecs.umich.edu"); - strcpy(name->release, "2.4.20"); + strcpy(name->release, "2.6.26"); strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); strcpy(name->machine, "alpha"); diff --git a/src/arch/alpha/process.cc b/src/arch/alpha/process.cc index 28e8df308..3e5851e74 100644 --- a/src/arch/alpha/process.cc +++ b/src/arch/alpha/process.cc @@ -32,8 +32,11 @@ #include "arch/alpha/isa_traits.hh" #include "arch/alpha/process.hh" #include "base/loader/object_file.hh" +#include "base/loader/elf_object.hh" #include "base/misc.hh" #include "cpu/thread_context.hh" +#include "mem/page_table.hh" +#include "sim/process_impl.hh" #include "sim/system.hh" using namespace AlphaISA; @@ -57,6 +60,119 @@ AlphaLiveProcess::AlphaLiveProcess(LiveProcessParams *params, // Set pointer for next thread stack. Reserve 8M for main stack. next_thread_stack_base = stack_base - (8 * 1024 * 1024); +} + +void +AlphaLiveProcess::argsInit(int intSize, int pageSize) +{ + objFile->loadSections(initVirtMem); + + typedef M5_auxv_t auxv_t; + std::vector auxv; + + ElfObject * elfObject = dynamic_cast(objFile); + if(elfObject) + { + // modern glibc uses a bunch of auxiliary vectors to set up + // TLS as well as do a bunch of other stuff + // these vectors go on the bottom of the stack, below argc/argv/envp + // pointers but above actual arg strings + // I don't have all the ones glibc looks at here, but so far it doesn't + // seem to be a problem. + // check out _dl_aux_init() in glibc/elf/dl-support.c for details + // --Lisa + auxv.push_back(auxv_t(M5_AT_PAGESZ, AlphaISA::VMPageSize)); + auxv.push_back(auxv_t(M5_AT_CLKTCK, 100)); + auxv.push_back(auxv_t(M5_AT_PHDR, elfObject->programHeaderTable())); + DPRINTF(Loader, "auxv at PHDR %08p\n", elfObject->programHeaderTable()); + auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount())); + auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint())); + auxv.push_back(auxv_t(M5_AT_UID, uid())); + auxv.push_back(auxv_t(M5_AT_EUID, euid())); + auxv.push_back(auxv_t(M5_AT_GID, gid())); + auxv.push_back(auxv_t(M5_AT_EGID, egid())); + + } + + // Calculate how much space we need for arg & env & auxv arrays. + int argv_array_size = intSize * (argv.size() + 1); + int envp_array_size = intSize * (envp.size() + 1); + int auxv_array_size = intSize * 2 * (auxv.size() + 1); + + int arg_data_size = 0; + for (int i = 0; i < argv.size(); ++i) { + arg_data_size += argv[i].size() + 1; + } + int env_data_size = 0; + for (int i = 0; i < envp.size(); ++i) { + env_data_size += envp[i].size() + 1; + } + + int space_needed = + argv_array_size + + envp_array_size + + auxv_array_size + + arg_data_size + + env_data_size; + + if (space_needed < 32*1024) + space_needed = 32*1024; + + // set bottom of stack + stack_min = stack_base - space_needed; + // align it + stack_min = roundDown(stack_min, pageSize); + stack_size = stack_base - stack_min; + // map memory + pTable->allocate(stack_min, roundUp(stack_size, pageSize)); + + // map out initial stack contents + Addr argv_array_base = stack_min + intSize; // room for argc + Addr envp_array_base = argv_array_base + argv_array_size; + Addr auxv_array_base = envp_array_base + envp_array_size; + Addr arg_data_base = auxv_array_base + auxv_array_size; + Addr env_data_base = arg_data_base + arg_data_size; + + // write contents to stack + uint64_t argc = argv.size(); + if (intSize == 8) + argc = htog((uint64_t)argc); + else if (intSize == 4) + argc = htog((uint32_t)argc); + else + panic("Unknown int size"); + + initVirtMem->writeBlob(stack_min, (uint8_t*)&argc, intSize); + + copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem); + copyStringArray(envp, envp_array_base, env_data_base, initVirtMem); + + //Copy the aux stuff + for(int x = 0; x < auxv.size(); x++) + { + initVirtMem->writeBlob(auxv_array_base + x * 2 * intSize, + (uint8_t*)&(auxv[x].a_type), intSize); + initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize, + (uint8_t*)&(auxv[x].a_val), intSize); + } + + assert(NumArgumentRegs >= 2); + + ThreadContext *tc = system->getThreadContext(contextIds[0]); + + tc->setIntReg(ArgumentReg[0], argc); + tc->setIntReg(ArgumentReg[1], argv_array_base); + tc->setIntReg(StackPointerReg, stack_min); + + Addr prog_entry = objFile->entryPoint(); + tc->setPC(prog_entry); + tc->setNextPC(prog_entry + sizeof(MachInst)); + +#if THE_ISA != ALPHA_ISA //e.g. MIPS or Sparc + tc->setNextNPC(prog_entry + (2 * sizeof(MachInst))); +#endif + + } void @@ -65,6 +181,8 @@ AlphaLiveProcess::startup() if (checkpointRestored) return; + Process::startup(); + argsInit(MachineBytes, VMPageSize); ThreadContext *tc = system->getThreadContext(contextIds[0]); diff --git a/src/arch/alpha/process.hh b/src/arch/alpha/process.hh index 0aeeb25db..65c4624ae 100644 --- a/src/arch/alpha/process.hh +++ b/src/arch/alpha/process.hh @@ -34,15 +34,14 @@ #include "sim/process.hh" -class ObjectFile; -class System; - class AlphaLiveProcess : public LiveProcess { protected: AlphaLiveProcess(LiveProcessParams *params, ObjectFile *objFile); void startup(); + + void argsInit(int intSize, int pageSize); }; #endif // __ARCH_ALPHA_PROCESS_HH__ diff --git a/src/base/loader/elf_object.cc b/src/base/loader/elf_object.cc index f71c4456b..edaf323c7 100644 --- a/src/base/loader/elf_object.cc +++ b/src/base/loader/elf_object.cc @@ -291,6 +291,8 @@ ElfObject::ElfObject(const string &_filename, int _fd, data.size = phdr.p_filesz; data.fileImage = fileData + phdr.p_offset; } else { + // If it's none of the above but is loadable, + // load the filesize worth of data Segment extra; extra.baseAddr = phdr.p_paddr; extra.size = phdr.p_filesz; diff --git a/src/sim/process.cc b/src/sim/process.cc index 73adc96e3..244fb9297 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -668,11 +668,6 @@ LiveProcess::create(LiveProcessParams * params) if (objFile->getArch() != ObjectFile::Alpha) fatal("Object file architecture does not match compiled ISA (Alpha)."); - if (objFile->hasTLS()) - fatal("Object file has a TLS section and single threaded TLS is not\n" - " currently supported for Alpha! Please recompile your " - "executable with \n a non-TLS toolchain.\n"); - switch (objFile->getOpSys()) { case ObjectFile::Tru64: process = new AlphaTru64Process(params, objFile); -- cgit v1.2.3 From aab595a3062d59388fed76f03c38eaf1e137a099 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Fri, 5 Dec 2008 13:58:21 -0500 Subject: INet: Allow updating on id, len, seq, and flag field for TCP segment offload --- src/base/inet.hh | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/base/inet.hh b/src/base/inet.hh index e88c0f75f..21ac5c89e 100644 --- a/src/base/inet.hh +++ b/src/base/inet.hh @@ -162,6 +162,9 @@ struct IpHdr : public ip_hdr uint32_t dst() const { return ntohl(ip_dst); } void sum(uint16_t sum) { ip_sum = sum; } + void id(uint16_t _id) { ip_id = htons(_id); } + void len(uint16_t _len) { ip_len = htons(_len); } + bool options(std::vector &vec) const; @@ -260,6 +263,8 @@ struct TcpHdr : public tcp_hdr uint16_t urp() const { return ntohs(th_urp); } void sum(uint16_t sum) { th_sum = sum; } + void seq(uint32_t _seq) { th_seq = htonl(_seq); } + void flags(uint8_t _flags) { th_flags = _flags; } bool options(std::vector &vec) const; @@ -348,6 +353,7 @@ struct UdpHdr : public udp_hdr uint16_t sum() const { return uh_sum; } void sum(uint16_t sum) { uh_sum = sum; } + void len(uint16_t _len) { uh_ulen = htons(_len); } int size() const { return sizeof(udp_hdr); } const uint8_t *bytes() const { return (const uint8_t *)this; } -- cgit v1.2.3 From 400e5162619f3a63c2ac3f7698af89a677829295 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Fri, 5 Dec 2008 13:58:21 -0500 Subject: IGbE: Add support for TCP segment offload --- src/dev/i8254xGBe.cc | 252 ++++++++++++++++++++++++++++++++++++++++------ src/dev/i8254xGBe.hh | 25 ++++- src/dev/i8254xGBe_defs.hh | 1 + 3 files changed, 242 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/dev/i8254xGBe.cc b/src/dev/i8254xGBe.cc index 0fbda1897..8493feb0d 100644 --- a/src/dev/i8254xGBe.cc +++ b/src/dev/i8254xGBe.cc @@ -883,45 +883,128 @@ IGbE::RxDescCache::unserialize(Checkpoint *cp, const std::string §ion) IGbE::TxDescCache::TxDescCache(IGbE *i, const std::string n, int s) : DescCache(i,n, s), pktDone(false), isTcp(false), pktWaiting(false), - pktEvent(this) + useTso(false), pktEvent(this), headerEvent(this) { } -int -IGbE::TxDescCache::getPacketSize() +void +IGbE::TxDescCache::processContextDesc() { assert(unusedCache.size()); - TxDesc *desc; + + DPRINTF(EthernetDesc, "Checking and processing context descriptors\n"); - DPRINTF(EthernetDesc, "Starting processing of descriptor\n"); - - while (unusedCache.size() && TxdOp::isContext(unusedCache.front())) { - DPRINTF(EthernetDesc, "Got context descriptor type... skipping\n"); + while (!useTso && unusedCache.size() && TxdOp::isContext(unusedCache.front())) { + DPRINTF(EthernetDesc, "Got context descriptor type...\n"); - // I think we can just ignore these for now? desc = unusedCache.front(); - DPRINTF(EthernetDesc, "Descriptor upper: %#x lower: %#X\n", desc->d1, - desc->d2); + DPRINTF(EthernetDesc, "Descriptor upper: %#x lower: %#X\n", + desc->d1, desc->d2); + + // is this going to be a tcp or udp packet? isTcp = TxdOp::tcp(desc) ? true : false; - // make sure it's ipv4 - //assert(TxdOp::ip(desc)); + if (TxdOp::tse(desc)) { + DPRINTF(EthernetDesc, "TCP offload enabled for packet hdrlen: %d mss: %d paylen %d\n", + TxdOp::hdrlen(desc), TxdOp::mss(desc), TxdOp::getLen(desc)); + // setup all the TSO variables + useTso = true; + tsoHeaderLen = TxdOp::hdrlen(desc); + tsoMss = TxdOp::mss(desc); + tsoTotalLen = TxdOp::getLen(desc); + tsoLoadedHeader = false; + tsoDescBytesUsed = 0; + tsoUsedLen = 0; + tsoPrevSeq = 0; + tsoPktHasHeader = false; + tsoPkts = 0; + } TxdOp::setDd(desc); unusedCache.pop_front(); usedCache.push_back(desc); } + if (!unusedCache.size()) + return; + + if (useTso && !tsoLoadedHeader) { + // we need to fetch a header + DPRINTF(EthernetDesc, "Starting DMA of TSO header\n"); + desc = unusedCache.front(); + assert(TxdOp::isData(desc) && TxdOp::getLen(desc) >= tsoHeaderLen); + pktWaiting = true; + assert(tsoHeaderLen <= 256); + igbe->dmaRead(igbe->platform->pciToDma(TxdOp::getBuf(desc)), + tsoHeaderLen, &headerEvent, tsoHeader, 0); + } +} + +void +IGbE::TxDescCache::headerComplete() +{ + DPRINTF(EthernetDesc, "TSO: Fetching TSO header complete\n"); + pktWaiting = false; + + assert(unusedCache.size()); + TxDesc *desc = unusedCache.front(); + DPRINTF(EthernetDesc, "TSO: len: %d tsoHeaderLen: %d\n", + TxdOp::getLen(desc), tsoHeaderLen); + + if (TxdOp::getLen(desc) == tsoHeaderLen) { + tsoDescBytesUsed = 0; + tsoLoadedHeader = true; + unusedCache.pop_front(); + usedCache.push_back(desc); + } else { + // I don't think this case happens, I think the headrer is always + // it's own packet, if it wasn't it might be as simple as just + // incrementing descBytesUsed by the header length, but I'm not + // completely sure + panic("TSO header part of bigger packet, not implemented\n"); + } + enableSm(); + igbe->checkDrain(); +} + +int +IGbE::TxDescCache::getPacketSize(EthPacketPtr p) +{ + TxDesc *desc; + + if (!unusedCache.size()) return -1; + + DPRINTF(EthernetDesc, "Starting processing of descriptor\n"); - DPRINTF(EthernetDesc, "Next TX packet is %d bytes\n", - TxdOp::getLen(unusedCache.front())); + assert(!useTso || tsoLoadedHeader); + desc = unusedCache.front(); - return TxdOp::getLen(unusedCache.front()); + + if (useTso) { + DPRINTF(EthernetDesc, "getPacket(): TxDescriptor data d1: %#llx d2: %#llx\n", desc->d1, desc->d2); + DPRINTF(EthernetDesc, "TSO: use: %d hdrlen: %d mss: %d total: %d used: %d loaded hdr: %d\n", + useTso, tsoHeaderLen, tsoMss, tsoTotalLen, tsoUsedLen, tsoLoadedHeader); + DPRINTF(EthernetDesc, "TSO: descBytesUsed: %d copyBytes: %d this descLen: %d\n", + tsoDescBytesUsed, tsoCopyBytes, TxdOp::getLen(desc)); + DPRINTF(EthernetDesc, "TSO: pktHasHeader: %d\n", tsoPktHasHeader); + + if (tsoPktHasHeader) + tsoCopyBytes = std::min((tsoMss + tsoHeaderLen) - p->length, TxdOp::getLen(desc) - tsoDescBytesUsed); + else + tsoCopyBytes = std::min(tsoMss, TxdOp::getLen(desc) - tsoDescBytesUsed); + Addr pkt_size = tsoCopyBytes + (tsoPktHasHeader ? 0 : tsoHeaderLen); + DPRINTF(EthernetDesc, "TSO: Next packet is %d bytes\n", pkt_size); + return pkt_size; + } + + DPRINTF(EthernetDesc, "Next TX packet is %d bytes\n", + TxdOp::getLen(unusedCache.front())); + return TxdOp::getLen(desc); } void @@ -939,10 +1022,29 @@ IGbE::TxDescCache::getPacketData(EthPacketPtr p) pktWaiting = true; DPRINTF(EthernetDesc, "Starting DMA of packet at offset %d\n", p->length); - igbe->dmaRead(igbe->platform->pciToDma(TxdOp::getBuf(desc)), + + if (useTso) { + assert(tsoLoadedHeader); + if (!tsoPktHasHeader) { + DPRINTF(EthernetDesc, "Loading TSO header (%d bytes) into start of packet\n", + tsoHeaderLen); + memcpy(p->data, &tsoHeader,tsoHeaderLen); + p->length +=tsoHeaderLen; + tsoPktHasHeader = true; + } + } + + if (useTso) { + tsoDescBytesUsed += tsoCopyBytes; + assert(tsoDescBytesUsed <= TxdOp::getLen(desc)); + DPRINTF(EthernetDesc, "Starting DMA of packet at offset %d length: %d\n", + p->length, tsoCopyBytes); + igbe->dmaRead(igbe->platform->pciToDma(TxdOp::getBuf(desc)) + tsoDescBytesUsed, + tsoCopyBytes, &pktEvent, p->data + p->length, igbe->txReadDelay); + } else { + igbe->dmaRead(igbe->platform->pciToDma(TxdOp::getBuf(desc)), TxdOp::getLen(desc), &pktEvent, p->data + p->length, igbe->txReadDelay); - - + } } void @@ -960,11 +1062,27 @@ IGbE::TxDescCache::pktComplete() assert((TxdOp::isLegacy(desc) || TxdOp::isData(desc)) && TxdOp::getLen(desc)); DPRINTF(EthernetDesc, "TxDescriptor data d1: %#llx d2: %#llx\n", desc->d1, desc->d2); + DPRINTF(EthernetDesc, "TSO: use: %d hdrlen: %d mss: %d total: %d used: %d loaded hdr: %d\n", + useTso, tsoHeaderLen, tsoMss, tsoTotalLen, tsoUsedLen, tsoLoadedHeader); - if (!TxdOp::eop(desc)) { + // Set the length of the data in the EtherPacket + if (useTso) { + pktPtr->length += tsoCopyBytes; + tsoUsedLen += tsoCopyBytes; + } else pktPtr->length += TxdOp::getLen(desc); + + DPRINTF(EthernetDesc, "TSO: descBytesUsed: %d copyBytes: %d\n", + tsoDescBytesUsed, tsoCopyBytes); + + + if ((!TxdOp::eop(desc) && !useTso) || + (pktPtr->length < ( tsoMss + tsoHeaderLen) && tsoTotalLen != tsoUsedLen)) { + assert(!useTso || (tsoDescBytesUsed == TxdOp::getLen(desc))); unusedCache.pop_front(); usedCache.push_back(desc); + + tsoDescBytesUsed = 0; pktDone = true; pktWaiting = false; pktMultiDesc = true; @@ -977,25 +1095,47 @@ IGbE::TxDescCache::pktComplete() igbe->checkDrain(); return; } - pktMultiDesc = false; - // Set the length of the data in the EtherPacket - pktPtr->length += TxdOp::getLen(desc); + pktMultiDesc = false; // no support for vlans assert(!TxdOp::vle(desc)); - // we alway report status - assert(TxdOp::rs(desc)); - // we only support single packet descriptors at this point - assert(TxdOp::eop(desc)); + if (!useTso) + assert(TxdOp::eop(desc)); // set that this packet is done - TxdOp::setDd(desc); + if (TxdOp::rs(desc)) + TxdOp::setDd(desc); DPRINTF(EthernetDesc, "TxDescriptor data d1: %#llx d2: %#llx\n", desc->d1, desc->d2); + if (useTso) { + IpPtr ip(pktPtr); + if (ip) { + DPRINTF(EthernetDesc, "TSO: Modifying IP header. Id + %d\n", + tsoPkts); + ip->id(ip->id() + tsoPkts++); + ip->len(pktPtr->length - EthPtr(pktPtr)->size()); + + TcpPtr tcp(ip); + if (tcp) { + DPRINTF(EthernetDesc, "TSO: Modifying TCP header. old seq %d + %d\n", + tcp->seq(), tsoPrevSeq); + tcp->seq(tcp->seq() + tsoPrevSeq); + if (tsoUsedLen != tsoTotalLen) + tcp->flags(tcp->flags() & ~9); // clear fin & psh + } + UdpPtr udp(ip); + if (udp) { + DPRINTF(EthernetDesc, "TSO: Modifying UDP header.\n"); + udp->len(pktPtr->length - EthPtr(pktPtr)->size()); + } + } + tsoPrevSeq = tsoUsedLen; + } + if (DTRACE(EthernetDesc)) { IpPtr ip(pktPtr); if (ip) @@ -1055,14 +1195,23 @@ IGbE::TxDescCache::pktComplete() } + if (!useTso || TxdOp::getLen(desc) == tsoDescBytesUsed) { + DPRINTF(EthernetDesc, "Descriptor Done\n"); + unusedCache.pop_front(); + usedCache.push_back(desc); + tsoDescBytesUsed = 0; + } + + if (useTso && tsoUsedLen == tsoTotalLen) + useTso = false; - unusedCache.pop_front(); - usedCache.push_back(desc); + + DPRINTF(EthernetDesc, "------Packet of %d bytes ready for transmission-------\n", + pktPtr->length); pktDone = true; pktWaiting = false; pktPtr = NULL; - - DPRINTF(EthernetDesc, "Descriptor Done\n"); + tsoPktHasHeader = false; if (igbe->regs.txdctl.wthresh() == 0) { DPRINTF(EthernetDesc, "WTHRESH == 0, writing back descriptor\n"); @@ -1083,6 +1232,22 @@ IGbE::TxDescCache::serialize(std::ostream &os) SERIALIZE_SCALAR(isTcp); SERIALIZE_SCALAR(pktWaiting); SERIALIZE_SCALAR(pktMultiDesc); + + SERIALIZE_SCALAR(useTso); + SERIALIZE_SCALAR(tsoHeaderLen); + SERIALIZE_SCALAR(tsoMss); + SERIALIZE_SCALAR(tsoTotalLen); + SERIALIZE_SCALAR(tsoUsedLen); + SERIALIZE_SCALAR(tsoPrevSeq);; + SERIALIZE_SCALAR(tsoPktPayloadBytes); + SERIALIZE_SCALAR(tsoLoadedHeader); + SERIALIZE_SCALAR(tsoPktHasHeader); + SERIALIZE_ARRAY(tsoHeader, 256); + SERIALIZE_SCALAR(tsoDescBytesUsed); + SERIALIZE_SCALAR(tsoCopyBytes); + SERIALIZE_SCALAR(tsoPkts); + + } void @@ -1093,6 +1258,20 @@ IGbE::TxDescCache::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(isTcp); UNSERIALIZE_SCALAR(pktWaiting); UNSERIALIZE_SCALAR(pktMultiDesc); + + UNSERIALIZE_SCALAR(useTso); + UNSERIALIZE_SCALAR(tsoHeaderLen); + UNSERIALIZE_SCALAR(tsoMss); + UNSERIALIZE_SCALAR(tsoTotalLen); + UNSERIALIZE_SCALAR(tsoUsedLen); + UNSERIALIZE_SCALAR(tsoPrevSeq);; + UNSERIALIZE_SCALAR(tsoPktPayloadBytes); + UNSERIALIZE_SCALAR(tsoLoadedHeader); + UNSERIALIZE_SCALAR(tsoPktHasHeader); + UNSERIALIZE_ARRAY(tsoHeader, 256); + UNSERIALIZE_SCALAR(tsoDescBytesUsed); + UNSERIALIZE_SCALAR(tsoCopyBytes); + UNSERIALIZE_SCALAR(tsoPkts); } bool @@ -1242,8 +1421,15 @@ IGbE::txStateMachine() } + txDescCache.processContextDesc(); + if (txDescCache.packetWaiting()) { + DPRINTF(EthernetSM, "TXS: Fetching TSO header, stopping ticking\n"); + txTick = false; + return; + } + int size; - size = txDescCache.getPacketSize(); + size = txDescCache.getPacketSize(txPacket); if (size > 0 && txFifo.avail() > size) { DPRINTF(EthernetSM, "TXS: Reserving %d bytes in FIFO and begining " "DMA of next packet\n", size); diff --git a/src/dev/i8254xGBe.hh b/src/dev/i8254xGBe.hh index 618145d07..473174bcb 100644 --- a/src/dev/i8254xGBe.hh +++ b/src/dev/i8254xGBe.hh @@ -462,8 +462,8 @@ class IGbE : public EtherDevice int descLeft() const { int left = unusedCache.size(); - if (cachePnt - descTail() >= 0) - left += (cachePnt - descTail()); + if (cachePnt >= descTail()) + left += (descLen() - cachePnt + descTail()); else left += (descTail() - cachePnt); @@ -636,6 +636,21 @@ class IGbE : public EtherDevice bool pktWaiting; bool pktMultiDesc; + // tso variables + bool useTso; + Addr tsoHeaderLen; + Addr tsoMss; + Addr tsoTotalLen; + Addr tsoUsedLen; + Addr tsoPrevSeq;; + Addr tsoPktPayloadBytes; + bool tsoLoadedHeader; + bool tsoPktHasHeader; + uint8_t tsoHeader[256]; + Addr tsoDescBytesUsed; + Addr tsoCopyBytes; + int tsoPkts; + public: TxDescCache(IGbE *i, std::string n, int s); @@ -643,8 +658,9 @@ class IGbE : public EtherDevice * return the size the of the packet to reserve space in tx fifo. * @return size of the packet */ - int getPacketSize(); + int getPacketSize(EthPacketPtr p); void getPacketData(EthPacketPtr p); + void processContextDesc(); /** Ask if the packet has been transfered so the state machine can give * it to the fifo. @@ -670,6 +686,9 @@ class IGbE : public EtherDevice void pktComplete(); EventWrapper pktEvent; + void headerComplete(); + EventWrapper headerEvent; + virtual bool hasOutstandingEvents(); virtual void serialize(std::ostream &os); diff --git a/src/dev/i8254xGBe_defs.hh b/src/dev/i8254xGBe_defs.hh index 91b3eacc9..8d9996ef0 100644 --- a/src/dev/i8254xGBe_defs.hh +++ b/src/dev/i8254xGBe_defs.hh @@ -200,6 +200,7 @@ int ipcso(TxDesc *d) { assert(isContext(d)); return bits(d->d1,15,8); } int ipcss(TxDesc *d) { assert(isContext(d)); return bits(d->d1,7,0); } int mss(TxDesc *d) { assert(isContext(d)); return bits(d->d2,63,48); } int hdrlen(TxDesc *d) { assert(isContext(d)); return bits(d->d2,47,40); } +int utcmd(TxDesc *d) { assert(isContext(d)); return bits(d->d2,24,31); } } // namespace TxdOp -- cgit v1.2.3 From dd788a23c972ec45248ad42e58eaa5141160cff9 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Fri, 5 Dec 2008 13:58:22 -0500 Subject: IGbE: Add support for newer 8257x based Intel NICs --- src/dev/Ethernet.py | 16 ++- src/dev/SConscript | 2 +- src/dev/i8254xGBe.cc | 246 ++++++++++++++++++++++++++++++++++++++++------ src/dev/i8254xGBe.hh | 28 +++++- src/dev/i8254xGBe_defs.hh | 226 +++++++++++++++++++++++++++++++++++++----- 5 files changed, 458 insertions(+), 60 deletions(-) (limited to 'src') diff --git a/src/dev/Ethernet.py b/src/dev/Ethernet.py index 5821a3e96..670f48eac 100644 --- a/src/dev/Ethernet.py +++ b/src/dev/Ethernet.py @@ -67,7 +67,9 @@ class EtherDevice(PciDevice): interface = Port("Ethernet Interrface") class IGbE(EtherDevice): + # Base class for two IGbE adapters listed above type = 'IGbE' + #abstract = True hardware_address = Param.EthernetAddr(NextEthernetAddr, "Ethernet Hardware Address") use_flow_control = Param.Bool(False, @@ -80,7 +82,6 @@ class IGbE(EtherDevice): "Number of enteries in the rx descriptor cache") clock = Param.Clock('500MHz', "Clock speed of the device") VendorID = 0x8086 - DeviceID = 0x1075 SubsystemID = 0x1008 SubsystemVendorID = 0x8086 Status = 0x0000 @@ -104,7 +105,20 @@ class IGbE(EtherDevice): wb_comp_delay = Param.Latency('10ns', "delay after desc wb occurs") tx_read_delay = Param.Latency('0ns', "delay after tx dma read") rx_write_delay = Param.Latency('0ns', "delay after rx dma read") + is8257 = Param.Bool("Select between and 8254x and 8257x device") + + +class IGbE_e1000(IGbE): + # Older Intel 8254x based gigabit ethernet adapter + # Uses Intel e1000 driver + DeviceID = 0x1075 + is8257 = False +class IGbE_igb(IGbE): + # Newer Intel 8257x based gigabit ethernet adapter + # Uses Intel igb driver and in theory supports packet splitting and LRO + DeviceID = 0x10C9 + is8257 = True class EtherDevBase(EtherDevice): type = 'EtherDevBase' diff --git a/src/dev/SConscript b/src/dev/SConscript index 54148b68b..2071600ba 100644 --- a/src/dev/SConscript +++ b/src/dev/SConscript @@ -98,7 +98,7 @@ if env['FULL_SYSTEM']: CompoundFlag('DiskImageAll', [ 'DiskImageRead', 'DiskImageWrite' ]) CompoundFlag('EthernetAll', [ 'Ethernet', 'EthernetPIO', 'EthernetDMA', 'EthernetData' , 'EthernetDesc', 'EthernetIntr', 'EthernetSM', - 'EthernetCksum' ]) + 'EthernetCksum', 'EthernetEEPROM' ]) CompoundFlag('EthernetNoData', [ 'Ethernet', 'EthernetPIO', 'EthernetDesc', 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ]) CompoundFlag('IdeAll', [ 'IdeCtrl', 'IdeDisk' ]) diff --git a/src/dev/i8254xGBe.cc b/src/dev/i8254xGBe.cc index 8493feb0d..2a7ba0b31 100644 --- a/src/dev/i8254xGBe.cc +++ b/src/dev/i8254xGBe.cc @@ -85,6 +85,9 @@ IGbE::IGbE(const Params *p) regs.rxdctl.gran(1); regs.rxdctl.wthresh(1); regs.fcrth(1); + regs.tdwba = 0; + regs.rlpml = 0; + regs.sw_fw_sync = 0; regs.pba.rxa(0x30); regs.pba.txa(0x10); @@ -197,6 +200,11 @@ IGbE::read(PacketPtr pkt) regs.imr &= ~regs.iam; chkInterrupt(); break; + case REG_EICR: + // This is only useful for MSI, but the driver reads it every time + // Just don't do anything + pkt->set(0); + break; case REG_ITR: pkt->set(regs.itr()); break; @@ -231,6 +239,9 @@ IGbE::read(PacketPtr pkt) case REG_RDLEN: pkt->set(regs.rdlen()); break; + case REG_SRRCTL: + pkt->set(regs.srrctl()); + break; case REG_RDH: pkt->set(regs.rdh()); break; @@ -246,6 +257,9 @@ IGbE::read(PacketPtr pkt) regs.rdtr.fpd(0); } break; + case REG_RXDCTL: + pkt->set(regs.rxdctl()); + break; case REG_RADV: pkt->set(regs.radv()); break; @@ -261,6 +275,9 @@ IGbE::read(PacketPtr pkt) case REG_TDH: pkt->set(regs.tdh()); break; + case REG_TXDCA_CTL: + pkt->set(regs.txdca_ctl()); + break; case REG_TDT: pkt->set(regs.tdt()); break; @@ -273,12 +290,34 @@ IGbE::read(PacketPtr pkt) case REG_TADV: pkt->set(regs.tadv()); break; + case REG_TDWBAL: + pkt->set(regs.tdwba & mask(32)); + break; + case REG_TDWBAH: + pkt->set(regs.tdwba >> 32); + break; case REG_RXCSUM: pkt->set(regs.rxcsum()); break; + case REG_RLPML: + pkt->set(regs.rlpml); + break; + case REG_RFCTL: + pkt->set(regs.rfctl()); + break; case REG_MANC: pkt->set(regs.manc()); break; + case REG_SWSM: + pkt->set(regs.swsm()); + regs.swsm.smbi(1); + break; + case REG_FWSM: + pkt->set(regs.fwsm()); + break; + case REG_SWFWSYNC: + pkt->set(regs.sw_fw_sync); + break; default: if (!(daddr >= REG_VFTA && daddr < (REG_VFTA + VLAN_FILTER_TABLE_SIZE*4)) && !(daddr >= REG_RAL && daddr < (REG_RAL + RCV_ADDRESS_TABLE_SIZE*8)) && @@ -385,6 +424,14 @@ IGbE::write(PacketPtr pkt) break; case REG_EERD: regs.eerd = val; + if (regs.eerd.start()) { + regs.eerd.done(1); + assert(regs.eerd.addr() < EEPROM_SIZE); + regs.eerd.data(flash[regs.eerd.addr()]); + regs.eerd.start(0); + DPRINTF(EthernetEEPROM, "EEPROM: read addr: %#X data %#x\n", + regs.eerd.addr(), regs.eerd.data()); + } break; case REG_MDIC: regs.mdic = val; @@ -399,10 +446,16 @@ IGbE::write(PacketPtr pkt) regs.mdic.data(0x796D); // link up break; case PHY_PID: - regs.mdic.data(0x02A8); + if (params()->is8257) + regs.mdic.data(0x0141); + else + regs.mdic.data(0x02A8); break; case PHY_EPID: - regs.mdic.data(0x0380); + if (params()->is8257) + regs.mdic.data(0x0CC0); + else + regs.mdic.data(0x0380); break; case PHY_GSTATUS: regs.mdic.data(0x7C00); @@ -485,6 +538,9 @@ IGbE::write(PacketPtr pkt) case REG_TIPG: ; // We don't care, so don't store anything break; + case REG_IVAR0: + warn("Writing to IVAR0, ignoring...\n"); + break; case REG_FCRTL: regs.fcrtl = val; break; @@ -503,6 +559,9 @@ IGbE::write(PacketPtr pkt) regs.rdlen = val & ~mask(7); rxDescCache.areaChanged(); break; + case REG_SRRCTL: + regs.srrctl = val; + break; case REG_RDH: regs.rdh = val; rxDescCache.areaChanged(); @@ -523,6 +582,9 @@ IGbE::write(PacketPtr pkt) case REG_RADV: regs.radv = val; break; + case REG_RXDCTL: + regs.rxdctl = val; + break; case REG_TDBAL: regs.tdba.tdbal( val & ~mask(4)); txDescCache.areaChanged(); @@ -539,6 +601,11 @@ IGbE::write(PacketPtr pkt) regs.tdh = val; txDescCache.areaChanged(); break; + case REG_TXDCA_CTL: + regs.txdca_ctl = val; + if (regs.txdca_ctl.enabled()) + panic("No support for DCA\n"); + break; case REG_TDT: regs.tdt = val; DPRINTF(EthernetSM, "TXS: TX Tail pointer updated\n"); @@ -558,12 +625,38 @@ IGbE::write(PacketPtr pkt) case REG_TADV: regs.tadv = val; break; + case REG_TDWBAL: + regs.tdwba &= ~mask(32); + regs.tdwba |= val; + txDescCache.completionWriteback(regs.tdwba & ~mask(1), regs.tdwba & mask(1)); + break; + case REG_TDWBAH: + regs.tdwba &= mask(32); + regs.tdwba |= (uint64_t)val << 32; + txDescCache.completionWriteback(regs.tdwba & ~mask(1), regs.tdwba & mask(1)); + break; case REG_RXCSUM: regs.rxcsum = val; break; + case REG_RLPML: + regs.rlpml = val; + break; + case REG_RFCTL: + regs.rfctl = val; + if (regs.rfctl.exsten()) + panic("Extended RX descriptors not implemented\n"); + break; case REG_MANC: regs.manc = val; break; + case REG_SWSM: + regs.swsm = val; + if (regs.fwsm.eep_fw_semaphore()) + regs.swsm.swesmbi(0); + break; + case REG_SWFWSYNC: + regs.sw_fw_sync = val; + break; default: if (!(daddr >= REG_VFTA && daddr < (REG_VFTA + VLAN_FILTER_TABLE_SIZE*4)) && !(daddr >= REG_RAL && daddr < (REG_RAL + RCV_ADDRESS_TABLE_SIZE*8)) && @@ -710,19 +803,38 @@ IGbE::RxDescCache::RxDescCache(IGbE *i, const std::string n, int s) void IGbE::RxDescCache::writePacket(EthPacketPtr packet) { - // We shouldn't have to deal with any of these yet - DPRINTF(EthernetDesc, "Packet Length: %d Desc Size: %d\n", - packet->length, igbe->regs.rctl.descSize()); - assert(packet->length < igbe->regs.rctl.descSize()); - - assert(unusedCache.size()); + assert(unusedCache.size()); //if (!unusedCache.size()) // return false; pktPtr = packet; pktDone = false; - igbe->dmaWrite(igbe->platform->pciToDma(unusedCache.front()->buf), - packet->length, &pktEvent, packet->data, igbe->rxWriteDelay); + + Addr buf; + RxDesc *desc = unusedCache.front(); + switch (igbe->regs.srrctl.desctype()) { + case RXDT_LEGACY: + buf = desc->legacy.buf; + DPRINTF(EthernetDesc, "Packet Length: %d Desc Size: %d\n", + packet->length, igbe->regs.rctl.descSize()); + assert(packet->length < igbe->regs.rctl.descSize()); + break; + case RXDT_ADV_ONEBUF: + int buf_len; + buf_len = igbe->regs.rctl.lpe() ? igbe->regs.srrctl.bufLen() : + igbe->regs.rctl.descSize(); + DPRINTF(EthernetDesc, "Packet Length: %d srrctl: %#x Desc Size: %d\n", + packet->length, igbe->regs.srrctl(), buf_len); + assert(packet->length < buf_len); + buf = desc->adv_read.pkt; + break; + default: + panic("Unimplemnted RX receive buffer type: %d\n", + igbe->regs.srrctl.desctype()); + } + + igbe->dmaWrite(igbe->platform->pciToDma(buf), packet->length, &pktEvent, + packet->data, igbe->rxWriteDelay); } void @@ -733,7 +845,6 @@ IGbE::RxDescCache::pktComplete() desc = unusedCache.front(); uint16_t crcfixup = igbe->regs.rctl.secrc() ? 0 : 4 ; - desc->len = htole((uint16_t)(pktPtr->length + crcfixup)); DPRINTF(EthernetDesc, "pktPtr->length: %d stripcrc offset: %d value written: %d %d\n", pktPtr->length, crcfixup, htole((uint16_t)(pktPtr->length + crcfixup)), @@ -744,21 +855,28 @@ IGbE::RxDescCache::pktComplete() DPRINTF(EthernetDesc, "Packet written to memory updating Descriptor\n"); - uint8_t status = RXDS_DD | RXDS_EOP; + uint16_t status = RXDS_DD | RXDS_EOP; uint8_t err = 0; + uint16_t ext_err = 0; + uint16_t csum = 0; + uint16_t ptype = 0; + uint16_t ip_id = 0; IpPtr ip(pktPtr); if (ip) { DPRINTF(EthernetDesc, "Proccesing Ip packet with Id=%d\n", ip->id()); + ptype |= RXDP_IPV4; + ip_id = ip->id(); if (igbe->regs.rxcsum.ipofld()) { DPRINTF(EthernetDesc, "Checking IP checksum\n"); status |= RXDS_IPCS; - desc->csum = htole(cksum(ip)); + csum = htole(cksum(ip)); igbe->rxIpChecksums++; if (cksum(ip) != 0) { err |= RXDE_IPE; + ext_err |= RXDEE_IPE; DPRINTF(EthernetDesc, "Checksum is bad!!\n"); } } @@ -766,11 +884,13 @@ IGbE::RxDescCache::pktComplete() if (tcp && igbe->regs.rxcsum.tuofld()) { DPRINTF(EthernetDesc, "Checking TCP checksum\n"); status |= RXDS_TCPCS; - desc->csum = htole(cksum(tcp)); + ptype |= RXDP_TCP; + csum = htole(cksum(tcp)); igbe->rxTcpChecksums++; if (cksum(tcp) != 0) { DPRINTF(EthernetDesc, "Checksum is bad!!\n"); err |= RXDE_TCPE; + ext_err |= RXDEE_TCPE; } } @@ -778,10 +898,12 @@ IGbE::RxDescCache::pktComplete() if (udp && igbe->regs.rxcsum.tuofld()) { DPRINTF(EthernetDesc, "Checking UDP checksum\n"); status |= RXDS_UDPCS; - desc->csum = htole(cksum(udp)); + ptype |= RXDP_UDP; + csum = htole(cksum(udp)); igbe->rxUdpChecksums++; if (cksum(udp) != 0) { DPRINTF(EthernetDesc, "Checksum is bad!!\n"); + ext_err |= RXDEE_TCPE; err |= RXDE_TCPE; } } @@ -789,12 +911,38 @@ IGbE::RxDescCache::pktComplete() DPRINTF(EthernetSM, "Proccesing Non-Ip packet\n"); } + switch (igbe->regs.srrctl.desctype()) { + case RXDT_LEGACY: + desc->legacy.len = htole((uint16_t)(pktPtr->length + crcfixup)); + desc->legacy.status = htole(status); + desc->legacy.errors = htole(err); + // No vlan support at this point... just set it to 0 + desc->legacy.vlan = 0; + break; + case RXDT_ADV_ONEBUF: + desc->adv_wb.pkt_len = htole((uint16_t)(pktPtr->length + crcfixup)); + desc->adv_wb.rss_type = htole(0); + desc->adv_wb.pkt_type = htole(ptype); + // no header splititng support yet + desc->adv_wb.header_len = htole(0); + desc->adv_wb.sph = htole(0); + if (igbe->regs.rxcsum.pcsd()) { + // no rss support right now + desc->adv_wb.rss_hash = htole(0); + } else { + desc->adv_wb.id = htole(ip_id); + desc->adv_wb.csum = htole(csum); + } + desc->adv_wb.status = htole(status); + desc->adv_wb.errors = htole(ext_err); + // no vlan support + desc->adv_wb.vlan_tag = htole(0); + break; + default: + panic("Unimplemnted RX receive buffer type %d\n", + igbe->regs.srrctl.desctype()); + } - desc->status = htole(status); - desc->errors = htole(err); - - // No vlan support at this point... just set it to 0 - desc->vlan = 0; // Deal with the rx timer interrupts if (igbe->regs.rdtr.delay()) { @@ -883,7 +1031,7 @@ IGbE::RxDescCache::unserialize(Checkpoint *cp, const std::string §ion) IGbE::TxDescCache::TxDescCache(IGbE *i, const std::string n, int s) : DescCache(i,n, s), pktDone(false), isTcp(false), pktWaiting(false), - useTso(false), pktEvent(this), headerEvent(this) + useTso(false), pktEvent(this), headerEvent(this), nullEvent(this) { } @@ -907,13 +1055,15 @@ IGbE::TxDescCache::processContextDesc() // is this going to be a tcp or udp packet? isTcp = TxdOp::tcp(desc) ? true : false; - if (TxdOp::tse(desc)) { + // setup all the TSO variables, they'll be ignored if we don't use + // tso for this connection + tsoHeaderLen = TxdOp::hdrlen(desc); + tsoMss = TxdOp::mss(desc); + + if (TxdOp::isType(desc, TxdOp::TXD_CNXT) && TxdOp::tse(desc)) { DPRINTF(EthernetDesc, "TCP offload enabled for packet hdrlen: %d mss: %d paylen %d\n", TxdOp::hdrlen(desc), TxdOp::mss(desc), TxdOp::getLen(desc)); - // setup all the TSO variables useTso = true; - tsoHeaderLen = TxdOp::hdrlen(desc); - tsoMss = TxdOp::mss(desc); tsoTotalLen = TxdOp::getLen(desc); tsoLoadedHeader = false; tsoDescBytesUsed = 0; @@ -921,6 +1071,7 @@ IGbE::TxDescCache::processContextDesc() tsoPrevSeq = 0; tsoPktHasHeader = false; tsoPkts = 0; + } TxdOp::setDd(desc); @@ -931,10 +1082,23 @@ IGbE::TxDescCache::processContextDesc() if (!unusedCache.size()) return; + desc = unusedCache.front(); + if (!useTso && TxdOp::isType(desc, TxdOp::TXD_ADVDATA) && TxdOp::tse(desc)) { + DPRINTF(EthernetDesc, "TCP offload(adv) enabled for packet hdrlen: %d mss: %d paylen %d\n", + tsoHeaderLen, tsoMss, TxdOp::getTsoLen(desc)); + useTso = true; + tsoTotalLen = TxdOp::getTsoLen(desc); + tsoLoadedHeader = false; + tsoDescBytesUsed = 0; + tsoUsedLen = 0; + tsoPrevSeq = 0; + tsoPktHasHeader = false; + tsoPkts = 0; + } + if (useTso && !tsoLoadedHeader) { // we need to fetch a header DPRINTF(EthernetDesc, "Starting DMA of TSO header\n"); - desc = unusedCache.front(); assert(TxdOp::isData(desc) && TxdOp::getLen(desc) >= tsoHeaderLen); pktWaiting = true; assert(tsoHeaderLen <= 256); @@ -1015,6 +1179,7 @@ IGbE::TxDescCache::getPacketData(EthPacketPtr p) TxDesc *desc; desc = unusedCache.front(); + DPRINTF(EthernetDesc, "getPacketData(): TxDescriptor data d1: %#llx d2: %#llx\n", desc->d1, desc->d2); assert((TxdOp::isLegacy(desc) || TxdOp::isData(desc)) && TxdOp::getLen(desc)); pktPtr = p; @@ -1216,14 +1381,34 @@ IGbE::TxDescCache::pktComplete() if (igbe->regs.txdctl.wthresh() == 0) { DPRINTF(EthernetDesc, "WTHRESH == 0, writing back descriptor\n"); writeback(0); + } else if (igbe->regs.txdctl.gran() && igbe->regs.txdctl.wthresh() >= + descInBlock(usedCache.size())) { + DPRINTF(EthernetDesc, "used > WTHRESH, writing back descriptor\n"); + writeback((igbe->cacheBlockSize()-1)>>4); } else if (igbe->regs.txdctl.wthresh() >= usedCache.size()) { DPRINTF(EthernetDesc, "used > WTHRESH, writing back descriptor\n"); writeback((igbe->cacheBlockSize()-1)>>4); } + enableSm(); igbe->checkDrain(); } +void +IGbE::TxDescCache::actionAfterWb() +{ + DPRINTF(EthernetDesc, "actionAfterWb() completionEnabled: %d\n", + completionEnabled); + igbe->postInterrupt(iGbReg::IT_TXDW); + if (completionEnabled) { + descEnd = igbe->regs.tdh(); + DPRINTF(EthernetDesc, "Completion writing back value: %d to addr: %#x\n", descEnd, + completionAddress); + igbe->dmaWrite(igbe->platform->pciToDma(mbits(completionAddress, 63, 2)), + sizeof(descEnd), &nullEvent, (uint8_t*)&descEnd, 0); + } +} + void IGbE::TxDescCache::serialize(std::ostream &os) { @@ -1247,7 +1432,9 @@ IGbE::TxDescCache::serialize(std::ostream &os) SERIALIZE_SCALAR(tsoCopyBytes); SERIALIZE_SCALAR(tsoPkts); - + SERIALIZE_SCALAR(completionAddress); + SERIALIZE_SCALAR(completionEnabled); + SERIALIZE_SCALAR(descEnd); } void @@ -1272,6 +1459,10 @@ IGbE::TxDescCache::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(tsoDescBytesUsed); UNSERIALIZE_SCALAR(tsoCopyBytes); UNSERIALIZE_SCALAR(tsoPkts); + + UNSERIALIZE_SCALAR(completionAddress); + UNSERIALIZE_SCALAR(completionEnabled); + UNSERIALIZE_SCALAR(descEnd); } bool @@ -1391,7 +1582,6 @@ IGbE::txStateMachine() } // Only support descriptor granularity - assert(regs.txdctl.gran()); if (regs.txdctl.lwthresh() && txDescCache.descLeft() < (regs.txdctl.lwthresh() * 8)) { DPRINTF(EthernetSM, "TXS: LWTHRESH caused posting of TXDLOW\n"); postInterrupt(IT_TXDLOW); diff --git a/src/dev/i8254xGBe.hh b/src/dev/i8254xGBe.hh index 473174bcb..5e5ab1d21 100644 --- a/src/dev/i8254xGBe.hh +++ b/src/dev/i8254xGBe.hh @@ -183,7 +183,7 @@ class IGbE : public EtherDevice virtual long descLen() const = 0; virtual void updateHead(long h) = 0; virtual void enableSm() = 0; - virtual void intAfterWb() const {} + virtual void actionAfterWb() {} virtual void fetchAfterWb() = 0; std::deque usedCache; @@ -440,7 +440,7 @@ class IGbE : public EtherDevice oldHead, curHead); // If we still have more to wb, call wb now - intAfterWb(); + actionAfterWb(); if (moreToWb) { moreToWb = false; DPRINTF(EthernetDesc, "Writeback has more todo\n"); @@ -625,16 +625,22 @@ class IGbE : public EtherDevice virtual long descLen() const { return igbe->regs.tdlen() >> 4; } virtual void updateHead(long h) { igbe->regs.tdh(h); } virtual void enableSm(); - virtual void intAfterWb() const { igbe->postInterrupt(iGbReg::IT_TXDW); } + virtual void actionAfterWb(); virtual void fetchAfterWb() { if (!igbe->txTick && igbe->getState() == SimObject::Running) fetchDescriptors(); } + + bool pktDone; bool isTcp; bool pktWaiting; bool pktMultiDesc; + Addr completionAddress; + bool completionEnabled; + uint32_t descEnd; + // tso variables bool useTso; @@ -662,6 +668,11 @@ class IGbE : public EtherDevice void getPacketData(EthPacketPtr p); void processContextDesc(); + /** Return the number of dsecriptors in a cache block for threshold + * operations. + */ + int descInBlock(int num_desc) { return num_desc / + igbe->cacheBlockSize() / sizeof(iGbReg::TxDesc); } /** Ask if the packet has been transfered so the state machine can give * it to the fifo. * @return packet available in descriptor cache @@ -689,8 +700,19 @@ class IGbE : public EtherDevice void headerComplete(); EventWrapper headerEvent; + + void completionWriteback(Addr a, bool enabled) { + DPRINTF(EthernetDesc, "Completion writeback Addr: %#x enabled: %d\n", + a, enabled); + completionAddress = a; + completionEnabled = enabled; + } + virtual bool hasOutstandingEvents(); + void nullCallback() { DPRINTF(EthernetDesc, "Completion writeback complete\n"); } + EventWrapper nullEvent; + virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); diff --git a/src/dev/i8254xGBe_defs.hh b/src/dev/i8254xGBe_defs.hh index 8d9996ef0..78492d47e 100644 --- a/src/dev/i8254xGBe_defs.hh +++ b/src/dev/i8254xGBe_defs.hh @@ -59,11 +59,14 @@ const uint32_t REG_FCTTV = 0x00170; const uint32_t REG_TIPG = 0x00410; const uint32_t REG_AIFS = 0x00458; const uint32_t REG_LEDCTL = 0x00e00; +const uint32_t REG_EICR = 0x01580; +const uint32_t REG_IVAR0 = 0x01700; const uint32_t REG_FCRTL = 0x02160; const uint32_t REG_FCRTH = 0x02168; const uint32_t REG_RDBAL = 0x02800; const uint32_t REG_RDBAH = 0x02804; const uint32_t REG_RDLEN = 0x02808; +const uint32_t REG_SRRCTL = 0x0280C; const uint32_t REG_RDH = 0x02810; const uint32_t REG_RDT = 0x02818; const uint32_t REG_RDTR = 0x02820; @@ -74,12 +77,17 @@ const uint32_t REG_TDBAL = 0x03800; const uint32_t REG_TDBAH = 0x03804; const uint32_t REG_TDLEN = 0x03808; const uint32_t REG_TDH = 0x03810; +const uint32_t REG_TXDCA_CTL = 0x03814; const uint32_t REG_TDT = 0x03818; const uint32_t REG_TIDV = 0x03820; const uint32_t REG_TXDCTL = 0x03828; const uint32_t REG_TADV = 0x0382C; +const uint32_t REG_TDWBAL = 0x03838; +const uint32_t REG_TDWBAH = 0x0383C; const uint32_t REG_CRCERRS = 0x04000; const uint32_t REG_RXCSUM = 0x05000; +const uint32_t REG_RLPML = 0x05004; +const uint32_t REG_RFCTL = 0x05008; const uint32_t REG_MTA = 0x05200; const uint32_t REG_RAL = 0x05400; const uint32_t REG_RAH = 0x05404; @@ -87,6 +95,9 @@ const uint32_t REG_VFTA = 0x05600; const uint32_t REG_WUC = 0x05800; const uint32_t REG_MANC = 0x05820; +const uint32_t REG_SWSM = 0x05B50; +const uint32_t REG_FWSM = 0x05B54; +const uint32_t REG_SWFWSYNC = 0x05B5C; const uint8_t EEPROM_READ_OPCODE_SPI = 0x03; const uint8_t EEPROM_RDSR_OPCODE_SPI = 0x05; @@ -94,9 +105,9 @@ const uint8_t EEPROM_SIZE = 64; const uint16_t EEPROM_CSUM = 0xBABA; const uint8_t VLAN_FILTER_TABLE_SIZE = 128; -const uint8_t RCV_ADDRESS_TABLE_SIZE = 16; +const uint8_t RCV_ADDRESS_TABLE_SIZE = 24; const uint8_t MULTICAST_TABLE_SIZE = 128; -const uint32_t STATS_REGS_SIZE = 0x124; +const uint32_t STATS_REGS_SIZE = 0x228; // Registers in that are accessed in the PHY @@ -108,14 +119,17 @@ const uint8_t PHY_EPSTATUS = 15; const uint8_t PHY_AGC = 18; // Receive Descriptor Status Flags -const uint8_t RXDS_PIF = 0x80; -const uint8_t RXDS_IPCS = 0x40; -const uint8_t RXDS_TCPCS = 0x20; -const uint8_t RXDS_UDPCS = 0x10; -const uint8_t RXDS_VP = 0x08; -const uint8_t RXDS_IXSM = 0x04; -const uint8_t RXDS_EOP = 0x02; -const uint8_t RXDS_DD = 0x01; +const uint16_t RXDS_DYNINT = 0x800; +const uint16_t RXDS_UDPV = 0x400; +const uint16_t RXDS_CRCV = 0x100; +const uint16_t RXDS_PIF = 0x080; +const uint16_t RXDS_IPCS = 0x040; +const uint16_t RXDS_TCPCS = 0x020; +const uint16_t RXDS_UDPCS = 0x010; +const uint16_t RXDS_VP = 0x008; +const uint16_t RXDS_IXSM = 0x004; +const uint16_t RXDS_EOP = 0x002; +const uint16_t RXDS_DD = 0x001; // Receive Descriptor Error Flags const uint8_t RXDE_RXE = 0x80; @@ -125,6 +139,32 @@ const uint8_t RXDE_SEQ = 0x04; const uint8_t RXDE_SE = 0x02; const uint8_t RXDE_CE = 0x01; +// Receive Descriptor Extended Error Flags +const uint16_t RXDEE_HBO = 0x008; +const uint16_t RXDEE_CE = 0x010; +const uint16_t RXDEE_LE = 0x020; +const uint16_t RXDEE_PE = 0x080; +const uint16_t RXDEE_OSE = 0x100; +const uint16_t RXDEE_USE = 0x200; +const uint16_t RXDEE_TCPE = 0x400; +const uint16_t RXDEE_IPE = 0x800; + + +// Receive Descriptor Types +const uint8_t RXDT_LEGACY = 0x00; +const uint8_t RXDT_ADV_ONEBUF = 0x01; +const uint8_t RXDT_ADV_SPLIT_A = 0x05; + +// Receive Descriptor Packet Types +const uint16_t RXDP_IPV4 = 0x001; +const uint16_t RXDP_IPV4E = 0x002; +const uint16_t RXDP_IPV6 = 0x004; +const uint16_t RXDP_IPV6E = 0x008; +const uint16_t RXDP_TCP = 0x010; +const uint16_t RXDP_UDP = 0x020; +const uint16_t RXDP_SCTP = 0x040; +const uint16_t RXDP_NFS = 0x080; + // Interrupt types enum IntTypes { @@ -147,12 +187,38 @@ enum IntTypes // Receive Descriptor struct struct RxDesc { - Addr buf; - uint16_t len; - uint16_t csum; - uint8_t status; - uint8_t errors; - uint16_t vlan; + union { + struct { + Addr buf; + uint16_t len; + uint16_t csum; + uint8_t status; + uint8_t errors; + uint16_t vlan; + } legacy; + struct { + Addr pkt; + Addr hdr; + } adv_read; + struct { + uint16_t rss_type:4; + uint16_t pkt_type:12; + uint16_t __reserved1:5; + uint16_t header_len:10; + uint16_t sph:1; + union { + struct { + uint16_t id; + uint16_t csum; + }; + uint32_t rss_hash; + }; + uint32_t status:20; + uint32_t errors:12; + uint16_t pkt_len; + uint16_t vlan_tag; + } adv_wb ; + }; }; struct TxDesc { @@ -163,24 +229,33 @@ struct TxDesc { namespace TxdOp { const uint8_t TXD_CNXT = 0x0; const uint8_t TXD_DATA = 0x1; +const uint8_t TXD_ADVCNXT = 0x2; +const uint8_t TXD_ADVDATA = 0x3; bool isLegacy(TxDesc *d) { return !bits(d->d2,29,29); } uint8_t getType(TxDesc *d) { return bits(d->d2, 23,20); } -bool isContext(TxDesc *d) { return !isLegacy(d) && getType(d) == TXD_CNXT; } -bool isData(TxDesc *d) { return !isLegacy(d) && getType(d) == TXD_DATA; } +bool isType(TxDesc *d, uint8_t type) { return getType(d) == type; } +bool isTypes(TxDesc *d, uint8_t t1, uint8_t t2) { return isType(d, t1) || isType(d, t2); } +bool isAdvDesc(TxDesc *d) { return !isLegacy(d) && isTypes(d, TXD_ADVDATA,TXD_ADVCNXT); } +bool isContext(TxDesc *d) { return !isLegacy(d) && isTypes(d,TXD_CNXT, TXD_ADVCNXT); } +bool isData(TxDesc *d) { return !isLegacy(d) && isTypes(d, TXD_DATA, TXD_ADVDATA); } Addr getBuf(TxDesc *d) { assert(isLegacy(d) || isData(d)); return d->d1; } Addr getLen(TxDesc *d) { if (isLegacy(d)) return bits(d->d2,15,0); else return bits(d->d2, 19,0); } -void setDd(TxDesc *d) -{ - replaceBits(d->d2, 35, 32, ULL(1)); -} +void setDd(TxDesc *d) { replaceBits(d->d2, 35, 32, ULL(1)); } -bool ide(TxDesc *d) { return bits(d->d2, 31,31); } +bool ide(TxDesc *d) { return bits(d->d2, 31,31) && (getType(d) == TXD_DATA || isLegacy(d)); } bool vle(TxDesc *d) { assert(isLegacy(d) || isData(d)); return bits(d->d2, 30,30); } bool rs(TxDesc *d) { return bits(d->d2, 27,27); } bool ic(TxDesc *d) { assert(isLegacy(d) || isData(d)); return isLegacy(d) && bits(d->d2, 26,26); } -bool tse(TxDesc *d) { return (isData(d) || isContext(d)) && bits(d->d2, 26,26); } +bool tse(TxDesc *d) { + if (isTypes(d, TXD_CNXT, TXD_DATA)) + return bits(d->d2, 26,26); + if (isType(d, TXD_ADVDATA)) + return bits(d->d2, 31, 31); + return false; +} + bool ifcs(TxDesc *d) { assert(isLegacy(d) || isData(d)); return bits(d->d2, 25,25); } bool eop(TxDesc *d) { assert(isLegacy(d) || isData(d)); return bits(d->d2, 24,24); } bool ip(TxDesc *d) { assert(isContext(d)); return bits(d->d2, 25,25); } @@ -199,7 +274,14 @@ int ipcse(TxDesc *d) { assert(isContext(d)); return bits(d->d1,31,16); } int ipcso(TxDesc *d) { assert(isContext(d)); return bits(d->d1,15,8); } int ipcss(TxDesc *d) { assert(isContext(d)); return bits(d->d1,7,0); } int mss(TxDesc *d) { assert(isContext(d)); return bits(d->d2,63,48); } -int hdrlen(TxDesc *d) { assert(isContext(d)); return bits(d->d2,47,40); } +int hdrlen(TxDesc *d) { + assert(isContext(d)); + if (!isAdvDesc(d)) + return bits(d->d2,47,40); + return bits(d->d2, 47,40) + bits(d->d1, 8,0) + bits(d->d1, 15, 9); +} + +int getTsoLen(TxDesc *d) { assert(isType(d, TXD_ADVDATA)); return bits(d->d2, 63,46); } int utcmd(TxDesc *d) { assert(isContext(d)); return bits(d->d2,24,31); } } // namespace TxdOp @@ -304,8 +386,8 @@ struct Regs { struct EERD : public Reg { // 0x0014 EERD Register using Reg::operator=; ADD_FIELD32(start,0,1); // start read - ADD_FIELD32(done,4,1); // done read - ADD_FIELD32(addr,8,8); // address + ADD_FIELD32(done,1,1); // done read + ADD_FIELD32(addr,2,14); // address ADD_FIELD32(data,16,16); // data }; EERD eerd; @@ -471,6 +553,17 @@ struct Regs { }; RDLEN rdlen; + struct SRRCTL : public Reg { // 0x280C SRRCTL Register + using Reg::operator=; + ADD_FIELD32(pktlen, 0, 7); + ADD_FIELD32(hdrlen, 16, 7); // guess based on header, not documented + ADD_FIELD32(desctype, 25,3); // type of descriptor 000 legacy, 001 adv, + //101 hdr split + int bufLen() { return pktlen() << 10; } + int hdrLen() { return hdrlen() << 6; } + }; + SRRCTL srrctl; + struct RDH : public Reg { // 0x2810 RDH Register using Reg::operator=; ADD_FIELD32(rdh,0,16); // head of the descriptor ring @@ -532,6 +625,14 @@ struct Regs { }; TDH tdh; + struct TXDCA_CTL : public Reg { // 0x3814 TXDCA_CTL Register + using Reg::operator=; + ADD_FIELD32(cpu_mask, 0, 5); + ADD_FIELD32(enabled, 5,1); + ADD_FIELD32(relax_ordering, 6, 1); + }; + TXDCA_CTL txdca_ctl; + struct TDT : public Reg { // 0x3818 TDT Register using Reg::operator=; ADD_FIELD32(tdt,0,16); // tail of the descriptor ring @@ -564,15 +665,42 @@ struct Regs { ADD_FIELD32(idv,0,16); // absolute interrupt delay }; TADV tadv; +/* + struct TDWBA : public Reg { // 0x3838 TDWBA Register + using Reg::operator=; + ADD_FIELD64(en,0,1); // enable transmit description ring address writeback + ADD_FIELD64(tdwbal,2,32); // base address of transmit descriptor ring address writeback + ADD_FIELD64(tdwbah,32,32); // base address of transmit descriptor ring + }; + TDWBA tdwba;*/ + uint64_t tdwba; struct RXCSUM : public Reg { // 0x5000 RXCSUM Register using Reg::operator=; ADD_FIELD32(pcss,0,8); ADD_FIELD32(ipofld,8,1); ADD_FIELD32(tuofld,9,1); + ADD_FIELD32(pcsd, 13,1); }; RXCSUM rxcsum; + uint32_t rlpml; // 0x5004 RLPML probably maximum accepted packet size + + struct RFCTL : public Reg { // 0x5008 RFCTL Register + using Reg::operator=; + ADD_FIELD32(iscsi_dis,0,1); + ADD_FIELD32(iscsi_dwc,1,5); + ADD_FIELD32(nfsw_dis,6,1); + ADD_FIELD32(nfsr_dis,7,1); + ADD_FIELD32(nfs_ver,8,2); + ADD_FIELD32(ipv6_dis,10,1); + ADD_FIELD32(ipv6xsum_dis,11,1); + ADD_FIELD32(ackdis,13,1); + ADD_FIELD32(ipfrsp_dis,14,1); + ADD_FIELD32(exsten,15,1); + }; + RFCTL rfctl; + struct MANC : public Reg { // 0x5820 MANC Register using Reg::operator=; ADD_FIELD32(smbus,0,1); // SMBus enabled ##### @@ -605,6 +733,32 @@ struct Regs { }; MANC manc; + struct SWSM : public Reg { // 0x5B50 SWSM register + using Reg::operator=; + ADD_FIELD32(smbi,0,1); // Semaphone bit + ADD_FIELD32(swesmbi, 1,1); // Software eeporm semaphore + ADD_FIELD32(wmng, 2,1); // Wake MNG clock + ADD_FIELD32(reserved, 3, 29); + }; + SWSM swsm; + + struct FWSM : public Reg { // 0x5B54 FWSM register + using Reg::operator=; + ADD_FIELD32(eep_fw_semaphore,0,1); + ADD_FIELD32(fw_mode, 1,3); + ADD_FIELD32(ide, 4,1); + ADD_FIELD32(sol, 5,1); + ADD_FIELD32(eep_roload, 6,1); + ADD_FIELD32(reserved, 7,8); + ADD_FIELD32(fw_val_bit, 15, 1); + ADD_FIELD32(reset_cnt, 16, 3); + ADD_FIELD32(ext_err_ind, 19, 6); + ADD_FIELD32(reserved2, 25, 7); + }; + FWSM fwsm; + + uint32_t sw_fw_sync; + void serialize(std::ostream &os) { paramOut(os, "ctrl", ctrl._data); @@ -625,6 +779,7 @@ struct Regs { paramOut(os, "fcrth", fcrth._data); paramOut(os, "rdba", rdba._data); paramOut(os, "rdlen", rdlen._data); + paramOut(os, "srrctl", srrctl._data); paramOut(os, "rdh", rdh._data); paramOut(os, "rdt", rdt._data); paramOut(os, "rdtr", rdtr._data); @@ -634,12 +789,20 @@ struct Regs { paramOut(os, "tdba", tdba._data); paramOut(os, "tdlen", tdlen._data); paramOut(os, "tdh", tdh._data); + paramOut(os, "txdca_ctl", txdca_ctl._data); paramOut(os, "tdt", tdt._data); paramOut(os, "tidv", tidv._data); paramOut(os, "txdctl", txdctl._data); paramOut(os, "tadv", tadv._data); + //paramOut(os, "tdwba", tdwba._data); + SERIALIZE_SCALAR(tdwba); paramOut(os, "rxcsum", rxcsum._data); + SERIALIZE_SCALAR(rlpml); + paramOut(os, "rfctl", rfctl._data); paramOut(os, "manc", manc._data); + paramOut(os, "swsm", swsm._data); + paramOut(os, "fwsm", fwsm._data); + SERIALIZE_SCALAR(sw_fw_sync); } void unserialize(Checkpoint *cp, const std::string §ion) @@ -662,6 +825,7 @@ struct Regs { paramIn(cp, section, "fcrth", fcrth._data); paramIn(cp, section, "rdba", rdba._data); paramIn(cp, section, "rdlen", rdlen._data); + paramIn(cp, section, "srrctl", srrctl._data); paramIn(cp, section, "rdh", rdh._data); paramIn(cp, section, "rdt", rdt._data); paramIn(cp, section, "rdtr", rdtr._data); @@ -671,12 +835,20 @@ struct Regs { paramIn(cp, section, "tdba", tdba._data); paramIn(cp, section, "tdlen", tdlen._data); paramIn(cp, section, "tdh", tdh._data); + paramIn(cp, section, "txdca_ctl", txdca_ctl._data); paramIn(cp, section, "tdt", tdt._data); paramIn(cp, section, "tidv", tidv._data); paramIn(cp, section, "txdctl", txdctl._data); paramIn(cp, section, "tadv", tadv._data); + UNSERIALIZE_SCALAR(tdwba); + //paramIn(cp, section, "tdwba", tdwba._data); paramIn(cp, section, "rxcsum", rxcsum._data); + UNSERIALIZE_SCALAR(rlpml); + paramIn(cp, section, "rfctl", rfctl._data); paramIn(cp, section, "manc", manc._data); + paramIn(cp, section, "swsm", swsm._data); + paramIn(cp, section, "fwsm", fwsm._data); + UNSERIALIZE_SCALAR(sw_fw_sync); } }; } // iGbReg namespace -- cgit v1.2.3 From e141cb7441e79b3596c795faf9f47424f26c65e9 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 6 Dec 2008 14:18:18 -0800 Subject: flags: Change naming of functions to be clearer --- src/arch/alpha/faults.cc | 2 +- src/base/flags.hh | 12 ++++---- src/mem/packet.hh | 42 +++++++++++++------------- src/mem/packet_access.hh | 4 +-- src/mem/request.hh | 76 +++++++++++++++++++++++------------------------- 5 files changed, 67 insertions(+), 69 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/faults.cc b/src/arch/alpha/faults.cc index e89cf5c64..e93e16711 100644 --- a/src/arch/alpha/faults.cc +++ b/src/arch/alpha/faults.cc @@ -144,7 +144,7 @@ DtbFault::invoke(ThreadContext *tc) // read, like the EV5). The EV6 approach is cleaner and seems to // work with EV5 PAL code, but not the other way around. if (!tc->misspeculating() && - reqFlags.none(Request::VPTE|Request::NO_FAULT)) { + reqFlags.noneSet(Request::VPTE|Request::NO_FAULT)) { // set VA register with faulting address tc->setMiscRegNoEffect(IPR_VA, vaddr); diff --git a/src/base/flags.hh b/src/base/flags.hh index 712b65319..2e0506391 100644 --- a/src/base/flags.hh +++ b/src/base/flags.hh @@ -59,12 +59,12 @@ class Flags return *this; } - bool any() const { return _flags; } - bool any(Type flags) const { return (_flags & flags); } - bool all() const { return !(~_flags); } - bool all(Type flags) const { return (_flags & flags) == flags; } - bool none() const { return _flags == 0; } - bool none(Type flags) const { return (_flags & flags) == 0; } + bool isSet() const { return _flags; } + bool isSet(Type flags) const { return (_flags & flags); } + bool allSet() const { return !(~_flags); } + bool allSet(Type flags) const { return (_flags & flags) == flags; } + bool noneSet() const { return _flags == 0; } + bool noneSet(Type flags) const { return (_flags & flags) == 0; } void clear() { _flags = 0; } void clear(Type flags) { _flags &= ~flags; } void set(Type flags) { _flags |= flags; } diff --git a/src/mem/packet.hh b/src/mem/packet.hh index b75490168..41f599fa0 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -407,15 +407,15 @@ class Packet : public FastAlloc, public Printable // Snoop flags void assertMemInhibit() { flags.set(MEM_INHIBIT); } - bool memInhibitAsserted() { return flags.any(MEM_INHIBIT); } + bool memInhibitAsserted() { return flags.isSet(MEM_INHIBIT); } void assertShared() { flags.set(SHARED); } - bool sharedAsserted() { return flags.any(SHARED); } + bool sharedAsserted() { return flags.isSet(SHARED); } // Special control flags void setExpressSnoop() { flags.set(EXPRESS_SNOOP); } - bool isExpressSnoop() { return flags.any(EXPRESS_SNOOP); } + bool isExpressSnoop() { return flags.isSet(EXPRESS_SNOOP); } void setSupplyExclusive() { flags.set(SUPPLY_EXCLUSIVE); } - bool isSupplyExclusive() { return flags.any(SUPPLY_EXCLUSIVE); } + bool isSupplyExclusive() { return flags.isSet(SUPPLY_EXCLUSIVE); } // Network error conditions... encapsulate them as methods since // their encoding keeps changing (from result field to command @@ -439,19 +439,19 @@ class Packet : public FastAlloc, public Printable void copyError(Packet *pkt) { assert(pkt->isError()); cmd = pkt->cmd; } /// Accessor function to get the source index of the packet. - NodeID getSrc() const { assert(flags.any(VALID_SRC)); return src; } + NodeID getSrc() const { assert(flags.isSet(VALID_SRC)); return src; } /// Accessor function to set the source index of the packet. void setSrc(NodeID _src) { src = _src; flags.set(VALID_SRC); } /// Reset source field, e.g. to retransmit packet on different bus. void clearSrc() { flags.clear(VALID_SRC); } /// Accessor function for the destination index of the packet. - NodeID getDest() const { assert(flags.any(VALID_DST)); return dest; } + NodeID getDest() const { assert(flags.isSet(VALID_DST)); return dest; } /// Accessor function to set the destination index of the packet. void setDest(NodeID _dest) { dest = _dest; flags.set(VALID_DST); } - Addr getAddr() const { assert(flags.all(VALID_ADDR)); return addr; } - int getSize() const { assert(flags.all(VALID_SIZE)); return size; } + Addr getAddr() const { assert(flags.isSet(VALID_ADDR)); return addr; } + int getSize() const { assert(flags.isSet(VALID_SIZE)); return size; } Addr getOffset(int blkSize) const { return getAddr() & (Addr)(blkSize - 1); } /** @@ -465,7 +465,7 @@ class Packet : public FastAlloc, public Printable addr(_req->paddr), size(_req->size), dest(_dest), time(curTick), senderState(NULL) { - if (req->flags.any(Request::VALID_PADDR)) + if (req->flags.isSet(Request::VALID_PADDR)) flags.set(VALID_ADDR|VALID_SIZE); } @@ -479,7 +479,7 @@ class Packet : public FastAlloc, public Printable addr(_req->paddr & ~(_blkSize - 1)), size(_blkSize), dest(_dest), time(curTick), senderState(NULL) { - if (req->flags.any(Request::VALID_PADDR)) + if (req->flags.isSet(Request::VALID_PADDR)) flags.set(VALID_ADDR|VALID_SIZE); } @@ -492,7 +492,7 @@ class Packet : public FastAlloc, public Printable */ Packet(Packet *pkt, bool clearFlags = false) : cmd(pkt->cmd), req(pkt->req), - data(pkt->flags.any(STATIC_DATA) ? pkt->data : NULL), + data(pkt->flags.isSet(STATIC_DATA) ? pkt->data : NULL), addr(pkt->addr), size(pkt->size), src(pkt->src), dest(pkt->dest), time(curTick), senderState(pkt->senderState) { @@ -526,7 +526,7 @@ class Packet : public FastAlloc, public Printable void reinitFromRequest() { - assert(req->flags.any(Request::VALID_PADDR)); + assert(req->flags.isSet(Request::VALID_PADDR)); flags = 0; addr = req->paddr; size = req->size; @@ -551,7 +551,7 @@ class Packet : public FastAlloc, public Printable cmd = cmd.responseCommand(); dest = src; - flags.set(VALID_DST, flags.any(VALID_SRC)); + flags.set(VALID_DST, flags.isSet(VALID_SRC)); flags.clear(VALID_SRC); } @@ -590,7 +590,7 @@ class Packet : public FastAlloc, public Printable void dataStatic(T *p) { - assert(flags.none(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA)); + assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA)); data = (PacketDataPtr)p; flags.set(STATIC_DATA); } @@ -603,7 +603,7 @@ class Packet : public FastAlloc, public Printable void dataDynamicArray(T *p) { - assert(flags.none(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA)); + assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA)); data = (PacketDataPtr)p; flags.set(DYNAMIC_DATA|ARRAY_DATA); } @@ -616,7 +616,7 @@ class Packet : public FastAlloc, public Printable void dataDynamic(T *p) { - assert(flags.none(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA)); + assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA)); data = (PacketDataPtr)p; flags.set(DYNAMIC_DATA); } @@ -628,7 +628,7 @@ class Packet : public FastAlloc, public Printable T* getPtr() { - assert(flags.any(STATIC_DATA|DYNAMIC_DATA)); + assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA)); return (T*)data; } @@ -689,9 +689,9 @@ class Packet : public FastAlloc, public Printable void deleteData() { - if (flags.any(ARRAY_DATA)) + if (flags.isSet(ARRAY_DATA)) delete [] data; - else if (flags.any(DYNAMIC_DATA)) + else if (flags.isSet(DYNAMIC_DATA)) delete data; flags.clear(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA); @@ -703,11 +703,11 @@ class Packet : public FastAlloc, public Printable allocate() { if (data) { - assert(flags.any(STATIC_DATA|DYNAMIC_DATA)); + assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA)); return; } - assert(flags.none(STATIC_DATA|DYNAMIC_DATA)); + assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA)); flags.set(DYNAMIC_DATA|ARRAY_DATA); data = new uint8_t[getSize()]; } diff --git a/src/mem/packet_access.hh b/src/mem/packet_access.hh index 1e233ee57..f70d508b2 100644 --- a/src/mem/packet_access.hh +++ b/src/mem/packet_access.hh @@ -46,7 +46,7 @@ template inline T Packet::get() { - assert(flags.any(STATIC_DATA|DYNAMIC_DATA)); + assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA)); assert(sizeof(T) <= size); return TheISA::gtoh(*(T*)data); } @@ -56,7 +56,7 @@ template inline void Packet::set(T v) { - assert(flags.any(STATIC_DATA|DYNAMIC_DATA)); + assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA)); assert(sizeof(T) <= size); *(T*)data = TheISA::htog(v); } diff --git a/src/mem/request.hh b/src/mem/request.hh index c7cadaa03..f60eb17fa 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -230,7 +230,7 @@ class Request : public FastAlloc void setPaddr(Addr _paddr) { - assert(flags.any(VALID_VADDR)); + assert(flags.isSet(VALID_VADDR)); paddr = _paddr; flags.set(VALID_PADDR); } @@ -241,8 +241,8 @@ class Request : public FastAlloc */ void splitOnVaddr(Addr split_addr, RequestPtr &req1, RequestPtr &req2) { - assert(flags.any(VALID_VADDR)); - assert(flags.none(VALID_PADDR)); + assert(flags.isSet(VALID_VADDR)); + assert(flags.noneSet(VALID_PADDR)); assert(split_addr > vaddr && split_addr < vaddr + size); req1 = new Request; *req1 = *this; @@ -259,7 +259,7 @@ class Request : public FastAlloc Addr getPaddr() { - assert(flags.any(VALID_PADDR)); + assert(flags.isSet(VALID_PADDR)); return paddr; } @@ -269,7 +269,7 @@ class Request : public FastAlloc int getSize() { - assert(flags.any(VALID_SIZE)); + assert(flags.isSet(VALID_SIZE)); return size; } @@ -277,64 +277,62 @@ class Request : public FastAlloc Tick getTime() { - assert(flags.any(VALID_PADDR|VALID_VADDR)); + assert(flags.isSet(VALID_PADDR|VALID_VADDR)); return time; } void setTime(Tick when) { - assert(flags.any(VALID_PADDR|VALID_VADDR)); + assert(flags.isSet(VALID_PADDR|VALID_VADDR)); time = when; } - void resetTime() { setTime(curTick); } - /** Accessor for flags. */ Flags getFlags() { - assert(flags.any(VALID_PADDR|VALID_VADDR)); + assert(flags.isSet(VALID_PADDR|VALID_VADDR)); return flags & PUBLIC_FLAGS; } Flags anyFlags(Flags _flags) { - assert(flags.any(VALID_PADDR|VALID_VADDR)); - assert(_flags.none(~PUBLIC_FLAGS)); - return flags.any(_flags); + assert(flags.isSet(VALID_PADDR|VALID_VADDR)); + assert(_flags.noneSet(~PUBLIC_FLAGS)); + return flags.isSet(_flags); } Flags allFlags(Flags _flags) { - assert(flags.any(VALID_PADDR|VALID_VADDR)); - assert(_flags.none(~PUBLIC_FLAGS)); - return flags.all(_flags); + assert(flags.isSet(VALID_PADDR|VALID_VADDR)); + assert(_flags.noneSet(~PUBLIC_FLAGS)); + return flags.allSet(_flags); } /** Accessor for flags. */ void setFlags(Flags _flags) { - assert(flags.any(VALID_PADDR|VALID_VADDR)); - assert(_flags.none(~PUBLIC_FLAGS)); + assert(flags.isSet(VALID_PADDR|VALID_VADDR)); + assert(_flags.noneSet(~PUBLIC_FLAGS)); flags.set(_flags); } void clearFlags(Flags _flags) { - assert(flags.any(VALID_PADDR|VALID_VADDR)); - assert(_flags.none(~PUBLIC_FLAGS)); + assert(flags.isSet(VALID_PADDR|VALID_VADDR)); + assert(_flags.noneSet(~PUBLIC_FLAGS)); flags.clear(_flags); } void clearFlags() { - assert(flags.any(VALID_PADDR|VALID_VADDR)); + assert(flags.isSet(VALID_PADDR|VALID_VADDR)); flags.clear(PUBLIC_FLAGS); } @@ -342,7 +340,7 @@ class Request : public FastAlloc Addr getVaddr() { - assert(flags.any(VALID_VADDR)); + assert(flags.isSet(VALID_VADDR)); return vaddr; } @@ -350,7 +348,7 @@ class Request : public FastAlloc int getAsid() { - assert(flags.any(VALID_VADDR)); + assert(flags.isSet(VALID_VADDR)); return asid; } @@ -358,7 +356,7 @@ class Request : public FastAlloc uint8_t getAsi() { - assert(flags.any(VALID_VADDR)); + assert(flags.isSet(VALID_VADDR)); return flags & ASI_BITS; } @@ -366,7 +364,7 @@ class Request : public FastAlloc void setAsi(uint8_t a) { - assert(flags.any(VALID_VADDR)); + assert(flags.isSet(VALID_VADDR)); flags.update(a, ASI_BITS); } @@ -374,8 +372,8 @@ class Request : public FastAlloc bool isMmapedIpr() { - assert(flags.any(VALID_PADDR)); - return flags.any(MMAPED_IPR); + assert(flags.isSet(VALID_PADDR)); + return flags.isSet(MMAPED_IPR); } /** Accessor function for asi.*/ @@ -390,14 +388,14 @@ class Request : public FastAlloc bool extraDataValid() { - return flags.any(VALID_EXTRA_DATA); + return flags.isSet(VALID_EXTRA_DATA); } /** Accessor function for store conditional return value.*/ uint64_t getExtraData() const { - assert(flags.any(VALID_EXTRA_DATA)); + assert(flags.isSet(VALID_EXTRA_DATA)); return extraData; } @@ -413,7 +411,7 @@ class Request : public FastAlloc int contextId() const { - assert(flags.any(VALID_CONTEXT_ID)); + assert(flags.isSet(VALID_CONTEXT_ID)); return _contextId; } @@ -421,7 +419,7 @@ class Request : public FastAlloc int threadId() const { - assert(flags.any(VALID_THREAD_ID)); + assert(flags.isSet(VALID_THREAD_ID)); return _threadId; } @@ -429,27 +427,27 @@ class Request : public FastAlloc Addr getPC() const { - assert(flags.any(VALID_PC)); + assert(flags.isSet(VALID_PC)); return pc; } /** Accessor Function to Check Cacheability. */ - bool isUncacheable() const { return flags.any(UNCACHEABLE); } - bool isInstRead() const { return flags.any(INST_READ); } - bool isLocked() const { return flags.any(LOCKED); } - bool isSwap() const { return flags.any(MEM_SWAP|MEM_SWAP_COND); } - bool isCondSwap() const { return flags.any(MEM_SWAP_COND); } + bool isUncacheable() const { return flags.isSet(UNCACHEABLE); } + bool isInstRead() const { return flags.isSet(INST_READ); } + bool isLocked() const { return flags.isSet(LOCKED); } + bool isSwap() const { return flags.isSet(MEM_SWAP|MEM_SWAP_COND); } + bool isCondSwap() const { return flags.isSet(MEM_SWAP_COND); } bool isMisaligned() const { - if (flags.any(NO_ALIGN_FAULT)) + if (flags.isSet(NO_ALIGN_FAULT)) return false; if ((vaddr & 0x1)) return true; - if (flags.any(NO_HALF_WORD_ALIGN_FAULT)) + if (flags.isSet(NO_HALF_WORD_ALIGN_FAULT)) return false; if ((vaddr & 0x2)) -- cgit v1.2.3 From e08c6be9feb5d381ca45afc581cf6efb090f0dd7 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 6 Dec 2008 14:18:18 -0800 Subject: SimObject: change naming of vectors so there are the same numbers of digits. i.e. we used to have Foo0, Foo1, ..., Foo10, Foo11, ..., Foo100 now we have Foo000, Foo001, ..., Foo010, Foo011, ..., Foo100 --- src/python/m5/SimObject.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index ac81582f3..868f969a6 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -27,7 +27,9 @@ # Authors: Steve Reinhardt # Nathan Binkert -import sys, types +import math +import sys +import types import proxy import m5 @@ -627,8 +629,9 @@ class SimObject(object): if len(value) == 1: value[0]._maybe_set_parent(self, attr) else: + width = int(math.ceil(math.log(len(value))/math.log(10))) for i,v in enumerate(value): - v._maybe_set_parent(self, "%s%d" % (attr, i)) + v._maybe_set_parent(self, "%s%0*d" % (attr, width, i)) self._values[attr] = value -- cgit v1.2.3 From a0d322be4021891ee21edb4424e4af1957a50d0a Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 6 Dec 2008 14:18:18 -0800 Subject: traceflags: Make "All" a valid trace flag. --- src/python/m5/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/python/m5/main.py b/src/python/m5/main.py index e1403203d..d34cca357 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -310,7 +310,7 @@ def main(): if flag.startswith('-'): flag = flag[1:] off = True - if flag not in traceflags.allFlags: + if flag not in traceflags.allFlags and flag != "All": print >>sys.stderr, "invalid trace flag '%s'" % flag sys.exit(1) -- cgit v1.2.3 From cbbc4501c87c7910ba74ea8d4b53df257c01940d Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 6 Dec 2008 14:18:18 -0800 Subject: eventq: move virtual function definitiions to the .cc file. --- src/sim/eventq.cc | 15 +++++++++++++++ src/sim/eventq.hh | 16 ++-------------- 2 files changed, 17 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/sim/eventq.cc b/src/sim/eventq.cc index dfff760a0..9c8792f8d 100644 --- a/src/sim/eventq.cc +++ b/src/sim/eventq.cc @@ -57,6 +57,21 @@ EventQueue mainEventQueue("Main Event Queue"); Counter Event::instanceCounter = 0; #endif +Event::~Event() +{ +} + +const std::string +Event::name() const +{ +#ifndef NDEBUG + return csprintf("Event_%d", instance); +#else + return csprintf("Event_%x", (uintptr_t)this); +#endif +} + + Event * Event::insertBefore(Event *event, Event *curr) { diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index 281df2dc3..5c98659b6 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -209,20 +209,8 @@ class Event : public Serializable, public FastAlloc #endif } - virtual - ~Event() - { - } - - virtual const std::string - name() const - { -#ifndef NDEBUG - return csprintf("Event_%d", instance); -#else - return csprintf("Event_%x", (uintptr_t)this); -#endif - } + virtual ~Event(); + virtual const std::string name() const; /// Return a C string describing the event. This string should /// *not* be dynamically allocated; just a const char array -- cgit v1.2.3 From 489e3e7381993e5b34d83a839303cf204c4f53b6 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 6 Dec 2008 14:18:18 -0800 Subject: eventq: use the flags data structure --- src/cpu/o3/commit_impl.hh | 2 +- src/sim/eventq.cc | 24 ++++++----- src/sim/eventq.hh | 101 ++++++++++++++++++++++++++++++++-------------- 3 files changed, 86 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index 46c4158f6..e215fe49e 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -53,7 +53,7 @@ DefaultCommit::TrapEvent::TrapEvent(DefaultCommit *_commit, unsigned _tid) : Event(CPU_Tick_Pri), commit(_commit), tid(_tid) { - this->setFlags(Event::AutoDelete); + this->setFlags(AutoDelete); } template diff --git a/src/sim/eventq.cc b/src/sim/eventq.cc index 9c8792f8d..f3d0eb461 100644 --- a/src/sim/eventq.cc +++ b/src/sim/eventq.cc @@ -182,7 +182,7 @@ EventQueue::serviceOne() { Event *event = head; Event *next = head->nextInBin; - event->clearFlags(Event::Scheduled); + event->flags.clear(Event::Scheduled); if (next) { // update the next bin pointer since it could be stale @@ -200,14 +200,14 @@ EventQueue::serviceOne() if (!event->squashed()) { event->process(); if (event->isExitEvent()) { - assert(!event->getFlags(Event::AutoDelete)); // would be silly + assert(!event->flags.isSet(Event::AutoDelete)); // would be silly return event; } } else { - event->clearFlags(Event::Squashed); + event->flags.clear(Event::Squashed); } - if (event->getFlags(Event::AutoDelete) && !event->scheduled()) + if (event->flags.isSet(Event::AutoDelete) && !event->scheduled()) delete event; return NULL; @@ -218,7 +218,8 @@ Event::serialize(std::ostream &os) { SERIALIZE_SCALAR(_when); SERIALIZE_SCALAR(_priority); - SERIALIZE_ENUM(_flags); + short _flags = flags; + SERIALIZE_SCALAR(_flags); } void @@ -233,9 +234,12 @@ Event::unserialize(Checkpoint *cp, const string §ion) // need to see if original event was in a scheduled, unsquashed // state, but don't want to restore those flags in the current // object itself (since they aren't immediately true) - UNSERIALIZE_ENUM(_flags); - bool wasScheduled = (_flags & Scheduled) && !(_flags & Squashed); - _flags &= ~(Squashed | Scheduled); + short _flags; + UNSERIALIZE_SCALAR(_flags); + flags = _flags; + + bool wasScheduled = flags.isSet(Scheduled) && !flags.isSet(Squashed); + flags.clear(Squashed | Scheduled); if (wasScheduled) { DPRINTF(Config, "rescheduling at %d\n", _when); @@ -254,7 +258,7 @@ EventQueue::serialize(ostream &os) Event *nextInBin = nextBin; while (nextInBin) { - if (nextInBin->getFlags(Event::AutoSerialize)) { + if (nextInBin->flags.isSet(Event::AutoSerialize)) { eventPtrs.push_back(nextInBin); paramOut(os, csprintf("event%d", numEvents++), nextInBin->name()); @@ -389,7 +393,7 @@ void Event::dump() const { cprintf("Event %s (%s)\n", name(), description()); - cprintf("Flags: %#x\n", _flags); + cprintf("Flags: %#x\n", flags); #ifdef EVENTQ_DEBUG cprintf("Created: %d\n", whenCreated); #endif diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index 5c98659b6..a29942d07 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -44,6 +44,7 @@ #include #include "base/fast_alloc.hh" +#include "base/flags.hh" #include "base/misc.hh" #include "base/trace.hh" #include "sim/serialize.hh" @@ -64,6 +65,19 @@ class Event : public Serializable, public FastAlloc { friend class EventQueue; + protected: + typedef short FlagsType; + typedef ::Flags Flags; + + static const FlagsType PublicRead = 0x003f; + static const FlagsType PublicWrite = 0x001d; + static const FlagsType Squashed = 0x0001; + static const FlagsType Scheduled = 0x0002; + static const FlagsType AutoDelete = 0x0004; + static const FlagsType AutoSerialize = 0x0008; + static const FlagsType IsExitEvent = 0x0010; + static const FlagsType IsMainQueue = 0x0020; + private: // The event queue is now a linked list of linked lists. The // 'nextBin' pointer is to find the bin, where a bin is defined as @@ -82,7 +96,7 @@ class Event : public Serializable, public FastAlloc Tick _when; //!< timestamp when event should be processed short _priority; //!< event priority - short _flags; + Flags flags; #ifndef NDEBUG /// Global counter to generate unique IDs for Event instances @@ -117,21 +131,48 @@ class Event : public Serializable, public FastAlloc } protected: - enum Flags { - None = 0x0, - Squashed = 0x1, - Scheduled = 0x2, - AutoDelete = 0x4, - AutoSerialize = 0x8, - IsExitEvent = 0x10, - IsMainQueue = 0x20 - }; + /// Accessor for flags. + Flags + getFlags() const + { + return flags & PublicRead; + } + + Flags + getFlags(Flags _flags) const + { + assert(flags.noneSet(~PublicRead)); + return flags.isSet(_flags); + } - bool getFlags(Flags f) const { return (_flags & f) == f; } - void setFlags(Flags f) { _flags |= f; } - void clearFlags(Flags f) { _flags &= ~f; } + Flags + allFlags(Flags _flags) const + { + assert(_flags.noneSet(~PublicRead)); + return flags.allSet(_flags); + } + + /// Accessor for flags. + void + setFlags(Flags _flags) + { + assert(_flags.noneSet(~PublicWrite)); + flags.set(_flags); + } + + void + clearFlags(Flags _flags) + { + assert(_flags.noneSet(~PublicWrite)); + flags.clear(_flags); + } + + void + clearFlags() + { + flags.clear(PublicWrite); + } - protected: // This function isn't really useful if TRACING_ON is not defined virtual void trace(const char *action); //!< trace event activity @@ -197,7 +238,7 @@ class Event : public Serializable, public FastAlloc * @param queue that the event gets scheduled on */ Event(Priority p = Default_Pri) - : nextBin(NULL), nextInBin(NULL), _priority(p), _flags(None) + : nextBin(NULL), nextInBin(NULL), _priority(p) { #ifndef NDEBUG instance = ++instanceCounter; @@ -234,16 +275,16 @@ class Event : public Serializable, public FastAlloc virtual void process() = 0; /// Determine if the current event is scheduled - bool scheduled() const { return getFlags(Scheduled); } + bool scheduled() const { return flags.isSet(Scheduled); } /// Squash the current event - void squash() { setFlags(Squashed); } + void squash() { flags.set(Squashed); } /// Check whether the event is squashed - bool squashed() const { return getFlags(Squashed); } + bool squashed() const { return flags.isSet(Squashed); } /// See if this is a SimExitEvent (without resorting to RTTI) - bool isExitEvent() const { return getFlags(IsExitEvent); } + bool isExitEvent() const { return flags.isSet(IsExitEvent); } /// Get the time that the event is scheduled Tick when() const { return _when; } @@ -398,7 +439,7 @@ DelayFunction(EventQueue *eventq, Tick when, T *object) public: DelayEvent(T *o) : object(o) - { setFlags(this->AutoDestroy); } + { this->setFlags(AutoDelete); } void process() { (object->*F)(); } const char *description() const { return "delay"; } }; @@ -431,11 +472,11 @@ EventQueue::schedule(Event *event, Tick when) event->setWhen(when, this); insert(event); - event->setFlags(Event::Scheduled); + event->flags.set(Event::Scheduled); if (this == &mainEventQueue) - event->setFlags(Event::IsMainQueue); + event->flags.set(Event::IsMainQueue); else - event->clearFlags(Event::IsMainQueue); + event->flags.clear(Event::IsMainQueue); if (DTRACE(Event)) event->trace("scheduled"); @@ -448,10 +489,10 @@ EventQueue::deschedule(Event *event) remove(event); - event->clearFlags(Event::Squashed); - event->clearFlags(Event::Scheduled); + event->flags.clear(Event::Squashed); + event->flags.clear(Event::Scheduled); - if (event->getFlags(Event::AutoDelete)) + if (event->flags.isSet(Event::AutoDelete)) delete event; if (DTRACE(Event)) @@ -469,12 +510,12 @@ EventQueue::reschedule(Event *event, Tick when, bool always) event->setWhen(when, this); insert(event); - event->clearFlags(Event::Squashed); - event->setFlags(Event::Scheduled); + event->flags.clear(Event::Squashed); + event->flags.set(Event::Scheduled); if (this == &mainEventQueue) - event->setFlags(Event::IsMainQueue); + event->flags.set(Event::IsMainQueue); else - event->clearFlags(Event::IsMainQueue); + event->flags.clear(Event::IsMainQueue); if (DTRACE(Event)) event->trace("rescheduled"); -- cgit v1.2.3 From e4790bcbe29b82dc81d4f34b78bb6ee2f718806a Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 6 Dec 2008 14:48:59 -0800 Subject: X86: Add add_entry back in. --- src/arch/x86/bios/IntelMP.py | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/arch/x86/bios/IntelMP.py b/src/arch/x86/bios/IntelMP.py index 70e7963fa..758932180 100644 --- a/src/arch/x86/bios/IntelMP.py +++ b/src/arch/x86/bios/IntelMP.py @@ -86,6 +86,15 @@ class X86IntelMPConfigTable(SimObject): ext_entries = VectorParam.X86IntelMPExtConfigEntry([], 'extended configuration table entries') + def add_entry(self, entry): + if isinstance(entry, X86IntelMPBaseConfigEntry): + self.base_entries.append(entry) + elif isinstance(entry, X86IntelMPExtConfigEntry): + self.base_entries.append(entry) + else: + panic("Don't know what type of Intel MP entry %s is." \ + % entry.__class__.__name__) + class X86IntelMPBaseConfigEntry(SimObject): type = 'X86IntelMPBaseConfigEntry' cxx_class = 'X86ISA::IntelMP::BaseConfigEntry' -- cgit v1.2.3 From 993b7be4bb3dae5b15cd4c23a4c0e4c3dc7ed734 Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Sun, 7 Dec 2008 15:07:42 -0500 Subject: imported patch aux-fix.patch --- src/arch/alpha/process.cc | 2 +- src/arch/sparc/process.cc | 2 +- src/arch/x86/process.cc | 2 +- src/sim/process.cc | 6 +++--- src/sim/process.hh | 12 ++++-------- 5 files changed, 10 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/process.cc b/src/arch/alpha/process.cc index 3e5851e74..004be1ec0 100644 --- a/src/arch/alpha/process.cc +++ b/src/arch/alpha/process.cc @@ -67,7 +67,7 @@ AlphaLiveProcess::argsInit(int intSize, int pageSize) { objFile->loadSections(initVirtMem); - typedef M5_auxv_t auxv_t; + typedef AuxVector auxv_t; std::vector auxv; ElfObject * elfObject = dynamic_cast(objFile); diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index 987e0465e..91baea40c 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -189,7 +189,7 @@ SparcLiveProcess::argsInit(int pageSize) { int intSize = sizeof(IntType); - typedef M5_auxv_t auxv_t; + typedef AuxVector auxv_t; std::vector auxv; diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index 8d0cd5038..2013190eb 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -200,7 +200,7 @@ X86LiveProcess::startup() void X86LiveProcess::argsInit(int intSize, int pageSize) { - typedef M5_auxv_t auxv_t; + typedef AuxVector auxv_t; std::vector auxv; Process::startup(); diff --git a/src/sim/process.cc b/src/sim/process.cc index 244fb9297..a1f4c7d1d 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -87,14 +87,14 @@ using namespace TheISA; int num_processes = 0; template -M5_auxv_t::M5_auxv_t(IntType type, IntType val) +AuxVector::AuxVector(IntType type, IntType val) { a_type = TheISA::htog(type); a_val = TheISA::htog(val); } -template class M5_auxv_t; -template class M5_auxv_t; +template class AuxVector; +template class AuxVector; Process::Process(ProcessParams * params) : SimObject(params), system(params->system), checkpointRestored(false), diff --git a/src/sim/process.hh b/src/sim/process.hh index 996663847..e6b7c80b7 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -62,19 +62,15 @@ namespace TheISA } template -struct M5_auxv_t +struct AuxVector { IntType a_type; - union { - IntType a_val; - IntType a_ptr; - IntType a_fcn; - }; + IntType a_val; - M5_auxv_t() + AuxVector() {} - M5_auxv_t(IntType type, IntType val); + AuxVector(IntType type, IntType val); }; class Process : public SimObject -- cgit v1.2.3 From 9192b7f1effaa9aabdd61840903e4f0c12079758 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 7 Dec 2008 12:59:48 -0800 Subject: Devices: Clean up the IDE controller. --- src/dev/ide_ctrl.cc | 825 +++++++++++++++++++++------------------------------- src/dev/ide_ctrl.hh | 243 ++++++---------- src/dev/ide_disk.cc | 200 +++++++------ src/dev/ide_disk.hh | 6 +- 4 files changed, 516 insertions(+), 758 deletions(-) (limited to 'src') diff --git a/src/dev/ide_ctrl.cc b/src/dev/ide_ctrl.cc index 6d7f1baf1..ced7686c7 100644 --- a/src/dev/ide_ctrl.cc +++ b/src/dev/ide_ctrl.cc @@ -30,203 +30,114 @@ * Miguel Serrano */ -#include -#include #include -#include #include "base/trace.hh" #include "cpu/intr_control.hh" #include "dev/ide_ctrl.hh" #include "dev/ide_disk.hh" -#include "dev/pciconfigall.hh" -#include "dev/pcireg.h" -#include "dev/platform.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" #include "params/IdeController.hh" -#include "sim/sim_object.hh" #include "sim/byteswap.hh" using namespace std; -//// -// Initialization and destruction -//// - -IdeController::IdeController(Params *p) - : PciDev(p) +// Bus master IDE registers +enum BMIRegOffset { + BMICommand = 0x0, + BMIStatus = 0x2, + BMIDescTablePtr = 0x4 +}; + +// PCI config space registers +enum ConfRegOffset { + PrimaryTiming = 0x40, + SecondaryTiming = 0x42, + DeviceTiming = 0x44, + UDMAControl = 0x48, + UDMATiming = 0x4A, + IDEConfig = 0x54 +}; + +static const uint16_t timeRegWithDecodeEn = 0x8000; + +IdeController::Channel::Channel( + string newName, Addr _cmdSize, Addr _ctrlSize) : + _name(newName), + cmdAddr(0), cmdSize(_cmdSize), ctrlAddr(0), ctrlSize(_ctrlSize), + master(NULL), slave(NULL), selected(NULL) { - // initialize the PIO interface addresses - pri_cmd_addr = 0; - pri_cmd_size = BARSize[0]; - - pri_ctrl_addr = 0; - pri_ctrl_size = BARSize[1]; - - sec_cmd_addr = 0; - sec_cmd_size = BARSize[2]; - - sec_ctrl_addr = 0; - sec_ctrl_size = BARSize[3]; - - // initialize the bus master interface (BMI) address to be configured - // via PCI - bmi_addr = 0; - bmi_size = BARSize[4]; - - // zero out all of the registers - memset(bmi_regs.data, 0, sizeof(bmi_regs)); - memset(config_regs.data, 0, sizeof(config_regs.data)); - - // setup initial values - // enable both channels - config_regs.idetim0 = htole((uint16_t)IDETIM_DECODE_EN); - config_regs.idetim1 = htole((uint16_t)IDETIM_DECODE_EN); - bmi_regs.bmis0 = DMA1CAP | DMA0CAP; - bmi_regs.bmis1 = DMA1CAP | DMA0CAP; - - // reset all internal variables - io_enabled = false; - bm_enabled = false; - memset(cmd_in_progress, 0, sizeof(cmd_in_progress)); - - // setup the disks attached to controller - memset(disks, 0, sizeof(disks)); - dev[0] = 0; - dev[1] = 0; - - if (params()->disks.size() > 3) - panic("IDE controllers support a maximum of 4 devices attached!\n"); - - for (int i = 0; i < params()->disks.size(); i++) { - disks[i] = params()->disks[i]; - disks[i]->setController(this); - } + memset(&bmiRegs, 0, sizeof(bmiRegs)); + bmiRegs.status.dmaCap0 = 1; + bmiRegs.status.dmaCap1 = 1; } -IdeController::~IdeController() +IdeController::Channel::~Channel() { - for (int i = 0; i < 4; i++) - if (disks[i]) - delete disks[i]; + delete master; + delete slave; } -//// -// Utility functions -/// - -void -IdeController::parseAddr(const Addr &addr, Addr &offset, IdeChannel &channel, - IdeRegType ®_type) -{ - offset = addr; - - if (addr >= pri_cmd_addr && addr < (pri_cmd_addr + pri_cmd_size)) { - offset -= pri_cmd_addr; - reg_type = COMMAND_BLOCK; - channel = PRIMARY; - } else if (addr >= pri_ctrl_addr && - addr < (pri_ctrl_addr + pri_ctrl_size)) { - offset -= pri_ctrl_addr; - reg_type = CONTROL_BLOCK; - channel = PRIMARY; - } else if (addr >= sec_cmd_addr && - addr < (sec_cmd_addr + sec_cmd_size)) { - offset -= sec_cmd_addr; - reg_type = COMMAND_BLOCK; - channel = SECONDARY; - } else if (addr >= sec_ctrl_addr && - addr < (sec_ctrl_addr + sec_ctrl_size)) { - offset -= sec_ctrl_addr; - reg_type = CONTROL_BLOCK; - channel = SECONDARY; - } else if (addr >= bmi_addr && addr < (bmi_addr + bmi_size)) { - offset -= bmi_addr; - reg_type = BMI_BLOCK; - channel = (offset < BMIC1) ? PRIMARY : SECONDARY; - } else { - panic("IDE controller access to invalid address: %#x\n", addr); - } -} - -int -IdeController::getDisk(IdeChannel channel) +IdeController::IdeController(Params *p) + : PciDev(p), primary(name() + ".primary", BARSize[0], BARSize[1]), + secondary(name() + ".secondary", BARSize[2], BARSize[3]), + bmiAddr(0), bmiSize(BARSize[4]), + primaryTiming(htole(timeRegWithDecodeEn)), + secondaryTiming(htole(timeRegWithDecodeEn)), + deviceTiming(0), udmaControl(0), udmaTiming(0), ideConfig(0), + ioEnabled(false), bmEnabled(false) { - int disk = 0; - uint8_t *devBit = &dev[0]; - - if (channel == SECONDARY) { - disk += 2; - devBit = &dev[1]; - } - - disk += *devBit; + if (params()->disks.size() > 3) + panic("IDE controllers support a maximum of 4 devices attached!\n"); - assert(*devBit == 0 || *devBit == 1); + // Assign the disks to channels + int numDisks = params()->disks.size(); + if (numDisks > 0) + primary.master = params()->disks[0]; + if (numDisks > 1) + primary.slave = params()->disks[1]; + if (numDisks > 2) + secondary.master = params()->disks[2]; + if (numDisks > 3) + secondary.slave = params()->disks[3]; - return disk; -} - -int -IdeController::getDisk(IdeDisk *diskPtr) -{ - for (int i = 0; i < 4; i++) { - if ((long)diskPtr == (long)disks[i]) - return i; + for (int i = 0; i < params()->disks.size(); i++) { + params()->disks[i]->setController(this); } - return -1; + primary.select(false); + secondary.select(false); } bool IdeController::isDiskSelected(IdeDisk *diskPtr) { - for (int i = 0; i < 4; i++) { - if ((long)diskPtr == (long)disks[i]) { - // is disk is on primary or secondary channel - int channel = i/2; - // is disk the master or slave - int devID = i%2; - - return (dev[channel] == devID); - } - } - panic("Unable to find disk by pointer!!\n"); + return (primary.selected == diskPtr || secondary.selected == diskPtr); } -//// -// Command completion -//// +void +IdeController::intrPost() +{ + primary.bmiRegs.status.intStatus = 1; + PciDev::intrPost(); +} void IdeController::setDmaComplete(IdeDisk *disk) { - int diskNum = getDisk(disk); - - if (diskNum < 0) - panic("Unable to find disk based on pointer %#x\n", disk); - - if (diskNum < 2) { - // clear the start/stop bit in the command register - bmi_regs.bmic0 &= ~SSBM; - // clear the bus master active bit in the status register - bmi_regs.bmis0 &= ~BMIDEA; - // set the interrupt bit - bmi_regs.bmis0 |= IDEINTS; + Channel *channel; + if (disk == primary.master || disk == primary.slave) { + channel = &primary; + } else if (disk == secondary.master || disk == secondary.slave) { + channel = &secondary; } else { - // clear the start/stop bit in the command register - bmi_regs.bmic1 &= ~SSBM; - // clear the bus master active bit in the status register - bmi_regs.bmis1 &= ~BMIDEA; - // set the interrupt bit - bmi_regs.bmis1 |= IDEINTS; + panic("Unable to find disk based on pointer %#x\n", disk); } -} - -//// -// Read and write handling -//// + channel->bmiRegs.command.startStop = 0; + channel->bmiRegs.status.active = 0; + channel->bmiRegs.status.intStatus = 1; +} Tick IdeController::readConfig(PacketPtr pkt) @@ -236,30 +147,28 @@ IdeController::readConfig(PacketPtr pkt) return PciDev::readConfig(pkt); } - assert(offset >= IDE_CTRL_CONF_START && (offset + 1) <= IDE_CTRL_CONF_END); - pkt->allocate(); switch (pkt->getSize()) { case sizeof(uint8_t): switch (offset) { - case IDE_CTRL_CONF_DEV_TIMING: - pkt->set(config_regs.sidetim); + case DeviceTiming: + pkt->set(deviceTiming); break; - case IDE_CTRL_CONF_UDMA_CNTRL: - pkt->set(config_regs.udmactl); + case UDMAControl: + pkt->set(udmaControl); break; - case IDE_CTRL_CONF_PRIM_TIMING+1: - pkt->set(htole(config_regs.idetim0) >> 8); + case PrimaryTiming + 1: + pkt->set(bits(htole(primaryTiming), 15, 8)); break; - case IDE_CTRL_CONF_SEC_TIMING+1: - pkt->set(htole(config_regs.idetim1) >> 8); + case SecondaryTiming + 1: + pkt->set(bits(htole(secondaryTiming), 15, 8)); break; - case IDE_CTRL_CONF_IDE_CONFIG: - pkt->set(htole(config_regs.ideconfig) & 0xFF); + case IDEConfig: + pkt->set(bits(htole(ideConfig), 7, 0)); break; - case IDE_CTRL_CONF_IDE_CONFIG+1: - pkt->set(htole(config_regs.ideconfig) >> 8); + case IDEConfig + 1: + pkt->set(bits(htole(ideConfig), 15, 8)); break; default: panic("Invalid PCI configuration read for size 1 at offset: %#x!\n", @@ -270,17 +179,17 @@ IdeController::readConfig(PacketPtr pkt) break; case sizeof(uint16_t): switch (offset) { - case IDE_CTRL_CONF_PRIM_TIMING: - pkt->set(config_regs.idetim0); + case PrimaryTiming: + pkt->set(primaryTiming); break; - case IDE_CTRL_CONF_SEC_TIMING: - pkt->set(config_regs.idetim1); + case SecondaryTiming: + pkt->set(secondaryTiming); break; - case IDE_CTRL_CONF_UDMA_TIMING: - pkt->set(config_regs.udmatim); + case UDMATiming: + pkt->set(udmaTiming); break; - case IDE_CTRL_CONF_IDE_CONFIG: - pkt->set(config_regs.ideconfig); + case IDEConfig: + pkt->set(ideConfig); break; default: panic("Invalid PCI configuration read for size 2 offset: %#x!\n", @@ -309,48 +218,45 @@ IdeController::writeConfig(PacketPtr pkt) if (offset < PCI_DEVICE_SPECIFIC) { PciDev::writeConfig(pkt); } else { - assert(offset >= IDE_CTRL_CONF_START && (offset + 1) <= IDE_CTRL_CONF_END); - switch (pkt->getSize()) { case sizeof(uint8_t): switch (offset) { - case IDE_CTRL_CONF_DEV_TIMING: - config_regs.sidetim = pkt->get(); + case DeviceTiming: + deviceTiming = pkt->get(); break; - case IDE_CTRL_CONF_UDMA_CNTRL: - config_regs.udmactl = pkt->get(); + case UDMAControl: + udmaControl = pkt->get(); break; - case IDE_CTRL_CONF_IDE_CONFIG: - config_regs.ideconfig = (config_regs.ideconfig & 0xFF00) | - (pkt->get()); + case IDEConfig: + replaceBits(ideConfig, 7, 0, pkt->get()); break; - case IDE_CTRL_CONF_IDE_CONFIG+1: - config_regs.ideconfig = (config_regs.ideconfig & 0x00FF) | - pkt->get() << 8; + case IDEConfig + 1: + replaceBits(ideConfig, 15, 8, pkt->get()); break; default: - panic("Invalid PCI configuration write for size 1 offset: %#x!\n", - offset); + panic("Invalid PCI configuration write " + "for size 1 offset: %#x!\n", offset); } DPRINTF(IdeCtrl, "PCI write offset: %#x size: 1 data: %#x\n", offset, (uint32_t)pkt->get()); break; case sizeof(uint16_t): switch (offset) { - case IDE_CTRL_CONF_PRIM_TIMING: - config_regs.idetim0 = pkt->get(); + case PrimaryTiming: + primaryTiming = pkt->get(); break; - case IDE_CTRL_CONF_SEC_TIMING: - config_regs.idetim1 = pkt->get(); + case SecondaryTiming: + secondaryTiming = pkt->get(); break; - case IDE_CTRL_CONF_UDMA_TIMING: - config_regs.udmatim = pkt->get(); + case UDMATiming: + udmaTiming = pkt->get(); break; - case IDE_CTRL_CONF_IDE_CONFIG: - config_regs.ideconfig = pkt->get(); + case IDEConfig: + ideConfig = pkt->get(); break; default: - panic("Invalid PCI configuration write for size 2 offset: %#x!\n", + panic("Invalid PCI configuration write " + "for size 2 offset: %#x!\n", offset); } DPRINTF(IdeCtrl, "PCI write offset: %#x size: 2 data: %#x\n", @@ -370,317 +276,223 @@ IdeController::writeConfig(PacketPtr pkt) switch(offset) { case PCI0_BASE_ADDR0: if (BARAddrs[0] != 0) - pri_cmd_addr = BARAddrs[0]; + primary.cmdAddr = BARAddrs[0]; break; case PCI0_BASE_ADDR1: if (BARAddrs[1] != 0) - pri_ctrl_addr = BARAddrs[1]; + primary.ctrlAddr = BARAddrs[1]; break; case PCI0_BASE_ADDR2: if (BARAddrs[2] != 0) - sec_cmd_addr = BARAddrs[2]; + secondary.cmdAddr = BARAddrs[2]; break; case PCI0_BASE_ADDR3: if (BARAddrs[3] != 0) - sec_ctrl_addr = BARAddrs[3]; + secondary.ctrlAddr = BARAddrs[3]; break; case PCI0_BASE_ADDR4: if (BARAddrs[4] != 0) - bmi_addr = BARAddrs[4]; + bmiAddr = BARAddrs[4]; break; case PCI_COMMAND: - if (letoh(config.command) & PCI_CMD_IOSE) - io_enabled = true; - else - io_enabled = false; - - if (letoh(config.command) & PCI_CMD_BME) - bm_enabled = true; - else - bm_enabled = false; + ioEnabled = (config.command & htole(PCI_CMD_IOSE)); + bmEnabled = (config.command & htole(PCI_CMD_BME)); break; } return configDelay; } - -Tick -IdeController::read(PacketPtr pkt) +void +IdeController::Channel::accessCommand(Addr offset, + int size, uint8_t *data, bool read) { - Addr offset; - IdeChannel channel; - IdeRegType reg_type; - int disk; - - pkt->allocate(); - if (pkt->getSize() != 1 && pkt->getSize() != 2 && pkt->getSize() !=4) - panic("Bad IDE read size: %d\n", pkt->getSize()); - - parseAddr(pkt->getAddr(), offset, channel, reg_type); - - if (!io_enabled) { - pkt->makeAtomicResponse(); - return pioDelay; - } - - switch (reg_type) { - case BMI_BLOCK: - switch (pkt->getSize()) { - case sizeof(uint8_t): - pkt->set(bmi_regs.data[offset]); - break; - case sizeof(uint16_t): - pkt->set(*(uint16_t*)&bmi_regs.data[offset]); - break; - case sizeof(uint32_t): - pkt->set(*(uint32_t*)&bmi_regs.data[offset]); - break; - default: - panic("IDE read of BMI reg invalid size: %#x\n", pkt->getSize()); - } - break; - - case COMMAND_BLOCK: - case CONTROL_BLOCK: - disk = getDisk(channel); + const Addr SelectOffset = 6; + const uint8_t SelectDevBit = 0x10; - if (disks[disk] == NULL) { - pkt->set(0); - break; - } + if (!read && offset == SelectOffset) + select(*data & SelectDevBit); - switch (offset) { - case DATA_OFFSET: - switch (pkt->getSize()) { - case sizeof(uint16_t): - disks[disk]->read(offset, reg_type, pkt->getPtr()); - break; - - case sizeof(uint32_t): - disks[disk]->read(offset, reg_type, pkt->getPtr()); - disks[disk]->read(offset, reg_type, - pkt->getPtr() + sizeof(uint16_t)); - break; - - default: - panic("IDE read of data reg invalid size: %#x\n", pkt->getSize()); - } - break; - default: - if (pkt->getSize() == sizeof(uint8_t)) { - disks[disk]->read(offset, reg_type, pkt->getPtr()); - } else - panic("IDE read of command reg of invalid size: %#x\n", pkt->getSize()); - } - break; - default: - panic("IDE controller read of unknown register block type!\n"); + if (selected == NULL) { + assert(size == sizeof(uint8_t)); + *data = 0; + } else if (read) { + selected->readCommand(offset, size, data); + } else { + selected->writeCommand(offset, size, data); } - if (pkt->getSize() == 1) - DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n", - offset, pkt->getSize(), (uint32_t)pkt->get()); - else if (pkt->getSize() == 2) - DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n", - offset, pkt->getSize(), pkt->get()); - else - DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n", - offset, pkt->getSize(), pkt->get()); - - pkt->makeAtomicResponse(); - return pioDelay; } -Tick -IdeController::write(PacketPtr pkt) +void +IdeController::Channel::accessControl(Addr offset, + int size, uint8_t *data, bool read) { - Addr offset; - IdeChannel channel; - IdeRegType reg_type; - int disk; - uint8_t oldVal, newVal; - - parseAddr(pkt->getAddr(), offset, channel, reg_type); - - if (!io_enabled) { - pkt->makeAtomicResponse(); - DPRINTF(IdeCtrl, "io not enabled\n"); - return pioDelay; + if (selected == NULL) { + assert(size == sizeof(uint8_t)); + *data = 0; + } else if (read) { + selected->readControl(offset, size, data); + } else { + selected->writeControl(offset, size, data); } +} - switch (reg_type) { - case BMI_BLOCK: - if (!bm_enabled) { - pkt->makeAtomicResponse(); - return pioDelay; - } - +void +IdeController::Channel::accessBMI(Addr offset, + int size, uint8_t *data, bool read) +{ + assert(offset + size <= sizeof(BMIRegs)); + if (read) { + memcpy(data, (uint8_t *)&bmiRegs + offset, size); + } else { switch (offset) { - // Bus master IDE command register - case BMIC1: - case BMIC0: - if (pkt->getSize() != sizeof(uint8_t)) - panic("Invalid BMIC write size: %x\n", pkt->getSize()); - - // select the current disk based on DEV bit - disk = getDisk(channel); - - oldVal = bmi_regs.chan[channel].bmic; - newVal = pkt->get(); - - // if a DMA transfer is in progress, R/W control cannot change - if (oldVal & SSBM) { - if ((oldVal & RWCON) ^ (newVal & RWCON)) { - (oldVal & RWCON) ? newVal |= RWCON : newVal &= ~RWCON; - } - } - - // see if the start/stop bit is being changed - if ((oldVal & SSBM) ^ (newVal & SSBM)) { - if (oldVal & SSBM) { - // stopping DMA transfer - DPRINTF(IdeCtrl, "Stopping DMA transfer\n"); + case BMICommand: + { + if (size != sizeof(uint8_t)) + panic("Invalid BMIC write size: %x\n", size); - // clear the BMIDEA bit - bmi_regs.chan[channel].bmis = - bmi_regs.chan[channel].bmis & ~BMIDEA; + BMICommandReg oldVal = bmiRegs.command; + BMICommandReg newVal = *data; - if (disks[disk] == NULL) - panic("DMA stop for disk %d which does not exist\n", - disk); + // if a DMA transfer is in progress, R/W control cannot change + if (oldVal.startStop && oldVal.rw != newVal.rw) + oldVal.rw = newVal.rw; - // inform the disk of the DMA transfer abort - disks[disk]->abortDma(); - } else { - // starting DMA transfer - DPRINTF(IdeCtrl, "Starting DMA transfer\n"); + if (oldVal.startStop != newVal.startStop) { + if (selected == NULL) + panic("DMA start for disk which does not exist\n"); - // set the BMIDEA bit - bmi_regs.chan[channel].bmis = - bmi_regs.chan[channel].bmis | BMIDEA; + if (oldVal.startStop) { + DPRINTF(IdeCtrl, "Stopping DMA transfer\n"); + bmiRegs.status.active = 0; - if (disks[disk] == NULL) - panic("DMA start for disk %d which does not exist\n", - disk); + selected->abortDma(); + } else { + DPRINTF(IdeCtrl, "Starting DMA transfer\n"); + bmiRegs.status.active = 1; - // inform the disk of the DMA transfer start - disks[disk]->startDma(letoh(bmi_regs.chan[channel].bmidtp)); + selected->startDma(letoh(bmiRegs.bmidtp)); + } } - } - - // update the register value - bmi_regs.chan[channel].bmic = newVal; - break; - - // Bus master IDE status register - case BMIS0: - case BMIS1: - if (pkt->getSize() != sizeof(uint8_t)) - panic("Invalid BMIS write size: %x\n", pkt->getSize()); - - oldVal = bmi_regs.chan[channel].bmis; - newVal = pkt->get(); - - // the BMIDEA bit is RO - newVal |= (oldVal & BMIDEA); - // to reset (set 0) IDEINTS and IDEDMAE, write 1 to each - if ((oldVal & IDEINTS) && (newVal & IDEINTS)) - newVal &= ~IDEINTS; // clear the interrupt? - else - (oldVal & IDEINTS) ? newVal |= IDEINTS : newVal &= ~IDEINTS; - - if ((oldVal & IDEDMAE) && (newVal & IDEDMAE)) - newVal &= ~IDEDMAE; - else - (oldVal & IDEDMAE) ? newVal |= IDEDMAE : newVal &= ~IDEDMAE; - - bmi_regs.chan[channel].bmis = newVal; + bmiRegs.command = newVal; + } break; - - // Bus master IDE descriptor table pointer register - case BMIDTP0: - case BMIDTP1: + case BMIStatus: { - if (pkt->getSize() != sizeof(uint32_t)) - panic("Invalid BMIDTP write size: %x\n", pkt->getSize()); - - bmi_regs.chan[channel].bmidtp = htole(pkt->get() & ~0x3); + if (size != sizeof(uint8_t)) + panic("Invalid BMIS write size: %x\n", size); + + BMIStatusReg oldVal = bmiRegs.status; + BMIStatusReg newVal = *data; + + // the BMIDEA bit is read only + newVal.active = oldVal.active; + + // to reset (set 0) IDEINTS and IDEDMAE, write 1 to each + if (oldVal.intStatus && newVal.intStatus) + newVal.intStatus = 0; // clear the interrupt? + else + newVal.intStatus = oldVal.intStatus; + if (oldVal.dmaError && newVal.dmaError) + newVal.dmaError = 0; + else + newVal.dmaError = oldVal.dmaError; + + bmiRegs.status = newVal; } break; - + case BMIDescTablePtr: + if (size != sizeof(uint32_t)) + panic("Invalid BMIDTP write size: %x\n", size); + bmiRegs.bmidtp = htole(*(uint32_t *)data & ~0x3); + break; default: - if (pkt->getSize() != sizeof(uint8_t) && - pkt->getSize() != sizeof(uint16_t) && - pkt->getSize() != sizeof(uint32_t)) - panic("IDE controller write of invalid write size: %x\n", - pkt->getSize()); - - // do a default copy of data into the registers - memcpy(&bmi_regs.data[offset], pkt->getPtr(), pkt->getSize()); + if (size != sizeof(uint8_t) && size != sizeof(uint16_t) && + size != sizeof(uint32_t)) + panic("IDE controller write of invalid write size: %x\n", size); + memcpy((uint8_t *)&bmiRegs + offset, data, size); } - break; - case COMMAND_BLOCK: - if (offset == IDE_SELECT_OFFSET) { - uint8_t *devBit = &dev[channel]; - *devBit = (letoh(pkt->get()) & IDE_SELECT_DEV_BIT) ? 1 : 0; - } - // fall-through ok! - case CONTROL_BLOCK: - disk = getDisk(channel); + } +} - if (disks[disk] == NULL) - break; +void +IdeController::dispatchAccess(PacketPtr pkt, bool read) +{ + pkt->allocate(); + if (pkt->getSize() != 1 && pkt->getSize() != 2 && pkt->getSize() !=4) + panic("Bad IDE read size: %d\n", pkt->getSize()); - switch (offset) { - case DATA_OFFSET: - switch (pkt->getSize()) { - case sizeof(uint16_t): - disks[disk]->write(offset, reg_type, pkt->getPtr()); - break; + if (!ioEnabled) { + pkt->makeAtomicResponse(); + DPRINTF(IdeCtrl, "io not enabled\n"); + return; + } - case sizeof(uint32_t): - disks[disk]->write(offset, reg_type, pkt->getPtr()); - disks[disk]->write(offset, reg_type, pkt->getPtr() + - sizeof(uint16_t)); - break; - default: - panic("IDE write of data reg invalid size: %#x\n", pkt->getSize()); - } - break; - default: - if (pkt->getSize() == sizeof(uint8_t)) { - disks[disk]->write(offset, reg_type, pkt->getPtr()); - } else - panic("IDE write of command reg of invalid size: %#x\n", pkt->getSize()); + Addr addr = pkt->getAddr(); + int size = pkt->getSize(); + uint8_t *dataPtr = pkt->getPtr(); + + if (addr >= primary.cmdAddr && + addr < (primary.cmdAddr + primary.cmdSize)) { + addr -= primary.cmdAddr; + primary.accessCommand(addr, size, dataPtr, read); + } else if (addr >= primary.ctrlAddr && + addr < (primary.ctrlAddr + primary.ctrlSize)) { + addr -= primary.ctrlAddr; + primary.accessControl(addr, size, dataPtr, read); + } else if (addr >= secondary.cmdAddr && + addr < (secondary.cmdAddr + secondary.cmdSize)) { + addr -= secondary.cmdAddr; + secondary.accessCommand(addr, size, dataPtr, read); + } else if (addr >= secondary.ctrlAddr && + addr < (secondary.ctrlAddr + secondary.ctrlSize)) { + addr -= secondary.ctrlAddr; + secondary.accessControl(addr, size, dataPtr, read); + } else if (addr >= bmiAddr && addr < (bmiAddr + bmiSize)) { + if (!read && !bmEnabled) + return; + addr -= bmiAddr; + if (addr < sizeof(Channel::BMIRegs)) { + primary.accessBMI(addr, size, dataPtr, read); + } else { + addr -= sizeof(Channel::BMIRegs); + secondary.accessBMI(addr, size, dataPtr, read); } - break; - default: - panic("IDE controller write of unknown register block type!\n"); + } else { + panic("IDE controller access to invalid address: %#x\n", addr); } + uint32_t data; if (pkt->getSize() == 1) - DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n", - offset, pkt->getSize(), (uint32_t)pkt->get()); + data = pkt->get(); else if (pkt->getSize() == 2) - DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n", - offset, pkt->getSize(), pkt->get()); + data = pkt->get(); else - DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n", - offset, pkt->getSize(), pkt->get()); - + data = pkt->get(); + DPRINTF(IdeCtrl, "%s from offset: %#x size: %#x data: %#x\n", + read ? "Read" : "Write", pkt->getAddr(), pkt->getSize(), data); pkt->makeAtomicResponse(); +} + +Tick +IdeController::read(PacketPtr pkt) +{ + dispatchAccess(pkt, true); return pioDelay; } -//// -// Serialization -//// +Tick +IdeController::write(PacketPtr pkt) +{ + dispatchAccess(pkt, false); + return pioDelay; +} void IdeController::serialize(std::ostream &os) @@ -688,30 +500,36 @@ IdeController::serialize(std::ostream &os) // Serialize the PciDev base class PciDev::serialize(os); - // Serialize register addresses and sizes - SERIALIZE_SCALAR(pri_cmd_addr); - SERIALIZE_SCALAR(pri_cmd_size); - SERIALIZE_SCALAR(pri_ctrl_addr); - SERIALIZE_SCALAR(pri_ctrl_size); - SERIALIZE_SCALAR(sec_cmd_addr); - SERIALIZE_SCALAR(sec_cmd_size); - SERIALIZE_SCALAR(sec_ctrl_addr); - SERIALIZE_SCALAR(sec_ctrl_size); - SERIALIZE_SCALAR(bmi_addr); - SERIALIZE_SCALAR(bmi_size); - - // Serialize registers - SERIALIZE_ARRAY(bmi_regs.data, - sizeof(bmi_regs.data) / sizeof(bmi_regs.data[0])); - SERIALIZE_ARRAY(dev, sizeof(dev) / sizeof(dev[0])); - SERIALIZE_ARRAY(config_regs.data, - sizeof(config_regs.data) / sizeof(config_regs.data[0])); + // Serialize channels + primary.serialize(os); + secondary.serialize(os); + + // Serialize config registers + SERIALIZE_SCALAR(primaryTiming); + SERIALIZE_SCALAR(secondaryTiming); + SERIALIZE_SCALAR(deviceTiming); + SERIALIZE_SCALAR(udmaControl); + SERIALIZE_SCALAR(udmaTiming); + SERIALIZE_SCALAR(ideConfig); // Serialize internal state - SERIALIZE_SCALAR(io_enabled); - SERIALIZE_SCALAR(bm_enabled); - SERIALIZE_ARRAY(cmd_in_progress, - sizeof(cmd_in_progress) / sizeof(cmd_in_progress[0])); + SERIALIZE_SCALAR(ioEnabled); + SERIALIZE_SCALAR(bmEnabled); +} + +void +IdeController::Channel::serialize(std::ostream &os) +{ + SERIALIZE_SCALAR(cmdAddr); + SERIALIZE_SCALAR(cmdSize); + SERIALIZE_SCALAR(ctrlAddr); + SERIALIZE_SCALAR(ctrlSize); + SERIALIZE_SCALAR((uint8_t)bmiRegs.command); + SERIALIZE_SCALAR(bmiRegs.reserved0); + SERIALIZE_SCALAR((uint8_t)bmiRegs.status); + SERIALIZE_SCALAR(bmiRegs.reserved1); + SERIALIZE_SCALAR(bmiRegs.bmidtp); + SERIALIZE_SCALAR(selectBit); } void @@ -720,30 +538,41 @@ IdeController::unserialize(Checkpoint *cp, const std::string §ion) // Unserialize the PciDev base class PciDev::unserialize(cp, section); - // Unserialize register addresses and sizes - UNSERIALIZE_SCALAR(pri_cmd_addr); - UNSERIALIZE_SCALAR(pri_cmd_size); - UNSERIALIZE_SCALAR(pri_ctrl_addr); - UNSERIALIZE_SCALAR(pri_ctrl_size); - UNSERIALIZE_SCALAR(sec_cmd_addr); - UNSERIALIZE_SCALAR(sec_cmd_size); - UNSERIALIZE_SCALAR(sec_ctrl_addr); - UNSERIALIZE_SCALAR(sec_ctrl_size); - UNSERIALIZE_SCALAR(bmi_addr); - UNSERIALIZE_SCALAR(bmi_size); - - // Unserialize registers - UNSERIALIZE_ARRAY(bmi_regs.data, - sizeof(bmi_regs.data) / sizeof(bmi_regs.data[0])); - UNSERIALIZE_ARRAY(dev, sizeof(dev) / sizeof(dev[0])); - UNSERIALIZE_ARRAY(config_regs.data, - sizeof(config_regs.data) / sizeof(config_regs.data[0])); + // Unserialize channels + primary.unserialize(cp, section); + secondary.unserialize(cp, section); + + // Unserialize config registers + UNSERIALIZE_SCALAR(primaryTiming); + UNSERIALIZE_SCALAR(secondaryTiming); + UNSERIALIZE_SCALAR(deviceTiming); + UNSERIALIZE_SCALAR(udmaControl); + UNSERIALIZE_SCALAR(udmaTiming); + UNSERIALIZE_SCALAR(ideConfig); // Unserialize internal state - UNSERIALIZE_SCALAR(io_enabled); - UNSERIALIZE_SCALAR(bm_enabled); - UNSERIALIZE_ARRAY(cmd_in_progress, - sizeof(cmd_in_progress) / sizeof(cmd_in_progress[0])); + UNSERIALIZE_SCALAR(ioEnabled); + UNSERIALIZE_SCALAR(bmEnabled); +} + +void +IdeController::Channel::unserialize( + Checkpoint *cp, const std::string §ion) +{ + uint8_t temp; + UNSERIALIZE_SCALAR(cmdAddr); + UNSERIALIZE_SCALAR(cmdSize); + UNSERIALIZE_SCALAR(ctrlAddr); + UNSERIALIZE_SCALAR(ctrlSize); + UNSERIALIZE_SCALAR(temp); + bmiRegs.command = temp; + UNSERIALIZE_SCALAR(bmiRegs.reserved0); + UNSERIALIZE_SCALAR(temp); + bmiRegs.status = temp; + UNSERIALIZE_SCALAR(bmiRegs.reserved1); + UNSERIALIZE_SCALAR(bmiRegs.bmidtp); + UNSERIALIZE_SCALAR(selectBit); + select(selectBit); } IdeController * diff --git a/src/dev/ide_ctrl.hh b/src/dev/ide_ctrl.hh index f22d83e9c..6a71a6640 100644 --- a/src/dev/ide_ctrl.hh +++ b/src/dev/ide_ctrl.hh @@ -37,61 +37,13 @@ #ifndef __IDE_CTRL_HH__ #define __IDE_CTRL_HH__ +#include "base/bitunion.hh" #include "dev/pcidev.hh" #include "dev/pcireg.h" #include "dev/io_device.hh" #include "params/IdeController.hh" -#define BMIC0 0x0 // Bus master IDE command register -#define BMIS0 0x2 // Bus master IDE status register -#define BMIDTP0 0x4 // Bus master IDE descriptor table pointer register -#define BMIC1 0x8 // Bus master IDE command register -#define BMIS1 0xa // Bus master IDE status register -#define BMIDTP1 0xc // Bus master IDE descriptor table pointer register - -// Bus master IDE command register bit fields -#define RWCON 0x08 // Bus master read/write control -#define SSBM 0x01 // Start/stop bus master - -// Bus master IDE status register bit fields -#define DMA1CAP 0x40 // Drive 1 DMA capable -#define DMA0CAP 0x20 // Drive 0 DMA capable -#define IDEINTS 0x04 // IDE Interrupt Status -#define IDEDMAE 0x02 // IDE DMA error -#define BMIDEA 0x01 // Bus master IDE active - -// IDE Command byte fields -#define IDE_SELECT_OFFSET (6) -#define IDE_SELECT_DEV_BIT 0x10 - -#define IDE_FEATURE_OFFSET IDE_ERROR_OFFSET -#define IDE_COMMAND_OFFSET IDE_STATUS_OFFSET - -// IDE Timing Register bit fields -#define IDETIM_DECODE_EN 0x8000 - -// PCI device specific register byte offsets -#define IDE_CTRL_CONF_START 0x40 -#define IDE_CTRL_CONF_END ((IDE_CTRL_CONF_START) + sizeof(config_regs)) - -#define IDE_CTRL_CONF_PRIM_TIMING 0x40 -#define IDE_CTRL_CONF_SEC_TIMING 0x42 -#define IDE_CTRL_CONF_DEV_TIMING 0x44 -#define IDE_CTRL_CONF_UDMA_CNTRL 0x48 -#define IDE_CTRL_CONF_UDMA_TIMING 0x4A -#define IDE_CTRL_CONF_IDE_CONFIG 0x54 - - -enum IdeRegType { - COMMAND_BLOCK, - CONTROL_BLOCK, - BMI_BLOCK -}; - class IdeDisk; -class IntrControl; -class PciConfigAll; -class Platform; /** * Device model for an Intel PIIX4 IDE controller @@ -99,137 +51,106 @@ class Platform; class IdeController : public PciDev { - friend class IdeDisk; + private: + // Bus master IDE status register bit fields + BitUnion8(BMIStatusReg) + Bitfield<6> dmaCap0; + Bitfield<5> dmaCap1; + Bitfield<2> intStatus; + Bitfield<1> dmaError; + Bitfield<0> active; + EndBitUnion(BMIStatusReg) + + BitUnion8(BMICommandReg) + Bitfield<3> rw; + Bitfield<0> startStop; + EndBitUnion(BMICommandReg) + + struct Channel + { + std::string _name; + + const std::string + name() + { + return _name; + } + + /** Command and control block registers */ + Addr cmdAddr, cmdSize, ctrlAddr, ctrlSize; + + /** Registers used for bus master interface */ + struct BMIRegs + { + BMICommandReg command; + uint8_t reserved0; + BMIStatusReg status; + uint8_t reserved1; + uint32_t bmidtp; + } bmiRegs; - enum IdeChannel { - PRIMARY = 0, - SECONDARY = 1 - }; + /** IDE disks connected to this controller */ + IdeDisk *master, *slave; - private: - /** Primary command block registers */ - Addr pri_cmd_addr; - Addr pri_cmd_size; - /** Primary control block registers */ - Addr pri_ctrl_addr; - Addr pri_ctrl_size; - /** Secondary command block registers */ - Addr sec_cmd_addr; - Addr sec_cmd_size; - /** Secondary control block registers */ - Addr sec_ctrl_addr; - Addr sec_ctrl_size; - /** Bus master interface (BMI) registers */ - Addr bmi_addr; - Addr bmi_size; + /** Currently selected disk */ + IdeDisk *selected; - private: - /** Registers used for bus master interface */ - union { - uint8_t data[16]; - - struct { - uint8_t bmic0; - uint8_t reserved_0; - uint8_t bmis0; - uint8_t reserved_1; - uint32_t bmidtp0; - uint8_t bmic1; - uint8_t reserved_2; - uint8_t bmis1; - uint8_t reserved_3; - uint32_t bmidtp1; - }; - - struct { - uint8_t bmic; - uint8_t reserved_4; - uint8_t bmis; - uint8_t reserved_5; - uint32_t bmidtp; - } chan[2]; + bool selectBit; - } bmi_regs; - /** Shadows of the device select bit */ - uint8_t dev[2]; - /** Registers used in device specific PCI configuration */ - union { - uint8_t data[22]; - - struct { - uint16_t idetim0; - uint16_t idetim1; - uint8_t sidetim; - uint8_t reserved_0[3]; - uint8_t udmactl; - uint8_t reserved_1; - uint16_t udmatim; - uint8_t reserved_2[8]; - uint16_t ideconfig; - }; - } config_regs; + void + select(bool selSlave) + { + selectBit = selSlave; + selected = selectBit ? slave : master; + } - // Internal management variables - bool io_enabled; - bool bm_enabled; - bool cmd_in_progress[4]; + void accessCommand(Addr offset, int size, uint8_t *data, bool read); + void accessControl(Addr offset, int size, uint8_t *data, bool read); + void accessBMI(Addr offset, int size, uint8_t *data, bool read); - private: - /** IDE disks connected to controller */ - IdeDisk *disks[4]; + Channel(std::string newName, Addr _cmdSize, Addr _ctrlSize); + ~Channel(); - private: - /** Parse the access address to pass on to device */ - void parseAddr(const Addr &addr, Addr &offset, IdeChannel &channel, - IdeRegType ®_type); + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); - /** Select the disk based on the channel and device bit */ - int getDisk(IdeChannel channel); + } primary, secondary; - /** Select the disk based on a pointer */ - int getDisk(IdeDisk *diskPtr); + /** Bus master interface (BMI) registers */ + Addr bmiAddr, bmiSize; - public: - /** See if a disk is selected based on its pointer */ - bool isDiskSelected(IdeDisk *diskPtr); + /** Registers used in device specific PCI configuration */ + uint16_t primaryTiming, secondaryTiming; + uint8_t deviceTiming; + uint8_t udmaControl; + uint16_t udmaTiming; + uint16_t ideConfig; + + // Internal management variables + bool ioEnabled; + bool bmEnabled; + + void dispatchAccess(PacketPtr pkt, bool read); public: typedef IdeControllerParams Params; const Params *params() const { return (const Params *)_params; } IdeController(Params *p); - ~IdeController(); - virtual Tick writeConfig(PacketPtr pkt); - virtual Tick readConfig(PacketPtr pkt); + /** See if a disk is selected based on its pointer */ + bool isDiskSelected(IdeDisk *diskPtr); + + void intrPost(); + + Tick writeConfig(PacketPtr pkt); + Tick readConfig(PacketPtr pkt); void setDmaComplete(IdeDisk *disk); - /** - * Read a done field for a given target. - * @param pkt Packet describing what is to be read - * @return The amount of time to complete this request - */ - virtual Tick read(PacketPtr pkt); - - /** - * Write a done field for a given target. - * @param pkt Packet describing what is to be written - * @return The amount of time to complete this request - */ - virtual Tick write(PacketPtr pkt); - - /** - * Serialize this object to the given output stream. - * @param os The stream to serialize to. - */ - virtual void serialize(std::ostream &os); - - /** - * Reconstruct the state of this object from a checkpoint. - * @param cp The checkpoint use. - * @param section The section name of this object - */ - virtual void unserialize(Checkpoint *cp, const std::string §ion); + Tick read(PacketPtr pkt); + Tick write(PacketPtr pkt); + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); }; #endif // __IDE_CTRL_HH_ diff --git a/src/dev/ide_disk.cc b/src/dev/ide_disk.cc index 9022cf087..83faf508e 100644 --- a/src/dev/ide_disk.cc +++ b/src/dev/ide_disk.cc @@ -177,7 +177,7 @@ Addr IdeDisk::pciToDma(Addr pciAddr) { if (ctrl) - return ctrl->plat->pciToDma(pciAddr); + return ctrl->pciToDma(pciAddr); else panic("Access to unset controller!\n"); } @@ -187,120 +187,127 @@ IdeDisk::pciToDma(Addr pciAddr) //// void -IdeDisk::read(const Addr &offset, IdeRegType reg_type, uint8_t *data) +IdeDisk::readCommand(const Addr offset, int size, uint8_t *data) { - DevAction_t action = ACT_NONE; - - switch (reg_type) { - case COMMAND_BLOCK: - switch (offset) { - // Data transfers occur two bytes at a time - case DATA_OFFSET: - *(uint16_t*)data = cmdReg.data; - action = ACT_DATA_READ_SHORT; - break; - case ERROR_OFFSET: - *data = cmdReg.error; - break; - case NSECTOR_OFFSET: - *data = cmdReg.sec_count; - break; - case SECTOR_OFFSET: - *data = cmdReg.sec_num; - break; - case LCYL_OFFSET: - *data = cmdReg.cyl_low; - break; - case HCYL_OFFSET: - *data = cmdReg.cyl_high; - break; - case DRIVE_OFFSET: - *data = cmdReg.drive; - break; - case STATUS_OFFSET: - *data = status; - action = ACT_STAT_READ; - break; - default: - panic("Invalid IDE command register offset: %#x\n", offset); + if (offset == DATA_OFFSET) { + if (size == sizeof(uint16_t)) { + *(uint16_t *)data = cmdReg.data; + } else if (size == sizeof(uint32_t)) { + *(uint16_t *)data = cmdReg.data; + updateState(ACT_DATA_READ_SHORT); + *((uint16_t *)data + 1) = cmdReg.data; + } else { + panic("Data read of unsupported size %d.\n", size); } + updateState(ACT_DATA_READ_SHORT); + return; + } + assert(size == sizeof(uint8_t)); + switch (offset) { + case ERROR_OFFSET: + *data = cmdReg.error; break; - case CONTROL_BLOCK: - if (offset == ALTSTAT_OFFSET) - *data = status; - else - panic("Invalid IDE control register offset: %#x\n", offset); + case NSECTOR_OFFSET: + *data = cmdReg.sec_count; + break; + case SECTOR_OFFSET: + *data = cmdReg.sec_num; + break; + case LCYL_OFFSET: + *data = cmdReg.cyl_low; + break; + case HCYL_OFFSET: + *data = cmdReg.cyl_high; + break; + case DRIVE_OFFSET: + *data = cmdReg.drive; + break; + case STATUS_OFFSET: + *data = status; + updateState(ACT_STAT_READ); break; default: - panic("Unknown register block!\n"); + panic("Invalid IDE command register offset: %#x\n", offset); } - DPRINTF(IdeDisk, "Read to disk at offset: %#x data %#x\n", offset, - (uint32_t)*data); - - if (action != ACT_NONE) - updateState(action); + DPRINTF(IdeDisk, "Read to disk at offset: %#x data %#x\n", offset, *data); } void -IdeDisk::write(const Addr &offset, IdeRegType reg_type, const uint8_t *data) +IdeDisk::readControl(const Addr offset, int size, uint8_t *data) { - DevAction_t action = ACT_NONE; + assert(size == sizeof(uint8_t)); + *data = status; + if (offset != ALTSTAT_OFFSET) + panic("Invalid IDE control register offset: %#x\n", offset); + DPRINTF(IdeDisk, "Read to disk at offset: %#x data %#x\n", offset, *data); +} - switch (reg_type) { - case COMMAND_BLOCK: - switch (offset) { - case DATA_OFFSET: - cmdReg.data = *(uint16_t*)data; - action = ACT_DATA_WRITE_SHORT; - break; - case FEATURES_OFFSET: - break; - case NSECTOR_OFFSET: - cmdReg.sec_count = *data; - break; - case SECTOR_OFFSET: - cmdReg.sec_num = *data; - break; - case LCYL_OFFSET: - cmdReg.cyl_low = *data; - break; - case HCYL_OFFSET: - cmdReg.cyl_high = *data; - break; - case DRIVE_OFFSET: - cmdReg.drive = *data; - action = ACT_SELECT_WRITE; - break; - case COMMAND_OFFSET: - cmdReg.command = *data; - action = ACT_CMD_WRITE; - break; - default: - panic("Invalid IDE command register offset: %#x\n", offset); +void +IdeDisk::writeCommand(const Addr offset, int size, const uint8_t *data) +{ + if (offset == DATA_OFFSET) { + if (size == sizeof(uint16_t)) { + cmdReg.data = *(const uint16_t *)data; + } else if (size == sizeof(uint32_t)) { + cmdReg.data = *(const uint16_t *)data; + updateState(ACT_DATA_WRITE_SHORT); + cmdReg.data = *((const uint16_t *)data + 1); + } else { + panic("Data write of unsupported size %d.\n", size); } + updateState(ACT_DATA_WRITE_SHORT); + return; + } + + assert(size == sizeof(uint8_t)); + switch (offset) { + case FEATURES_OFFSET: break; - case CONTROL_BLOCK: - if (offset == CONTROL_OFFSET) { - if (*data & CONTROL_RST_BIT) { - // force the device into the reset state - devState = Device_Srst; - action = ACT_SRST_SET; - } else if (devState == Device_Srst && !(*data & CONTROL_RST_BIT)) - action = ACT_SRST_CLEAR; - - nIENBit = (*data & CONTROL_IEN_BIT) ? true : false; - } - else - panic("Invalid IDE control register offset: %#x\n", offset); + case NSECTOR_OFFSET: + cmdReg.sec_count = *data; + break; + case SECTOR_OFFSET: + cmdReg.sec_num = *data; + break; + case LCYL_OFFSET: + cmdReg.cyl_low = *data; + break; + case HCYL_OFFSET: + cmdReg.cyl_high = *data; + break; + case DRIVE_OFFSET: + cmdReg.drive = *data; + updateState(ACT_SELECT_WRITE); + break; + case COMMAND_OFFSET: + cmdReg.command = *data; + updateState(ACT_CMD_WRITE); break; default: - panic("Unknown register block!\n"); + panic("Invalid IDE command register offset: %#x\n", offset); } + DPRINTF(IdeDisk, "Write to disk at offset: %#x data %#x\n", offset, + (uint32_t)*data); +} + +void +IdeDisk::writeControl(const Addr offset, int size, const uint8_t *data) +{ + if (offset != CONTROL_OFFSET) + panic("Invalid IDE control register offset: %#x\n", offset); + + if (*data & CONTROL_RST_BIT) { + // force the device into the reset state + devState = Device_Srst; + updateState(ACT_SRST_SET); + } else if (devState == Device_Srst && !(*data & CONTROL_RST_BIT)) { + updateState(ACT_SRST_CLEAR); + } + + nIENBit = *data & CONTROL_IEN_BIT; DPRINTF(IdeDisk, "Write to disk at offset: %#x data %#x\n", offset, (uint32_t)*data); - if (action != ACT_NONE) - updateState(action); } //// @@ -683,7 +690,6 @@ IdeDisk::intrPost() // talk to controller to set interrupt if (ctrl) { - ctrl->bmi_regs.bmis0 |= IDEINTS; ctrl->intrPost(); } } diff --git a/src/dev/ide_disk.hh b/src/dev/ide_disk.hh index 62c89add4..68ae5c3c0 100644 --- a/src/dev/ide_disk.hh +++ b/src/dev/ide_disk.hh @@ -278,8 +278,10 @@ class IdeDisk : public SimObject } // Device register read/write - void read(const Addr &offset, IdeRegType regtype, uint8_t *data); - void write(const Addr &offset, IdeRegType regtype, const uint8_t *data); + void readCommand(const Addr offset, int size, uint8_t *data); + void readControl(const Addr offset, int size, uint8_t *data); + void writeCommand(const Addr offset, int size, const uint8_t *data); + void writeControl(const Addr offset, int size, const uint8_t *data); // Start/abort functions void startDma(const uint32_t &prdTableBase); -- cgit v1.2.3 From 19273164da50011d59b7f362026f8e80260807d4 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 8 Dec 2008 07:16:40 -0800 Subject: output: Change default output directory and files and update tests. --HG-- rename : tests/long/00.gzip/ref/alpha/tru64/o3-timing/stderr => tests/long/00.gzip/ref/alpha/tru64/o3-timing/simerr rename : tests/long/00.gzip/ref/alpha/tru64/o3-timing/stdout => tests/long/00.gzip/ref/alpha/tru64/o3-timing/simout rename : tests/long/00.gzip/ref/alpha/tru64/o3-timing/m5stats.txt => tests/long/00.gzip/ref/alpha/tru64/o3-timing/stats.txt rename : tests/long/00.gzip/ref/alpha/tru64/simple-atomic/stderr => tests/long/00.gzip/ref/alpha/tru64/simple-atomic/simerr rename : tests/long/00.gzip/ref/alpha/tru64/simple-atomic/stdout => tests/long/00.gzip/ref/alpha/tru64/simple-atomic/simout rename : tests/long/00.gzip/ref/alpha/tru64/simple-atomic/m5stats.txt => tests/long/00.gzip/ref/alpha/tru64/simple-atomic/stats.txt rename : tests/long/00.gzip/ref/alpha/tru64/simple-timing/stderr => tests/long/00.gzip/ref/alpha/tru64/simple-timing/simerr rename : tests/long/00.gzip/ref/alpha/tru64/simple-timing/stdout => tests/long/00.gzip/ref/alpha/tru64/simple-timing/simout rename : tests/long/00.gzip/ref/alpha/tru64/simple-timing/m5stats.txt => tests/long/00.gzip/ref/alpha/tru64/simple-timing/stats.txt rename : tests/long/00.gzip/ref/sparc/linux/o3-timing/stderr => tests/long/00.gzip/ref/sparc/linux/o3-timing/simerr rename : tests/long/00.gzip/ref/sparc/linux/o3-timing/stdout => tests/long/00.gzip/ref/sparc/linux/o3-timing/simout rename : tests/long/00.gzip/ref/sparc/linux/o3-timing/m5stats.txt => tests/long/00.gzip/ref/sparc/linux/o3-timing/stats.txt rename : tests/long/00.gzip/ref/sparc/linux/simple-atomic/stderr => tests/long/00.gzip/ref/sparc/linux/simple-atomic/simerr rename : tests/long/00.gzip/ref/sparc/linux/simple-atomic/stdout => tests/long/00.gzip/ref/sparc/linux/simple-atomic/simout rename : tests/long/00.gzip/ref/sparc/linux/simple-atomic/m5stats.txt => tests/long/00.gzip/ref/sparc/linux/simple-atomic/stats.txt rename : tests/long/00.gzip/ref/sparc/linux/simple-timing/stderr => tests/long/00.gzip/ref/sparc/linux/simple-timing/simerr rename : tests/long/00.gzip/ref/sparc/linux/simple-timing/stdout => tests/long/00.gzip/ref/sparc/linux/simple-timing/simout rename : tests/long/00.gzip/ref/sparc/linux/simple-timing/m5stats.txt => tests/long/00.gzip/ref/sparc/linux/simple-timing/stats.txt rename : tests/long/00.gzip/ref/x86/linux/simple-atomic/stderr => tests/long/00.gzip/ref/x86/linux/simple-atomic/simerr rename : tests/long/00.gzip/ref/x86/linux/simple-atomic/stdout => tests/long/00.gzip/ref/x86/linux/simple-atomic/simout rename : tests/long/00.gzip/ref/x86/linux/simple-atomic/m5stats.txt => tests/long/00.gzip/ref/x86/linux/simple-atomic/stats.txt rename : tests/long/00.gzip/ref/x86/linux/simple-timing/stderr => tests/long/00.gzip/ref/x86/linux/simple-timing/simerr rename : tests/long/00.gzip/ref/x86/linux/simple-timing/stdout => tests/long/00.gzip/ref/x86/linux/simple-timing/simout rename : tests/long/00.gzip/ref/x86/linux/simple-timing/m5stats.txt => tests/long/00.gzip/ref/x86/linux/simple-timing/stats.txt rename : tests/long/10.linux-boot/ref/alpha/linux/tsunami-o3-dual/stderr => tests/long/10.linux-boot/ref/alpha/linux/tsunami-o3-dual/simerr rename : tests/long/10.linux-boot/ref/alpha/linux/tsunami-o3-dual/stdout => tests/long/10.linux-boot/ref/alpha/linux/tsunami-o3-dual/simout rename : tests/long/10.linux-boot/ref/alpha/linux/tsunami-o3-dual/m5stats.txt => tests/long/10.linux-boot/ref/alpha/linux/tsunami-o3-dual/stats.txt rename : tests/long/10.linux-boot/ref/alpha/linux/tsunami-o3/stderr => tests/long/10.linux-boot/ref/alpha/linux/tsunami-o3/simerr rename : tests/long/10.linux-boot/ref/alpha/linux/tsunami-o3/stdout => tests/long/10.linux-boot/ref/alpha/linux/tsunami-o3/simout rename : tests/long/10.linux-boot/ref/alpha/linux/tsunami-o3/m5stats.txt => tests/long/10.linux-boot/ref/alpha/linux/tsunami-o3/stats.txt rename : tests/long/10.mcf/ref/sparc/linux/simple-atomic/stderr => tests/long/10.mcf/ref/sparc/linux/simple-atomic/simerr rename : tests/long/10.mcf/ref/sparc/linux/simple-atomic/stdout => tests/long/10.mcf/ref/sparc/linux/simple-atomic/simout rename : tests/long/10.mcf/ref/sparc/linux/simple-atomic/m5stats.txt => tests/long/10.mcf/ref/sparc/linux/simple-atomic/stats.txt rename : tests/long/10.mcf/ref/sparc/linux/simple-timing/stderr => tests/long/10.mcf/ref/sparc/linux/simple-timing/simerr rename : tests/long/10.mcf/ref/sparc/linux/simple-timing/stdout => tests/long/10.mcf/ref/sparc/linux/simple-timing/simout rename : tests/long/10.mcf/ref/sparc/linux/simple-timing/m5stats.txt => tests/long/10.mcf/ref/sparc/linux/simple-timing/stats.txt rename : tests/long/10.mcf/ref/x86/linux/simple-atomic/stderr => tests/long/10.mcf/ref/x86/linux/simple-atomic/simerr rename : tests/long/10.mcf/ref/x86/linux/simple-atomic/stdout => tests/long/10.mcf/ref/x86/linux/simple-atomic/simout rename : tests/long/10.mcf/ref/x86/linux/simple-atomic/m5stats.txt => tests/long/10.mcf/ref/x86/linux/simple-atomic/stats.txt rename : tests/long/10.mcf/ref/x86/linux/simple-timing/stderr => tests/long/10.mcf/ref/x86/linux/simple-timing/simerr rename : tests/long/10.mcf/ref/x86/linux/simple-timing/stdout => tests/long/10.mcf/ref/x86/linux/simple-timing/simout rename : tests/long/10.mcf/ref/x86/linux/simple-timing/m5stats.txt => tests/long/10.mcf/ref/x86/linux/simple-timing/stats.txt rename : tests/long/20.parser/ref/x86/linux/simple-atomic/stderr => tests/long/20.parser/ref/x86/linux/simple-atomic/simerr rename : tests/long/20.parser/ref/x86/linux/simple-atomic/stdout => tests/long/20.parser/ref/x86/linux/simple-atomic/simout rename : tests/long/20.parser/ref/x86/linux/simple-atomic/m5stats.txt => tests/long/20.parser/ref/x86/linux/simple-atomic/stats.txt rename : tests/long/20.parser/ref/x86/linux/simple-timing/stderr => tests/long/20.parser/ref/x86/linux/simple-timing/simerr rename : tests/long/20.parser/ref/x86/linux/simple-timing/stdout => tests/long/20.parser/ref/x86/linux/simple-timing/simout rename : tests/long/20.parser/ref/x86/linux/simple-timing/m5stats.txt => tests/long/20.parser/ref/x86/linux/simple-timing/stats.txt rename : tests/long/30.eon/ref/alpha/tru64/o3-timing/stderr => tests/long/30.eon/ref/alpha/tru64/o3-timing/simerr rename : tests/long/30.eon/ref/alpha/tru64/o3-timing/stdout => tests/long/30.eon/ref/alpha/tru64/o3-timing/simout rename : tests/long/30.eon/ref/alpha/tru64/o3-timing/m5stats.txt => tests/long/30.eon/ref/alpha/tru64/o3-timing/stats.txt rename : tests/long/30.eon/ref/alpha/tru64/simple-atomic/stderr => tests/long/30.eon/ref/alpha/tru64/simple-atomic/simerr rename : tests/long/30.eon/ref/alpha/tru64/simple-atomic/stdout => tests/long/30.eon/ref/alpha/tru64/simple-atomic/simout rename : tests/long/30.eon/ref/alpha/tru64/simple-atomic/m5stats.txt => tests/long/30.eon/ref/alpha/tru64/simple-atomic/stats.txt rename : tests/long/30.eon/ref/alpha/tru64/simple-timing/stderr => tests/long/30.eon/ref/alpha/tru64/simple-timing/simerr rename : tests/long/30.eon/ref/alpha/tru64/simple-timing/stdout => tests/long/30.eon/ref/alpha/tru64/simple-timing/simout rename : tests/long/30.eon/ref/alpha/tru64/simple-timing/m5stats.txt => tests/long/30.eon/ref/alpha/tru64/simple-timing/stats.txt rename : tests/long/40.perlbmk/ref/alpha/tru64/o3-timing/stderr => tests/long/40.perlbmk/ref/alpha/tru64/o3-timing/simerr rename : tests/long/40.perlbmk/ref/alpha/tru64/o3-timing/stdout => tests/long/40.perlbmk/ref/alpha/tru64/o3-timing/simout rename : tests/long/40.perlbmk/ref/alpha/tru64/o3-timing/m5stats.txt => tests/long/40.perlbmk/ref/alpha/tru64/o3-timing/stats.txt rename : tests/long/40.perlbmk/ref/alpha/tru64/simple-atomic/stderr => tests/long/40.perlbmk/ref/alpha/tru64/simple-atomic/simerr rename : tests/long/40.perlbmk/ref/alpha/tru64/simple-atomic/stdout => tests/long/40.perlbmk/ref/alpha/tru64/simple-atomic/simout rename : tests/long/40.perlbmk/ref/alpha/tru64/simple-atomic/m5stats.txt => tests/long/40.perlbmk/ref/alpha/tru64/simple-atomic/stats.txt rename : tests/long/40.perlbmk/ref/alpha/tru64/simple-timing/stderr => tests/long/40.perlbmk/ref/alpha/tru64/simple-timing/simerr rename : tests/long/40.perlbmk/ref/alpha/tru64/simple-timing/stdout => tests/long/40.perlbmk/ref/alpha/tru64/simple-timing/simout rename : tests/long/40.perlbmk/ref/alpha/tru64/simple-timing/m5stats.txt => tests/long/40.perlbmk/ref/alpha/tru64/simple-timing/stats.txt rename : tests/long/50.vortex/ref/alpha/tru64/o3-timing/stderr => tests/long/50.vortex/ref/alpha/tru64/o3-timing/simerr rename : tests/long/50.vortex/ref/alpha/tru64/o3-timing/stdout => tests/long/50.vortex/ref/alpha/tru64/o3-timing/simout rename : tests/long/50.vortex/ref/alpha/tru64/o3-timing/m5stats.txt => tests/long/50.vortex/ref/alpha/tru64/o3-timing/stats.txt rename : tests/long/50.vortex/ref/alpha/tru64/simple-atomic/stderr => tests/long/50.vortex/ref/alpha/tru64/simple-atomic/simerr rename : tests/long/50.vortex/ref/alpha/tru64/simple-atomic/stdout => tests/long/50.vortex/ref/alpha/tru64/simple-atomic/simout rename : tests/long/50.vortex/ref/alpha/tru64/simple-atomic/m5stats.txt => tests/long/50.vortex/ref/alpha/tru64/simple-atomic/stats.txt rename : tests/long/50.vortex/ref/alpha/tru64/simple-timing/stderr => tests/long/50.vortex/ref/alpha/tru64/simple-timing/simerr rename : tests/long/50.vortex/ref/alpha/tru64/simple-timing/stdout => tests/long/50.vortex/ref/alpha/tru64/simple-timing/simout rename : tests/long/50.vortex/ref/alpha/tru64/simple-timing/m5stats.txt => tests/long/50.vortex/ref/alpha/tru64/simple-timing/stats.txt rename : tests/long/50.vortex/ref/sparc/linux/simple-atomic/stderr => tests/long/50.vortex/ref/sparc/linux/simple-atomic/simerr rename : tests/long/50.vortex/ref/sparc/linux/simple-atomic/stdout => tests/long/50.vortex/ref/sparc/linux/simple-atomic/simout rename : tests/long/50.vortex/ref/sparc/linux/simple-atomic/m5stats.txt => tests/long/50.vortex/ref/sparc/linux/simple-atomic/stats.txt rename : tests/long/50.vortex/ref/sparc/linux/simple-timing/stderr => tests/long/50.vortex/ref/sparc/linux/simple-timing/simerr rename : tests/long/50.vortex/ref/sparc/linux/simple-timing/stdout => tests/long/50.vortex/ref/sparc/linux/simple-timing/simout rename : tests/long/50.vortex/ref/sparc/linux/simple-timing/m5stats.txt => tests/long/50.vortex/ref/sparc/linux/simple-timing/stats.txt rename : tests/long/60.bzip2/ref/alpha/tru64/o3-timing/stderr => tests/long/60.bzip2/ref/alpha/tru64/o3-timing/simerr rename : tests/long/60.bzip2/ref/alpha/tru64/o3-timing/stdout => tests/long/60.bzip2/ref/alpha/tru64/o3-timing/simout rename : tests/long/60.bzip2/ref/alpha/tru64/o3-timing/m5stats.txt => tests/long/60.bzip2/ref/alpha/tru64/o3-timing/stats.txt rename : tests/long/60.bzip2/ref/alpha/tru64/simple-atomic/stderr => tests/long/60.bzip2/ref/alpha/tru64/simple-atomic/simerr rename : tests/long/60.bzip2/ref/alpha/tru64/simple-atomic/stdout => tests/long/60.bzip2/ref/alpha/tru64/simple-atomic/simout rename : tests/long/60.bzip2/ref/alpha/tru64/simple-atomic/m5stats.txt => tests/long/60.bzip2/ref/alpha/tru64/simple-atomic/stats.txt rename : tests/long/60.bzip2/ref/alpha/tru64/simple-timing/stderr => tests/long/60.bzip2/ref/alpha/tru64/simple-timing/simerr rename : tests/long/60.bzip2/ref/alpha/tru64/simple-timing/stdout => tests/long/60.bzip2/ref/alpha/tru64/simple-timing/simout rename : tests/long/60.bzip2/ref/alpha/tru64/simple-timing/m5stats.txt => tests/long/60.bzip2/ref/alpha/tru64/simple-timing/stats.txt rename : tests/long/60.bzip2/ref/x86/linux/simple-atomic/stderr => tests/long/60.bzip2/ref/x86/linux/simple-atomic/simerr rename : tests/long/60.bzip2/ref/x86/linux/simple-atomic/stdout => tests/long/60.bzip2/ref/x86/linux/simple-atomic/simout rename : tests/long/60.bzip2/ref/x86/linux/simple-atomic/m5stats.txt => tests/long/60.bzip2/ref/x86/linux/simple-atomic/stats.txt rename : tests/long/60.bzip2/ref/x86/linux/simple-timing/stderr => tests/long/60.bzip2/ref/x86/linux/simple-timing/simerr rename : tests/long/60.bzip2/ref/x86/linux/simple-timing/stdout => tests/long/60.bzip2/ref/x86/linux/simple-timing/simout rename : tests/long/60.bzip2/ref/x86/linux/simple-timing/m5stats.txt => tests/long/60.bzip2/ref/x86/linux/simple-timing/stats.txt rename : tests/long/70.twolf/ref/alpha/tru64/o3-timing/stderr => tests/long/70.twolf/ref/alpha/tru64/o3-timing/simerr rename : tests/long/70.twolf/ref/alpha/tru64/o3-timing/stdout => tests/long/70.twolf/ref/alpha/tru64/o3-timing/simout rename : tests/long/70.twolf/ref/alpha/tru64/o3-timing/m5stats.txt => tests/long/70.twolf/ref/alpha/tru64/o3-timing/stats.txt rename : tests/long/70.twolf/ref/alpha/tru64/simple-atomic/stderr => tests/long/70.twolf/ref/alpha/tru64/simple-atomic/simerr rename : tests/long/70.twolf/ref/alpha/tru64/simple-atomic/stdout => tests/long/70.twolf/ref/alpha/tru64/simple-atomic/simout rename : tests/long/70.twolf/ref/alpha/tru64/simple-atomic/m5stats.txt => tests/long/70.twolf/ref/alpha/tru64/simple-atomic/stats.txt rename : tests/long/70.twolf/ref/alpha/tru64/simple-timing/stderr => tests/long/70.twolf/ref/alpha/tru64/simple-timing/simerr rename : tests/long/70.twolf/ref/alpha/tru64/simple-timing/stdout => tests/long/70.twolf/ref/alpha/tru64/simple-timing/simout rename : tests/long/70.twolf/ref/alpha/tru64/simple-timing/m5stats.txt => tests/long/70.twolf/ref/alpha/tru64/simple-timing/stats.txt rename : tests/long/70.twolf/ref/sparc/linux/simple-atomic/stderr => tests/long/70.twolf/ref/sparc/linux/simple-atomic/simerr rename : tests/long/70.twolf/ref/sparc/linux/simple-atomic/stdout => tests/long/70.twolf/ref/sparc/linux/simple-atomic/simout rename : tests/long/70.twolf/ref/sparc/linux/simple-atomic/m5stats.txt => tests/long/70.twolf/ref/sparc/linux/simple-atomic/stats.txt rename : tests/long/70.twolf/ref/sparc/linux/simple-timing/stderr => tests/long/70.twolf/ref/sparc/linux/simple-timing/simerr rename : tests/long/70.twolf/ref/sparc/linux/simple-timing/stdout => tests/long/70.twolf/ref/sparc/linux/simple-timing/simout rename : tests/long/70.twolf/ref/sparc/linux/simple-timing/m5stats.txt => tests/long/70.twolf/ref/sparc/linux/simple-timing/stats.txt rename : tests/long/70.twolf/ref/x86/linux/simple-atomic/stderr => tests/long/70.twolf/ref/x86/linux/simple-atomic/simerr rename : tests/long/70.twolf/ref/x86/linux/simple-atomic/stdout => tests/long/70.twolf/ref/x86/linux/simple-atomic/simout rename : tests/long/70.twolf/ref/x86/linux/simple-atomic/m5stats.txt => tests/long/70.twolf/ref/x86/linux/simple-atomic/stats.txt rename : tests/long/70.twolf/ref/x86/linux/simple-timing/stderr => tests/long/70.twolf/ref/x86/linux/simple-timing/simerr rename : tests/long/70.twolf/ref/x86/linux/simple-timing/stdout => tests/long/70.twolf/ref/x86/linux/simple-timing/simout rename : tests/long/70.twolf/ref/x86/linux/simple-timing/m5stats.txt => tests/long/70.twolf/ref/x86/linux/simple-timing/stats.txt rename : tests/long/80.solaris-boot/ref/sparc/solaris/t1000-simple-atomic/stderr => tests/long/80.solaris-boot/ref/sparc/solaris/t1000-simple-atomic/simerr rename : tests/long/80.solaris-boot/ref/sparc/solaris/t1000-simple-atomic/stdout => tests/long/80.solaris-boot/ref/sparc/solaris/t1000-simple-atomic/simout rename : tests/long/80.solaris-boot/ref/sparc/solaris/t1000-simple-atomic/m5stats.txt => tests/long/80.solaris-boot/ref/sparc/solaris/t1000-simple-atomic/stats.txt rename : tests/quick/00.hello/ref/alpha/linux/o3-timing/stderr => tests/quick/00.hello/ref/alpha/linux/o3-timing/simerr rename : tests/quick/00.hello/ref/alpha/linux/o3-timing/stdout => tests/quick/00.hello/ref/alpha/linux/o3-timing/simout rename : tests/quick/00.hello/ref/alpha/linux/o3-timing/m5stats.txt => tests/quick/00.hello/ref/alpha/linux/o3-timing/stats.txt rename : tests/quick/00.hello/ref/alpha/linux/simple-atomic/stderr => tests/quick/00.hello/ref/alpha/linux/simple-atomic/simerr rename : tests/quick/00.hello/ref/alpha/linux/simple-atomic/stdout => tests/quick/00.hello/ref/alpha/linux/simple-atomic/simout rename : tests/quick/00.hello/ref/alpha/linux/simple-atomic/m5stats.txt => tests/quick/00.hello/ref/alpha/linux/simple-atomic/stats.txt rename : tests/quick/00.hello/ref/alpha/linux/simple-timing/stderr => tests/quick/00.hello/ref/alpha/linux/simple-timing/simerr rename : tests/quick/00.hello/ref/alpha/linux/simple-timing/stdout => tests/quick/00.hello/ref/alpha/linux/simple-timing/simout rename : tests/quick/00.hello/ref/alpha/linux/simple-timing/m5stats.txt => tests/quick/00.hello/ref/alpha/linux/simple-timing/stats.txt rename : tests/quick/00.hello/ref/alpha/tru64/o3-timing/stderr => tests/quick/00.hello/ref/alpha/tru64/o3-timing/simerr rename : tests/quick/00.hello/ref/alpha/tru64/o3-timing/stdout => tests/quick/00.hello/ref/alpha/tru64/o3-timing/simout rename : tests/quick/00.hello/ref/alpha/tru64/o3-timing/m5stats.txt => tests/quick/00.hello/ref/alpha/tru64/o3-timing/stats.txt rename : tests/quick/00.hello/ref/alpha/tru64/simple-atomic/stderr => tests/quick/00.hello/ref/alpha/tru64/simple-atomic/simerr rename : tests/quick/00.hello/ref/alpha/tru64/simple-atomic/stdout => tests/quick/00.hello/ref/alpha/tru64/simple-atomic/simout rename : tests/quick/00.hello/ref/alpha/tru64/simple-atomic/m5stats.txt => tests/quick/00.hello/ref/alpha/tru64/simple-atomic/stats.txt rename : tests/quick/00.hello/ref/alpha/tru64/simple-timing/stderr => tests/quick/00.hello/ref/alpha/tru64/simple-timing/simerr rename : tests/quick/00.hello/ref/alpha/tru64/simple-timing/stdout => tests/quick/00.hello/ref/alpha/tru64/simple-timing/simout rename : tests/quick/00.hello/ref/alpha/tru64/simple-timing/m5stats.txt => tests/quick/00.hello/ref/alpha/tru64/simple-timing/stats.txt rename : tests/quick/00.hello/ref/mips/linux/simple-atomic/stderr => tests/quick/00.hello/ref/mips/linux/simple-atomic/simerr rename : tests/quick/00.hello/ref/mips/linux/simple-atomic/stdout => tests/quick/00.hello/ref/mips/linux/simple-atomic/simout rename : tests/quick/00.hello/ref/mips/linux/simple-atomic/m5stats.txt => tests/quick/00.hello/ref/mips/linux/simple-atomic/stats.txt rename : tests/quick/00.hello/ref/mips/linux/simple-timing/stderr => tests/quick/00.hello/ref/mips/linux/simple-timing/simerr rename : tests/quick/00.hello/ref/mips/linux/simple-timing/stdout => tests/quick/00.hello/ref/mips/linux/simple-timing/simout rename : tests/quick/00.hello/ref/mips/linux/simple-timing/m5stats.txt => tests/quick/00.hello/ref/mips/linux/simple-timing/stats.txt rename : tests/quick/00.hello/ref/sparc/linux/simple-atomic/stderr => tests/quick/00.hello/ref/sparc/linux/simple-atomic/simerr rename : tests/quick/00.hello/ref/sparc/linux/simple-atomic/stdout => tests/quick/00.hello/ref/sparc/linux/simple-atomic/simout rename : tests/quick/00.hello/ref/sparc/linux/simple-atomic/m5stats.txt => tests/quick/00.hello/ref/sparc/linux/simple-atomic/stats.txt rename : tests/quick/00.hello/ref/sparc/linux/simple-timing/stderr => tests/quick/00.hello/ref/sparc/linux/simple-timing/simerr rename : tests/quick/00.hello/ref/sparc/linux/simple-timing/stdout => tests/quick/00.hello/ref/sparc/linux/simple-timing/simout rename : tests/quick/00.hello/ref/sparc/linux/simple-timing/m5stats.txt => tests/quick/00.hello/ref/sparc/linux/simple-timing/stats.txt rename : tests/quick/00.hello/ref/x86/linux/simple-atomic/stderr => tests/quick/00.hello/ref/x86/linux/simple-atomic/simerr rename : tests/quick/00.hello/ref/x86/linux/simple-atomic/stdout => tests/quick/00.hello/ref/x86/linux/simple-atomic/simout rename : tests/quick/00.hello/ref/x86/linux/simple-atomic/m5stats.txt => tests/quick/00.hello/ref/x86/linux/simple-atomic/stats.txt rename : tests/quick/00.hello/ref/x86/linux/simple-timing/stderr => tests/quick/00.hello/ref/x86/linux/simple-timing/simerr rename : tests/quick/00.hello/ref/x86/linux/simple-timing/stdout => tests/quick/00.hello/ref/x86/linux/simple-timing/simout rename : tests/quick/00.hello/ref/x86/linux/simple-timing/m5stats.txt => tests/quick/00.hello/ref/x86/linux/simple-timing/stats.txt rename : tests/quick/01.hello-2T-smt/ref/alpha/linux/o3-timing/stderr => tests/quick/01.hello-2T-smt/ref/alpha/linux/o3-timing/simerr rename : tests/quick/01.hello-2T-smt/ref/alpha/linux/o3-timing/stdout => tests/quick/01.hello-2T-smt/ref/alpha/linux/o3-timing/simout rename : tests/quick/01.hello-2T-smt/ref/alpha/linux/o3-timing/m5stats.txt => tests/quick/01.hello-2T-smt/ref/alpha/linux/o3-timing/stats.txt rename : tests/quick/02.insttest/ref/sparc/linux/o3-timing/stderr => tests/quick/02.insttest/ref/sparc/linux/o3-timing/simerr rename : tests/quick/02.insttest/ref/sparc/linux/o3-timing/stdout => tests/quick/02.insttest/ref/sparc/linux/o3-timing/simout rename : tests/quick/02.insttest/ref/sparc/linux/o3-timing/m5stats.txt => tests/quick/02.insttest/ref/sparc/linux/o3-timing/stats.txt rename : tests/quick/02.insttest/ref/sparc/linux/simple-atomic/stderr => tests/quick/02.insttest/ref/sparc/linux/simple-atomic/simerr rename : tests/quick/02.insttest/ref/sparc/linux/simple-atomic/stdout => tests/quick/02.insttest/ref/sparc/linux/simple-atomic/simout rename : tests/quick/02.insttest/ref/sparc/linux/simple-atomic/m5stats.txt => tests/quick/02.insttest/ref/sparc/linux/simple-atomic/stats.txt rename : tests/quick/02.insttest/ref/sparc/linux/simple-timing/stderr => tests/quick/02.insttest/ref/sparc/linux/simple-timing/simerr rename : tests/quick/02.insttest/ref/sparc/linux/simple-timing/stdout => tests/quick/02.insttest/ref/sparc/linux/simple-timing/simout rename : tests/quick/02.insttest/ref/sparc/linux/simple-timing/m5stats.txt => tests/quick/02.insttest/ref/sparc/linux/simple-timing/stats.txt rename : tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-atomic-dual/stderr => tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-atomic-dual/simerr rename : tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-atomic-dual/stdout => tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-atomic-dual/simout rename : tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-atomic-dual/m5stats.txt => tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-atomic-dual/stats.txt rename : tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-atomic/stderr => tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-atomic/simerr rename : tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-atomic/stdout => tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-atomic/simout rename : tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-atomic/m5stats.txt => tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-atomic/stats.txt rename : tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-timing-dual/stderr => tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-timing-dual/simerr rename : tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-timing-dual/stdout => tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-timing-dual/simout rename : tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-timing-dual/m5stats.txt => tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-timing-dual/stats.txt rename : tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-timing/stderr => tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-timing/simerr rename : tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-timing/stdout => tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-timing/simout rename : tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-timing/m5stats.txt => tests/quick/10.linux-boot/ref/alpha/linux/tsunami-simple-timing/stats.txt rename : tests/quick/20.eio-short/ref/alpha/eio/detailed/stderr => tests/quick/20.eio-short/ref/alpha/eio/detailed/simerr rename : tests/quick/20.eio-short/ref/alpha/eio/detailed/stdout => tests/quick/20.eio-short/ref/alpha/eio/detailed/simout rename : tests/quick/20.eio-short/ref/alpha/eio/detailed/m5stats.txt => tests/quick/20.eio-short/ref/alpha/eio/detailed/stats.txt rename : tests/quick/20.eio-short/ref/alpha/eio/simple-atomic/stderr => tests/quick/20.eio-short/ref/alpha/eio/simple-atomic/simerr rename : tests/quick/20.eio-short/ref/alpha/eio/simple-atomic/stdout => tests/quick/20.eio-short/ref/alpha/eio/simple-atomic/simout rename : tests/quick/20.eio-short/ref/alpha/eio/simple-atomic/m5stats.txt => tests/quick/20.eio-short/ref/alpha/eio/simple-atomic/stats.txt rename : tests/quick/20.eio-short/ref/alpha/eio/simple-timing/stderr => tests/quick/20.eio-short/ref/alpha/eio/simple-timing/simerr rename : tests/quick/20.eio-short/ref/alpha/eio/simple-timing/stdout => tests/quick/20.eio-short/ref/alpha/eio/simple-timing/simout rename : tests/quick/20.eio-short/ref/alpha/eio/simple-timing/m5stats.txt => tests/quick/20.eio-short/ref/alpha/eio/simple-timing/stats.txt rename : tests/quick/30.eio-mp/ref/alpha/eio/simple-atomic-mp/stderr => tests/quick/30.eio-mp/ref/alpha/eio/simple-atomic-mp/simerr rename : tests/quick/30.eio-mp/ref/alpha/eio/simple-atomic-mp/stdout => tests/quick/30.eio-mp/ref/alpha/eio/simple-atomic-mp/simout rename : tests/quick/30.eio-mp/ref/alpha/eio/simple-atomic-mp/m5stats.txt => tests/quick/30.eio-mp/ref/alpha/eio/simple-atomic-mp/stats.txt rename : tests/quick/30.eio-mp/ref/alpha/eio/simple-timing-mp/stderr => tests/quick/30.eio-mp/ref/alpha/eio/simple-timing-mp/simerr rename : tests/quick/30.eio-mp/ref/alpha/eio/simple-timing-mp/stdout => tests/quick/30.eio-mp/ref/alpha/eio/simple-timing-mp/simout rename : tests/quick/30.eio-mp/ref/alpha/eio/simple-timing-mp/m5stats.txt => tests/quick/30.eio-mp/ref/alpha/eio/simple-timing-mp/stats.txt rename : tests/quick/50.memtest/ref/alpha/linux/memtest/stderr => tests/quick/50.memtest/ref/alpha/linux/memtest/simerr rename : tests/quick/50.memtest/ref/alpha/linux/memtest/stdout => tests/quick/50.memtest/ref/alpha/linux/memtest/simout rename : tests/quick/50.memtest/ref/alpha/linux/memtest/m5stats.txt => tests/quick/50.memtest/ref/alpha/linux/memtest/stats.txt rename : tests/quick/80.netperf-stream/ref/alpha/linux/twosys-tsunami-simple-atomic/stderr => tests/quick/80.netperf-stream/ref/alpha/linux/twosys-tsunami-simple-atomic/simerr rename : tests/quick/80.netperf-stream/ref/alpha/linux/twosys-tsunami-simple-atomic/stdout => tests/quick/80.netperf-stream/ref/alpha/linux/twosys-tsunami-simple-atomic/simout rename : tests/quick/80.netperf-stream/ref/alpha/linux/twosys-tsunami-simple-atomic/m5stats.txt => tests/quick/80.netperf-stream/ref/alpha/linux/twosys-tsunami-simple-atomic/stats.txt --- src/python/m5/main.py | 9 +++++++-- src/python/m5/simulate.py | 7 ++++--- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/python/m5/main.py b/src/python/m5/main.py index d34cca357..4853c8908 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -78,7 +78,7 @@ add_option('-N', "--release-notes", action="store_true", default=False, help="Show the release notes") # Options for configuring the base simulator -add_option('-d', "--outdir", metavar="DIR", default=".", +add_option('-d', "--outdir", metavar="DIR", default="m5out", help="Set the output directory to DIR [Default: %default]") add_option('-r', "--redirect-stdout", action="store_true", default=False, help="Redirect stdout (& stderr, without -e) to file") @@ -101,9 +101,14 @@ add_option('-v', "--verbose", action="count", default=0, # Statistics options set_group("Statistics Options") -add_option("--stats-file", metavar="FILE", default="m5stats.txt", +add_option("--stats-file", metavar="FILE", default="stats.txt", help="Sets the output file for statistics [Default: %default]") +# Configuration Options +set_group("Configuration Options") +add_option("--dump-config", metavar="FILE", default="config.ini", + help="Dump configuration output file [Default: %default]") + # Debugging options set_group("Debugging Options") add_option("--debug-break", metavar="TIME[,TIME]", action='append', split=',', diff --git a/src/python/m5/simulate.py b/src/python/m5/simulate.py index e4dbd5784..617ac3be2 100644 --- a/src/python/m5/simulate.py +++ b/src/python/m5/simulate.py @@ -46,9 +46,10 @@ def instantiate(root): root.unproxy_all() - ini_file = file(os.path.join(options.outdir, 'config.ini'), 'w') - root.print_ini(ini_file) - ini_file.close() # close config.ini + if options.dump_config: + ini_file = file(os.path.join(options.outdir, options.dump_config), 'w') + root.print_ini(ini_file) + ini_file.close() # Initialize the global statistics internal.stats.initSimStats() -- cgit v1.2.3 From d0c0c25ebc082576d29257c51e4aee96b378f0c6 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 8 Dec 2008 07:17:48 -0800 Subject: eventq: Add some debugging code to the eventq. --- src/sim/eventq.cc | 1 + src/sim/eventq.hh | 13 +++++++++++++ 2 files changed, 14 insertions(+) (limited to 'src') diff --git a/src/sim/eventq.cc b/src/sim/eventq.cc index f3d0eb461..d1f84fcb2 100644 --- a/src/sim/eventq.cc +++ b/src/sim/eventq.cc @@ -59,6 +59,7 @@ Counter Event::instanceCounter = 0; Event::~Event() { + assert(!scheduled()); } const std::string diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index a29942d07..33bb34252 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -77,6 +77,9 @@ class Event : public Serializable, public FastAlloc static const FlagsType AutoSerialize = 0x0008; static const FlagsType IsExitEvent = 0x0010; static const FlagsType IsMainQueue = 0x0020; +#ifdef EVENTQ_DEBUG + static const FlagsType Initialized = 0xf000; +#endif private: // The event queue is now a linked list of linked lists. The @@ -245,6 +248,7 @@ class Event : public Serializable, public FastAlloc queue = NULL; #endif #ifdef EVENTQ_DEBUG + flags.set(Initialized); whenCreated = curTick; whenScheduled = 0; #endif @@ -469,6 +473,9 @@ EventQueue::schedule(Event *event, Tick when) { assert(when >= curTick); assert(!event->scheduled()); +#ifdef EVENTQ_DEBUG + assert((event->flags & Event::Initialized) == Event::Initialized); +#endif event->setWhen(when, this); insert(event); @@ -486,6 +493,9 @@ inline void EventQueue::deschedule(Event *event) { assert(event->scheduled()); +#ifdef EVENTQ_DEBUG + assert((event->flags & Event::Initialized) == Event::Initialized); +#endif remove(event); @@ -504,6 +514,9 @@ EventQueue::reschedule(Event *event, Tick when, bool always) { assert(when >= curTick); assert(always || event->scheduled()); +#ifdef EVENTQ_DEBUG + assert((event->flags & Event::Initialized) == Event::Initialized); +#endif if (event->scheduled()) remove(event); -- cgit v1.2.3 From dae531c0494bc6142ae3febc3623a4514a727614 Mon Sep 17 00:00:00 2001 From: Richard Strong Date: Tue, 9 Dec 2008 10:34:08 -0800 Subject: IDE: Fix serialization for the IDE controller. --- src/dev/ide_ctrl.cc | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/dev/ide_ctrl.cc b/src/dev/ide_ctrl.cc index ced7686c7..454bafac1 100644 --- a/src/dev/ide_ctrl.cc +++ b/src/dev/ide_ctrl.cc @@ -524,9 +524,11 @@ IdeController::Channel::serialize(std::ostream &os) SERIALIZE_SCALAR(cmdSize); SERIALIZE_SCALAR(ctrlAddr); SERIALIZE_SCALAR(ctrlSize); - SERIALIZE_SCALAR((uint8_t)bmiRegs.command); + uint8_t command = bmiRegs.command; + SERIALIZE_SCALAR(command); SERIALIZE_SCALAR(bmiRegs.reserved0); - SERIALIZE_SCALAR((uint8_t)bmiRegs.status); + uint8_t status = bmiRegs.status; + SERIALIZE_SCALAR(status); SERIALIZE_SCALAR(bmiRegs.reserved1); SERIALIZE_SCALAR(bmiRegs.bmidtp); SERIALIZE_SCALAR(selectBit); @@ -559,16 +561,17 @@ void IdeController::Channel::unserialize( Checkpoint *cp, const std::string §ion) { - uint8_t temp; UNSERIALIZE_SCALAR(cmdAddr); UNSERIALIZE_SCALAR(cmdSize); UNSERIALIZE_SCALAR(ctrlAddr); UNSERIALIZE_SCALAR(ctrlSize); - UNSERIALIZE_SCALAR(temp); - bmiRegs.command = temp; + uint8_t command; + UNSERIALIZE_SCALAR(command); + bmiRegs.command = command; UNSERIALIZE_SCALAR(bmiRegs.reserved0); - UNSERIALIZE_SCALAR(temp); - bmiRegs.status = temp; + uint8_t status; + UNSERIALIZE_SCALAR(status); + bmiRegs.status = status; UNSERIALIZE_SCALAR(bmiRegs.reserved1); UNSERIALIZE_SCALAR(bmiRegs.bmidtp); UNSERIALIZE_SCALAR(selectBit); -- cgit v1.2.3 From 13f7fdcf67f9ed893a575e78ef170b42eda58ef4 Mon Sep 17 00:00:00 2001 From: Author Name Date: Sun, 14 Dec 2008 23:29:49 -0800 Subject: The ide_ctrl serialize and unserialize were broken. Multiple channels were saving their state under the same name. This patch separates the saved state of the primary and secondary channel. --- src/dev/ide_ctrl.cc | 58 ++++++++++++++++++++++++++++------------------------- src/dev/ide_ctrl.hh | 9 ++++++--- 2 files changed, 37 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/dev/ide_ctrl.cc b/src/dev/ide_ctrl.cc index 454bafac1..3d4e71888 100644 --- a/src/dev/ide_ctrl.cc +++ b/src/dev/ide_ctrl.cc @@ -501,8 +501,8 @@ IdeController::serialize(std::ostream &os) PciDev::serialize(os); // Serialize channels - primary.serialize(os); - secondary.serialize(os); + primary.serialize("primary", os); + secondary.serialize("secondary", os); // Serialize config registers SERIALIZE_SCALAR(primaryTiming); @@ -515,23 +515,25 @@ IdeController::serialize(std::ostream &os) // Serialize internal state SERIALIZE_SCALAR(ioEnabled); SERIALIZE_SCALAR(bmEnabled); + SERIALIZE_SCALAR(bmiAddr); + SERIALIZE_SCALAR(bmiSize); } void -IdeController::Channel::serialize(std::ostream &os) +IdeController::Channel::serialize(const std::string &base, std::ostream &os) { - SERIALIZE_SCALAR(cmdAddr); - SERIALIZE_SCALAR(cmdSize); - SERIALIZE_SCALAR(ctrlAddr); - SERIALIZE_SCALAR(ctrlSize); + paramOut(os, base + ".cmdAddr", cmdAddr); + paramOut(os, base + ".cmdSize", cmdSize); + paramOut(os, base + ".ctrlAddr", ctrlAddr); + paramOut(os, base + ".ctrlSize", ctrlSize); uint8_t command = bmiRegs.command; - SERIALIZE_SCALAR(command); - SERIALIZE_SCALAR(bmiRegs.reserved0); + paramOut(os, base + ".bmiRegs.command", command); + paramOut(os, base + ".bmiRegs.reserved0", bmiRegs.reserved0); uint8_t status = bmiRegs.status; - SERIALIZE_SCALAR(status); - SERIALIZE_SCALAR(bmiRegs.reserved1); - SERIALIZE_SCALAR(bmiRegs.bmidtp); - SERIALIZE_SCALAR(selectBit); + paramOut(os, base + ".bmiRegs.status", status); + paramOut(os, base + ".bmiRegs.reserved1", bmiRegs.reserved1); + paramOut(os, base + ".bmiRegs.bmidtp", bmiRegs.bmidtp); + paramOut(os, base + ".selectBit", selectBit); } void @@ -541,8 +543,8 @@ IdeController::unserialize(Checkpoint *cp, const std::string §ion) PciDev::unserialize(cp, section); // Unserialize channels - primary.unserialize(cp, section); - secondary.unserialize(cp, section); + primary.unserialize("primary", cp, section); + secondary.unserialize("secondary", cp, section); // Unserialize config registers UNSERIALIZE_SCALAR(primaryTiming); @@ -555,26 +557,28 @@ IdeController::unserialize(Checkpoint *cp, const std::string §ion) // Unserialize internal state UNSERIALIZE_SCALAR(ioEnabled); UNSERIALIZE_SCALAR(bmEnabled); + UNSERIALIZE_SCALAR(bmiAddr); + UNSERIALIZE_SCALAR(bmiSize); } void -IdeController::Channel::unserialize( - Checkpoint *cp, const std::string §ion) +IdeController::Channel::unserialize(const std::string &base, Checkpoint *cp, + const std::string §ion) { - UNSERIALIZE_SCALAR(cmdAddr); - UNSERIALIZE_SCALAR(cmdSize); - UNSERIALIZE_SCALAR(ctrlAddr); - UNSERIALIZE_SCALAR(ctrlSize); + paramIn(cp, section, base + ".cmdAddr", cmdAddr); + paramIn(cp, section, base + ".cmdSize", cmdSize); + paramIn(cp, section, base + ".ctrlAddr", ctrlAddr); + paramIn(cp, section, base + ".ctrlSize", ctrlSize); uint8_t command; - UNSERIALIZE_SCALAR(command); + paramIn(cp, section, base +".bmiRegs.command", command); bmiRegs.command = command; - UNSERIALIZE_SCALAR(bmiRegs.reserved0); + paramIn(cp, section, base + ".bmiRegs.reserved0", bmiRegs.reserved0); uint8_t status; - UNSERIALIZE_SCALAR(status); + paramIn(cp, section, base + ".bmiRegs.status", status); bmiRegs.status = status; - UNSERIALIZE_SCALAR(bmiRegs.reserved1); - UNSERIALIZE_SCALAR(bmiRegs.bmidtp); - UNSERIALIZE_SCALAR(selectBit); + paramIn(cp, section, base + ".bmiRegs.reserved1", bmiRegs.reserved1); + paramIn(cp, section, base + ".bmiRegs.bmidtp", bmiRegs.bmidtp); + paramIn(cp, section, base + ".selectBit", selectBit); select(selectBit); } diff --git a/src/dev/ide_ctrl.hh b/src/dev/ide_ctrl.hh index 6a71a6640..89dc1ee9d 100644 --- a/src/dev/ide_ctrl.hh +++ b/src/dev/ide_ctrl.hh @@ -111,10 +111,13 @@ class IdeController : public PciDev Channel(std::string newName, Addr _cmdSize, Addr _ctrlSize); ~Channel(); - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); + void serialize(const std::string &base, std::ostream &os); + void unserialize(const std::string &base, Checkpoint *cp, + const std::string §ion); + }; - } primary, secondary; + Channel primary; + Channel secondary; /** Bus master interface (BMI) registers */ Addr bmiAddr, bmiSize; -- cgit v1.2.3 From f0d1a209716215e86a2a8f147dc1be5f6e077840 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Mon, 15 Dec 2008 00:47:01 -0800 Subject: PCI: Add some missing breaks to a couple case statements. --- src/dev/pcidev.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/dev/pcidev.cc b/src/dev/pcidev.cc index e1dd7e553..56b8cd3c8 100644 --- a/src/dev/pcidev.cc +++ b/src/dev/pcidev.cc @@ -216,8 +216,10 @@ PciDev::writeConfig(PacketPtr pkt) switch (offset) { case PCI0_INTERRUPT_LINE: config.interruptLine = pkt->get(); + break; case PCI_CACHE_LINE_SIZE: config.cacheLineSize = pkt->get(); + break; case PCI_LATENCY_TIMER: config.latencyTimer = pkt->get(); break; @@ -240,8 +242,10 @@ PciDev::writeConfig(PacketPtr pkt) switch (offset) { case PCI_COMMAND: config.command = pkt->get(); + break; case PCI_STATUS: config.status = pkt->get(); + break; case PCI_CACHE_LINE_SIZE: config.cacheLineSize = pkt->get(); break; -- cgit v1.2.3 From 02cd18f536544d4b5fa19681b4c9dbd5b2cb87ff Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 16 Dec 2008 23:06:37 -0800 Subject: SPARC: Truncate syscall args and return values appropriately. --- src/arch/sparc/syscallreturn.hh | 14 ++++++++++++-- src/cpu/simple_thread.hh | 11 +++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/arch/sparc/syscallreturn.hh b/src/arch/sparc/syscallreturn.hh index cf13fc3e8..d4e6c7c50 100644 --- a/src/arch/sparc/syscallreturn.hh +++ b/src/arch/sparc/syscallreturn.hh @@ -50,13 +50,23 @@ namespace SparcISA tc->setIntReg(NumIntArchRegs + 2, tc->readIntReg(NumIntArchRegs + 2) & 0xEE); //tc->setMiscRegNoEffect(MISCREG_CCR, tc->readMiscRegNoEffect(MISCREG_CCR) & 0xEE); - tc->setIntReg(ReturnValueReg, return_value.value()); + IntReg val = return_value.value(); + if (bits(tc->readMiscRegNoEffect( + SparcISA::MISCREG_PSTATE), 3, 3)) { + val = bits(val, 31, 0); + } + tc->setIntReg(ReturnValueReg, val); } else { // got an error, set XCC.C tc->setIntReg(NumIntArchRegs + 2, tc->readIntReg(NumIntArchRegs + 2) | 0x11); //tc->setMiscRegNoEffect(MISCREG_CCR, tc->readMiscRegNoEffect(MISCREG_CCR) | 0x11); - tc->setIntReg(ReturnValueReg, -return_value.value()); + IntReg val = -return_value.value(); + if (bits(tc->readMiscRegNoEffect( + SparcISA::MISCREG_PSTATE), 3, 3)) { + val = bits(val, 31, 0); + } + tc->setIntReg(ReturnValueReg, val); } } }; diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index a503ab600..4831b701a 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -385,8 +385,15 @@ class SimpleThread : public ThreadState TheISA::IntReg getSyscallArg(int i) { assert(i < TheISA::NumArgumentRegs); - return regs.readIntReg(TheISA::flattenIntIndex(getTC(), - TheISA::ArgumentReg[i])); + TheISA::IntReg val = regs.readIntReg( + TheISA::flattenIntIndex(getTC(), TheISA::ArgumentReg[i])); +#if THE_ISA == SPARC_ISA + if (bits(this->readMiscRegNoEffect( + SparcISA::MISCREG_PSTATE), 3, 3)) { + val = bits(val, 31, 0); + } +#endif + return val; } // used to shift args for indirect syscall -- cgit v1.2.3 From 1704ba2273d9623095ddcd269055aedb8e818e03 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Wed, 17 Dec 2008 09:51:18 -0800 Subject: Make Alpha pseudo-insts available from SE mode. --- src/arch/alpha/isa/decoder.isa | 21 ++++++++++++++++----- src/arch/alpha/isa/main.isa | 2 -- src/cpu/BaseCPU.py | 9 +++++---- src/sim/SConscript | 2 +- src/sim/pseudo_inst.cc | 39 +++++++++++++++++++++++++++------------ src/sim/pseudo_inst.hh | 13 ++++++++----- 6 files changed, 57 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/isa/decoder.isa b/src/arch/alpha/isa/decoder.isa index 115cf7fa7..f057f00cc 100644 --- a/src/arch/alpha/isa/decoder.isa +++ b/src/arch/alpha/isa/decoder.isa @@ -783,14 +783,19 @@ decode OPCODE default Unknown::unknown() { } } - format BasicOperate { - 0x1e: decode PALMODE { - 0: OpcdecFault::hw_rei(); - 1:hw_rei({{ xc->hwrei(); }}, IsSerializing, IsSerializeBefore); + 0x1e: decode PALMODE { + 0: OpcdecFault::hw_rei(); + format BasicOperate { + 1: hw_rei({{ xc->hwrei(); }}, IsSerializing, IsSerializeBefore); } + } + +#endif + format BasicOperate { // M5 special opcodes use the reserved 0x01 opcode space 0x01: decode M5FUNC { +#if FULL_SYSTEM 0x00: arm({{ PseudoInst::arm(xc->tcBase()); }}, IsNonSpeculative); @@ -806,6 +811,7 @@ decode OPCODE default Unknown::unknown() { 0x04: quiesceTime({{ R0 = PseudoInst::quiesceTime(xc->tcBase()); }}, IsNonSpeculative, IsUnverifiable); +#endif 0x07: rpns({{ R0 = PseudoInst::rpns(xc->tcBase()); }}, IsNonSpeculative, IsUnverifiable); @@ -822,12 +828,14 @@ decode OPCODE default Unknown::unknown() { 0x21: m5exit({{ PseudoInst::m5exit(xc->tcBase(), R16); }}, No_OpClass, IsNonSpeculative); +#if FULL_SYSTEM 0x31: loadsymbol({{ PseudoInst::loadsymbol(xc->tcBase()); }}, No_OpClass, IsNonSpeculative); 0x30: initparam({{ Ra = xc->tcBase()->getCpuPtr()->system->init_param; }}); +#endif 0x40: resetstats({{ PseudoInst::resetstats(xc->tcBase(), R16, R17); }}, IsNonSpeculative); @@ -840,18 +848,22 @@ decode OPCODE default Unknown::unknown() { 0x43: m5checkpoint({{ PseudoInst::m5checkpoint(xc->tcBase(), R16, R17); }}, IsNonSpeculative); +#if FULL_SYSTEM 0x50: m5readfile({{ R0 = PseudoInst::readfile(xc->tcBase(), R16, R17, R18); }}, IsNonSpeculative); +#endif 0x51: m5break({{ PseudoInst::debugbreak(xc->tcBase()); }}, IsNonSpeculative); 0x52: m5switchcpu({{ PseudoInst::switchcpu(xc->tcBase()); }}, IsNonSpeculative); +#if FULL_SYSTEM 0x53: m5addsymbol({{ PseudoInst::addsymbol(xc->tcBase(), R16, R17); }}, IsNonSpeculative); +#endif 0x54: m5panic({{ panic("M5 panic instruction called at pc=%#x.", xc->readPC()); }}, IsNonSpeculative); @@ -872,5 +884,4 @@ decode OPCODE default Unknown::unknown() { }}, IsNonSpeculative); } } -#endif } diff --git a/src/arch/alpha/isa/main.isa b/src/arch/alpha/isa/main.isa index 5231712c8..f34bd4b33 100644 --- a/src/arch/alpha/isa/main.isa +++ b/src/arch/alpha/isa/main.isa @@ -68,9 +68,7 @@ using namespace AlphaISA; output exec {{ #include -#if FULL_SYSTEM #include "sim/pseudo_inst.hh" -#endif #include "arch/alpha/ipr.hh" #include "base/fenv.hh" #include "config/ss_compatible_fp.hh" diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py index f98c6af8e..985c415a0 100644 --- a/src/cpu/BaseCPU.py +++ b/src/cpu/BaseCPU.py @@ -71,13 +71,14 @@ class BaseCPU(MemObject): checker = Param.BaseCPU("checker CPU") + do_checkpoint_insts = Param.Bool(True, + "enable checkpoint pseudo instructions") + do_statistics_insts = Param.Bool(True, + "enable statistics pseudo instructions") + if build_env['FULL_SYSTEM']: profile = Param.Latency('0ns', "trace the kernel stack") do_quiesce = Param.Bool(True, "enable quiesce instructions") - do_checkpoint_insts = Param.Bool(True, - "enable checkpoint pseudo instructions") - do_statistics_insts = Param.Bool(True, - "enable statistics pseudo instructions") else: workload = VectorParam.Process("processes to run") diff --git a/src/sim/SConscript b/src/sim/SConscript index 7acf4e9b6..48200161c 100644 --- a/src/sim/SConscript +++ b/src/sim/SConscript @@ -43,6 +43,7 @@ Source('eventq.cc') Source('faults.cc') Source('init.cc') BinSource('main.cc') +Source('pseudo_inst.cc') Source('root.cc') Source('serialize.cc') Source('sim_events.cc') @@ -54,7 +55,6 @@ Source('system.cc') if env['FULL_SYSTEM']: Source('arguments.cc') - Source('pseudo_inst.cc') else: Source('tlb.cc') SimObject('Process.py') diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index e43279376..130a2f0fe 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -50,7 +50,9 @@ #include "sim/stats.hh" #include "sim/system.hh" #include "sim/debug.hh" +#if FULL_SYSTEM #include "sim/vptr.hh" +#endif using namespace std; @@ -59,6 +61,8 @@ using namespace TheISA; namespace PseudoInst { +#if FULL_SYSTEM + void arm(ThreadContext *tc) { @@ -125,6 +129,8 @@ quiesceTime(ThreadContext *tc) return (tc->readLastActivate() - tc->readLastSuspend()) / Clock::Int::ns; } +#endif + uint64_t rpns(ThreadContext *tc) { @@ -139,6 +145,8 @@ m5exit(ThreadContext *tc, Tick delay) mainEventQueue.schedule(event, when); } +#if FULL_SYSTEM + void loadsymbol(ThreadContext *tc) { @@ -187,6 +195,21 @@ loadsymbol(ThreadContext *tc) file.close(); } +void +addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr) +{ + char symb[100]; + CopyStringOut(tc, symb, symbolAddr, 100); + std::string symbol(symb); + + DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr); + + tc->getSystemPtr()->kernelSymtab->insert(addr,symbol); +} + +#endif + + void resetstats(ThreadContext *tc, Tick delay, Tick period) { @@ -213,18 +236,6 @@ dumpstats(ThreadContext *tc, Tick delay, Tick period) Stats::StatEvent(true, false, when, repeat); } -void -addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr) -{ - char symb[100]; - CopyStringOut(tc, symb, symbolAddr, 100); - std::string symbol(symb); - - DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr); - - tc->getSystemPtr()->kernelSymtab->insert(addr,symbol); -} - void dumpresetstats(ThreadContext *tc, Tick delay, Tick period) { @@ -251,6 +262,8 @@ m5checkpoint(ThreadContext *tc, Tick delay, Tick period) mainEventQueue.schedule(event, when); } +#if FULL_SYSTEM + uint64_t readfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset) { @@ -286,6 +299,8 @@ readfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset) return result; } +#endif + void debugbreak(ThreadContext *tc) { diff --git a/src/sim/pseudo_inst.hh b/src/sim/pseudo_inst.hh index 80f58f80d..7d013eda7 100644 --- a/src/sim/pseudo_inst.hh +++ b/src/sim/pseudo_inst.hh @@ -42,22 +42,25 @@ extern bool doStatisticsInsts; extern bool doCheckpointInsts; extern bool doQuiesce; +#if FULL_SYSTEM void arm(ThreadContext *tc); void quiesce(ThreadContext *tc); void quiesceNs(ThreadContext *tc, uint64_t ns); void quiesceCycles(ThreadContext *tc, uint64_t cycles); uint64_t quiesceTime(ThreadContext *tc); +uint64_t readfile(ThreadContext *tc, Addr vaddr, uint64_t len, + uint64_t offset); +void loadsymbol(ThreadContext *xc); +void addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr); +#endif + uint64_t rpns(ThreadContext *tc); void m5exit(ThreadContext *tc, Tick delay); -void loadsymbol(ThreadContext *xc); void resetstats(ThreadContext *tc, Tick delay, Tick period); void dumpstats(ThreadContext *tc, Tick delay, Tick period); void dumpresetstats(ThreadContext *tc, Tick delay, Tick period); void m5checkpoint(ThreadContext *tc, Tick delay, Tick period); -uint64_t readfile(ThreadContext *tc, Addr vaddr, uint64_t len, - uint64_t offset); void debugbreak(ThreadContext *tc); void switchcpu(ThreadContext *tc); -void addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr); -/* namespace PsuedoInst */ } +/* namespace PseudoInst */ } -- cgit v1.2.3 From 9f89d43b653061fe335cdb4c8dfac9b046d6416c Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Tue, 6 Jan 2009 10:36:55 -0500 Subject: IGbE: Remove is8257 variable --- src/dev/Ethernet.py | 11 ++++++----- src/dev/i8254xGBe.cc | 10 ++-------- 2 files changed, 8 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/dev/Ethernet.py b/src/dev/Ethernet.py index 670f48eac..d73d56d03 100644 --- a/src/dev/Ethernet.py +++ b/src/dev/Ethernet.py @@ -69,7 +69,6 @@ class EtherDevice(PciDevice): class IGbE(EtherDevice): # Base class for two IGbE adapters listed above type = 'IGbE' - #abstract = True hardware_address = Param.EthernetAddr(NextEthernetAddr, "Ethernet Hardware Address") use_flow_control = Param.Bool(False, @@ -105,20 +104,22 @@ class IGbE(EtherDevice): wb_comp_delay = Param.Latency('10ns', "delay after desc wb occurs") tx_read_delay = Param.Latency('0ns', "delay after tx dma read") rx_write_delay = Param.Latency('0ns', "delay after rx dma read") - is8257 = Param.Bool("Select between and 8254x and 8257x device") - + phy_pid = Param.UInt16("Phy PID that corresponds to device ID") + phy_epid = Param.UInt16("Phy EPID that corresponds to device ID") class IGbE_e1000(IGbE): # Older Intel 8254x based gigabit ethernet adapter # Uses Intel e1000 driver DeviceID = 0x1075 - is8257 = False + phy_pid = 0x02A8 + phy_epid = 0x0380 class IGbE_igb(IGbE): # Newer Intel 8257x based gigabit ethernet adapter # Uses Intel igb driver and in theory supports packet splitting and LRO DeviceID = 0x10C9 - is8257 = True + phy_pid = 0x0141 + phy_epid = 0x0CC0 class EtherDevBase(EtherDevice): type = 'EtherDevBase' diff --git a/src/dev/i8254xGBe.cc b/src/dev/i8254xGBe.cc index 2a7ba0b31..1e4fd130c 100644 --- a/src/dev/i8254xGBe.cc +++ b/src/dev/i8254xGBe.cc @@ -446,16 +446,10 @@ IGbE::write(PacketPtr pkt) regs.mdic.data(0x796D); // link up break; case PHY_PID: - if (params()->is8257) - regs.mdic.data(0x0141); - else - regs.mdic.data(0x02A8); + regs.mdic.data(params()->phy_pid); break; case PHY_EPID: - if (params()->is8257) - regs.mdic.data(0x0CC0); - else - regs.mdic.data(0x0380); + regs.mdic.data(params()->phy_epid); break; case PHY_GSTATUS: regs.mdic.data(0x7C00); -- cgit v1.2.3 From 11ac0c7acfe2d75d51e56e3a4305bf3209b3d420 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Tue, 6 Jan 2009 10:36:56 -0500 Subject: INET: Add functions to header types to get offset in packet and start of payload; add function to split packet at last known header --- src/base/inet.cc | 21 +++++++++++++++++++++ src/base/inet.hh | 42 ++++++++++++++++++++++++++---------------- 2 files changed, 47 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/base/inet.cc b/src/base/inet.cc index b8da12a99..8c3240fa6 100644 --- a/src/base/inet.cc +++ b/src/base/inet.cc @@ -206,4 +206,25 @@ TcpOpt::sack(vector &vec) const return false; } +int +hsplit(const EthPacketPtr &ptr) +{ + int split_point = 0; + + IpPtr ip(ptr); + if (ip) { + split_point = ip.pstart(); + + TcpPtr tcp(ip); + if (tcp) + split_point = tcp.pstart(); + + UdpPtr udp(ip); + if (udp) + split_point = udp.pstart(); + } + return split_point; +} + + /* namespace Net */ } diff --git a/src/base/inet.hh b/src/base/inet.hh index 21ac5c89e..59b05291d 100644 --- a/src/base/inet.hh +++ b/src/base/inet.hh @@ -140,6 +140,8 @@ class EthPtr EthPacketPtr packet() { return p; } bool operator!() const { return !p; } operator bool() const { return p; } + int off() const { return 0; } + int pstart() const { return off() + ((const EthHdr*)p->data)->size(); } }; /* @@ -216,6 +218,8 @@ class IpPtr EthPacketPtr packet() { return p; } bool operator!() const { return !p; } operator bool() const { return p; } + int off() const { return sizeof(eth_hdr); } + int pstart() const { return off() + get()->size(); } }; uint16_t cksum(const IpPtr &ptr); @@ -279,9 +283,9 @@ class TcpPtr { protected: EthPacketPtr p; - int off; + int _off; - void set(const EthPacketPtr &ptr, int offset) { p = ptr; off = offset; } + void set(const EthPacketPtr &ptr, int offset) { p = ptr; _off = offset; } void set(const IpPtr &ptr) { if (ptr && ptr->proto() == IP_PROTO_TCP) @@ -291,25 +295,27 @@ class TcpPtr } public: - TcpPtr() : p(0), off(0) {} - TcpPtr(const IpPtr &ptr) : p(0), off(0) { set(ptr); } - TcpPtr(const TcpPtr &ptr) : p(ptr.p), off(ptr.off) {} + TcpPtr() : p(0), _off(0) {} + TcpPtr(const IpPtr &ptr) : p(0), _off(0) { set(ptr); } + TcpPtr(const TcpPtr &ptr) : p(ptr.p), _off(ptr._off) {} - TcpHdr *get() { return (TcpHdr *)(p->data + off); } + TcpHdr *get() { return (TcpHdr *)(p->data + _off); } TcpHdr *operator->() { return get(); } TcpHdr &operator*() { return *get(); } - const TcpHdr *get() const { return (const TcpHdr *)(p->data + off); } + const TcpHdr *get() const { return (const TcpHdr *)(p->data + _off); } const TcpHdr *operator->() const { return get(); } const TcpHdr &operator*() const { return *get(); } const TcpPtr &operator=(const IpPtr &i) { set(i); return *this; } - const TcpPtr &operator=(const TcpPtr &t) { set(t.p, t.off); return *this; } + const TcpPtr &operator=(const TcpPtr &t) { set(t.p, t._off); return *this; } const EthPacketPtr packet() const { return p; } EthPacketPtr packet() { return p; } bool operator!() const { return !p; } operator bool() const { return p; } + int off() const { return _off; } + int pstart() const { return off() + get()->size(); } }; uint16_t cksum(const TcpPtr &ptr); @@ -366,9 +372,9 @@ class UdpPtr { protected: EthPacketPtr p; - int off; + int _off; - void set(const EthPacketPtr &ptr, int offset) { p = ptr; off = offset; } + void set(const EthPacketPtr &ptr, int offset) { p = ptr; _off = offset; } void set(const IpPtr &ptr) { if (ptr && ptr->proto() == IP_PROTO_UDP) @@ -378,29 +384,33 @@ class UdpPtr } public: - UdpPtr() : p(0), off(0) {} - UdpPtr(const IpPtr &ptr) : p(0), off(0) { set(ptr); } - UdpPtr(const UdpPtr &ptr) : p(ptr.p), off(ptr.off) {} + UdpPtr() : p(0), _off(0) {} + UdpPtr(const IpPtr &ptr) : p(0), _off(0) { set(ptr); } + UdpPtr(const UdpPtr &ptr) : p(ptr.p), _off(ptr._off) {} - UdpHdr *get() { return (UdpHdr *)(p->data + off); } + UdpHdr *get() { return (UdpHdr *)(p->data + _off); } UdpHdr *operator->() { return get(); } UdpHdr &operator*() { return *get(); } - const UdpHdr *get() const { return (const UdpHdr *)(p->data + off); } + const UdpHdr *get() const { return (const UdpHdr *)(p->data + _off); } const UdpHdr *operator->() const { return get(); } const UdpHdr &operator*() const { return *get(); } const UdpPtr &operator=(const IpPtr &i) { set(i); return *this; } - const UdpPtr &operator=(const UdpPtr &t) { set(t.p, t.off); return *this; } + const UdpPtr &operator=(const UdpPtr &t) { set(t.p, t._off); return *this; } const EthPacketPtr packet() const { return p; } EthPacketPtr packet() { return p; } bool operator!() const { return !p; } operator bool() const { return p; } + int off() const { return _off; } + int pstart() const { return off() + get()->size(); } }; uint16_t cksum(const UdpPtr &ptr); +int hsplit(const EthPacketPtr &ptr); + /* namespace Net */ } #endif // __BASE_INET_HH__ -- cgit v1.2.3 From 2adc60795b0e21d46f983293b3b71b48ee105c14 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Tue, 6 Jan 2009 10:36:57 -0500 Subject: IGbE: Implement header splitting with large MTU --- src/dev/i8254xGBe.cc | 196 ++++++++++++++++++++++++++++++++++------------ src/dev/i8254xGBe.hh | 25 +++++- src/dev/i8254xGBe_defs.hh | 4 +- 3 files changed, 169 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/dev/i8254xGBe.cc b/src/dev/i8254xGBe.cc index 1e4fd130c..cf6692fb4 100644 --- a/src/dev/i8254xGBe.cc +++ b/src/dev/i8254xGBe.cc @@ -57,7 +57,7 @@ using namespace Net; IGbE::IGbE(const Params *p) : EtherDevice(p), etherInt(NULL), drainEvent(NULL), useFlowControl(p->use_flow_control), rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size), rxTick(false), - txTick(false), txFifoTick(false), rxDmaPacket(false), + txTick(false), txFifoTick(false), rxDmaPacket(false), pktOffset(0), fetchDelay(p->fetch_delay), wbDelay(p->wb_delay), fetchCompDelay(p->fetch_comp_delay), wbCompDelay(p->wb_comp_delay), rxWriteDelay(p->rx_write_delay), txReadDelay(p->tx_read_delay), @@ -789,13 +789,27 @@ IGbE::chkInterrupt() IGbE::RxDescCache::RxDescCache(IGbE *i, const std::string n, int s) - : DescCache(i, n, s), pktDone(false), pktEvent(this) + : DescCache(i, n, s), pktDone(false), splitCount(0), + pktEvent(this), pktHdrEvent(this), pktDataEvent(this) { } void -IGbE::RxDescCache::writePacket(EthPacketPtr packet) +IGbE::RxDescCache::pktSplitDone() +{ + splitCount++; + DPRINTF(EthernetDesc, "Part of split packet done: splitcount now %d\n", splitCount); + assert(splitCount <= 2); + if (splitCount != 2) + return; + splitCount = 0; + DPRINTF(EthernetDesc, "Part of split packet done: calling pktComplete()\n"); + pktComplete(); +} + +int +IGbE::RxDescCache::writePacket(EthPacketPtr packet, int pkt_offset) { assert(unusedCache.size()); //if (!unusedCache.size()) @@ -803,32 +817,90 @@ IGbE::RxDescCache::writePacket(EthPacketPtr packet) pktPtr = packet; pktDone = false; + int buf_len, hdr_len; - Addr buf; RxDesc *desc = unusedCache.front(); switch (igbe->regs.srrctl.desctype()) { case RXDT_LEGACY: - buf = desc->legacy.buf; + assert(pkt_offset == 0); + bytesCopied = packet->length; DPRINTF(EthernetDesc, "Packet Length: %d Desc Size: %d\n", packet->length, igbe->regs.rctl.descSize()); assert(packet->length < igbe->regs.rctl.descSize()); + igbe->dmaWrite(igbe->platform->pciToDma(desc->legacy.buf), packet->length, &pktEvent, + packet->data, igbe->rxWriteDelay); break; case RXDT_ADV_ONEBUF: - int buf_len; + assert(pkt_offset == 0); + bytesCopied = packet->length; buf_len = igbe->regs.rctl.lpe() ? igbe->regs.srrctl.bufLen() : igbe->regs.rctl.descSize(); DPRINTF(EthernetDesc, "Packet Length: %d srrctl: %#x Desc Size: %d\n", packet->length, igbe->regs.srrctl(), buf_len); assert(packet->length < buf_len); - buf = desc->adv_read.pkt; + igbe->dmaWrite(igbe->platform->pciToDma(desc->adv_read.pkt), packet->length, &pktEvent, + packet->data, igbe->rxWriteDelay); + desc->adv_wb.header_len = htole(0); + desc->adv_wb.sph = htole(0); + desc->adv_wb.pkt_len = htole((uint16_t)(pktPtr->length)); + break; + case RXDT_ADV_SPLIT_A: + int split_point; + + buf_len = igbe->regs.rctl.lpe() ? igbe->regs.srrctl.bufLen() : + igbe->regs.rctl.descSize(); + hdr_len = igbe->regs.rctl.lpe() ? igbe->regs.srrctl.hdrLen() : 0; + DPRINTF(EthernetDesc, "lpe: %d Packet Length: %d offset: %d srrctl: %#x hdr addr: %#x Hdr Size: %d desc addr: %#x Desc Size: %d\n", + igbe->regs.rctl.lpe(), packet->length, pkt_offset, igbe->regs.srrctl(), desc->adv_read.hdr, hdr_len, desc->adv_read.pkt, buf_len); + + split_point = hsplit(pktPtr); + + if (packet->length <= hdr_len) { + bytesCopied = packet->length; + assert(pkt_offset == 0); + DPRINTF(EthernetDesc, "Header Splitting: Entire packet being placed in header\n"); + igbe->dmaWrite(igbe->platform->pciToDma(desc->adv_read.hdr), packet->length, &pktEvent, + packet->data, igbe->rxWriteDelay); + desc->adv_wb.header_len = htole((uint16_t)packet->length); + desc->adv_wb.sph = htole(0); + desc->adv_wb.pkt_len = htole(0); + } else if (split_point) { + if (pkt_offset) { + // we are only copying some data, header/data has already been + // copied + int max_to_copy = std::min(packet->length - pkt_offset, buf_len); + bytesCopied += max_to_copy; + DPRINTF(EthernetDesc, "Header Splitting: Continuing data buffer copy\n"); + igbe->dmaWrite(igbe->platform->pciToDma(desc->adv_read.pkt),max_to_copy, &pktEvent, + packet->data + pkt_offset, igbe->rxWriteDelay); + desc->adv_wb.header_len = htole(0); + desc->adv_wb.pkt_len = htole((uint16_t)max_to_copy); + desc->adv_wb.sph = htole(0); + } else { + int max_to_copy = std::min(packet->length - split_point, buf_len); + bytesCopied += max_to_copy + split_point; + + DPRINTF(EthernetDesc, "Header Splitting: splitting at %d\n", + split_point); + igbe->dmaWrite(igbe->platform->pciToDma(desc->adv_read.hdr), split_point, &pktHdrEvent, + packet->data, igbe->rxWriteDelay); + igbe->dmaWrite(igbe->platform->pciToDma(desc->adv_read.pkt), + max_to_copy, &pktDataEvent, packet->data + split_point, igbe->rxWriteDelay); + desc->adv_wb.header_len = htole(split_point); + desc->adv_wb.sph = 1; + desc->adv_wb.pkt_len = htole((uint16_t)(max_to_copy)); + } + } else { + panic("Header split not fitting within header buffer or undecodable" + " packet not fitting in header unsupported\n"); + } break; default: panic("Unimplemnted RX receive buffer type: %d\n", igbe->regs.srrctl.desctype()); } + return bytesCopied; - igbe->dmaWrite(igbe->platform->pciToDma(buf), packet->length, &pktEvent, - packet->data, igbe->rxWriteDelay); } void @@ -839,8 +911,8 @@ IGbE::RxDescCache::pktComplete() desc = unusedCache.front(); uint16_t crcfixup = igbe->regs.rctl.secrc() ? 0 : 4 ; - DPRINTF(EthernetDesc, "pktPtr->length: %d stripcrc offset: %d value written: %d %d\n", - pktPtr->length, crcfixup, + DPRINTF(EthernetDesc, "pktPtr->length: %d bytesCopied: %d stripcrc offset: %d value written: %d %d\n", + pktPtr->length, bytesCopied, crcfixup, htole((uint16_t)(pktPtr->length + crcfixup)), (uint16_t)(pktPtr->length + crcfixup)); @@ -849,13 +921,17 @@ IGbE::RxDescCache::pktComplete() DPRINTF(EthernetDesc, "Packet written to memory updating Descriptor\n"); - uint16_t status = RXDS_DD | RXDS_EOP; + uint16_t status = RXDS_DD; uint8_t err = 0; uint16_t ext_err = 0; uint16_t csum = 0; uint16_t ptype = 0; uint16_t ip_id = 0; + assert(bytesCopied <= pktPtr->length); + if (bytesCopied == pktPtr->length) + status |= RXDS_EOP; + IpPtr ip(pktPtr); if (ip) { @@ -913,13 +989,10 @@ IGbE::RxDescCache::pktComplete() // No vlan support at this point... just set it to 0 desc->legacy.vlan = 0; break; + case RXDT_ADV_SPLIT_A: case RXDT_ADV_ONEBUF: - desc->adv_wb.pkt_len = htole((uint16_t)(pktPtr->length + crcfixup)); desc->adv_wb.rss_type = htole(0); desc->adv_wb.pkt_type = htole(ptype); - // no header splititng support yet - desc->adv_wb.header_len = htole(0); - desc->adv_wb.sph = htole(0); if (igbe->regs.rxcsum.pcsd()) { // no rss support right now desc->adv_wb.rss_hash = htole(0); @@ -937,47 +1010,51 @@ IGbE::RxDescCache::pktComplete() igbe->regs.srrctl.desctype()); } + DPRINTF(EthernetDesc, "Descriptor complete w0: %#x w1: %#x\n", + desc->adv_read.pkt, desc->adv_read.hdr); - // Deal with the rx timer interrupts - if (igbe->regs.rdtr.delay()) { - DPRINTF(EthernetSM, "RXS: Scheduling DTR for %d\n", - igbe->regs.rdtr.delay() * igbe->intClock()); - igbe->reschedule(igbe->rdtrEvent, - curTick + igbe->regs.rdtr.delay() * igbe->intClock(), true); - } + if (bytesCopied == pktPtr->length) { + DPRINTF(EthernetDesc, "Packet completely written to descriptor buffers\n"); + // Deal with the rx timer interrupts + if (igbe->regs.rdtr.delay()) { + DPRINTF(EthernetSM, "RXS: Scheduling DTR for %d\n", + igbe->regs.rdtr.delay() * igbe->intClock()); + igbe->reschedule(igbe->rdtrEvent, + curTick + igbe->regs.rdtr.delay() * igbe->intClock(), true); + } - if (igbe->regs.radv.idv()) { - DPRINTF(EthernetSM, "RXS: Scheduling ADV for %d\n", - igbe->regs.radv.idv() * igbe->intClock()); - if (!igbe->radvEvent.scheduled()) { - igbe->schedule(igbe->radvEvent, - curTick + igbe->regs.radv.idv() * igbe->intClock()); + if (igbe->regs.radv.idv()) { + DPRINTF(EthernetSM, "RXS: Scheduling ADV for %d\n", + igbe->regs.radv.idv() * igbe->intClock()); + if (!igbe->radvEvent.scheduled()) { + igbe->schedule(igbe->radvEvent, + curTick + igbe->regs.radv.idv() * igbe->intClock()); + } } - } - // if neither radv or rdtr, maybe itr is set... - if (!igbe->regs.rdtr.delay() && !igbe->regs.radv.idv()) { - DPRINTF(EthernetSM, "RXS: Receive interrupt delay disabled, posting IT_RXT\n"); - igbe->postInterrupt(IT_RXT); - } + // if neither radv or rdtr, maybe itr is set... + if (!igbe->regs.rdtr.delay() && !igbe->regs.radv.idv()) { + DPRINTF(EthernetSM, "RXS: Receive interrupt delay disabled, posting IT_RXT\n"); + igbe->postInterrupt(IT_RXT); + } - // If the packet is small enough, interrupt appropriately - // I wonder if this is delayed or not?! - if (pktPtr->length <= igbe->regs.rsrpd.idv()) { - DPRINTF(EthernetSM, "RXS: Posting IT_SRPD beacuse small packet received\n"); - igbe->postInterrupt(IT_SRPD); + // If the packet is small enough, interrupt appropriately + // I wonder if this is delayed or not?! + if (pktPtr->length <= igbe->regs.rsrpd.idv()) { + DPRINTF(EthernetSM, "RXS: Posting IT_SRPD beacuse small packet received\n"); + igbe->postInterrupt(IT_SRPD); + } + bytesCopied = 0; } - DPRINTF(EthernetDesc, "Processing of this descriptor complete\n"); - unusedCache.pop_front(); - usedCache.push_back(desc); - - pktPtr = NULL; + igbe->checkDrain(); enableSm(); pktDone = true; - igbe->checkDrain(); + DPRINTF(EthernetDesc, "Processing of this descriptor complete\n"); + unusedCache.pop_front(); + usedCache.push_back(desc); } void @@ -1003,7 +1080,9 @@ bool IGbE::RxDescCache::hasOutstandingEvents() { return pktEvent.scheduled() || wbEvent.scheduled() || - fetchEvent.scheduled(); + fetchEvent.scheduled() || pktHdrEvent.scheduled() || + pktDataEvent.scheduled(); + } void @@ -1011,6 +1090,8 @@ IGbE::RxDescCache::serialize(std::ostream &os) { DescCache::serialize(os); SERIALIZE_SCALAR(pktDone); + SERIALIZE_SCALAR(splitCount); + SERIALIZE_SCALAR(bytesCopied); } void @@ -1018,6 +1099,8 @@ IGbE::RxDescCache::unserialize(Checkpoint *cp, const std::string §ion) { DescCache::unserialize(cp, section); UNSERIALIZE_SCALAR(pktDone); + UNSERIALIZE_SCALAR(splitCount); + UNSERIALIZE_SCALAR(bytesCopied); } @@ -1680,6 +1763,8 @@ IGbE::rxStateMachine() rxDmaPacket = false; DPRINTF(EthernetSM, "RXS: Packet completed DMA to memory\n"); int descLeft = rxDescCache.descLeft(); + DPRINTF(EthernetSM, "RXS: descLeft: %d rdmts: %d rdlen: %d\n", + descLeft, regs.rctl.rdmts(), regs.rdlen()); switch (regs.rctl.rdmts()) { case 2: if (descLeft > .125 * regs.rdlen()) break; case 1: if (descLeft > .250 * regs.rdlen()) break; @@ -1689,6 +1774,9 @@ IGbE::rxStateMachine() break; } + if (rxFifo.empty()) + rxDescCache.writeback(0); + if (descLeft == 0) { rxDescCache.writeback(0); DPRINTF(EthernetSM, "RXS: No descriptors left in ring, forcing" @@ -1746,10 +1834,14 @@ IGbE::rxStateMachine() pkt = rxFifo.front(); - rxDescCache.writePacket(pkt); + pktOffset = rxDescCache.writePacket(pkt, pktOffset); DPRINTF(EthernetSM, "RXS: Writing packet into memory\n"); - DPRINTF(EthernetSM, "RXS: Removing packet from FIFO\n"); - rxFifo.pop(); + if (pktOffset == pkt->length) { + DPRINTF(EthernetSM, "RXS: Removing packet from FIFO\n"); + pktOffset = 0; + rxFifo.pop(); + } + DPRINTF(EthernetSM, "RXS: stopping ticking until packet DMA completes\n"); rxTick = false; rxDmaPacket = true; @@ -1866,6 +1958,8 @@ IGbE::serialize(std::ostream &os) inter_time = interEvent.when(); SERIALIZE_SCALAR(inter_time); + SERIALIZE_SCALAR(pktOffset); + nameOut(os, csprintf("%s.TxDescCache", name())); txDescCache.serialize(os); @@ -1923,6 +2017,8 @@ IGbE::unserialize(Checkpoint *cp, const std::string §ion) if (inter_time) schedule(interEvent, inter_time); + UNSERIALIZE_SCALAR(pktOffset); + txDescCache.unserialize(cp, csprintf("%s.TxDescCache", section)); rxDescCache.unserialize(cp, csprintf("%s.RxDescCache", section)); diff --git a/src/dev/i8254xGBe.hh b/src/dev/i8254xGBe.hh index 5e5ab1d21..6dd2141b0 100644 --- a/src/dev/i8254xGBe.hh +++ b/src/dev/i8254xGBe.hh @@ -83,6 +83,9 @@ class IGbE : public EtherDevice bool rxDmaPacket; + // Number of bytes copied from current RX packet + int pktOffset; + // Delays in managaging descriptors Tick fetchDelay, wbDelay; Tick fetchCompDelay, wbCompDelay; @@ -586,6 +589,12 @@ class IGbE : public EtherDevice bool pktDone; + /** Variable to head with header/data completion events */ + int splitCount; + + /** Bytes of packet that have been copied, so we know when to set EOP */ + int bytesCopied; + public: RxDescCache(IGbE *i, std::string n, int s); @@ -593,20 +602,28 @@ class IGbE : public EtherDevice * descriptor and update the book keeping. Should only be called when * there are no dma's pending. * @param packet ethernet packet to write - * @return if the packet could be written (there was a free descriptor) + * @param pkt_offset bytes already copied from the packet to memory + * @return pkt_offset + number of bytes copied during this call */ - void writePacket(EthPacketPtr packet); + int writePacket(EthPacketPtr packet, int pkt_offset); + /** Called by event when dma to write packet is completed */ void pktComplete(); - /** Check if the dma on the packet has completed. + /** Check if the dma on the packet has completed and RX state machine + * can continue */ - bool packetDone(); EventWrapper pktEvent; + // Event to handle issuing header and data write at the same time + // and only callking pktComplete() when both are completed + void pktSplitDone(); + EventWrapper pktHdrEvent; + EventWrapper pktDataEvent; + virtual bool hasOutstandingEvents(); virtual void serialize(std::ostream &os); diff --git a/src/dev/i8254xGBe_defs.hh b/src/dev/i8254xGBe_defs.hh index 78492d47e..4634dd9a3 100644 --- a/src/dev/i8254xGBe_defs.hh +++ b/src/dev/i8254xGBe_defs.hh @@ -555,8 +555,8 @@ struct Regs { struct SRRCTL : public Reg { // 0x280C SRRCTL Register using Reg::operator=; - ADD_FIELD32(pktlen, 0, 7); - ADD_FIELD32(hdrlen, 16, 7); // guess based on header, not documented + ADD_FIELD32(pktlen, 0, 8); + ADD_FIELD32(hdrlen, 8, 8); // guess based on header, not documented ADD_FIELD32(desctype, 25,3); // type of descriptor 000 legacy, 001 adv, //101 hdr split int bufLen() { return pktlen() << 10; } -- cgit v1.2.3 From b0ab5c894d84d4522cae3a254158e47ba112909c Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 6 Jan 2009 22:34:18 -0800 Subject: Tracing: Make tracing aware of macro and micro ops. --- src/cpu/SConscript | 4 ++- src/cpu/exetrace.cc | 69 +++++++++++++++++++++++++++++++++++++------------- src/cpu/exetrace.hh | 13 +++++++--- src/cpu/inteltrace.hh | 11 +++++--- src/cpu/legiontrace.hh | 11 +++++--- src/cpu/nativetrace.hh | 12 ++++++--- src/cpu/simple/base.cc | 5 ++-- src/sim/insttracer.hh | 13 +++++++--- 8 files changed, 98 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/cpu/SConscript b/src/cpu/SConscript index 750e1ee4c..334504660 100644 --- a/src/cpu/SConscript +++ b/src/cpu/SConscript @@ -170,10 +170,12 @@ TraceFlag('ExecSpeculative') TraceFlag('ExecSymbol') TraceFlag('ExecThread') TraceFlag('ExecTicks') +TraceFlag('ExecMicro') +TraceFlag('ExecMacro') TraceFlag('Fetch') TraceFlag('IntrControl') TraceFlag('PCEvent') TraceFlag('Quiesce') CompoundFlag('Exec', [ 'ExecEnable', 'ExecTicks', 'ExecOpClass', 'ExecThread', - 'ExecEffAddr', 'ExecResult', 'ExecSymbol' ]) + 'ExecEffAddr', 'ExecResult', 'ExecSymbol', 'ExecMicro' ]) diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc index 824fbb5f6..4c0f83a21 100644 --- a/src/cpu/exetrace.cc +++ b/src/cpu/exetrace.cc @@ -46,7 +46,7 @@ using namespace TheISA; namespace Trace { void -Trace::ExeTracerRecord::dump() +Trace::ExeTracerRecord::traceInst(StaticInstPtr inst, bool ran) { ostream &outs = Trace::output(); @@ -61,7 +61,6 @@ Trace::ExeTracerRecord::dump() if (IsOn(ExecThread)) outs << "T" << thread->threadId() << " : "; - std::string sym_str; Addr sym_addr; if (debugSymbolTable @@ -69,36 +68,47 @@ Trace::ExeTracerRecord::dump() && debugSymbolTable->findNearestSymbol(PC, sym_str, sym_addr)) { if (PC != sym_addr) sym_str += csprintf("+%d", PC - sym_addr); - outs << "@" << sym_str << " : "; + outs << "@" << sym_str; } else { - outs << "0x" << hex << PC << " : "; + outs << "0x" << hex << PC; } + if (inst->isMicroop()) { + outs << "." << setw(2) << dec << upc; + } else { + outs << " "; + } + + outs << " : "; + // // Print decoded instruction // outs << setw(26) << left; - outs << staticInst->disassemble(PC, debugSymbolTable); - outs << " : "; + outs << inst->disassemble(PC, debugSymbolTable); - if (IsOn(ExecOpClass)) { - outs << Enums::OpClassStrings[staticInst->opClass()] << " : "; - } + if (ran) { + outs << " : "; - if (IsOn(ExecResult) && data_status != DataInvalid) { - ccprintf(outs, " D=%#018x", data.as_int); - } + if (IsOn(ExecOpClass)) { + outs << Enums::OpClassStrings[inst->opClass()] << " : "; + } - if (IsOn(ExecEffAddr) && addr_valid) - outs << " A=0x" << hex << addr; + if (IsOn(ExecResult) && data_status != DataInvalid) { + ccprintf(outs, " D=%#018x", data.as_int); + } - if (IsOn(ExecFetchSeq) && fetch_seq_valid) - outs << " FetchSeq=" << dec << fetch_seq; + if (IsOn(ExecEffAddr) && addr_valid) + outs << " A=0x" << hex << addr; - if (IsOn(ExecCPSeq) && cp_seq_valid) - outs << " CPSeq=" << dec << cp_seq; + if (IsOn(ExecFetchSeq) && fetch_seq_valid) + outs << " FetchSeq=" << dec << fetch_seq; + + if (IsOn(ExecCPSeq) && cp_seq_valid) + outs << " CPSeq=" << dec << cp_seq; + } // // End of line... @@ -106,6 +116,29 @@ Trace::ExeTracerRecord::dump() outs << endl; } +void +Trace::ExeTracerRecord::dump() +{ + /* + * The behavior this check tries to achieve is that if ExecMacro is on, + * the macroop will be printed. If it's on and microops are also on, it's + * printed before the microops start printing to give context. If the + * microops aren't printed, then it's printed only when the final microop + * finishes. Macroops then behave like regular instructions and don't + * complete/print when they fault. + */ + if (IsOn(ExecMacro) && staticInst->isMicroop() && + (IsOn(ExecMicro) && + macroStaticInst && staticInst->isFirstMicroop()) || + (!IsOn(ExecMicro) && + macroStaticInst && staticInst->isLastMicroop())) { + traceInst(macroStaticInst, false); + } + if (IsOn(ExecMicro) || !staticInst->isMicroop()) { + traceInst(staticInst, true); + } +} + /* namespace Trace */ } //////////////////////////////////////////////////////////////////////// diff --git a/src/cpu/exetrace.hh b/src/cpu/exetrace.hh index 84660432b..e5b22c881 100644 --- a/src/cpu/exetrace.hh +++ b/src/cpu/exetrace.hh @@ -47,11 +47,15 @@ class ExeTracerRecord : public InstRecord { public: ExeTracerRecord(Tick _when, ThreadContext *_thread, - const StaticInstPtr &_staticInst, Addr _pc, bool spec) - : InstRecord(_when, _thread, _staticInst, _pc, spec) + const StaticInstPtr _staticInst, Addr _pc, bool spec, + const StaticInstPtr _macroStaticInst = NULL, MicroPC _upc = 0) + : InstRecord(_when, _thread, _staticInst, _pc, spec, + _macroStaticInst, _upc) { } + void traceInst(StaticInstPtr inst, bool ran); + void dump(); }; @@ -64,7 +68,8 @@ class ExeTracer : public InstTracer InstRecord * getInstRecord(Tick when, ThreadContext *tc, - const StaticInstPtr staticInst, Addr pc) + const StaticInstPtr staticInst, Addr pc, + const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0) { if (!IsOn(ExecEnable)) return NULL; @@ -76,7 +81,7 @@ class ExeTracer : public InstTracer return NULL; return new ExeTracerRecord(when, tc, - staticInst, pc, tc->misspeculating()); + staticInst, pc, tc->misspeculating(), macroStaticInst, upc); } }; diff --git a/src/cpu/inteltrace.hh b/src/cpu/inteltrace.hh index 5d5bcda8e..e34658b58 100644 --- a/src/cpu/inteltrace.hh +++ b/src/cpu/inteltrace.hh @@ -47,8 +47,10 @@ class IntelTraceRecord : public InstRecord { public: IntelTraceRecord(Tick _when, ThreadContext *_thread, - const StaticInstPtr &_staticInst, Addr _pc, bool spec) - : InstRecord(_when, _thread, _staticInst, _pc, spec) + const StaticInstPtr _staticInst, Addr _pc, bool spec, + const StaticInstPtr _macroStaticInst = NULL, MicroPC _upc = 0) + : InstRecord(_when, _thread, _staticInst, _pc, spec, + _macroStaticInst, _upc) { } @@ -64,7 +66,8 @@ class IntelTrace : public InstTracer IntelTraceRecord * getInstRecord(Tick when, ThreadContext *tc, - const StaticInstPtr staticInst, Addr pc) + const StaticInstPtr staticInst, Addr pc, + const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0) { if (!IsOn(ExecEnable)) return NULL; @@ -76,7 +79,7 @@ class IntelTrace : public InstTracer return NULL; return new IntelTraceRecord(when, tc, - staticInst, pc, tc->misspeculating()); + staticInst, pc, tc->misspeculating(), macroStaticInst, upc); } }; diff --git a/src/cpu/legiontrace.hh b/src/cpu/legiontrace.hh index 97193ff1a..9962063e4 100644 --- a/src/cpu/legiontrace.hh +++ b/src/cpu/legiontrace.hh @@ -46,8 +46,10 @@ class LegionTraceRecord : public InstRecord { public: LegionTraceRecord(Tick _when, ThreadContext *_thread, - const StaticInstPtr &_staticInst, Addr _pc, bool spec) - : InstRecord(_when, _thread, _staticInst, _pc, spec) + const StaticInstPtr _staticInst, Addr _pc, bool spec, + const StaticInstPtr _macroStaticInst = NULL, MicroPC _upc = 0) + : InstRecord(_when, _thread, _staticInst, _pc, spec, + _macroStaticInst, _upc) { } @@ -63,13 +65,14 @@ class LegionTrace : public InstTracer LegionTraceRecord * getInstRecord(Tick when, ThreadContext *tc, - const StaticInstPtr staticInst, Addr pc) + const StaticInstPtr staticInst, Addr pc, + const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0) { if (tc->misspeculating()) return NULL; return new LegionTraceRecord(when, tc, - staticInst, pc, tc->misspeculating()); + staticInst, pc, tc->misspeculating(), macroStaticInst, upc); } }; diff --git a/src/cpu/nativetrace.hh b/src/cpu/nativetrace.hh index ab038c4c3..9e912d92f 100644 --- a/src/cpu/nativetrace.hh +++ b/src/cpu/nativetrace.hh @@ -54,8 +54,11 @@ class NativeTraceRecord : public InstRecord public: NativeTraceRecord(NativeTrace * _parent, Tick _when, ThreadContext *_thread, - const StaticInstPtr &_staticInst, Addr _pc, bool spec) - : InstRecord(_when, _thread, _staticInst, _pc, spec), parent(_parent) + const StaticInstPtr _staticInst, Addr _pc, bool spec, + const StaticInstPtr _macroStaticInst = NULL, MicroPC _upc = 0) + : InstRecord(_when, _thread, _staticInst, _pc, spec, + _macroStaticInst, _upc), + parent(_parent) { } @@ -192,13 +195,14 @@ class NativeTrace : public InstTracer NativeTraceRecord * getInstRecord(Tick when, ThreadContext *tc, - const StaticInstPtr staticInst, Addr pc) + const StaticInstPtr staticInst, Addr pc, + const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0) { if (tc->misspeculating()) return NULL; return new NativeTraceRecord(this, when, tc, - staticInst, pc, tc->misspeculating()); + staticInst, pc, tc->misspeculating(), macroStaticInst, upc); } void diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index b3379cddb..3c154afb6 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -418,8 +418,9 @@ BaseSimpleCPU::preExecute() if(curStaticInst) { #if TRACING_ON - traceData = tracer->getInstRecord(curTick, tc, curStaticInst, - thread->readPC()); + traceData = tracer->getInstRecord(curTick, tc, + curStaticInst, thread->readPC(), + curMacroStaticInst, thread->readMicroPC()); DPRINTF(Decode,"Decode: Decoded %s instruction: 0x%x\n", curStaticInst->getName(), curStaticInst->machInst); diff --git a/src/sim/insttracer.hh b/src/sim/insttracer.hh index 39a5536b0..9fb5f9f22 100644 --- a/src/sim/insttracer.hh +++ b/src/sim/insttracer.hh @@ -55,6 +55,8 @@ class InstRecord // dump the record StaticInstPtr staticInst; Addr PC; + StaticInstPtr macroStaticInst; + MicroPC upc; bool misspeculating; // The remaining fields are only valid for particular instruction @@ -86,10 +88,13 @@ class InstRecord public: InstRecord(Tick _when, ThreadContext *_thread, - const StaticInstPtr &_staticInst, - Addr _pc, bool spec) + const StaticInstPtr _staticInst, + Addr _pc, bool spec, + const StaticInstPtr _macroStaticInst = NULL, + MicroPC _upc = 0) : when(_when), thread(_thread), staticInst(_staticInst), PC(_pc), + macroStaticInst(_macroStaticInst), upc(_upc), misspeculating(spec) { data_status = DataInvalid; @@ -137,7 +142,9 @@ class InstTracer : public SimObject virtual InstRecord * getInstRecord(Tick when, ThreadContext *tc, - const StaticInstPtr staticInst, Addr pc) = 0; + const StaticInstPtr staticInst, Addr pc, + const StaticInstPtr macroStaticInst = NULL, + MicroPC _upc = 0) = 0; }; -- cgit v1.2.3 From 7b7a72158ab194864e7985e68fc5161b563b44a8 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 6 Jan 2009 22:40:41 -0800 Subject: X86: Change indentation on microop disassembly. --- src/arch/x86/insts/static_inst.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/arch/x86/insts/static_inst.cc b/src/arch/x86/insts/static_inst.cc index 0c1508d5a..15fc4bee6 100644 --- a/src/arch/x86/insts/static_inst.cc +++ b/src/arch/x86/insts/static_inst.cc @@ -63,13 +63,13 @@ namespace X86ISA void X86StaticInst::printMnemonic(std::ostream &os, const char * mnemonic) const { - ccprintf(os, "\t%s ", mnemonic); + ccprintf(os, " %s ", mnemonic); } void X86StaticInst::printMnemonic(std::ostream &os, const char * instMnemonic, const char * mnemonic) const { - ccprintf(os, "\t%s : %s ", instMnemonic, mnemonic); + ccprintf(os, " %s : %s ", instMnemonic, mnemonic); } void X86StaticInst::printSegment(std::ostream &os, int segment) const -- cgit v1.2.3 From 9e24d8c599a3090f3ce59a608ff887ac434aa1ca Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 6 Jan 2009 22:44:59 -0800 Subject: X86: Move the macroop class out of the isa description into C++. --- src/arch/x86/insts/macroop.hh | 119 ++++++++++++++++++++++++++++++++++++++++++ src/arch/x86/isa/includes.isa | 1 + src/arch/x86/isa/macroop.isa | 50 ++---------------- 3 files changed, 124 insertions(+), 46 deletions(-) create mode 100644 src/arch/x86/insts/macroop.hh (limited to 'src') diff --git a/src/arch/x86/insts/macroop.hh b/src/arch/x86/insts/macroop.hh new file mode 100644 index 000000000..d89a693ba --- /dev/null +++ b/src/arch/x86/insts/macroop.hh @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * 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: Gabe Black + */ + +#ifndef __ARCH_X86_INSTS_MACROOP_HH__ +#define __ARCH_X86_INSTS_MACROOP_HH__ + +#include "arch/x86/emulenv.hh" +#include "arch/x86/types.hh" +#include "arch/x86/insts/static_inst.hh" + +namespace X86ISA +{ +// Base class for combinationally generated macroops +class MacroopBase : public StaticInst +{ + protected: + const uint32_t numMicroops; + X86ISA::EmulEnv emulEnv; + + //Constructor. + MacroopBase(const char *mnem, ExtMachInst _machInst, + uint32_t _numMicroops, X86ISA::EmulEnv _emulEnv) + : StaticInst(mnem, _machInst, No_OpClass), + numMicroops(_numMicroops), emulEnv(_emulEnv) + { + assert(numMicroops); + microops = new StaticInstPtr[numMicroops]; + flags[IsMacroop] = true; + } + + ~MacroopBase() + { + delete [] microops; + } + + StaticInstPtr * microops; + + StaticInstPtr fetchMicroop(MicroPC microPC) + { + assert(microPC < numMicroops); + return microops[microPC]; + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + return mnemonic; + } + + public: + ExtMachInst + getExtMachInst() + { + return machInst; + } + + X86ISA::EmulEnv + getEmulEnv() + { + return emulEnv; + } +}; +} + +#endif //__ARCH_X86_INSTS_MACROOP_HH__ diff --git a/src/arch/x86/isa/includes.isa b/src/arch/x86/isa/includes.isa index e523b7e32..cddc4247c 100644 --- a/src/arch/x86/isa/includes.isa +++ b/src/arch/x86/isa/includes.isa @@ -97,6 +97,7 @@ output header {{ #include #include "arch/x86/emulenv.hh" +#include "arch/x86/insts/macroop.hh" #include "arch/x86/insts/microfpop.hh" #include "arch/x86/insts/microldstop.hh" #include "arch/x86/insts/microregop.hh" diff --git a/src/arch/x86/isa/macroop.isa b/src/arch/x86/isa/macroop.isa index 7d94dd95c..c5134f336 100644 --- a/src/arch/x86/isa/macroop.isa +++ b/src/arch/x86/isa/macroop.isa @@ -72,56 +72,14 @@ def template MacroExecPanic {{ output header {{ // Base class for combinationally generated macroops - class Macroop : public StaticInst + class Macroop : public X86ISA::MacroopBase { - protected: - const uint32_t numMicroops; - X86ISA::EmulEnv emulEnv; - - //Constructor. + public: Macroop(const char *mnem, ExtMachInst _machInst, uint32_t _numMicroops, X86ISA::EmulEnv _emulEnv) - : StaticInst(mnem, _machInst, No_OpClass), - numMicroops(_numMicroops), emulEnv(_emulEnv) - { - assert(numMicroops); - microops = new StaticInstPtr[numMicroops]; - flags[IsMacroop] = true; - } - - ~Macroop() - { - delete [] microops; - } - - StaticInstPtr * microops; - - StaticInstPtr fetchMicroop(MicroPC microPC) - { - assert(microPC < numMicroops); - return microops[microPC]; - } - - std::string generateDisassembly(Addr pc, - const SymbolTable *symtab) const - { - return mnemonic; - } - - public: + : MacroopBase(mnem, _machInst, _numMicroops, _emulEnv) + {} %(MacroExecPanic)s - - ExtMachInst - getExtMachInst() - { - return machInst; - } - - X86ISA::EmulEnv - getEmulEnv() - { - return emulEnv; - } }; }}; -- cgit v1.2.3 From 8cab1805f9854d74b4a73c5c3b316aa7ad2d2177 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 6 Jan 2009 22:46:28 -0800 Subject: X86: Move the function that prints memory args into the inst base class. --- src/arch/x86/insts/microldstop.cc | 29 ++--------------------------- src/arch/x86/insts/static_inst.cc | 38 ++++++++++++++++++++++++++++++++++++++ src/arch/x86/insts/static_inst.hh | 3 +++ 3 files changed, 43 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/arch/x86/insts/microldstop.cc b/src/arch/x86/insts/microldstop.cc index 9638a2ae3..7cc6a330f 100644 --- a/src/arch/x86/insts/microldstop.cc +++ b/src/arch/x86/insts/microldstop.cc @@ -64,7 +64,6 @@ namespace X86ISA const SymbolTable *symtab) const { std::stringstream response; - bool someAddr = false; printMnemonic(response, instMnem, mnemonic); if(flags[IsLoad]) @@ -72,32 +71,8 @@ namespace X86ISA else printSrcReg(response, 2, dataSize); response << ", "; - printSegment(response, segment); - response << ":["; - if(scale != 0 && _srcRegIdx[0] != ZeroReg) - { - if(scale != 1) - ccprintf(response, "%d*", scale); - printSrcReg(response, 0, addressSize); - someAddr = true; - } - if(_srcRegIdx[1] != ZeroReg) - { - if(someAddr) - response << " + "; - printSrcReg(response, 1, addressSize); - someAddr = true; - } - if(disp != 0) - { - if(someAddr) - response << " + "; - ccprintf(response, "%#x", disp); - someAddr = true; - } - if(!someAddr) - response << "0"; - response << "]"; + printMem(response, segment, scale, index, base, disp, + addressSize, false); return response.str(); } } diff --git a/src/arch/x86/insts/static_inst.cc b/src/arch/x86/insts/static_inst.cc index 15fc4bee6..f4ed44603 100644 --- a/src/arch/x86/insts/static_inst.cc +++ b/src/arch/x86/insts/static_inst.cc @@ -240,6 +240,44 @@ namespace X86ISA } } + void X86StaticInst::printMem(std::ostream &os, uint8_t segment, + uint8_t scale, RegIndex index, RegIndex base, + uint64_t disp, uint8_t addressSize, bool rip) const + { + bool someAddr = false; + printSegment(os, segment); + os << ":["; + if (rip) { + os << "rip"; + someAddr = true; + } else { + if (scale != 0 && index != ZeroReg) + { + if(scale != 1) + ccprintf(os, "%d*", scale); + printReg(os, index, addressSize); + someAddr = true; + } + if (base != ZeroReg) + { + if(someAddr) + os << " + "; + printReg(os, base, addressSize); + someAddr = true; + } + } + if (disp != 0) + { + if(someAddr) + os << " + "; + ccprintf(os, "%#x", disp); + someAddr = true; + } + if (!someAddr) + os << "0"; + os << "]"; + } + std::string X86StaticInst::generateDisassembly(Addr pc, const SymbolTable *symtab) const { diff --git a/src/arch/x86/insts/static_inst.hh b/src/arch/x86/insts/static_inst.hh index e5c333e75..8480f2713 100644 --- a/src/arch/x86/insts/static_inst.hh +++ b/src/arch/x86/insts/static_inst.hh @@ -89,6 +89,9 @@ namespace X86ISA void printReg(std::ostream &os, int reg, int size) const; void printSrcReg(std::ostream &os, int reg, int size) const; void printDestReg(std::ostream &os, int reg, int size) const; + void printMem(std::ostream &os, uint8_t segment, + uint8_t scale, RegIndex index, RegIndex base, + uint64_t disp, uint8_t addressSize, bool rip) const; inline uint64_t merge(uint64_t into, uint64_t val, int size) const { -- cgit v1.2.3 From 115b1a7ed350b9f1171b3f1b39c4c0875d1c0a5f Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 6 Jan 2009 22:55:27 -0800 Subject: X86: Autogenerate macroop generateDisassemble function. --- src/arch/x86/insts/macroop.hh | 18 +++++---- src/arch/x86/isa/macroop.isa | 71 ++++++++++++++++++++++++++++++------ src/arch/x86/isa/microops/base.isa | 2 +- src/arch/x86/isa/microops/debug.isa | 2 +- src/arch/x86/isa/microops/fpop.isa | 2 +- src/arch/x86/isa/microops/ldstop.isa | 2 +- src/arch/x86/isa/microops/limmop.isa | 2 +- src/arch/x86/isa/microops/regop.isa | 2 +- src/arch/x86/isa/microops/seqop.isa | 2 +- src/arch/x86/isa/microops/specop.isa | 4 +- src/arch/x86/isa/specialize.isa | 46 +++++++++++++++++++++-- 11 files changed, 121 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/arch/x86/insts/macroop.hh b/src/arch/x86/insts/macroop.hh index d89a693ba..d6925a1a5 100644 --- a/src/arch/x86/insts/macroop.hh +++ b/src/arch/x86/insts/macroop.hh @@ -65,17 +65,19 @@ namespace X86ISA { // Base class for combinationally generated macroops -class MacroopBase : public StaticInst +class MacroopBase : public X86StaticInst { protected: + const char *macrocodeBlock; + const uint32_t numMicroops; - X86ISA::EmulEnv emulEnv; + X86ISA::EmulEnv env; //Constructor. MacroopBase(const char *mnem, ExtMachInst _machInst, - uint32_t _numMicroops, X86ISA::EmulEnv _emulEnv) - : StaticInst(mnem, _machInst, No_OpClass), - numMicroops(_numMicroops), emulEnv(_emulEnv) + uint32_t _numMicroops, X86ISA::EmulEnv _env) : + X86StaticInst(mnem, _machInst, No_OpClass), + numMicroops(_numMicroops), env(_env) { assert(numMicroops); microops = new StaticInstPtr[numMicroops]; @@ -95,8 +97,8 @@ class MacroopBase : public StaticInst return microops[microPC]; } - std::string generateDisassembly(Addr pc, - const SymbolTable *symtab) const + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const { return mnemonic; } @@ -111,7 +113,7 @@ class MacroopBase : public StaticInst X86ISA::EmulEnv getEmulEnv() { - return emulEnv; + return env; } }; } diff --git a/src/arch/x86/isa/macroop.isa b/src/arch/x86/isa/macroop.isa index c5134f336..8eaf5f786 100644 --- a/src/arch/x86/isa/macroop.isa +++ b/src/arch/x86/isa/macroop.isa @@ -76,8 +76,8 @@ output header {{ { public: Macroop(const char *mnem, ExtMachInst _machInst, - uint32_t _numMicroops, X86ISA::EmulEnv _emulEnv) - : MacroopBase(mnem, _machInst, _numMicroops, _emulEnv) + uint32_t _numMicroops, X86ISA::EmulEnv _env) + : MacroopBase(mnem, _machInst, _numMicroops, _env) {} %(MacroExecPanic)s }; @@ -102,22 +102,42 @@ def template MacroDeclare {{ %(declareLabels)s public: // Constructor. - %(class_name)s(ExtMachInst machInst, X86ISA::EmulEnv env); + %(class_name)s(ExtMachInst machInst, X86ISA::EmulEnv _env); + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; }; }}; +def template MacroDisassembly {{ + std::string + X86Macroop::%(class_name)s::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream out; + out << mnemonic << "\t"; + + int regSize = %(regSize)s; + %(disassembly)s + // Shut up gcc. + regSize = regSize; + return out.str(); + } +}}; + // Basic instruction class constructor template. def template MacroConstructor {{ inline X86Macroop::%(class_name)s::%(class_name)s( - ExtMachInst machInst, EmulEnv env) - : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s, env) + ExtMachInst machInst, EmulEnv _env) + : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s, _env) { %(adjust_env)s; %(adjust_imm)s; %(adjust_disp)s; %(do_modrm)s; %(constructor)s; + const char *macrocodeBlock = "%(class_name)s"; //alloc_microops is the code that sets up the microops //array in the parent class. %(alloc_microops)s; @@ -158,7 +178,12 @@ let {{ adjustedDisp = adjustedDisp; ''' def getAllocator(self, env): - return "new X86Macroop::%s(machInst, %s)" % (self.name, env.getAllocator()) + return "new X86Macroop::%s(machInst, %s)" % \ + (self.name, env.getAllocator()) + def getMnemonic(self): + mnemonic = self.name.lower() + mnemonic = re.match(r'[^_]*', mnemonic).group(0) + return mnemonic def getDeclaration(self): #FIXME This first parameter should be the mnemonic. I need to #write some code which pulls that out @@ -166,12 +191,12 @@ let {{ for (label, microop) in self.labels.items(): declareLabels += "const static uint64_t label_%s = %d;\n" \ % (label, microop.micropc) - iop = InstObjParams(self.name, self.name, "Macroop", + iop = InstObjParams(self.getMnemonic(), self.name, "Macroop", {"code" : "", "declareLabels" : declareLabels }) return MacroDeclare.subst(iop); - def getDefinition(self): + def getDefinition(self, env): #FIXME This first parameter should be the mnemonic. I need to #write some code which pulls that out numMicroops = len(self.microops) @@ -184,14 +209,28 @@ let {{ (micropc, op.getAllocator(True, not isLast, micropc == 0, isLast)) micropc += 1 - iop = InstObjParams(self.name, self.name, "Macroop", + if env.useStackSize: + useStackSize = "true" + else: + useStackSize = "false" + if env.memoryInst: + memoryInst = "true" + else: + memoryInst = "false" + regSize = '''(%s || (env.base == INTREG_RSP && %s) ? + env.stackSize : + env.dataSize)''' % (useStackSize, memoryInst) + iop = InstObjParams(self.getMnemonic(), self.name, "Macroop", {"code" : "", "num_microops" : numMicroops, "alloc_microops" : allocMicroops, "adjust_env" : self.adjust_env, "adjust_imm" : self.adjust_imm, "adjust_disp" : self.adjust_disp, + "disassembly" : env.disassembly, + "regSize" : regSize, "do_modrm" : self.doModRM}) - return MacroConstructor.subst(iop); + return MacroConstructor.subst(iop) + \ + MacroDisassembly.subst(iop); }}; let {{ @@ -207,6 +246,16 @@ let {{ self.dataSize = "OPSIZE" self.stackSize = "STACKSIZE" self.doModRM = False + self.disassembly = "" + self.firstArgument = True + self.useStackSize = False + self.memoryInst = False + + def addToDisassembly(self, code): + if not self.firstArgument: + self.disassembly += "out << \", \";\n" + self.firstArgument = False + self.disassembly += code def getAllocator(self): if self.size == 'b': @@ -264,7 +313,7 @@ let {{ if env.doModRM: macroop.doModRM = doModRMString blocks.header_output = macroop.getDeclaration() - blocks.decoder_output = macroop.getDefinition() + blocks.decoder_output = macroop.getDefinition(env) macroop.declared = True blocks.decode_block = "return %s;\n" % macroop.getAllocator(env) return blocks diff --git a/src/arch/x86/isa/microops/base.isa b/src/arch/x86/isa/microops/base.isa index 2b73cf563..f1007bf71 100644 --- a/src/arch/x86/isa/microops/base.isa +++ b/src/arch/x86/isa/microops/base.isa @@ -76,7 +76,7 @@ let {{ StaticInstPtr ''' + generatorNameTemplate + '''(StaticInstPtr curMacroop) { - static const char * mnemonic = romMnemonic; + static const char *macrocodeBlock = romMnemonic; static const ExtMachInst dummyExtMachInst; static const EmulEnv dummyEmulEnv(0, 0, 1, 1, 1); diff --git a/src/arch/x86/isa/microops/debug.isa b/src/arch/x86/isa/microops/debug.isa index 895e97199..38fee59bb 100644 --- a/src/arch/x86/isa/microops/debug.isa +++ b/src/arch/x86/isa/microops/debug.isa @@ -183,7 +183,7 @@ let {{ self.cond = "0" def getAllocator(self, *microFlags): - allocator = '''new %(class_name)s(machInst, mnemonic + allocator = '''new %(class_name)s(machInst, macrocodeBlock %(flags)s, "%(message)s", %(cc)s)''' % { "class_name" : self.className, "flags" : self.microFlagsText(microFlags), diff --git a/src/arch/x86/isa/microops/fpop.isa b/src/arch/x86/isa/microops/fpop.isa index 2919aa277..d4acfdbf4 100644 --- a/src/arch/x86/isa/microops/fpop.isa +++ b/src/arch/x86/isa/microops/fpop.isa @@ -245,7 +245,7 @@ let {{ self.className += "Top" def getAllocator(self, *microFlags): - return '''new %(class_name)s(machInst, mnemonic + return '''new %(class_name)s(machInst, macrocodeBlock %(flags)s, %(src1)s, %(src2)s, %(dest)s, %(dataSize)s, %(spm)d)''' % { "class_name" : self.className, diff --git a/src/arch/x86/isa/microops/ldstop.isa b/src/arch/x86/isa/microops/ldstop.isa index 30a7c8801..8a0af14be 100644 --- a/src/arch/x86/isa/microops/ldstop.isa +++ b/src/arch/x86/isa/microops/ldstop.isa @@ -362,7 +362,7 @@ let {{ self.addressSize = addressSize def getAllocator(self, *microFlags): - allocator = '''new %(class_name)s(machInst, mnemonic + allocator = '''new %(class_name)s(machInst, macrocodeBlock %(flags)s, %(scale)s, %(index)s, %(base)s, %(disp)s, %(segment)s, %(data)s, %(dataSize)s, %(addressSize)s)''' % { diff --git a/src/arch/x86/isa/microops/limmop.isa b/src/arch/x86/isa/microops/limmop.isa index 6686444fd..4e75ab8b0 100644 --- a/src/arch/x86/isa/microops/limmop.isa +++ b/src/arch/x86/isa/microops/limmop.isa @@ -154,7 +154,7 @@ let {{ self.dataSize = dataSize def getAllocator(self, *microFlags): - allocator = '''new %(class_name)s(machInst, mnemonic + allocator = '''new %(class_name)s(machInst, macrocodeBlock %(flags)s, %(dest)s, %(imm)s, %(dataSize)s)''' % { "class_name" : self.className, "mnemonic" : self.mnemonic, diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 944d5e9ec..492452a51 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -438,7 +438,7 @@ let {{ className = self.className if self.mnemonic == self.base_mnemonic + 'i': className += "Imm" - allocator = '''new %(class_name)s(machInst, mnemonic + allocator = '''new %(class_name)s(machInst, macrocodeBlock %(flags)s, %(src1)s, %(op2)s, %(dest)s, %(dataSize)s, %(ext)s)''' % { "class_name" : className, diff --git a/src/arch/x86/isa/microops/seqop.isa b/src/arch/x86/isa/microops/seqop.isa index f03094f66..332519b87 100644 --- a/src/arch/x86/isa/microops/seqop.isa +++ b/src/arch/x86/isa/microops/seqop.isa @@ -181,7 +181,7 @@ let {{ self.cond = "0" def getAllocator(self, *microFlags): - allocator = '''new %(class_name)s(machInst, mnemonic + allocator = '''new %(class_name)s(machInst, macrocodeBlock %(flags)s, %(target)s, %(cc)s)''' % { "class_name" : self.className, "flags" : self.microFlagsText(microFlags), diff --git a/src/arch/x86/isa/microops/specop.isa b/src/arch/x86/isa/microops/specop.isa index ad14b54a3..c6e172ef1 100644 --- a/src/arch/x86/isa/microops/specop.isa +++ b/src/arch/x86/isa/microops/specop.isa @@ -230,7 +230,7 @@ let {{ self.cond = "0" def getAllocator(self, *microFlags): - allocator = '''new %(class_name)s(machInst, mnemonic + allocator = '''new %(class_name)s(machInst, macrocodeBlock %(flags)s, %(fault)s, %(cc)s)''' % { "class_name" : self.className, "flags" : self.microFlagsText(microFlags), @@ -257,7 +257,7 @@ let {{ pass def getAllocator(self, *microFlags): - return "new MicroHalt(machInst, mnemonic %s)" % \ + return "new MicroHalt(machInst, macrocodeBlock %s)" % \ self.microFlagsText(microFlags) microopClasses["halt"] = Halt diff --git a/src/arch/x86/isa/specialize.isa b/src/arch/x86/isa/specialize.isa index abf734307..b74363470 100644 --- a/src/arch/x86/isa/specialize.isa +++ b/src/arch/x86/isa/specialize.isa @@ -86,8 +86,17 @@ let {{ let {{ def doRipRelativeDecode(Name, opTypes, env): # print "RIPing %s with opTypes %s" % (Name, opTypes) - normBlocks = specializeInst(Name + "_M", copy.copy(opTypes), copy.copy(env)) - ripBlocks = specializeInst(Name + "_P", copy.copy(opTypes), copy.copy(env)) + env.memoryInst = True + normEnv = copy.copy(env) + normEnv.addToDisassembly( + '''printMem(out, env.seg, env.scale, env.index, env.base, + machInst.displacement, env.addressSize, false);''') + normBlocks = specializeInst(Name + "_M", copy.copy(opTypes), normEnv) + ripEnv = copy.copy(env) + ripEnv.addToDisassembly( + '''printMem(out, env.seg, 1, 0, 0, + machInst.displacement, env.addressSize, true);''') + ripBlocks = specializeInst(Name + "_P", copy.copy(opTypes), ripEnv) blocks = OutputBlocks() blocks.append(normBlocks) @@ -138,12 +147,17 @@ let {{ #Figure out what to do with fixed register operands #This is the index to use, so we should stick it some place. if opType.reg in ("A", "B", "C", "D"): - env.addReg("INTREG_R%sX" % opType.reg) + regString = "INTREG_R%sX" % opType.reg else: - env.addReg("INTREG_R%s" % opType.reg) + regString = "INTREG_R%s" % opType.reg + env.addReg(regString) + env.addToDisassembly( + "printReg(out, %s, regSize);\n" % regString) Name += "_R" elif opType.tag == "B": # This refers to registers whose index is encoded as part of the opcode + env.addToDisassembly( + "printReg(out, %s, regSize);\n" % InstRegIndex) Name += "_R" env.addReg(InstRegIndex) elif opType.tag == "M": @@ -156,24 +170,34 @@ let {{ elif opType.tag == "C": # A control register indexed by the "reg" field env.addReg(ModRMRegIndex) + env.addToDisassembly( + "ccprintf(out, \"CR%%d\", %s);\n" % ModRMRegIndex) Name += "_C" elif opType.tag == "D": # A debug register indexed by the "reg" field env.addReg(ModRMRegIndex) + env.addToDisassembly( + "ccprintf(out, \"DR%%d\", %s);\n" % ModRMRegIndex) Name += "_D" elif opType.tag == "S": # A segment selector register indexed by the "reg" field env.addReg(ModRMRegIndex) + env.addToDisassembly( + "printSegment(out, %s);\n" % ModRMRegIndex) Name += "_S" elif opType.tag in ("G", "P", "T", "V"): # Use the "reg" field of the ModRM byte to select the register env.addReg(ModRMRegIndex) + env.addToDisassembly( + "printReg(out, %s, regSize);\n" % ModRMRegIndex) Name += "_R" elif opType.tag in ("E", "Q", "W"): # This might refer to memory or to a register. We need to # divide it up farther. regEnv = copy.copy(env) regEnv.addReg(ModRMRMIndex) + regEnv.addToDisassembly( + "printReg(out, %s, regSize);\n" % ModRMRMIndex) # This refers to memory. The macroop constructor should set up # modrm addressing. memEnv = copy.copy(env) @@ -183,6 +207,8 @@ let {{ (doRipRelativeDecode, Name, copy.copy(opTypes), memEnv)) elif opType.tag in ("I", "J"): # Immediates + env.addToDisassembly( + "ccprintf(out, \"%#x\", machInst.immediate);\n") Name += "_I" elif opType.tag == "O": # Immediate containing a memory offset @@ -190,10 +216,22 @@ let {{ elif opType.tag in ("PR", "R", "VR"): # Non register modrm settings should cause an error env.addReg(ModRMRMIndex) + env.addToDisassembly( + "printReg(out, %s, regSize);\n" % ModRMRMIndex) Name += "_R" elif opType.tag in ("X", "Y"): # This type of memory addressing is for string instructions. # They'll use the right index and segment internally. + if opType.tag == "X": + env.addToDisassembly( + '''printMem(out, env.seg, + 1, X86ISA::ZeroReg, X86ISA::INTREG_RSI, 0, + env.addressSize, false);''') + else: + env.addToDisassembly( + '''printMem(out, SEGMENT_REG_ES, + 1, X86ISA::ZeroReg, X86ISA::INTREG_RDI, 0, + env.addressSize, false);''') Name += "_M" else: raise Exception, "Unrecognized tag %s." % opType.tag -- cgit v1.2.3 From b23633ad1b3210d54386a9bab8c453f2bb4b7874 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 6 Jan 2009 23:55:46 -0800 Subject: X86: Hook in the M5 pseudo insts. --- src/arch/x86/isa/decoder/two_byte_opcodes.isa | 92 ++++++++++++++++++++++++++- src/arch/x86/isa/formats/basic.isa | 8 +++ src/arch/x86/isa/includes.isa | 1 + src/arch/x86/isa/operands.isa | 4 ++ src/arch/x86/predecoder_tables.cc | 2 +- 5 files changed, 104 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index b8013165e..4ebe03d84 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -163,8 +163,96 @@ } 0x02: lar_Gv_Ew(); 0x03: lsl_Gv_Ew(); - //sandpile.org doesn't seem to know what this is... ? - 0x04: loadall_or_reset_or_hang(); + // sandpile.org doesn't seem to know what this is...? We'll + // use it for pseudo instructions. We've got 16 bits of space + // to play with so there can be quite a few pseudo + // instructions. + //0x04: loadall_or_reset_or_hang(); + 0x4: decode IMMEDIATE { + format BasicOperate { +#if FULL_SYSTEM + 0x00: m5arm({{ + PseudoInst::arm(xc->tcBase()); + }}, IsNonSpeculative); + 0x01: m5quiesce({{ + PseudoInst::quiesce(xc->tcBase()); + }}, IsNonSpeculative); + 0x02: m5quiesceNs({{ + PseudoInst::quiesceNs(xc->tcBase(), Rdi); + }}, IsNonSpeculative); + 0x03: m5quiesceCycle({{ + PseudoInst::quiesceCycles(xc->tcBase(), Rdi); + }}, IsNonSpeculative); + 0x04: m5quiesceTime({{ + Rax = PseudoInst::quiesceTime(xc->tcBase()); + }}, IsNonSpeculative); +#endif + 0x07: m5rpns({{ + Rax = PseudoInst::rpns(xc->tcBase()); + }}, IsNonSpeculative); + 0x21: m5exit({{ + PseudoInst::m5exit(xc->tcBase(), Rdi); + }}, IsNonSpeculative); +#if FULL_SYSTEM + 0x30: m5initparam({{ + Rax = xc->tcBase()->getCpuPtr()-> + system->init_param; + }}, IsNonSpeculative); + 0x31: m5loadsymbol({{ + PseudoInst::loadsymbol(xc->tcBase()); + }}, IsNonSpeculative); +#endif + 0x40: m5resetstats({{ + PseudoInst::resetstats(xc->tcBase(), Rdi, Rsi); + }}, IsNonSpeculative); + 0x41: m5dumpstats({{ + PseudoInst::dumpstats(xc->tcBase(), Rdi, Rsi); + }}, IsNonSpeculative); + 0x42: m5dumpresetstats({{ + PseudoInst::dumpresetstats(xc->tcBase(), Rdi, Rsi); + }}, IsNonSpeculative); + 0x43: m5checkpoint({{ + PseudoInst::m5checkpoint(xc->tcBase(), Rdi, Rsi); + }}, IsNonSpeculative); +#if FULL_SYSTEM + 0x50: m5readfile({{ + Rax = PseudoInst::readfile( + xc->tcBase(), Rdi, Rsi, Rdx); + }}, IsNonSpeculative); +#endif + 0x51: m5debugbreak({{ + PseudoInst::debugbreak(xc->tcBase()); + }}, IsNonSpeculative); + 0x52: m5switchcpu({{ + PseudoInst::switchcpu(xc->tcBase()); + }}, IsNonSpeculative); +#if FULL_SYSTEM + 0x53: m5addsymbol({{ + PseudoInst::addsymbol(xc->tcBase(), Rdi, Rsi); + }}, IsNonSpeculative); +#endif + 0x54: m5panic({{ + panic("M5 panic instruction called at pc=%#x.\n", + xc->readPC()); + }}, IsNonSpeculative); + 0x55: m5reserved1({{ + warn("M5 reserved opcode 1 ignored.\n"); + }}, IsNonSpeculative); + 0x56: m5reserved2({{ + warn("M5 reserved opcode 2 ignored.\n"); + }}, IsNonSpeculative); + 0x57: m5reserved3({{ + warn("M5 reserved opcode 3 ignored.\n"); + }}, IsNonSpeculative); + 0x58: m5reserved4({{ + warn("M5 reserved opcode 4 ignored.\n"); + }}, IsNonSpeculative); + 0x59: m5reserved5({{ + warn("M5 reserved opcode 5 ignored.\n"); + }}, IsNonSpeculative); + default: Inst::UD2(); + } + } #if FULL_SYSTEM 0x05: syscall(); #else diff --git a/src/arch/x86/isa/formats/basic.isa b/src/arch/x86/isa/formats/basic.isa index 7aea7085f..b96bae238 100644 --- a/src/arch/x86/isa/formats/basic.isa +++ b/src/arch/x86/isa/formats/basic.isa @@ -147,3 +147,11 @@ def template BasicDecode {{ def template BasicDecodeWithMnemonic {{ return new %(class_name)s("%(mnemonic)s", machInst); }}; + +def format BasicOperate(code, *flags) {{ + iop = InstObjParams(name, Name, 'X86ISA::X86StaticInst', code, flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; diff --git a/src/arch/x86/isa/includes.isa b/src/arch/x86/isa/includes.isa index cddc4247c..909f2f389 100644 --- a/src/arch/x86/isa/includes.isa +++ b/src/arch/x86/isa/includes.isa @@ -156,6 +156,7 @@ output exec {{ #include "sim/sim_exit.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" +#include "sim/pseudo_inst.hh" using namespace X86ISA; using namespace std; diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa index 343b37d41..a409d1f0f 100644 --- a/src/arch/x86/isa/operands.isa +++ b/src/arch/x86/isa/operands.isa @@ -113,6 +113,10 @@ def operands {{ 'Rbx': ('IntReg', 'uqw', '(INTREG_RBX)', 'IsInteger', 13), 'Rcx': ('IntReg', 'uqw', '(INTREG_RCX)', 'IsInteger', 14), 'Rdx': ('IntReg', 'uqw', '(INTREG_RDX)', 'IsInteger', 15), + 'Rsp': ('IntReg', 'uqw', '(INTREG_RSP)', 'IsInteger', 16), + 'Rbp': ('IntReg', 'uqw', '(INTREG_RBP)', 'IsInteger', 17), + 'Rsi': ('IntReg', 'uqw', '(INTREG_RSI)', 'IsInteger', 18), + 'Rdi': ('IntReg', 'uqw', '(INTREG_RDI)', 'IsInteger', 19), 'FpSrcReg1': ('FloatReg', 'df', 'src1', 'IsFloating', 20), 'FpSrcReg2': ('FloatReg', 'df', 'src2', 'IsFloating', 21), 'FpDestReg': ('FloatReg', 'df', 'dest', 'IsFloating', 22), diff --git a/src/arch/x86/predecoder_tables.cc b/src/arch/x86/predecoder_tables.cc index bcd5face6..5f2b5c421 100644 --- a/src/arch/x86/predecoder_tables.cc +++ b/src/arch/x86/predecoder_tables.cc @@ -201,7 +201,7 @@ namespace X86ISA //For two byte instructions { //LSB // MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F -/* 0 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , BY , +/* 0 */ 0 , 0 , 0 , 0 , WO, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , BY , /* 0 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 2 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 3 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , -- cgit v1.2.3 From 81180a3bf005586d7ca1fae77dd7888b99e45864 Mon Sep 17 00:00:00 2001 From: Richard Strong Date: Sun, 11 Jan 2009 22:45:03 -0800 Subject: This fix addresses an ill formed if statement that fails to compile. The fix was the simple addition of another set of parenthesis to ensure the correct condition resolution. --- src/cpu/exetrace.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc index 4c0f83a21..7227602b5 100644 --- a/src/cpu/exetrace.cc +++ b/src/cpu/exetrace.cc @@ -128,10 +128,10 @@ Trace::ExeTracerRecord::dump() * complete/print when they fault. */ if (IsOn(ExecMacro) && staticInst->isMicroop() && - (IsOn(ExecMicro) && + ((IsOn(ExecMicro) && macroStaticInst && staticInst->isFirstMicroop()) || (!IsOn(ExecMicro) && - macroStaticInst && staticInst->isLastMicroop())) { + macroStaticInst && staticInst->isLastMicroop()))) { traceInst(macroStaticInst, false); } if (IsOn(ExecMicro) || !staticInst->isMicroop()) { -- cgit v1.2.3 From 8153790d0004439f8e9d473da97699644234117b Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Tue, 13 Jan 2009 14:17:50 -0800 Subject: SCons: centralize the Dir() workaround for newer versions of scons. Scons bug id: 2006 M5 Bug id: 308 --- src/SConscript | 5 +++++ src/arch/mips/SConscript | 3 --- src/arch/sparc/SConscript | 4 ---- src/arch/x86/SConscript | 14 -------------- src/cpu/SConscript | 4 ---- src/kern/SConscript | 13 ------------- src/mem/SConscript | 4 ---- 7 files changed, 5 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/SConscript b/src/SConscript index 2da5830a9..a14e868fe 100644 --- a/src/SConscript +++ b/src/SConscript @@ -220,6 +220,11 @@ for extra_dir in extras_dir_list: # Add a flag defining what THE_ISA should be for all compilation env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())]) +# Workaround for bug in SCons version > 0.97d20071212 +# Scons bug id: 2006 M5 Bug id: 308 +for root, dirs, files in os.walk(base_dir, topdown=True): + Dir(root[len(base_dir) + 1:]) + ######################################################################## # # Walk the tree and execute all SConscripts in subdirectories diff --git a/src/arch/mips/SConscript b/src/arch/mips/SConscript index 0368e68bc..0b470def6 100644 --- a/src/arch/mips/SConscript +++ b/src/arch/mips/SConscript @@ -33,9 +33,6 @@ Import('*') if env['TARGET_ISA'] == 'mips': -# Workaround for bug in SCons version > 0.97d20071212 -# Scons bug id: 2006 M5 Bug id: 308 - Dir('isa/formats') Source('faults.cc') Source('regfile/int_regfile.cc') Source('regfile/float_regfile.cc') diff --git a/src/arch/sparc/SConscript b/src/arch/sparc/SConscript index 126587835..6a4c08a8e 100644 --- a/src/arch/sparc/SConscript +++ b/src/arch/sparc/SConscript @@ -32,10 +32,6 @@ Import('*') if env['TARGET_ISA'] == 'sparc': -# Workaround for bug in SCons version > 0.97d20071212 -# Scons bug id: 2006 M5 Bug id: 308 - Dir('isa/formats') - Dir('isa/formats/mem') Source('asi.cc') Source('faults.cc') Source('floatregfile.cc') diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript index c2081156d..37719e75d 100644 --- a/src/arch/x86/SConscript +++ b/src/arch/x86/SConscript @@ -357,17 +357,3 @@ if env['TARGET_ISA'] == 'x86': # Only non-header files need to be compiled. if not f.path.endswith('.hh'): Source(f) - - # Workaround for bug in SCons version > 0.97d20071212 - # Scons bug id: 2006 M5 Bug id: 308 - from os.path import dirname, join as joinpath - - Dir('isa') - Dir('isa/microops') - Dir('isa/decoder') - Dir('isa/formats') - Dir('isa/insts') - isa_dirs = set(map(lambda x:dirname(x), python_files)) - for d in isa_dirs: - Dir(joinpath('isa/insts', d)) - diff --git a/src/cpu/SConscript b/src/cpu/SConscript index 334504660..f210cec9b 100644 --- a/src/cpu/SConscript +++ b/src/cpu/SConscript @@ -149,10 +149,6 @@ if env['USE_CHECKER']: print i, print ", please set USE_CHECKER=False or use one of those CPU models" Exit(1) -# Workaround for bug in SCons version > 0.97d20071212 -# Scons bug id: 2006 M5 Bug id: 308 -else: - Dir('checker') TraceFlag('Activity') TraceFlag('Commit') diff --git a/src/kern/SConscript b/src/kern/SConscript index b905a8b41..546c4b058 100644 --- a/src/kern/SConscript +++ b/src/kern/SConscript @@ -41,22 +41,9 @@ if env['FULL_SYSTEM']: Source('linux/linux_syscalls.cc') Source('linux/printk.cc') - # Workaround for bug in SCons version > 0.97d20071212 - # Scons bug id: 2006 M5 Bug id: 308 - Dir('tru64') - if env['TARGET_ISA'] == 'alpha': Source('tru64/dump_mbuf.cc') Source('tru64/printf.cc') Source('tru64/tru64_events.cc') Source('tru64/tru64_syscalls.cc') TraceFlag('BADADDR') - -# Workaround for bug in SCons version > 0.97d20071212 -# Scons bug id: 2006 M5 Bug id: 308 -else: - Dir('linux') - if env['TARGET_ISA'] == 'alpha': - Dir('tru64') - elif env['TARGET_ISA'] == 'sparc': - Dir('solaris') diff --git a/src/mem/SConscript b/src/mem/SConscript index c181c88c6..0b0017f81 100644 --- a/src/mem/SConscript +++ b/src/mem/SConscript @@ -35,10 +35,6 @@ SimObject('Bus.py') SimObject('PhysicalMemory.py') SimObject('MemObject.py') -# Workaround for bug in SCons version > 0.97d20071212 -# Scons bug id: 2006 M5 Bug id: 308 -Dir('config') - Source('bridge.cc') Source('bus.cc') Source('dram.cc') -- cgit v1.2.3 From 140b4b891ec60496d8aa805fd694d45647ba083c Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Sat, 17 Jan 2009 18:55:09 -0500 Subject: CopyEngine: Implement a I/OAT-like copy engine. --- src/dev/CopyEngine.py | 59 ++++ src/dev/SConscript | 3 + src/dev/copy_engine.cc | 747 ++++++++++++++++++++++++++++++++++++++++++++ src/dev/copy_engine.hh | 169 ++++++++++ src/dev/copy_engine_defs.hh | 225 +++++++++++++ 5 files changed, 1203 insertions(+) create mode 100644 src/dev/CopyEngine.py create mode 100644 src/dev/copy_engine.cc create mode 100644 src/dev/copy_engine.hh create mode 100644 src/dev/copy_engine_defs.hh (limited to 'src') diff --git a/src/dev/CopyEngine.py b/src/dev/CopyEngine.py new file mode 100644 index 000000000..29d9a23dd --- /dev/null +++ b/src/dev/CopyEngine.py @@ -0,0 +1,59 @@ +# Copyright (c) 2008 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Ali Saidi + +from m5.SimObject import SimObject +from m5.params import * +from m5.proxy import * +from Pci import PciDevice + +class CopyEngine(PciDevice): + type = 'CopyEngine' + VendorID = 0x8086 + DeviceID = 0x1a38 + Revision = 0xA2 # CM2 stepping (newest listed) + SubsystemID = 0 + SubsystemVendorID = 0 + Status = 0x0000 + SubClassCode = 0x08 + ClassCode = 0x80 + ProgIF = 0x00 + MaximumLatency = 0x00 + MinimumGrant = 0xff + InterruptLine = 0x20 + InterruptPin = 0x01 + BAR0Size = '1kB' + + ChanCnt = Param.UInt8(4, "Number of DMA channels that exist on device") + XferCap = Param.MemorySize('4kB', "Number of bits of transfer size that are supported") + + + clock = Param.Clock('500MHz', "Clock speed of the device") + latBeforeBegin = Param.Latency('20ns', "Latency after a DMA command is seen before it's proccessed") + latAfterCompletion = Param.Latency('20ns', "Latency after a DMA command is complete before it's reported as such") + + diff --git a/src/dev/SConscript b/src/dev/SConscript index 2071600ba..c09ec3dcd 100644 --- a/src/dev/SConscript +++ b/src/dev/SConscript @@ -33,6 +33,7 @@ Import('*') if env['FULL_SYSTEM']: SimObject('BadDevice.py') + SimObject('CopyEngine.py') SimObject('Device.py') SimObject('DiskImage.py') SimObject('Ethernet.py') @@ -44,6 +45,7 @@ if env['FULL_SYSTEM']: SimObject('Uart.py') Source('baddev.cc') + Source('copy_engine.cc') Source('disk_image.cc') Source('etherbus.cc') Source('etherdevice.cc') @@ -73,6 +75,7 @@ if env['FULL_SYSTEM']: TraceFlag('DiskImageRead') TraceFlag('DiskImageWrite') TraceFlag('DMA') + TraceFlag('DMACopyEngine') TraceFlag('Ethernet') TraceFlag('EthernetCksum') TraceFlag('EthernetDMA') diff --git a/src/dev/copy_engine.cc b/src/dev/copy_engine.cc new file mode 100644 index 000000000..46d3127e7 --- /dev/null +++ b/src/dev/copy_engine.cc @@ -0,0 +1,747 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + +/* @file + * Device model for Intel's I/O AT DMA copy engine. + */ + +#include + +#include "base/trace.hh" +#include "dev/copy_engine.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" +#include "params/CopyEngine.hh" +#include "sim/stats.hh" +#include "sim/system.hh" + +using namespace CopyEngineReg; +using namespace std; + +CopyEngine::CopyEngine(const Params *p) + : PciDev(p) +{ + // All Reg regs are initialized to 0 by default + regs.chanCount = p->ChanCnt; + regs.xferCap = findMsbSet(p->XferCap); + regs.attnStatus = 0; + + if (regs.chanCount > 64) + fatal("CopyEngine interface doesn't support more than 64 DMA engines\n"); + + for (int x = 0; x < regs.chanCount; x++) { + CopyEngineChannel *ch = new CopyEngineChannel(this, x); + chan.push_back(ch); + } +} + + +CopyEngine::CopyEngineChannel::CopyEngineChannel(CopyEngine *_ce, int cid) + : ce(_ce), channelId(cid), busy(false), underReset(false), + refreshNext(false), latBeforeBegin(ce->params()->latBeforeBegin), + latAfterCompletion(ce->params()->latAfterCompletion), + completionDataReg(0), nextState(Idle), drainEvent(NULL), + fetchCompleteEvent(this), addrCompleteEvent(this), + readCompleteEvent(this), writeCompleteEvent(this), + statusCompleteEvent(this) + +{ + cr.status.dma_transfer_status(3); + cr.descChainAddr = 0; + cr.completionAddr = 0; + + curDmaDesc = new DmaDesc; + memset(curDmaDesc, 0, sizeof(DmaDesc)); + copyBuffer = new uint8_t[ce->params()->XferCap]; +} + +CopyEngine::~CopyEngine() +{ + for (int x = 0; x < chan.size(); x++) { + delete chan[x]; + } +} + +CopyEngine::CopyEngineChannel::~CopyEngineChannel() +{ + delete curDmaDesc; + delete [] copyBuffer; + delete cePort; +} + +void +CopyEngine::init() +{ + PciDev::init(); + for (int x = 0; x < chan.size(); x++) + chan[x]->init(); +} + +void +CopyEngine::CopyEngineChannel::init() +{ + Port *peer; + + cePort = new DmaPort(ce, ce->sys); + peer = ce->dmaPort->getPeer()->getOwner()->getPort(""); + peer->setPeer(cePort); + cePort->setPeer(peer); +} + +void +CopyEngine::CopyEngineChannel::recvCommand() +{ + if (cr.command.start_dma()) { + assert(!busy); + cr.status.dma_transfer_status(0); + nextState = DescriptorFetch; + fetchAddress = cr.descChainAddr; + if (ce->getState() == SimObject::Running) + fetchDescriptor(cr.descChainAddr); + } else if (cr.command.append_dma()) { + if (!busy) { + nextState = AddressFetch; + if (ce->getState() == SimObject::Running) + fetchNextAddr(lastDescriptorAddr); + } else + refreshNext = true; + } else if (cr.command.reset_dma()) { + if (busy) + underReset = true; + else { + cr.status.dma_transfer_status(3); + nextState = Idle; + } + } else if (cr.command.resume_dma() || cr.command.abort_dma() || + cr.command.suspend_dma()) + panic("Resume, Abort, and Suspend are not supported\n"); + cr.command(0); +} + +Tick +CopyEngine::read(PacketPtr pkt) +{ + int bar; + Addr daddr; + + if (!getBAR(pkt->getAddr(), bar, daddr)) + panic("Invalid PCI memory access to unmapped memory.\n"); + + // Only Memory register BAR is allowed + assert(bar == 0); + + int size = pkt->getSize(); + if (size != sizeof(uint64_t) && size != sizeof(uint32_t) && + size != sizeof(uint16_t) && size != sizeof(uint8_t)) { + panic("Unknown size for MMIO access: %d\n", pkt->getSize()); + } + + DPRINTF(DMACopyEngine, "Read device register %#X size: %d\n", daddr, size); + + pkt->allocate(); + + /// + /// Handle read of register here + /// + + if (daddr < 0x80) { + switch (daddr) { + case GEN_CHANCOUNT: + assert(size == sizeof(regs.chanCount)); + pkt->set(regs.chanCount); + break; + case GEN_XFERCAP: + assert(size == sizeof(regs.xferCap)); + pkt->set(regs.xferCap); + break; + case GEN_INTRCTRL: + assert(size == sizeof(uint8_t)); + pkt->set(regs.intrctrl()); + regs.intrctrl.master_int_enable(0); + break; + case GEN_ATTNSTATUS: + assert(size == sizeof(regs.attnStatus)); + pkt->set(regs.attnStatus); + regs.attnStatus = 0; + break; + default: + panic("Read request to unknown register number: %#x\n", daddr); + } + pkt->makeAtomicResponse(); + return pioDelay; + } + + + // Find which channel we're accessing + int chanid = 0; + daddr -= 0x80; + while (daddr >= 0x80) { + chanid++; + daddr -= 0x80; + } + + if (chanid >= regs.chanCount) + panic("Access to channel %d (device only configured for %d channels)", + chanid, regs.chanCount); + + /// + /// Channel registers are handled here + /// + chan[chanid]->channelRead(pkt, daddr, size); + + pkt->makeAtomicResponse(); + return pioDelay; +} + +void +CopyEngine::CopyEngineChannel::channelRead(Packet *pkt, Addr daddr, int size) +{ + switch (daddr) { + case CHAN_CONTROL: + assert(size == sizeof(uint16_t)); + pkt->set(cr.ctrl()); + cr.ctrl.in_use(1); + break; + case CHAN_STATUS: + assert(size == sizeof(uint64_t)); + pkt->set(cr.status() | ~busy); + break; + case CHAN_CHAINADDR: + assert(size == sizeof(uint64_t) || size == sizeof(uint32_t)); + if (size == sizeof(uint64_t)) + pkt->set(cr.descChainAddr); + else + pkt->set(bits(cr.descChainAddr,0,31)); + break; + case CHAN_CHAINADDR_HIGH: + assert(size == sizeof(uint32_t)); + pkt->set(bits(cr.descChainAddr,32,63)); + break; + case CHAN_COMMAND: + assert(size == sizeof(uint8_t)); + pkt->set(cr.command()); + break; + case CHAN_CMPLNADDR: + assert(size == sizeof(uint64_t) || size == sizeof(uint32_t)); + if (size == sizeof(uint64_t)) + pkt->set(cr.completionAddr); + else + pkt->set(bits(cr.completionAddr,0,31)); + break; + case CHAN_CMPLNADDR_HIGH: + assert(size == sizeof(uint32_t)); + pkt->set(bits(cr.completionAddr,32,63)); + break; + case CHAN_ERROR: + assert(size == sizeof(uint32_t)); + pkt->set(cr.error()); + break; + default: + panic("Read request to unknown channel register number: (%d)%#x\n", + channelId, daddr); + } +} + + +Tick +CopyEngine::write(PacketPtr pkt) +{ + int bar; + Addr daddr; + + + if (!getBAR(pkt->getAddr(), bar, daddr)) + panic("Invalid PCI memory access to unmapped memory.\n"); + + // Only Memory register BAR is allowed + assert(bar == 0); + + int size = pkt->getSize(); + + /// + /// Handle write of register here + /// + + if (size == sizeof(uint64_t)) { + uint64_t val M5_VAR_USED = pkt->get(); + DPRINTF(DMACopyEngine, "Wrote device register %#X value %#X\n", daddr, val); + } else if (size == sizeof(uint32_t)) { + uint32_t val M5_VAR_USED = pkt->get(); + DPRINTF(DMACopyEngine, "Wrote device register %#X value %#X\n", daddr, val); + } else if (size == sizeof(uint16_t)) { + uint16_t val M5_VAR_USED = pkt->get(); + DPRINTF(DMACopyEngine, "Wrote device register %#X value %#X\n", daddr, val); + } else if (size == sizeof(uint8_t)) { + uint8_t val M5_VAR_USED = pkt->get(); + DPRINTF(DMACopyEngine, "Wrote device register %#X value %#X\n", daddr, val); + } else { + panic("Unknown size for MMIO access: %d\n", size); + } + + if (daddr < 0x80) { + switch (daddr) { + case GEN_CHANCOUNT: + case GEN_XFERCAP: + case GEN_ATTNSTATUS: + DPRINTF(DMACopyEngine, "Warning, ignorning write to register %x\n", + daddr); + break; + case GEN_INTRCTRL: + regs.intrctrl.master_int_enable(bits(pkt->get(),0,1)); + break; + default: + panic("Read request to unknown register number: %#x\n", daddr); + } + pkt->makeAtomicResponse(); + return pioDelay; + } + + // Find which channel we're accessing + int chanid = 0; + daddr -= 0x80; + while (daddr >= 0x80) { + chanid++; + daddr -= 0x80; + } + + if (chanid >= regs.chanCount) + panic("Access to channel %d (device only configured for %d channels)", + chanid, regs.chanCount); + + /// + /// Channel registers are handled here + /// + chan[chanid]->channelWrite(pkt, daddr, size); + + pkt->makeAtomicResponse(); + return pioDelay; +} + +void +CopyEngine::CopyEngineChannel::channelWrite(Packet *pkt, Addr daddr, int size) +{ + switch (daddr) { + case CHAN_CONTROL: + assert(size == sizeof(uint16_t)); + int old_int_disable; + old_int_disable = cr.ctrl.interrupt_disable(); + cr.ctrl(pkt->get()); + if (cr.ctrl.interrupt_disable()) + cr.ctrl.interrupt_disable(0); + else + cr.ctrl.interrupt_disable(old_int_disable); + break; + case CHAN_STATUS: + assert(size == sizeof(uint64_t)); + DPRINTF(DMACopyEngine, "Warning, ignorning write to register %x\n", + daddr); + break; + case CHAN_CHAINADDR: + assert(size == sizeof(uint64_t) || size == sizeof(uint32_t)); + if (size == sizeof(uint64_t)) + cr.descChainAddr = pkt->get(); + else + cr.descChainAddr = (uint64_t)pkt->get() | + (cr.descChainAddr & ~mask(32)); + DPRINTF(DMACopyEngine, "Chain Address %x\n", cr.descChainAddr); + break; + case CHAN_CHAINADDR_HIGH: + assert(size == sizeof(uint32_t)); + cr.descChainAddr = ((uint64_t)pkt->get() <<32) | + (cr.descChainAddr & mask(32)); + DPRINTF(DMACopyEngine, "Chain Address %x\n", cr.descChainAddr); + break; + case CHAN_COMMAND: + assert(size == sizeof(uint8_t)); + cr.command(pkt->get()); + recvCommand(); + break; + case CHAN_CMPLNADDR: + assert(size == sizeof(uint64_t) || size == sizeof(uint32_t)); + if (size == sizeof(uint64_t)) + cr.completionAddr = pkt->get(); + else + cr.completionAddr = pkt->get() | + (cr.completionAddr & ~mask(32)); + break; + case CHAN_CMPLNADDR_HIGH: + assert(size == sizeof(uint32_t)); + cr.completionAddr = ((uint64_t)pkt->get() <<32) | + (cr.completionAddr & mask(32)); + break; + case CHAN_ERROR: + assert(size == sizeof(uint32_t)); + cr.error(~pkt->get() & cr.error()); + break; + default: + panic("Read request to unknown channel register number: (%d)%#x\n", + channelId, daddr); + } +} + +void +CopyEngine::regStats() +{ + using namespace Stats; + bytesCopied + .init(regs.chanCount) + .name(name() + ".bytes_copied") + .desc("Number of bytes copied by each engine") + .flags(total) + ; + copiesProcessed + .init(regs.chanCount) + .name(name() + ".copies_processed") + .desc("Number of copies processed by each engine") + .flags(total) + ; +} + +void +CopyEngine::CopyEngineChannel::fetchDescriptor(Addr address) +{ + DPRINTF(DMACopyEngine, "Reading descriptor from at memory location %#x(%#x)\n", + address, ce->platform->pciToDma(address)); + assert(address); + busy = true; + + DPRINTF(DMACopyEngine, "dmaAction: %#x, %d bytes, to addr %#x\n", + ce->platform->pciToDma(address), sizeof(DmaDesc), curDmaDesc); + + cePort->dmaAction(MemCmd::ReadReq, ce->platform->pciToDma(address), + sizeof(DmaDesc), &fetchCompleteEvent, (uint8_t*)curDmaDesc, + latBeforeBegin); + lastDescriptorAddr = address; +} + +void +CopyEngine::CopyEngineChannel::fetchDescComplete() +{ + DPRINTF(DMACopyEngine, "Read of descriptor complete\n"); + + if ((curDmaDesc->command & DESC_CTRL_NULL)) { + DPRINTF(DMACopyEngine, "Got NULL descriptor, skipping\n"); + assert(!(curDmaDesc->command & DESC_CTRL_CP_STS)); + if (curDmaDesc->command & DESC_CTRL_CP_STS) { + panic("Shouldn't be able to get here\n"); + nextState = CompletionWrite; + if (inDrain()) return; + writeCompletionStatus(); + } else { + busy = false; + nextState = Idle; + inDrain(); + } + return; + } + + if (curDmaDesc->command & ~DESC_CTRL_CP_STS) + panic("Descriptor has flag other that completion status set\n"); + + nextState = DMARead; + if (inDrain()) return; + readCopyBytes(); +} + +void +CopyEngine::CopyEngineChannel::readCopyBytes() +{ + DPRINTF(DMACopyEngine, "Reading %d bytes from buffer to memory location %#x(%#x)\n", + curDmaDesc->len, curDmaDesc->dest, + ce->platform->pciToDma(curDmaDesc->src)); + cePort->dmaAction(MemCmd::ReadReq, ce->platform->pciToDma(curDmaDesc->src), + curDmaDesc->len, &readCompleteEvent, copyBuffer, 0); +} + +void +CopyEngine::CopyEngineChannel::readCopyBytesComplete() +{ + DPRINTF(DMACopyEngine, "Read of bytes to copy complete\n"); + + nextState = DMAWrite; + if (inDrain()) return; + writeCopyBytes(); +} + +void +CopyEngine::CopyEngineChannel::writeCopyBytes() +{ + DPRINTF(DMACopyEngine, "Writing %d bytes from buffer to memory location %#x(%#x)\n", + curDmaDesc->len, curDmaDesc->dest, + ce->platform->pciToDma(curDmaDesc->dest)); + + cePort->dmaAction(MemCmd::WriteReq, ce->platform->pciToDma(curDmaDesc->dest), + curDmaDesc->len, &writeCompleteEvent, copyBuffer, 0); + + ce->bytesCopied[channelId] += curDmaDesc->len; + ce->copiesProcessed[channelId]++; +} + +void +CopyEngine::CopyEngineChannel::writeCopyBytesComplete() +{ + DPRINTF(DMACopyEngine, "Write of bytes to copy complete user1: %#x\n", + curDmaDesc->user1); + + cr.status.compl_desc_addr(lastDescriptorAddr >> 6); + completionDataReg = cr.status() | 1; + + if (curDmaDesc->command & DESC_CTRL_CP_STS) { + nextState = CompletionWrite; + if (inDrain()) return; + writeCompletionStatus(); + return; + } + + continueProcessing(); +} + +void +CopyEngine::CopyEngineChannel::continueProcessing() +{ + busy = false; + + if (underReset) { + underReset = false; + refreshNext = false; + busy = false; + nextState = Idle; + return; + } + + if (curDmaDesc->next) { + nextState = DescriptorFetch; + fetchAddress = curDmaDesc->next; + if (inDrain()) return; + fetchDescriptor(curDmaDesc->next); + } else if (refreshNext) { + nextState = AddressFetch; + refreshNext = false; + if (inDrain()) return; + fetchNextAddr(lastDescriptorAddr); + } else { + inDrain(); + nextState = Idle; + } +} + +void +CopyEngine::CopyEngineChannel::writeCompletionStatus() +{ + DPRINTF(DMACopyEngine, "Writing completion status %#x to address %#x(%#x)\n", + completionDataReg, cr.completionAddr, + ce->platform->pciToDma(cr.completionAddr)); + + cePort->dmaAction(MemCmd::WriteReq, ce->platform->pciToDma(cr.completionAddr), + sizeof(completionDataReg), &statusCompleteEvent, + (uint8_t*)&completionDataReg, latAfterCompletion); +} + +void +CopyEngine::CopyEngineChannel::writeStatusComplete() +{ + DPRINTF(DMACopyEngine, "Writing completion status complete\n"); + continueProcessing(); +} + +void +CopyEngine::CopyEngineChannel::fetchNextAddr(Addr address) +{ + DPRINTF(DMACopyEngine, "Fetching next address...\n"); + busy = true; + cePort->dmaAction(MemCmd::ReadReq, ce->platform->pciToDma(address + + offsetof(DmaDesc, next)), sizeof(Addr), &addrCompleteEvent, + (uint8_t*)curDmaDesc + offsetof(DmaDesc, next), 0); +} + +void +CopyEngine::CopyEngineChannel::fetchAddrComplete() +{ + DPRINTF(DMACopyEngine, "Fetching next address complete: %#x\n", + curDmaDesc->next); + if (!curDmaDesc->next) { + DPRINTF(DMACopyEngine, "Got NULL descriptor, nothing more to do\n"); + busy = false; + nextState = Idle; + inDrain(); + return; + } + nextState = DescriptorFetch; + fetchAddress = curDmaDesc->next; + if (inDrain()) return; + fetchDescriptor(curDmaDesc->next); +} + +bool +CopyEngine::CopyEngineChannel::inDrain() +{ + if (ce->getState() == SimObject::Draining) { + DPRINTF(DMACopyEngine, "processing drain\n"); + assert(drainEvent); + drainEvent->process(); + drainEvent = NULL; + } + + return ce->getState() != SimObject::Running; +} + +unsigned int +CopyEngine::CopyEngineChannel::drain(Event *de) +{ + if (nextState == Idle || ce->getState() != SimObject::Running) + return 0; + unsigned int count = 1; + count += cePort->drain(de); + + DPRINTF(DMACopyEngine, "unable to drain, returning %d\n", count); + drainEvent = de; + return count; +} + +unsigned int +CopyEngine::drain(Event *de) +{ + unsigned int count; + count = pioPort->drain(de) + dmaPort->drain(de) + configPort->drain(de); + for (int x = 0;x < chan.size(); x++) + count += chan[x]->drain(de); + + if (count) + changeState(Draining); + else + changeState(Drained); + + DPRINTF(DMACopyEngine, "call to CopyEngine::drain() returning %d\n", count); + return count; +} + +void +CopyEngine::serialize(std::ostream &os) +{ + PciDev::serialize(os); + regs.serialize(os); + for (int x =0; x < chan.size(); x++) { + nameOut(os, csprintf("%s.channel%d", name(), x)); + chan[x]->serialize(os); + } +} + +void +CopyEngine::unserialize(Checkpoint *cp, const std::string §ion) +{ + PciDev::unserialize(cp, section); + regs.unserialize(cp, section); + for (int x = 0; x < chan.size(); x++) + chan[x]->unserialize(cp, csprintf("%s.channel%d", section, x)); +} + +void +CopyEngine::CopyEngineChannel::serialize(std::ostream &os) +{ + SERIALIZE_SCALAR(channelId); + SERIALIZE_SCALAR(busy); + SERIALIZE_SCALAR(underReset); + SERIALIZE_SCALAR(refreshNext); + SERIALIZE_SCALAR(lastDescriptorAddr); + SERIALIZE_SCALAR(completionDataReg); + SERIALIZE_SCALAR(fetchAddress); + int nextState = this->nextState; + SERIALIZE_SCALAR(nextState); + arrayParamOut(os, "curDmaDesc", (uint8_t*)curDmaDesc, sizeof(DmaDesc)); + SERIALIZE_ARRAY(copyBuffer, ce->params()->XferCap); + cr.serialize(os); + +} +void +CopyEngine::CopyEngineChannel::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_SCALAR(channelId); + UNSERIALIZE_SCALAR(busy); + UNSERIALIZE_SCALAR(underReset); + UNSERIALIZE_SCALAR(refreshNext); + UNSERIALIZE_SCALAR(lastDescriptorAddr); + UNSERIALIZE_SCALAR(completionDataReg); + UNSERIALIZE_SCALAR(fetchAddress); + int nextState; + UNSERIALIZE_SCALAR(nextState); + this->nextState = (ChannelState)nextState; + arrayParamIn(cp, section, "curDmaDesc", (uint8_t*)curDmaDesc, sizeof(DmaDesc)); + UNSERIALIZE_ARRAY(copyBuffer, ce->params()->XferCap); + cr.unserialize(cp, section); + +} + +void +CopyEngine::CopyEngineChannel::restartStateMachine() +{ + switch(nextState) { + case AddressFetch: + fetchNextAddr(lastDescriptorAddr); + break; + case DescriptorFetch: + fetchDescriptor(fetchAddress); + break; + case DMARead: + readCopyBytes(); + break; + case DMAWrite: + writeCopyBytes(); + break; + case CompletionWrite: + writeCompletionStatus(); + break; + case Idle: + break; + default: + panic("Unknown state for CopyEngineChannel\n"); + } +} + +void +CopyEngine::resume() +{ + SimObject::resume(); + for (int x = 0;x < chan.size(); x++) + chan[x]->resume(); +} + + +void +CopyEngine::CopyEngineChannel::resume() +{ + DPRINTF(DMACopyEngine, "Restarting state machine at state %d\n", nextState); + restartStateMachine(); +} + +CopyEngine * +CopyEngineParams::create() +{ + return new CopyEngine(this); +} diff --git a/src/dev/copy_engine.hh b/src/dev/copy_engine.hh new file mode 100644 index 000000000..0224261d9 --- /dev/null +++ b/src/dev/copy_engine.hh @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + +/* @file + * Device model for Intel's I/O Acceleration Technology (I/OAT). + * A DMA asyncronous copy engine + */ + +#ifndef __DEV_COPY_ENGINE_HH__ +#define __DEV_COPY_ENGINE_HH__ + +#include + +#include "base/statistics.hh" +#include "dev/copy_engine_defs.hh" +#include "dev/pcidev.hh" +#include "params/CopyEngine.hh" +#include "sim/eventq.hh" + +class CopyEngine : public PciDev +{ + class CopyEngineChannel + { + private: + DmaPort *cePort; + CopyEngine *ce; + CopyEngineReg::ChanRegs cr; + int channelId; + CopyEngineReg::DmaDesc *curDmaDesc; + uint8_t *copyBuffer; + + bool busy; + bool underReset; + bool refreshNext; + Addr lastDescriptorAddr; + Addr fetchAddress; + + Tick latBeforeBegin; + Tick latAfterCompletion; + + uint64_t completionDataReg; + + enum ChannelState { + Idle, + AddressFetch, + DescriptorFetch, + DMARead, + DMAWrite, + CompletionWrite + }; + + ChannelState nextState; + + Event *drainEvent; + public: + CopyEngineChannel(CopyEngine *_ce, int cid); + ~CopyEngineChannel(); + 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) + { panic("CopyEngineChannel has no I/O access\n"); } + + void channelRead(PacketPtr pkt, Addr daddr, int size); + void channelWrite(PacketPtr pkt, Addr daddr, int size); + + unsigned int drain(Event *de); + void resume(); + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); + + private: + void fetchDescriptor(Addr address); + void fetchDescComplete(); + EventWrapper + fetchCompleteEvent; + + void fetchNextAddr(Addr address); + void fetchAddrComplete(); + EventWrapper + addrCompleteEvent; + + void readCopyBytes(); + void readCopyBytesComplete(); + EventWrapper + readCompleteEvent; + + void writeCopyBytes(); + void writeCopyBytesComplete(); + EventWrapper + writeCompleteEvent; + + void writeCompletionStatus(); + void writeStatusComplete(); + EventWrapper + statusCompleteEvent; + + + void continueProcessing(); + void recvCommand(); + bool inDrain(); + void restartStateMachine(); + }; + + private: + + Stats::Vector<> bytesCopied; + Stats::Vector<> copiesProcessed; + + // device registers + CopyEngineReg::Regs regs; + + // Array of channels each one with regs/dma port/etc + std::vector chan; + + public: + typedef CopyEngineParams Params; + const Params * + params() const + { + return dynamic_cast(_params); + } + CopyEngine(const Params *params); + ~CopyEngine(); + + void regStats(); + void init(); + + virtual Tick read(PacketPtr pkt); + virtual Tick write(PacketPtr pkt); + + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); + virtual unsigned int drain(Event *de); + virtual void resume(); +}; + +#endif //__DEV_COPY_ENGINE_HH__ + diff --git a/src/dev/copy_engine_defs.hh b/src/dev/copy_engine_defs.hh new file mode 100644 index 000000000..16bf57d58 --- /dev/null +++ b/src/dev/copy_engine_defs.hh @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + +/* @file + * Register and structure descriptions for Intel's I/O AT DMA Engine + */ +#include "base/bitfield.hh" +#include "sim/serialize.hh" + +namespace CopyEngineReg { + + +// General Channel independant registers, 128 bytes starting at 0x00 +const uint32_t GEN_CHANCOUNT = 0x00; +const uint32_t GEN_XFERCAP = 0x01; +const uint32_t GEN_INTRCTRL = 0x03; +const uint32_t GEN_ATTNSTATUS = 0x04; + + +// Channel specific registers, each block is 128 bytes, starting at 0x80 +const uint32_t CHAN_CONTROL = 0x00; +const uint32_t CHAN_STATUS = 0x04; +const uint32_t CHAN_CHAINADDR = 0x0C; +const uint32_t CHAN_CHAINADDR_LOW = 0x0C; +const uint32_t CHAN_CHAINADDR_HIGH = 0x10; +const uint32_t CHAN_COMMAND = 0x14; +const uint32_t CHAN_CMPLNADDR = 0x18; +const uint32_t CHAN_CMPLNADDR_LOW = 0x18; +const uint32_t CHAN_CMPLNADDR_HIGH = 0x1C; +const uint32_t CHAN_ERROR = 0x28; + + +const uint32_t DESC_CTRL_INT_GEN = 0x00000001; +const uint32_t DESC_CTRL_SRC_SN = 0x00000002; +const uint32_t DESC_CTRL_DST_SN = 0x00000004; +const uint32_t DESC_CTRL_CP_STS = 0x00000008; +const uint32_t DESC_CTRL_FRAME = 0x00000010; +const uint32_t DESC_CTRL_NULL = 0x00000020; + +struct DmaDesc { + uint32_t len; + uint32_t command; + Addr src; + Addr dest; + Addr next; + uint64_t reserved1; + uint64_t reserved2; + uint64_t user1; + uint64_t user2; +}; + +#define ADD_FIELD8(NAME, OFFSET, BITS) \ + inline uint8_t NAME() { return bits(_data, OFFSET+BITS-1, OFFSET); } \ + inline void NAME(uint8_t d) { replaceBits(_data, OFFSET+BITS-1, OFFSET,d); } + +#define ADD_FIELD16(NAME, OFFSET, BITS) \ + inline uint16_t NAME() { return bits(_data, OFFSET+BITS-1, OFFSET); } \ + inline void NAME(uint16_t d) { replaceBits(_data, OFFSET+BITS-1, OFFSET,d); } + +#define ADD_FIELD32(NAME, OFFSET, BITS) \ + inline uint32_t NAME() { return bits(_data, OFFSET+BITS-1, OFFSET); } \ + inline void NAME(uint32_t d) { replaceBits(_data, OFFSET+BITS-1, OFFSET,d); } + +#define ADD_FIELD64(NAME, OFFSET, BITS) \ + inline uint64_t NAME() { return bits(_data, OFFSET+BITS-1, OFFSET); } \ + inline void NAME(uint64_t d) { replaceBits(_data, OFFSET+BITS-1, OFFSET,d); } + +template +struct Reg { + T _data; + T operator()() { return _data; } + const Reg &operator=(T d) { _data = d; return *this;} + bool operator==(T d) { return d == _data; } + void operator()(T d) { _data = d; } + Reg() { _data = 0; } + void serialize(std::ostream &os) + { + SERIALIZE_SCALAR(_data); + } + void unserialize(Checkpoint *cp, const std::string §ion) + { + UNSERIALIZE_SCALAR(_data); + } +}; + + +struct Regs { + uint8_t chanCount; + uint8_t xferCap; + + struct INTRCTRL : public Reg { // 0x03 + using Reg::operator =; + ADD_FIELD8(master_int_enable,0,1); + ADD_FIELD8(interrupt_status,1,1); + ADD_FIELD8(interrupt,2,1); + }; + INTRCTRL intrctrl; + + uint32_t attnStatus; // Read clears + + void serialize(std::ostream &os) + { + SERIALIZE_SCALAR(chanCount); + SERIALIZE_SCALAR(xferCap); + paramOut(os, "intrctrl", intrctrl._data); + SERIALIZE_SCALAR(attnStatus); + } + + void unserialize(Checkpoint *cp, const std::string §ion) + { + UNSERIALIZE_SCALAR(chanCount); + UNSERIALIZE_SCALAR(xferCap); + paramIn(cp, section, "intrctrl", intrctrl._data); + UNSERIALIZE_SCALAR(attnStatus); + } + +}; + +struct ChanRegs { + struct CHANCTRL : public Reg { // channelX + 0x00 + using Reg::operator =; + ADD_FIELD16(interrupt_disable,0,1); + ADD_FIELD16(error_completion_enable, 2,1); + ADD_FIELD16(any_error_abort_enable,3,1); + ADD_FIELD16(error_int_enable,4,1); + ADD_FIELD16(desc_addr_snoop_control,5,1); + ADD_FIELD16(in_use, 8,1); + }; + CHANCTRL ctrl; + + struct CHANSTS : public Reg { // channelX + 0x04 + ADD_FIELD64(dma_transfer_status, 0, 3); + ADD_FIELD64(unaffiliated_error, 3, 1); + ADD_FIELD64(soft_error, 4, 1); + ADD_FIELD64(compl_desc_addr, 6, 58); + }; + CHANSTS status; + + uint64_t descChainAddr; + + struct CHANCMD : public Reg { // channelX + 0x14 + ADD_FIELD8(start_dma,0,1); + ADD_FIELD8(append_dma,1,1); + ADD_FIELD8(suspend_dma,2,1); + ADD_FIELD8(abort_dma,3,1); + ADD_FIELD8(resume_dma,4,1); + ADD_FIELD8(reset_dma,5,1); + }; + CHANCMD command; + + uint64_t completionAddr; + + struct CHANERR : public Reg { // channel X + 0x28 + ADD_FIELD32(source_addr_error,0,1); + ADD_FIELD32(dest_addr_error,1,1); + ADD_FIELD32(ndesc_addr_error,2,1); + ADD_FIELD32(desc_error,3,1); + ADD_FIELD32(chain_addr_error,4,1); + ADD_FIELD32(chain_cmd_error,5,1); + ADD_FIELD32(chipset_parity_error,6,1); + ADD_FIELD32(dma_parity_error,7,1); + ADD_FIELD32(read_data_error,8,1); + ADD_FIELD32(write_data_error,9,1); + ADD_FIELD32(desc_control_error,10,1); + ADD_FIELD32(desc_len_error,11,1); + ADD_FIELD32(completion_addr_error,12,1); + ADD_FIELD32(interrupt_config_error,13,1); + ADD_FIELD32(soft_error,14,1); + ADD_FIELD32(unaffiliated_error,15,1); + }; + CHANERR error; + + void serialize(std::ostream &os) + { + paramOut(os, "ctrl", ctrl._data); + paramOut(os, "status", status._data); + SERIALIZE_SCALAR(descChainAddr); + paramOut(os, "command", command._data); + SERIALIZE_SCALAR(completionAddr); + paramOut(os, "error", error._data); + } + + void unserialize(Checkpoint *cp, const std::string §ion) + { + paramIn(cp, section, "ctrl", ctrl._data); + paramIn(cp, section, "status", status._data); + UNSERIALIZE_SCALAR(descChainAddr); + paramIn(cp, section, "command", command._data); + UNSERIALIZE_SCALAR(completionAddr); + paramIn(cp, section, "error", error._data); + } + + +}; + +} //namespace CopyEngineReg + + -- cgit v1.2.3 From b4227bd7f697a1f29d25639864f5683d9ddcd41f Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Sat, 17 Jan 2009 18:56:46 -0500 Subject: Fix issue 326: glibc non-deterministic because it reads /proc --- src/kern/SConscript | 3 +++ src/kern/linux/linux.cc | 65 +++++++++++++++++++++++++++++++++++++++++++++ src/kern/linux/linux.hh | 9 ++++++- src/kern/operatingsystem.cc | 44 ++++++++++++++++++++++++++++++ src/kern/operatingsystem.hh | 6 +++++ src/sim/syscall_emul.hh | 14 +++++++--- src/sim/system.cc | 13 +++++++++ src/sim/system.hh | 6 +++++ 8 files changed, 156 insertions(+), 4 deletions(-) create mode 100644 src/kern/linux/linux.cc create mode 100644 src/kern/operatingsystem.cc (limited to 'src') diff --git a/src/kern/SConscript b/src/kern/SConscript index 546c4b058..fc682aee0 100644 --- a/src/kern/SConscript +++ b/src/kern/SConscript @@ -47,3 +47,6 @@ if env['FULL_SYSTEM']: Source('tru64/tru64_events.cc') Source('tru64/tru64_syscalls.cc') TraceFlag('BADADDR') +else: + Source('linux/linux.cc') + Source('operatingsystem.cc') diff --git a/src/kern/linux/linux.cc b/src/kern/linux/linux.cc new file mode 100644 index 000000000..b14e3c709 --- /dev/null +++ b/src/kern/linux/linux.cc @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2009 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + +#include + +#include "cpu/thread_context.hh" +#include "kern/linux/linux.hh" +#include "sim/process.hh" +#include "sim/system.hh" + +int +Linux::openSpecialFile(std::string path, LiveProcess *process, ThreadContext *tc) +{ + DPRINTF(SyscallVerbose, "Opening special file: %s\n", path.c_str()); + if (path.compare(0, 13, "/proc/meminfo") == 0) { + std::string data = Linux::procMeminfo(process, tc); + FILE *f = tmpfile(); + int fd = fileno(f); + int ret M5_VAR_USED = fwrite(data.c_str(), 1, data.size(), f); + assert(ret == data.size()); + rewind(f); + return fd; + } + + warn("Attempting to open special file: %s. Ignorning. Simulation may" + " take un-expected code path or be non-deterministic until proper" + " handling is implemented.\n", path.c_str()); + return -1; +} + +std::string +Linux::procMeminfo(LiveProcess *process, ThreadContext *tc) +{ + return csprintf("MemTotal:%12d kB\nMemFree: %12d kB\n", + process->system->memSize() >> 10, + process->system->freeMemSize() >> 10); +} + diff --git a/src/kern/linux/linux.hh b/src/kern/linux/linux.hh index a41fac9a7..ad35fa726 100644 --- a/src/kern/linux/linux.hh +++ b/src/kern/linux/linux.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2005 The Regents of The University of Michigan + * Copyright (c) 2004-2009 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,9 +39,13 @@ class Linux {}; #else //!FULL_SYSTEM #include +#include #include "kern/operatingsystem.hh" +class ThreadContext; +class LiveProcess; + /// /// This class encapsulates the types, structures, constants, /// functions, and syscall-number mappings specific to the Alpha Linux @@ -158,6 +162,9 @@ class Linux : public OperatingSystem int64_t ru_nivcsw; //!< involuntary " }; + static int openSpecialFile(std::string path, LiveProcess *process, ThreadContext *tc); + static std::string procMeminfo(LiveProcess *process, ThreadContext *tc); + }; // class Linux diff --git a/src/kern/operatingsystem.cc b/src/kern/operatingsystem.cc new file mode 100644 index 000000000..8951b8193 --- /dev/null +++ b/src/kern/operatingsystem.cc @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2009 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + + +#include "kern/operatingsystem.hh" +#include "base/misc.hh" + +int +OperatingSystem::openSpecialFile(std::string path, LiveProcess *process, ThreadContext *tc) +{ + warn("Attempting to open special file: %s. Ignorning. Simulation may" + " take un-expected code path or be non-deterministic until proper" + " handling is implemented.\n", path.c_str()); + return -1; +} + + diff --git a/src/kern/operatingsystem.hh b/src/kern/operatingsystem.hh index 10daae3d7..712b97c35 100644 --- a/src/kern/operatingsystem.hh +++ b/src/kern/operatingsystem.hh @@ -40,6 +40,10 @@ class OperatingSystem {}; #else //!FULL_SYSTEM +#include + +class LiveProcess; +class ThreadContext; /// This struct is used to build an target-OS-dependent table that /// maps the target's open() flags to the host open() flags. @@ -117,6 +121,8 @@ class OperatingSystem { int64_t ru_nivcsw; //!< involuntary " } rusage; + static int openSpecialFile(std::string path, LiveProcess *process, ThreadContext *tc); + }; // class OperatingSystem diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index 57403ab27..c334c1e26 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -537,10 +537,18 @@ openFunc(SyscallDesc *desc, int callnum, LiveProcess *process, DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str()); - // open the file - int fd = open(path.c_str(), hostFlags, mode); + int fd; + if (!path.compare(0, 6, "/proc/") || !path.compare(0, 8, "/system/") || + !path.compare(0, 10, "/platform/") || !path.compare(0, 5, "/sys/")) { + // It's a proc/sys entery and requires special handling + fd = OS::openSpecialFile(path, process, tc); + return (fd == -1) ? -1 : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false); + } else { + // open the file + fd = open(path.c_str(), hostFlags, mode); + return (fd == -1) ? -errno : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false); + } - return (fd == -1) ? -errno : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false); } diff --git a/src/sim/system.cc b/src/sim/system.cc index 29b1d1f61..864b0fdc7 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -244,6 +244,19 @@ System::new_page() fatal("Out of memory, please increase size of physical memory."); return return_addr; } + +Addr +System::memSize() +{ + return physmem->size(); +} + +Addr +System::freeMemSize() +{ + return physmem->size() - (page_ptr << LogVMPageSize); +} + #endif void diff --git a/src/sim/system.hh b/src/sim/system.hh index 9715767b1..bfa5ea8bb 100644 --- a/src/sim/system.hh +++ b/src/sim/system.hh @@ -139,6 +139,12 @@ class System : public SimObject return next_PID++; } + /** Amount of physical memory that is still free */ + Addr freeMemSize(); + + /** Amount of physical memory that exists */ + Addr memSize(); + #endif // FULL_SYSTEM -- cgit v1.2.3 From 51d780fa4d84316bdd56a2d7cd405642e887c649 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 19 Jan 2009 09:03:41 -0800 Subject: scons: Don't add all objects to the library twice --- src/SConscript | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/SConscript b/src/SConscript index a14e868fe..cb523aa94 100644 --- a/src/SConscript +++ b/src/SConscript @@ -1011,8 +1011,8 @@ def makeEnv(label, objsfx, strip = False, **kwargs): # First make a library of everything but main() so other programs can # link against m5. - static_lib = new_env.StaticLibrary(libname, static_objs + static_objs) - shared_lib = new_env.SharedLibrary(libname, shared_objs + shared_objs) + static_lib = new_env.StaticLibrary(libname, static_objs) + shared_lib = new_env.SharedLibrary(libname, shared_objs) for target, sources in unit_tests: objs = [ new_env.StaticObject(s) for s in sources ] -- cgit v1.2.3 From f15f252d4e45f74a3b6e5ef0a7afacc656480792 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 19 Jan 2009 09:59:13 -0800 Subject: python: Rework how things are imported --- src/SConscript | 107 +++++++++++++++++++++------------------------- src/python/m5/__init__.py | 18 ++++---- src/python/swig/core.i | 26 ++++++----- src/sim/SConscript | 1 - src/sim/compile_info.cc | 56 ------------------------ 5 files changed, 74 insertions(+), 134 deletions(-) delete mode 100644 src/sim/compile_info.cc (limited to 'src') diff --git a/src/SConscript b/src/SConscript index cb523aa94..fed0355cf 100644 --- a/src/SConscript +++ b/src/SConscript @@ -272,7 +272,7 @@ class DictImporter(object): self.installed = set() def find_module(self, fullname, path): - if fullname == '__scons': + if fullname == 'defines': return self if fullname == 'm5.objects': @@ -296,8 +296,8 @@ class DictImporter(object): mod.__path__ = fullname.split('.') return mod - if fullname == '__scons': - mod.__dict__['m5_build_env'] = build_env + if fullname == 'defines': + mod.__dict__['buildEnv'] = build_env return mod srcfile = self.modules[fullname] @@ -358,13 +358,51 @@ depends = [ File(py_modules[dep]) for dep in module_depends ] # Commands for the basic automatically generated python files # +scons_dir = str(SCons.Node.FS.default_fs.SConstruct_dir) + +hg_info = ("Unknown", "Unknown", "Unknown") +hg_demandimport = False +try: + if not exists(scons_dir) or not isdir(scons_dir) or \ + not exists(joinpath(scons_dir, ".hg")): + raise ValueError(".hg directory not found") + + import mercurial.demandimport, mercurial.hg, mercurial.ui + import mercurial.util, mercurial.node + hg_demandimport = True + + repo = mercurial.hg.repository(mercurial.ui.ui(), scons_dir) + rev = mercurial.node.nullrev + repo.changelog.count() + changenode = repo.changelog.node(rev) + changes = repo.changelog.read(changenode) + id = mercurial.node.hex(changenode) + date = mercurial.util.datestr(changes[2]) + + hg_info = (rev, id, date) +except ImportError, e: + print "Mercurial not found" +except ValueError, e: + print e +except Exception, e: + print "Other mercurial exception: %s" % e + +if hg_demandimport: + mercurial.demandimport.disable() + # Generate Python file containing a dict specifying the current # build_env flags. def makeDefinesPyFile(target, source, env): f = file(str(target[0]), 'w') - print >>f, "m5_build_env = ", source[0] + build_env, hg_info = [ x.get_contents() for x in source ] + print >>f, "buildEnv = %s" % build_env + print >>f, "hgRev, hgId, hgDate = %s" % hg_info f.close() +defines_info = [ Value(build_env), Value(hg_info) ] +# Generate a file with all of the compile options in it +env.Command('python/m5/defines.py', defines_info, makeDefinesPyFile) +PySource('m5', 'python/m5/defines.py') + # Generate python file containing info about the M5 source code def makeInfoPyFile(target, source, env): f = file(str(target[0]), 'w') @@ -373,6 +411,12 @@ def makeInfoPyFile(target, source, env): print >>f, "%s = %s" % (src, repr(data)) f.close() +# Generate a file that wraps the basic top level files +env.Command('python/m5/info.py', + [ '#/AUTHORS', '#/LICENSE', '#/README', '#/RELEASE_NOTES' ], + makeInfoPyFile) +PySource('m5', 'python/m5/info.py') + # Generate the __init__.py file for m5.objects def makeObjectsInitFile(target, source, env): f = file(str(target[0]), 'w') @@ -382,16 +426,6 @@ def makeObjectsInitFile(target, source, env): print >>f, 'from %s import *' % module.get_contents() f.close() -# Generate a file with all of the compile options in it -env.Command('python/m5/defines.py', Value(build_env), makeDefinesPyFile) -PySource('m5', 'python/m5/defines.py') - -# Generate a file that wraps the basic top level files -env.Command('python/m5/info.py', - [ '#/AUTHORS', '#/LICENSE', '#/README', '#/RELEASE_NOTES' ], - makeInfoPyFile) -PySource('m5', 'python/m5/info.py') - # Generate an __init__.py file for the objects package env.Command('python/m5/objects/__init__.py', [ Value(o) for o in sort_list(sim_object_modfiles) ], @@ -821,43 +855,6 @@ env.Command('base/traceflags.hh', flags, traceFlagsHH) env.Command('base/traceflags.cc', flags, traceFlagsCC) Source('base/traceflags.cc') -# Generate program_info.cc -def programInfo(target, source, env): - def gen_file(target, rev, node, date): - pi_stats = file(target, 'w') - print >>pi_stats, 'const char *hgRev = "%s:%s";' % (rev, node) - print >>pi_stats, 'const char *hgDate = "%s";' % date - pi_stats.close() - - target = str(target[0]) - scons_dir = str(source[0].get_contents()) - try: - import mercurial.demandimport, mercurial.hg, mercurial.ui - import mercurial.util, mercurial.node - if not exists(scons_dir) or not isdir(scons_dir) or \ - not exists(joinpath(scons_dir, ".hg")): - raise ValueError - repo = mercurial.hg.repository(mercurial.ui.ui(), scons_dir) - rev = mercurial.node.nullrev + repo.changelog.count() - changenode = repo.changelog.node(rev) - changes = repo.changelog.read(changenode) - date = mercurial.util.datestr(changes[2]) - - gen_file(target, rev, mercurial.node.hex(changenode), date) - - mercurial.demandimport.disable() - except ImportError: - gen_file(target, "Unknown", "Unknown", "Unknown") - - except: - print "in except" - gen_file(target, "Unknown", "Unknown", "Unknown") - mercurial.demandimport.disable() - -env.Command('base/program_info.cc', - Value(str(SCons.Node.FS.default_fs.SConstruct_dir)), - programInfo) - # embed python files. All .py files that have been indicated by a # PySource() call in a SConscript need to be embedded into the M5 # library. To do that, we compile the file to byte code, marshal the @@ -974,14 +971,8 @@ def make_objs(sources, env, static): # recompiled whenever anything else does date_obj = XObject('base/date.cc') - # Make the generation of program_info.cc dependend on all - # the other cc files and the compiling of program_info.cc - # dependent on all the objects but program_info.o - pinfo_obj = XObject('base/program_info.cc') - env.Depends('base/program_info.cc', sources) env.Depends(date_obj, objs) - env.Depends(pinfo_obj, objs) - objs.extend([date_obj, pinfo_obj]) + objs.append(date_obj) return objs # Function to create a new build environment as clone of current diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py index 7b071bccd..4151d1a13 100644 --- a/src/python/m5/__init__.py +++ b/src/python/m5/__init__.py @@ -77,18 +77,18 @@ env.update(os.environ) # importing *you*). try: import internal - running_m5 = True except ImportError: - running_m5 = False + internal = None -if running_m5: - import defines - build_env.update(defines.m5_build_env) -else: - import __scons - build_env.update(__scons.m5_build_env) +import defines +build_env.update(defines.buildEnv) + +if internal: + defines.compileDate = internal.core.compileDate + for k,v in internal.core.__dict__.iteritems(): + if k.startswith('flag_'): + setattr(defines, k[5:], v) -if running_m5: from event import * from simulate import * from main import options, main diff --git a/src/python/swig/core.i b/src/python/swig/core.i index 566998639..c567bea4d 100644 --- a/src/python/swig/core.i +++ b/src/python/swig/core.i @@ -41,15 +41,24 @@ #include "sim/startup.hh" extern const char *compileDate; -std::vector compileFlags(); -extern const char *hgRev; -extern const char *hgDate; + +#ifdef DEBUG +const bool flag_DEBUG = true; +#else +const bool flag_DEBUG = false; +#endif +#ifdef NDEBUG +const bool flag_NDEBUG = true; +#else +const bool flag_NDEBUG = false; +#endif +const bool flag_TRACING_ON = TRACING_ON; + inline void disableAllListeners() { ListenSocket::disableAll(); } %} %include "stdint.i" %include "std_string.i" -%include "std_vector.i" %include "sim/host.hh" void setOutputDir(const std::string &dir); @@ -59,12 +68,9 @@ void disableAllListeners(); %immutable compileDate; char *compileDate; - -namespace std { %template(StringVector) vector; } -std::vector compileFlags(); - -char *hgRev; -char *hgDate; +const bool flag_DEBUG; +const bool flag_NDEBUG; +const bool flag_TRACING_ON; void setClockFrequency(Tick ticksPerSecond); diff --git a/src/sim/SConscript b/src/sim/SConscript index 48200161c..750007947 100644 --- a/src/sim/SConscript +++ b/src/sim/SConscript @@ -36,7 +36,6 @@ SimObject('System.py') SimObject('InstTracer.py') Source('async.cc') -Source('compile_info.cc') Source('core.cc') Source('debug.cc') Source('eventq.cc') diff --git a/src/sim/compile_info.cc b/src/sim/compile_info.cc deleted file mode 100644 index 482972f9f..000000000 --- a/src/sim/compile_info.cc +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2008 The Hewlett-Packard Development Company - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Nathan Binkert - * Steve Reinhardt - */ - -#include -#include - -std::vector -compileFlags() -{ - static const char *flags[] = { -#ifdef DEBUG - "DEBUG", -#endif -#ifdef NDEBUG - "NDEBUG", -#endif -#if TRACING_ON - "TRACING_ON", -#endif - }; - - std::vector result; - for (int i = 0; i < sizeof(flags) / sizeof(flags[0]); ++i) - result.push_back(flags[i]); - - return result; -} - -- cgit v1.2.3 From 0876c822dd25e57e8811ceb31f67a3536c9855b0 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 19 Jan 2009 09:59:13 -0800 Subject: tracing: panic() if people try to use tracing, but TRACING_ON is not set. Also clean things up so that help strings can more easily be added. Move the help function into trace.py --- src/SConscript | 37 +++++++++++++++++-------------------- src/python/SConscript | 1 + src/python/m5/main.py | 44 +++++++++++++++++++------------------------- src/python/m5/trace.py | 20 ++++++++++++++++++++ 4 files changed, 57 insertions(+), 45 deletions(-) create mode 100644 src/python/m5/trace.py (limited to 'src') diff --git a/src/SConscript b/src/SConscript index fed0355cf..5ba89381d 100644 --- a/src/SConscript +++ b/src/SConscript @@ -175,30 +175,25 @@ Export('UnitTest') # # Trace Flags # -all_flags = {} -trace_flags = [] -def TraceFlag(name, desc=''): - if name in all_flags: +trace_flags = {} +def TraceFlag(name, desc=None): + if name in trace_flags: raise AttributeError, "Flag %s already specified" % name - flag = (name, (), desc) - trace_flags.append(flag) - all_flags[name] = () + trace_flags[name] = (name, (), desc) -def CompoundFlag(name, flags, desc=''): - if name in all_flags: +def CompoundFlag(name, flags, desc=None): + if name in trace_flags: raise AttributeError, "Flag %s already specified" % name compound = tuple(flags) for flag in compound: - if flag not in all_flags: + if flag not in trace_flags: raise AttributeError, "Trace flag %s not found" % flag - if all_flags[flag]: + if trace_flags[flag][1]: raise AttributeError, \ "Compound flag can't point to another compound flag" - flag = (name, compound, desc) - trace_flags.append(flag) - all_flags[name] = compound + trace_flags[name] = (name, compound, desc) Export('TraceFlag') Export('CompoundFlag') @@ -666,14 +661,16 @@ def traceFlagsPy(target, source, env): val = eval(s.get_contents()) allFlags.append(val) - print >>f, 'baseFlags = [' + allFlags.sort() + + print >>f, 'basic = [' for flag, compound, desc in allFlags: if not compound: print >>f, " '%s'," % flag print >>f, " ]" print >>f - print >>f, 'compoundFlags = [' + print >>f, 'compound = [' print >>f, " 'All'," for flag, compound, desc in allFlags: if compound: @@ -681,10 +678,10 @@ def traceFlagsPy(target, source, env): print >>f, " ]" print >>f - print >>f, "allFlags = frozenset(baseFlags + compoundFlags)" + print >>f, "all = frozenset(basic + compound)" print >>f - print >>f, 'compoundFlagMap = {' + print >>f, 'compoundMap = {' all = tuple([flag for flag,compound,desc in allFlags if not compound]) print >>f, " 'All' : %s," % (all, ) for flag, compound, desc in allFlags: @@ -693,7 +690,7 @@ def traceFlagsPy(target, source, env): print >>f, " }" print >>f - print >>f, 'flagDescriptions = {' + print >>f, 'descriptions = {' print >>f, " 'All' : 'All flags'," for flag, compound, desc in allFlags: print >>f, " '%s' : '%s'," % (flag, desc) @@ -847,7 +844,7 @@ extern const Flags *compoundFlags[]; f.close() -flags = [ Value(f) for f in trace_flags ] +flags = [ Value(f) for f in trace_flags.values() ] env.Command('base/traceflags.py', flags, traceFlagsPy) PySource('m5', 'base/traceflags.py') diff --git a/src/python/SConscript b/src/python/SConscript index 94119c77d..726254c1d 100644 --- a/src/python/SConscript +++ b/src/python/SConscript @@ -48,6 +48,7 @@ PySource('m5', 'm5/simulate.py') PySource('m5', 'm5/smartdict.py') PySource('m5', 'm5/stats.py') PySource('m5', 'm5/ticks.py') +PySource('m5', 'm5/trace.py') PySource('m5.util', 'm5/util/__init__.py') PySource('m5.util', 'm5/util/attrdict.py') PySource('m5.util', 'm5/util/jobfile.py') diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 4853c8908..4e9714705 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -138,6 +138,13 @@ def main(): import event import info import internal + import trace + + def check_tracing(): + if defines.TRACING_ON: + return + + panic("Tracing is not enabled. Compile with TRACING_ON") # load the options.py config file to allow people to set their own # default options @@ -221,21 +228,9 @@ def main(): print if options.trace_help: - import traceflags - done = True - print "Base Flags:" - traceflags.baseFlags.sort() - print_list(traceflags.baseFlags, indent=4) - print - print "Compound Flags:" - traceflags.compoundFlags.sort() - for flag in traceflags.compoundFlags: - if flag == 'All': - continue - print " %s:" % flag - print_list(traceflags.compoundFlagMap[flag], indent=8) - print + check_tracing() + trace.help() if options.list_sim_objects: import SimObject @@ -306,7 +301,7 @@ def main(): internal.debug.schedBreakCycle(int(when)) if options.trace_flags: - import traceflags + check_tracing() on_flags = [] off_flags = [] @@ -315,7 +310,7 @@ def main(): if flag.startswith('-'): flag = flag[1:] off = True - if flag not in traceflags.allFlags and flag != "All": + if flag not in trace.flags.all and flag != "All": print >>sys.stderr, "invalid trace flag '%s'" % flag sys.exit(1) @@ -325,24 +320,23 @@ def main(): on_flags.append(flag) for flag in on_flags: - internal.trace.set(flag) + trace.set(flag) for flag in off_flags: - internal.trace.clear(flag) + trace.clear(flag) if options.trace_start: - def enable_trace(): - internal.trace.cvar.enabled = True - - e = event.create(enable_trace) + check_tracing() + e = event.create(trace.enable) event.mainq.schedule(e, options.trace_start) else: - internal.trace.cvar.enabled = True + trace.enable() - internal.trace.output(options.trace_file) + trace.output(options.trace_file) for ignore in options.trace_ignore: - internal.trace.ignore(ignore) + check_tracing() + trace.ignore(ignore) sys.argv = arguments sys.path = [ os.path.dirname(sys.argv[0]) ] + sys.path diff --git a/src/python/m5/trace.py b/src/python/m5/trace.py new file mode 100644 index 000000000..9e2351dbe --- /dev/null +++ b/src/python/m5/trace.py @@ -0,0 +1,20 @@ +import internal +import traceflags as flags + +from internal.trace import clear, output, set, ignore + +def enable(): + internal.trace.cvar.enabled = True + +def help(): + print "Base Flags:" + for flag in trace.flags.basic: + print " %s: %s" % (flag, trace.flags.descriptions[flag]) + print + print "Compound Flags:" + for flag in trace.flags.compound: + if flag == 'All': + continue + print " %s: %s" % (flag, trace.flags.descriptions[flag]) + print_list(trace.flags.compoundMap[flag], indent=8) + print -- cgit v1.2.3 From c9d3113015c69766f65851addf41172b9bc046b2 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 19 Jan 2009 09:59:14 -0800 Subject: tracing: Add help strings for some of the trace flags --- src/arch/sparc/SConscript | 2 +- src/arch/x86/SConscript | 6 +++--- src/base/SConscript | 26 ++++++++++++++------------ 3 files changed, 18 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/arch/sparc/SConscript b/src/arch/sparc/SConscript index 6a4c08a8e..148277358 100644 --- a/src/arch/sparc/SConscript +++ b/src/arch/sparc/SConscript @@ -44,7 +44,7 @@ if env['TARGET_ISA'] == 'sparc': Source('utility.cc') SimObject('SparcTLB.py') - TraceFlag('Sparc') + TraceFlag('Sparc', "Generic SPARC ISA stuff") if env['FULL_SYSTEM']: SimObject('SparcSystem.py') diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript index 37719e75d..a57e388ea 100644 --- a/src/arch/x86/SConscript +++ b/src/arch/x86/SConscript @@ -106,11 +106,11 @@ if env['TARGET_ISA'] == 'x86': Source('utility.cc') SimObject('X86TLB.py') - TraceFlag('Predecoder') - TraceFlag('X86') + TraceFlag('Predecoder', "Predecoder debug output") + TraceFlag('X86', "Generic X86 ISA debugging") if env['FULL_SYSTEM']: - TraceFlag('LocalApic') + TraceFlag('LocalApic', "Local APIC debugging") SimObject('X86LocalApic.py') SimObject('X86System.py') diff --git a/src/base/SConscript b/src/base/SConscript index c09fdc976..000060e93 100644 --- a/src/base/SConscript +++ b/src/base/SConscript @@ -81,16 +81,18 @@ if env['USE_MYSQL']: Source('mysql.cc') Source('stats/mysql.cc') -TraceFlag('Annotate') -TraceFlag('GDBAcc') -TraceFlag('GDBExtra') -TraceFlag('GDBMisc') -TraceFlag('GDBRead') -TraceFlag('GDBRecv') -TraceFlag('GDBSend') -TraceFlag('GDBWrite') -TraceFlag('SQL') -TraceFlag('StatEvents') +TraceFlag('Annotate', "State machine annotation debugging") +TraceFlag('GDBAcc', "Remote debugger accesses") +TraceFlag('GDBExtra', "Dump extra information on reads and writes") +TraceFlag('GDBMisc', "Breakpoints, traps, watchpoints, etc.") +TraceFlag('GDBRead', "Reads to the remote address space") +TraceFlag('GDBRecv', "Messages received from the remote application") +TraceFlag('GDBSend', "Messages sent to the remote application") +TraceFlag('GDBWrite', "Writes to the remote address space") +TraceFlag('SQL', "SQL queries sent to the server") +TraceFlag('StatEvents', "Statistics event tracking") -CompoundFlag('GDBAll', [ 'GDBMisc', 'GDBAcc', 'GDBRead', 'GDBWrite', 'GDBSend', - 'GDBRecv', 'GDBExtra' ]) +CompoundFlag('GDBAll', + [ 'GDBMisc', 'GDBAcc', 'GDBRead', 'GDBWrite', 'GDBSend', 'GDBRecv', + 'GDBExtra' ], + desc="All Remote debugging flags") -- cgit v1.2.3 From da14789c32e14c62cdb0e11957607955e2a19c8a Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 19 Jan 2009 09:59:15 -0800 Subject: python: Try to isolate the stuff that's in the m5.internal package a bit more. --- src/python/SConscript | 2 ++ src/python/m5/__init__.py | 1 + src/python/m5/core.py | 5 +++++ src/python/m5/debug.py | 3 +++ src/python/m5/main.py | 34 +++++++++++++++++----------------- 5 files changed, 28 insertions(+), 17 deletions(-) create mode 100644 src/python/m5/core.py create mode 100644 src/python/m5/debug.py (limited to 'src') diff --git a/src/python/SConscript b/src/python/SConscript index 726254c1d..a767545ec 100644 --- a/src/python/SConscript +++ b/src/python/SConscript @@ -39,6 +39,8 @@ PySource('m5', 'm5/__init__.py') PySource('m5', 'm5/SimObject.py') PySource('m5', 'm5/config.py') PySource('m5', 'm5/convert.py') +PySource('m5', 'm5/core.py') +PySource('m5', 'm5/debug.py') PySource('m5', 'm5/event.py') PySource('m5', 'm5/main.py') PySource('m5', 'm5/options.py') diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py index 4151d1a13..3a6d39499 100644 --- a/src/python/m5/__init__.py +++ b/src/python/m5/__init__.py @@ -93,6 +93,7 @@ if internal: from simulate import * from main import options, main import stats + import core import SimObject import params diff --git a/src/python/m5/core.py b/src/python/m5/core.py new file mode 100644 index 000000000..34590016e --- /dev/null +++ b/src/python/m5/core.py @@ -0,0 +1,5 @@ +import internal + +def setOutputDir(dir): + internal.core.setOutputDir(dir) + diff --git a/src/python/m5/debug.py b/src/python/m5/debug.py new file mode 100644 index 000000000..74c397562 --- /dev/null +++ b/src/python/m5/debug.py @@ -0,0 +1,3 @@ +import internal + +from internal.debug import schedBreakCycle, setRemoteGDBPort diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 4e9714705..19ceaf10d 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -135,9 +135,12 @@ add_option("--list-sim-objects", action='store_true', default=False, help="List all built-in SimObjects, their parameters and default values") def main(): + import core + import debug + import defines import event import info - import internal + import stats import trace def check_tracing(): @@ -185,19 +188,17 @@ def main(): done = False if options.build_info: - import defines - done = True print 'Build information:' print - print 'compiled %s' % internal.core.cvar.compileDate; - print "revision %s" % internal.core.cvar.hgRev - print "commit date %s" % internal.core.cvar.hgDate + print 'compiled %s' % defines.compileDate; + print "revision %s:%s" % (defines.hgRev, defines.hgId) + print "commit date %s" % defines.hgDate print 'build options:' - keys = defines.m5_build_env.keys() + keys = defines.buildEnv.keys() keys.sort() for key in keys: - val = defines.m5_build_env[key] + val = defines.buildEnv[key] print ' %s = %s' % (key, val) print @@ -265,9 +266,10 @@ def main(): print "M5 Simulator System" print brief_copyright print - print "M5 compiled %s" % internal.core.cvar.compileDate; - print "M5 revision %s" % internal.core.cvar.hgRev - print "M5 commit date %s" % internal.core.cvar.hgDate + + print "M5 compiled %s" % defines.compileDate; + print "M5 revision %s:%s" % (defines.hgRev, defines.hgId) + print "M5 commit date %s" % defines.hgDate print "M5 started %s" % datetime.datetime.now().strftime("%b %e %Y %X") print "M5 executing on %s" % socket.gethostname() @@ -285,20 +287,18 @@ def main(): options.usage(2) # tell C++ about output directory - internal.core.setOutputDir(options.outdir) + core.setOutputDir(options.outdir) # update the system path with elements from the -p option sys.path[0:0] = options.path - import objects - # set stats options - internal.stats.initText(options.stats_file) + stats.initText(options.stats_file) # set debugging options - internal.debug.setRemoteGDBPort(options.remote_gdb_port) + debug.setRemoteGDBPort(options.remote_gdb_port) for when in options.debug_break: - internal.debug.schedBreakCycle(int(when)) + debug.schedBreakCycle(int(when)) if options.trace_flags: check_tracing() -- cgit v1.2.3 From 81b8c0c79a0ed55f2d81fc66bf7e4667f708c1de Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 19 Jan 2009 14:43:09 -0800 Subject: python: add fatal() function to the m5 package and use it --- src/python/m5/__init__.py | 11 +++++++++++ src/python/m5/main.py | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py index 3a6d39499..97b22ef2a 100644 --- a/src/python/m5/__init__.py +++ b/src/python/m5/__init__.py @@ -36,10 +36,21 @@ import smartdict MaxTick = 2**63 - 1 # define this here so we can use it right away if necessary + +# panic() should be called when something happens that should never +# ever happen regardless of what the user does (i.e., an acutal m5 +# bug). def panic(string): print >>sys.stderr, 'panic:', string sys.exit(1) +# fatal() should be called when the simulation cannot continue due to +# some condition that is the user's fault (bad configuration, invalid +# arguments, etc.) and not a simulator bug. +def fatal(string): + print >>sys.stderr, 'fatal:', string + sys.exit(1) + # force scalars to one-element lists for uniformity def makeList(objOrList): if isinstance(objOrList, list): diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 19ceaf10d..38adac632 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -147,7 +147,7 @@ def main(): if defines.TRACING_ON: return - panic("Tracing is not enabled. Compile with TRACING_ON") + fatal("Tracing is not enabled. Compile with TRACING_ON") # load the options.py config file to allow people to set their own # default options -- cgit v1.2.3 From dbac448b088eea12d8b20400c7a770e57e28d771 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 19 Jan 2009 20:36:49 -0800 Subject: thread_context: move getSystemPtr so SE mode can get to it. There was really no reason that it should be FS only. --- src/cpu/o3/thread_context.hh | 2 +- src/cpu/o3/thread_context_impl.hh | 3 +-- src/cpu/simple_thread.hh | 2 +- src/cpu/thread_context.hh | 4 ++-- 4 files changed, 5 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index 8682e071e..6de773ff1 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -86,10 +86,10 @@ class O3ThreadContext : public ThreadContext virtual int threadId() { return thread->threadId(); } virtual void setThreadId(int id) { return thread->setThreadId(id); } -#if FULL_SYSTEM /** Returns a pointer to the system. */ virtual System *getSystemPtr() { return cpu->system; } +#if FULL_SYSTEM /** Returns a pointer to physical memory. */ virtual PhysicalMemory *getPhysMemPtr() { return cpu->physmem; } diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index 735827ebc..12b2d1b31 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -54,9 +54,8 @@ void O3ThreadContext::takeOverFrom(ThreadContext *old_context) { // some things should already be set up -#if FULL_SYSTEM assert(getSystemPtr() == old_context->getSystemPtr()); -#else +#if !FULL_SYSTEM assert(getProcessPtr() == old_context->getProcessPtr()); #endif diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index 4831b701a..678bb42bb 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -201,9 +201,9 @@ class SimpleThread : public ThreadState TheISA::DTB *getDTBPtr() { return dtb; } -#if FULL_SYSTEM System *getSystemPtr() { return system; } +#if FULL_SYSTEM FunctionalPort *getPhysPort() { return physPort; } /** Return a virtual port. This port cannot be cached locally in an object. diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index 9ee5250a3..7c3f11c12 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -129,9 +129,9 @@ class ThreadContext virtual TheISA::DTB *getDTBPtr() = 0; -#if FULL_SYSTEM virtual System *getSystemPtr() = 0; +#if FULL_SYSTEM virtual TheISA::Kernel::Statistics *getKernelStats() = 0; virtual FunctionalPort *getPhysPort() = 0; @@ -318,9 +318,9 @@ class ProxyThreadContext : public ThreadContext TheISA::DTB *getDTBPtr() { return actualTC->getDTBPtr(); } -#if FULL_SYSTEM System *getSystemPtr() { return actualTC->getSystemPtr(); } +#if FULL_SYSTEM TheISA::Kernel::Statistics *getKernelStats() { return actualTC->getKernelStats(); } -- cgit v1.2.3 From 10fc45da27f0c18c1a8b90af3d76127fc4467391 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Wed, 21 Jan 2009 14:56:18 -0800 Subject: o3cpu: give a name to the activity recorder for better tracing --- src/cpu/activity.cc | 13 ++++++++----- src/cpu/activity.hh | 10 ++++++++-- src/cpu/o3/cpu.cc | 2 +- 3 files changed, 17 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/cpu/activity.cc b/src/cpu/activity.cc index 15e0556ad..a2a34edf9 100644 --- a/src/cpu/activity.cc +++ b/src/cpu/activity.cc @@ -28,15 +28,18 @@ * Authors: Kevin Lim */ -#include +#include #include "base/timebuf.hh" #include "cpu/activity.hh" -ActivityRecorder::ActivityRecorder(int num_stages, int longest_latency, - int activity) - : activityBuffer(longest_latency, 0), longestLatency(longest_latency), - activityCount(activity), numStages(num_stages) +using namespace std; + +ActivityRecorder::ActivityRecorder(const string &name, int num_stages, + int longest_latency, int activity) + : _name(name), activityBuffer(longest_latency, 0), + longestLatency(longest_latency), activityCount(activity), + numStages(num_stages) { stageActive = new bool[numStages]; std::memset(stageActive, 0, numStages); diff --git a/src/cpu/activity.hh b/src/cpu/activity.hh index e99927339..d75ff150e 100644 --- a/src/cpu/activity.hh +++ b/src/cpu/activity.hh @@ -49,9 +49,11 @@ * idle. If count is zero, then the CPU can safely idle as it has no * more outstanding work to do. */ -class ActivityRecorder { +class ActivityRecorder +{ public: - ActivityRecorder(int num_stages, int longest_latency, int count); + ActivityRecorder(const std::string &name, int num_stages, + int longest_latency, int count); /** Records that there is activity this cycle. */ void activity(); @@ -92,6 +94,10 @@ class ActivityRecorder { void validate(); private: + // provide name() for DPRINTF. + std::string _name; + const std::string &name() { return _name; } + /** Time buffer that tracks if any cycles has active communication * in them. It should be as long as the longest communication * latency in the system. Each time any time buffer is written, diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 7320d5638..f567c1868 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -192,7 +192,7 @@ FullO3CPU::FullO3CPU(DerivO3CPUParams *params) decodeQueue(params->backComSize, params->forwardComSize), renameQueue(params->backComSize, params->forwardComSize), iewQueue(params->backComSize, params->forwardComSize), - activityRec(NumStages, + activityRec(name(), NumStages, params->backComSize + params->forwardComSize, params->activity), -- cgit v1.2.3 From 37ffe52ca406405ad42f9444286a7d1deef29a9c Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Fri, 23 Jan 2009 17:19:47 -0500 Subject: IGbE: Fix two e1000 driver bugs that I missed before. --- src/dev/i8254xGBe.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/dev/i8254xGBe.cc b/src/dev/i8254xGBe.cc index cf6692fb4..d6a888b21 100644 --- a/src/dev/i8254xGBe.cc +++ b/src/dev/i8254xGBe.cc @@ -1108,6 +1108,7 @@ IGbE::RxDescCache::unserialize(Checkpoint *cp, const std::string §ion) IGbE::TxDescCache::TxDescCache(IGbE *i, const std::string n, int s) : DescCache(i,n, s), pktDone(false), isTcp(false), pktWaiting(false), + completionAddress(0), completionEnabled(false), useTso(false), pktEvent(this), headerEvent(this), nullEvent(this) { @@ -1319,7 +1320,8 @@ IGbE::TxDescCache::pktComplete() if ((!TxdOp::eop(desc) && !useTso) || - (pktPtr->length < ( tsoMss + tsoHeaderLen) && tsoTotalLen != tsoUsedLen)) { + (pktPtr->length < ( tsoMss + tsoHeaderLen) && + tsoTotalLen != tsoUsedLen && useTso)) { assert(!useTso || (tsoDescBytesUsed == TxdOp::getLen(desc))); unusedCache.pop_front(); usedCache.push_back(desc); -- cgit v1.2.3 From 56d5212ba7a3588feb8ce0ed5d3a31c704106730 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Fri, 23 Jan 2009 17:19:48 -0500 Subject: Trace: Add DPRINTFS macro that takes parameter to call name() for trace printing. --- src/base/trace.hh | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/base/trace.hh b/src/base/trace.hh index 72d7ba605..fa24e9c48 100644 --- a/src/base/trace.hh +++ b/src/base/trace.hh @@ -97,6 +97,12 @@ inline const std::string &name() { return Trace::DefaultName; } Trace::dprintf(curTick, name(), __VA_ARGS__); \ } while (0) +#define DPRINTFS(x,s, ...) do { \ + if (DTRACE(x)) \ + Trace::dprintf(curTick, s->name(), __VA_ARGS__); \ +} while (0) + + #define DPRINTFR(x, ...) do { \ if (DTRACE(x)) \ Trace::dprintf((Tick)-1, std::string(), __VA_ARGS__); \ @@ -119,6 +125,7 @@ inline const std::string &name() { return Trace::DefaultName; } #define DTRACE(x) (false) #define DDUMP(x, data, count) do {} while (0) #define DPRINTF(x, ...) do {} while (0) +#define DPRINTFS(x, ...) do {} while (0) #define DPRINTFR(...) do {} while (0) #define DDUMPN(data, count) do {} while (0) #define DPRINTFN(...) do {} while (0) -- cgit v1.2.3 From f0fb3ac060234ed5860c8d5bca3e84dbd8d30c36 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 24 Jan 2009 07:27:21 -0800 Subject: cpu: provide a wakeup mechanism that can be used to pull CPUs out of sleep. Make interrupts use the new wakeup method, and pull all of the interrupt stuff into the cpu base class so that only the wakeup code needs to be updated. I tried to make wakeup, wakeCPU, and the various other mechanisms for waking and sleeping a little more sane, but I couldn't understand why the statistics were changing the way they were. Maybe we'll try again some day. --- src/cpu/base.cc | 18 ------------------ src/cpu/base.hh | 23 ++++++++++++++++++++--- src/cpu/o3/cpu.cc | 27 +++++++++++++++------------ src/cpu/o3/cpu.hh | 7 ++++--- src/cpu/ozone/cpu.hh | 2 +- src/cpu/ozone/cpu_impl.hh | 4 +--- src/cpu/simple/base.cc | 11 +++++------ src/cpu/simple/base.hh | 2 +- 8 files changed, 47 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 167606135..29095f12a 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -389,24 +389,6 @@ BaseCPU::ProfileEvent::process() cpu->schedule(this, curTick + interval); } -void -BaseCPU::postInterrupt(int int_num, int index) -{ - interrupts->post(int_num, index); -} - -void -BaseCPU::clearInterrupt(int int_num, int index) -{ - interrupts->clear(int_num, index); -} - -void -BaseCPU::clearInterrupts() -{ - interrupts->clearAll(); -} - void BaseCPU::serialize(std::ostream &os) { diff --git a/src/cpu/base.hh b/src/cpu/base.hh index 83d73ede0..c8215e047 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -125,9 +125,26 @@ class BaseCPU : public MemObject return interrupts; } - virtual void postInterrupt(int int_num, int index); - virtual void clearInterrupt(int int_num, int index); - virtual void clearInterrupts(); + virtual void wakeup() = 0; + + void + postInterrupt(int int_num, int index) + { + interrupts->post(int_num, index); + wakeup(); + } + + void + clearInterrupt(int int_num, int index) + { + interrupts->clear(int_num, index); + } + + void + clearInterrupts() + { + interrupts->clearAll(); + } bool checkInterrupts(ThreadContext *tc) const diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index f567c1868..4f6d5d41c 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -893,18 +893,6 @@ FullO3CPU::activateWhenReady(int tid) } #if FULL_SYSTEM -template -void -FullO3CPU::postInterrupt(int int_num, int index) -{ - BaseCPU::postInterrupt(int_num, index); - - if (this->thread[0]->status() == ThreadContext::Suspended) { - DPRINTF(IPI,"Suspended Processor awoke\n"); - this->threadContexts[0]->activate(); - } -} - template Fault FullO3CPU::hwrei(unsigned tid) @@ -1689,6 +1677,21 @@ FullO3CPU::wakeCPU() schedule(tickEvent, nextCycle()); } +#if FULL_SYSTEM +template +void +FullO3CPU::wakeup() +{ + if (this->thread[0]->status() != ThreadContext::Suspended) + return; + + this->wakeCPU(); + + DPRINTF(Quiesce, "Suspended Processor woken\n"); + this->threadContexts[0]->activate(); +} +#endif + template int FullO3CPU::getFreeTid() diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index d24e8c383..d14001d0d 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -402,9 +402,6 @@ class FullO3CPU : public BaseO3CPU void trap(Fault fault, unsigned tid); #if FULL_SYSTEM - /** Posts an interrupt. */ - void postInterrupt(int int_num, int index); - /** HW return from error interrupt. */ Fault hwrei(unsigned tid); @@ -701,6 +698,10 @@ class FullO3CPU : public BaseO3CPU /** Wakes the CPU, rescheduling the CPU if it's not already active. */ void wakeCPU(); +#if FULL_SYSTEM + virtual void wakeup(); +#endif + /** Gets a free thread id. Use if thread ids change across system. */ int getFreeTid(); diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index 6b5e7282d..55ad7b3fb 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -333,7 +333,7 @@ class OzoneCPU : public BaseCPU Status _status; public: - void postInterrupt(int int_num, int index); + void wakeup(); void zero_fill_64(Addr addr) { static int warned = 0; diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index 1402f4b72..84ee69464 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -582,10 +582,8 @@ OzoneCPU::dbg_vtophys(Addr addr) #if FULL_SYSTEM template void -OzoneCPU::postInterrupt(int int_num, int index) +OzoneCPU::wakeup() { - BaseCPU::postInterrupt(int_num, index); - if (_status == Idle) { DPRINTF(IPI,"Suspended Processor awoke\n"); // thread.activate(); diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index 3c154afb6..89d9ce383 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -303,14 +303,13 @@ BaseSimpleCPU::dbg_vtophys(Addr addr) #if FULL_SYSTEM void -BaseSimpleCPU::postInterrupt(int int_num, int index) +BaseSimpleCPU::wakeup() { - BaseCPU::postInterrupt(int_num, index); + if (thread->status() != ThreadContext::Suspended) + return; - if (thread->status() == ThreadContext::Suspended) { - DPRINTF(Quiesce,"Suspended Processor awoke\n"); - thread->activate(); - } + DPRINTF(Quiesce,"Suspended Processor awoke\n"); + thread->activate(); } #endif // FULL_SYSTEM diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index 6e72b8f6c..34d0f5954 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -98,7 +98,7 @@ class BaseSimpleCPU : public BaseCPU } public: - void postInterrupt(int int_num, int index); + void wakeup(); void zero_fill_64(Addr addr) { static int warned = 0; -- cgit v1.2.3 From 64ed39f61b89675237e145ed4a81b49f353921ed Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 24 Jan 2009 07:27:22 -0800 Subject: pseudo inst: Add new wake cpu instruction for sending a message to wake a cpu. It's instantaneous and so it's somewhat bogus, but it's a first step. --- src/arch/alpha/isa/decoder.isa | 3 +++ src/sim/pseudo_inst.cc | 9 +++++++++ src/sim/pseudo_inst.hh | 1 + 3 files changed, 13 insertions(+) (limited to 'src') diff --git a/src/arch/alpha/isa/decoder.isa b/src/arch/alpha/isa/decoder.isa index f057f00cc..67bc5c7a2 100644 --- a/src/arch/alpha/isa/decoder.isa +++ b/src/arch/alpha/isa/decoder.isa @@ -815,6 +815,9 @@ decode OPCODE default Unknown::unknown() { 0x07: rpns({{ R0 = PseudoInst::rpns(xc->tcBase()); }}, IsNonSpeculative, IsUnverifiable); + 0x09: wakeCPU({{ + PseudoInst::wakeCPU(xc->tcBase(), R16); + }}, IsNonSpeculative, IsUnverifiable); 0x10: deprecated_ivlb({{ warn_once("Obsolete M5 ivlb instruction encountered.\n"); }}); diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index 130a2f0fe..f1cf2835d 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -137,6 +137,15 @@ rpns(ThreadContext *tc) return curTick / Clock::Int::ns; } +void +wakeCPU(ThreadContext *tc, uint64_t cpuid) +{ + System *sys = tc->getSystemPtr(); + ThreadContext *other_tc = sys->threadContexts[cpuid]; + if (other_tc->status() == ThreadContext::Suspended) + other_tc->activate(); +} + void m5exit(ThreadContext *tc, Tick delay) { diff --git a/src/sim/pseudo_inst.hh b/src/sim/pseudo_inst.hh index 7d013eda7..30996fc3b 100644 --- a/src/sim/pseudo_inst.hh +++ b/src/sim/pseudo_inst.hh @@ -55,6 +55,7 @@ void addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr); #endif uint64_t rpns(ThreadContext *tc); +void wakeCPU(ThreadContext *tc, uint64_t cpuid); void m5exit(ThreadContext *tc, Tick delay); void resetstats(ThreadContext *tc, Tick delay, Tick period); void dumpstats(ThreadContext *tc, Tick delay, Tick period); -- cgit v1.2.3 From 3f9e2350a1c909f141c09bb409a381957853678c Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 25 Jan 2009 20:26:53 -0800 Subject: Devices: Make the destructor virtual on the CopyEnginChannel object. This fixes a compile warning which becomes an error. --- src/dev/copy_engine.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/dev/copy_engine.hh b/src/dev/copy_engine.hh index 0224261d9..475c0a5bf 100644 --- a/src/dev/copy_engine.hh +++ b/src/dev/copy_engine.hh @@ -81,7 +81,7 @@ class CopyEngine : public PciDev Event *drainEvent; public: CopyEngineChannel(CopyEngine *_ce, int cid); - ~CopyEngineChannel(); + virtual ~CopyEngineChannel(); void init(); std::string name() { assert(ce); return ce->name() + csprintf("-chan%d", channelId); } -- cgit v1.2.3 From d9794784bac54483660e438980d592b6ffe5c311 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 25 Jan 2009 20:29:03 -0800 Subject: CPU: Add a setCPU function to the interrupt objects. --- src/arch/alpha/interrupts.hh | 9 ++++++++- src/arch/sparc/interrupts.hh | 12 ++++++++++-- src/arch/x86/interrupts.hh | 9 +++++++++ src/cpu/base.cc | 3 +++ 4 files changed, 30 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/interrupts.hh b/src/arch/alpha/interrupts.hh index 89db134ff..f8e0ad4ef 100644 --- a/src/arch/alpha/interrupts.hh +++ b/src/arch/alpha/interrupts.hh @@ -48,6 +48,7 @@ class Interrupts : public SimObject bool newInfoSet; int newIpl; int newSummary; + BaseCPU * cpu; protected: uint64_t interrupts[NumInterruptLevels]; @@ -62,13 +63,19 @@ class Interrupts : public SimObject return dynamic_cast(_params); } - Interrupts(Params * p) : SimObject(p) + Interrupts(Params * p) : SimObject(p), cpu(NULL) { memset(interrupts, 0, sizeof(interrupts)); intstatus = 0; newInfoSet = false; } + void + setCPU(BaseCPU * _cpu) + { + cpu = _cpu; + } + void post(int int_num, int index) { diff --git a/src/arch/sparc/interrupts.hh b/src/arch/sparc/interrupts.hh index 66b3792b5..ec930e2b0 100644 --- a/src/arch/sparc/interrupts.hh +++ b/src/arch/sparc/interrupts.hh @@ -43,12 +43,20 @@ namespace SparcISA class Interrupts : public SimObject { - private: + BaseCPU * cpu; + uint64_t interrupts[NumInterruptTypes]; uint64_t intStatus; public: + + void + setCPU(BaseCPU * _cpu) + { + cpu = _cpu; + } + typedef SparcInterruptsParams Params; const Params * @@ -57,7 +65,7 @@ class Interrupts : public SimObject return dynamic_cast(_params); } - Interrupts(Params * p) : SimObject(p) + Interrupts(Params * p) : SimObject(p), cpu(NULL) { clearAll(); } diff --git a/src/arch/x86/interrupts.hh b/src/arch/x86/interrupts.hh index 8c7316217..c5e3bde0d 100644 --- a/src/arch/x86/interrupts.hh +++ b/src/arch/x86/interrupts.hh @@ -69,6 +69,7 @@ #include "sim/eventq.hh" class ThreadContext; +class BaseCPU; namespace X86ISA { @@ -182,12 +183,20 @@ class Interrupts : public BasicPioDevice, IntDev void requestInterrupt(uint8_t vector, uint8_t deliveryMode, bool level); + BaseCPU *cpu; + public: /* * Params stuff. */ typedef X86LocalApicParams Params; + void + setCPU(BaseCPU * newCPU) + { + cpu = newCPU; + } + void setClock(Tick newClock) { diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 29095f12a..06fcebad8 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -194,6 +194,8 @@ BaseCPU::BaseCPU(Params *p) } } #if FULL_SYSTEM + interrupts->setCPU(this); + profileEvent = NULL; if (params()->profile) profileEvent = new ProfileEvent(this, params()->profile); @@ -348,6 +350,7 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc) #if FULL_SYSTEM interrupts = oldCPU->interrupts; + interrupts->setCPU(this); for (int i = 0; i < threadContexts.size(); ++i) threadContexts[i]->profileClear(); -- cgit v1.2.3 From 389fbfdab19332ad191e9abed1c12a673fb7eda9 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 25 Jan 2009 20:30:51 -0800 Subject: X86: Make the interrupt object wake up the CPU when something becomes pending. --- src/arch/x86/interrupts.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc index a16ea5360..4f7753703 100644 --- a/src/arch/x86/interrupts.cc +++ b/src/arch/x86/interrupts.cc @@ -281,6 +281,7 @@ X86ISA::Interrupts::requestInterrupt(uint8_t vector, initVector = vector; } } + cpu->wakeup(); } Tick -- cgit v1.2.3 From 0449fb2b7a51f911d9814b79250047fa8f083829 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 25 Jan 2009 20:31:17 -0800 Subject: X86: Fix a bug in the iret microcode. --- .../general_purpose/control_transfer/interrupts_and_exceptions.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py b/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py index 57bc13698..1f14eb95c 100644 --- a/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py +++ b/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py @@ -75,6 +75,8 @@ def macroop IRET_PROT { ld t2, ss, [1, t0, rsp], "1 * env.stackSize", dataSize=ssz ld t3, ss, [1, t0, rsp], "2 * env.stackSize", dataSize=ssz + # Read the handy m5 register for use later + rdm5reg t4 ### @@ -89,7 +91,6 @@ def macroop IRET_PROT { br label("protToVirtFallThrough"), flags=(nCECF,) #CPL=0 - rdm5reg t4 andi t0, t4, 0x30, flags=(EZF,) br label("protToVirtFallThrough"), flags=(nCEZF,) -- cgit v1.2.3 From 919c3e7fb6675c35fdc8d54aebb13c6e938de4b9 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 25 Jan 2009 20:32:26 -0800 Subject: Dev: Make the RTC device ignore writes to a read only bit. --- src/dev/mc146818.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/dev/mc146818.cc b/src/dev/mc146818.cc index e5a81ff75..7b219e30c 100644 --- a/src/dev/mc146818.cc +++ b/src/dev/mc146818.cc @@ -35,6 +35,7 @@ #include +#include "base/bitfield.hh" #include "base/time.hh" #include "base/trace.hh" #include "dev/mc146818.hh" @@ -87,9 +88,10 @@ MC146818::writeData(const uint8_t addr, const uint8_t data) else { switch (addr) { case RTC_STAT_REGA: - if (data != (RTCA_32768HZ | RTCA_1024HZ)) + // The "update in progress" bit is read only. + if ((data & ~RTCA_UIP) != (RTCA_32768HZ | RTCA_1024HZ)) panic("Unimplemented RTC register A value write!\n"); - stat_regA = data; + replaceBits(stat_regA, data, 6, 0); break; case RTC_STAT_REGB: if ((data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR)) -- cgit v1.2.3 From 3c5988b86c9fcb06927a8e12095e278b55593911 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 25 Jan 2009 20:32:43 -0800 Subject: X86: Implement the bswap instruction. --- src/arch/x86/isa/decoder/two_byte_opcodes.isa | 6 +++++- .../data_conversion/endian_conversion.py | 20 +++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index 4ebe03d84..064f5ce86 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -915,7 +915,11 @@ default: Inst::UD2(); } } - 0x19: bswap_B(); + 0x19: decode OPSIZE { + 4: Inst::BSWAP_D(Bd); + 8: Inst::BSWAP_Q(Bq); + default: Inst::UD2(); + } 0x1A: decode LEGACY_DECODEVAL { // no prefix 0x0: decode OPCODE_OP_BOTTOM3 { diff --git a/src/arch/x86/isa/insts/general_purpose/data_conversion/endian_conversion.py b/src/arch/x86/isa/insts/general_purpose/data_conversion/endian_conversion.py index b375ac27e..ac2343462 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_conversion/endian_conversion.py +++ b/src/arch/x86/isa/insts/general_purpose/data_conversion/endian_conversion.py @@ -53,7 +53,25 @@ # # Authors: Gabe Black -microcode = "" +microcode = ''' +def macroop BSWAP_D_R +{ + roli reg, reg, 8, dataSize=2 + roli reg, reg, 16, dataSize=4 + roli reg, reg, 8, dataSize=2 +}; + +def macroop BSWAP_Q_R +{ + roli reg, reg, 8, dataSize=2 + roli reg, reg, 16, dataSize=4 + roli reg, reg, 8, dataSize=2 + roli reg, reg, 32, dataSize=8 + roli reg, reg, 8, dataSize=2 + roli reg, reg, 16, dataSize=4 + roli reg, reg, 8, dataSize=2 +}; +''' #let {{ # class BSWAP(Inst): # "GenFault ${new UnimpInstFault}" -- cgit v1.2.3 From 52defeb4e76e7f426c91eb0d0e5e2222d2ab387e Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 25 Jan 2009 20:33:27 -0800 Subject: X86: Implement the xadd instruction. --- src/arch/x86/isa/decoder/two_byte_opcodes.isa | 4 ++-- .../x86/isa/insts/general_purpose/semaphores.py | 24 ++++++++++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index 064f5ce86..3cdfa48bb 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -870,8 +870,8 @@ 0x7: Inst::MOVSX_W(Gv,Ev); } 0x18: decode OPCODE_OP_BOTTOM3 { - 0x0: xadd_Eb_Gb(); - 0x1: xadd_Ev_Gv(); + 0x0: Inst::XADD(Eb,Gb); + 0x1: Inst::XADD(Ev,Gv); //0x7: group9(); 0x7: decode MODRM_REG { 0x1: cmpxchg_Mq(); diff --git a/src/arch/x86/isa/insts/general_purpose/semaphores.py b/src/arch/x86/isa/insts/general_purpose/semaphores.py index da16477fc..f23241863 100644 --- a/src/arch/x86/isa/insts/general_purpose/semaphores.py +++ b/src/arch/x86/isa/insts/general_purpose/semaphores.py @@ -78,10 +78,30 @@ def macroop CMPXCHG_P_R { st t1, seg, riprel, disp mov rax, rax, t1, flags=(nCZF,) }; + +def macroop XADD_M_R { + ldst t1, seg, sib, disp + add t2, t1, reg, flags=(OF,SF,ZF,AF,PF,CF) + st t2, seg, sib, disp + mov reg, reg, t1 +}; + +def macroop XADD_P_R { + rdip t7 + ldst t1, seg, riprel, disp + add t2, t1, reg, flags=(OF,SF,ZF,AF,PF,CF) + st t2, seg, riprel, disp + mov reg, reg, t1 +}; + +def macroop XADD_R_R { + add t2, regm, reg, flags=(OF,SF,ZF,AF,PF,CF) + mov regm, regm, reg + mov reg, reg, t2 +}; + ''' #let {{ -# class XADD(Inst): -# "GenFault ${new UnimpInstFault}" # class XCHG(Inst): # "GenFault ${new UnimpInstFault}" #}}; -- cgit v1.2.3 From dbe28da1be7415ad5f496b983c0345c5e9714fb9 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 25 Jan 2009 20:33:52 -0800 Subject: X86: Add fake devices for non-existant serial ports. --- src/dev/x86/Pc.py | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/dev/x86/Pc.py b/src/dev/x86/Pc.py index 080844e4a..51a21c349 100644 --- a/src/dev/x86/Pc.py +++ b/src/dev/x86/Pc.py @@ -61,11 +61,19 @@ class Pc(Platform): com_1.pio_addr = x86IOAddress(0x3f8) com_1.terminal = terminal + # Devices to catch access to non-existant serial ports. + fake_com_2 = IsaFake(pio_addr=x86IOAddress(0x2f8), pio_size=8) + fake_com_3 = IsaFake(pio_addr=x86IOAddress(0x3e8), pio_size=8) + fake_com_4 = IsaFake(pio_addr=x86IOAddress(0x2e8), pio_size=8) + def attachIO(self, bus): self.south_bridge.attachIO(bus) self.i_dont_exist.pio = bus.port self.behind_pci.pio = bus.port self.com_1.pio = bus.port + self.fake_com_2.pio = bus.port + self.fake_com_3.pio = bus.port + self.fake_com_4.pio = bus.port self.pciconfig.pio = bus.default bus.responder_set = True bus.responder = self.pciconfig -- cgit v1.2.3 From 151bc018dd621b62b60ee5eca10c7531de6eb441 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 25 Jan 2009 20:34:17 -0800 Subject: X86: Add a device to back the non-existant floppy drive controller. --- src/dev/x86/Pc.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/dev/x86/Pc.py b/src/dev/x86/Pc.py index 51a21c349..7211fa3f4 100644 --- a/src/dev/x86/Pc.py +++ b/src/dev/x86/Pc.py @@ -66,6 +66,9 @@ class Pc(Platform): fake_com_3 = IsaFake(pio_addr=x86IOAddress(0x3e8), pio_size=8) fake_com_4 = IsaFake(pio_addr=x86IOAddress(0x2e8), pio_size=8) + # A device to catch accesses to the non-existant floppy controller. + fake_floppy = IsaFake(pio_addr=x86IOAddress(0x3f2), pio_size=4) + def attachIO(self, bus): self.south_bridge.attachIO(bus) self.i_dont_exist.pio = bus.port @@ -74,6 +77,7 @@ class Pc(Platform): self.fake_com_2.pio = bus.port self.fake_com_3.pio = bus.port self.fake_com_4.pio = bus.port + self.fake_floppy.pio = bus.port self.pciconfig.pio = bus.default bus.responder_set = True bus.responder = self.pciconfig -- cgit v1.2.3 From 56e182a6a9e58b951712582c4c63cf303847156e Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 25 Jan 2009 20:35:00 -0800 Subject: X86: Add a dummy minimal DMA controller that doesn't do anything. --- src/dev/x86/I8237.py | 36 +++++++++++++ src/dev/x86/SConscript | 4 ++ src/dev/x86/SouthBridge.py | 4 ++ src/dev/x86/i8237.cc | 130 +++++++++++++++++++++++++++++++++++++++++++++ src/dev/x86/i8237.hh | 66 +++++++++++++++++++++++ 5 files changed, 240 insertions(+) create mode 100644 src/dev/x86/I8237.py create mode 100644 src/dev/x86/i8237.cc create mode 100644 src/dev/x86/i8237.hh (limited to 'src') diff --git a/src/dev/x86/I8237.py b/src/dev/x86/I8237.py new file mode 100644 index 000000000..20788a164 --- /dev/null +++ b/src/dev/x86/I8237.py @@ -0,0 +1,36 @@ +# Copyright (c) 2008 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +from m5.params import * +from m5.proxy import * +from Device import BasicPioDevice + +class I8237(BasicPioDevice): + type = 'I8237' + cxx_class = 'X86ISA::I8237' + pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") diff --git a/src/dev/x86/SConscript b/src/dev/x86/SConscript index 3481235c6..167b14a84 100644 --- a/src/dev/x86/SConscript +++ b/src/dev/x86/SConscript @@ -49,6 +49,10 @@ if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'x86': Source('i8254.cc') TraceFlag('I8254', 'Interrupts from the I8254 timer'); + SimObject('I8237.py') + Source('i8237.cc') + TraceFlag('I8237', 'The I8237 dma controller'); + SimObject('PcSpeaker.py') Source('speaker.cc') TraceFlag('PcSpeaker') diff --git a/src/dev/x86/SouthBridge.py b/src/dev/x86/SouthBridge.py index 8a9bea01b..bbe3ad102 100644 --- a/src/dev/x86/SouthBridge.py +++ b/src/dev/x86/SouthBridge.py @@ -30,6 +30,7 @@ from m5.params import * from m5.proxy import * from Cmos import Cmos from I82094AA import I82094AA +from I8237 import I8237 from I8254 import I8254 from I8259 import I8259 from PcSpeaker import PcSpeaker @@ -47,6 +48,7 @@ class SouthBridge(SimObject): _pic1 = I8259(pio_addr=x86IOAddress(0x20), mode='I8259Master') _pic2 = I8259(pio_addr=x86IOAddress(0xA0), mode='I8259Slave') _cmos = Cmos(pio_addr=x86IOAddress(0x70)) + _dma1 = I8237(pio_addr=x86IOAddress(0x0)) _pit = I8254(pio_addr=x86IOAddress(0x40)) _speaker = PcSpeaker(pio_addr=x86IOAddress(0x61)) _io_apic = I82094AA(pio_addr=0xFEC00000) @@ -54,6 +56,7 @@ class SouthBridge(SimObject): pic1 = Param.I8259(_pic1, "Master PIC") pic2 = Param.I8259(_pic2, "Slave PIC") cmos = Param.Cmos(_cmos, "CMOS memory and real time clock device") + dma1 = Param.I8237(_dma1, "The first dma controller") pit = Param.I8254(_pit, "Programmable interval timer") speaker = Param.PcSpeaker(_speaker, "PC speaker") io_apic = Param.I82094AA(_io_apic, "I/O APIC") @@ -67,6 +70,7 @@ class SouthBridge(SimObject): self.speaker.i8254 = self.pit # Connect to the bus self.cmos.pio = bus.port + self.dma1.pio = bus.port self.pic1.pio = bus.port self.pic2.pio = bus.port self.pit.pio = bus.port diff --git a/src/dev/x86/i8237.cc b/src/dev/x86/i8237.cc new file mode 100644 index 000000000..5afe6b91a --- /dev/null +++ b/src/dev/x86/i8237.cc @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "dev/x86/i8237.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" + +Tick +X86ISA::I8237::read(PacketPtr pkt) +{ + assert(pkt->getSize() == 1); + Addr offset = pkt->getAddr() - pioAddr; + switch (offset) { + case 0x0: + panic("Read from i8237 channel 0 current address unimplemented.\n"); + case 0x1: + panic("Read from i8237 channel 0 remaining " + "word count unimplemented.\n"); + case 0x2: + panic("Read from i8237 channel 1 current address unimplemented.\n"); + case 0x3: + panic("Read from i8237 channel 1 remaining " + "word count unimplemented.\n"); + case 0x4: + panic("Read from i8237 channel 2 current address unimplemented.\n"); + case 0x5: + panic("Read from i8237 channel 2 remaining " + "word count unimplemented.\n"); + case 0x6: + panic("Read from i8237 channel 3 current address unimplemented.\n"); + case 0x7: + panic("Read from i8237 channel 3 remaining " + "word count unimplemented.\n"); + case 0x8: + panic("Read from i8237 status register unimplemented.\n"); + default: + panic("Read from undefined i8237 register %d.\n", offset); + } + return latency; +} + +Tick +X86ISA::I8237::write(PacketPtr pkt) +{ + assert(pkt->getSize() == 1); + Addr offset = pkt->getAddr() - pioAddr; + switch (offset) { + case 0x0: + panic("Write to i8237 channel 0 starting address unimplemented.\n"); + case 0x1: + panic("Write to i8237 channel 0 starting " + "word count unimplemented.\n"); + case 0x2: + panic("Write to i8237 channel 1 starting address unimplemented.\n"); + case 0x3: + panic("Write to i8237 channel 1 starting " + "word count unimplemented.\n"); + case 0x4: + panic("Write to i8237 channel 2 starting address unimplemented.\n"); + case 0x5: + panic("Write to i8237 channel 2 starting " + "word count unimplemented.\n"); + case 0x6: + panic("Write to i8237 channel 3 starting address unimplemented.\n"); + case 0x7: + panic("Write to i8237 channel 3 starting " + "word count unimplemented.\n"); + case 0x8: + panic("Write to i8237 command register unimplemented.\n"); + case 0x9: + panic("Write to i8237 request register unimplemented.\n"); + case 0xa: + { + uint8_t command = pkt->get(); + uint8_t select = bits(command, 1, 0); + uint8_t bitVal = bits(command, 2); + if (!bitVal) + panic("Turning on i8237 channels unimplemented.\n"); + replaceBits(maskReg, select, bitVal); + } + break; + case 0xb: + panic("Write to i8237 mode register unimplemented.\n"); + case 0xc: + panic("Write to i8237 clear LSB/MSB flip-flop " + "register unimplemented.\n"); + case 0xd: + panic("Write to i8237 master clear/reset register unimplemented.\n"); + case 0xe: + panic("Write to i8237 clear mask register unimplemented.\n"); + case 0xf: + panic("Write to i8237 write all mask register bits unimplemented.\n"); + default: + panic("Write to undefined i8254 register.\n"); + } + return latency; +} + +X86ISA::I8237 * +I8237Params::create() +{ + return new X86ISA::I8237(this); +} diff --git a/src/dev/x86/i8237.hh b/src/dev/x86/i8237.hh new file mode 100644 index 000000000..2d73b8ab5 --- /dev/null +++ b/src/dev/x86/i8237.hh @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __DEV_X86_I8237_HH__ +#define __DEV_X86_I8237_HH__ + +#include "dev/io_device.hh" +#include "params/I8237.hh" + +namespace X86ISA +{ + +class I8237 : public BasicPioDevice +{ + protected: + Tick latency; + uint8_t maskReg; + + public: + typedef I8237Params Params; + + const Params * + params() const + { + return dynamic_cast(_params); + } + + I8237(Params *p) : BasicPioDevice(p), latency(p->pio_latency), maskReg(0) + { + pioSize = 16; + } + Tick read(PacketPtr pkt); + + Tick write(PacketPtr pkt); +}; + +}; // namespace X86ISA + +#endif //__DEV_X86_I8237_HH__ -- cgit v1.2.3 From 0b228fc1ab7dbcf212a6d08aef8c7b7ff555a592 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 29 Jan 2009 22:27:11 -0800 Subject: Fix typo --- src/sim/System.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/sim/System.py b/src/sim/System.py index 5712a5c03..3b0bc1e46 100644 --- a/src/sim/System.py +++ b/src/sim/System.py @@ -38,7 +38,7 @@ class System(SimObject): type = 'System' swig_objdecls = [ '%include "python/swig/system.i"' ] - physmem = Param.PhysicalMemory(Parent.any, "phsyical memory") + physmem = Param.PhysicalMemory(Parent.any, "physical memory") mem_mode = Param.MemoryMode('atomic', "The mode the memory system is in") if build_env['FULL_SYSTEM']: abstract = True -- cgit v1.2.3 From 35a85a4e86143c5bf23d5b74c14856792a0a624c Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Fri, 30 Jan 2009 19:08:13 -0500 Subject: Config: Cause a fatal() when a parameter without a default value isn't set(FS #315). --- src/cpu/BaseCPU.py | 2 +- src/dev/DiskImage.py | 1 + src/python/m5/SimObject.py | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py index 985c415a0..f3688e991 100644 --- a/src/cpu/BaseCPU.py +++ b/src/cpu/BaseCPU.py @@ -69,7 +69,7 @@ class BaseCPU(MemObject): function_trace = Param.Bool(False, "Enable function trace") function_trace_start = Param.Tick(0, "Cycle to start function trace") - checker = Param.BaseCPU("checker CPU") + checker = Param.BaseCPU(NULL, "checker CPU") do_checkpoint_insts = Param.Bool(True, "enable checkpoint pseudo instructions") diff --git a/src/dev/DiskImage.py b/src/dev/DiskImage.py index af2407458..92eb0553c 100644 --- a/src/dev/DiskImage.py +++ b/src/dev/DiskImage.py @@ -42,3 +42,4 @@ class CowDiskImage(DiskImage): child = Param.DiskImage(RawDiskImage(read_only=True), "child image") table_size = Param.Int(65536, "initial table size") + image_file = "" diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index 868f969a6..2b5dd1bc2 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -748,7 +748,8 @@ class SimObject(object): for param in param_names: value = self._values.get(param) if value is None: - continue + m5.fatal("%s.%s without default or user set value" \ + % (self.path(), param)) value = value.getValue() if isinstance(self._params[param], VectorParamDesc): -- cgit v1.2.3 From f4291aac256622546a5a51dce109599007f5b3cb Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Fri, 30 Jan 2009 20:04:15 -0500 Subject: Errors: Print a URL with a hash of the format string to find more information about an error. --- src/base/misc.cc | 14 ++++++++++++++ src/python/m5/SimObject.py | 4 ++-- src/python/m5/__init__.py | 20 ++++++++++++++++---- src/python/m5/params.py | 4 ++-- 4 files changed, 34 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/base/misc.cc b/src/base/misc.cc index b0c769ac6..035282baf 100644 --- a/src/base/misc.cc +++ b/src/base/misc.cc @@ -31,6 +31,7 @@ #include #include #include +#include #include "base/cprintf.hh" #include "base/hostinfo.hh" @@ -68,15 +69,20 @@ __exit_message(const char *prefix, int code, default: format += "\n"; } + + uint32_t crc = crc32(0, (const Bytef*)fmt, strlen(fmt)); format += " @ cycle %d\n[%s:%s, line %d]\n"; format += "Memory Usage: %ld KBytes\n"; + format += "For more information see: http://www.m5sim.org/%s/%x\n"; args.push_back(curTick); args.push_back(func); args.push_back(file); args.push_back(line); args.push_back(memUsage()); + args.push_back(prefix); + args.push_back(crc); ccprintf(cerr, format.c_str(), args); @@ -103,6 +109,8 @@ __base_message(std::ostream &stream, const char *prefix, bool verbose, default: format += "\n"; } + + uint32_t crc = crc32(0, (const Bytef*)fmt, strlen(fmt)); if (verbose) { format += " @ cycle %d\n[%s:%s, line %d]\n"; @@ -112,5 +120,11 @@ __base_message(std::ostream &stream, const char *prefix, bool verbose, args.push_back(line); } + if (strcmp(prefix, "warn") == 0) { + format += "For more information see: http://www.m5sim.org/%s/%x\n"; + args.push_back(prefix); + args.push_back(crc); + } + ccprintf(stream, format.c_str(), args); } diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index 2b5dd1bc2..1db9c7495 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -748,8 +748,8 @@ class SimObject(object): for param in param_names: value = self._values.get(param) if value is None: - m5.fatal("%s.%s without default or user set value" \ - % (self.path(), param)) + m5.fatal("%s.%s without default or user set value", + self.path(), param) value = value.getValue() if isinstance(self._params[param], VectorParamDesc): diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py index 97b22ef2a..733258acf 100644 --- a/src/python/m5/__init__.py +++ b/src/python/m5/__init__.py @@ -37,18 +37,30 @@ MaxTick = 2**63 - 1 # define this here so we can use it right away if necessary +def errorURL(prefix, s): + try: + import zlib + hashstr = "%x" % zlib.crc32(s) + except: + hashstr = "UnableToHash" + return "For more information see: http://www.m5sim.org/%s/%s" % \ + (prefix, hashstr) + + # panic() should be called when something happens that should never # ever happen regardless of what the user does (i.e., an acutal m5 # bug). -def panic(string): - print >>sys.stderr, 'panic:', string +def panic(fmt, *args): + print >>sys.stderr, 'panic:', fmt % args + print >>sys.stderr, errorURL('panic',fmt) sys.exit(1) # fatal() should be called when the simulation cannot continue due to # some condition that is the user's fault (bad configuration, invalid # arguments, etc.) and not a simulator bug. -def fatal(string): - print >>sys.stderr, 'fatal:', string +def fatal(fmt, *args): + print >>sys.stderr, 'fatal:', fmt % args + print >>sys.stderr, errorURL('fatal',fmt) sys.exit(1) # force scalars to one-element lists for uniformity diff --git a/src/python/m5/params.py b/src/python/m5/params.py index 081bd342e..18eeac0d1 100644 --- a/src/python/m5/params.py +++ b/src/python/m5/params.py @@ -327,8 +327,8 @@ class CheckedIntType(MetaParamValue): if not (hasattr(cls, 'min') and hasattr(cls, 'max')): if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): panic("CheckedInt subclass %s must define either\n" \ - " 'min' and 'max' or 'size' and 'unsigned'\n" \ - % name); + " 'min' and 'max' or 'size' and 'unsigned'\n", + name); if cls.unsigned: cls.min = 0 cls.max = 2 ** cls.size - 1 -- cgit v1.2.3 From e7293dd24eb15ce568ffbb2f6aa8ae60f88472b1 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Fri, 30 Jan 2009 20:04:17 -0500 Subject: Errors: Use the correct panic/warn/fatal/info message in some places. --- src/arch/sparc/tlb.cc | 2 +- src/sim/process.cc | 2 +- src/sim/simulate.cc | 2 +- src/sim/system.cc | 14 +++++++------- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc index 875ae1411..9e5230674 100644 --- a/src/arch/sparc/tlb.cc +++ b/src/arch/sparc/tlb.cc @@ -1129,7 +1129,7 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) break; case ASI_SPARC_ERROR_EN_REG: case ASI_SPARC_ERROR_STATUS_REG: - warn("Ignoring write to SPARC ERROR regsiter\n"); + inform("Ignoring write to SPARC ERROR regsiter\n"); break; case ASI_HYP_SCRATCHPAD: case ASI_SCRATCHPAD: diff --git a/src/sim/process.cc b/src/sim/process.cc index a1f4c7d1d..b335d0cf2 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -343,7 +343,7 @@ Process::checkAndAllocNextPage(Addr vaddr) if(stack_base - stack_min > 8*1024*1024) fatal("Over max stack size for one thread\n"); pTable->allocate(stack_min, TheISA::PageBytes); - warn("Increasing stack size by one page."); + inform("Increasing stack size by one page."); }; return true; } diff --git a/src/sim/simulate.cc b/src/sim/simulate.cc index 9af873f90..1ac2c80df 100644 --- a/src/sim/simulate.cc +++ b/src/sim/simulate.cc @@ -84,7 +84,7 @@ simulate(Tick num_cycles) if (se_event != limit_event) { assert(limit_event->scheduled()); limit_event->squash(); - warn_once("be nice to actually delete the event here"); + hack_once("be nice to actually delete the event here"); } return se_event; diff --git a/src/sim/system.cc b/src/sim/system.cc index 864b0fdc7..d16524c41 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -95,12 +95,12 @@ System::System(Params *p) * Load the kernel code into memory */ if (params()->kernel == "") { - warn("No kernel set for full system simulation. Assuming you know what" + inform("No kernel set for full system simulation. Assuming you know what" " you're doing...\n"); } else { // Load kernel code kernel = createObjectFile(params()->kernel); - warn("kernel located at: %s", params()->kernel); + inform("kernel located at: %s", params()->kernel); if (kernel == NULL) fatal("Could not load kernel file %s", params()->kernel); @@ -115,16 +115,16 @@ System::System(Params *p) // load symbols if (!kernel->loadGlobalSymbols(kernelSymtab)) - panic("could not load kernel symbols\n"); + fatal("could not load kernel symbols\n"); if (!kernel->loadLocalSymbols(kernelSymtab)) - panic("could not load kernel local symbols\n"); + fatal("could not load kernel local symbols\n"); if (!kernel->loadGlobalSymbols(debugSymbolTable)) - panic("could not load kernel symbols\n"); + fatal("could not load kernel symbols\n"); if (!kernel->loadLocalSymbols(debugSymbolTable)) - panic("could not load kernel local symbols\n"); + fatal("could not load kernel local symbols\n"); DPRINTF(Loader, "Kernel start = %#x\n", kernelStart); DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd); @@ -184,7 +184,7 @@ System::registerThreadContext(ThreadContext *tc, int assigned) } if (threadContexts[id]) - panic("Cannot have two CPUs with the same id (%d)\n", id); + fatal("Cannot have two CPUs with the same id (%d)\n", id); threadContexts[id] = tc; _numContexts++; -- cgit v1.2.3 From be5d350afc829acf87aad5e8701f3f67476edc8b Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Fri, 30 Jan 2009 20:04:57 -0500 Subject: SCons: Fix how we get Mercurial revision information since internals keep changing. --- src/SConscript | 24 ++++++------------------ src/python/m5/main.py | 6 ++---- 2 files changed, 8 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/SConscript b/src/SConscript index 5ba89381d..27ad56397 100644 --- a/src/SConscript +++ b/src/SConscript @@ -355,25 +355,16 @@ depends = [ File(py_modules[dep]) for dep in module_depends ] scons_dir = str(SCons.Node.FS.default_fs.SConstruct_dir) -hg_info = ("Unknown", "Unknown", "Unknown") +hg_info = "Unknown" hg_demandimport = False try: if not exists(scons_dir) or not isdir(scons_dir) or \ not exists(joinpath(scons_dir, ".hg")): raise ValueError(".hg directory not found") - - import mercurial.demandimport, mercurial.hg, mercurial.ui - import mercurial.util, mercurial.node - hg_demandimport = True - - repo = mercurial.hg.repository(mercurial.ui.ui(), scons_dir) - rev = mercurial.node.nullrev + repo.changelog.count() - changenode = repo.changelog.node(rev) - changes = repo.changelog.read(changenode) - id = mercurial.node.hex(changenode) - date = mercurial.util.datestr(changes[2]) - - hg_info = (rev, id, date) + import subprocess + output = subprocess.Popen("hg id -n -i -t -b".split(), + stdout=subprocess.PIPE).communicate()[0] + hg_info = output.strip() except ImportError, e: print "Mercurial not found" except ValueError, e: @@ -381,16 +372,13 @@ except ValueError, e: except Exception, e: print "Other mercurial exception: %s" % e -if hg_demandimport: - mercurial.demandimport.disable() - # Generate Python file containing a dict specifying the current # build_env flags. def makeDefinesPyFile(target, source, env): f = file(str(target[0]), 'w') build_env, hg_info = [ x.get_contents() for x in source ] print >>f, "buildEnv = %s" % build_env - print >>f, "hgRev, hgId, hgDate = %s" % hg_info + print >>f, "hgRev = '%s'" % hg_info f.close() defines_info = [ Value(build_env), Value(hg_info) ] diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 38adac632..3edeccc10 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -192,8 +192,7 @@ def main(): print 'Build information:' print print 'compiled %s' % defines.compileDate; - print "revision %s:%s" % (defines.hgRev, defines.hgId) - print "commit date %s" % defines.hgDate + print "revision %s" % defines.hgRev print 'build options:' keys = defines.buildEnv.keys() keys.sort() @@ -268,8 +267,7 @@ def main(): print print "M5 compiled %s" % defines.compileDate; - print "M5 revision %s:%s" % (defines.hgRev, defines.hgId) - print "M5 commit date %s" % defines.hgDate + print "M5 revision %s" % defines.hgRev print "M5 started %s" % datetime.datetime.now().strftime("%b %e %Y %X") print "M5 executing on %s" % socket.gethostname() -- cgit v1.2.3 From 953e4bba59262ed4ee7268e5f49b992d7b0c02d6 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 1 Feb 2009 16:59:34 -0800 Subject: X86: Set/correct some default values for x86 parameters. --- src/arch/x86/bios/ACPI.py | 2 +- src/arch/x86/bios/IntelMP.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/arch/x86/bios/ACPI.py b/src/arch/x86/bios/ACPI.py index 20eb66be0..6f7cae946 100644 --- a/src/arch/x86/bios/ACPI.py +++ b/src/arch/x86/bios/ACPI.py @@ -94,6 +94,6 @@ class X86ACPIRSDP(SimObject): # here. revision = Param.UInt8(2, 'revision of ACPI being used, zero indexed') - rsdt = Param.X86ACPIRSDT('root system description table') + rsdt = Param.X86ACPIRSDT(NULL, 'root system description table') xsdt = Param.X86ACPIXSDT(X86ACPIXSDT(), 'extended system description table') diff --git a/src/arch/x86/bios/IntelMP.py b/src/arch/x86/bios/IntelMP.py index 758932180..1b9e819b3 100644 --- a/src/arch/x86/bios/IntelMP.py +++ b/src/arch/x86/bios/IntelMP.py @@ -115,9 +115,9 @@ class X86IntelMPProcessor(X86IntelMPBaseConfigEntry): enable = Param.Bool(True, 'if this processor is usable') bootstrap = Param.Bool(False, 'if this is the bootstrap processor') - stepping = Param.UInt8(0) - model = Param.UInt8(0) - family = Param.UInt8(0) + stepping = Param.UInt8(0, 'Processor stepping') + model = Param.UInt8(0, 'Processor model') + family = Param.UInt8(0, 'Processor family') feature_flags = Param.UInt32(0, 'flags returned by the CPUID instruction') -- cgit v1.2.3 From 64b663c6071ecd58eff6dacd38ee351038259427 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 31 Jan 2009 23:26:43 -0800 Subject: X86: Initialize the value behind port 61 so unused bits are consistent. --- src/dev/x86/speaker.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/dev/x86/speaker.hh b/src/dev/x86/speaker.hh index 7d28d6cf7..6778dcb28 100644 --- a/src/dev/x86/speaker.hh +++ b/src/dev/x86/speaker.hh @@ -64,7 +64,7 @@ class Speaker : public BasicPioDevice } Speaker(Params *p) : BasicPioDevice(p), - latency(p->pio_latency), timer(p->i8254) + latency(p->pio_latency), controlVal(0), timer(p->i8254) { pioSize = 1; } -- cgit v1.2.3 From 6a3f255a84d93f3e621319fd81f355416e385c8c Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 31 Jan 2009 23:33:54 -0800 Subject: X86: Rework interrupt pins to allow one to many connections. --- src/dev/x86/Cmos.py | 4 +- src/dev/x86/I82094AA.py | 5 ++- src/dev/x86/I8254.py | 4 +- src/dev/x86/I8259.py | 8 ++-- src/dev/x86/SouthBridge.py | 21 ++++++++--- src/dev/x86/X86IntPin.py | 24 +++++++++--- src/dev/x86/cmos.cc | 4 +- src/dev/x86/cmos.hh | 6 +-- src/dev/x86/i82094aa.cc | 20 +++++++++- src/dev/x86/i82094aa.hh | 9 ++--- src/dev/x86/i8254.cc | 7 +++- src/dev/x86/i8254.hh | 4 +- src/dev/x86/i8259.cc | 38 +++++++++++++------ src/dev/x86/i8259.hh | 11 ++---- src/dev/x86/intdev.cc | 18 +++++++-- src/dev/x86/intdev.hh | 92 +++++++++++++++++++++++++++++++++++++++------- 16 files changed, 207 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/src/dev/x86/Cmos.py b/src/dev/x86/Cmos.py index a9910f70d..0a92145e2 100644 --- a/src/dev/x86/Cmos.py +++ b/src/dev/x86/Cmos.py @@ -29,6 +29,7 @@ from m5.params import * from m5.proxy import * from Device import BasicPioDevice +from X86IntPin import X86IntSourcePin class Cmos(BasicPioDevice): type = 'Cmos' @@ -36,4 +37,5 @@ class Cmos(BasicPioDevice): time = Param.Time('01/01/2009', "System time to use ('Now' for actual time)") pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") - int_pin = Param.X86IntPin('Pin to signal RTC alarm interrupts to') + int_pin = Param.X86IntSourcePin(X86IntSourcePin(), + 'Pin to signal RTC alarm interrupts to') diff --git a/src/dev/x86/I82094AA.py b/src/dev/x86/I82094AA.py index b4ad96a9f..5ca58614d 100644 --- a/src/dev/x86/I82094AA.py +++ b/src/dev/x86/I82094AA.py @@ -29,7 +29,7 @@ from m5.params import * from m5.proxy import * from Device import BasicPioDevice -from X86IntPin import X86IntPin +from X86IntPin import X86IntSinkPin class I82094AA(BasicPioDevice): type = 'I82094AA' @@ -37,6 +37,7 @@ class I82094AA(BasicPioDevice): pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") pio_addr = Param.Addr("Device address") int_port = Port("Port for sending and receiving interrupt messages") + external_int_pic = Param.I8259("External PIC, if any") def pin(self, line): - return X86IntPin(device=self, line=line) + return X86IntSinkPin(device=self, number=line) diff --git a/src/dev/x86/I8254.py b/src/dev/x86/I8254.py index d67d04e86..f468717cc 100644 --- a/src/dev/x86/I8254.py +++ b/src/dev/x86/I8254.py @@ -29,9 +29,11 @@ from m5.params import * from m5.proxy import * from Device import BasicPioDevice +from X86IntPin import X86IntSourcePin class I8254(BasicPioDevice): type = 'I8254' cxx_class = 'X86ISA::I8254' pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") - int_pin = Param.X86IntPin('Pin to signal timer interrupts to') + int_pin = Param.X86IntSourcePin(X86IntSourcePin(), + 'Pin to signal timer interrupts to') diff --git a/src/dev/x86/I8259.py b/src/dev/x86/I8259.py index d241b092a..e0128d032 100644 --- a/src/dev/x86/I8259.py +++ b/src/dev/x86/I8259.py @@ -29,7 +29,7 @@ from m5.params import * from m5.proxy import * from Device import BasicPioDevice -from X86IntPin import X86IntPin +from X86IntPin import X86IntSourcePin, X86IntSinkPin class X86I8259CascadeMode(Enum): map = {'I8259Master' : 0, @@ -41,8 +41,10 @@ class I8259(BasicPioDevice): type = 'I8259' cxx_class='X86ISA::I8259' pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") - output = Param.X86IntPin('The pin this I8259 drives') + output = Param.X86IntSourcePin(X86IntSourcePin(), + 'The pin this I8259 drives') mode = Param.X86I8259CascadeMode('How this I8259 is cascaded') + slave = Param.I8259('Slave I8259, if any') def pin(self, line): - return X86IntPin(device=self, line=line) + return X86IntSinkPin(device=self, number=line) diff --git a/src/dev/x86/SouthBridge.py b/src/dev/x86/SouthBridge.py index bbe3ad102..ba9aaf2b4 100644 --- a/src/dev/x86/SouthBridge.py +++ b/src/dev/x86/SouthBridge.py @@ -34,6 +34,7 @@ from I8237 import I8237 from I8254 import I8254 from I8259 import I8259 from PcSpeaker import PcSpeaker +from X86IntPin import X86IntLine from m5.SimObject import SimObject def x86IOAddress(port): @@ -52,6 +53,9 @@ class SouthBridge(SimObject): _pit = I8254(pio_addr=x86IOAddress(0x40)) _speaker = PcSpeaker(pio_addr=x86IOAddress(0x61)) _io_apic = I82094AA(pio_addr=0xFEC00000) + # This is to make sure the interrupt lines are instantiated. Don't use + # it for anything directly. + int_lines = VectorParam.X86IntLine([], "Interrupt lines") pic1 = Param.I8259(_pic1, "Master PIC") pic2 = Param.I8259(_pic2, "Slave PIC") @@ -61,13 +65,20 @@ class SouthBridge(SimObject): speaker = Param.PcSpeaker(_speaker, "PC speaker") io_apic = Param.I82094AA(_io_apic, "I/O APIC") + def connectPins(self, source, sink): + self.int_lines.append(X86IntLine(source=source, sink=sink)) + def attachIO(self, bus): - # Make internal connections - self.pic1.output = self.io_apic.pin(0) - self.pic2.output = self.pic1.pin(2) - self.cmos.int_pin = self.pic2.pin(0) - self.pit.int_pin = self.pic1.pin(0) + # Route interupt signals + self.connectPins(self.pic1.output, self.io_apic.pin(0)) + self.connectPins(self.pic2.output, self.pic1.pin(2)) + self.connectPins(self.cmos.int_pin, self.pic2.pin(0)) + self.connectPins(self.pit.int_pin, self.pic1.pin(0)) + self.connectPins(self.pit.int_pin, self.io_apic.pin(2)) + # Tell the devices about each other + self.pic1.slave = self.pic2 self.speaker.i8254 = self.pit + self.io_apic.external_int_pic = self.pic1 # Connect to the bus self.cmos.pio = bus.port self.dma1.pio = bus.port diff --git a/src/dev/x86/X86IntPin.py b/src/dev/x86/X86IntPin.py index 372b4ab66..35e274624 100644 --- a/src/dev/x86/X86IntPin.py +++ b/src/dev/x86/X86IntPin.py @@ -29,9 +29,23 @@ from m5.params import * from m5.SimObject import SimObject -class X86IntPin(SimObject): - type = 'X86IntPin' - cxx_class = 'X86ISA::IntPin' +# A generic pin to drive an interrupt signal generated by a device. +class X86IntSourcePin(SimObject): + type = 'X86IntSourcePin' + cxx_class = 'X86ISA::IntSourcePin' - line = Param.Int("Interrupt line for this pin") - device = Param.SimObject("Device which handles interrupts") +# A generic pin to receive an interrupt signal generated by another device. +class X86IntSinkPin(SimObject): + type = 'X86IntSinkPin' + cxx_class = 'X86ISA::IntSinkPin' + + device = Param.SimObject("Device this pin belongs to") + number = Param.Int("The pin number on the device") + +# An interrupt line which is driven by a source pin and drives a sink pin. +class X86IntLine(SimObject): + type = 'X86IntLine' + cxx_class = 'X86ISA::IntLine' + + source = Param.X86IntSourcePin("Pin driving this line") + sink = Param.X86IntSinkPin("Pin driven by this line") diff --git a/src/dev/x86/cmos.cc b/src/dev/x86/cmos.cc index c88592870..6bdc78a4b 100644 --- a/src/dev/x86/cmos.cc +++ b/src/dev/x86/cmos.cc @@ -36,7 +36,9 @@ void X86ISA::Cmos::X86RTC::handleEvent() { assert(intPin); - intPin->signalInterrupt(); + intPin->raise(); + //XXX This is a hack. + intPin->lower(); } Tick diff --git a/src/dev/x86/cmos.hh b/src/dev/x86/cmos.hh index 45fb9e8f2..76276dbc1 100644 --- a/src/dev/x86/cmos.hh +++ b/src/dev/x86/cmos.hh @@ -38,7 +38,7 @@ namespace X86ISA { -class IntPin; +class IntSourcePin; class Cmos : public BasicPioDevice { @@ -57,10 +57,10 @@ class Cmos : public BasicPioDevice class X86RTC : public MC146818 { protected: - IntPin * intPin; + IntSourcePin * intPin; public: X86RTC(EventManager *em, const std::string &n, const struct tm time, - bool bcd, Tick frequency, IntPin * _intPin) : + bool bcd, Tick frequency, IntSourcePin * _intPin) : MC146818(em, n, time, bcd, frequency), intPin(_intPin) { } diff --git a/src/dev/x86/i82094aa.cc b/src/dev/x86/i82094aa.cc index a229fffc3..03944c190 100644 --- a/src/dev/x86/i82094aa.cc +++ b/src/dev/x86/i82094aa.cc @@ -36,7 +36,8 @@ #include "sim/system.hh" X86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), IntDev(this), - latency(p->pio_latency), pioAddr(p->pio_addr), extIntPic(NULL) + latency(p->pio_latency), pioAddr(p->pio_addr), + extIntPic(p->external_int_pic) { // This assumes there's only one I/O APIC in the system id = sys->numContexts(); @@ -47,6 +48,7 @@ X86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), IntDev(this), entry.mask = 1; for (int i = 0; i < TableSize; i++) { redirTable[i] = entry; + pinStates[i] = false; } } @@ -209,6 +211,22 @@ X86ISA::I82094AA::signalInterrupt(int line) } } +void +X86ISA::I82094AA::raiseInterruptPin(int number) +{ + assert(number < TableSize); + if (!pinStates[number]) + signalInterrupt(number); + pinStates[number] = true; +} + +void +X86ISA::I82094AA::lowerInterruptPin(int number) +{ + assert(number < TableSize); + pinStates[number] = false; +} + X86ISA::I82094AA * I82094AAParams::create() { diff --git a/src/dev/x86/i82094aa.hh b/src/dev/x86/i82094aa.hh index 6a8873d45..b11e2bcb1 100644 --- a/src/dev/x86/i82094aa.hh +++ b/src/dev/x86/i82094aa.hh @@ -77,6 +77,7 @@ class I82094AA : public PioDevice, public IntDev static const uint8_t APICVersion = 0x14; RedirTableEntry redirTable[TableSize]; + bool pinStates[TableSize]; public: typedef I82094AAParams Params; @@ -89,12 +90,6 @@ class I82094AA : public PioDevice, public IntDev I82094AA(Params *p); - void - setExtIntPic(I8259 * pic) - { - extIntPic = pic; - } - Tick read(PacketPtr pkt); Tick write(PacketPtr pkt); @@ -123,6 +118,8 @@ class I82094AA : public PioDevice, public IntDev } void signalInterrupt(int line); + void raiseInterruptPin(int number); + void lowerInterruptPin(int number); }; }; // namespace X86ISA diff --git a/src/dev/x86/i8254.cc b/src/dev/x86/i8254.cc index ac3847cd6..4f37eebad 100644 --- a/src/dev/x86/i8254.cc +++ b/src/dev/x86/i8254.cc @@ -37,8 +37,11 @@ void X86ISA::I8254::counterInterrupt(unsigned int num) { DPRINTF(I8254, "Interrupt from counter %d.\n", num); - if (num == 0) - intPin->signalInterrupt(); + if (num == 0) { + intPin->raise(); + //XXX This is a hack. + intPin->lower(); + } } Tick diff --git a/src/dev/x86/i8254.hh b/src/dev/x86/i8254.hh index e6860b2c4..7de20dfd4 100644 --- a/src/dev/x86/i8254.hh +++ b/src/dev/x86/i8254.hh @@ -38,7 +38,7 @@ namespace X86ISA { -class IntPin; +class IntSourcePin; class I8254 : public BasicPioDevice { @@ -64,7 +64,7 @@ class I8254 : public BasicPioDevice X86Intel8254Timer pit; - IntPin *intPin; + IntSourcePin *intPin; void counterInterrupt(unsigned int num); diff --git a/src/dev/x86/i8259.cc b/src/dev/x86/i8259.cc index b3d3a5aa2..b7c8bb08a 100644 --- a/src/dev/x86/i8259.cc +++ b/src/dev/x86/i8259.cc @@ -36,20 +36,12 @@ X86ISA::I8259::I8259(Params * p) : BasicPioDevice(p), IntDev(this), latency(p->pio_latency), output(p->output), - mode(p->mode), slave(NULL), + mode(p->mode), slave(p->slave), IRR(0), ISR(0), IMR(0), readIRR(true), initControlWord(0), autoEOI(false) { - if (output) { - I8259 * master; - master = dynamic_cast(output->getDevice()); - if (master) - master->setSlave(this); - I82094AA * ioApic; - ioApic = dynamic_cast(output->getDevice()); - if (ioApic) - ioApic->setExtIntPic(this); - } + for (int i = 0; i < NumLines; i++) + pinStates[i] = false; pioSize = 2; } @@ -237,7 +229,9 @@ X86ISA::I8259::requestInterrupt(int line) if (bits(ISR, 7, line) == 0) { if (output) { DPRINTF(I8259, "Propogating interrupt.\n"); - output->signalInterrupt(); + output->raise(); + //XXX This is a hack. + output->lower(); } else { warn("Received interrupt but didn't have " "anyone to tell about it.\n"); @@ -260,6 +254,26 @@ X86ISA::I8259::signalInterrupt(int line) } } +void +X86ISA::I8259::raiseInterruptPin(int number) +{ + if (number >= NumLines) + fatal("Line number %d doesn't exist. The max is %d.\n", + number, NumLines - 1); + if (!pinStates[number]) + signalInterrupt(number); + pinStates[number] = true; +} + +void +X86ISA::I8259::lowerInterruptPin(int number) +{ + if (number >= NumLines) + fatal("Line number %d doesn't exist. The max is %d.\n", + number, NumLines - 1); + pinStates[number] = false; +} + int X86ISA::I8259::getVector() { diff --git a/src/dev/x86/i8259.hh b/src/dev/x86/i8259.hh index 5a2cf72e8..dfb56646a 100644 --- a/src/dev/x86/i8259.hh +++ b/src/dev/x86/i8259.hh @@ -45,9 +45,10 @@ class I8259 : public BasicPioDevice, public IntDev { protected: static const int NumLines = 8; + bool pinStates[NumLines]; Tick latency; - IntPin *output; + IntSourcePin *output; Enums::X86I8259CascadeMode mode; I8259 * slave; @@ -90,16 +91,12 @@ class I8259 : public BasicPioDevice, public IntDev I8259(Params * p); - void - setSlave(I8259 * _slave) - { - slave = _slave; - } - Tick read(PacketPtr pkt); Tick write(PacketPtr pkt); void signalInterrupt(int line); + void raiseInterruptPin(int number); + void lowerInterruptPin(int number); int getVector(); }; diff --git a/src/dev/x86/intdev.cc b/src/dev/x86/intdev.cc index 463b3c9fe..e386687a9 100644 --- a/src/dev/x86/intdev.cc +++ b/src/dev/x86/intdev.cc @@ -30,8 +30,20 @@ #include "dev/x86/intdev.hh" -X86ISA::IntPin * -X86IntPinParams::create() +X86ISA::IntSourcePin * +X86IntSourcePinParams::create() { - return new X86ISA::IntPin(this); + return new X86ISA::IntSourcePin(this); +} + +X86ISA::IntSinkPin * +X86IntSinkPinParams::create() +{ + return new X86ISA::IntSinkPin(this); +} + +X86ISA::IntLine * +X86IntLineParams::create() +{ + return new X86ISA::IntLine(this); } diff --git a/src/dev/x86/intdev.hh b/src/dev/x86/intdev.hh index ba9a073a4..ca8e7eea5 100644 --- a/src/dev/x86/intdev.hh +++ b/src/dev/x86/intdev.hh @@ -38,7 +38,9 @@ #include "mem/mem_object.hh" #include "mem/mport.hh" #include "sim/sim_object.hh" -#include "params/X86IntPin.hh" +#include "params/X86IntSourcePin.hh" +#include "params/X86IntSinkPin.hh" +#include "params/X86IntLine.hh" namespace X86ISA { @@ -99,6 +101,18 @@ class IntDev panic("signalInterrupt not implemented.\n"); } + virtual void + raiseInterruptPin(int number) + { + panic("raiseInterruptPin not implemented.\n"); + } + + virtual void + lowerInterruptPin(int number) + { + panic("lowerInterruptPin not implemented.\n"); + } + virtual Tick recvMessage(PacketPtr pkt) { @@ -113,20 +127,34 @@ class IntDev } }; -class IntPin : public SimObject +class IntSinkPin : public SimObject { - protected: + public: IntDev * device; - int line; + int number; - public: - typedef X86IntPinParams Params; + typedef X86IntSinkPinParams Params; + + const Params * + params() const + { + return dynamic_cast(_params); + } - IntDev * - getDevice() const + IntSinkPin(Params *p) : SimObject(p), + device(dynamic_cast(p->device)), number(p->number) { - return device; + assert(device); } +}; + +class IntSourcePin : public SimObject +{ + protected: + std::vector sinks; + + public: + typedef X86IntSourcePinParams Params; const Params * params() const @@ -134,16 +162,52 @@ class IntPin : public SimObject return dynamic_cast(_params); } - IntPin(Params *p) : SimObject(p), - device(dynamic_cast(p->device)), line(p->line) + void + addSink(IntSinkPin *sink) { - assert(device); + sinks.push_back(sink); } void - signalInterrupt() + raise() + { + for (int i = 0; i < sinks.size(); i++) { + const IntSinkPin &pin = *sinks[i]; + pin.device->raiseInterruptPin(pin.number); + } + } + + void + lower() + { + for (int i = 0; i < sinks.size(); i++) { + const IntSinkPin &pin = *sinks[i]; + pin.device->lowerInterruptPin(pin.number); + } + } + + IntSourcePin(Params *p) : SimObject(p) + {} +}; + +class IntLine : public SimObject +{ + protected: + IntSourcePin *source; + IntSinkPin *sink; + + public: + typedef X86IntLineParams Params; + + const Params * + params() const + { + return dynamic_cast(_params); + } + + IntLine(Params *p) : SimObject(p), source(p->source), sink(p->sink) { - device->signalInterrupt(line); + source->addSink(sink); } }; -- cgit v1.2.3 From e1c412cec690083f93ae0cb741c03e00e77cde71 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 31 Jan 2009 23:44:05 -0800 Subject: X86: Configure the IO APIC more. --- src/dev/x86/pc.cc | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'src') diff --git a/src/dev/x86/pc.cc b/src/dev/x86/pc.cc index 94fb23e21..c2e562517 100644 --- a/src/dev/x86/pc.cc +++ b/src/dev/x86/pc.cc @@ -83,6 +83,23 @@ Pc::init() entry.vector = 0x20; ioApic.writeReg(0x10, entry.bottomDW); ioApic.writeReg(0x11, entry.topDW); + entry.deliveryMode = DeliveryMode::Fixed; + entry.vector = 0x24; + ioApic.writeReg(0x18, entry.bottomDW); + ioApic.writeReg(0x19, entry.topDW); + entry.mask = 1; + entry.vector = 0x21; + ioApic.writeReg(0x12, entry.bottomDW); + ioApic.writeReg(0x13, entry.topDW); + entry.vector = 0x20; + ioApic.writeReg(0x14, entry.bottomDW); + ioApic.writeReg(0x15, entry.topDW); + entry.vector = 0x28; + ioApic.writeReg(0x20, entry.bottomDW); + ioApic.writeReg(0x21, entry.topDW); + entry.vector = 0x2C; + ioApic.writeReg(0x28, entry.bottomDW); + ioApic.writeReg(0x29, entry.topDW); } Tick -- cgit v1.2.3 From 0287f19edecd317a139d2ff809901b9c91eb0c2e Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 31 Jan 2009 23:56:46 -0800 Subject: X86: Set up the console interrupt and add some DPRINTFs. --- src/dev/x86/i8259.cc | 4 +++- src/dev/x86/pc.cc | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/dev/x86/i8259.cc b/src/dev/x86/i8259.cc index b7c8bb08a..f9e0a0c93 100644 --- a/src/dev/x86/i8259.cc +++ b/src/dev/x86/i8259.cc @@ -242,7 +242,7 @@ X86ISA::I8259::requestInterrupt(int line) void X86ISA::I8259::signalInterrupt(int line) { - DPRINTF(I8259, "Interrupt raised on line %d.\n", line); + DPRINTF(I8259, "Interrupt requested for line %d.\n", line); if (line >= NumLines) fatal("Line number %d doesn't exist. The max is %d.\n", line, NumLines - 1); @@ -257,6 +257,7 @@ X86ISA::I8259::signalInterrupt(int line) void X86ISA::I8259::raiseInterruptPin(int number) { + DPRINTF(I8259, "Interrupt signal raised for pin %d.\n", number); if (number >= NumLines) fatal("Line number %d doesn't exist. The max is %d.\n", number, NumLines - 1); @@ -268,6 +269,7 @@ X86ISA::I8259::raiseInterruptPin(int number) void X86ISA::I8259::lowerInterruptPin(int number) { + DPRINTF(I8259, "Interrupt signal lowered for pin %d.\n", number); if (number >= NumLines) fatal("Line number %d doesn't exist. The max is %d.\n", number, NumLines - 1); diff --git a/src/dev/x86/pc.cc b/src/dev/x86/pc.cc index c2e562517..2deed95d3 100644 --- a/src/dev/x86/pc.cc +++ b/src/dev/x86/pc.cc @@ -42,6 +42,7 @@ #include "dev/terminal.hh" #include "dev/x86/i82094aa.hh" #include "dev/x86/i8254.hh" +#include "dev/x86/i8259.hh" #include "dev/x86/pc.hh" #include "dev/x86/south_bridge.hh" #include "sim/system.hh" @@ -112,8 +113,8 @@ Pc::intrFrequency() void Pc::postConsoleInt() { - warn_once("Don't know what interrupt to post for console.\n"); - //panic("Need implementation\n"); + southBridge->ioApic->signalInterrupt(4); + southBridge->pic1->signalInterrupt(4); } void -- cgit v1.2.3 From 7cf276bed34c2ed1f8f86bbf46497aab3f8ebc6c Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 31 Jan 2009 23:59:01 -0800 Subject: X86: Add a keyboard controller device. --- src/dev/x86/I8042.py | 43 ++++ src/dev/x86/SConscript | 4 + src/dev/x86/SouthBridge.py | 13 ++ src/dev/x86/i8042.cc | 529 +++++++++++++++++++++++++++++++++++++++++++++ src/dev/x86/i8042.hh | 142 ++++++++++++ 5 files changed, 731 insertions(+) create mode 100644 src/dev/x86/I8042.py create mode 100644 src/dev/x86/i8042.cc create mode 100644 src/dev/x86/i8042.hh (limited to 'src') diff --git a/src/dev/x86/I8042.py b/src/dev/x86/I8042.py new file mode 100644 index 000000000..1f6a48410 --- /dev/null +++ b/src/dev/x86/I8042.py @@ -0,0 +1,43 @@ +# Copyright (c) 2008 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +from m5.params import * +from m5.proxy import * +from Device import BasicPioDevice +from X86IntPin import X86IntSourcePin + +class I8042(BasicPioDevice): + type = 'I8042' + cxx_class = 'X86ISA::I8042' + pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") + data_port = Param.Addr('Data port address') + command_port = Param.Addr('Command/status port address') + mouse_int_pin = Param.X86IntSourcePin(X86IntSourcePin(), + 'Pin to signal the mouse has data') + keyboard_int_pin = Param.X86IntSourcePin(X86IntSourcePin(), + 'Pin to signal the keyboard has data') diff --git a/src/dev/x86/SConscript b/src/dev/x86/SConscript index 167b14a84..e7543dfdf 100644 --- a/src/dev/x86/SConscript +++ b/src/dev/x86/SConscript @@ -53,6 +53,10 @@ if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'x86': Source('i8237.cc') TraceFlag('I8237', 'The I8237 dma controller'); + SimObject('I8042.py') + Source('i8042.cc') + TraceFlag('I8042', 'The I8042 keyboard controller'); + SimObject('PcSpeaker.py') Source('speaker.cc') TraceFlag('PcSpeaker') diff --git a/src/dev/x86/SouthBridge.py b/src/dev/x86/SouthBridge.py index ba9aaf2b4..a3db83610 100644 --- a/src/dev/x86/SouthBridge.py +++ b/src/dev/x86/SouthBridge.py @@ -29,6 +29,7 @@ from m5.params import * from m5.proxy import * from Cmos import Cmos +from I8042 import I8042 from I82094AA import I82094AA from I8237 import I8237 from I8254 import I8254 @@ -50,6 +51,8 @@ class SouthBridge(SimObject): _pic2 = I8259(pio_addr=x86IOAddress(0xA0), mode='I8259Slave') _cmos = Cmos(pio_addr=x86IOAddress(0x70)) _dma1 = I8237(pio_addr=x86IOAddress(0x0)) + _keyboard = I8042(data_port=x86IOAddress(0x60), \ + command_port=x86IOAddress(0x64)) _pit = I8254(pio_addr=x86IOAddress(0x40)) _speaker = PcSpeaker(pio_addr=x86IOAddress(0x61)) _io_apic = I82094AA(pio_addr=0xFEC00000) @@ -61,6 +64,7 @@ class SouthBridge(SimObject): pic2 = Param.I8259(_pic2, "Slave PIC") cmos = Param.Cmos(_cmos, "CMOS memory and real time clock device") dma1 = Param.I8237(_dma1, "The first dma controller") + keyboard = Param.I8042(_keyboard, "The keyboard controller") pit = Param.I8254(_pit, "Programmable interval timer") speaker = Param.PcSpeaker(_speaker, "PC speaker") io_apic = Param.I82094AA(_io_apic, "I/O APIC") @@ -75,6 +79,14 @@ class SouthBridge(SimObject): self.connectPins(self.cmos.int_pin, self.pic2.pin(0)) self.connectPins(self.pit.int_pin, self.pic1.pin(0)) self.connectPins(self.pit.int_pin, self.io_apic.pin(2)) +# self.connectPins(self.keyboard.keyboard_int_pin, +# self.pic1.pin(1)) + self.connectPins(self.keyboard.keyboard_int_pin, + self.io_apic.pin(1)) +# self.connectPins(self.keyboard.mouse_int_pin, +# self.pic2.pin(4)) + self.connectPins(self.keyboard.mouse_int_pin, + self.io_apic.pin(12)) # Tell the devices about each other self.pic1.slave = self.pic2 self.speaker.i8254 = self.pit @@ -82,6 +94,7 @@ class SouthBridge(SimObject): # Connect to the bus self.cmos.pio = bus.port self.dma1.pio = bus.port + self.keyboard.pio = bus.port self.pic1.pio = bus.port self.pic2.pio = bus.port self.pit.pio = bus.port diff --git a/src/dev/x86/i8042.cc b/src/dev/x86/i8042.cc new file mode 100644 index 000000000..7dff49823 --- /dev/null +++ b/src/dev/x86/i8042.cc @@ -0,0 +1,529 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "base/bitunion.hh" +#include "dev/x86/i8042.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" + +// The 8042 has a whopping 32 bytes of internal RAM. +const uint8_t RamSize = 32; +const uint8_t NumOutputBits = 14; +const uint8_t KeyboardID[] = {0xab, 0x83}; +const uint8_t MouseID[] = {0x00}; +const uint8_t CommandAck = 0xfa; +const uint8_t CommandNack = 0xfe; +const uint8_t BatSuccessful = 0xaa; + +enum Port64Command +{ + GetCommandByte = 0x20, + ReadControllerRamBase = 0x20, + WriteCommandByte = 0x60, + WriteControllerRamBase = 0x60, + CheckForPassword = 0xA4, + LoadPassword = 0xA5, + CheckPassword = 0xA6, + DisableMouse = 0xA7, + EnableMouse = 0xA8, + TestMouse = 0xA9, + SelfTest = 0xAA, + InterfaceTest = 0xAB, + DiagnosticDump = 0xAC, + DisableKeyboard = 0xAD, + EnableKeyboard = 0xAE, + ReadInputPort = 0xC0, + ContinuousPollLow = 0xC1, + ContinuousPollHigh = 0xC2, + ReadOutputPort = 0xD0, + WriteOutputPort = 0xD1, + WriteKeyboardOutputBuff = 0xD2, + WriteMouseOutputBuff = 0xD3, + WriteToMouse = 0xD4, + DisableA20 = 0xDD, + EnableA20 = 0xDF, + ReadTestInputs = 0xE0, + PulseOutputBitBase = 0xF0, + SystemReset = 0xFE +}; + +enum Port60Command +{ + MouseScale1to1 = 0xE6, + MouseScale2to1 = 0xE7, + SetMouseResolution = 0xE8, + MouseGetStatus = 0xE9, + MouseReadData = 0xEB, + MouseResetWrapMode = 0xEC, + LEDWrite = 0xED, + DiagnosticEcho = 0xEE, + MouseWrapMode = 0xEE, + AlternateScanCodes = 0xF0, + MouseRemoteMode = 0xF0, + ReadKeyboardID = 0xF2, + ReadMouseID = 0xF2, + TypematicInfo = 0xF3, + MouseSampleRate = 0xF3, + KeyboardEnable = 0xF4, + MouseEnableReporting = 0xF4, + KeyboardDisable = 0xF5, + MouseDisableReporting = 0xF5, + DefaultsAndDisableKeyboard = 0xF6, + DefaultsAndDisableMouse = 0xF6, + AllKeysToTypematic = 0xF7, + AllKeysToMakeRelease = 0xF8, + AllKeysToMake = 0xF9, + AllKeysToTypematicMakeRelease = 0xFA, + KeyToTypematic = 0xFB, + KeyToMakeRelease = 0xFC, + KeyToMakeOnly = 0xFD, + Resend = 0xFE, + KeyboardReset = 0xFF, + MouseReset = 0xFF +}; + +void +X86ISA::I8042::addressRanges(AddrRangeList &range_list) +{ + range_list.clear(); + range_list.push_back(RangeSize(dataPort, 1)); + range_list.push_back(RangeSize(commandPort, 1)); +} + +bool +X86ISA::I8042::writeData(uint8_t newData, bool mouse) +{ + if (!statusReg.outputFull) { + DPRINTF(I8042, "Set data %#02x.\n", newData); + dataReg = newData; + statusReg.outputFull = 1; + statusReg.mouseOutputFull = (mouse ? 1 : 0); + return true; + } else { + return false; + } +} + +void +X86ISA::I8042::keyboardAck() +{ + while (!keyboardBuffer.empty()) + keyboardBuffer.pop(); + writeKeyboardData(&CommandAck, sizeof(CommandAck)); +} + +void +X86ISA::I8042::writeKeyboardData(const uint8_t *data, int size) +{ + assert(data || size == 0); + while (size) { + keyboardBuffer.push(*(data++)); + size--; + } + if (writeData(keyboardBuffer.front())) { + keyboardBuffer.pop(); + if (commandByte.keyboardFullInt) { + DPRINTF(I8042, "Sending keyboard interrupt.\n"); + keyboardIntPin->raise(); + //XXX This is a hack. + keyboardIntPin->lower(); + } + } +} + +void +X86ISA::I8042::mouseAck() +{ + while (!mouseBuffer.empty()) + mouseBuffer.pop(); + writeMouseData(&CommandAck, sizeof(CommandAck)); +} + +void +X86ISA::I8042::mouseNack() +{ + while (!mouseBuffer.empty()) + mouseBuffer.pop(); + writeMouseData(&CommandNack, sizeof(CommandAck)); +} + +void +X86ISA::I8042::writeMouseData(const uint8_t *data, int size) +{ + assert(data || size == 0); + while (size) { + mouseBuffer.push(*(data++)); + size--; + } + if (writeData(mouseBuffer.front(), true)) { + mouseBuffer.pop(); + if (commandByte.mouseFullInt) { + DPRINTF(I8042, "Sending mouse interrupt.\n"); + mouseIntPin->raise(); + //XXX This is a hack + mouseIntPin->lower(); + } + } +} + +uint8_t +X86ISA::I8042::readDataOut() +{ + uint8_t data = dataReg; + statusReg.outputFull = 0; + statusReg.mouseOutputFull = 0; + if (!keyboardBuffer.empty()) { + writeKeyboardData(NULL, 0); + } + if (!mouseBuffer.empty()) { + writeMouseData(NULL, 0); + } + return data; +} + +Tick +X86ISA::I8042::read(PacketPtr pkt) +{ + assert(pkt->getSize() == 1); + Addr addr = pkt->getAddr(); + if (addr == dataPort) { + uint8_t data = readDataOut(); + //DPRINTF(I8042, "Read from data port got %#02x.\n", data); + pkt->set(data); + } else if (addr == commandPort) { + //DPRINTF(I8042, "Read status as %#02x.\n", (uint8_t)statusReg); + pkt->set((uint8_t)statusReg); + } else { + panic("Read from unrecognized port %#x.\n", addr); + } + return latency; +} + +Tick +X86ISA::I8042::write(PacketPtr pkt) +{ + assert(pkt->getSize() == 1); + Addr addr = pkt->getAddr(); + uint8_t data = pkt->get(); + if (addr == dataPort) { + statusReg.commandLast = 0; + switch (lastCommand) { + case NoCommand: + if (lastKeyboardCommand != NoCommand) { + switch (lastKeyboardCommand) { + case LEDWrite: + DPRINTF(I8042, "Setting LEDs: " + "caps lock %s, num lock %s, scroll lock %s\n", + bits(data, 2) ? "on" : "off", + bits(data, 1) ? "on" : "off", + bits(data, 0) ? "on" : "off"); + keyboardAck(); + lastKeyboardCommand = NoCommand; + break; + case TypematicInfo: + DPRINTF(I8042, + "Setting typematic info to %#02x.\n", data); + keyboardAck(); + lastKeyboardCommand = NoCommand; + break; + } + break; + } + DPRINTF(I8042, "Got port 0x60 command %#02x.\n", data); + switch (data) { + case LEDWrite: + DPRINTF(I8042, "Got LED write command.\n"); + keyboardAck(); + lastKeyboardCommand = LEDWrite; + break; + case DiagnosticEcho: + panic("Keyboard diagnostic echo unimplemented.\n"); + case AlternateScanCodes: + panic("Accessing alternate scan codes unimplemented.\n"); + case ReadKeyboardID: + DPRINTF(I8042, "Got keyboard read ID command.\n"); + keyboardAck(); + writeKeyboardData((uint8_t *)&KeyboardID, sizeof(KeyboardID)); + break; + case TypematicInfo: + DPRINTF(I8042, "Setting typematic info.\n"); + keyboardAck(); + lastKeyboardCommand = TypematicInfo; + break; + case KeyboardEnable: + DPRINTF(I8042, "Enabling the keyboard.\n"); + keyboardAck(); + break; + case KeyboardDisable: + DPRINTF(I8042, "Disabling the keyboard.\n"); + keyboardAck(); + break; + case DefaultsAndDisableKeyboard: + DPRINTF(I8042, "Disabling and resetting the keyboard.\n"); + keyboardAck(); + break; + case AllKeysToTypematic: + panic("Setting all keys to typemantic unimplemented.\n"); + case AllKeysToMakeRelease: + panic("Setting all keys to make/release unimplemented.\n"); + case AllKeysToMake: + panic("Setting all keys to make unimplemented.\n"); + case AllKeysToTypematicMakeRelease: + panic("Setting all keys to " + "typematic/make/release unimplemented.\n"); + case KeyToTypematic: + panic("Setting a key to typematic unimplemented.\n"); + case KeyToMakeRelease: + panic("Setting a key to make/release unimplemented.\n"); + case KeyToMakeOnly: + panic("Setting key to make only unimplemented.\n"); + case Resend: + panic("Keyboard resend unimplemented.\n"); + case KeyboardReset: + panic("Keyboard reset unimplemented.\n"); + default: + panic("Unknown keyboard command %#02x.\n", data); + } + break; + case WriteToMouse: + if (lastMouseCommand != NoCommand) { + switch(lastMouseCommand) { + case SetMouseResolution: + DPRINTF(I8042, "Mouse resolution set to %d.\n", data); + mouseResolution = data; + mouseAck(); + lastMouseCommand = NoCommand; + break; + case MouseSampleRate: + DPRINTF(I8042, "Mouse sample rate %d samples " + "per second.\n", data); + mouseSampleRate = data; + mouseAck(); + lastMouseCommand = NoCommand; + break; + default: + panic("Not expecting data for a mouse command.\n"); + } + break; + } + switch (data) { + case MouseScale1to1: + DPRINTF(I8042, "Setting mouse scale to 1:1.\n"); + mouseStatus.twoToOne = 0; + mouseAck(); + break; + case MouseScale2to1: + DPRINTF(I8042, "Setting mouse scale to 2:1.\n"); + mouseStatus.twoToOne = 1; + mouseAck(); + break; + case SetMouseResolution: + DPRINTF(I8042, "Setting mouse resolution.\n"); + lastMouseCommand = SetMouseResolution; + mouseAck(); + break; + case MouseGetStatus: + DPRINTF(I8042, "Getting mouse status.\n"); + mouseAck(); + writeMouseData((uint8_t *)&(mouseStatus), 1); + writeMouseData(&mouseResolution, sizeof(mouseResolution)); + writeMouseData(&mouseSampleRate, sizeof(mouseSampleRate)); + break; + case MouseReadData: + panic("Reading mouse data unimplemented.\n"); + case MouseResetWrapMode: + panic("Resetting mouse wrap mode unimplemented.\n"); + case MouseWrapMode: + panic("Setting mouse wrap mode unimplemented.\n"); + case MouseRemoteMode: + panic("Setting mouse remote mode unimplemented.\n"); + case ReadMouseID: + DPRINTF(I8042, "Mouse ID requested.\n"); + mouseAck(); + writeMouseData(MouseID, sizeof(MouseID)); + break; + case MouseSampleRate: + DPRINTF(I8042, "Setting mouse sample rate.\n"); + lastMouseCommand = MouseSampleRate; + mouseAck(); + break; + case MouseDisableReporting: + DPRINTF(I8042, "Disabling data reporting.\n"); + mouseStatus.enabled = 0; + mouseAck(); + break; + case MouseEnableReporting: + DPRINTF(I8042, "Enabling data reporting.\n"); + mouseStatus.enabled = 1; + mouseAck(); + break; + case DefaultsAndDisableMouse: + DPRINTF(I8042, "Disabling and resetting mouse.\n"); + mouseSampleRate = 100; + mouseResolution = 4; + mouseStatus.twoToOne = 0; + mouseStatus.enabled = 0; + mouseAck(); + break; + case Resend: + panic("Keyboard resent unimplemented.\n"); + case MouseReset: + DPRINTF(I8042, "Resetting the mouse.\n"); + mouseSampleRate = 100; + mouseResolution = 4; + mouseStatus.twoToOne = 0; + mouseStatus.enabled = 0; + mouseAck(); + writeMouseData(&BatSuccessful, sizeof(BatSuccessful)); + writeMouseData(MouseID, sizeof(MouseID)); + break; + default: + warn("Unknown mouse command %#02x.\n", data); + mouseNack(); + break; + } + break; + case WriteCommandByte: + commandByte = data; + DPRINTF(I8042, "Got data %#02x for \"Write " + "command byte\" command.\n", data); + statusReg.passedSelfTest = (uint8_t)commandByte.passedSelfTest; + break; + case WriteMouseOutputBuff: + DPRINTF(I8042, "Got data %#02x for \"Write " + "mouse output buffer\" command.\n", data); + writeMouseData(&data, sizeof(data)); + break; + default: + panic("Data written for unrecognized " + "command %#02x\n", lastCommand); + } + lastCommand = NoCommand; + } else if (addr == commandPort) { + DPRINTF(I8042, "Got command %#02x.\n", data); + statusReg.commandLast = 1; + // These purposefully leave off the first byte of the controller RAM + // so it can be handled specially. + if (data > ReadControllerRamBase && + data < ReadControllerRamBase + RamSize) { + panic("Attempted to use i8042 read controller RAM command to " + "get byte %d.\n", data - ReadControllerRamBase); + } else if (data > WriteControllerRamBase && + data < WriteControllerRamBase + RamSize) { + panic("Attempted to use i8042 read controller RAM command to " + "get byte %d.\n", data - ReadControllerRamBase); + } else if (data >= PulseOutputBitBase && + data < PulseOutputBitBase + NumOutputBits) { + panic("Attempted to use i8042 pulse output bit command to " + "to pulse bit %d.\n", data - PulseOutputBitBase); + } + switch (data) { + case GetCommandByte: + DPRINTF(I8042, "Getting command byte.\n"); + writeData(commandByte); + break; + case WriteCommandByte: + DPRINTF(I8042, "Setting command byte.\n"); + lastCommand = WriteCommandByte; + break; + case CheckForPassword: + panic("i8042 \"Check for password\" command not implemented.\n"); + case LoadPassword: + panic("i8042 \"Load password\" command not implemented.\n"); + case CheckPassword: + panic("i8042 \"Check password\" command not implemented.\n"); + case DisableMouse: + DPRINTF(I8042, "Disabling mouse at controller.\n"); + commandByte.disableMouse = 1; + break; + case EnableMouse: + DPRINTF(I8042, "Enabling mouse at controller.\n"); + commandByte.disableMouse = 0; + break; + case TestMouse: + panic("i8042 \"Test mouse\" command not implemented.\n"); + case SelfTest: + panic("i8042 \"Self test\" command not implemented.\n"); + case InterfaceTest: + panic("i8042 \"Interface test\" command not implemented.\n"); + case DiagnosticDump: + panic("i8042 \"Diagnostic dump\" command not implemented.\n"); + case DisableKeyboard: + DPRINTF(I8042, "Disabling keyboard at controller.\n"); + commandByte.disableKeyboard = 1; + break; + case EnableKeyboard: + DPRINTF(I8042, "Enabling keyboard at controller.\n"); + commandByte.disableKeyboard = 0; + break; + case ReadInputPort: + panic("i8042 \"Read input port\" command not implemented.\n"); + case ContinuousPollLow: + panic("i8042 \"Continuous poll low\" command not implemented.\n"); + case ContinuousPollHigh: + panic("i8042 \"Continuous poll high\" command not implemented.\n"); + case ReadOutputPort: + panic("i8042 \"Read output port\" command not implemented.\n"); + case WriteOutputPort: + panic("i8042 \"Write output port\" command not implemented.\n"); + case WriteKeyboardOutputBuff: + panic("i8042 \"Write keyboard output buffer\" " + "command not implemented.\n"); + case WriteMouseOutputBuff: + DPRINTF(I8042, "Got command to write to mouse output buffer.\n"); + lastCommand = WriteMouseOutputBuff; + break; + case WriteToMouse: + DPRINTF(I8042, "Expecting mouse command.\n"); + lastCommand = WriteToMouse; + break; + case DisableA20: + panic("i8042 \"Disable A20\" command not implemented.\n"); + case EnableA20: + panic("i8042 \"Enable A20\" command not implemented.\n"); + case ReadTestInputs: + panic("i8042 \"Read test inputs\" command not implemented.\n"); + case SystemReset: + panic("i8042 \"System reset\" command not implemented.\n"); + default: + panic("Write to unknown i8042 " + "(keyboard controller) command port.\n"); + } + } else { + panic("Write to unrecognized port %#x.\n", addr); + } + return latency; +} + +X86ISA::I8042 * +I8042Params::create() +{ + return new X86ISA::I8042(this); +} diff --git a/src/dev/x86/i8042.hh b/src/dev/x86/i8042.hh new file mode 100644 index 000000000..7eeb5f7e0 --- /dev/null +++ b/src/dev/x86/i8042.hh @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __DEV_X86_I8042_HH__ +#define __DEV_X86_I8042_HH__ + +#include "dev/io_device.hh" +#include "dev/x86/intdev.hh" +#include "params/I8042.hh" + +#include + +namespace X86ISA +{ + +class IntPin; + +class I8042 : public BasicPioDevice +{ + protected: + BitUnion8(StatusReg) + Bitfield<7> parityError; + Bitfield<6> timeout; + Bitfield<5> mouseOutputFull; + Bitfield<4> keyboardUnlocked; + Bitfield<3> commandLast; + Bitfield<2> passedSelfTest; + Bitfield<1> inputFull; + Bitfield<0> outputFull; + EndBitUnion(StatusReg) + + BitUnion8(CommandByte) + Bitfield<6> convertScanCodes; + Bitfield<5> disableMouse; + Bitfield<4> disableKeyboard; + Bitfield<2> passedSelfTest; + Bitfield<1> mouseFullInt; + Bitfield<0> keyboardFullInt; + EndBitUnion(CommandByte) + + Tick latency; + Addr dataPort; + Addr commandPort; + + StatusReg statusReg; + CommandByte commandByte; + + uint8_t dataReg; + + static const uint16_t NoCommand = (uint16_t)(-1); + uint16_t lastCommand; + + BitUnion8(MouseStatus) + Bitfield<6> remote; + Bitfield<5> enabled; + Bitfield<4> twoToOne; + Bitfield<2> leftButton; + Bitfield<0> rightButton; + EndBitUnion(MouseStatus) + + IntSourcePin *mouseIntPin; + std::queue mouseBuffer; + uint16_t lastMouseCommand; + uint8_t mouseResolution; + uint8_t mouseSampleRate; + MouseStatus mouseStatus; + + + IntSourcePin *keyboardIntPin; + std::queue keyboardBuffer; + uint16_t lastKeyboardCommand; + + bool writeData(uint8_t newData, bool mouse = false); + void keyboardAck(); + void writeKeyboardData(const uint8_t *data, int size); + void mouseAck(); + void mouseNack(); + void writeMouseData(const uint8_t *data, int size); + uint8_t readDataOut(); + + public: + typedef I8042Params Params; + + const Params * + params() const + { + return dynamic_cast(_params); + } + + I8042(Params *p) : BasicPioDevice(p), latency(p->pio_latency), + dataPort(p->data_port), commandPort(p->command_port), + statusReg(0), commandByte(0), dataReg(0), lastCommand(NoCommand), + mouseIntPin(p->mouse_int_pin), lastMouseCommand(NoCommand), + keyboardIntPin(p->keyboard_int_pin), + lastKeyboardCommand(NoCommand) + { + statusReg.passedSelfTest = 1; + statusReg.commandLast = 1; + statusReg.keyboardUnlocked = 1; + + commandByte.convertScanCodes = 1; + commandByte.passedSelfTest = 1; + commandByte.keyboardFullInt = 1; + } + + void addressRanges(AddrRangeList &range_list); + + Tick read(PacketPtr pkt); + + Tick write(PacketPtr pkt); +}; + +}; // namespace X86ISA + +#endif //__DEV_X86_I8042_HH__ -- cgit v1.2.3 From c2c5740b98c6601385e143c88aefbd827422f717 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 31 Jan 2009 23:59:25 -0800 Subject: X86: Refactor and clean up the keyboard controller. --- src/dev/x86/i8042.cc | 513 +++++++++++++++++++++------------------------------ src/dev/x86/i8042.hh | 169 ++++++++++++++--- 2 files changed, 357 insertions(+), 325 deletions(-) (limited to 'src') diff --git a/src/dev/x86/i8042.cc b/src/dev/x86/i8042.cc index 7dff49823..78ce307ae 100644 --- a/src/dev/x86/i8042.cc +++ b/src/dev/x86/i8042.cc @@ -36,79 +36,12 @@ // The 8042 has a whopping 32 bytes of internal RAM. const uint8_t RamSize = 32; const uint8_t NumOutputBits = 14; -const uint8_t KeyboardID[] = {0xab, 0x83}; -const uint8_t MouseID[] = {0x00}; +const uint8_t X86ISA::PS2Keyboard::ID[] = {0xab, 0x83}; +const uint8_t X86ISA::PS2Mouse::ID[] = {0x00}; const uint8_t CommandAck = 0xfa; const uint8_t CommandNack = 0xfe; const uint8_t BatSuccessful = 0xaa; -enum Port64Command -{ - GetCommandByte = 0x20, - ReadControllerRamBase = 0x20, - WriteCommandByte = 0x60, - WriteControllerRamBase = 0x60, - CheckForPassword = 0xA4, - LoadPassword = 0xA5, - CheckPassword = 0xA6, - DisableMouse = 0xA7, - EnableMouse = 0xA8, - TestMouse = 0xA9, - SelfTest = 0xAA, - InterfaceTest = 0xAB, - DiagnosticDump = 0xAC, - DisableKeyboard = 0xAD, - EnableKeyboard = 0xAE, - ReadInputPort = 0xC0, - ContinuousPollLow = 0xC1, - ContinuousPollHigh = 0xC2, - ReadOutputPort = 0xD0, - WriteOutputPort = 0xD1, - WriteKeyboardOutputBuff = 0xD2, - WriteMouseOutputBuff = 0xD3, - WriteToMouse = 0xD4, - DisableA20 = 0xDD, - EnableA20 = 0xDF, - ReadTestInputs = 0xE0, - PulseOutputBitBase = 0xF0, - SystemReset = 0xFE -}; - -enum Port60Command -{ - MouseScale1to1 = 0xE6, - MouseScale2to1 = 0xE7, - SetMouseResolution = 0xE8, - MouseGetStatus = 0xE9, - MouseReadData = 0xEB, - MouseResetWrapMode = 0xEC, - LEDWrite = 0xED, - DiagnosticEcho = 0xEE, - MouseWrapMode = 0xEE, - AlternateScanCodes = 0xF0, - MouseRemoteMode = 0xF0, - ReadKeyboardID = 0xF2, - ReadMouseID = 0xF2, - TypematicInfo = 0xF3, - MouseSampleRate = 0xF3, - KeyboardEnable = 0xF4, - MouseEnableReporting = 0xF4, - KeyboardDisable = 0xF5, - MouseDisableReporting = 0xF5, - DefaultsAndDisableKeyboard = 0xF6, - DefaultsAndDisableMouse = 0xF6, - AllKeysToTypematic = 0xF7, - AllKeysToMakeRelease = 0xF8, - AllKeysToMake = 0xF9, - AllKeysToTypematicMakeRelease = 0xFA, - KeyToTypematic = 0xFB, - KeyToMakeRelease = 0xFC, - KeyToMakeOnly = 0xFD, - Resend = 0xFE, - KeyboardReset = 0xFF, - MouseReset = 0xFF -}; - void X86ISA::I8042::addressRanges(AddrRangeList &range_list) { @@ -117,80 +50,46 @@ X86ISA::I8042::addressRanges(AddrRangeList &range_list) range_list.push_back(RangeSize(commandPort, 1)); } -bool -X86ISA::I8042::writeData(uint8_t newData, bool mouse) -{ - if (!statusReg.outputFull) { - DPRINTF(I8042, "Set data %#02x.\n", newData); - dataReg = newData; - statusReg.outputFull = 1; - statusReg.mouseOutputFull = (mouse ? 1 : 0); - return true; - } else { - return false; - } -} - -void -X86ISA::I8042::keyboardAck() -{ - while (!keyboardBuffer.empty()) - keyboardBuffer.pop(); - writeKeyboardData(&CommandAck, sizeof(CommandAck)); -} - void -X86ISA::I8042::writeKeyboardData(const uint8_t *data, int size) +X86ISA::I8042::writeData(uint8_t newData, bool mouse) { - assert(data || size == 0); - while (size) { - keyboardBuffer.push(*(data++)); - size--; - } - if (writeData(keyboardBuffer.front())) { - keyboardBuffer.pop(); - if (commandByte.keyboardFullInt) { - DPRINTF(I8042, "Sending keyboard interrupt.\n"); - keyboardIntPin->raise(); - //XXX This is a hack. - keyboardIntPin->lower(); - } + DPRINTF(I8042, "Set data %#02x.\n", newData); + dataReg = newData; + statusReg.outputFull = 1; + statusReg.mouseOutputFull = (mouse ? 1 : 0); + if (!mouse && commandByte.keyboardFullInt) { + DPRINTF(I8042, "Sending keyboard interrupt.\n"); + keyboardIntPin->raise(); + //This is a hack + keyboardIntPin->lower(); + } else if (mouse && commandByte.mouseFullInt) { + DPRINTF(I8042, "Sending mouse interrupt.\n"); + mouseIntPin->raise(); + //This is a hack + mouseIntPin->lower(); } } void -X86ISA::I8042::mouseAck() +X86ISA::PS2Device::ack() { - while (!mouseBuffer.empty()) - mouseBuffer.pop(); - writeMouseData(&CommandAck, sizeof(CommandAck)); + bufferData(&CommandAck, sizeof(CommandAck)); } void -X86ISA::I8042::mouseNack() +X86ISA::PS2Device::nack() { - while (!mouseBuffer.empty()) - mouseBuffer.pop(); - writeMouseData(&CommandNack, sizeof(CommandAck)); + bufferData(&CommandNack, sizeof(CommandNack)); } void -X86ISA::I8042::writeMouseData(const uint8_t *data, int size) +X86ISA::PS2Device::bufferData(const uint8_t *data, int size) { assert(data || size == 0); while (size) { - mouseBuffer.push(*(data++)); + outBuffer.push(*(data++)); size--; } - if (writeData(mouseBuffer.front(), true)) { - mouseBuffer.pop(); - if (commandByte.mouseFullInt) { - DPRINTF(I8042, "Sending mouse interrupt.\n"); - mouseIntPin->raise(); - //XXX This is a hack - mouseIntPin->lower(); - } - } } uint8_t @@ -199,15 +98,196 @@ X86ISA::I8042::readDataOut() uint8_t data = dataReg; statusReg.outputFull = 0; statusReg.mouseOutputFull = 0; - if (!keyboardBuffer.empty()) { - writeKeyboardData(NULL, 0); - } - if (!mouseBuffer.empty()) { - writeMouseData(NULL, 0); + if (keyboard.hasData()) { + writeData(keyboard.getData(), false); + } else if (mouse.hasData()) { + writeData(mouse.getData(), true); } return data; } +bool +X86ISA::PS2Keyboard::processData(uint8_t data) +{ + if (lastCommand != NoCommand) { + switch (lastCommand) { + case LEDWrite: + DPRINTF(I8042, "Setting LEDs: " + "caps lock %s, num lock %s, scroll lock %s\n", + bits(data, 2) ? "on" : "off", + bits(data, 1) ? "on" : "off", + bits(data, 0) ? "on" : "off"); + ack(); + lastCommand = NoCommand; + break; + case TypematicInfo: + DPRINTF(I8042, "Setting typematic info to %#02x.\n", data); + ack(); + lastCommand = NoCommand; + break; + } + return hasData(); + } + switch (data) { + case LEDWrite: + DPRINTF(I8042, "Got LED write command.\n"); + ack(); + lastCommand = LEDWrite; + break; + case DiagnosticEcho: + panic("Keyboard diagnostic echo unimplemented.\n"); + case AlternateScanCodes: + panic("Accessing alternate scan codes unimplemented.\n"); + case ReadID: + DPRINTF(I8042, "Got keyboard read ID command.\n"); + ack(); + bufferData((uint8_t *)&ID, sizeof(ID)); + break; + case TypematicInfo: + DPRINTF(I8042, "Setting typematic info.\n"); + ack(); + lastCommand = TypematicInfo; + break; + case Enable: + DPRINTF(I8042, "Enabling the keyboard.\n"); + ack(); + break; + case Disable: + DPRINTF(I8042, "Disabling the keyboard.\n"); + ack(); + break; + case DefaultsAndDisable: + DPRINTF(I8042, "Disabling and resetting the keyboard.\n"); + ack(); + break; + case AllKeysToTypematic: + panic("Setting all keys to typemantic unimplemented.\n"); + case AllKeysToMakeRelease: + panic("Setting all keys to make/release unimplemented.\n"); + case AllKeysToMake: + panic("Setting all keys to make unimplemented.\n"); + case AllKeysToTypematicMakeRelease: + panic("Setting all keys to " + "typematic/make/release unimplemented.\n"); + case KeyToTypematic: + panic("Setting a key to typematic unimplemented.\n"); + case KeyToMakeRelease: + panic("Setting a key to make/release unimplemented.\n"); + case KeyToMakeOnly: + panic("Setting key to make only unimplemented.\n"); + case Resend: + panic("Keyboard resend unimplemented.\n"); + case Reset: + panic("Keyboard reset unimplemented.\n"); + default: + panic("Unknown keyboard command %#02x.\n", data); + } + return hasData(); +} + +bool +X86ISA::PS2Mouse::processData(uint8_t data) +{ + if (lastCommand != NoCommand) { + switch(lastCommand) { + case SetResolution: + DPRINTF(I8042, "Mouse resolution set to %d.\n", data); + resolution = data; + ack(); + lastCommand = NoCommand; + break; + case SampleRate: + DPRINTF(I8042, "Mouse sample rate %d samples " + "per second.\n", data); + sampleRate = data; + ack(); + lastCommand = NoCommand; + break; + default: + panic("Not expecting data for a mouse command.\n"); + } + return hasData(); + } + switch (data) { + case Scale1to1: + DPRINTF(I8042, "Setting mouse scale to 1:1.\n"); + status.twoToOne = 0; + ack(); + break; + case Scale2to1: + DPRINTF(I8042, "Setting mouse scale to 2:1.\n"); + status.twoToOne = 1; + ack(); + break; + case SetResolution: + DPRINTF(I8042, "Setting mouse resolution.\n"); + lastCommand = SetResolution; + ack(); + break; + case GetStatus: + DPRINTF(I8042, "Getting mouse status.\n"); + ack(); + bufferData((uint8_t *)&(status), 1); + bufferData(&resolution, sizeof(resolution)); + bufferData(&sampleRate, sizeof(sampleRate)); + break; + case ReadData: + panic("Reading mouse data unimplemented.\n"); + case ResetWrapMode: + panic("Resetting mouse wrap mode unimplemented.\n"); + case WrapMode: + panic("Setting mouse wrap mode unimplemented.\n"); + case RemoteMode: + panic("Setting mouse remote mode unimplemented.\n"); + case ReadID: + DPRINTF(I8042, "Mouse ID requested.\n"); + ack(); + bufferData(ID, sizeof(ID)); + break; + case SampleRate: + DPRINTF(I8042, "Setting mouse sample rate.\n"); + lastCommand = SampleRate; + ack(); + break; + case DisableReporting: + DPRINTF(I8042, "Disabling data reporting.\n"); + status.enabled = 0; + ack(); + break; + case EnableReporting: + DPRINTF(I8042, "Enabling data reporting.\n"); + status.enabled = 1; + ack(); + break; + case DefaultsAndDisable: + DPRINTF(I8042, "Disabling and resetting mouse.\n"); + sampleRate = 100; + resolution = 4; + status.twoToOne = 0; + status.enabled = 0; + ack(); + break; + case Resend: + panic("Mouse resend unimplemented.\n"); + case Reset: + DPRINTF(I8042, "Resetting the mouse.\n"); + sampleRate = 100; + resolution = 4; + status.twoToOne = 0; + status.enabled = 0; + ack(); + bufferData(&BatSuccessful, sizeof(BatSuccessful)); + bufferData(ID, sizeof(ID)); + break; + default: + warn("Unknown mouse command %#02x.\n", data); + nack(); + break; + } + return hasData(); +} + + Tick X86ISA::I8042::read(PacketPtr pkt) { @@ -236,178 +316,13 @@ X86ISA::I8042::write(PacketPtr pkt) statusReg.commandLast = 0; switch (lastCommand) { case NoCommand: - if (lastKeyboardCommand != NoCommand) { - switch (lastKeyboardCommand) { - case LEDWrite: - DPRINTF(I8042, "Setting LEDs: " - "caps lock %s, num lock %s, scroll lock %s\n", - bits(data, 2) ? "on" : "off", - bits(data, 1) ? "on" : "off", - bits(data, 0) ? "on" : "off"); - keyboardAck(); - lastKeyboardCommand = NoCommand; - break; - case TypematicInfo: - DPRINTF(I8042, - "Setting typematic info to %#02x.\n", data); - keyboardAck(); - lastKeyboardCommand = NoCommand; - break; - } - break; - } - DPRINTF(I8042, "Got port 0x60 command %#02x.\n", data); - switch (data) { - case LEDWrite: - DPRINTF(I8042, "Got LED write command.\n"); - keyboardAck(); - lastKeyboardCommand = LEDWrite; - break; - case DiagnosticEcho: - panic("Keyboard diagnostic echo unimplemented.\n"); - case AlternateScanCodes: - panic("Accessing alternate scan codes unimplemented.\n"); - case ReadKeyboardID: - DPRINTF(I8042, "Got keyboard read ID command.\n"); - keyboardAck(); - writeKeyboardData((uint8_t *)&KeyboardID, sizeof(KeyboardID)); - break; - case TypematicInfo: - DPRINTF(I8042, "Setting typematic info.\n"); - keyboardAck(); - lastKeyboardCommand = TypematicInfo; - break; - case KeyboardEnable: - DPRINTF(I8042, "Enabling the keyboard.\n"); - keyboardAck(); - break; - case KeyboardDisable: - DPRINTF(I8042, "Disabling the keyboard.\n"); - keyboardAck(); - break; - case DefaultsAndDisableKeyboard: - DPRINTF(I8042, "Disabling and resetting the keyboard.\n"); - keyboardAck(); - break; - case AllKeysToTypematic: - panic("Setting all keys to typemantic unimplemented.\n"); - case AllKeysToMakeRelease: - panic("Setting all keys to make/release unimplemented.\n"); - case AllKeysToMake: - panic("Setting all keys to make unimplemented.\n"); - case AllKeysToTypematicMakeRelease: - panic("Setting all keys to " - "typematic/make/release unimplemented.\n"); - case KeyToTypematic: - panic("Setting a key to typematic unimplemented.\n"); - case KeyToMakeRelease: - panic("Setting a key to make/release unimplemented.\n"); - case KeyToMakeOnly: - panic("Setting key to make only unimplemented.\n"); - case Resend: - panic("Keyboard resend unimplemented.\n"); - case KeyboardReset: - panic("Keyboard reset unimplemented.\n"); - default: - panic("Unknown keyboard command %#02x.\n", data); + if (keyboard.processData(data)) { + writeData(keyboard.getData(), false); } break; case WriteToMouse: - if (lastMouseCommand != NoCommand) { - switch(lastMouseCommand) { - case SetMouseResolution: - DPRINTF(I8042, "Mouse resolution set to %d.\n", data); - mouseResolution = data; - mouseAck(); - lastMouseCommand = NoCommand; - break; - case MouseSampleRate: - DPRINTF(I8042, "Mouse sample rate %d samples " - "per second.\n", data); - mouseSampleRate = data; - mouseAck(); - lastMouseCommand = NoCommand; - break; - default: - panic("Not expecting data for a mouse command.\n"); - } - break; - } - switch (data) { - case MouseScale1to1: - DPRINTF(I8042, "Setting mouse scale to 1:1.\n"); - mouseStatus.twoToOne = 0; - mouseAck(); - break; - case MouseScale2to1: - DPRINTF(I8042, "Setting mouse scale to 2:1.\n"); - mouseStatus.twoToOne = 1; - mouseAck(); - break; - case SetMouseResolution: - DPRINTF(I8042, "Setting mouse resolution.\n"); - lastMouseCommand = SetMouseResolution; - mouseAck(); - break; - case MouseGetStatus: - DPRINTF(I8042, "Getting mouse status.\n"); - mouseAck(); - writeMouseData((uint8_t *)&(mouseStatus), 1); - writeMouseData(&mouseResolution, sizeof(mouseResolution)); - writeMouseData(&mouseSampleRate, sizeof(mouseSampleRate)); - break; - case MouseReadData: - panic("Reading mouse data unimplemented.\n"); - case MouseResetWrapMode: - panic("Resetting mouse wrap mode unimplemented.\n"); - case MouseWrapMode: - panic("Setting mouse wrap mode unimplemented.\n"); - case MouseRemoteMode: - panic("Setting mouse remote mode unimplemented.\n"); - case ReadMouseID: - DPRINTF(I8042, "Mouse ID requested.\n"); - mouseAck(); - writeMouseData(MouseID, sizeof(MouseID)); - break; - case MouseSampleRate: - DPRINTF(I8042, "Setting mouse sample rate.\n"); - lastMouseCommand = MouseSampleRate; - mouseAck(); - break; - case MouseDisableReporting: - DPRINTF(I8042, "Disabling data reporting.\n"); - mouseStatus.enabled = 0; - mouseAck(); - break; - case MouseEnableReporting: - DPRINTF(I8042, "Enabling data reporting.\n"); - mouseStatus.enabled = 1; - mouseAck(); - break; - case DefaultsAndDisableMouse: - DPRINTF(I8042, "Disabling and resetting mouse.\n"); - mouseSampleRate = 100; - mouseResolution = 4; - mouseStatus.twoToOne = 0; - mouseStatus.enabled = 0; - mouseAck(); - break; - case Resend: - panic("Keyboard resent unimplemented.\n"); - case MouseReset: - DPRINTF(I8042, "Resetting the mouse.\n"); - mouseSampleRate = 100; - mouseResolution = 4; - mouseStatus.twoToOne = 0; - mouseStatus.enabled = 0; - mouseAck(); - writeMouseData(&BatSuccessful, sizeof(BatSuccessful)); - writeMouseData(MouseID, sizeof(MouseID)); - break; - default: - warn("Unknown mouse command %#02x.\n", data); - mouseNack(); - break; + if (mouse.processData(data)) { + writeData(mouse.getData(), true); } break; case WriteCommandByte: @@ -419,7 +334,7 @@ X86ISA::I8042::write(PacketPtr pkt) case WriteMouseOutputBuff: DPRINTF(I8042, "Got data %#02x for \"Write " "mouse output buffer\" command.\n", data); - writeMouseData(&data, sizeof(data)); + writeData(data, true); break; default: panic("Data written for unrecognized " diff --git a/src/dev/x86/i8042.hh b/src/dev/x86/i8042.hh index 7eeb5f7e0..8a941f9a5 100644 --- a/src/dev/x86/i8042.hh +++ b/src/dev/x86/i8042.hh @@ -42,9 +42,147 @@ namespace X86ISA class IntPin; +class PS2Device +{ + protected: + std::queue outBuffer; + + static const uint16_t NoCommand = (uint16_t)(-1); + + uint16_t lastCommand; + void bufferData(const uint8_t *data, int size); + void ack(); + void nack(); + + public: + virtual ~PS2Device() + {}; + + PS2Device() : lastCommand(NoCommand) + {} + + bool hasData() + { + return !outBuffer.empty(); + } + + uint8_t getData() + { + uint8_t data = outBuffer.front(); + outBuffer.pop(); + return data; + } + + virtual bool processData(uint8_t data) = 0; +}; + +class PS2Mouse : public PS2Device +{ + protected: + static const uint8_t ID[]; + + enum Command + { + Scale1to1 = 0xE6, + Scale2to1 = 0xE7, + SetResolution = 0xE8, + GetStatus = 0xE9, + ReadData = 0xEB, + ResetWrapMode = 0xEC, + WrapMode = 0xEE, + RemoteMode = 0xF0, + ReadID = 0xF2, + SampleRate = 0xF3, + EnableReporting = 0xF4, + DisableReporting = 0xF5, + DefaultsAndDisable = 0xF6, + Resend = 0xFE, + Reset = 0xFF + }; + + BitUnion8(Status) + Bitfield<6> remote; + Bitfield<5> enabled; + Bitfield<4> twoToOne; + Bitfield<2> leftButton; + Bitfield<0> rightButton; + EndBitUnion(Status) + + Status status; + uint8_t resolution; + uint8_t sampleRate; + public: + PS2Mouse() : PS2Device(), status(0), resolution(4), sampleRate(100) + {} + + bool processData(uint8_t data); +}; + +class PS2Keyboard : public PS2Device +{ + protected: + static const uint8_t ID[]; + + enum Command + { + LEDWrite = 0xED, + DiagnosticEcho = 0xEE, + AlternateScanCodes = 0xF0, + ReadID = 0xF2, + TypematicInfo = 0xF3, + Enable = 0xF4, + Disable = 0xF5, + DefaultsAndDisable = 0xF6, + AllKeysToTypematic = 0xF7, + AllKeysToMakeRelease = 0xF8, + AllKeysToMake = 0xF9, + AllKeysToTypematicMakeRelease = 0xFA, + KeyToTypematic = 0xFB, + KeyToMakeRelease = 0xFC, + KeyToMakeOnly = 0xFD, + Resend = 0xFE, + Reset = 0xFF + }; + + public: + bool processData(uint8_t data); +}; + class I8042 : public BasicPioDevice { protected: + enum Command + { + GetCommandByte = 0x20, + ReadControllerRamBase = 0x20, + WriteCommandByte = 0x60, + WriteControllerRamBase = 0x60, + CheckForPassword = 0xA4, + LoadPassword = 0xA5, + CheckPassword = 0xA6, + DisableMouse = 0xA7, + EnableMouse = 0xA8, + TestMouse = 0xA9, + SelfTest = 0xAA, + InterfaceTest = 0xAB, + DiagnosticDump = 0xAC, + DisableKeyboard = 0xAD, + EnableKeyboard = 0xAE, + ReadInputPort = 0xC0, + ContinuousPollLow = 0xC1, + ContinuousPollHigh = 0xC2, + ReadOutputPort = 0xD0, + WriteOutputPort = 0xD1, + WriteKeyboardOutputBuff = 0xD2, + WriteMouseOutputBuff = 0xD3, + WriteToMouse = 0xD4, + DisableA20 = 0xDD, + EnableA20 = 0xDF, + ReadTestInputs = 0xE0, + PulseOutputBitBase = 0xF0, + SystemReset = 0xFE + }; + BitUnion8(StatusReg) Bitfield<7> parityError; Bitfield<6> timeout; @@ -77,32 +215,13 @@ class I8042 : public BasicPioDevice static const uint16_t NoCommand = (uint16_t)(-1); uint16_t lastCommand; - BitUnion8(MouseStatus) - Bitfield<6> remote; - Bitfield<5> enabled; - Bitfield<4> twoToOne; - Bitfield<2> leftButton; - Bitfield<0> rightButton; - EndBitUnion(MouseStatus) - IntSourcePin *mouseIntPin; - std::queue mouseBuffer; - uint16_t lastMouseCommand; - uint8_t mouseResolution; - uint8_t mouseSampleRate; - MouseStatus mouseStatus; + IntSourcePin *keyboardIntPin; + PS2Mouse mouse; + PS2Keyboard keyboard; - IntSourcePin *keyboardIntPin; - std::queue keyboardBuffer; - uint16_t lastKeyboardCommand; - - bool writeData(uint8_t newData, bool mouse = false); - void keyboardAck(); - void writeKeyboardData(const uint8_t *data, int size); - void mouseAck(); - void mouseNack(); - void writeMouseData(const uint8_t *data, int size); + void writeData(uint8_t newData, bool mouse = false); uint8_t readDataOut(); public: @@ -117,9 +236,7 @@ class I8042 : public BasicPioDevice I8042(Params *p) : BasicPioDevice(p), latency(p->pio_latency), dataPort(p->data_port), commandPort(p->command_port), statusReg(0), commandByte(0), dataReg(0), lastCommand(NoCommand), - mouseIntPin(p->mouse_int_pin), lastMouseCommand(NoCommand), - keyboardIntPin(p->keyboard_int_pin), - lastKeyboardCommand(NoCommand) + mouseIntPin(p->mouse_int_pin), keyboardIntPin(p->keyboard_int_pin) { statusReg.passedSelfTest = 1; statusReg.commandLast = 1; -- cgit v1.2.3 From bb7ad80bbe565800b09c38bdc02c12f827ec9240 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 1 Feb 2009 00:00:03 -0800 Subject: X86: Plug in an IDE controller. --- src/dev/x86/Pc.py | 2 +- src/dev/x86/SouthBridge.py | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/dev/x86/Pc.py b/src/dev/x86/Pc.py index 7211fa3f4..6f315cbcb 100644 --- a/src/dev/x86/Pc.py +++ b/src/dev/x86/Pc.py @@ -67,7 +67,7 @@ class Pc(Platform): fake_com_4 = IsaFake(pio_addr=x86IOAddress(0x2e8), pio_size=8) # A device to catch accesses to the non-existant floppy controller. - fake_floppy = IsaFake(pio_addr=x86IOAddress(0x3f2), pio_size=4) + fake_floppy = IsaFake(pio_addr=x86IOAddress(0x3f2), pio_size=2) def attachIO(self, bus): self.south_bridge.attachIO(bus) diff --git a/src/dev/x86/SouthBridge.py b/src/dev/x86/SouthBridge.py index a3db83610..be9276145 100644 --- a/src/dev/x86/SouthBridge.py +++ b/src/dev/x86/SouthBridge.py @@ -34,6 +34,7 @@ from I82094AA import I82094AA from I8237 import I8237 from I8254 import I8254 from I8259 import I8259 +from Ide import IdeController from PcSpeaker import PcSpeaker from X86IntPin import X86IntLine from m5.SimObject import SimObject @@ -72,6 +73,21 @@ class SouthBridge(SimObject): def connectPins(self, source, sink): self.int_lines.append(X86IntLine(source=source, sink=sink)) + # IDE controller + ide = IdeController(disks=[], pci_func=0, pci_dev=4, pci_bus=0) + ide.BAR0 = 0x1f0 + ide.BAR0LegacyIO = True + ide.BAR1 = 0x3f4 + ide.BAR1Size = '3B' + ide.BAR1LegacyIO = True + ide.BAR2 = 0x170 + ide.BAR2LegacyIO = True + ide.BAR3 = 0x374 + ide.BAR3Size = '3B' + ide.BAR3LegacyIO = True + ide.BAR4 = 1 + ide.Command = 1 + def attachIO(self, bus): # Route interupt signals self.connectPins(self.pic1.output, self.io_apic.pin(0)) @@ -94,6 +110,7 @@ class SouthBridge(SimObject): # Connect to the bus self.cmos.pio = bus.port self.dma1.pio = bus.port + self.ide.pio = bus.port self.keyboard.pio = bus.port self.pic1.pio = bus.port self.pic2.pio = bus.port -- cgit v1.2.3 From 3ecc38cb8b882169fb64bf939f709326915f375e Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 1 Feb 2009 00:02:21 -0800 Subject: Devices: Add support for legacy fixed IO locations in BARs. --- src/dev/Pci.py | 6 ++++ src/dev/alpha/tsunami.cc | 14 ++++++++- src/dev/alpha/tsunami.hh | 12 +++++++- src/dev/alpha/tsunami_pchip.cc | 11 +++++++ src/dev/alpha/tsunami_pchip.hh | 2 ++ src/dev/pciconfigall.cc | 2 +- src/dev/pcidev.cc | 69 +++++++++++++++++++++++++----------------- src/dev/pcidev.hh | 3 ++ src/dev/platform.hh | 4 ++- src/dev/sparc/t1000.cc | 16 +++++++++- src/dev/sparc/t1000.hh | 12 +++++++- src/dev/x86/pc.cc | 15 +++++++-- src/dev/x86/pc.hh | 12 +++++++- 13 files changed, 141 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/dev/Pci.py b/src/dev/Pci.py index b50e1b15c..bd67d82fb 100644 --- a/src/dev/Pci.py +++ b/src/dev/Pci.py @@ -73,6 +73,12 @@ class PciDevice(DmaDevice): BAR3Size = Param.MemorySize32('0B', "Base Address Register 3 Size") BAR4Size = Param.MemorySize32('0B', "Base Address Register 4 Size") BAR5Size = Param.MemorySize32('0B', "Base Address Register 5 Size") + BAR0LegacyIO = Param.Bool(False, "Whether BAR0 is hardwired legacy IO") + BAR1LegacyIO = Param.Bool(False, "Whether BAR1 is hardwired legacy IO") + BAR2LegacyIO = Param.Bool(False, "Whether BAR2 is hardwired legacy IO") + BAR3LegacyIO = Param.Bool(False, "Whether BAR3 is hardwired legacy IO") + BAR4LegacyIO = Param.Bool(False, "Whether BAR4 is hardwired legacy IO") + BAR5LegacyIO = Param.Bool(False, "Whether BAR5 is hardwired legacy IO") CardbusCIS = Param.UInt32(0x00, "Cardbus Card Information Structure") SubsystemID = Param.UInt16(0x00, "Subsystem ID") diff --git a/src/dev/alpha/tsunami.cc b/src/dev/alpha/tsunami.cc index 7923fc3f1..b6478fe22 100644 --- a/src/dev/alpha/tsunami.cc +++ b/src/dev/alpha/tsunami.cc @@ -96,11 +96,23 @@ Tsunami::pciToDma(Addr pciAddr) const Addr -Tsunami::calcConfigAddr(int bus, int dev, int func) +Tsunami::calcPciConfigAddr(int bus, int dev, int func) { return pchip->calcConfigAddr(bus, dev, func); } +Addr +Tsunami::calcPciIOAddr(Addr addr) +{ + return pchip->calcIOAddr(addr); +} + +Addr +Tsunami::calcPciMemAddr(Addr addr) +{ + return pchip->calcMemAddr(addr); +} + void Tsunami::serialize(std::ostream &os) { diff --git a/src/dev/alpha/tsunami.hh b/src/dev/alpha/tsunami.hh index 44c5d41a4..64aafe533 100644 --- a/src/dev/alpha/tsunami.hh +++ b/src/dev/alpha/tsunami.hh @@ -116,7 +116,17 @@ class Tsunami : public Platform /** * Calculate the configuration address given a bus/dev/func. */ - virtual Addr calcConfigAddr(int bus, int dev, int func); + virtual Addr calcPciConfigAddr(int bus, int dev, int func); + + /** + * Calculate the address for an IO location on the PCI bus. + */ + virtual Addr calcPciIOAddr(Addr addr); + + /** + * Calculate the address for a memory location on the PCI bus. + */ + virtual Addr calcPciMemAddr(Addr addr); /** * Serialize this object to the given output stream. diff --git a/src/dev/alpha/tsunami_pchip.cc b/src/dev/alpha/tsunami_pchip.cc index 83bcf8e65..4df7d1150 100644 --- a/src/dev/alpha/tsunami_pchip.cc +++ b/src/dev/alpha/tsunami_pchip.cc @@ -300,6 +300,7 @@ TsunamiPChip::translatePciToDma(Addr busAddr) // if no match was found, then return the original address return busAddr; } + Addr TsunamiPChip::calcConfigAddr(int bus, int dev, int func) { @@ -310,7 +311,17 @@ TsunamiPChip::calcConfigAddr(int bus, int dev, int func) return TsunamiPciBus0Config | (func << 8) | (dev << 11); } +Addr +TsunamiPChip::calcIOAddr(Addr addr) +{ + return TSUNAMI_PCI0_IO + addr; +} +Addr +TsunamiPChip::calcMemAddr(Addr addr) +{ + return TSUNAMI_PCI0_MEMORY + addr; +} void TsunamiPChip::serialize(std::ostream &os) diff --git a/src/dev/alpha/tsunami_pchip.hh b/src/dev/alpha/tsunami_pchip.hh index 53050565f..d31a28dbe 100644 --- a/src/dev/alpha/tsunami_pchip.hh +++ b/src/dev/alpha/tsunami_pchip.hh @@ -84,6 +84,8 @@ class TsunamiPChip : public BasicPioDevice Addr translatePciToDma(Addr busAddr); Addr calcConfigAddr(int bus, int dev, int func); + Addr calcIOAddr(Addr addr); + Addr calcMemAddr(Addr addr); virtual Tick read(PacketPtr pkt); virtual Tick write(PacketPtr pkt); diff --git a/src/dev/pciconfigall.cc b/src/dev/pciconfigall.cc index faf033705..74396be5d 100644 --- a/src/dev/pciconfigall.cc +++ b/src/dev/pciconfigall.cc @@ -47,7 +47,7 @@ using namespace std; PciConfigAll::PciConfigAll(const Params *p) : PioDevice(p) { - pioAddr = p->platform->calcConfigAddr(params()->bus,0,0); + pioAddr = p->platform->calcPciConfigAddr(params()->bus,0,0); } diff --git a/src/dev/pcidev.cc b/src/dev/pcidev.cc index 56b8cd3c8..b311ed8cf 100644 --- a/src/dev/pcidev.cc +++ b/src/dev/pcidev.cc @@ -59,7 +59,7 @@ PciDev::PciConfigPort::PciConfigPort(PciDev *dev, int busid, int devid, : SimpleTimingPort(dev->name() + "-pciconf", dev), device(dev), platform(p), busId(busid), deviceId(devid), functionId(funcid) { - configAddr = platform->calcConfigAddr(busId, deviceId, functionId); + configAddr = platform->calcPciConfigAddr(busId, deviceId, functionId); } @@ -121,15 +121,26 @@ PciDev::PciDev(const Params *p) BARSize[4] = p->BAR4Size; BARSize[5] = p->BAR5Size; + legacyIO[0] = p->BAR0LegacyIO; + legacyIO[1] = p->BAR1LegacyIO; + legacyIO[2] = p->BAR2LegacyIO; + legacyIO[3] = p->BAR3LegacyIO; + legacyIO[4] = p->BAR4LegacyIO; + legacyIO[5] = p->BAR5LegacyIO; + for (int i = 0; i < 6; ++i) { - uint32_t barsize = BARSize[i]; - if (barsize != 0 && !isPowerOf2(barsize)) { - fatal("BAR %d size %d is not a power of 2\n", i, BARSize[i]); + if (legacyIO[i]) { + BARAddrs[i] = platform->calcPciIOAddr(letoh(config.baseAddr[i])); + config.baseAddr[i] = 0; + } else { + BARAddrs[i] = 0; + uint32_t barsize = BARSize[i]; + if (barsize != 0 && !isPowerOf2(barsize)) { + fatal("BAR %d size %d is not a power of 2\n", i, BARSize[i]); + } } } - memset(BARAddrs, 0, sizeof(BARAddrs)); - plat->registerPciDevice(0, p->pci_dev, p->pci_func, letoh(config.interruptLine)); } @@ -268,30 +279,32 @@ PciDev::writeConfig(PacketPtr pkt) { int barnum = BAR_NUMBER(offset); - // convert BAR values to host endianness - uint32_t he_old_bar = letoh(config.baseAddr[barnum]); - uint32_t he_new_bar = letoh(pkt->get()); - - uint32_t bar_mask = - BAR_IO_SPACE(he_old_bar) ? BAR_IO_MASK : BAR_MEM_MASK; - - // Writing 0xffffffff to a BAR tells the card to set the - // value of the bar to a bitmask indicating the size of - // memory it needs - if (he_new_bar == 0xffffffff) { - he_new_bar = ~(BARSize[barnum] - 1); - } else { - // does it mean something special to write 0 to a BAR? - he_new_bar &= ~bar_mask; - if (he_new_bar) { - Addr space_base = BAR_IO_SPACE(he_old_bar) ? - TSUNAMI_PCI0_IO : TSUNAMI_PCI0_MEMORY; - BARAddrs[barnum] = he_new_bar + space_base; - pioPort->sendStatusChange(Port::RangeChange); + if (!legacyIO[barnum]) { + // convert BAR values to host endianness + uint32_t he_old_bar = letoh(config.baseAddr[barnum]); + uint32_t he_new_bar = letoh(pkt->get()); + + uint32_t bar_mask = + BAR_IO_SPACE(he_old_bar) ? BAR_IO_MASK : BAR_MEM_MASK; + + // Writing 0xffffffff to a BAR tells the card to set the + // value of the bar to a bitmask indicating the size of + // memory it needs + if (he_new_bar == 0xffffffff) { + he_new_bar = ~(BARSize[barnum] - 1); + } else { + // does it mean something special to write 0 to a BAR? + he_new_bar &= ~bar_mask; + if (he_new_bar) { + BARAddrs[barnum] = BAR_IO_SPACE(he_old_bar) ? + platform->calcPciIOAddr(he_new_bar) : + platform->calcPciMemAddr(he_new_bar); + pioPort->sendStatusChange(Port::RangeChange); + } } + config.baseAddr[barnum] = htole((he_new_bar & ~bar_mask) | + (he_old_bar & bar_mask)); } - config.baseAddr[barnum] = htole((he_new_bar & ~bar_mask) | - (he_old_bar & bar_mask)); } break; diff --git a/src/dev/pcidev.hh b/src/dev/pcidev.hh index a584a957d..5da8b2dfc 100644 --- a/src/dev/pcidev.hh +++ b/src/dev/pcidev.hh @@ -99,6 +99,9 @@ class PciDev : public DmaDevice /** The current address mapping of the BARs */ Addr BARAddrs[6]; + /** Whether the BARs are really hardwired legacy IO locations. */ + bool legacyIO[6]; + /** * Does the given address lie within the space mapped by the given * base address register? diff --git a/src/dev/platform.hh b/src/dev/platform.hh index fc556787d..5f6f1df81 100644 --- a/src/dev/platform.hh +++ b/src/dev/platform.hh @@ -69,7 +69,9 @@ class Platform : public SimObject virtual void postPciInt(int line); virtual void clearPciInt(int line); virtual Addr pciToDma(Addr pciAddr) const; - virtual Addr calcConfigAddr(int bus, int dev, int func) = 0; + virtual Addr calcPciConfigAddr(int bus, int dev, int func) = 0; + virtual Addr calcPciIOAddr(Addr addr) = 0; + virtual Addr calcPciMemAddr(Addr addr) = 0; virtual void registerPciDevice(uint8_t bus, uint8_t dev, uint8_t func, uint8_t intr); diff --git a/src/dev/sparc/t1000.cc b/src/dev/sparc/t1000.cc index d42b442a1..88fb358ef 100644 --- a/src/dev/sparc/t1000.cc +++ b/src/dev/sparc/t1000.cc @@ -94,7 +94,21 @@ T1000::pciToDma(Addr pciAddr) const Addr -T1000::calcConfigAddr(int bus, int dev, int func) +T1000::calcPciConfigAddr(int bus, int dev, int func) +{ + panic("Need implementation\n"); + M5_DUMMY_RETURN +} + +Addr +T1000::calcPciIOAddr(Addr addr) +{ + panic("Need implementation\n"); + M5_DUMMY_RETURN +} + +Addr +T1000::calcPciMemAddr(Addr addr) { panic("Need implementation\n"); M5_DUMMY_RETURN diff --git a/src/dev/sparc/t1000.hh b/src/dev/sparc/t1000.hh index 76de0a550..01ff3d319 100644 --- a/src/dev/sparc/t1000.hh +++ b/src/dev/sparc/t1000.hh @@ -91,7 +91,17 @@ class T1000 : public Platform /** * Calculate the configuration address given a bus/dev/func. */ - virtual Addr calcConfigAddr(int bus, int dev, int func); + virtual Addr calcPciConfigAddr(int bus, int dev, int func); + + /** + * Calculate the address for an IO location on the PCI bus. + */ + virtual Addr calcPciIOAddr(Addr addr); + + /** + * Calculate the address for a memory location on the PCI bus. + */ + virtual Addr calcPciMemAddr(Addr addr); }; #endif // __DEV_T1000_HH__ diff --git a/src/dev/x86/pc.cc b/src/dev/x86/pc.cc index 2deed95d3..3dfa50d7f 100644 --- a/src/dev/x86/pc.cc +++ b/src/dev/x86/pc.cc @@ -143,9 +143,8 @@ Pc::pciToDma(Addr pciAddr) const M5_DUMMY_RETURN } - Addr -Pc::calcConfigAddr(int bus, int dev, int func) +Pc::calcPciConfigAddr(int bus, int dev, int func) { assert(func < 8); assert(dev < 32); @@ -153,6 +152,18 @@ Pc::calcConfigAddr(int bus, int dev, int func) return (PhysAddrPrefixPciConfig | (func << 8) | (dev << 11)); } +Addr +Pc::calcPciIOAddr(Addr addr) +{ + return PhysAddrPrefixIO + addr; +} + +Addr +Pc::calcPciMemAddr(Addr addr) +{ + return addr; +} + Pc * PcParams::create() { diff --git a/src/dev/x86/pc.hh b/src/dev/x86/pc.hh index 21055a566..427cc4165 100644 --- a/src/dev/x86/pc.hh +++ b/src/dev/x86/pc.hh @@ -93,7 +93,17 @@ class Pc : public Platform /** * Calculate the configuration address given a bus/dev/func. */ - virtual Addr calcConfigAddr(int bus, int dev, int func); + virtual Addr calcPciConfigAddr(int bus, int dev, int func); + + /** + * Calculate the address for an IO location on the PCI bus. + */ + virtual Addr calcPciIOAddr(Addr addr); + + /** + * Calculate the address for a memory location on the PCI bus. + */ + virtual Addr calcPciMemAddr(Addr addr); }; #endif // __DEV_PC_HH__ -- cgit v1.2.3 From 77209689499f2c843bebd9fca300fdd421277b15 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 1 Feb 2009 00:04:34 -0800 Subject: X86: Make sure the predecoder is cleared out for interrupts. --- src/cpu/simple/base.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index 89d9ce383..9af5d0150 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -321,6 +321,7 @@ BaseSimpleCPU::checkForInterrupts() Fault interrupt = interrupts->getInterrupt(tc); if (interrupt != NoFault) { + predecoder.reset(); interrupts->updateIntrInfo(tc); interrupt->invoke(tc); } -- cgit v1.2.3 From 483c3e96b7e30d3bd788f32c5b421133e71ec476 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 1 Feb 2009 00:08:16 -0800 Subject: X86: Calculate flags based on the actual result. --- src/arch/x86/insts/microregop.cc | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/arch/x86/insts/microregop.cc b/src/arch/x86/insts/microregop.cc index 080926627..2ea975746 100644 --- a/src/arch/x86/insts/microregop.cc +++ b/src/arch/x86/insts/microregop.cc @@ -67,6 +67,9 @@ namespace X86ISA bool subtract) const { DPRINTF(X86, "flagMask = %#x\n", flagMask); + if (_destRegIdx[0] & (1 << 6)) { + _dest >>= 8; + } uint64_t flags = oldFlags & ~flagMask; if(flagMask & (ECFBit | CFBit)) { -- cgit v1.2.3 From 06cdbe5ea7138d0f340448438d64e98c72936e1b Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 1 Feb 2009 00:11:49 -0800 Subject: X86: Compute PCI config addresses correctly. --- src/arch/x86/tlb.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index 6f1c1a03c..1009386d7 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -547,7 +547,8 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) tc->readMiscRegNoEffect(MISCREG_PCI_CONFIG_ADDRESS); if (bits(configAddress, 31, 31)) { req->setPaddr(PhysAddrPrefixPciConfig | - bits(configAddress, 30, 0)); + mbits(configAddress, 30, 2) | + (IOPort & mask(2))); } } else { req->setPaddr(PhysAddrPrefixIO | IOPort); -- cgit v1.2.3 From f3b8371dfcad39c609e4bf5ecf50c17e57fca805 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 1 Feb 2009 00:15:38 -0800 Subject: X86: Add extended Intel MP entries correctly. --- src/arch/x86/bios/IntelMP.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/bios/IntelMP.py b/src/arch/x86/bios/IntelMP.py index 1b9e819b3..04e79b6ac 100644 --- a/src/arch/x86/bios/IntelMP.py +++ b/src/arch/x86/bios/IntelMP.py @@ -90,7 +90,7 @@ class X86IntelMPConfigTable(SimObject): if isinstance(entry, X86IntelMPBaseConfigEntry): self.base_entries.append(entry) elif isinstance(entry, X86IntelMPExtConfigEntry): - self.base_entries.append(entry) + self.ext_entries.append(entry) else: panic("Don't know what type of Intel MP entry %s is." \ % entry.__class__.__name__) -- cgit v1.2.3 From d432bd13b2f4796a4a9a97831c521ab66aadc414 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 1 Feb 2009 00:18:13 -0800 Subject: X86: Fix some incorrect register widths. --- src/arch/x86/isa/operands.isa | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa index a409d1f0f..d46741f00 100644 --- a/src/arch/x86/isa/operands.isa +++ b/src/arch/x86/isa/operands.isa @@ -159,7 +159,7 @@ def operands {{ 'CSAttr': ('ControlReg', 'udw', 'MISCREG_CS_ATTR', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 208), 'MiscRegDest': ('ControlReg', 'uqw', 'dest', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 209), 'MiscRegSrc1': ('ControlReg', 'uqw', 'src1', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 210), - 'TscOp': ('ControlReg', 'udw', 'MISCREG_TSC', (None, None, ['IsSerializeAfter', 'IsSerializing', 'IsNonSpeculative']), 211), - 'M5Reg': ('ControlReg', 'udw', 'MISCREG_M5_REG', (None, None, None), 212), + 'TscOp': ('ControlReg', 'uqw', 'MISCREG_TSC', (None, None, ['IsSerializeAfter', 'IsSerializing', 'IsNonSpeculative']), 211), + 'M5Reg': ('ControlReg', 'uqw', 'MISCREG_M5_REG', (None, None, None), 212), 'Mem': ('Mem', 'uqw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 300) }}; -- cgit v1.2.3 From f1b43b39a764645c8e15b66a1a01d404f03c8307 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 1 Feb 2009 00:25:15 -0800 Subject: X86: Hook up the IDE controller interrupt line. --- src/dev/x86/SouthBridge.py | 1 + src/dev/x86/pc.cc | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/dev/x86/SouthBridge.py b/src/dev/x86/SouthBridge.py index be9276145..8d766471e 100644 --- a/src/dev/x86/SouthBridge.py +++ b/src/dev/x86/SouthBridge.py @@ -87,6 +87,7 @@ class SouthBridge(SimObject): ide.BAR3LegacyIO = True ide.BAR4 = 1 ide.Command = 1 + ide.InterruptLine = 20 def attachIO(self, bus): # Route interupt signals diff --git a/src/dev/x86/pc.cc b/src/dev/x86/pc.cc index 3dfa50d7f..5005bd296 100644 --- a/src/dev/x86/pc.cc +++ b/src/dev/x86/pc.cc @@ -127,13 +127,13 @@ Pc::clearConsoleInt() void Pc::postPciInt(int line) { - panic("Need implementation\n"); + southBridge->ioApic->signalInterrupt(line); } void Pc::clearPciInt(int line) { - panic("Need implementation\n"); + warn_once("Tried to clear PCI interrupt %d\n", line); } Addr -- cgit v1.2.3 From 70cd5bfce5549495c6e969fa509bfd5f56190e10 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 1 Feb 2009 00:26:10 -0800 Subject: X86: Configure the first PCI interrupt. --- src/dev/x86/SouthBridge.py | 3 ++- src/dev/x86/pc.cc | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/dev/x86/SouthBridge.py b/src/dev/x86/SouthBridge.py index 8d766471e..d89ed9dc6 100644 --- a/src/dev/x86/SouthBridge.py +++ b/src/dev/x86/SouthBridge.py @@ -87,7 +87,8 @@ class SouthBridge(SimObject): ide.BAR3LegacyIO = True ide.BAR4 = 1 ide.Command = 1 - ide.InterruptLine = 20 + ide.InterruptLine = 14 + ide.InterruptPin = 1 def attachIO(self, bus): # Route interupt signals diff --git a/src/dev/x86/pc.cc b/src/dev/x86/pc.cc index 5005bd296..d23474c67 100644 --- a/src/dev/x86/pc.cc +++ b/src/dev/x86/pc.cc @@ -101,6 +101,12 @@ Pc::init() entry.vector = 0x2C; ioApic.writeReg(0x28, entry.bottomDW); ioApic.writeReg(0x29, entry.topDW); + entry.vector = 0x2E; + ioApic.writeReg(0x2C, entry.bottomDW); + ioApic.writeReg(0x2D, entry.topDW); + entry.vector = 0x30; + ioApic.writeReg(0x30, entry.bottomDW); + ioApic.writeReg(0x31, entry.topDW); } Tick -- cgit v1.2.3 From 57be1dfe48a25db872627b61d4c64b560ccc640b Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 1 Feb 2009 00:27:15 -0800 Subject: X86: Implement pciToDma. --- src/dev/x86/pc.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/dev/x86/pc.cc b/src/dev/x86/pc.cc index d23474c67..d1ab4af7f 100644 --- a/src/dev/x86/pc.cc +++ b/src/dev/x86/pc.cc @@ -112,7 +112,7 @@ Pc::init() Tick Pc::intrFrequency() { - panic("Need implementation\n"); + panic("Need implementation for intrFrequency\n"); M5_DUMMY_RETURN } @@ -145,8 +145,7 @@ Pc::clearPciInt(int line) Addr Pc::pciToDma(Addr pciAddr) const { - panic("Need implementation\n"); - M5_DUMMY_RETURN + return pciAddr; } Addr -- cgit v1.2.3 From ca6e0d75c8343e707f5632e12af8e797160d3e6c Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 1 Feb 2009 00:28:28 -0800 Subject: X86: Fix the microcode for the LODS instruction. --- src/arch/x86/isa/insts/general_purpose/string/load_string.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/string/load_string.py b/src/arch/x86/isa/insts/general_purpose/string/load_string.py index 8d144dc4d..14198701a 100644 --- a/src/arch/x86/isa/insts/general_purpose/string/load_string.py +++ b/src/arch/x86/isa/insts/general_purpose/string/load_string.py @@ -61,9 +61,9 @@ def macroop LODS_M { subi t4, t0, dsz, dataSize=asz mov t3, t3, t4, flags=(nCEZF,), dataSize=asz - ld rax, seg, [1, t0, rdi] + ld rax, seg, [1, t0, rsi] - add rdi, rdi, t3, dataSize=asz + add rsi, rsi, t3, dataSize=asz }; def macroop LODS_E_M { @@ -76,10 +76,10 @@ def macroop LODS_E_M { mov t3, t3, t4, flags=(nCEZF,), dataSize=asz topOfLoop: - ld rax, seg, [1, t0, rdi] + ld rax, seg, [1, t0, rsi] subi rcx, rcx, 1, flags=(EZF,), dataSize=asz - add rdi, rdi, t3, dataSize=asz + add rsi, rsi, t3, dataSize=asz br label("topOfLoop"), flags=(nCEZF,) end: fault "NoFault" -- cgit v1.2.3 From 6b60a2970637129a39f04724ff082b2b0ffc1eb1 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 1 Feb 2009 00:30:11 -0800 Subject: X86: Fix the time keeping of the Local APIC timer. --- src/arch/x86/interrupts.cc | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc index 4f7753703..29157b3f5 100644 --- a/src/arch/x86/interrupts.cc +++ b/src/arch/x86/interrupts.cc @@ -344,10 +344,19 @@ X86ISA::Interrupts::readReg(ApicRegIndex reg) break; case APIC_CURRENT_COUNT: { - assert(clock); - uint32_t val = regs[reg] - curTick / clock; - val /= (16 * divideFromConf(regs[APIC_DIVIDE_CONFIGURATION])); - return val; + if (apicTimerEvent.scheduled()) { + assert(clock); + // Compute how many m5 ticks happen per count. + uint64_t ticksPerCount = clock * + divideFromConf(regs[APIC_DIVIDE_CONFIGURATION]); + // Compute how many m5 ticks are left. + uint64_t val = apicTimerEvent.when() - curTick; + // Turn that into a count. + val = (val + ticksPerCount - 1) / ticksPerCount; + return val; + } else { + return 0; + } } default: break; @@ -441,19 +450,17 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val) { assert(clock); newVal = bits(val, 31, 0); - uint32_t newCount = newVal * - (divideFromConf(regs[APIC_DIVIDE_CONFIGURATION]) * 16); - regs[APIC_CURRENT_COUNT] = newCount + curTick / clock; - // Find out how long a "tick" of the timer should take. - Tick timerTick = 16 * clock; + // Compute how many timer ticks we're being programmed for. + uint64_t newCount = newVal * + (divideFromConf(regs[APIC_DIVIDE_CONFIGURATION])); // Schedule on the edge of the next tick plus the new count. - Tick offset = curTick % timerTick; + Tick offset = curTick % clock; if (offset) { reschedule(apicTimerEvent, - curTick + (newCount + 1) * timerTick - offset, true); + curTick + (newCount + 1) * clock - offset, true); } else { reschedule(apicTimerEvent, - curTick + newCount * timerTick, true); + curTick + newCount * clock, true); } } break; -- cgit v1.2.3 From 7b585114704532133c3aed01847fa534167018b3 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 1 Feb 2009 00:30:54 -0800 Subject: CPU: Don't always reset the micro pc on faults. Let the faults handle it. --- src/cpu/simple/base.cc | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index 9af5d0150..b1a77247f 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -472,8 +472,6 @@ BaseSimpleCPU::advancePC(Fault fault) if (fault != NoFault) { curMacroStaticInst = StaticInst::nullStaticInstPtr; predecoder.reset(); - thread->setMicroPC(normalMicroPC(0)); - thread->setNextMicroPC(normalMicroPC(1)); fault->invoke(tc); } else { //If we're at the last micro op for this instruction -- cgit v1.2.3 From 03a00735c2d15e393f328cb05c6e560a85923225 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 1 Feb 2009 17:03:11 -0800 Subject: X86: Keep track of the vector for all exceptions/faults. --- src/arch/x86/faults.hh | 67 +++++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/arch/x86/faults.hh b/src/arch/x86/faults.hh index 3bcacffe2..dc86d2cec 100644 --- a/src/arch/x86/faults.hh +++ b/src/arch/x86/faults.hh @@ -69,11 +69,13 @@ namespace X86ISA protected: const char * faultName; const char * mnem; + uint8_t vector; uint64_t errorCode; X86FaultBase(const char * _faultName, const char * _mnem, - uint64_t _errorCode = 0) : - faultName(_faultName), mnem(_mnem), errorCode(_errorCode) + const uint8_t _vector, uint64_t _errorCode = 0) : + faultName(_faultName), mnem(_mnem), + vector(_vector), errorCode(_errorCode) { } @@ -105,8 +107,8 @@ namespace X86ISA { protected: X86Fault(const char * name, const char * mnem, - uint64_t _errorCode = 0) : - X86FaultBase(name, mnem, _errorCode) + const uint8_t vector, uint64_t _errorCode = 0) : + X86FaultBase(name, mnem, vector, _errorCode) {} }; @@ -116,8 +118,8 @@ namespace X86ISA { protected: X86Trap(const char * name, const char * mnem, - uint64_t _errorCode = 0) : - X86FaultBase(name, mnem, _errorCode) + const uint8_t vector, uint64_t _errorCode = 0) : + X86FaultBase(name, mnem, vector, _errorCode) {} #if FULL_SYSTEM @@ -130,8 +132,8 @@ namespace X86ISA { protected: X86Abort(const char * name, const char * mnem, - uint64_t _errorCode = 0) : - X86FaultBase(name, mnem, _errorCode) + const uint8_t vector, uint64_t _errorCode = 0) : + X86FaultBase(name, mnem, vector, _errorCode) {} #if FULL_SYSTEM @@ -143,10 +145,9 @@ namespace X86ISA class X86Interrupt : public X86FaultBase { protected: - uint8_t vector; - X86Interrupt(const char * name, const char * mnem, uint8_t _vector, - uint64_t _errorCode = 0) : - X86FaultBase(name, mnem, _errorCode), vector(_vector) + X86Interrupt(const char * name, const char * mnem, + const uint8_t _vector, uint64_t _errorCode = 0) : + X86FaultBase(name, mnem, _vector, _errorCode) {} #if FULL_SYSTEM @@ -208,7 +209,7 @@ namespace X86ISA { public: DivideByZero() : - X86Fault("Divide-by-Zero-Error", "#DE") + X86Fault("Divide-by-Zero-Error", "#DE", 0) {} }; @@ -216,7 +217,7 @@ namespace X86ISA { public: DebugException() : - X86FaultBase("Debug", "#DB") + X86FaultBase("Debug", "#DB", 1) {} }; @@ -224,7 +225,7 @@ namespace X86ISA { public: NonMaskableInterrupt(uint8_t _vector) : - X86Interrupt("Non Maskable Interrupt", "#NMI", _vector) + X86Interrupt("Non Maskable Interrupt", "#NMI", 2, _vector) {} }; @@ -232,7 +233,7 @@ namespace X86ISA { public: Breakpoint() : - X86Trap("Breakpoint", "#BP") + X86Trap("Breakpoint", "#BP", 3) {} }; @@ -240,7 +241,7 @@ namespace X86ISA { public: OverflowTrap() : - X86Trap("Overflow", "#OF") + X86Trap("Overflow", "#OF", 4) {} }; @@ -248,7 +249,7 @@ namespace X86ISA { public: BoundRange() : - X86Fault("Bound-Range", "#BR") + X86Fault("Bound-Range", "#BR", 5) {} }; @@ -256,7 +257,7 @@ namespace X86ISA { public: InvalidOpcode() : - X86Fault("Invalid-Opcode", "#UD") + X86Fault("Invalid-Opcode", "#UD", 6) {} }; @@ -264,7 +265,7 @@ namespace X86ISA { public: DeviceNotAvailable() : - X86Fault("Device-Not-Available", "#NM") + X86Fault("Device-Not-Available", "#NM", 7) {} }; @@ -272,7 +273,7 @@ namespace X86ISA { public: DoubleFault() : - X86Abort("Double-Fault", "#DF") + X86Abort("Double-Fault", "#DF", 8) {} }; @@ -280,7 +281,7 @@ namespace X86ISA { public: InvalidTSS() : - X86Fault("Invalid-TSS", "#TS") + X86Fault("Invalid-TSS", "#TS", 10) {} }; @@ -288,7 +289,7 @@ namespace X86ISA { public: SegmentNotPresent() : - X86Fault("Segment-Not-Present", "#NP") + X86Fault("Segment-Not-Present", "#NP", 11) {} }; @@ -296,7 +297,7 @@ namespace X86ISA { public: StackFault() : - X86Fault("Stack", "#SS") + X86Fault("Stack", "#SS", 12) {} }; @@ -304,7 +305,7 @@ namespace X86ISA { public: GeneralProtection(uint64_t _errorCode) : - X86Fault("General-Protection", "#GP", _errorCode) + X86Fault("General-Protection", "#GP", 13, _errorCode) {} }; @@ -312,7 +313,7 @@ namespace X86ISA { public: PageFault() : - X86Fault("Page-Fault", "#PF") + X86Fault("Page-Fault", "#PF", 14) {} }; @@ -320,7 +321,7 @@ namespace X86ISA { public: X87FpExceptionPending() : - X86Fault("x87 Floating-Point Exception Pending", "#MF") + X86Fault("x87 Floating-Point Exception Pending", "#MF", 16) {} }; @@ -328,7 +329,7 @@ namespace X86ISA { public: AlignmentCheck() : - X86Fault("Alignment-Check", "#AC") + X86Fault("Alignment-Check", "#AC", 17) {} }; @@ -336,7 +337,7 @@ namespace X86ISA { public: MachineCheck() : - X86Abort("Machine-Check", "#MC") + X86Abort("Machine-Check", "#MC", 18) {} }; @@ -344,7 +345,7 @@ namespace X86ISA { public: SIMDFloatingPointFault() : - X86Fault("SIMD Floating-Point", "#XF") + X86Fault("SIMD Floating-Point", "#XF", 19) {} }; @@ -352,7 +353,7 @@ namespace X86ISA { public: SecurityException() : - X86FaultBase("Security Exception", "#SX") + X86FaultBase("Security Exception", "#SX", 30) {} }; @@ -397,7 +398,7 @@ namespace X86ISA Addr vaddr; public: FakeITLBFault(Addr _vaddr) : - X86Fault("fake instruction tlb fault", "itlb"), + X86Fault("fake instruction tlb fault", "itlb", 0), vaddr(_vaddr) {} @@ -410,7 +411,7 @@ namespace X86ISA Addr vaddr; public: FakeDTLBFault(Addr _vaddr) : - X86Fault("fake data tlb fault", "dtlb"), + X86Fault("fake data tlb fault", "dtlb", 0), vaddr(_vaddr) {} -- cgit v1.2.3 From c0cd58812e23ff540c0ef80203f1baad16a9eda1 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 1 Feb 2009 17:04:21 -0800 Subject: X86: Touch up the interrupt entering microcode. --- src/arch/x86/isa/insts/romutil.py | 67 ++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/romutil.py b/src/arch/x86/isa/insts/romutil.py index 9645ee85d..2724637d1 100644 --- a/src/arch/x86/isa/insts/romutil.py +++ b/src/arch/x86/isa/insts/romutil.py @@ -59,25 +59,20 @@ def rom # Get the target CS descriptor using the selector in the gate # descriptor. # - srli t4, t1, 16, dataSize=8 - andi t5, t4, 0xF8, dataSize=8 - andi t0, t4, 0x4, flags=(EZF,), dataSize=2 + srli t10, t4, 16, dataSize=8 + andi t5, t10, 0xF8, dataSize=8 + andi t0, t10, 0x4, flags=(EZF,), dataSize=2 br rom_local_label("globalDescriptor"), flags=(CEZF,) ld t3, tsl, [1, t0, t5], dataSize=8, addressSize=8 br rom_local_label("processDescriptor") globalDescriptor: ld t3, tsg, [1, t0, t5], dataSize=8, addressSize=8 processDescriptor: - chks t4, t3, IntCSCheck, dataSize=8 - wrdl hs, t3, t4, dataSize=8 - - # Check that the target offset is in canonical form - wrdh t4, t1, t2, dataSize=8 - srli t4, t4, 47, dataSize=8 - addi t4, t4, 1, dataSize=8 - srli t4, t4, 1, dataSize=8 - or t4, t4, t4, flags=(EZF,), dataSize=2 - fault "new GeneralProtection(0)", flags=(nCEZF,) + chks t10, t3, IntCSCheck, dataSize=8 + wrdl hs, t3, t10, dataSize=8 + + # Stick the target offset in t9. + wrdh t9, t4, t2, dataSize=8 # @@ -85,27 +80,25 @@ processDescriptor: # # Record what we might set the stack selector to. - rdsel t6, ss - wrsel hs, t6 + rdsel t11, ss # Check if we're changing privelege level. At this point we can assume # we're going to a DPL that's less than or equal to the CPL. - rdattr t4, hs, dataSize=8 - srli t4, t4, 3, dataSize=8 - andi t4, t4, 3, dataSize=8 + rdattr t10, hs, dataSize=8 + srli t10, t10, 3, dataSize=8 + andi t10, t10, 3, dataSize=8 rdattr t5, cs, dataSize=8 srli t5, t5, 3, dataSize=8 - sub t5, t5, t4, dataSize=8 + sub t5, t5, t10, dataSize=8 andi t0, t5, 0x3, flags=(EZF,), dataSize=8 # We're going to change priviledge, so zero out the stack selector. We # need to let the IST have priority so we don't branch yet. - limm t4, 0 - wrsel hs, t4, flags=(nCEZF,) + wrsel t11, t0, flags=(nCEZF,) # Check the IST field of the gate descriptor - srli t4, t1, 32, dataSize=8 - andi t4, t4, 0x7, dataSize=8 - subi t0, t4, 1, flags=(ECF,), dataSize=8 + srli t10, t4, 32, dataSize=8 + andi t10, t10, 0x7, dataSize=8 + subi t0, t10, 1, flags=(ECF,), dataSize=8 br rom_local_label("istStackSwitch"), flags=(nCECF,) br rom_local_label("cplStackSwitch"), flags=(nCEZF,) @@ -134,42 +127,42 @@ stackSwitched: ## ## Point of no return. ## We're now going to irrevocably modify visible state. - ## Anything bad that's going to happen should have happened by now. + ## Anything bad that's going to happen should have happened by now or will + ## happen right now. ## + wrip t0, t9, dataSize=8 # # Build up the interrupt stack frame # + # Write out the contents of memory st t7, hs, [1, t0, t6], dataSize=8 limm t5, 0, dataSize=8 rdsel t5, cs, dataSize=2 st t5, hs, [1, t0, t6], 8, dataSize=8 - rflags t4, dataSize=8 - st t4, hs, [1, t0, t6], 16, dataSize=8 + rflags t10, dataSize=8 + st t10, hs, [1, t0, t6], 16, dataSize=8 st rsp, hs, [1, t0, t6], 24, dataSize=8 rdsel t5, ss, dataSize=2 st t5, hs, [1, t0, t6], 32, dataSize=8 # Set the stack segment mov rsp, rsp, t6, dataSize=8 - rdsel t7, hs, dataSize=2 - wrsel ss, t7, dataSize=2 + wrsel ss, t11, dataSize=2 # # Set up the target code segment # - srli t5, t1, 16, dataSize=8 + srli t5, t4, 16, dataSize=8 andi t5, t5, 0xFF, dataSize=8 wrdl cs, t3, t5, dataSize=8 wrsel cs, t5, dataSize=2 - wrdh t7, t1, t2, dataSize=8 - wrip t0, t7, dataSize=8 # - # Adjust rflags which is still in t4 from above + # Adjust rflags which is still in t10 from above # # Set IF to the lowest bit of the original gate type. @@ -177,16 +170,16 @@ stackSwitched: # Set the TF, NT, and RF bits. We'll flip them at the end. limm t6, (1 << 8) | (1 << 14) | (1 << 16) - or t4, t4, t6 - srli t5, t1, 40, dataSize=8 - srli t7, t4, 9, dataSize=8 + or t10, t10, t6 + srli t5, t4, 40, dataSize=8 + srli t7, t10, 9, dataSize=8 xor t5, t7, t5, dataSize=8 andi t5, t5, 1, dataSize=8 slli t5, t5, 9, dataSize=8 or t6, t5, t6, dataSize=8 # Put the results into rflags - wrflags t6, t4 + wrflags t6, t10 eret }; -- cgit v1.2.3 From 6b53b8387e1a0c05d878d47962c27bf7493b6d36 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 1 Feb 2009 17:05:37 -0800 Subject: X86: Make the chks microop check for the right int descriptor type. --- src/arch/x86/isa/insts/romutil.py | 11 +---------- src/arch/x86/isa/microops/regop.isa | 6 ++++++ 2 files changed, 7 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/romutil.py b/src/arch/x86/isa/insts/romutil.py index 2724637d1..9b4a80d44 100644 --- a/src/arch/x86/isa/insts/romutil.py +++ b/src/arch/x86/isa/insts/romutil.py @@ -43,18 +43,9 @@ def rom ld t2, idtr, [1, t0, t4], 8, dataSize=8, addressSize=8 ld t4, idtr, [1, t0, t4], dataSize=8, addressSize=8 - # Check permissions + # Make sure the descriptor is a legal gate. chks t1, t4, IntGateCheck - mov t1, t1, t4, dataSize=8 - - # Check that it's the right type - srli t4, t1, 40, dataSize=8 - andi t4, t4, 0xe, dataSize=8 - xori t4, t4, 0xe, flags=(EZF,), dataSize=8 - fault "new GeneralProtection(0)", flags=(nCEZF,) - - # # Get the target CS descriptor using the selector in the gate # descriptor. diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 492452a51..200024690 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -1067,9 +1067,15 @@ let {{ "not implemented.\\n"); break; case SegIntGateCheck: + // Check permissions. if (desc.dpl < m5reg.cpl) { fault = new GeneralProtection((uint16_t)selector); } + // Make sure the gate's the right type. + if (m5reg.mode == LongMode && ((desc.type & 0xe) != 0xe) || + ((desc.type & 0x6) != 0x6)) { + fault = new GeneralProtection(0); + } break; case SegSSCheck: if (selector.si || selector.ti) { -- cgit v1.2.3 From 041402a949ac61c2b871ce0595fd6a406ea9629c Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 1 Feb 2009 17:06:25 -0800 Subject: X86: Fix the upper bound on some ranges that were setting up the micro code assembler. --- src/arch/x86/isa/microasm.isa | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa index f9e0a2fa8..bc49d3362 100644 --- a/src/arch/x86/isa/microasm.isa +++ b/src/arch/x86/isa/microasm.isa @@ -76,9 +76,9 @@ let {{ mainRom = X86MicrocodeRom('main ROM') assembler = MicroAssembler(X86Macroop, microopClasses, mainRom, Rom_Macroop) # Add in symbols for the microcode registers - for num in range(15): + for num in range(16): assembler.symbols["t%d" % num] = "NUM_INTREGS+%d" % num - for num in range(7): + for num in range(8): assembler.symbols["ufp%d" % num] = "FLOATREG_MICROFP(%d)" % num # Add in symbols for the segment descriptor registers for letter in ("C", "D", "E", "F", "G", "H", "S"): @@ -140,7 +140,7 @@ let {{ for reg in ('ax', 'bx', 'cx', 'dx', 'sp', 'bp', 'si', 'di'): assembler.symbols["r%s" % reg] = "INTREG_R%s" % reg.upper() - for reg in range(15): + for reg in range(16): assembler.symbols["cr%d" % reg] = "MISCREG_CR%d" % reg for flag in ('CF', 'PF', 'ECF', 'AF', 'EZF', 'ZF', 'SF', 'OF', \ -- cgit v1.2.3 From 9b4d1e0f9a08ff36651d12151d0b51c37fefd643 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 1 Feb 2009 17:07:18 -0800 Subject: X86: Distinguish between hardware and software interrupts/exceptions --- src/arch/x86/isa/microasm.isa | 2 +- src/arch/x86/isa/microops/regop.isa | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa index bc49d3362..778754e0c 100644 --- a/src/arch/x86/isa/microasm.isa +++ b/src/arch/x86/isa/microasm.isa @@ -86,7 +86,7 @@ let {{ # Add in symbols for the various checks of segment selectors. for check in ("NoCheck", "CSCheck", "CallGateCheck", "IntGateCheck", - "SSCheck", "IretCheck", "IntCSCheck"): + "SoftIntGateCheck", "SSCheck", "IretCheck", "IntCSCheck"): assembler.symbols[check] = "Seg%s" % check for reg in ("TR", "IDTR"): diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 200024690..2e6160ec6 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -234,7 +234,7 @@ output header {{ enum SegmentSelectorCheck { SegNoCheck, SegCSCheck, SegCallGateCheck, SegIntGateCheck, - SegSSCheck, SegIretCheck, SegIntCSCheck + SegSoftIntGateCheck, SegSSCheck, SegIretCheck, SegIntCSCheck }; enum LongModeDescriptorType { @@ -1066,11 +1066,13 @@ let {{ panic("CS checks for far calls/jumps through call gates" "not implemented.\\n"); break; - case SegIntGateCheck: + case SegSoftIntGateCheck: // Check permissions. if (desc.dpl < m5reg.cpl) { fault = new GeneralProtection((uint16_t)selector); } + // Fall through on purpose + case SegIntGateCheck: // Make sure the gate's the right type. if (m5reg.mode == LongMode && ((desc.type & 0xe) != 0xe) || ((desc.type & 0x6) != 0x6)) { -- cgit v1.2.3 From 2f8cec849d49d2692665aec20a1cd441e743dae7 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 1 Feb 2009 17:07:43 -0800 Subject: X86: Make the long mode interrupt/exception microcode handle an error code. --- src/arch/x86/faults.cc | 1 + src/arch/x86/isa/insts/romutil.py | 72 ++++++++++++++++++++++++++------------- 2 files changed, 49 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/arch/x86/faults.cc b/src/arch/x86/faults.cc index 18680899e..2ce377bdd 100644 --- a/src/arch/x86/faults.cc +++ b/src/arch/x86/faults.cc @@ -123,6 +123,7 @@ namespace X86ISA } tc->setIntReg(INTREG_MICRO(1), vector); tc->setIntReg(INTREG_MICRO(7), tc->readPC()); + tc->setIntReg(INTREG_MICRO(15), (uint64_t)(-1)); tc->setMicroPC(romMicroPC(entry)); tc->setNextMicroPC(romMicroPC(entry) + 1); } diff --git a/src/arch/x86/isa/insts/romutil.py b/src/arch/x86/isa/insts/romutil.py index 9b4a80d44..ea41d2ca8 100644 --- a/src/arch/x86/isa/insts/romutil.py +++ b/src/arch/x86/isa/insts/romutil.py @@ -26,13 +26,13 @@ # # Authors: Gabe Black -microcode = ''' +intCodeTemplate = ''' def rom { # This vectors the CPU into an interrupt handler in long mode. # On entry, t1 is set to the vector of the interrupt and t7 is the current # ip. We need that because rdip returns the next ip. - extern longModeInterrupt: + extern %(startLabel)s: # # Get the 64 bit interrupt or trap gate descriptor from the IDT @@ -44,7 +44,7 @@ def rom ld t4, idtr, [1, t0, t4], dataSize=8, addressSize=8 # Make sure the descriptor is a legal gate. - chks t1, t4, IntGateCheck + chks t1, t4, %(gateCheckType)s # # Get the target CS descriptor using the selector in the gate @@ -53,12 +53,12 @@ def rom srli t10, t4, 16, dataSize=8 andi t5, t10, 0xF8, dataSize=8 andi t0, t10, 0x4, flags=(EZF,), dataSize=2 - br rom_local_label("globalDescriptor"), flags=(CEZF,) + br rom_local_label("%(startLabel)s_globalDescriptor"), flags=(CEZF,) ld t3, tsl, [1, t0, t5], dataSize=8, addressSize=8 - br rom_local_label("processDescriptor") -globalDescriptor: + br rom_local_label("%(startLabel)s_processDescriptor") +%(startLabel)s_globalDescriptor: ld t3, tsg, [1, t0, t5], dataSize=8, addressSize=8 -processDescriptor: +%(startLabel)s_processDescriptor: chks t10, t3, IntCSCheck, dataSize=8 wrdl hs, t3, t10, dataSize=8 @@ -90,29 +90,29 @@ processDescriptor: srli t10, t4, 32, dataSize=8 andi t10, t10, 0x7, dataSize=8 subi t0, t10, 1, flags=(ECF,), dataSize=8 - br rom_local_label("istStackSwitch"), flags=(nCECF,) - br rom_local_label("cplStackSwitch"), flags=(nCEZF,) + br rom_local_label("%(startLabel)s_istStackSwitch"), flags=(nCECF,) + br rom_local_label("%(startLabel)s_cplStackSwitch"), flags=(nCEZF,) # If we're here, it's because the stack isn't being switched. - # Set t6 to the new rsp. - subi t6, rsp, 40, dataSize=8 - - # Align the stack + # Set t6 to the new aligned rsp. + mov t6, rsp, dataSize=8 andi t6, t6, 0xF0, dataSize=1 + subi t6, t6, 40 + %(errorCodeSize)d, dataSize=8 # Check that we can access everything we need to on the stack ldst t0, hs, [1, t0, t6], dataSize=8, addressSize=8 - ldst t0, hs, [1, t0, t6], 32, dataSize=8, addressSize=8 - br rom_local_label("stackSwitched") + ldst t0, hs, [1, t0, t6], \ + 32 + %(errorCodeSize)d, dataSize=8, addressSize=8 + br rom_local_label("%(startLabel)s_stackSwitched") -istStackSwitch: +%(startLabel)s_istStackSwitch: panic "IST based stack switching isn't implemented" - br rom_local_label("stackSwitched") + br rom_local_label("%(startLabel)s_stackSwitched") -cplStackSwitch: +%(startLabel)s_cplStackSwitch: panic "CPL change initiated stack switching isn't implemented" -stackSwitched: +%(startLabel)s_stackSwitched: ## @@ -130,15 +130,16 @@ stackSwitched: # Write out the contents of memory - st t7, hs, [1, t0, t6], dataSize=8 + %(errorCodeCode)s + st t7, hs, [1, t0, t6], %(errorCodeSize)d, dataSize=8, addressSize=8 limm t5, 0, dataSize=8 rdsel t5, cs, dataSize=2 - st t5, hs, [1, t0, t6], 8, dataSize=8 + st t5, hs, [1, t0, t6], 8 + %(errorCodeSize)d, dataSize=8, addressSize=8 rflags t10, dataSize=8 - st t10, hs, [1, t0, t6], 16, dataSize=8 - st rsp, hs, [1, t0, t6], 24, dataSize=8 + st t10, hs, [1, t0, t6], 16 + %(errorCodeSize)d, dataSize=8, addressSize=8 + st rsp, hs, [1, t0, t6], 24 + %(errorCodeSize)d, dataSize=8, addressSize=8 rdsel t5, ss, dataSize=2 - st t5, hs, [1, t0, t6], 32, dataSize=8 + st t5, hs, [1, t0, t6], 32 + %(errorCodeSize)d, dataSize=8, addressSize=8 # Set the stack segment mov rsp, rsp, t6, dataSize=8 @@ -174,7 +175,30 @@ stackSwitched: eret }; +''' +microcode = \ +intCodeTemplate % {\ + "startLabel" : "longModeInterrupt", + "gateCheckType" : "IntGateCheck", + "errorCodeSize" : 0, + "errorCodeCode" : "" +} + \ +intCodeTemplate % {\ + "startLabel" : "longModeSoftInterrupt", + "gateCheckType" : "SoftIntGateCheck", + "errorCodeSize" : 0, + "errorCodeCode" : "" +} + \ +intCodeTemplate % {\ + "startLabel" : "longModeInterruptWithError", + "gateCheckType" : "IntGateCheck", + "errorCodeSize" : 8, + "errorCodeCode" : ''' + st t15, hs, [1, t0, t6], dataSize=8, addressSize=8 + ''' +} + \ +''' def rom { # This vectors the CPU into an interrupt handler in legacy mode. -- cgit v1.2.3 From 923a14dde749ad6b1887ccea764439a167555772 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 1 Feb 2009 17:08:32 -0800 Subject: X86: Make the fault classes handle error codes better. --- src/arch/x86/faults.cc | 4 ++- src/arch/x86/faults.hh | 54 ++++++++++++++++++++++++++----------- src/arch/x86/isa/microops/regop.isa | 11 ++++---- 3 files changed, 46 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/arch/x86/faults.cc b/src/arch/x86/faults.cc index 2ce377bdd..7702d98eb 100644 --- a/src/arch/x86/faults.cc +++ b/src/arch/x86/faults.cc @@ -123,7 +123,9 @@ namespace X86ISA } tc->setIntReg(INTREG_MICRO(1), vector); tc->setIntReg(INTREG_MICRO(7), tc->readPC()); - tc->setIntReg(INTREG_MICRO(15), (uint64_t)(-1)); + if (errorCode != (uint64_t)(-1)) { + tc->setIntReg(INTREG_MICRO(15), errorCode); + } tc->setMicroPC(romMicroPC(entry)); tc->setNextMicroPC(romMicroPC(entry) + 1); } diff --git a/src/arch/x86/faults.hh b/src/arch/x86/faults.hh index dc86d2cec..9c9cf3909 100644 --- a/src/arch/x86/faults.hh +++ b/src/arch/x86/faults.hh @@ -58,6 +58,7 @@ #ifndef __ARCH_X86_FAULTS_HH__ #define __ARCH_X86_FAULTS_HH__ +#include "base/bitunion.hh" #include "base/misc.hh" #include "sim/faults.hh" @@ -73,7 +74,7 @@ namespace X86ISA uint64_t errorCode; X86FaultBase(const char * _faultName, const char * _mnem, - const uint8_t _vector, uint64_t _errorCode = 0) : + const uint8_t _vector, uint64_t _errorCode = -1) : faultName(_faultName), mnem(_mnem), vector(_vector), errorCode(_errorCode) { @@ -107,7 +108,7 @@ namespace X86ISA { protected: X86Fault(const char * name, const char * mnem, - const uint8_t vector, uint64_t _errorCode = 0) : + const uint8_t vector, uint64_t _errorCode = -1) : X86FaultBase(name, mnem, vector, _errorCode) {} }; @@ -118,7 +119,7 @@ namespace X86ISA { protected: X86Trap(const char * name, const char * mnem, - const uint8_t vector, uint64_t _errorCode = 0) : + const uint8_t vector, uint64_t _errorCode = -1) : X86FaultBase(name, mnem, vector, _errorCode) {} @@ -132,7 +133,7 @@ namespace X86ISA { protected: X86Abort(const char * name, const char * mnem, - const uint8_t vector, uint64_t _errorCode = 0) : + const uint8_t vector, uint64_t _errorCode = -1) : X86FaultBase(name, mnem, vector, _errorCode) {} @@ -146,7 +147,7 @@ namespace X86ISA { protected: X86Interrupt(const char * name, const char * mnem, - const uint8_t _vector, uint64_t _errorCode = 0) : + const uint8_t _vector, uint64_t _errorCode = -1) : X86FaultBase(name, mnem, _vector, _errorCode) {} @@ -273,48 +274,69 @@ namespace X86ISA { public: DoubleFault() : - X86Abort("Double-Fault", "#DF", 8) + X86Abort("Double-Fault", "#DF", 8, 0) {} }; class InvalidTSS : public X86Fault { public: - InvalidTSS() : - X86Fault("Invalid-TSS", "#TS", 10) + InvalidTSS(uint32_t _errorCode) : + X86Fault("Invalid-TSS", "#TS", 10, _errorCode) {} }; class SegmentNotPresent : public X86Fault { public: - SegmentNotPresent() : - X86Fault("Segment-Not-Present", "#NP", 11) + SegmentNotPresent(uint32_t _errorCode) : + X86Fault("Segment-Not-Present", "#NP", 11, _errorCode) {} }; class StackFault : public X86Fault { public: - StackFault() : - X86Fault("Stack", "#SS", 12) + StackFault(uint32_t _errorCode) : + X86Fault("Stack", "#SS", 12, _errorCode) {} }; class GeneralProtection : public X86Fault { public: - GeneralProtection(uint64_t _errorCode) : + GeneralProtection(uint32_t _errorCode) : X86Fault("General-Protection", "#GP", 13, _errorCode) {} }; class PageFault : public X86Fault { + protected: + BitUnion32(PageFaultErrorCode) + Bitfield<0> present; + Bitfield<1> write; + Bitfield<2> user; + Bitfield<3> reserved; + Bitfield<4> fetch; + EndBitUnion(PageFaultErrorCode) + public: - PageFault() : - X86Fault("Page-Fault", "#PF", 14) + PageFault(uint32_t _errorCode) : + X86Fault("Page-Fault", "#PF", 14, _errorCode) {} + PageFault(bool present, bool write, bool user, + bool reserved, bool fetch) : + X86Fault("Page-Fault", "#PF", 14, 0) + { + PageFaultErrorCode code = 0; + code.present = present; + code.write = write; + code.user = user; + code.reserved = reserved; + code.fetch = fetch; + errorCode = code; + } }; class X87FpExceptionPending : public X86Fault @@ -329,7 +351,7 @@ namespace X86ISA { public: AlignmentCheck() : - X86Fault("Alignment-Check", "#AC", 17) + X86Fault("Alignment-Check", "#AC", 17, 0) {} }; diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 2e6160ec6..202bfc7f5 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -1069,7 +1069,7 @@ let {{ case SegSoftIntGateCheck: // Check permissions. if (desc.dpl < m5reg.cpl) { - fault = new GeneralProtection((uint16_t)selector); + fault = new GeneralProtection(selector); } // Fall through on purpose case SegIntGateCheck: @@ -1082,8 +1082,7 @@ let {{ case SegSSCheck: if (selector.si || selector.ti) { if (!desc.p) { - //FIXME This needs to also push the selector. - fault = new StackFault; + fault = new StackFault(selector); } } else { if ((m5reg.submode != SixtyFourBitMode || @@ -1092,7 +1091,7 @@ let {{ desc.type.codeOrData == 0 && desc.type.w) || (desc.dpl != m5reg.cpl) || (selector.rpl != m5reg.cpl)) { - fault = new GeneralProtection(psrc1 & 0xFFFF); + fault = new GeneralProtection(selector); } } break; @@ -1103,9 +1102,9 @@ let {{ !(desc.s == 1 && desc.type.codeOrData == 1) || (!desc.type.c && desc.dpl != selector.rpl) || (desc.type.c && desc.dpl > selector.rpl)) { - fault = new GeneralProtection(psrc1 & 0xFFFF); + fault = new GeneralProtection(selector); } else if (!desc.p) { - fault = new SegmentNotPresent; + fault = new SegmentNotPresent(selector); } break; } -- cgit v1.2.3 From 5a4eed5d34c814486086bf45d7750905de32d972 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 1 Feb 2009 17:09:08 -0800 Subject: X86: All x86 fault classes now attempt to do something useful. --- src/arch/x86/faults.cc | 57 ++++++++++++++++++++++++++++++--------- src/arch/x86/faults.hh | 35 +++++++++++++++--------- src/arch/x86/isa/insts/romutil.py | 2 +- 3 files changed, 69 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/arch/x86/faults.cc b/src/arch/x86/faults.cc index 7702d98eb..1234e68e5 100644 --- a/src/arch/x86/faults.cc +++ b/src/arch/x86/faults.cc @@ -101,34 +101,67 @@ namespace X86ISA { #if FULL_SYSTEM - void X86Trap::invoke(ThreadContext * tc) - { - panic("X86 faults are not implemented!"); - } - - void X86Abort::invoke(ThreadContext * tc) - { - panic("X86 faults are not implemented!"); - } - - void X86Interrupt::invoke(ThreadContext * tc) + void X86FaultBase::invoke(ThreadContext * tc) { using namespace X86ISAInst::RomLabels; HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); MicroPC entry; if (m5reg.mode == LongMode) { - entry = extern_label_longModeInterrupt; + if (isSoft()) { + entry = extern_label_longModeSoftInterrupt; + } else { + entry = extern_label_longModeInterrupt; + } } else { entry = extern_label_legacyModeInterrupt; } tc->setIntReg(INTREG_MICRO(1), vector); tc->setIntReg(INTREG_MICRO(7), tc->readPC()); if (errorCode != (uint64_t)(-1)) { + if (m5reg.mode == LongMode) { + entry = extern_label_longModeInterruptWithError; + } else { + panic("Legacy mode interrupts with error codes " + "aren't implementde.\n"); + } + // Software interrupts shouldn't have error codes. If one does, + // there would need to be microcode to set it up. + assert(!isSoft()); tc->setIntReg(INTREG_MICRO(15), errorCode); } tc->setMicroPC(romMicroPC(entry)); tc->setNextMicroPC(romMicroPC(entry) + 1); } + + void X86Trap::invoke(ThreadContext * tc) + { + X86FaultBase::invoke(tc); + // This is the same as a fault, but it happens -after- the instruction. + tc->setPC(tc->readNextPC()); + tc->setNextPC(tc->readNextNPC()); + tc->setNextNPC(tc->readNextNPC() + sizeof(MachInst)); + } + + void X86Abort::invoke(ThreadContext * tc) + { + panic("Abort exception!"); + } + + void PageFault::invoke(ThreadContext * tc) + { + HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); + X86FaultBase::invoke(tc); + /* + * If something bad happens while trying to enter the page fault + * handler, I'm pretty sure that's a double fault and then all bets are + * off. That means it should be safe to update this state now. + */ + if (m5reg.mode == LongMode) { + tc->setMiscReg(MISCREG_CR2, addr); + } else { + tc->setMiscReg(MISCREG_CR2, (uint32_t)addr); + } + } void FakeITLBFault::invoke(ThreadContext * tc) { diff --git a/src/arch/x86/faults.hh b/src/arch/x86/faults.hh index 9c9cf3909..6a6dfc80a 100644 --- a/src/arch/x86/faults.hh +++ b/src/arch/x86/faults.hh @@ -95,11 +95,14 @@ namespace X86ISA return mnem; } - void - invoke(ThreadContext * tc) + virtual bool isSoft() { - panic("Unimplemented fault %s.\n", name()); + return false; } + +#if FULL_SYSTEM + void invoke(ThreadContext * tc); +#endif }; // Base class for x86 faults which behave as if the underlying instruction @@ -150,10 +153,6 @@ namespace X86ISA const uint8_t _vector, uint64_t _errorCode = -1) : X86FaultBase(name, mnem, _vector, _errorCode) {} - -#if FULL_SYSTEM - void invoke(ThreadContext * tc); -#endif }; class UnimpInstFault : public FaultBase @@ -321,13 +320,16 @@ namespace X86ISA Bitfield<4> fetch; EndBitUnion(PageFaultErrorCode) + Addr addr; + public: - PageFault(uint32_t _errorCode) : - X86Fault("Page-Fault", "#PF", 14, _errorCode) + PageFault(Addr _addr, uint32_t _errorCode) : + X86Fault("Page-Fault", "#PF", 14, _errorCode), addr(_addr) {} - PageFault(bool present, bool write, bool user, - bool reserved, bool fetch) : - X86Fault("Page-Fault", "#PF", 14, 0) + + PageFault(Addr _addr, bool present, bool write, + bool user, bool reserved, bool fetch) : + X86Fault("Page-Fault", "#PF", 14, 0), addr(_addr) { PageFaultErrorCode code = 0; code.present = present; @@ -337,6 +339,10 @@ namespace X86ISA code.fetch = fetch; errorCode = code; } + +#if FULL_SYSTEM + void invoke(ThreadContext * tc); +#endif }; class X87FpExceptionPending : public X86Fault @@ -410,6 +416,11 @@ namespace X86ISA SoftwareInterrupt(uint8_t _vector) : X86Interrupt("Software Interrupt", "INTn", _vector) {} + + bool isSoft() + { + return true; + } }; // These faults aren't part of the ISA definition. They trigger filling diff --git a/src/arch/x86/isa/insts/romutil.py b/src/arch/x86/isa/insts/romutil.py index ea41d2ca8..1345c3d05 100644 --- a/src/arch/x86/isa/insts/romutil.py +++ b/src/arch/x86/isa/insts/romutil.py @@ -95,7 +95,7 @@ def rom # If we're here, it's because the stack isn't being switched. # Set t6 to the new aligned rsp. - mov t6, rsp, dataSize=8 + mov t6, t6, rsp, dataSize=8 andi t6, t6, 0xF0, dataSize=1 subi t6, t6, 40 + %(errorCodeSize)d, dataSize=8 -- cgit v1.2.3 From 73f579a804f33092aa2dfac09a57d6c6b2acaf3d Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 1 Feb 2009 22:40:51 -0800 Subject: X86: Add some missing default arguments. --- src/dev/x86/I8042.py | 2 ++ src/dev/x86/I82094AA.py | 2 +- src/dev/x86/I8259.py | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/dev/x86/I8042.py b/src/dev/x86/I8042.py index 1f6a48410..31192adcd 100644 --- a/src/dev/x86/I8042.py +++ b/src/dev/x86/I8042.py @@ -35,6 +35,8 @@ class I8042(BasicPioDevice): type = 'I8042' cxx_class = 'X86ISA::I8042' pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") + # This isn't actually used for anything here. + pio_addr = 0x0 data_port = Param.Addr('Data port address') command_port = Param.Addr('Command/status port address') mouse_int_pin = Param.X86IntSourcePin(X86IntSourcePin(), diff --git a/src/dev/x86/I82094AA.py b/src/dev/x86/I82094AA.py index 5ca58614d..9d57beed1 100644 --- a/src/dev/x86/I82094AA.py +++ b/src/dev/x86/I82094AA.py @@ -37,7 +37,7 @@ class I82094AA(BasicPioDevice): pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks") pio_addr = Param.Addr("Device address") int_port = Port("Port for sending and receiving interrupt messages") - external_int_pic = Param.I8259("External PIC, if any") + external_int_pic = Param.I8259(NULL, "External PIC, if any") def pin(self, line): return X86IntSinkPin(device=self, number=line) diff --git a/src/dev/x86/I8259.py b/src/dev/x86/I8259.py index e0128d032..0a516d30a 100644 --- a/src/dev/x86/I8259.py +++ b/src/dev/x86/I8259.py @@ -44,7 +44,7 @@ class I8259(BasicPioDevice): output = Param.X86IntSourcePin(X86IntSourcePin(), 'The pin this I8259 drives') mode = Param.X86I8259CascadeMode('How this I8259 is cascaded') - slave = Param.I8259('Slave I8259, if any') + slave = Param.I8259(NULL, 'Slave I8259, if any') def pin(self, line): return X86IntSinkPin(device=self, number=line) -- cgit v1.2.3 From 64eb0dc9cdd22b8c1e55ff7faaae1cae83c0a1a9 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Wed, 4 Feb 2009 16:26:15 -0800 Subject: some new files are missing copyright notices --- src/python/m5/core.py | 28 ++++++++++++++++++++++++++++ src/python/m5/debug.py | 28 ++++++++++++++++++++++++++++ src/python/m5/trace.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+) (limited to 'src') diff --git a/src/python/m5/core.py b/src/python/m5/core.py index 34590016e..232fe2ceb 100644 --- a/src/python/m5/core.py +++ b/src/python/m5/core.py @@ -1,3 +1,31 @@ +# Copyright (c) 2008 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + import internal def setOutputDir(dir): diff --git a/src/python/m5/debug.py b/src/python/m5/debug.py index 74c397562..cd40b8fa3 100644 --- a/src/python/m5/debug.py +++ b/src/python/m5/debug.py @@ -1,3 +1,31 @@ +# Copyright (c) 2008 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + import internal from internal.debug import schedBreakCycle, setRemoteGDBPort diff --git a/src/python/m5/trace.py b/src/python/m5/trace.py index 9e2351dbe..c97263c9b 100644 --- a/src/python/m5/trace.py +++ b/src/python/m5/trace.py @@ -1,3 +1,31 @@ +# Copyright (c) 2008 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + import internal import traceflags as flags -- cgit v1.2.3 From e1798d063e6d794bd44ba329e1b3ba5ac1dca9a5 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 6 Feb 2009 20:55:50 -0800 Subject: Quell g++ 4.3 warning about operator ambiguity --- src/arch/x86/isa/microops/regop.isa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 202bfc7f5..567335b7f 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -1074,7 +1074,7 @@ let {{ // Fall through on purpose case SegIntGateCheck: // Make sure the gate's the right type. - if (m5reg.mode == LongMode && ((desc.type & 0xe) != 0xe) || + if ((m5reg.mode == LongMode && (desc.type & 0xe) != 0xe) || ((desc.type & 0x6) != 0x6)) { fault = new GeneralProtection(0); } -- cgit v1.2.3 From 9e268ae63fe61c2365447d0df6baa351751cacb7 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 9 Feb 2009 20:10:12 -0800 Subject: scons: Don't build the intermediate static library unless explicitly requested. This means that similar to libm5_fast.so, you need to explicitly build build/ALPHA_SE/libm5_fast.a if you want it. --- src/SConscript | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/SConscript b/src/SConscript index 27ad56397..894a08df9 100644 --- a/src/SConscript +++ b/src/SConscript @@ -992,10 +992,10 @@ def makeEnv(label, objsfx, strip = False, **kwargs): for target, sources in unit_tests: objs = [ new_env.StaticObject(s) for s in sources ] - new_env.Program("unittest/%s.%s" % (target, label), objs + static_lib) + new_env.Program("unittest/%s.%s" % (target, label), objs + static_objs) # Now link a stub with main() and the static library. - objects = [new_env.Object(s) for s in cc_bin_sources] + static_lib + objects = [new_env.Object(s) for s in cc_bin_sources] + static_objs if strip: unstripped_exe = exename + '.unstripped' new_env.Program(unstripped_exe, objects) -- cgit v1.2.3 From dd6ea8797fdfbe00331a17ab3ffade10bbcbde1f Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 9 Feb 2009 20:10:14 -0800 Subject: scons: Require SCons version 0.98.1 This allows me to clean things up so we are up to date with respect to deprecated features. There are many features scheduled for permanent failure in scons 2.0 and 0.98.1 provides the most compatability for that. It also paves the way for some nice new features that I will add soon --- src/SConscript | 29 +++++------------------------ src/arch/alpha/SConsopts | 2 +- 2 files changed, 6 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/SConscript b/src/SConscript index 894a08df9..c02bf239d 100644 --- a/src/SConscript +++ b/src/SConscript @@ -48,7 +48,7 @@ Import('*') # Children need to see the environment Export('env') -build_env = dict([(opt, env[opt]) for opt in env.ExportOptions]) +build_env = dict([(opt, env[opt]) for opt in env.ExportVariables]) def sort_list(_list): """return a sorted copy of '_list'""" @@ -242,7 +242,7 @@ for extra_dir in extras_dir_list: build_dir = joinpath(env['BUILDDIR'], root[prefix_len:]) SConscript(joinpath(root, 'SConscript'), build_dir=build_dir) -for opt in env.ExportOptions: +for opt in env.ExportVariables: env.ConfigFile(opt) ######################################################################## @@ -353,25 +353,6 @@ depends = [ File(py_modules[dep]) for dep in module_depends ] # Commands for the basic automatically generated python files # -scons_dir = str(SCons.Node.FS.default_fs.SConstruct_dir) - -hg_info = "Unknown" -hg_demandimport = False -try: - if not exists(scons_dir) or not isdir(scons_dir) or \ - not exists(joinpath(scons_dir, ".hg")): - raise ValueError(".hg directory not found") - import subprocess - output = subprocess.Popen("hg id -n -i -t -b".split(), - stdout=subprocess.PIPE).communicate()[0] - hg_info = output.strip() -except ImportError, e: - print "Mercurial not found" -except ValueError, e: - print e -except Exception, e: - print "Other mercurial exception: %s" % e - # Generate Python file containing a dict specifying the current # build_env flags. def makeDefinesPyFile(target, source, env): @@ -381,7 +362,7 @@ def makeDefinesPyFile(target, source, env): print >>f, "hgRev = '%s'" % hg_info f.close() -defines_info = [ Value(build_env), Value(hg_info) ] +defines_info = [ Value(build_env), Value(env['HG_INFO']) ] # Generate a file with all of the compile options in it env.Command('python/m5/defines.py', defines_info, makeDefinesPyFile) PySource('m5', 'python/m5/defines.py') @@ -970,11 +951,11 @@ def makeEnv(label, objsfx, strip = False, **kwargs): libname = 'm5_' + label exename = 'm5.' + label - new_env = env.Copy(OBJSUFFIX=objsfx, SHOBJSUFFIX=objsfx + 's') + new_env = env.Clone(OBJSUFFIX=objsfx, SHOBJSUFFIX=objsfx + 's') new_env.Label = label new_env.Append(**kwargs) - swig_env = new_env.Copy() + swig_env = new_env.Clone() if env['GCC']: swig_env.Append(CCFLAGS='-Wno-uninitialized') swig_env.Append(CCFLAGS='-Wno-sign-compare') diff --git a/src/arch/alpha/SConsopts b/src/arch/alpha/SConsopts index 633eeb06f..b418e27c8 100644 --- a/src/arch/alpha/SConsopts +++ b/src/arch/alpha/SConsopts @@ -33,5 +33,5 @@ Import('*') all_isa_list.append('alpha') # Alpha can be compiled with Turbolaser support instead of Tsunami -sticky_opts.Add(BoolOption('ALPHA_TLASER', +sticky_vars.Add(BoolVariable('ALPHA_TLASER', 'Model Alpha TurboLaser platform (vs. Tsunami)', False)) -- cgit v1.2.3 From 20c5ec6e1cb52d9e0f39d50bb254bffda139c4ea Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 9 Feb 2009 20:10:15 -0800 Subject: copyright: This file need not have had the more restrictive copyright. --- src/arch/x86/SConsopts | 45 +++++++++------------------------------------ 1 file changed, 9 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/arch/x86/SConsopts b/src/arch/x86/SConsopts index d8b7cbed1..f8b700271 100644 --- a/src/arch/x86/SConsopts +++ b/src/arch/x86/SConsopts @@ -3,43 +3,16 @@ # Copyright (c) 2007 The Hewlett-Packard Development Company # All rights reserved. # -# Redistribution and use of this software in source and binary forms, -# with or without modification, are permitted provided that the -# following conditions are met: -# -# The software must be used only for Non-Commercial Use which means any -# use which is NOT directed to receiving any direct monetary -# compensation for, or commercial advantage from such use. Illustrative -# examples of non-commercial use are academic research, personal study, -# teaching, education and corporate research & development. -# Illustrative examples of commercial use are distributing products for -# commercial advantage and providing services using the software for -# commercial advantage. -# -# If you wish to use this software or functionality therein that may be -# covered by patents for commercial use, please contact: -# Director of Intellectual Property Licensing -# Office of Strategy and Technology -# Hewlett-Packard Company -# 1501 Page Mill Road -# Palo Alto, California 94304 -# -# 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +# 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. No right of -# sublicense is granted herewith. Derivatives of the software and -# output created using the software may be prepared, but only for -# Non-Commercial Uses. Derivatives of the software may be shared with -# others provided: (i) the others agree to abide by the list of -# conditions herein which includes the Non-Commercial Use restrictions; -# and (ii) such Derivatives of the software include the above copyright -# notice to acknowledge the contribution from this software where -# applicable, this list of conditions and the disclaimer below. +# 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 -- cgit v1.2.3 From 2d0a66cbc123fc345deb070c323130382518f367 Mon Sep 17 00:00:00 2001 From: Korey Sewell Date: Tue, 10 Feb 2009 15:49:29 -0800 Subject: CPU: Prepare CPU models for the new in-order CPU model. Some new functions and forward declarations are necessary to make things work --- src/cpu/SConscript | 10 ++++++---- src/cpu/o3/ras.hh | 3 +++ src/cpu/static_inst.hh | 11 ++++++++--- 3 files changed, 17 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/cpu/SConscript b/src/cpu/SConscript index f210cec9b..eee8edca4 100644 --- a/src/cpu/SConscript +++ b/src/cpu/SConscript @@ -48,12 +48,14 @@ execfile(models_db.srcnode().abspath) # Template for execute() signature. exec_sig_template = ''' -virtual Fault execute(%s *xc, Trace::InstRecord *traceData) const = 0; -virtual Fault initiateAcc(%s *xc, Trace::InstRecord *traceData) const +virtual Fault execute(%(type)s *xc, Trace::InstRecord *traceData) const = 0; +virtual Fault initiateAcc(%(type)s *xc, Trace::InstRecord *traceData) const { panic("initiateAcc not defined!"); M5_DUMMY_RETURN }; -virtual Fault completeAcc(Packet *pkt, %s *xc, +virtual Fault completeAcc(Packet *pkt, %(type)s *xc, Trace::InstRecord *traceData) const { panic("completeAcc not defined!"); M5_DUMMY_RETURN }; +virtual int memAccSize(%(type)s *xc) +{ panic("memAccSize not defined!"); M5_DUMMY_RETURN }; ''' mem_ini_sig_template = ''' @@ -82,7 +84,7 @@ def gen_cpu_exec_signatures(target, source, env): ''' for cpu in temp_cpu_list: xc_type = CpuModel.dict[cpu].strings['CPU_exec_context'] - print >> f, exec_sig_template % (xc_type, xc_type, xc_type) + print >> f, exec_sig_template % { 'type' : xc_type } print >> f, ''' #endif // __CPU_STATIC_INST_EXEC_SIGS_HH__ ''' diff --git a/src/cpu/o3/ras.hh b/src/cpu/o3/ras.hh index 97846ed16..f0621c5b5 100644 --- a/src/cpu/o3/ras.hh +++ b/src/cpu/o3/ras.hh @@ -71,6 +71,9 @@ class ReturnAddrStack */ void restore(unsigned top_entry_idx, const Addr &restored_target); + bool empty() { return usedEntries == 0; } + + bool full() { return usedEntries == numEntries; } private: /** Increments the top of stack index. */ inline void incrTos() diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index 032a304ad..f28b53ccf 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -56,9 +56,8 @@ class Packet; class O3CPUImpl; template class BaseO3DynInst; typedef BaseO3DynInst O3DynInst; - -template -class OzoneDynInst; +template class OzoneDynInst; +class InOrderDynInst; class CheckerCPU; class FastCPU; @@ -434,6 +433,12 @@ class StaticInst : public StaticInstBase */ bool hasBranchTarget(Addr pc, ThreadContext *tc, Addr &tgt) const; + virtual Request::Flags memAccFlags() + { + panic("StaticInst::memAccFlags called on non-memory instruction"); + return 0; + }; + /** * Return string representation of disassembled instruction. * The default version of this function will call the internal -- cgit v1.2.3 From 34a5cd887075ff8bee987b87e43ae3818c6ac765 Mon Sep 17 00:00:00 2001 From: Korey Sewell Date: Tue, 10 Feb 2009 15:49:29 -0800 Subject: ExeTrace: Allow subclasses of the tracer to define their own prefix to dump --- src/cpu/exetrace.cc | 8 +++++++- src/cpu/exetrace.hh | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc index 7227602b5..5897d1dbc 100644 --- a/src/cpu/exetrace.cc +++ b/src/cpu/exetrace.cc @@ -45,13 +45,19 @@ using namespace TheISA; namespace Trace { +void +ExeTracerRecord::dumpTicks(ostream &outs) +{ + ccprintf(outs, "%7d: ", when); +} + void Trace::ExeTracerRecord::traceInst(StaticInstPtr inst, bool ran) { ostream &outs = Trace::output(); if (IsOn(ExecTicks)) - ccprintf(outs, "%7d: ", when); + dumpTicks(outs); outs << thread->getCpuPtr()->name() << " "; diff --git a/src/cpu/exetrace.hh b/src/cpu/exetrace.hh index e5b22c881..e49a2bb59 100644 --- a/src/cpu/exetrace.hh +++ b/src/cpu/exetrace.hh @@ -57,6 +57,7 @@ class ExeTracerRecord : public InstRecord void traceInst(StaticInstPtr inst, bool ran); void dump(); + virtual void dumpTicks(std::ostream &outs); }; class ExeTracer : public InstTracer -- cgit v1.2.3 From 36d9065f5f716f88c82a3f4e9a75fa040039aa0a Mon Sep 17 00:00:00 2001 From: Korey Sewell Date: Tue, 10 Feb 2009 15:49:29 -0800 Subject: syscall: Expose ioctl for MIPS --- src/arch/mips/linux/linux.hh | 18 +++++++++--------- src/arch/mips/linux/process.cc | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/arch/mips/linux/linux.hh b/src/arch/mips/linux/linux.hh index 0d71a3c58..4667748fb 100644 --- a/src/arch/mips/linux/linux.hh +++ b/src/arch/mips/linux/linux.hh @@ -94,15 +94,15 @@ class MipsLinux : public Linux //@{ /// ioctl() command codes. - static const unsigned TIOCGETP = 0x7408; - static const unsigned TIOCSETP = 0x7409; - static const unsigned TIOCSETN = 0x740a; - static const unsigned TIOCSETC = 0x7411; - static const unsigned TIOCGETC = 0x7412; - static const unsigned FIONREAD = 0x467f; - static const unsigned TIOCISATTY = 0x5480; - static const unsigned TIOCGETS = 0x540d; - static const unsigned TIOCGETA = 0x7417; + static const unsigned TIOCGETP_ = 0x7408; + static const unsigned TIOCSETP_ = 0x7409; + static const unsigned TIOCSETN_ = 0x740a; + static const unsigned TIOCSETC_ = 0x7411; + static const unsigned TIOCGETC_ = 0x7412; + static const unsigned FIONREAD_ = 0x467f; + static const unsigned TIOCISATTY_ = 0x5480; + static const unsigned TIOCGETS_ = 0x540d; + static const unsigned TIOCGETA_ = 0x7417; //@} /// For table(). diff --git a/src/arch/mips/linux/process.cc b/src/arch/mips/linux/process.cc index 56413484b..ce09e1628 100644 --- a/src/arch/mips/linux/process.cc +++ b/src/arch/mips/linux/process.cc @@ -175,7 +175,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 51 */ SyscallDesc("acct", unimplementedFunc), /* 52 */ SyscallDesc("umount2", unimplementedFunc), /* 53 */ SyscallDesc("lock", unimplementedFunc), - /* 54 */ SyscallDesc("ioctl", unimplementedFunc/*ioctlFunc*/), + /* 54 */ SyscallDesc("ioctl", ioctlFunc), /* 55 */ SyscallDesc("fcntl", fcntlFunc), /* 56 */ SyscallDesc("mpx", unimplementedFunc), /* 57 */ SyscallDesc("setpgid", unimplementedFunc), -- cgit v1.2.3 From 973d8b8b13b8e4ea178cafa95aaf6538699b8b15 Mon Sep 17 00:00:00 2001 From: Korey Sewell Date: Tue, 10 Feb 2009 15:49:29 -0800 Subject: InOrder: Import new inorder CPU model from MIPS. This model currently only works in MIPS_SE mode, so it will take some effort to clean it up and make it generally useful. Hopefully people are willing to help make that happen! --- src/cpu/cpu_models.py | 3 + src/cpu/inorder/InOrderCPU.py | 80 ++ src/cpu/inorder/InOrderTrace.py | 35 + src/cpu/inorder/SConscript | 82 ++ src/cpu/inorder/SConsopts | 33 + src/cpu/inorder/comm.hh | 104 ++ src/cpu/inorder/cpu.cc | 1322 ++++++++++++++++++++++++ src/cpu/inorder/cpu.hh | 730 +++++++++++++ src/cpu/inorder/first_stage.cc | 251 +++++ src/cpu/inorder/first_stage.hh | 97 ++ src/cpu/inorder/inorder_cpu_builder.cc | 61 ++ src/cpu/inorder/inorder_dyn_inst.cc | 780 ++++++++++++++ src/cpu/inorder/inorder_dyn_inst.hh | 975 +++++++++++++++++ src/cpu/inorder/inorder_trace.cc | 94 ++ src/cpu/inorder/inorder_trace.hh | 98 ++ src/cpu/inorder/params.hh | 124 +++ src/cpu/inorder/pipeline_stage.cc | 1033 ++++++++++++++++++ src/cpu/inorder/pipeline_stage.hh | 358 +++++++ src/cpu/inorder/pipeline_traits.5stage.cc | 166 +++ src/cpu/inorder/pipeline_traits.5stage.hh | 147 +++ src/cpu/inorder/pipeline_traits.9stage.cc | 242 +++++ src/cpu/inorder/pipeline_traits.9stage.hh | 155 +++ src/cpu/inorder/pipeline_traits.9stage.smt2.cc | 240 +++++ src/cpu/inorder/pipeline_traits.9stage.smt2.hh | 155 +++ src/cpu/inorder/pipeline_traits.cc | 153 +++ src/cpu/inorder/pipeline_traits.hh | 177 ++++ src/cpu/inorder/reg_dep_map.cc | 236 +++++ src/cpu/inorder/reg_dep_map.hh | 105 ++ src/cpu/inorder/resource.cc | 434 ++++++++ src/cpu/inorder/resource.hh | 404 ++++++++ src/cpu/inorder/resource_pool.9stage.cc | 357 +++++++ src/cpu/inorder/resource_pool.cc | 364 +++++++ src/cpu/inorder/resource_pool.hh | 189 ++++ src/cpu/inorder/resources/agen_unit.cc | 98 ++ src/cpu/inorder/resources/agen_unit.hh | 64 ++ src/cpu/inorder/resources/bpred_unit.cc | 426 ++++++++ src/cpu/inorder/resources/bpred_unit.hh | 258 +++++ src/cpu/inorder/resources/branch_predictor.cc | 149 +++ src/cpu/inorder/resources/branch_predictor.hh | 87 ++ src/cpu/inorder/resources/cache_unit.cc | 609 +++++++++++ src/cpu/inorder/resources/cache_unit.hh | 305 ++++++ src/cpu/inorder/resources/decode_unit.cc | 92 ++ src/cpu/inorder/resources/decode_unit.hh | 68 ++ src/cpu/inorder/resources/execution_unit.cc | 182 ++++ src/cpu/inorder/resources/execution_unit.hh | 77 ++ src/cpu/inorder/resources/fetch_seq_unit.cc | 324 ++++++ src/cpu/inorder/resources/fetch_seq_unit.hh | 119 +++ src/cpu/inorder/resources/graduation_unit.cc | 113 ++ src/cpu/inorder/resources/graduation_unit.hh | 70 ++ src/cpu/inorder/resources/inst_buffer.cc | 222 ++++ src/cpu/inorder/resources/inst_buffer.hh | 93 ++ src/cpu/inorder/resources/inst_buffer_new.cc | 156 +++ src/cpu/inorder/resources/inst_buffer_new.hh | 109 ++ src/cpu/inorder/resources/mem_dep_unit.hh | 66 ++ src/cpu/inorder/resources/mult_div_unit.cc | 291 ++++++ src/cpu/inorder/resources/mult_div_unit.hh | 138 +++ src/cpu/inorder/resources/resource_list.hh | 47 + src/cpu/inorder/resources/tlb_unit.cc | 186 ++++ src/cpu/inorder/resources/tlb_unit.hh | 124 +++ src/cpu/inorder/resources/use_def.cc | 326 ++++++ src/cpu/inorder/resources/use_def.hh | 102 ++ src/cpu/inorder/thread_context.cc | 371 +++++++ src/cpu/inorder/thread_context.hh | 286 +++++ src/cpu/inorder/thread_state.hh | 90 ++ 64 files changed, 15432 insertions(+) create mode 100644 src/cpu/inorder/InOrderCPU.py create mode 100644 src/cpu/inorder/InOrderTrace.py create mode 100644 src/cpu/inorder/SConscript create mode 100644 src/cpu/inorder/SConsopts create mode 100644 src/cpu/inorder/comm.hh create mode 100644 src/cpu/inorder/cpu.cc create mode 100644 src/cpu/inorder/cpu.hh create mode 100644 src/cpu/inorder/first_stage.cc create mode 100644 src/cpu/inorder/first_stage.hh create mode 100644 src/cpu/inorder/inorder_cpu_builder.cc create mode 100644 src/cpu/inorder/inorder_dyn_inst.cc create mode 100644 src/cpu/inorder/inorder_dyn_inst.hh create mode 100644 src/cpu/inorder/inorder_trace.cc create mode 100644 src/cpu/inorder/inorder_trace.hh create mode 100644 src/cpu/inorder/params.hh create mode 100644 src/cpu/inorder/pipeline_stage.cc create mode 100644 src/cpu/inorder/pipeline_stage.hh create mode 100644 src/cpu/inorder/pipeline_traits.5stage.cc create mode 100644 src/cpu/inorder/pipeline_traits.5stage.hh create mode 100644 src/cpu/inorder/pipeline_traits.9stage.cc create mode 100644 src/cpu/inorder/pipeline_traits.9stage.hh create mode 100644 src/cpu/inorder/pipeline_traits.9stage.smt2.cc create mode 100644 src/cpu/inorder/pipeline_traits.9stage.smt2.hh create mode 100644 src/cpu/inorder/pipeline_traits.cc create mode 100644 src/cpu/inorder/pipeline_traits.hh create mode 100644 src/cpu/inorder/reg_dep_map.cc create mode 100644 src/cpu/inorder/reg_dep_map.hh create mode 100644 src/cpu/inorder/resource.cc create mode 100644 src/cpu/inorder/resource.hh create mode 100644 src/cpu/inorder/resource_pool.9stage.cc create mode 100644 src/cpu/inorder/resource_pool.cc create mode 100644 src/cpu/inorder/resource_pool.hh create mode 100644 src/cpu/inorder/resources/agen_unit.cc create mode 100644 src/cpu/inorder/resources/agen_unit.hh create mode 100644 src/cpu/inorder/resources/bpred_unit.cc create mode 100644 src/cpu/inorder/resources/bpred_unit.hh create mode 100644 src/cpu/inorder/resources/branch_predictor.cc create mode 100644 src/cpu/inorder/resources/branch_predictor.hh create mode 100644 src/cpu/inorder/resources/cache_unit.cc create mode 100644 src/cpu/inorder/resources/cache_unit.hh create mode 100644 src/cpu/inorder/resources/decode_unit.cc create mode 100644 src/cpu/inorder/resources/decode_unit.hh create mode 100644 src/cpu/inorder/resources/execution_unit.cc create mode 100644 src/cpu/inorder/resources/execution_unit.hh create mode 100644 src/cpu/inorder/resources/fetch_seq_unit.cc create mode 100644 src/cpu/inorder/resources/fetch_seq_unit.hh create mode 100644 src/cpu/inorder/resources/graduation_unit.cc create mode 100644 src/cpu/inorder/resources/graduation_unit.hh create mode 100644 src/cpu/inorder/resources/inst_buffer.cc create mode 100644 src/cpu/inorder/resources/inst_buffer.hh create mode 100644 src/cpu/inorder/resources/inst_buffer_new.cc create mode 100644 src/cpu/inorder/resources/inst_buffer_new.hh create mode 100644 src/cpu/inorder/resources/mem_dep_unit.hh create mode 100644 src/cpu/inorder/resources/mult_div_unit.cc create mode 100644 src/cpu/inorder/resources/mult_div_unit.hh create mode 100644 src/cpu/inorder/resources/resource_list.hh create mode 100644 src/cpu/inorder/resources/tlb_unit.cc create mode 100644 src/cpu/inorder/resources/tlb_unit.hh create mode 100644 src/cpu/inorder/resources/use_def.cc create mode 100644 src/cpu/inorder/resources/use_def.hh create mode 100644 src/cpu/inorder/thread_context.cc create mode 100644 src/cpu/inorder/thread_context.hh create mode 100644 src/cpu/inorder/thread_state.hh (limited to 'src') diff --git a/src/cpu/cpu_models.py b/src/cpu/cpu_models.py index 5b0c6c4da..793f8c646 100644 --- a/src/cpu/cpu_models.py +++ b/src/cpu/cpu_models.py @@ -82,3 +82,6 @@ CpuModel('CheckerCPU', 'checker_cpu_exec.cc', CpuModel('O3CPU', 'o3_cpu_exec.cc', '#include "cpu/o3/isa_specific.hh"', { 'CPU_exec_context': 'O3DynInst' }) +CpuModel('InOrderCPU', 'inorder_cpu_exec.cc', + '#include "cpu/inorder/inorder_dyn_inst.hh"', + { 'CPU_exec_context': 'InOrderDynInst' }) diff --git a/src/cpu/inorder/InOrderCPU.py b/src/cpu/inorder/InOrderCPU.py new file mode 100644 index 000000000..a5e81a090 --- /dev/null +++ b/src/cpu/inorder/InOrderCPU.py @@ -0,0 +1,80 @@ +# Copyright (c) 2007 MIPS Technologies, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Korey Sewell + +from m5.params import * +from m5.proxy import * +from m5 import build_env +from BaseCPU import BaseCPU + +class InOrderCPU(BaseCPU): + type = 'InOrderCPU' + activity = Param.Unsigned(0, "Initial count") + numThreads = Param.Unsigned(1, "number of HW thread contexts") + + cachePorts = Param.Unsigned("Cache Ports") + stageWidth = Param.Unsigned(1, "Stage width") + + 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") + _mem_ports = ['icache_port', 'dcache_port'] + + predType = Param.String("tournament", "Branch predictor type ('local', 'tournament')") + localPredictorSize = Param.Unsigned(2048, "Size of local predictor") + localCtrBits = Param.Unsigned(2, "Bits per counter") + localHistoryTableSize = Param.Unsigned(2048, "Size of local history table") + localHistoryBits = Param.Unsigned(11, "Bits for the local history") + globalPredictorSize = Param.Unsigned(8192, "Size of global predictor") + globalCtrBits = Param.Unsigned(2, "Bits per counter") + globalHistoryBits = Param.Unsigned(13, "Bits of history") + choicePredictorSize = Param.Unsigned(8192, "Size of choice predictor") + choiceCtrBits = Param.Unsigned(2, "Bits of choice counters") + + BTBEntries = Param.Unsigned(4096, "Number of BTB entries") + BTBTagSize = Param.Unsigned(16, "Size of the BTB tags, in bits") + + RASSize = Param.Unsigned(16, "RAS size") + + instShiftAmt = Param.Unsigned(2, "Number of bits to shift instructions by") + functionTrace = Param.Bool(False, "Enable function trace") + functionTraceStart = Param.Tick(0, "Cycle to start function trace") + stageTracing = Param.Bool(False, "Enable tracing of each stage in CPU") + + memBlockSize = Param.Unsigned("Memory Block Size") + + multLatency = Param.Unsigned(1, "Latency for Multiply Operations") + multRepeatRate = Param.Unsigned(1, "Repeat Rate for Multiply Operations") + div8Latency = Param.Unsigned(1, "Latency for 8-bit Divide Operations") + div8RepeatRate = Param.Unsigned(1, "Repeat Rate for 8-bit Divide Operations") + div16Latency = Param.Unsigned(1, "Latency for 16-bit Divide Operations") + div16RepeatRate = Param.Unsigned(1, "Repeat Rate for 16-bit Divide Operations") + div24Latency = Param.Unsigned(1, "Latency for 24-bit Divide Operations") + div24RepeatRate = Param.Unsigned(1, "Repeat Rate for 24-bit Divide Operations") + div32Latency = Param.Unsigned(1, "Latency for 32-bit Divide Operations") + div32RepeatRate = Param.Unsigned(1, "Repeat Rate for 32-bit Divide Operations") diff --git a/src/cpu/inorder/InOrderTrace.py b/src/cpu/inorder/InOrderTrace.py new file mode 100644 index 000000000..3453fa675 --- /dev/null +++ b/src/cpu/inorder/InOrderTrace.py @@ -0,0 +1,35 @@ +# Copyright (c) 2007 MIPS Technologies, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Korey Sewell + +from m5.SimObject import SimObject +from m5.params import * +from InstTracer import InstTracer + +class InOrderTrace(InstTracer): + type = 'InOrderTrace' + cxx_class = 'Trace::InOrderTrace' diff --git a/src/cpu/inorder/SConscript b/src/cpu/inorder/SConscript new file mode 100644 index 000000000..c7edd1d76 --- /dev/null +++ b/src/cpu/inorder/SConscript @@ -0,0 +1,82 @@ +# -*- mode:python -*- + +# Copyright (c) 2007 MIPS Technologies, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Korey Sewell + +Import('*') + +if 'InOrderCPU' in env['CPU_MODELS']: + SimObject('InOrderCPU.py') + SimObject('InOrderTrace.py') + + TraceFlag('ResReqCount') + TraceFlag('FreeList') + TraceFlag('InOrderCachePort') + TraceFlag('InOrderStage') + TraceFlag('InOrderStall') + TraceFlag('InOrderCPU') + TraceFlag('InOrderMDU') + TraceFlag('RegDepMap') + TraceFlag('Rename') + TraceFlag('InOrderDynInst') + TraceFlag('Resource') + TraceFlag('RefCount') + + CompoundFlag('InOrderCPUAll', [ 'InOrderStage', 'InOrderStall', 'InOrderCPU', + 'InOrderMDU', 'RegDepMap', 'Resource', 'Rename']) + + Source('pipeline_traits.cc') + Source('inorder_dyn_inst.cc') + Source('inorder_cpu_builder.cc') + Source('inorder_trace.cc') + Source('pipeline_stage.cc') + Source('first_stage.cc') + Source('resource.cc') + Source('resources/agen_unit.cc') + Source('resources/execution_unit.cc') + Source('resources/bpred_unit.cc') + Source('resources/branch_predictor.cc') + Source('resources/cache_unit.cc') + Source('resources/use_def.cc') + Source('resources/decode_unit.cc') + Source('resources/inst_buffer.cc') + Source('resources/graduation_unit.cc') + Source('resources/tlb_unit.cc') + Source('resources/fetch_seq_unit.cc') + Source('resources/mult_div_unit.cc') + Source('resource_pool.cc') + Source('reg_dep_map.cc') + Source('../o3/btb.cc') + Source('../o3/tournament_pred.cc') + Source('../o3/2bit_local_pred.cc') + Source('../o3/free_list.cc') + Source('../o3/rename_map.cc') + Source('../o3/ras.cc') + Source('thread_context.cc') + Source('cpu.cc') + diff --git a/src/cpu/inorder/SConsopts b/src/cpu/inorder/SConsopts new file mode 100644 index 000000000..82ebd18ea --- /dev/null +++ b/src/cpu/inorder/SConsopts @@ -0,0 +1,33 @@ +# -*- mode:python -*- + +# Copyright (c) 2007 MIPS Technologies, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Korey Sewell + +Import('*') + +all_cpu_list.append('InOrderCPU') diff --git a/src/cpu/inorder/comm.hh b/src/cpu/inorder/comm.hh new file mode 100644 index 000000000..c687a9ab4 --- /dev/null +++ b/src/cpu/inorder/comm.hh @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __CPU_INORDER_COMM_HH__ +#define __CPU_INORDER_COMM_HH__ + +#include + +#include "arch/faults.hh" +#include "arch/isa_traits.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inst_seq.hh" +#include "sim/host.hh" + +/** Struct that defines the information passed from in between stages */ +/** This information mainly goes forward through the pipeline. */ +struct InterStageStruct { + int size; + ThePipeline::DynInstPtr insts[ThePipeline::StageWidth]; + bool squash; + bool branchMispredict; + bool branchTaken; + uint64_t mispredPC; + uint64_t nextPC; + InstSeqNum squashedSeqNum; + bool includeSquashInst; +}; + +/** Turn This into a Class */ +/** Struct that defines all backwards communication. */ +struct TimeStruct { + struct stageComm { + bool squash; + bool predIncorrect; + uint64_t branchAddr; + + // @todo: Might want to package this kind of branch stuff into a single + // struct as it is used pretty frequently. + bool branchMispredict; + bool branchTaken; + uint64_t mispredPC; + uint64_t nextPC; + + unsigned branchCount; + + // Represents the instruction that has either been retired or + // squashed. Similar to having a single bus that broadcasts the + // retired or squashed sequence number. + InstSeqNum doneSeqNum; + InstSeqNum bdelayDoneSeqNum; + bool squashDelaySlot; + + //Just in case we want to do a commit/squash on a cycle + //(necessary for multiple ROBs?) + bool commitInsts; + InstSeqNum squashSeqNum; + + // Communication specifically to the IQ to tell the IQ that it can + // schedule a non-speculative instruction. + InstSeqNum nonSpecSeqNum; + + bool uncached; + ThePipeline::DynInstPtr uncachedLoad; + + bool interruptPending; + bool clearInterrupt; + }; + + stageComm stageInfo[ThePipeline::NumStages][ThePipeline::MaxThreads]; + + bool stageBlock[ThePipeline::NumStages][ThePipeline::MaxThreads]; + bool stageUnblock[ThePipeline::NumStages][ThePipeline::MaxThreads]; +}; + +#endif //__CPU_INORDER_COMM_HH__ diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc new file mode 100644 index 000000000..adbf645f4 --- /dev/null +++ b/src/cpu/inorder/cpu.cc @@ -0,0 +1,1322 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include "arch/utility.hh" +#include "cpu/exetrace.hh" +#include "cpu/activity.hh" +#include "cpu/simple_thread.hh" +#include "cpu/thread_context.hh" +#include "cpu/base.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/thread_context.hh" +#include "cpu/inorder/thread_state.hh" +#include "cpu/inorder/cpu.hh" +#include "params/InOrderCPU.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/first_stage.hh" +#include "cpu/inorder/resources/resource_list.hh" +#include "cpu/inorder/resource_pool.hh" +#include "mem/translating_port.hh" +#include "sim/process.hh" +//#include "sim/root.hh" +#include "sim/stat_control.hh" +#include + +using namespace std; +using namespace TheISA; +using namespace ThePipeline; + +InOrderCPU::TickEvent::TickEvent(InOrderCPU *c) + : Event(CPU_Tick_Pri), cpu(c) +{ } + + +void +InOrderCPU::TickEvent::process() +{ + cpu->tick(); +} + + +const char * +InOrderCPU::TickEvent::description() +{ + return "InOrderCPU tick event"; +} + +InOrderCPU::CPUEvent::CPUEvent(InOrderCPU *_cpu, CPUEventType e_type, + Fault fault, unsigned _tid, unsigned _vpe) + : Event(CPU_Tick_Pri), cpu(_cpu) +{ + setEvent(e_type, fault, _tid, _vpe); +} + +void +InOrderCPU::CPUEvent::process() +{ + switch (cpuEventType) + { + case ActivateThread: + cpu->activateThread(tid); + break; + + //@TODO: Consider Implementing "Suspend Thread" as Separate from Deallocate + case SuspendThread: // Suspend & Deallocate are same for now. + //cpu->suspendThread(tid); + //break; + case DeallocateThread: + cpu->deallocateThread(tid); + break; + + case EnableVPEs: + cpu->enableVPEs(vpe); + break; + + case DisableVPEs: + cpu->disableVPEs(tid, vpe); + break; + + case EnableThreads: + cpu->enableThreads(vpe); + break; + + case DisableThreads: + cpu->disableThreads(tid, vpe); + break; + + case Trap: + cpu->trapCPU(fault, tid); + break; + + default: + fatal("Unrecognized Event Type %d", cpuEventType); + } + + cpu->cpuEventRemoveList.push(this); +} + +const char * +InOrderCPU::CPUEvent::description() +{ + return "InOrderCPU event"; +} + +void +InOrderCPU::CPUEvent::scheduleEvent(int delay) +{ + if (squashed()) + mainEventQueue.reschedule(this,curTick + cpu->ticks(delay)); + else if (!scheduled()) + mainEventQueue.schedule(this,curTick + cpu->ticks(delay)); +} + +void +InOrderCPU::CPUEvent::unscheduleEvent() +{ + if (scheduled()) + squash(); +} + +InOrderCPU::InOrderCPU(Params *params) + : BaseCPU(params), + cpu_id(params->cpu_id), + tickEvent(this), + miscRegFile(this), + timeBuffer(2 , 2), + removeInstsThisCycle(false), + activityRec(params->name, NumStages, 10, params->activity), + switchCount(0), + deferRegistration(false/*params->deferRegistration*/), + stageTracing(params->stageTracing), + numThreads(params->numThreads), + numVirtProcs(1) +{ + cpu_params = params; + + resPool = new ResourcePool(this, params); +// resPool->init(); + + coreType = "default"; // eventually get this from params + + _status = Idle; + + // Resize for Multithreading CPUs + thread.resize(numThreads); + + int active_threads = params->workload.size(); + + if (active_threads > MaxThreads) { + panic("Workload Size too large. Increase the 'MaxThreads'" + "in your InOrder implementation or " + "edit your workload size."); + } + + // Bind the fetch & data ports from the resource pool. + fetchPortIdx = resPool->getPortIdx(params->fetchMemPort); + if (fetchPortIdx == 0) { + warn("Unable to find port to fetch instructions from.\n"); + } + + dataPortIdx = resPool->getPortIdx(params->dataMemPort); + if (dataPortIdx == 0) { + warn("Unable to find port for data.\n"); + } + + + /* Use this port to for syscall emulation writes to memory. */ + //Port *mem_port = NULL; + //TranslatingPort *trans_port = NULL; + + for (int i = 0; i < numThreads; ++i) { + if (i < params->workload.size()) { + DPRINTF(InOrderCPU, "Workload[%i] process is %#x", + i, this->thread[i]); + this->thread[i] = new Thread(this, i, params->workload[i], + i); + + // Start thread's off in "Suspended" status + this->thread[i]->setStatus(ThreadContext::Suspended); + + } else { + //Allocate Empty thread so M5 can use later + //when scheduling threads to CPU + Process* dummy_proc = params->workload[0]; //LiveProcess::createDummy(); + this->thread[i] = new Thread(this, i, dummy_proc, i); + + // Set Up Syscall Emulation Port + //this->thread[i]->setMemPort(trans_port); + } + + // Setup the TC that will serve as the interface to the threads/CPU. + InOrderThreadContext *tc = new InOrderThreadContext; + tc->cpu = this; + tc->thread = this->thread[i]; + + // Give the thread the TC. + thread[i]->tc = tc; + thread[i]->setFuncExeInst(0); + globalSeqNum[i] = 1; + + // Add the TC to the CPU's list of TC's. + this->threadContexts.push_back(tc); + } + + // Initialize TimeBuffer Stage Queues + // For now just have these time buffers be pretty big. + // @note: This could be statically allocated but changes + // would have to be made to the standard time buffer class. + for (int stNum=0; stNum < NumStages - 1; stNum++) { + stageQueue[stNum] = new StageQueue(NumStages, NumStages); + } + + + // Set Up Pipeline Stages + for (int stNum=0; stNum < NumStages; stNum++) { + if (stNum == 0) + pipelineStage[stNum] = new FirstStage(params, stNum); + else + pipelineStage[stNum] = new PipelineStage(params, stNum); + + pipelineStage[stNum]->setCPU(this); + pipelineStage[stNum]->setActiveThreads(&activeThreads); + pipelineStage[stNum]->setTimeBuffer(&timeBuffer); + + // Take Care of 1st/Nth stages + if (stNum > 0) + pipelineStage[stNum]->setPrevStageQueue(stageQueue[stNum - 1]); + if (stNum < NumStages - 2) + pipelineStage[stNum]->setNextStageQueue(stageQueue[stNum + 1]); + } + + // Initialize thread specific variables + for (int tid=0; tid < numThreads; tid++) { + archRegDepMap[tid].setCPU(this); + + nonSpecInstActive[tid] = false; + nonSpecSeqNum[tid] = 0; + + squashSeqNum[tid] = MaxAddr; + lastSquashCycle[tid] = 0; + + intRegFile[tid].clear(); + floatRegFile[tid].clear(); + } + + // Update miscRegFile if necessary + if (numThreads > 1) { + miscRegFile.expandForMultithreading(numThreads, numVirtProcs); + } + + miscRegFile.clear(); + + lastRunningCycle = curTick; + contextSwitch = false; + + // Define dummy instructions and resource requests to be used. + DynInstPtr dummyBufferInst = new InOrderDynInst(this, NULL, 0, 0); + dummyReq = new ResourceRequest(NULL, NULL, 0, 0, 0, 0); + + // Reset CPU to reset state. +#if FULL_SYSTEM + Fault resetFault = new ResetFault(); + resetFault->invoke(tcBase()); +#else + reset(); +#endif + + // Schedule First Tick Event, CPU will reschedule itself from here on out. + scheduleTickEvent(0); +} + + +void +InOrderCPU::regStats() +{ + /* Register the Resource Pool's stats here.*/ + resPool->regStats(); + + /* Register any of the InOrderCPU's stats here.*/ + timesIdled + .name(name() + ".timesIdled") + .desc("Number of times that the entire CPU went into an idle state and" + " unscheduled itself") + .prereq(timesIdled); + + idleCycles + .name(name() + ".idleCycles") + .desc("Total number of cycles that the CPU has spent unscheduled due " + "to idling") + .prereq(idleCycles); + + threadCycles + .init(numThreads) + .name(name() + ".threadCycles") + .desc("Total Number of Cycles A Thread Was Active in CPU (Per-Thread)"); + + smtCycles + .name(name() + ".smtCycles") + .desc("Total number of cycles that the CPU was simultaneous multithreading.(SMT)"); + + committedInsts + .init(numThreads) + .name(name() + ".committedInsts") + .desc("Number of Instructions Simulated (Per-Thread)"); + + smtCommittedInsts + .init(numThreads) + .name(name() + ".smtCommittedInsts") + .desc("Number of SMT Instructions Simulated (Per-Thread)"); + + totalCommittedInsts + .name(name() + ".committedInsts_total") + .desc("Number of Instructions Simulated (Total)"); + + cpi + .name(name() + ".cpi") + .desc("CPI: Cycles Per Instruction (Per-Thread)") + .precision(6); + cpi = threadCycles / committedInsts; + + smtCpi + .name(name() + ".smt_cpi") + .desc("CPI: Total SMT-CPI") + .precision(6); + smtCpi = smtCycles / smtCommittedInsts; + + totalCpi + .name(name() + ".cpi_total") + .desc("CPI: Total CPI of All Threads") + .precision(6); + totalCpi = simTicks / totalCommittedInsts; + + ipc + .name(name() + ".ipc") + .desc("IPC: Instructions Per Cycle (Per-Thread)") + .precision(6); + ipc = committedInsts / threadCycles; + + smtIpc + .name(name() + ".smt_ipc") + .desc("IPC: Total SMT-IPC") + .precision(6); + smtIpc = smtCommittedInsts / smtCycles; + + totalIpc + .name(name() + ".ipc_total") + .desc("IPC: Total IPC of All Threads") + .precision(6); + totalIpc = totalCommittedInsts / simTicks; + + BaseCPU::regStats(); +} + + +void +InOrderCPU::tick() +{ + DPRINTF(InOrderCPU, "\n\nInOrderCPU: Ticking main, InOrderCPU.\n"); + + ++numCycles; + + //Tick each of the stages + for (int stNum=NumStages - 1; stNum >= 0 ; stNum--) { + pipelineStage[stNum]->tick(); + } + + // Now advance the time buffers one tick + timeBuffer.advance(); + for (int sqNum=0; sqNum < NumStages - 1; sqNum++) { + stageQueue[sqNum]->advance(); + } + activityRec.advance(); + + // Any squashed requests, events, or insts then remove them now + cleanUpRemovedReqs(); + cleanUpRemovedEvents(); + cleanUpRemovedInsts(); + + // Re-schedule CPU for this cycle + if (!tickEvent.scheduled()) { + if (_status == SwitchedOut) { + // increment stat + lastRunningCycle = curTick; + } else if (!activityRec.active()) { + DPRINTF(InOrderCPU, "sleeping CPU.\n"); + lastRunningCycle = curTick; + timesIdled++; + } else { + //Tick next_tick = curTick + cycles(1); + //tickEvent.schedule(next_tick); + mainEventQueue.schedule(&tickEvent, nextCycle(curTick + 1)); + DPRINTF(InOrderCPU, "Scheduled CPU for next tick @ %i.\n", nextCycle() + curTick); + } + } + + tickThreadStats(); + updateThreadPriority(); +} + + +void +InOrderCPU::init() +{ + if (!deferRegistration) { + registerThreadContexts(); + } + + // Set inSyscall so that the CPU doesn't squash when initially + // setting up registers. + for (int i = 0; i < number_of_threads; ++i) + thread[i]->inSyscall = true; + + for (int tid=0; tid < number_of_threads; tid++) { + + ThreadContext *src_tc = thread[tid]->getTC(); + + // Threads start in the Suspended State + if (src_tc->status() != ThreadContext::Suspended) { + continue; + } + + } + + // Clear inSyscall. + for (int i = 0; i < number_of_threads; ++i) + thread[i]->inSyscall = false; + + // Call Initializiation Routine for Resource Pool + resPool->init(); +} + +void +InOrderCPU::readFunctional(Addr addr, uint32_t &buffer) +{ + tcBase()->getMemPort()->readBlob(addr, (uint8_t*)&buffer, sizeof(uint32_t)); + buffer = gtoh(buffer); +} + +void +InOrderCPU::reset() +{ + miscRegFile.reset(coreType, numThreads, numVirtProcs, dynamic_cast(this)); +} + +Port* +InOrderCPU::getPort(const std::string &if_name, int idx) +{ + return resPool->getPort(if_name, idx); +} + +void +InOrderCPU::trap(Fault fault, unsigned tid, int delay) +{ + scheduleCpuEvent(Trap, fault, tid, 0/*vpe*/, delay); +} + +void +InOrderCPU::trapCPU(Fault fault, unsigned tid) +{ + fault->invoke(tcBase(tid)); +} + +void +InOrderCPU::scheduleCpuEvent(CPUEventType c_event, Fault fault, + unsigned tid, unsigned vpe, unsigned delay) +{ + CPUEvent *cpu_event = new CPUEvent(this, c_event, fault, tid, vpe); + + if (delay >= 0) { + DPRINTF(InOrderCPU, "Scheduling CPU Event Type #%i for cycle %i.\n", + c_event, curTick + delay); + mainEventQueue.schedule(cpu_event,curTick + delay); + } else { + cpu_event->process(); + cpuEventRemoveList.push(cpu_event); + } + + // Broadcast event to the Resource Pool + DynInstPtr dummy_inst = new InOrderDynInst(this, NULL, getNextEventNum(), tid); + resPool->scheduleEvent(c_event, dummy_inst, 0, 0, tid); +} + +inline bool +InOrderCPU::isThreadActive(unsigned tid) +{ + list::iterator isActive = std::find( + activeThreads.begin(), activeThreads.end(), tid); + + return (isActive != activeThreads.end()); +} + + +void +InOrderCPU::activateThread(unsigned tid) +{ + if (!isThreadActive(tid)) { + DPRINTF(InOrderCPU, "Adding Thread %i to active threads list in CPU.\n", + tid); + activeThreads.push_back(tid); + + wakeCPU(); + } +} + +void +InOrderCPU::deactivateThread(unsigned tid) +{ + DPRINTF(InOrderCPU, "[tid:%i]: Calling deactivate thread.\n", tid); + + if (isThreadActive(tid)) { + DPRINTF(InOrderCPU,"[tid:%i]: Removing from active threads list\n", + tid); + list::iterator thread_it = std::find(activeThreads.begin(), + activeThreads.end(), tid); + + removePipelineStalls(*thread_it); + + //@TODO: change stage status' to Idle? + + activeThreads.erase(thread_it); + } +} + +void +InOrderCPU::removePipelineStalls(unsigned tid) +{ + DPRINTF(InOrderCPU,"[tid:%i]: Removing all pipeline stalls\n", + tid); + + for (int stNum = 0; stNum < NumStages ; stNum++) { + pipelineStage[stNum]->removeStalls(tid); + } + +} +bool +InOrderCPU::isThreadInCPU(unsigned tid) +{ + list::iterator isCurrent = std::find( + currentThreads.begin(), currentThreads.end(), tid); + + return (isCurrent != currentThreads.end()); +} + +void +InOrderCPU::addToCurrentThreads(unsigned tid) +{ + if (!isThreadInCPU(tid)) { + DPRINTF(InOrderCPU, "Adding Thread %i to current threads list in CPU.\n", + tid); + currentThreads.push_back(tid); + } +} + +void +InOrderCPU::removeFromCurrentThreads(unsigned tid) +{ + if (isThreadInCPU(tid)) { + DPRINTF(InOrderCPU, "Adding Thread %i to current threads list in CPU.\n", + tid); + list::iterator isCurrent = std::find( + currentThreads.begin(), currentThreads.end(), tid); + currentThreads.erase(isCurrent); + } +} + +bool +InOrderCPU::isThreadSuspended(unsigned tid) +{ + list::iterator isSuspended = std::find( + suspendedThreads.begin(), suspendedThreads.end(), tid); + + return (isSuspended!= suspendedThreads.end()); +} + +void +InOrderCPU::enableVirtProcElement(unsigned vpe) +{ + DPRINTF(InOrderCPU, "[vpe:%i]: Scheduling " + "Enabling of concurrent virtual processor execution", + vpe); + + scheduleCpuEvent(EnableVPEs, NoFault, 0/*tid*/, vpe); +} + +void +InOrderCPU::enableVPEs(unsigned vpe) +{ + DPRINTF(InOrderCPU, "[vpe:%i]: Enabling Concurrent Execution " + "virtual processors %i", vpe); + + list::iterator thread_it = currentThreads.begin(); + + while (thread_it != currentThreads.end()) { + if (!isThreadSuspended(*thread_it)) { + activateThread(*thread_it); + } + thread_it++; + } +} + +void +InOrderCPU::disableVirtProcElement(unsigned tid, unsigned vpe) +{ + DPRINTF(InOrderCPU, "[vpe:%i]: Scheduling " + "Disabling of concurrent virtual processor execution", + vpe); + + scheduleCpuEvent(DisableVPEs, NoFault, 0/*tid*/, vpe); +} + +void +InOrderCPU::disableVPEs(unsigned tid, unsigned vpe) +{ + DPRINTF(InOrderCPU, "[vpe:%i]: Disabling Concurrent Execution of " + "virtual processors %i", vpe); + + unsigned base_vpe = TheISA::getVirtProcNum(tcBase(tid)); + + list::iterator thread_it = activeThreads.begin(); + + std::vector::iterator> removeList; + + while (thread_it != activeThreads.end()) { + if (base_vpe != vpe) { + removeList.push_back(thread_it); + } + thread_it++; + } + + for (int i = 0; i < removeList.size(); i++) { + activeThreads.erase(removeList[i]); + } +} + +void +InOrderCPU::enableMultiThreading(unsigned vpe) +{ + // Schedule event to take place at end of cycle + DPRINTF(InOrderCPU, "[vpe:%i]: Scheduling Enable Multithreading on " + "virtual processor %i", vpe); + + scheduleCpuEvent(EnableThreads, NoFault, 0/*tid*/, vpe); +} + +void +InOrderCPU::enableThreads(unsigned vpe) +{ + DPRINTF(InOrderCPU, "[vpe:%i]: Enabling Multithreading on " + "virtual processor %i", vpe); + + list::iterator thread_it = currentThreads.begin(); + + while (thread_it != currentThreads.end()) { + if (TheISA::getVirtProcNum(tcBase(*thread_it)) == vpe) { + if (!isThreadSuspended(*thread_it)) { + activateThread(*thread_it); + } + } + thread_it++; + } +} +void +InOrderCPU::disableMultiThreading(unsigned tid, unsigned vpe) +{ + // Schedule event to take place at end of cycle + DPRINTF(InOrderCPU, "[tid:%i]: Scheduling Disable Multithreading on " + "virtual processor %i", tid, vpe); + + scheduleCpuEvent(DisableThreads, NoFault, tid, vpe); +} + +void +InOrderCPU::disableThreads(unsigned tid, unsigned vpe) +{ + DPRINTF(InOrderCPU, "[tid:%i]: Disabling Multithreading on " + "virtual processor %i", tid, vpe); + + list::iterator thread_it = activeThreads.begin(); + + std::vector::iterator> removeList; + + while (thread_it != activeThreads.end()) { + if (TheISA::getVirtProcNum(tcBase(*thread_it)) == vpe) { + removeList.push_back(thread_it); + } + thread_it++; + } + + for (int i = 0; i < removeList.size(); i++) { + activeThreads.erase(removeList[i]); + } +} + +void +InOrderCPU::updateThreadPriority() +{ + if (activeThreads.size() > 1) + { + //DEFAULT TO ROUND ROBIN SCHEME + //e.g. Move highest priority to end of thread list + list::iterator list_begin = activeThreads.begin(); + list::iterator list_end = activeThreads.end(); + + unsigned high_thread = *list_begin; + + activeThreads.erase(list_begin); + + activeThreads.push_back(high_thread); + } +} + +inline void +InOrderCPU::tickThreadStats() +{ + /** Keep track of cycles that each thread is active */ + list::iterator thread_it = activeThreads.begin(); + while (thread_it != activeThreads.end()) { + threadCycles[*thread_it]++; + thread_it++; + } + + // Keep track of cycles where SMT is active + if (activeThreads.size() > 1) { + smtCycles++; + } +} + +void +InOrderCPU::activateContext(unsigned tid, int delay) +{ + DPRINTF(InOrderCPU,"[tid:%i]: Activating ...\n", tid); + + scheduleCpuEvent(ActivateThread, NoFault, tid, 0/*vpe*/, delay); + + // Be sure to signal that there's some activity so the CPU doesn't + // deschedule itself. + activityRec.activity(); + + _status = Running; +} + + +void +InOrderCPU::suspendContext(unsigned tid, int delay) +{ + scheduleCpuEvent(SuspendThread, NoFault, tid, 0/*vpe*/, delay); + //_status = Idle; +} + +void +InOrderCPU::suspendThread(unsigned tid) +{ + DPRINTF(InOrderCPU,"[tid: %i]: Suspended ...\n", tid); + deactivateThread(tid); +} + +void +InOrderCPU::deallocateContext(unsigned tid, int delay) +{ + scheduleCpuEvent(DeallocateThread, NoFault, tid, 0/*vpe*/, delay); +} + +void +InOrderCPU::deallocateThread(unsigned tid) +{ + DPRINTF(InOrderCPU,"[tid:%i]: Deallocating ...", tid); + + //removeThread(tid); + + removeFromCurrentThreads(tid); + + deactivateThread(tid); + + squashThreadInPipeline(tid); +} + +void +InOrderCPU::squashThreadInPipeline(unsigned tid) +{ + //Squash all instructions in each stage + for (int stNum=NumStages - 1; stNum >= 0 ; stNum--) { + pipelineStage[stNum]->squash(0 /*seq_num*/, tid); + } +} + +void +InOrderCPU::haltContext(unsigned tid, int delay) +{ + DPRINTF(InOrderCPU, "[tid:%i]: Halt context called.\n", tid); + + // Halt is same thing as deallocate for now + // @TODO: Differentiate between halt & deallocate in the CPU + // model + deallocateContext(tid, delay); +} + +void +InOrderCPU::insertThread(unsigned tid) +{ + panic("Unimplemented Function\n."); +} + +void +InOrderCPU::removeThread(unsigned tid) +{ + DPRINTF(InOrderCPU, "Removing Thread %i from CPU.\n", tid); + + /** Broadcast to CPU resources*/ +} + +void +InOrderCPU::activateWhenReady(int tid) +{ + panic("Unimplemented Function\n."); +} + + +void +InOrderCPU::signalSwitched() +{ + panic("Unimplemented Function\n."); +} + + +void +InOrderCPU::takeOverFrom(BaseCPU *oldCPU) +{ + panic("Take Over From Another CPU\n."); +} + +uint64_t +InOrderCPU::readPC(unsigned tid) +{ + return PC[tid]; +} + + +void +InOrderCPU::setPC(Addr new_PC, unsigned tid) +{ + PC[tid] = new_PC; +} + + +uint64_t +InOrderCPU::readNextPC(unsigned tid) +{ + return nextPC[tid]; +} + + +void +InOrderCPU::setNextPC(uint64_t new_NPC, unsigned tid) +{ + nextPC[tid] = new_NPC; +} + + +uint64_t +InOrderCPU::readNextNPC(unsigned tid) +{ + return nextNPC[tid]; +} + + +void +InOrderCPU::setNextNPC(uint64_t new_NNPC, unsigned tid) +{ + nextNPC[tid] = new_NNPC; +} + +uint64_t +InOrderCPU::readIntReg(int reg_idx, unsigned tid) +{ + return intRegFile[tid].readReg(reg_idx); +} + +FloatReg +InOrderCPU::readFloatReg(int reg_idx, unsigned tid, int width) +{ + + return floatRegFile[tid].readReg(reg_idx, width); +} + +FloatRegBits +InOrderCPU::readFloatRegBits(int reg_idx, unsigned tid, int width) +{; + return floatRegFile[tid].readRegBits(reg_idx, width); +} + +void +InOrderCPU::setIntReg(int reg_idx, uint64_t val, unsigned tid) +{ + intRegFile[tid].setReg(reg_idx, val); +} + + +void +InOrderCPU::setFloatReg(int reg_idx, FloatReg val, unsigned tid, int width) +{ + floatRegFile[tid].setReg(reg_idx, val, width); +} + + +void +InOrderCPU::setFloatRegBits(int reg_idx, FloatRegBits val, unsigned tid, int width) +{ + floatRegFile[tid].setRegBits(reg_idx, val, width); +} + +uint64_t +InOrderCPU::readRegOtherThread(unsigned reg_idx, unsigned tid) +{ + // If Default value is set, then retrieve target thread + if (tid == -1) { + tid = TheISA::getTargetThread(tcBase(tid)); + } + + if (reg_idx < FP_Base_DepTag) { // Integer Register File + return readIntReg(reg_idx, tid); + } else if (reg_idx < Ctrl_Base_DepTag) { // Float Register File + reg_idx -= FP_Base_DepTag; + return readFloatRegBits(reg_idx, tid); + } else { + reg_idx -= Ctrl_Base_DepTag; + return readMiscReg(reg_idx, tid); // Misc. Register File + } +} +void +InOrderCPU::setRegOtherThread(unsigned reg_idx, const MiscReg &val, unsigned tid) +{ + // If Default value is set, then retrieve target thread + if (tid == -1) { + tid = TheISA::getTargetThread(tcBase(tid)); + } + + if (reg_idx < FP_Base_DepTag) { // Integer Register File + setIntReg(reg_idx, val, tid); + } else if (reg_idx < Ctrl_Base_DepTag) { // Float Register File + reg_idx -= FP_Base_DepTag; + setFloatRegBits(reg_idx, val, tid); + } else { + reg_idx -= Ctrl_Base_DepTag; + setMiscReg(reg_idx, val, tid); // Misc. Register File + } +} + +MiscReg +InOrderCPU::readMiscRegNoEffect(int misc_reg, unsigned tid) +{ + return miscRegFile.readRegNoEffect(misc_reg, tid); +} + +MiscReg +InOrderCPU::readMiscReg(int misc_reg, unsigned tid) +{ + return miscRegFile.readReg(misc_reg, tcBase(tid), tid); +} + +void +InOrderCPU::setMiscRegNoEffect(int misc_reg, const MiscReg &val, unsigned tid) +{ + miscRegFile.setRegNoEffect(misc_reg, val, tid); +} + +void +InOrderCPU::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid) +{ + miscRegFile.setReg(misc_reg, val, tcBase(tid), tid); +} + + +InOrderCPU::ListIt +InOrderCPU::addInst(DynInstPtr &inst) +{ + int tid = inst->readTid(); + + instList[tid].push_back(inst); + + return --(instList[tid].end()); +} + +void +InOrderCPU::instDone(DynInstPtr inst, unsigned tid) +{ + // Set the CPU's PCs - This contributes to the precise state of the CPU which can be used + // when restoring a thread to the CPU after a fork or after an exception + // @TODO: Set-Up Grad-Info/Committed-Info to let ThreadState know if it's a branch or not + setPC(inst->readPC(), tid); + setNextPC(inst->readNextPC(), tid); + setNextNPC(inst->readNextNPC(), tid); + + // Finalize Trace Data For Instruction + if (inst->traceData) { + //inst->traceData->setCycle(curTick); + inst->traceData->setFetchSeq(inst->seqNum); + //inst->traceData->setCPSeq(cpu->tcBase(tid)->numInst); + inst->traceData->dump(); + delete inst->traceData; + inst->traceData = NULL; + } + + // Set Last Graduated Instruction In Thread State + //thread[tid]->lastGradInst = inst; + + // Increment thread-state's instruction count + thread[tid]->numInst++; + + // Increment thread-state's instruction stats + thread[tid]->numInsts++; + + // Count committed insts per thread stats + committedInsts[tid]++; + + // Count total insts committed stat + totalCommittedInsts++; + + // Count SMT-committed insts per thread stat + if (numActiveThreads() > 1) { + smtCommittedInsts[tid]++; + } + + // Check for instruction-count-based events. + comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst); + + // Broadcast to other resources an instruction + // has been completed + resPool->scheduleEvent((CPUEventType)ResourcePool::InstGraduated, inst, tid); + + // Finally, remove instruction from CPU + removeInst(inst); +} + +void +InOrderCPU::addToRemoveList(DynInstPtr &inst) +{ + removeInstsThisCycle = true; + + removeList.push(inst->getInstListIt()); +} + +void +InOrderCPU::removeInst(DynInstPtr &inst) +{ + DPRINTF(InOrderCPU, "Removing graduated instruction [tid:%i] PC %#x " + "[sn:%lli]\n", + inst->threadNumber, inst->readPC(), inst->seqNum); + + removeInstsThisCycle = true; + + // Remove the instruction. + removeList.push(inst->getInstListIt()); +} + +void +InOrderCPU::removeInstsUntil(const InstSeqNum &seq_num, + unsigned tid) +{ + //assert(!instList[tid].empty()); + + removeInstsThisCycle = true; + + ListIt inst_iter = instList[tid].end(); + + inst_iter--; + + DPRINTF(InOrderCPU, "Deleting instructions from CPU instruction " + "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n", + tid, seq_num, (*inst_iter)->seqNum); + + while ((*inst_iter)->seqNum > seq_num) { + + bool break_loop = (inst_iter == instList[tid].begin()); + + squashInstIt(inst_iter, tid); + + inst_iter--; + + if (break_loop) + break; + } +} + + +inline void +InOrderCPU::squashInstIt(const ListIt &instIt, const unsigned &tid) +{ + if ((*instIt)->threadNumber == tid) { + DPRINTF(InOrderCPU, "Squashing instruction, " + "[tid:%i] [sn:%lli] PC %#x\n", + (*instIt)->threadNumber, + (*instIt)->seqNum, + (*instIt)->readPC()); + + (*instIt)->setSquashed(); + + removeList.push(instIt); + } +} + + +void +InOrderCPU::cleanUpRemovedInsts() +{ + while (!removeList.empty()) { + DPRINTF(InOrderCPU, "Removing instruction, " + "[tid:%i] [sn:%lli] PC %#x\n", + (*removeList.front())->threadNumber, + (*removeList.front())->seqNum, + (*removeList.front())->readPC()); + + DynInstPtr inst = *removeList.front(); + int tid = inst->threadNumber; + + // Make Sure Resource Schedule Is Emptied Out + ThePipeline::ResSchedule *inst_sched = &inst->resSched; + while (!inst_sched->empty()) { + ThePipeline::ScheduleEntry* sch_entry = inst_sched->top(); + inst_sched->pop(); + delete sch_entry; + } + + // Remove From Register Dependency Map, If Necessary + archRegDepMap[(*removeList.front())->threadNumber]. + remove((*removeList.front())); + + + // Clear if Non-Speculative + if (inst->staticInst && + inst->seqNum == nonSpecSeqNum[tid] && + nonSpecInstActive[tid] == true) { + nonSpecInstActive[tid] = false; + } + + instList[tid].erase(removeList.front()); + + removeList.pop(); + + DPRINTF(RefCount, "pop from remove list: [sn:%i]: Refcount = %i.\n", + inst->seqNum, + 0/*inst->curCount()*/); + + } + + removeInstsThisCycle = false; +} + +void +InOrderCPU::cleanUpRemovedReqs() +{ + while (!reqRemoveList.empty()) { + ResourceRequest *res_req = reqRemoveList.front(); + + DPRINTF(RefCount, "[tid:%i]: Removing Request, " + "[sn:%lli] [slot:%i] [stage_num:%i] [res:%s] [refcount:%i].\n", + res_req->inst->threadNumber, + res_req->inst->seqNum, + res_req->getSlot(), + res_req->getStageNum(), + res_req->res->name(), + 0/*res_req->inst->curCount()*/); + + reqRemoveList.pop(); + + delete res_req; + + DPRINTF(RefCount, "after remove request: [sn:%i]: Refcount = %i.\n", + res_req->inst->seqNum, + 0/*res_req->inst->curCount()*/); + } +} + +void +InOrderCPU::cleanUpRemovedEvents() +{ + while (!cpuEventRemoveList.empty()) { + Event *cpu_event = cpuEventRemoveList.front(); + cpuEventRemoveList.pop(); + delete cpu_event; + } +} + +/* + +void +InOrderCPU::removeAllInsts() +{ + instList.clear(); +} +*/ + +void +InOrderCPU::dumpInsts() +{ + int num = 0; + + ListIt inst_list_it = instList[0].begin(); + + cprintf("Dumping Instruction List\n"); + + while (inst_list_it != instList[0].end()) { + cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" + "Squashed:%i\n\n", + num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber, + (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(), + (*inst_list_it)->isSquashed()); + inst_list_it++; + ++num; + } +} +/* + +void +InOrderCPU::wakeDependents(DynInstPtr &inst) +{ + iew.wakeDependents(inst); +} +*/ + +void +InOrderCPU::wakeCPU() +{ + if (/*activityRec.active() || */tickEvent.scheduled()) { + DPRINTF(Activity, "CPU already running.\n"); + return; + } + + DPRINTF(Activity, "Waking up CPU\n"); + + //idleCycles += (curTick - 1) - lastRunningCycle; + + mainEventQueue.schedule(&tickEvent, curTick); +} + +void +InOrderCPU::syscall(int64_t callnum, int tid) +{ + DPRINTF(InOrderCPU, "[tid:%i] Executing syscall().\n\n", tid); + + DPRINTF(Activity,"Activity: syscall() called.\n"); + + // Temporarily increase this by one to account for the syscall + // instruction. + ++(this->thread[tid]->funcExeInst); + + // Execute the actual syscall. + this->thread[tid]->syscall(callnum); + + // Decrease funcExeInst by one as the normal commit will handle + // incrementing it. + --(this->thread[tid]->funcExeInst); + + // Clear Non-Speculative Block Variable + nonSpecInstActive[tid] = false; +} + +IntReg +InOrderCPU::getSyscallArg(int idx, int tid) +{ + return readIntReg(ArgumentReg0 + idx, tid); +} + +void +InOrderCPU::setSyscallArg(int idx, IntReg val, int tid) +{ + setIntReg(ArgumentReg0 + idx, val, tid); +} + +void +InOrderCPU::setSyscallReturn(SyscallReturn return_value, int tid) +{ + if (return_value.successful()) { + // no error + setIntReg(SyscallSuccessReg, 0, tid); + setIntReg(ReturnValueReg, return_value.value(), tid); + } else { + // got an error, return details + setIntReg(SyscallSuccessReg, (IntReg) -1, tid); + setIntReg(ReturnValueReg, -return_value.value(), tid); + } +} + +Fault +InOrderCPU::read(DynInstPtr inst) +{ + Resource *mem_res = resPool->getResource(dataPortIdx); + return mem_res->doDataAccess(inst); +} + +Fault +InOrderCPU::write(DynInstPtr inst) +{ + Resource *mem_res = resPool->getResource(dataPortIdx); + return mem_res->doDataAccess(inst); +} diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh new file mode 100644 index 000000000..cd1eb6f92 --- /dev/null +++ b/src/cpu/inorder/cpu.hh @@ -0,0 +1,730 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __CPU_INORDER_CPU_HH__ +#define __CPU_INORDER_CPU_HH__ + +#include +#include +#include +#include +#include + +#include "arch/isa_traits.hh" +#include "base/statistics.hh" +#include "base/timebuf.hh" +#include "config/full_system.hh" +#include "cpu/activity.hh" +#include "cpu/base.hh" +#include "cpu/simple_thread.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/pipeline_stage.hh" +#include "cpu/inorder/thread_state.hh" +#include "cpu/inorder/reg_dep_map.hh" +#include "cpu/o3/dep_graph.hh" +#include "cpu/o3/rename_map.hh" +#include "mem/packet.hh" +#include "mem/port.hh" +#include "mem/request.hh" +#include "sim/eventq.hh" +#include "sim/process.hh" + +class ThreadContext; +class MemInterface; +class MemObject; +class Process; +class ResourcePool; + +class InOrderCPU : public BaseCPU +{ + + protected: + typedef ThePipeline::Params Params; + typedef InOrderThreadState Thread; + + //ISA TypeDefs + typedef TheISA::IntReg IntReg; + typedef TheISA::FloatReg FloatReg; + typedef TheISA::FloatRegBits FloatRegBits; + typedef TheISA::MiscReg MiscReg; + typedef TheISA::RegFile RegFile; + typedef SimpleRenameMap RenameMap; + + //DynInstPtr TypeDefs + typedef ThePipeline::DynInstPtr DynInstPtr; + typedef std::list::iterator ListIt; + + //TimeBuffer TypeDefs + typedef TimeBuffer StageQueue; + + friend class Resource; + + public: + /** Constructs a CPU with the given parameters. */ + InOrderCPU(Params *params); + + /** CPU ID */ + int cpu_id; + + /** Type of core that this is */ + std::string coreType; + + int readCpuId() { return cpu_id; } + + void setCpuId(int val) { cpu_id = val; } + + Params *cpu_params; + + TheISA::ITB * itb; + TheISA::DTB * dtb; + + public: + enum Status { + Running, + Idle, + Halted, + Blocked, + SwitchedOut + }; + + /** Overall CPU status. */ + Status _status; + + private: + /** Define TickEvent for the CPU */ + class TickEvent : public Event + { + private: + /** Pointer to the CPU. */ + InOrderCPU *cpu; + + public: + /** Constructs a tick event. */ + TickEvent(InOrderCPU *c); + + /** Processes a tick event, calling tick() on the CPU. */ + void process(); + + /** Returns the description of the tick event. */ + const char *description(); + }; + + /** The tick event used for scheduling CPU ticks. */ + TickEvent tickEvent; + + /** Schedule tick event, regardless of its current state. */ + void scheduleTickEvent(int delay) + { + if (tickEvent.squashed()) + mainEventQueue.reschedule(&tickEvent, nextCycle(curTick + ticks(delay))); + else if (!tickEvent.scheduled()) + mainEventQueue.schedule(&tickEvent, nextCycle(curTick + ticks(delay))); + } + + /** Unschedule tick event, regardless of its current state. */ + void unscheduleTickEvent() + { + if (tickEvent.scheduled()) + tickEvent.squash(); + } + + public: + // List of Events That can be scheduled from + // within the CPU. + // NOTE(1): The Resource Pool also uses this event list + // to schedule events broadcast to all resources interfaces + // NOTE(2): CPU Events usually need to schedule a corresponding resource + // pool event. + enum CPUEventType { + ActivateThread, + DeallocateThread, + SuspendThread, + DisableThreads, + EnableThreads, + DisableVPEs, + EnableVPEs, + Trap, + InstGraduated, + SquashAll, + UpdatePCs, + NumCPUEvents + }; + + /** Define CPU Event */ + class CPUEvent : public Event + { + protected: + InOrderCPU *cpu; + + public: + CPUEventType cpuEventType; + unsigned tid; + unsigned vpe; + Fault fault; + + public: + /** Constructs a CPU event. */ + CPUEvent(InOrderCPU *_cpu, CPUEventType e_type, Fault fault, + unsigned _tid, unsigned _vpe); + + /** Set Type of Event To Be Scheduled */ + void setEvent(CPUEventType e_type, Fault _fault, unsigned _tid, unsigned _vpe) + { + fault = _fault; + cpuEventType = e_type; + tid = _tid; + vpe = _vpe; + } + + /** Processes a resource event. */ + virtual void process(); + + /** Returns the description of the resource event. */ + const char *description(); + + /** Schedule Event */ + void scheduleEvent(int delay); + + /** Unschedule This Event */ + void unscheduleEvent(); + }; + + /** Schedule a CPU Event */ + void scheduleCpuEvent(CPUEventType cpu_event, Fault fault, unsigned tid, + unsigned vpe, unsigned delay = 0); + + public: + /** Interface between the CPU and CPU resources. */ + ResourcePool *resPool; + + /** Instruction used to signify that there is no *real* instruction in buffer slot */ + DynInstPtr dummyBufferInst; + + /** Used by resources to signify a denied access to a resource. */ + ResourceRequest *dummyReq; + + /** Identifies the resource id that identifies a fetch + * access unit. + */ + unsigned fetchPortIdx; + + /** Identifies the resource id that identifies a data + * access unit. + */ + unsigned dataPortIdx; + + /** The Pipeline Stages for the CPU */ + PipelineStage *pipelineStage[ThePipeline::NumStages]; + + TheISA::IntReg PC[ThePipeline::MaxThreads]; + TheISA::IntReg nextPC[ThePipeline::MaxThreads]; + TheISA::IntReg nextNPC[ThePipeline::MaxThreads]; + + /** The Register File for the CPU */ + /** @TODO: This regFile wont be a sufficient solution for out-of-order, add register + * files as a resource in order to handle ths problem + */ + TheISA::IntRegFile intRegFile[ThePipeline::MaxThreads];; + TheISA::FloatRegFile floatRegFile[ThePipeline::MaxThreads];; + TheISA::MiscRegFile miscRegFile; + + /** Dependency Tracker for Integer & Floating Point Regs */ + RegDepMap archRegDepMap[ThePipeline::MaxThreads]; + + /** Global communication structure */ + TimeBuffer timeBuffer; + + /** Communication structure that sits in between pipeline stages */ + StageQueue *stageQueue[ThePipeline::NumStages-1]; + + public: + + /** Registers statistics. */ + void regStats(); + + /** Ticks CPU, calling tick() on each stage, and checking the overall + * activity to see if the CPU should deschedule itself. + */ + void tick(); + + /** Initialize the CPU */ + void init(); + + /** Reset State in the CPU */ + void reset(); + + /** Get a Memory Port */ + Port* getPort(const std::string &if_name, int idx = 0); + + /** trap() - sets up a trap event on the cpuTraps to handle given fault. + * trapCPU() - Traps to handle given fault + */ + void trap(Fault fault, unsigned tid, int delay = 0); + void trapCPU(Fault fault, unsigned tid); + + /** Setup CPU to insert a thread's context */ + void insertThread(unsigned tid); + + /** Remove all of a thread's context from CPU */ + void removeThread(unsigned tid); + + /** Add Thread to Active Threads List. */ + void activateContext(unsigned tid, int delay = 0); + void activateThread(unsigned tid); + + /** Remove Thread from Active Threads List */ + void suspendContext(unsigned tid, int delay = 0); + void suspendThread(unsigned tid); + + /** Remove Thread from Active Threads List && + * Remove Thread Context from CPU. + */ + void deallocateContext(unsigned tid, int delay = 0); + void deallocateThread(unsigned tid); + void deactivateThread(unsigned tid); + + /** Remove Thread from Active Threads List && + * Remove Thread Context from CPU. + */ + void haltContext(unsigned tid, int delay = 0); + + void removePipelineStalls(unsigned tid); + + void squashThreadInPipeline(unsigned tid); + + /// Notify the CPU to enable a virtual processor element. + virtual void enableVirtProcElement(unsigned vpe); + void enableVPEs(unsigned vpe); + + /// Notify the CPU to disable a virtual processor element. + virtual void disableVirtProcElement(unsigned tid, unsigned vpe); + void disableVPEs(unsigned tid, unsigned vpe); + + /// Notify the CPU that multithreading is enabled. + virtual void enableMultiThreading(unsigned vpe); + void enableThreads(unsigned vpe); + + /// Notify the CPU that multithreading is disabled. + virtual void disableMultiThreading(unsigned tid, unsigned vpe); + void disableThreads(unsigned tid, unsigned vpe); + + // Sets a thread-rescheduling condition. + void setThreadRescheduleCondition(uint32_t tid) + { + //@TODO: IMPLEMENT ME + } + + /** Activate a Thread When CPU Resources are Available. */ + void activateWhenReady(int tid); + + /** Add or Remove a Thread Context in the CPU. */ + void doContextSwitch(); + + /** Update The Order In Which We Process Threads. */ + void updateThreadPriority(); + + /** Switches a Pipeline Stage to Active. (Unused currently) */ + void switchToActive(int stage_idx) + { /*pipelineStage[stage_idx]->switchToActive();*/ } + + /** Switches out this CPU. (Unused currently) */ + //void switchOut(Sampler *sampler); + + /** Signals to this CPU that a stage has completed switching out. (Unused currently)*/ + void signalSwitched(); + + /** Takes over from another CPU. (Unused currently)*/ + void takeOverFrom(BaseCPU *oldCPU); + + /** Get the current instruction sequence number, and increment it. */ + InstSeqNum getAndIncrementInstSeq(unsigned tid) + { return globalSeqNum[tid]++; } + + /** Get the current instruction sequence number, and increment it. */ + InstSeqNum nextInstSeqNum(unsigned tid) + { return globalSeqNum[tid]; } + + /** Increment Instruction Sequence Number */ + void incrInstSeqNum(unsigned tid) + { globalSeqNum[tid]++; } + + /** Set Instruction Sequence Number */ + void setInstSeqNum(unsigned tid, InstSeqNum seq_num) + { + globalSeqNum[tid] = seq_num; + } + + InstSeqNum getNextEventNum() + { + return cpuEventNum++; + } + + /** Get instruction asid. */ + int getInstAsid(unsigned tid) + { return thread[tid]->getInstAsid(); } + + /** Get data asid. */ + int getDataAsid(unsigned tid) + { return thread[tid]->getDataAsid(); } + + /** Register file accessors */ + uint64_t readIntReg(int reg_idx, unsigned tid); + + FloatReg readFloatReg(int reg_idx, unsigned tid, + int width = TheISA::SingleWidth); + + FloatRegBits readFloatRegBits(int reg_idx, unsigned tid, + int width = TheISA::SingleWidth); + + void setIntReg(int reg_idx, uint64_t val, unsigned tid); + + void setFloatReg(int reg_idx, FloatReg val, unsigned tid, + int width = TheISA::SingleWidth); + + void setFloatRegBits(int reg_idx, FloatRegBits val, unsigned tid, + int width = TheISA::SingleWidth); + + /** Reads a miscellaneous register. */ + MiscReg readMiscRegNoEffect(int misc_reg, unsigned tid); + + /** Reads a misc. register, including any side effects the read + * might have as defined by the architecture. + */ + MiscReg readMiscReg(int misc_reg, unsigned tid); + + /** Sets a miscellaneous register. */ + void setMiscRegNoEffect(int misc_reg, const MiscReg &val, unsigned tid); + + /** Sets a misc. register, including any side effects the write + * might have as defined by the architecture. + */ + void setMiscReg(int misc_reg, const MiscReg &val, unsigned tid); + + /** Reads a int/fp/misc reg. from another thread depending on ISA-defined + * target thread + */ + uint64_t readRegOtherThread(unsigned misc_reg, unsigned tid = -1); + + /** Sets a int/fp/misc reg. from another thread depending on an ISA-defined + * target thread + */ + void setRegOtherThread(unsigned misc_reg, const MiscReg &val, unsigned tid); + + /** Reads the commit PC of a specific thread. */ + uint64_t readPC(unsigned tid); + + /** Sets the commit PC of a specific thread. */ + void setPC(Addr new_PC, unsigned tid); + + /** Reads the next PC of a specific thread. */ + uint64_t readNextPC(unsigned tid); + + /** Sets the next PC of a specific thread. */ + void setNextPC(uint64_t val, unsigned tid); + + /** Reads the next NPC of a specific thread. */ + uint64_t readNextNPC(unsigned tid); + + /** Sets the next NPC of a specific thread. */ + void setNextNPC(uint64_t val, unsigned tid); + + /** Add Destination Register To Dependency Maps */ + //void addToRegDepMap(DynInstPtr &inst); + + /** Function to add instruction onto the head of the list of the + * instructions. Used when new instructions are fetched. + */ + ListIt addInst(DynInstPtr &inst); + + /** Function to tell the CPU that an instruction has completed. */ + void instDone(DynInstPtr inst, unsigned tid); + + /** Add Instructions to the CPU Remove List*/ + void addToRemoveList(DynInstPtr &inst); + + /** Remove an instruction from CPU */ + void removeInst(DynInstPtr &inst); + + /** Remove all instructions younger than the given sequence number. */ + void removeInstsUntil(const InstSeqNum &seq_num,unsigned tid); + + /** Removes the instruction pointed to by the iterator. */ + inline void squashInstIt(const ListIt &instIt, const unsigned &tid); + + /** Cleans up all instructions on the instruction remove list. */ + void cleanUpRemovedInsts(); + + /** Cleans up all instructions on the request remove list. */ + void cleanUpRemovedReqs(); + + /** Cleans up all instructions on the CPU event remove list. */ + void cleanUpRemovedEvents(); + + /** Debug function to print all instructions on the list. */ + void dumpInsts(); + + /** Translates instruction requestion in syscall emulation mode. */ + Fault translateInstReq(RequestPtr &req, Thread *thread) + { + return thread->getProcessPtr()->pTable->translate(req); + } + + /** Translates data read request in syscall emulation mode. */ + Fault translateDataReadReq(RequestPtr &req, Thread *thread) + { + return thread->getProcessPtr()->pTable->translate(req); + } + + /** Translates data write request in syscall emulation mode. */ + Fault translateDataWriteReq(RequestPtr &req, Thread *thread) + { + return thread->getProcessPtr()->pTable->translate(req); + } + + /** Forwards an instruction read to the appropriate data + * resource (indexes into Resource Pool thru "dataPortIdx") + */ + Fault read(DynInstPtr inst); + + /** Forwards an instruction write. to the appropriate data + * resource (indexes into Resource Pool thru "dataPortIdx") + */ + Fault write(DynInstPtr inst); + + /** Executes a syscall.*/ + void syscall(int64_t callnum, int tid); + + /** Gets a syscall argument. */ + IntReg getSyscallArg(int i, int tid); + + /** Used to shift args for indirect syscall. */ + void setSyscallArg(int i, IntReg val, int tid); + + /** Sets the return value of a syscall. */ + void setSyscallReturn(SyscallReturn return_value, int tid); + + public: + /** Per-Thread List of all the instructions in flight. */ + std::list instList[ThePipeline::MaxThreads]; + + /** List of all the instructions that will be removed at the end of this + * cycle. + */ + std::queue removeList; + + /** List of all the resource requests that will be removed at the end of this + * cycle. + */ + std::queue reqRemoveList; + + /** List of all the cpu event requests that will be removed at the end of + * the current cycle. + */ + std::queue cpuEventRemoveList; + +#ifdef DEBUG + /** Debug structure to keep track of the sequence numbers still in + * flight. + */ + std::set snList; +#endif + + /** Records if instructions need to be removed this cycle due to + * being retired or squashed. + */ + bool removeInstsThisCycle; + + /** True if there is non-speculative Inst Active In Pipeline. Lets any + * execution unit know, NOT to execute while the instruction is active. + */ + bool nonSpecInstActive[ThePipeline::MaxThreads]; + + /** Instruction Seq. Num of current non-speculative instruction. */ + InstSeqNum nonSpecSeqNum[ThePipeline::MaxThreads]; + + /** Instruction Seq. Num of last instruction squashed in pipeline */ + InstSeqNum squashSeqNum[ThePipeline::MaxThreads]; + + /** Last Cycle that the CPU squashed instruction end. */ + Tick lastSquashCycle[ThePipeline::MaxThreads]; + + std::list fetchPriorityList; + + /** Rename Map for architectural-to-physical register mappings. + * In a In-order processor, the mapping is fixed + * (e.g. Thread 1: 0-31, Thread 1: 32-63, etc.) + * In a Out-of-Order processor, this is used to maintain + * sequential consistency (?right word here?). + */ + RenameMap renameMap[ThePipeline::MaxThreads]; + + protected: + /** Active Threads List */ + std::list activeThreads; + + /** Current Threads List */ + std::list currentThreads; + + /** Suspended Threads List */ + std::list suspendedThreads; + + /** Thread Status Functions (Unused Currently) */ + bool isThreadInCPU(unsigned tid); + bool isThreadActive(unsigned tid); + bool isThreadSuspended(unsigned tid); + void addToCurrentThreads(unsigned tid); + void removeFromCurrentThreads(unsigned tid); + + private: + /** The activity recorder; used to tell if the CPU has any + * activity remaining or if it can go to idle and deschedule + * itself. + */ + ActivityRecorder activityRec; + + public: + void readFunctional(Addr addr, uint32_t &buffer); + + /** Number of Active Threads in the CPU */ + int numActiveThreads() { return activeThreads.size(); } + + /** Records that there was time buffer activity this cycle. */ + void activityThisCycle() { activityRec.activity(); } + + /** Changes a stage's status to active within the activity recorder. */ + void activateStage(const int idx) + { activityRec.activateStage(idx); } + + /** Changes a stage's status to inactive within the activity recorder. */ + void deactivateStage(const int idx) + { activityRec.deactivateStage(idx); } + + /** Wakes the CPU, rescheduling the CPU if it's not already active. */ + void wakeCPU(); + + /** Gets a free thread id. Use if thread ids change across system. */ + int getFreeTid(); + + // LL/SC debug functionality + unsigned stCondFails; + unsigned readStCondFailures() { return stCondFails; } + unsigned setStCondFailures(unsigned st_fails) { return stCondFails = st_fails; } + + public: + /** Returns a pointer to a thread context. */ + ThreadContext *tcBase(unsigned tid = 0) + { + return thread[tid]->getTC(); + } + + /** The global sequence number counter. */ + InstSeqNum globalSeqNum[ThePipeline::MaxThreads]; + + /** The global event number counter. */ + InstSeqNum cpuEventNum; + + /** Counter of how many stages have completed switching out. */ + int switchCount; + + /** Pointers to all of the threads in the CPU. */ + std::vector thread; + + /** Pointer to the icache interface. */ + MemInterface *icacheInterface; + /** Pointer to the dcache interface. */ + MemInterface *dcacheInterface; + + /** Whether or not the CPU should defer its registration. */ + bool deferRegistration; + + /** Per-Stage Instruction Tracing */ + bool stageTracing; + + /** Is there a context switch pending? */ + bool contextSwitch; + + /** Threads Scheduled to Enter CPU */ + std::list cpuWaitList; + + /** The cycle that the CPU was last running, used for statistics. */ + Tick lastRunningCycle; + + /** Number of Threads the CPU can process */ + unsigned numThreads; + + /** Number of Virtual Processors the CPU can process */ + unsigned numVirtProcs; + + /** Update Thread , used for statistic purposes*/ + inline void tickThreadStats(); + + /** Per-Thread Tick */ + Stats::Vector<> threadCycles; + + /** Tick for SMT */ + Stats::Scalar<> smtCycles; + + /** Stat for total number of times the CPU is descheduled. */ + Stats::Scalar<> timesIdled; + + /** Stat for total number of cycles the CPU spends descheduled. */ + Stats::Scalar<> idleCycles; + + /** Stat for the number of committed instructions per thread. */ + Stats::Vector<> committedInsts; + + /** Stat for the number of committed instructions per thread. */ + Stats::Vector<> smtCommittedInsts; + + /** Stat for the total number of committed instructions. */ + Stats::Scalar<> totalCommittedInsts; + + /** Stat for the CPI per thread. */ + Stats::Formula cpi; + + /** Stat for the SMT-CPI per thread. */ + Stats::Formula smtCpi; + + /** Stat for the total CPI. */ + Stats::Formula totalCpi; + + /** Stat for the IPC per thread. */ + Stats::Formula ipc; + + /** Stat for the total IPC. */ + Stats::Formula smtIpc; + + /** Stat for the total IPC. */ + Stats::Formula totalIpc; +}; + +#endif // __CPU_O3_CPU_HH__ diff --git a/src/cpu/inorder/first_stage.cc b/src/cpu/inorder/first_stage.cc new file mode 100644 index 000000000..ce30f8466 --- /dev/null +++ b/src/cpu/inorder/first_stage.cc @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include "base/str.hh" +#include "cpu/inorder/first_stage.hh" +#include "cpu/inorder/resources/resource_list.hh" +#include "cpu/inorder/resource_pool.hh" +#include "cpu/inorder/cpu.hh" +#include "params/InOrderTrace.hh" + +using namespace std; +using namespace ThePipeline; + +FirstStage::FirstStage(Params *params, unsigned stage_num) + : PipelineStage(params, stage_num) +{ + for(int tid=0; tid < this->numThreads; tid++) { + stageStatus[tid] = Running; + } + + numFetchingThreads = 1; + + fetchPolicy = RoundRobin; +} + +void +FirstStage::setCPU(InOrderCPU *cpu_ptr) +{ + cpu = cpu_ptr; + + fetchPriorityList = &cpu->fetchPriorityList; + + DPRINTF(InOrderStage, "Set CPU pointer.\n"); +} + + +void +FirstStage::squash(InstSeqNum squash_seq_num, unsigned tid) +{ + // Set status to squashing. + //stageStatus[tid] = Squashing; + + // Clear the instruction list and skid buffer in case they have any + // insts in them. + DPRINTF(InOrderStage, "Removing instructions from stage instruction list.\n"); + while (!insts[tid].empty()) { + if (insts[tid].front()->seqNum <= squash_seq_num) { + DPRINTF(InOrderStage,"[tid:%i]: Cannot remove [sn:%i] because it's <= " + "squashing seqNum %i.\n", + tid, + insts[tid].front()->seqNum, + squash_seq_num); + + DPRINTF(InOrderStage, "[tid:%i]: Cannot remove incoming " + "instructions before delay slot [sn:%i]. %i insts" + "left.\n", tid, squash_seq_num, + insts[tid].size()); + break; + } + DPRINTF(InOrderStage, "[tid:%i]: Removing instruction, [sn:%i] PC %08p.\n", + tid, insts[tid].front()->seqNum, insts[tid].front()->PC); + insts[tid].pop(); + } + + // Now that squash has propagated to the first stage, + // Alert CPU to remove instructions from the CPU instruction list. + // @todo: Move this to the CPU object. + cpu->removeInstsUntil(squash_seq_num, tid); +} + +void +FirstStage::processStage(bool &status_change) +{ + list::iterator threads = (*activeThreads).begin(); + + //Check stall and squash signals. + while (threads != (*activeThreads).end()) { + unsigned tid = *threads++; + status_change = checkSignalsAndUpdate(tid) || status_change; + } + + for (int threadFetched = 0; threadFetched < numFetchingThreads; + threadFetched++) { + int tid = getFetchingThread(fetchPolicy); + + if (tid >= 0) { + DPRINTF(InOrderStage, "Processing [tid:%i]\n",tid); + processThread(status_change, tid); + } else { + DPRINTF(InOrderStage, "No more threads to fetch from.\n"); + } + } +} + +//@TODO: Note in documentation, that when you make a pipeline stage change, then +//make sure you change the first stage too +void +FirstStage::processInsts(unsigned tid) +{ + bool all_reqs_completed = true; + + for (int insts_fetched = 0; insts_fetched < stageWidth && canSendInstToNextStage(); insts_fetched++) { + DynInstPtr inst; + bool new_inst = false; + + if (!insts[tid].empty()) { + inst = insts[tid].front(); + } else { + // Get new instruction. + new_inst = true; + + inst = new InOrderDynInst(cpu, + cpu->thread[tid], + cpu->nextInstSeqNum(tid), + tid); + +#if TRACING_ON + inst->traceData = + tracer->getInstRecord(ThePipeline::NumStages, + cpu->stageTracing, + cpu->thread[tid]->getTC()); + +#endif // TRACING_ON + + DPRINTF(RefCount, "creation: [tid:%i]: [sn:%i]: Refcount = %i.\n", + inst->readTid(), + inst->seqNum, + 0/*inst->curCount()*/); + + // Add instruction to the CPU's list of instructions. + inst->setInstListIt(cpu->addInst(inst)); + + DPRINTF(RefCount, "after add to CPU List: [tid:%i]: [sn:%i]: Refcount = %i.\n", + inst->readTid(), + inst->seqNum, + 0/*inst->curCount()*/); + + // Create Front-End Resource Schedule For Instruction + ThePipeline::createFrontEndSchedule(inst); + } + + // Don't let instruction pass to next stage if it hasnt completed + // all of it's requests for this stage. + all_reqs_completed = processInstSchedule(inst); + + if (!all_reqs_completed) { + if (new_inst) { + DPRINTF(InOrderStage, "[tid:%u]: [sn:%u] Did not finish all " + "requests for this stage. Keep in stage inst. " + "list.\n", tid, inst->seqNum); + insts[tid].push(inst); + } + break; + } else if (!insts[tid].empty()){ + insts[tid].pop(); + } + + sendInstToNextStage(inst); + //++stageProcessedInsts; + } + + // Record that stage has written to the time buffer for activity + // tracking. + if (toNextStageIndex) { + wroteToTimeBuffer = true; + } +} + +int +FirstStage::getFetchingThread(FetchPriority &fetch_priority) +{ + if (numThreads > 1) { + switch (fetch_priority) { + + case SingleThread: + return 0; + + case RoundRobin: + return roundRobin(); + + default: + return -1; + } + } else { + int tid = *((*activeThreads).begin()); + + if (stageStatus[tid] == Running || + stageStatus[tid] == Idle) { + return tid; + } else { + return -1; + } + } + +} + +int +FirstStage::roundRobin() +{ + list::iterator pri_iter = (*fetchPriorityList).begin(); + list::iterator end = (*fetchPriorityList).end(); + + int high_pri; + + while (pri_iter != end) { + high_pri = *pri_iter; + + assert(high_pri <= numThreads); + + if (stageStatus[high_pri] == Running || + stageStatus[high_pri] == Idle) { + + (*fetchPriorityList).erase(pri_iter); + (*fetchPriorityList).push_back(high_pri); + + return high_pri; + } + + pri_iter++; + } + + return -1; +} diff --git a/src/cpu/inorder/first_stage.hh b/src/cpu/inorder/first_stage.hh new file mode 100644 index 000000000..55914c85c --- /dev/null +++ b/src/cpu/inorder/first_stage.hh @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __CPU_INORDER_FIRST_STAGE_HH__ +#define __CPU_INORDER_FIRST_STAGE_HH__ + +#include +#include + +#include "base/statistics.hh" +#include "base/timebuf.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/comm.hh" +#include "cpu/inorder/params.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/pipeline_stage.hh" + +class InOrderCPU; + +class FirstStage : public PipelineStage { + public: + FirstStage(ThePipeline::Params *params, unsigned stage_num); + + /** Set Pointer to CPU */ + void setCPU(InOrderCPU *cpu_ptr); + + /** Evaluate Stage Info. & Execute Stage */ + void processStage(bool &status_change); + + /** Process All Instructions Available */ + void processInsts(unsigned tid); + + /** Squash Instructions Above a Seq. Num */ + void squash(InstSeqNum squash_seq_num, unsigned tid); + + /** There are no insts. coming from previous stages, so there is + * no need to sort insts here + */ + void sortInsts() {} + + /** There are no skidBuffers for the first stage. So + * just use an empty function. + */ + void skidInsert(unsigned tid) { } + + /** The number of fetching threads in the CPU */ + int numFetchingThreads; + + //@TODO: Add fetch priority information to a resource class... + /** Fetching Policy, Add new policies here.*/ + enum FetchPriority { + SingleThread, + RoundRobin + }; + + /** Fetch policy. */ + FetchPriority fetchPolicy; + + /** List that has the threads organized by priority. */ + std::list *fetchPriorityList; + + /** Return the next fetching thread */ + int getFetchingThread(FetchPriority &fetch_priority); + + /** Return next thred given Round Robin Policy for Thread Fetching */ + int roundRobin(); +}; + +#endif // __CPU_INORDER_FIRST_STAGE_HH__ diff --git a/src/cpu/inorder/inorder_cpu_builder.cc b/src/cpu/inorder/inorder_cpu_builder.cc new file mode 100644 index 000000000..b1b4bea80 --- /dev/null +++ b/src/cpu/inorder/inorder_cpu_builder.cc @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include + +#include "cpu/base.hh" +#include "cpu/inst_seq.hh" +#include "cpu/static_inst.hh" +#include "cpu/inorder/cpu.hh" +//#include "cpu/inorder/params.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "params/InOrderCPU.hh" + +InOrderCPU * +InOrderCPUParams::create() +{ + int actual_num_threads = + (numThreads >= workload.size()) ? numThreads : workload.size(); + + if (workload.size() == 0) { + fatal("Must specify at least one workload!"); + } + + numThreads = actual_num_threads; + + instShiftAmt = 2; + + return new InOrderCPU(this); +} + + + diff --git a/src/cpu/inorder/inorder_dyn_inst.cc b/src/cpu/inorder/inorder_dyn_inst.cc new file mode 100644 index 000000000..89362c656 --- /dev/null +++ b/src/cpu/inorder/inorder_dyn_inst.cc @@ -0,0 +1,780 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include +#include +#include +#include + +#include "base/cprintf.hh" +#include "base/trace.hh" + +#include "arch/faults.hh" +#include "cpu/exetrace.hh" +#include "mem/request.hh" + +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/cpu.hh" + +using namespace std; +using namespace TheISA; +using namespace ThePipeline; + +InOrderDynInst::InOrderDynInst(TheISA::ExtMachInst machInst, Addr inst_PC, + Addr pred_PC, InstSeqNum seq_num, + InOrderCPU *cpu) + : staticInst(machInst, inst_PC), traceData(NULL), cpu(cpu) +{ + seqNum = seq_num; + + PC = inst_PC; + nextPC = PC + sizeof(MachInst); + nextNPC = nextPC + sizeof(MachInst); + predPC = pred_PC; + + initVars(); +} + +InOrderDynInst::InOrderDynInst(InOrderCPU *cpu, + InOrderThreadState *state, + InstSeqNum seq_num, + unsigned tid) + : traceData(NULL), cpu(cpu) +{ + seqNum = seq_num; + thread = state; + threadNumber = tid; + initVars(); +} + +InOrderDynInst::InOrderDynInst(StaticInstPtr &_staticInst) + : staticInst(_staticInst), traceData(NULL) +{ + seqNum = 0; + initVars(); +} + +InOrderDynInst::InOrderDynInst() + : traceData(NULL), cpu(cpu) +{ initVars(); } + +int InOrderDynInst::instcount = 0; + + +void +InOrderDynInst::setMachInst(ExtMachInst machInst) +{ + staticInst = StaticInst::decode(machInst, PC); + + for (int i = 0; i < this->staticInst->numDestRegs(); i++) { + _destRegIdx[i] = this->staticInst->destRegIdx(i); + } + + for (int i = 0; i < this->staticInst->numSrcRegs(); i++) { + _srcRegIdx[i] = this->staticInst->srcRegIdx(i); + this->_readySrcRegIdx[i] = 0; + } +} + +void +InOrderDynInst::initVars() +{ + req = NULL; + effAddr = 0; + physEffAddr = 0; + + readyRegs = 0; + + nextStage = 0; + nextInstStageNum = 0; + + for(int i = 0; i < MaxInstDestRegs; i++) + instResult[i].val.integer = 0; + + status.reset(); + + memAddrReady = false; + eaCalcDone = false; + memOpDone = false; + + predictTaken = false; + procDelaySlotOnMispred = false; + + lqIdx = -1; + sqIdx = -1; + + // Also make this a parameter, or perhaps get it from xc or cpu. + asid = 0; + + virtProcNumber = 0; + + // Initialize the fault to be NoFault. + fault = NoFault; + + // Make sure to have the renamed register entries set to the same + // as the normal register entries. It will allow the IQ to work + // without any modifications. + if (this->staticInst) { + for (int i = 0; i < this->staticInst->numDestRegs(); i++) { + _destRegIdx[i] = this->staticInst->destRegIdx(i); + } + + for (int i = 0; i < this->staticInst->numSrcRegs(); i++) { + _srcRegIdx[i] = this->staticInst->srcRegIdx(i); + this->_readySrcRegIdx[i] = 0; + } + } + + // Update Instruction Count for this instruction + ++instcount; + if (instcount > 500) { + fatal("Number of Active Instructions in CPU is too high. " + "(Not Dereferencing Ptrs. Correctly?)\n"); + } + + + + DPRINTF(InOrderDynInst, "DynInst: [tid:%i] [sn:%lli] Instruction created. (active insts: %i)\n", + threadNumber, seqNum, instcount); + +#ifdef DEBUG + cpu->snList.insert(seqNum); +#endif +} + + +InOrderDynInst::~InOrderDynInst() +{ + if (req) { + delete req; + } + + if (traceData) { + delete traceData; + } + + fault = NoFault; + + --instcount; + + deleteStages(); + + DPRINTF(InOrderDynInst, "DynInst: [tid:%i] [sn:%lli] Instruction destroyed. (active insts: %i)\n", + threadNumber, seqNum, instcount); +#ifdef DEBUG + cpu->snList.erase(seqNum); +#endif +} + +void +InOrderDynInst::setStaticInst(StaticInstPtr &static_inst) +{ + this->staticInst = static_inst; + + // Make sure to have the renamed register entries set to the same + // as the normal register entries. It will allow the IQ to work + // without any modifications. + if (this->staticInst) { + for (int i = 0; i < this->staticInst->numDestRegs(); i++) { + _destRegIdx[i] = this->staticInst->destRegIdx(i); + } + + for (int i = 0; i < this->staticInst->numSrcRegs(); i++) { + _srcRegIdx[i] = this->staticInst->srcRegIdx(i); + this->_readySrcRegIdx[i] = 0; + } + } +} + +Fault +InOrderDynInst::execute() +{ + // @todo: Pretty convoluted way to avoid squashing from happening + // when using the TC during an instruction's execution + // (specifically for instructions that have side-effects that use + // the TC). Fix this. + bool in_syscall = this->thread->inSyscall; + this->thread->inSyscall = true; + + this->fault = this->staticInst->execute(this, this->traceData); + + this->thread->inSyscall = in_syscall; + + return this->fault; +} + +Fault +InOrderDynInst::initiateAcc() +{ + // @todo: Pretty convoluted way to avoid squashing from happening + // when using the TC during an instruction's execution + // (specifically for instructions that have side-effects that use + // the TC). Fix this. + bool in_syscall = this->thread->inSyscall; + this->thread->inSyscall = true; + + this->fault = this->staticInst->initiateAcc(this, this->traceData); + + this->thread->inSyscall = in_syscall; + + return this->fault; +} + + +Fault +InOrderDynInst::completeAcc(Packet *pkt) +{ + this->fault = this->staticInst->completeAcc(pkt, this, this->traceData); + + return this->fault; +} + +InstStage *InOrderDynInst::addStage() +{ + this->currentInstStage = new InstStage(this, nextInstStageNum++); + instStageList.push_back( this->currentInstStage ); + return this->currentInstStage; +} + +InstStage *InOrderDynInst::addStage(int stage_num) +{ + nextInstStageNum = stage_num; + return InOrderDynInst::addStage(); +} + +void InOrderDynInst::deleteStages() { + std::list::iterator list_it = instStageList.begin(); + std::list::iterator list_end = instStageList.end(); + + while(list_it != list_end) { + delete *list_it; + list_it++; + } +} + +Fault +InOrderDynInst::calcEA() +{ + return staticInst->eaCompInst()->execute(this, this->traceData); +} + +Fault +InOrderDynInst::memAccess() +{ + //return staticInst->memAccInst()->execute(this, this->traceData); + return initiateAcc( ); +} + +void +InOrderDynInst::syscall(int64_t callnum) +{ + cpu->syscall(callnum, this->threadNumber); +} + +void +InOrderDynInst::prefetch(Addr addr, unsigned flags) +{ + // This is the "functional" implementation of prefetch. Not much + // happens here since prefetches don't affect the architectural + // state. +/* + // Generate a MemReq so we can translate the effective address. + MemReqPtr req = new MemReq(addr, thread->getXCProxy(), 1, flags); + req->asid = asid; + + // Prefetches never cause faults. + fault = NoFault; + + // note this is a local, not InOrderDynInst::fault + Fault trans_fault = cpu->translateDataReadReq(req); + + if (trans_fault == NoFault && !(req->flags & UNCACHEABLE)) { + // It's a valid address to cacheable space. Record key MemReq + // parameters so we can generate another one just like it for + // the timing access without calling translate() again (which + // might mess up the TLB). + effAddr = req->vaddr; + physEffAddr = req->paddr; + memReqFlags = req->flags; + } else { + // Bogus address (invalid or uncacheable space). Mark it by + // setting the eff_addr to InvalidAddr. + effAddr = physEffAddr = MemReq::inval_addr; + } + + if (traceData) { + traceData->setAddr(addr); + } +*/ +} + +void +InOrderDynInst::writeHint(Addr addr, int size, unsigned flags) +{ + // Not currently supported. +} + +/** + * @todo Need to find a way to get the cache block size here. + */ +Fault +InOrderDynInst::copySrcTranslate(Addr src) +{ + // Not currently supported. + return NoFault; +} + +/** + * @todo Need to find a way to get the cache block size here. + */ +Fault +InOrderDynInst::copy(Addr dest) +{ + // Not currently supported. + return NoFault; +} + +void +InOrderDynInst::releaseReq(ResourceRequest* req) +{ + std::list::iterator list_it = reqList.begin(); + std::list::iterator list_end = reqList.end(); + + while(list_it != list_end) { + if((*list_it)->getResIdx() == req->getResIdx() && + (*list_it)->getSlot() == req->getSlot()) { + DPRINTF(InOrderDynInst, "[tid:%u]: [sn:%i] Done with request to %s.\n", + threadNumber, seqNum, req->res->name()); + reqList.erase(list_it); + return; + } + list_it++; + } + + panic("Releasing Res. Request That Isnt There!\n"); +} + +/** Records an integer source register being set to a value. */ +void +InOrderDynInst::setIntSrc(int idx, uint64_t val) +{ + DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Source Value %i being set to %#x.\n", + threadNumber, seqNum, idx, val); + instSrc[idx].integer = val; +} + +/** Records an fp register being set to a value. */ +void +InOrderDynInst::setFloatSrc(int idx, FloatReg val, int width) +{ + if (width == 32) + instSrc[idx].fp = val; + else if (width == 64) + instSrc[idx].dbl = val; + else + panic("Unsupported width!"); +} + +/** Records an fp register being set to an integer value. */ +void +InOrderDynInst::setFloatRegBitsSrc(int idx, uint64_t val) +{ + instSrc[idx].integer = val; +} + +/** Reads a integer register. */ +IntReg +InOrderDynInst::readIntRegOperand(const StaticInst *si, int idx, unsigned tid) +{ + DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Source Value %i read as %#x.\n", + threadNumber, seqNum, idx, instSrc[idx].integer); + return instSrc[idx].integer; +} + +/** Reads a FP register. */ +FloatReg +InOrderDynInst::readFloatRegOperand(const StaticInst *si, int idx, int width) +{ + return instSrc[idx].fp; +} + + +/** Reads a FP register as a integer. */ +FloatRegBits +InOrderDynInst::readFloatRegOperandBits(const StaticInst *si, int idx, int width) +{ + return instSrc[idx].integer; +} + +/** Reads a miscellaneous register. */ +MiscReg +InOrderDynInst::readMiscReg(int misc_reg) +{ + return this->cpu->readMiscReg(misc_reg, threadNumber); +} + +/** Reads a misc. register, including any side-effects the read + * might have as defined by the architecture. + */ +MiscReg +InOrderDynInst::readMiscRegNoEffect(int misc_reg) +{ + return this->cpu->readMiscRegNoEffect(misc_reg, threadNumber); +} + +/** Reads a miscellaneous register. */ +MiscReg +InOrderDynInst::readMiscRegOperandNoEffect(const StaticInst *si, int idx) +{ + return this->cpu->readMiscRegNoEffect( + si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, + this->threadNumber); +} + +/** Reads a misc. register, including any side-effects the read + * might have as defined by the architecture. + */ +MiscReg +InOrderDynInst::readMiscRegOperand(const StaticInst *si, int idx) +{ + return this->cpu->readMiscReg( + si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, + this->threadNumber); +} + +/** Sets a misc. register. */ +void +InOrderDynInst::setMiscRegOperandNoEffect(const StaticInst * si, int idx, const MiscReg &val) +{ + instResult[si->destRegIdx(idx)].val.integer = val; + instResult[si->destRegIdx(idx)].tick = curTick; + + this->cpu->setMiscRegNoEffect( + si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag, + val, this->threadNumber); +} + +/** Sets a misc. register, including any side-effects the write + * might have as defined by the architecture. + */ +void +InOrderDynInst::setMiscRegOperand(const StaticInst *si, int idx, + const MiscReg &val) +{ + instResult[si->destRegIdx(idx)].val.integer = val; + instResult[si->destRegIdx(idx)].tick = curTick; + + this->cpu->setMiscReg( + si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag, + val, this->threadNumber); +} + +MiscReg +InOrderDynInst::readRegOtherThread(unsigned reg_idx, int tid) +{ + if (tid == -1) { + tid = TheISA::getTargetThread(this->cpu->tcBase(threadNumber)); + } + + if (reg_idx < FP_Base_DepTag) { // Integer Register File + return this->cpu->readIntReg(reg_idx, tid); + } else if (reg_idx < Ctrl_Base_DepTag) { // Float Register File + reg_idx -= FP_Base_DepTag; + return this->cpu->readFloatRegBits(reg_idx, tid); + } else { + reg_idx -= Ctrl_Base_DepTag; + return this->cpu->readMiscReg(reg_idx, tid); // Misc. Register File + } +} + +/** Sets a Integer register. */ +void +InOrderDynInst::setIntRegOperand(const StaticInst *si, int idx, IntReg val) +{ + instResult[idx].val.integer = val; + instResult[idx].tick = curTick; +} + +/** Sets a FP register. */ +void +InOrderDynInst::setFloatRegOperand(const StaticInst *si, int idx, FloatReg val, int width) +{ + if (width == 32) + instResult[idx].val.fp = val; + else if (width == 64) + instResult[idx].val.dbl = val; + else + panic("Unsupported Floating Point Width!"); + + instResult[idx].tick = curTick; +} + +/** Sets a FP register as a integer. */ +void +InOrderDynInst::setFloatRegOperandBits(const StaticInst *si, int idx, + FloatRegBits val, int width) +{ + instResult[idx].val.integer = val; + instResult[idx].tick = curTick; +} + +/** Sets a misc. register. */ +/* Alter this when wanting to *speculate* on Miscellaneous registers */ +void +InOrderDynInst::setMiscRegNoEffect(int misc_reg, const MiscReg &val) +{ + this->cpu->setMiscRegNoEffect(misc_reg, val, threadNumber); +} + +/** Sets a misc. register, including any side-effects the write + * might have as defined by the architecture. + */ +/* Alter this if/when wanting to *speculate* on Miscellaneous registers */ +void +InOrderDynInst::setMiscReg(int misc_reg, const MiscReg &val) +{ + this->cpu->setMiscReg(misc_reg, val, threadNumber); +} + +void +InOrderDynInst::setRegOtherThread(unsigned reg_idx, const MiscReg &val, int tid) +{ + if (tid == -1) { + tid = TheISA::getTargetThread(this->cpu->tcBase(threadNumber)); + } + + if (reg_idx < FP_Base_DepTag) { // Integer Register File + this->cpu->setIntReg(reg_idx, val, tid); + } else if (reg_idx < Ctrl_Base_DepTag) { // Float Register File + reg_idx -= FP_Base_DepTag; + this->cpu->setFloatRegBits(reg_idx, val, tid); + } else { + reg_idx -= Ctrl_Base_DepTag; + this->cpu->setMiscReg(reg_idx, val, tid); // Misc. Register File + } +} + +void +InOrderDynInst::deallocateContext(int thread_num) +{ + this->cpu->deallocateContext(thread_num); +} + +void +InOrderDynInst::enableVirtProcElement(unsigned vpe) +{ + this->cpu->enableVirtProcElement(vpe); +} + +void +InOrderDynInst::disableVirtProcElement(unsigned vpe) +{ + this->cpu->disableVirtProcElement(threadNumber, vpe); +} + +void +InOrderDynInst::enableMultiThreading(unsigned vpe) +{ + this->cpu->enableMultiThreading(vpe); +} + +void +InOrderDynInst::disableMultiThreading(unsigned vpe) +{ + this->cpu->disableMultiThreading(threadNumber, vpe); +} + +void +InOrderDynInst::setThreadRescheduleCondition(uint32_t cond) +{ + this->cpu->setThreadRescheduleCondition(cond); +} + +template +inline Fault +InOrderDynInst::read(Addr addr, T &data, unsigned flags) +{ + return cpu->read(this); +} + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +template +Fault +InOrderDynInst::read(Addr addr, uint64_t &data, unsigned flags); + +template +Fault +InOrderDynInst::read(Addr addr, uint32_t &data, unsigned flags); + +template +Fault +InOrderDynInst::read(Addr addr, uint16_t &data, unsigned flags); + +template +Fault +InOrderDynInst::read(Addr addr, uint8_t &data, unsigned flags); + +#endif //DOXYGEN_SHOULD_SKIP_THIS + +template<> +Fault +InOrderDynInst::read(Addr addr, double &data, unsigned flags) +{ + return read(addr, *(uint64_t*)&data, flags); +} + +template<> +Fault +InOrderDynInst::read(Addr addr, float &data, unsigned flags) +{ + return read(addr, *(uint32_t*)&data, flags); +} + +template<> +Fault +InOrderDynInst::read(Addr addr, int32_t &data, unsigned flags) +{ + return read(addr, (uint32_t&)data, flags); +} + +template +inline Fault +InOrderDynInst::write(T data, Addr addr, unsigned flags, uint64_t *res) +{ + //memcpy(memData, gtoh(data), sizeof(T)); + storeData = data; + + DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Setting store data to %#x.\n", + threadNumber, seqNum, memData); + return cpu->write(this); +} + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +template +Fault +InOrderDynInst::write(uint64_t data, Addr addr, + unsigned flags, uint64_t *res); + +template +Fault +InOrderDynInst::write(uint32_t data, Addr addr, + unsigned flags, uint64_t *res); + +template +Fault +InOrderDynInst::write(uint16_t data, Addr addr, + unsigned flags, uint64_t *res); + +template +Fault +InOrderDynInst::write(uint8_t data, Addr addr, + unsigned flags, uint64_t *res); + +#endif //DOXYGEN_SHOULD_SKIP_THIS + +template<> +Fault +InOrderDynInst::write(double data, Addr addr, unsigned flags, uint64_t *res) +{ + return write(*(uint64_t*)&data, addr, flags, res); +} + +template<> +Fault +InOrderDynInst::write(float data, Addr addr, unsigned flags, uint64_t *res) +{ + return write(*(uint32_t*)&data, addr, flags, res); +} + + +template<> +Fault +InOrderDynInst::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) +{ + return write((uint32_t)data, addr, flags, res); +} + + +void +InOrderDynInst::dump() +{ + cprintf("T%d : %#08d `", threadNumber, PC); + cout << staticInst->disassemble(PC); + cprintf("'\n"); +} + +void +InOrderDynInst::dump(std::string &outstring) +{ + std::ostringstream s; + s << "T" << threadNumber << " : 0x" << PC << " " + << staticInst->disassemble(PC); + + outstring = s.str(); +} + + +#define NOHASH +#ifndef NOHASH + +#include "base/hashmap.hh" + +unsigned int MyHashFunc(const InOrderDynInst *addr) +{ + unsigned a = (unsigned)addr; + unsigned hash = (((a >> 14) ^ ((a >> 2) & 0xffff))) & 0x7FFFFFFF; + + return hash; +} + +typedef m5::hash_map +my_hash_t; + +my_hash_t thishash; +#endif + +#ifdef DEBUG + +void +InOrderDynInst::dumpSNList() +{ + std::set::iterator sn_it = cpu->snList.begin(); + + int count = 0; + while (sn_it != cpu->snList.end()) { + cprintf("%i: [sn:%lli] not destroyed\n", count, (*sn_it)); + count++; + sn_it++; + } +} +#endif + diff --git a/src/cpu/inorder/inorder_dyn_inst.hh b/src/cpu/inorder/inorder_dyn_inst.hh new file mode 100644 index 000000000..9f52f954f --- /dev/null +++ b/src/cpu/inorder/inorder_dyn_inst.hh @@ -0,0 +1,975 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * Copyright (c) 2004-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + * Korey Sewell + */ + +#ifndef __CPU_INORDER_DYN_INST_HH__ +#define __CPU_INORDER_DYN_INST_HH__ + +#include +#include +#include + +#include "arch/faults.hh" +#include "base/fast_alloc.hh" +#include "base/trace.hh" +#include "cpu/inorder/inorder_trace.hh" +#include "config/full_system.hh" +#include "cpu/thread_context.hh" +#include "cpu/exetrace.hh" +#include "cpu/inst_seq.hh" +#include "cpu/op_class.hh" +#include "cpu/static_inst.hh" +#include "cpu/inorder/thread_state.hh" +#include "cpu/inorder/resource.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "mem/packet.hh" +#include "sim/system.hh" + +/** + * @file + * Defines a dynamic instruction context for a inorder CPU model. + */ + +// Forward declaration. +class StaticInstPtr; +class ResourceRequest; + +class InOrderDynInst : public FastAlloc, public RefCounted +{ + public: + // Binary machine instruction type. + typedef TheISA::MachInst MachInst; + // Extended machine instruction type + typedef TheISA::ExtMachInst ExtMachInst; + // Logical register index type. + typedef TheISA::RegIndex RegIndex; + // Integer register type. + typedef TheISA::IntReg IntReg; + // Floating point register type. + typedef TheISA::FloatReg FloatReg; + // Floating point register type. + typedef TheISA::MiscReg MiscReg; + + typedef short int PhysRegIndex; + + /** The refcounted DynInst pointer to be used. In most cases this is + * what should be used, and not DynInst*. + */ + typedef RefCountingPtr DynInstPtr; + + // The list of instructions iterator type. + typedef std::list::iterator ListIt; + + enum { + MaxInstSrcRegs = TheISA::MaxInstSrcRegs, /// Max source regs + MaxInstDestRegs = TheISA::MaxInstDestRegs, /// Max dest regs + }; + + public: + /** BaseDynInst constructor given a binary instruction. + * @param inst The binary instruction. + * @param PC The PC of the instruction. + * @param pred_PC The predicted next PC. + * @param seq_num The sequence number of the instruction. + * @param cpu Pointer to the instruction's CPU. + */ + InOrderDynInst(ExtMachInst inst, Addr PC, Addr pred_PC, InstSeqNum seq_num, + InOrderCPU *cpu); + + /** BaseDynInst constructor given a binary instruction. + * @param seq_num The sequence number of the instruction. + * @param cpu Pointer to the instruction's CPU. + * NOTE: Must set Binary Instrution through Member Function + */ + InOrderDynInst(InOrderCPU *cpu, InOrderThreadState *state, InstSeqNum seq_num, + unsigned tid); + + /** BaseDynInst constructor given a StaticInst pointer. + * @param _staticInst The StaticInst for this BaseDynInst. + */ + InOrderDynInst(StaticInstPtr &_staticInst); + + /** Skeleton Constructor. */ + InOrderDynInst(); + + /** InOrderDynInst destructor. */ + ~InOrderDynInst(); + + public: + /** The sequence number of the instruction. */ + InstSeqNum seqNum; + + /** The sequence number of the instruction. */ + InstSeqNum bdelaySeqNum; + + enum Status { + RegDepMapEntry, /// Instruction has been entered onto the RegDepMap + IqEntry, /// Instruction is in the IQ + RobEntry, /// Instruction is in the ROB + LsqEntry, /// Instruction is in the LSQ + Completed, /// Instruction has completed + ResultReady, /// Instruction has its result + CanIssue, /// Instruction can issue and execute + Issued, /// Instruction has issued + Executed, /// Instruction has executed + CanCommit, /// Instruction can commit + AtCommit, /// Instruction has reached commit + Committed, /// Instruction has committed + Squashed, /// Instruction is squashed + SquashedInIQ, /// Instruction is squashed in the IQ + SquashedInLSQ, /// Instruction is squashed in the LSQ + SquashedInROB, /// Instruction is squashed in the ROB + RecoverInst, /// Is a recover instruction + BlockingInst, /// Is a blocking instruction + ThreadsyncWait, /// Is a thread synchronization instruction + SerializeBefore, /// Needs to serialize on + /// instructions ahead of it + SerializeAfter, /// Needs to serialize instructions behind it + SerializeHandled, /// Serialization has been handled + NumStatus + }; + + /** The status of this BaseDynInst. Several bits can be set. */ + std::bitset status; + + /** The thread this instruction is from. */ + short threadNumber; + + /** data address space ID, for loads & stores. */ + short asid; + + /** The virtual processor number */ + short virtProcNumber; + + /** The StaticInst used by this BaseDynInst. */ + StaticInstPtr staticInst; + + /** InstRecord that tracks this instructions. */ + Trace::InOrderTraceRecord *traceData; + + /** Pointer to the Impl's CPU object. */ + InOrderCPU *cpu; + + /** Pointer to the thread state. */ + InOrderThreadState *thread; + + /** The kind of fault this instruction has generated. */ + Fault fault; + + /** The memory request. */ + Request *req; + + /** Pointer to the data for the memory access. */ + uint8_t *memData; + + /** Data used for a store for operation. */ + uint64_t loadData; + + /** Data used for a store for operation. */ + uint64_t storeData; + + /** The resource schedule for this inst */ + ThePipeline::ResSchedule resSched; + + /** List of active resource requests for this instruction */ + std::list reqList; + + /** The effective virtual address (lds & stores only). */ + Addr effAddr; + + /** The effective physical address. */ + Addr physEffAddr; + + /** Effective virtual address for a copy source. */ + Addr copySrcEffAddr; + + /** Effective physical address for a copy source. */ + Addr copySrcPhysEffAddr; + + /** The memory request flags (from translation). */ + unsigned memReqFlags; + + /** How many source registers are ready. */ + unsigned readyRegs; + + /** An instruction src/dest has to be one of these types */ + union InstValue { + uint64_t integer; + float fp; + double dbl; + }; + + /** Result of an instruction execution */ + struct InstResult { + InstValue val; + Tick tick; + }; + + /** The source of the instruction; assumes for now that there's only one + * destination register. + */ + InstValue instSrc[MaxInstSrcRegs]; + + /** The result of the instruction; assumes for now that there's only one + * destination register. + */ + InstResult instResult[MaxInstDestRegs]; + + /** PC of this instruction. */ + Addr PC; + + /** Next non-speculative PC. It is not filled in at fetch, but rather + * once the target of the branch is truly known (either decode or + * execute). + */ + Addr nextPC; + + /** Next next non-speculative PC. It is not filled in at fetch, but rather + * once the target of the branch is truly known (either decode or + * execute). + */ + Addr nextNPC; + + /** Predicted next PC. */ + Addr predPC; + + /** Address to fetch from */ + Addr fetchAddr; + + /** Address to get/write data from/to */ + Addr memAddr; + + /** Whether or not the source register is ready. + * @todo: Not sure this should be here vs the derived class. + */ + bool _readySrcRegIdx[MaxInstSrcRegs]; + + /** Physical register index of the destination registers of this + * instruction. + */ + PhysRegIndex _destRegIdx[MaxInstDestRegs]; + + /** Physical register index of the source registers of this + * instruction. + */ + PhysRegIndex _srcRegIdx[MaxInstSrcRegs]; + + /** Physical register index of the previous producers of the + * architected destinations. + */ + PhysRegIndex _prevDestRegIdx[MaxInstDestRegs]; + + int nextStage; + + /* vars to keep track of InstStage's - used for resource sched defn */ + int nextInstStageNum; + ThePipeline::InstStage *currentInstStage; + std::list instStageList; + + private: + /** Function to initialize variables in the constructors. */ + void initVars(); + + public: + Tick memTime; + + //////////////////////////////////////////////////////////// + // + // BASE INSTRUCTION INFORMATION. + // + //////////////////////////////////////////////////////////// + void setMachInst(ExtMachInst inst); + + /** Sets the StaticInst. */ + void setStaticInst(StaticInstPtr &static_inst); + + /** Sets the sequence number. */ + void setSeqNum(InstSeqNum seq_num) { seqNum = seq_num; } + + /** Sets the ASID. */ + void setASID(short addr_space_id) { asid = addr_space_id; } + + /** Reads the thread id. */ + short readTid() { return threadNumber; } + + /** Sets the thread id. */ + void setTid(unsigned tid) { threadNumber = tid; } + + void setVpn(int id) { virtProcNumber = id; } + + int readVpn() { return virtProcNumber; } + + /** Sets the pointer to the thread state. */ + void setThreadState(InOrderThreadState *state) { thread = state; } + + /** Returns the thread context. */ + ThreadContext *tcBase() { return thread->getTC(); } + + /** Returns the fault type. */ + Fault getFault() { return fault; } + + //////////////////////////////////////////////////////////// + // + // INSTRUCTION TYPES - Forward checks to StaticInst object. + // + //////////////////////////////////////////////////////////// + bool isNop() const { return staticInst->isNop(); } + bool isMemRef() const { return staticInst->isMemRef(); } + bool isLoad() const { return staticInst->isLoad(); } + bool isStore() const { return staticInst->isStore(); } + bool isStoreConditional() const + { return staticInst->isStoreConditional(); } + bool isInstPrefetch() const { return staticInst->isInstPrefetch(); } + bool isDataPrefetch() const { return staticInst->isDataPrefetch(); } + bool isCopy() const { return staticInst->isCopy(); } + bool isInteger() const { return staticInst->isInteger(); } + bool isFloating() const { return staticInst->isFloating(); } + bool isControl() const { return staticInst->isControl(); } + bool isCall() const { return staticInst->isCall(); } + bool isReturn() const { return staticInst->isReturn(); } + bool isDirectCtrl() const { return staticInst->isDirectCtrl(); } + bool isIndirectCtrl() const { return staticInst->isIndirectCtrl(); } + bool isCondCtrl() const { return staticInst->isCondCtrl(); } + bool isUncondCtrl() const { return staticInst->isUncondCtrl(); } + bool isCondDelaySlot() const { return staticInst->isCondDelaySlot(); } + + bool isThreadSync() const { return staticInst->isThreadSync(); } + bool isSerializing() const { return staticInst->isSerializing(); } + bool isSerializeBefore() const + { return staticInst->isSerializeBefore() || status[SerializeBefore]; } + bool isSerializeAfter() const + { return staticInst->isSerializeAfter() || status[SerializeAfter]; } + bool isMemBarrier() const { return staticInst->isMemBarrier(); } + bool isWriteBarrier() const { return staticInst->isWriteBarrier(); } + bool isNonSpeculative() const { return staticInst->isNonSpeculative(); } + bool isQuiesce() const { return staticInst->isQuiesce(); } + bool isIprAccess() const { return staticInst->isIprAccess(); } + bool isUnverifiable() const { return staticInst->isUnverifiable(); } + + ///////////////////////////////////////////// + // + // RESOURCE SCHEDULING + // + ///////////////////////////////////////////// + + void setNextStage(int stage_num) { nextStage = stage_num; } + int getNextStage() { return nextStage; } + + ThePipeline::InstStage *addStage(); + ThePipeline::InstStage *addStage(int stage); + ThePipeline::InstStage *currentStage() { return currentInstStage; } + void deleteStages(); + + /** Add A Entry To Reource Schedule */ + void addToSched(ThePipeline::ScheduleEntry* sched_entry) + { resSched.push(sched_entry); } + + + /** Print Resource Schedule */ + void printSched() + { + using namespace ThePipeline; + + ResSchedule tempSched; + std::cerr << "\tInst. Res. Schedule: "; + while (!resSched.empty()) { + std::cerr << '\t' << resSched.top()->stageNum << "-" + << resSched.top()->resNum << ", "; + + tempSched.push(resSched.top()); + resSched.pop(); + } + + std::cerr << std::endl; + resSched = tempSched; + } + + /** Return Next Resource Stage To Be Used */ + int nextResStage() + { + if (resSched.empty()) + return -1; + else + return resSched.top()->stageNum; + } + + + /** Return Next Resource To Be Used */ + int nextResource() + { + if (resSched.empty()) + return -1; + else + return resSched.top()->resNum; + } + + /** Remove & Deallocate a schedule entry */ + void popSchedEntry() + { + if (!resSched.empty()) { + ThePipeline::ScheduleEntry* sked = resSched.top(); + resSched.pop(); + delete sked; + } + } + + /** Release a Resource Request (Currently Unused) */ + void releaseReq(ResourceRequest* req); + + //////////////////////////////////////////// + // + // INSTRUCTION EXECUTION + // + //////////////////////////////////////////// + /** Returns the opclass of this instruction. */ + OpClass opClass() const { return staticInst->opClass(); } + + /** Executes the instruction.*/ + Fault execute(); + + unsigned curResSlot; + + unsigned getCurResSlot() { return curResSlot; } + + void setCurResSlot(unsigned slot_num) { curResSlot = slot_num; } + + /** Calls a syscall. */ + void syscall(int64_t callnum); + void prefetch(Addr addr, unsigned flags); + void writeHint(Addr addr, int size, unsigned flags); + Fault copySrcTranslate(Addr src); + Fault copy(Addr dest); + + //////////////////////////////////////////////////////////// + // + // MULTITHREADING INTERFACE TO CPU MODELS + // + //////////////////////////////////////////////////////////// + virtual void deallocateContext(int thread_num); + + virtual void enableVirtProcElement(unsigned vpe); + virtual void disableVirtProcElement(unsigned vpe); + + virtual void enableMultiThreading(unsigned vpe); + virtual void disableMultiThreading(unsigned vpe); + + virtual void setThreadRescheduleCondition(uint32_t cond); + + //////////////////////////////////////////////////////////// + // + // PROGRAM COUNTERS - PC/NPC/NPC + // + //////////////////////////////////////////////////////////// + /** Read the PC of this instruction. */ + const Addr readPC() const { return PC; } + + /** Sets the PC of this instruction. */ + void setPC(Addr pc) { PC = pc; } + + /** Returns the next PC. This could be the speculative next PC if it is + * called prior to the actual branch target being calculated. + */ + Addr readNextPC() { return nextPC; } + + /** Set the next PC of this instruction (its actual target). */ + void setNextPC(uint64_t val) { nextPC = val; } + + /** Returns the next NPC. This could be the speculative next NPC if it is + * called prior to the actual branch target being calculated. + */ + Addr readNextNPC() { return nextNPC; } + + /** Set the next PC of this instruction (its actual target). */ + void setNextNPC(uint64_t val) { nextNPC = val; } + + //////////////////////////////////////////////////////////// + // + // BRANCH PREDICTION + // + //////////////////////////////////////////////////////////// + /** Set the predicted target of this current instruction. */ + void setPredTarg(Addr predicted_PC) { predPC = predicted_PC; } + + /** Returns the predicted target of the branch. */ + Addr readPredTarg() { return predPC; } + + /** Returns whether the instruction was predicted taken or not. */ + bool predTaken() { return predictTaken; } + + /** Returns whether the instruction mispredicted. */ + bool mispredicted() + { + // Special case since a not-taken, cond. delay slot, effectively + // nullifies the delay slot instruction + if (isCondDelaySlot() && !predictTaken) { + return predPC != nextPC; + } else { + return predPC != nextNPC; + } + } + + /** Returns whether the instruction mispredicted. */ + bool mistargeted() { return predPC != nextNPC; } + + /** Returns the branch target address. */ + Addr branchTarget() const { return staticInst->branchTarget(PC); } + + /** Checks whether or not this instruction has had its branch target + * calculated yet. For now it is not utilized and is hacked to be + * always false. + * @todo: Actually use this instruction. + */ + bool doneTargCalc() { return false; } + + void setBranchPred(bool prediction) { predictTaken = prediction; } + + int squashingStage; + + bool predictTaken; + + bool procDelaySlotOnMispred; + + //////////////////////////////////////////// + // + // MEMORY ACCESS + // + //////////////////////////////////////////// + /** + * Does a read to a given address. + * @param addr The address to read. + * @param data The read's data is written into this parameter. + * @param flags The request's flags. + * @return Returns any fault due to the read. + */ + template + Fault read(Addr addr, T &data, unsigned flags); + + /** + * Does a write to a given address. + * @param data The data to be written. + * @param addr The address to write to. + * @param flags The request's flags. + * @param res The result of the write (for load locked/store conditionals). + * @return Returns any fault due to the write. + */ + template + Fault write(T data, Addr addr, unsigned flags, + uint64_t *res); + + /** Initiates a memory access - Calculate Eff. Addr & Initiate Memory Access + * Only valid for memory operations. + */ + Fault initiateAcc(); + + /** Completes a memory access - Only valid for memory operations. */ + Fault completeAcc(Packet *pkt); + + /** Calculates Eff. Addr. part of a memory instruction. */ + Fault calcEA(); + + /** Read Effective Address from instruction & do memory access */ + Fault memAccess(); + + RequestPtr memReq; + + bool memAddrReady; + + bool validMemAddr() + { return memAddrReady; } + + void setMemAddr(Addr addr) + { memAddr = addr; memAddrReady = true;} + + void unsetMemAddr() + { memAddrReady = false;} + + Addr getMemAddr() + { return memAddr; } + + int getMemAccSize() { return staticInst->memAccSize(this); } + + int getMemFlags() { return staticInst->memAccFlags(); } + + /** Sets the effective address. */ + void setEA(Addr &ea) { instEffAddr = ea; eaCalcDone = true; } + + /** Returns the effective address. */ + const Addr &getEA() const { return instEffAddr; } + + /** Returns whether or not the eff. addr. calculation has been completed. */ + bool doneEACalc() { return eaCalcDone; } + + /** Returns whether or not the eff. addr. source registers are ready. + * Assume that src registers 1..n-1 are the ones that the + * EA calc depends on. (i.e. src reg 0 is the source of the data to be + * stored) + */ + bool eaSrcsReady() + { + for (int i = 1; i < numSrcRegs(); ++i) { + if (!_readySrcRegIdx[i]) + return false; + } + + return true; + } + + ////////////////////////////////////////////////// + // + // SOURCE-DESTINATION REGISTER INDEXING + // + ////////////////////////////////////////////////// + /** Returns the number of source registers. */ + int8_t numSrcRegs() const { return staticInst->numSrcRegs(); } + + /** Returns the number of destination registers. */ + int8_t numDestRegs() const { return staticInst->numDestRegs(); } + + // the following are used to track physical register usage + // for machines with separate int & FP reg files + int8_t numFPDestRegs() const { return staticInst->numFPDestRegs(); } + int8_t numIntDestRegs() const { return staticInst->numIntDestRegs(); } + + /** Returns the logical register index of the i'th destination register. */ + RegIndex destRegIdx(int i) const { return staticInst->destRegIdx(i); } + + /** Returns the logical register index of the i'th source register. */ + RegIndex srcRegIdx(int i) const { return staticInst->srcRegIdx(i); } + + ////////////////////////////////////////////////// + // + // RENAME/PHYSICAL REGISTER FILE SUPPORT + // + ////////////////////////////////////////////////// + /** Returns the physical register index of the i'th destination + * register. + */ + PhysRegIndex renamedDestRegIdx(int idx) const + { + return _destRegIdx[idx]; + } + + /** Returns the physical register index of the i'th source register. */ + PhysRegIndex renamedSrcRegIdx(int idx) const + { + return _srcRegIdx[idx]; + } + + /** Returns the physical register index of the previous physical register + * that remapped to the same logical register index. + */ + PhysRegIndex prevDestRegIdx(int idx) const + { + return _prevDestRegIdx[idx]; + } + + /** Returns if a source register is ready. */ + bool isReadySrcRegIdx(int idx) const + { + return this->_readySrcRegIdx[idx]; + } + + /** Records that one of the source registers is ready. */ + void markSrcRegReady() + { + if (++readyRegs == numSrcRegs()) { + status.set(CanIssue); + } + } + + /** Marks a specific register as ready. */ + void markSrcRegReady(RegIndex src_idx) + { + _readySrcRegIdx[src_idx] = true; + + markSrcRegReady(); + } + + /** Renames a destination register to a physical register. Also records + * the previous physical register that the logical register mapped to. + */ + void renameDestReg(int idx, + PhysRegIndex renamed_dest, + PhysRegIndex previous_rename) + { + _destRegIdx[idx] = renamed_dest; + _prevDestRegIdx[idx] = previous_rename; + } + + /** Renames a source logical register to the physical register which + * has/will produce that logical register's result. + * @todo: add in whether or not the source register is ready. + */ + void renameSrcReg(int idx, PhysRegIndex renamed_src) + { + _srcRegIdx[idx] = renamed_src; + } + + + PhysRegIndex readDestRegIdx(int idx) + { + return _destRegIdx[idx]; + } + + void setDestRegIdx(int idx, PhysRegIndex dest_idx) + { + _destRegIdx[idx] = dest_idx; + } + + int getDestIdxNum(PhysRegIndex dest_idx) + { + for (int i=0; i < staticInst->numDestRegs(); i++) { + if (_destRegIdx[i] == dest_idx) + return i; + } + + return -1; + } + + PhysRegIndex readSrcRegIdx(int idx) + { + return _srcRegIdx[idx]; + } + + void setSrcRegIdx(int idx, PhysRegIndex src_idx) + { + _srcRegIdx[idx] = src_idx; + } + + int getSrcIdxNum(PhysRegIndex src_idx) + { + for (int i=0; i < staticInst->numSrcRegs(); i++) { + if (_srcRegIdx[i] == src_idx) + return i; + } + + return -1; + } + + //////////////////////////////////////////////////// + // + // SOURCE-DESTINATION REGISTER VALUES + // + //////////////////////////////////////////////////// + + /** Functions that sets an integer or floating point + * source register to a value. */ + void setIntSrc(int idx, uint64_t val); + void setFloatSrc(int idx, FloatReg val, int width = 32); + void setFloatRegBitsSrc(int idx, uint64_t val); + + uint64_t* getIntSrcPtr(int idx) { return &instSrc[idx].integer; } + uint64_t readIntSrc(int idx) { return instSrc[idx].integer; } + + /** These Instructions read a integer/float/misc. source register + * value in the instruction. The instruction's execute function will + * call these and it is the interface that is used by the ISA descr. + * language (which is why the name isnt readIntSrc(...)) Note: That + * the source reg. value is set using the setSrcReg() function. + */ + IntReg readIntRegOperand(const StaticInst *si, int idx, unsigned tid=0); + FloatReg readFloatRegOperand(const StaticInst *si, int idx, + int width = TheISA::SingleWidth); + FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx, + int width = TheISA::SingleWidth); + MiscReg readMiscReg(int misc_reg); + MiscReg readMiscRegNoEffect(int misc_reg); + MiscReg readMiscRegOperand(const StaticInst *si, int idx); + MiscReg readMiscRegOperandNoEffect(const StaticInst *si, int idx); + + /** Returns the result value instruction. */ + uint64_t readIntResult(int idx) { return instResult[idx].val.integer; } + float readFloatResult(int idx) { return instResult[idx].val.fp; } + double readDoubleResult(int idx) { return instResult[idx].val.dbl; } + Tick readResultTime(int idx) { return instResult[idx].tick; } + + uint64_t* getIntResultPtr(int idx) { return &instResult[idx].val.integer; } + + /** This is the interface that an instruction will use to write + * it's destination register. + */ + void setIntRegOperand(const StaticInst *si, int idx, IntReg val); + void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val, + int width = TheISA::SingleWidth); + void setFloatRegOperandBits(const StaticInst *si, int idx, FloatRegBits val, + int width = TheISA::SingleWidth); + void setMiscReg(int misc_reg, const MiscReg &val); + void setMiscRegNoEffect(int misc_reg, const MiscReg &val); + void setMiscRegOperand(const StaticInst *si, int idx, const MiscReg &val); + void setMiscRegOperandNoEffect(const StaticInst *si, int idx, const MiscReg &val); + + virtual uint64_t readRegOtherThread(unsigned idx, int tid = -1); + virtual void setRegOtherThread(unsigned idx, const uint64_t &val, int tid = -1); + + ////////////////////////////////////////////////////////////// + // + // INSTRUCTION STATUS FLAGS (READ/SET) + // + ////////////////////////////////////////////////////////////// + /** Sets this instruction as entered on the CPU Reg Dep Map */ + void setRegDepEntry() { status.set(RegDepMapEntry); } + + /** Returns whether or not the entry is on the CPU Reg Dep Map */ + bool isRegDepEntry() const { return status[RegDepMapEntry]; } + + /** Sets this instruction as completed. */ + void setCompleted() { status.set(Completed); } + + /** Returns whether or not this instruction is completed. */ + bool isCompleted() const { return status[Completed]; } + + /** Marks the result as ready. */ + void setResultReady() { status.set(ResultReady); } + + /** Returns whether or not the result is ready. */ + bool isResultReady() const { return status[ResultReady]; } + + /** Sets this instruction as ready to issue. */ + void setCanIssue() { status.set(CanIssue); } + + /** Returns whether or not this instruction is ready to issue. */ + bool readyToIssue() const { return status[CanIssue]; } + + /** Sets this instruction as issued from the IQ. */ + void setIssued() { status.set(Issued); } + + /** Returns whether or not this instruction has issued. */ + bool isIssued() const { return status[Issued]; } + + /** Sets this instruction as executed. */ + void setExecuted() { status.set(Executed); } + + /** Returns whether or not this instruction has executed. */ + bool isExecuted() const { return status[Executed]; } + + /** Sets this instruction as ready to commit. */ + void setCanCommit() { status.set(CanCommit); } + + /** Clears this instruction as being ready to commit. */ + void clearCanCommit() { status.reset(CanCommit); } + + /** Returns whether or not this instruction is ready to commit. */ + bool readyToCommit() const { return status[CanCommit]; } + + void setAtCommit() { status.set(AtCommit); } + + bool isAtCommit() { return status[AtCommit]; } + + /** Sets this instruction as committed. */ + void setCommitted() { status.set(Committed); } + + /** Returns whether or not this instruction is committed. */ + bool isCommitted() const { return status[Committed]; } + + /** Sets this instruction as squashed. */ + void setSquashed() { status.set(Squashed); } + + /** Returns whether or not this instruction is squashed. */ + bool isSquashed() const { return status[Squashed]; } + + /** Temporarily sets this instruction as a serialize before instruction. */ + void setSerializeBefore() { status.set(SerializeBefore); } + + /** Clears the serializeBefore part of this instruction. */ + void clearSerializeBefore() { status.reset(SerializeBefore); } + + /** Checks if this serializeBefore is only temporarily set. */ + bool isTempSerializeBefore() { return status[SerializeBefore]; } + + /** Temporarily sets this instruction as a serialize after instruction. */ + void setSerializeAfter() { status.set(SerializeAfter); } + + /** Clears the serializeAfter part of this instruction.*/ + void clearSerializeAfter() { status.reset(SerializeAfter); } + + /** Checks if this serializeAfter is only temporarily set. */ + bool isTempSerializeAfter() { return status[SerializeAfter]; } + + /** Sets the serialization part of this instruction as handled. */ + void setSerializeHandled() { status.set(SerializeHandled); } + + /** Checks if the serialization part of this instruction has been + * handled. This does not apply to the temporary serializing + * state; it only applies to this instruction's own permanent + * serializing state. + */ + bool isSerializeHandled() { return status[SerializeHandled]; } + + private: + /** Instruction effective address. + * @todo: Consider if this is necessary or not. + */ + Addr instEffAddr; + + /** Whether or not the effective address calculation is completed. + * @todo: Consider if this is necessary or not. + */ + bool eaCalcDone; + + public: + /** Whether or not the memory operation is done. */ + bool memOpDone; + + public: + /** Load queue index. */ + int16_t lqIdx; + + /** Store queue index. */ + int16_t sqIdx; + + /** Iterator pointing to this BaseDynInst in the list of all insts. */ + ListIt instListIt; + + /** Returns iterator to this instruction in the list of all insts. */ + ListIt &getInstListIt() { return instListIt; } + + /** Sets iterator for this instruction in the list of all insts. */ + void setInstListIt(ListIt _instListIt) { instListIt = _instListIt; } + + /** Count of total number of dynamic instructions. */ + static int instcount; + +#ifdef DEBUG + void dumpSNList(); +#endif + + /** Dumps out contents of this BaseDynInst. */ + void dump(); + + /** Dumps out contents of this BaseDynInst into given string. */ + void dump(std::string &outstring); + + + //inline int curCount() { return curCount(); } +}; + + +#endif // __CPU_BASE_DYN_INST_HH__ diff --git a/src/cpu/inorder/inorder_trace.cc b/src/cpu/inorder/inorder_trace.cc new file mode 100644 index 000000000..f12a1b7a9 --- /dev/null +++ b/src/cpu/inorder/inorder_trace.cc @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * Copyright (c) 2001-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + */ + +#include + +#include "cpu/exetrace.hh" +#include "cpu/inorder/inorder_trace.hh" +#include "cpu/static_inst.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/thread_context.hh" +#include "params/InOrderTrace.hh" + +using namespace std; +using namespace TheISA; + +namespace Trace { + +inline void +Trace::InOrderTraceRecord::dumpTicks(std::ostream &outs) +{ + if (!stageTrace) { + ccprintf(outs, "%7d: ", when); + } else { + ccprintf(outs, ""); + for (int i=0; i < stageCycle.size(); i++) { + if (i < stageCycle.size() - 1) + outs << dec << stageCycle[i] << "-"; + else + outs << dec << stageCycle[i] << ":"; + } + } +} + +InOrderTraceRecord * +InOrderTrace::getInstRecord(unsigned num_stages, bool stage_tracing, + ThreadContext *tc) +{ + if (!IsOn(ExecEnable)) + return NULL; + + if (!Trace::enabled) + return NULL; + + return new InOrderTraceRecord(num_stages, stage_tracing, tc); +} + +InOrderTraceRecord * +InOrderTrace::getInstRecord(Tick when, ThreadContext *tc, + const StaticInstPtr staticInst, Addr pc, + const StaticInstPtr macroStaticInst, MicroPC upc) +{ + return new InOrderTraceRecord(ThePipeline::NumStages, true, tc); +} + +/* namespace Trace */ } + +//////////////////////////////////////////////////////////////////////// +// +// ExeTracer Simulation Object +// +Trace::InOrderTrace * +InOrderTraceParams::create() +{ + return new Trace::InOrderTrace(this); +}; + diff --git a/src/cpu/inorder/inorder_trace.hh b/src/cpu/inorder/inorder_trace.hh new file mode 100644 index 000000000..4338b438c --- /dev/null +++ b/src/cpu/inorder/inorder_trace.hh @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * Copyright (c) 2001-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + */ + +#ifndef __INORDERTRACE_HH__ +#define __INORDERTRACE_HH__ + +#include "base/trace.hh" +#include "cpu/static_inst.hh" +#include "sim/host.hh" +#include "sim/insttracer.hh" +#include "params/InOrderTrace.hh" +#include "cpu/exetrace.hh" + +class ThreadContext; + + +namespace Trace { + +class InOrderTraceRecord : public ExeTracerRecord +{ + public: + InOrderTraceRecord(unsigned num_stages, bool _stage_tracing, + ThreadContext *_thread, bool spec = false) + : ExeTracerRecord(0, _thread, NULL, 0, spec) + { + stageTrace = _stage_tracing; + stageCycle.resize(num_stages); + } + + // Trace stage-by-stage execution of instructions. + bool stageTrace; + std::vector stageCycle; + + void dumpTicks(std::ostream &outs); + + void + setStageCycle(int num_stage, Tick cur_cycle) + { + if (stageTrace) { + stageCycle[num_stage] = cur_cycle; + } else { + when = cur_cycle; + } + } + + void + setStaticInst(const StaticInstPtr &_staticInst) + { + staticInst = _staticInst; + } + void setPC(Addr _pc) { PC = _pc; } +}; + +class InOrderTrace : public InstTracer +{ + public: + InOrderTrace(const InOrderTraceParams *p) : InstTracer(p) + {} + + InOrderTraceRecord * + getInstRecord(unsigned num_stages, bool stage_tracing, ThreadContext *tc); + + virtual InOrderTraceRecord *getInstRecord(Tick when, ThreadContext *tc, + const StaticInstPtr staticInst, Addr pc, + const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0); +}; + +/* namespace Trace */ } + +#endif // __EXETRACE_HH__ diff --git a/src/cpu/inorder/params.hh b/src/cpu/inorder/params.hh new file mode 100644 index 000000000..67f8f47f0 --- /dev/null +++ b/src/cpu/inorder/params.hh @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + */ + +#ifndef __CPU_INORDER_PARAMS_HH__ +#define __CPU_INORDER_PARAMS_HH__ + +#include "cpu/base.hh" + +//Forward declarations +class FunctionalMemory; +class Process; +class MemObject; +class MemInterface; + +/** + * This file defines the parameters that will be used for the InOrderCPU. + * This must be defined externally so that the Impl can have a params class + * defined that it can pass to all of the individual stages. + */ + +class InOrderParams : public BaseCPU::Params +{ + public: + + // Workloads +#if !FULL_SYSTEM + std::vector workload; + Process *process; +#endif // FULL_SYSTEM + + // + // Memory System/Caches + // + unsigned cachePorts; + std::string fetchMemPort; + std::string dataMemPort; + + // + // Branch predictor (BP & BTB) + // + std::string predType; + unsigned localPredictorSize; + unsigned localCtrBits; + unsigned localHistoryTableSize; + unsigned localHistoryBits; + unsigned globalPredictorSize; + unsigned globalCtrBits; + unsigned globalHistoryBits; + unsigned choicePredictorSize; + unsigned choiceCtrBits; + unsigned BTBEntries; + unsigned BTBTagSize; + unsigned RASSize; + + // Pipeline Parameters + unsigned stageWidth; + + // InOrderCPU Simulation Parameters + unsigned instShiftAmt; + unsigned activity; + unsigned deferRegistration; + + // + // Memory Parameters + // + unsigned memBlockSize; + + // + // Multiply Divide Unit + // + // @NOTE: If >1 MDU is needed and each MDU is to use varying parametesr, + // then MDU must be defined as its own SimObject so that an arbitrary # can + // be defined with different parameters + /** Latency & Repeat Rate for Multiply Insts */ + unsigned multLatency; + unsigned multRepeatRate; + + /** Latency & Repeat Rate for 8-bit Divide Insts */ + unsigned div8Latency; + unsigned div8RepeatRate; + + /** Latency & Repeat Rate for 16-bit Divide Insts */ + unsigned div16Latency; + unsigned div16RepeatRate; + + /** Latency & Repeat Rate for 24-bit Divide Insts */ + unsigned div24Latency; + unsigned div24RepeatRate; + + /** Latency & Repeat Rate for 32-bit Divide Insts */ + unsigned div32Latency; + unsigned div32RepeatRate; + + +}; + +#endif // __CPU_O3_CPU_INORDER_PARAMS_HH__ diff --git a/src/cpu/inorder/pipeline_stage.cc b/src/cpu/inorder/pipeline_stage.cc new file mode 100644 index 000000000..547b42537 --- /dev/null +++ b/src/cpu/inorder/pipeline_stage.cc @@ -0,0 +1,1033 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include "base/str.hh" +#include "cpu/inorder/pipeline_stage.hh" +#include "cpu/inorder/resource_pool.hh" +#include "cpu/inorder/cpu.hh" + +using namespace std; +using namespace ThePipeline; + +PipelineStage::PipelineStage(Params *params, unsigned stage_num) + : numThreads(ThePipeline::MaxThreads) +{ + stageNum = stage_num; + stageWidth = ThePipeline::StageWidth; + + _status = Inactive; + + prevStageValid = false; + nextStageValid = false; + + // Init. structures + for(int tid=0; tid < numThreads; tid++) { + stageStatus[tid] = Idle; + + for (int stNum = 0; stNum < NumStages; stNum++) { + stalls[tid].stage[stNum] = false; + } + stalls[tid].resources.clear(); + + if (stageNum < BackEndStartStage) + lastStallingStage[tid] = BackEndStartStage - 1; + else + lastStallingStage[tid] = NumStages - 1; + } + + stageBufferMax = ThePipeline::interStageBuffSize[stage_num]; +} + + +void +PipelineStage::init(Params *params, unsigned stage_num) +{ + stageNum = stage_num; + stageWidth = ThePipeline::StageWidth; + + _status = Inactive; + + numThreads = ThePipeline::MaxThreads; + + prevStageValid = false; + nextStageValid = false; + + // Init. structures + for(int tid=0; tid < numThreads; tid++) { + stageStatus[tid] = Idle; + + for (int stNum = 0; stNum < NumStages; stNum++) { + stalls[tid].stage[stNum] = false; + } + stalls[tid].resources.clear(); + + if (stageNum < BackEndStartStage) + lastStallingStage[tid] = BackEndStartStage - 1; + else + lastStallingStage[tid] = NumStages - 1; + } + + stageBufferMax = ThePipeline::interStageBuffSize[stage_num]; +} + + +std::string +PipelineStage::name() const +{ + return cpu->name() + ".stage-" + to_string(stageNum); +} + + +void +PipelineStage::regStats() +{ +/* stageIdleCycles + .name(name() + ".IdleCycles") + .desc("Number of cycles stage is idle") + .prereq(stageIdleCycles); + stageBlockedCycles + .name(name() + ".BlockedCycles") + .desc("Number of cycles stage is blocked") + .prereq(stageBlockedCycles); + stageRunCycles + .name(name() + ".RunCycles") + .desc("Number of cycles stage is running") + .prereq(stageRunCycles); + stageUnblockCycles + .name(name() + ".UnblockCycles") + .desc("Number of cycles stage is unblocking") + .prereq(stageUnblockCycles); + stageSquashCycles + .name(name() + ".SquashCycles") + .desc("Number of cycles stage is squashing") + .prereq(stageSquashCycles); + stageProcessedInsts + .name(name() + ".ProcessedInsts") + .desc("Number of instructions handled by stage") + .prereq(stageProcessedInsts); + stageSquashedInsts + .name(name() + ".SquashedInsts") + .desc("Number of squashed instructions handled by stage") + .prereq(stageSquashedInsts);*/ +} + + +void +PipelineStage::setCPU(InOrderCPU *cpu_ptr) +{ + cpu = cpu_ptr; + + dummyBufferInst = new InOrderDynInst(cpu_ptr, NULL, 0, 0); + + DPRINTF(InOrderStage, "Set CPU pointer.\n"); + + tracer = dynamic_cast(cpu->getTracer()); +} + + +void +PipelineStage::setTimeBuffer(TimeBuffer *tb_ptr) +{ + DPRINTF(InOrderStage, "Setting time buffer pointer.\n"); + timeBuffer = tb_ptr; + + // Setup wire to write information back to fetch. + toPrevStages = timeBuffer->getWire(0); + + // Create wires to get information from proper places in time buffer. + fromNextStages = timeBuffer->getWire(-1); +} + + +void +PipelineStage::setPrevStageQueue(TimeBuffer *prev_stage_ptr) +{ + DPRINTF(InOrderStage, "Setting previous stage queue pointer.\n"); + prevStageQueue = prev_stage_ptr; + + // Setup wire to read information from fetch queue. + prevStage = prevStageQueue->getWire(-1); + + prevStageValid = true; +} + + + +void +PipelineStage::setNextStageQueue(TimeBuffer *next_stage_ptr) +{ + DPRINTF(InOrderStage, "Setting next stage pointer.\n"); + nextStageQueue = next_stage_ptr; + + // Setup wire to write information to proper place in stage queue. + nextStage = nextStageQueue->getWire(0); + + nextStageValid = true; +} + + + +void +PipelineStage::setActiveThreads(list *at_ptr) +{ + DPRINTF(InOrderStage, "Setting active threads list pointer.\n"); + activeThreads = at_ptr; +} + +/*inline void +PipelineStage::switchToActive() +{ + if (_status == Inactive) { + DPRINTF(Activity, "Activating stage.\n"); + + cpu->activateStage(stageNum); + + _status = Active; + } +}*/ + +void +PipelineStage::switchOut() +{ + // Stage can immediately switch out. + cpu->signalSwitched(); +} + + +void +PipelineStage::takeOverFrom() +{ + _status = Inactive; + + // Be sure to reset state and clear out any old instructions. + for (int i = 0; i < numThreads; ++i) { + stageStatus[i] = Idle; + + for (int stNum = 0; stNum < NumStages; stNum++) { + stalls[i].stage[stNum] = false; + } + + stalls[i].resources.clear(); + + while (!insts[i].empty()) + insts[i].pop(); + + while (!skidBuffer[i].empty()) + skidBuffer[i].pop(); + } + wroteToTimeBuffer = false; +} + + + +bool +PipelineStage::checkStall(unsigned tid) const +{ + bool ret_val = false; + + // Only check pipeline stall from stage directly following this stage + if (stalls[tid].stage[stageNum + 1]) { + DPRINTF(InOrderStage,"[tid:%i]: Stall fom Stage %i detected.\n", + tid, stageNum + 1); + ret_val = true; + } + + if (!stalls[tid].resources.empty()) { + string stall_src; + + for (int i=0; i < stalls[tid].resources.size(); i++) { + stall_src += stalls[tid].resources[i]->res->name() + ":"; + } + + DPRINTF(InOrderStage,"[tid:%i]: Stall fom resources (%s) detected.\n", + tid, stall_src); + ret_val = true; + } + + return ret_val; +} + + +void +PipelineStage::removeStalls(unsigned tid) +{ + for (int stNum = 0; stNum < NumStages; stNum++) { + stalls[tid].stage[stNum] = false; + } + stalls[tid].resources.clear(); +} + +inline bool +PipelineStage::prevStageInstsValid() +{ + return prevStage->size > 0; +} + +bool +PipelineStage::isBlocked(unsigned tid) +{ + return stageStatus[tid] == Blocked; +} + +bool +PipelineStage::block(unsigned tid) +{ + DPRINTF(InOrderStage, "[tid:%d]: Blocking, sending block signal back to previous stages.\n", tid); + + // Add the current inputs to the skid buffer so they can be + // reprocessed when this stage unblocks. + // skidInsert(tid); + + // If the stage status is blocked or unblocking then stage has not yet + // signalled fetch to unblock. In that case, there is no need to tell + // fetch to block. + if (stageStatus[tid] != Blocked) { + // Set the status to Blocked. + stageStatus[tid] = Blocked; + + if (stageStatus[tid] != Unblocking) { + if (prevStageValid) + toPrevStages->stageBlock[stageNum][tid] = true; + wroteToTimeBuffer = true; + } + + return true; + } + + + return false; +} + +void +PipelineStage::blockDueToBuffer(unsigned tid) +{ + DPRINTF(InOrderStage, "[tid:%d]: Blocking instructions from passing to next stage.\n", tid); + + if (stageStatus[tid] != Blocked) { + // Set the status to Blocked. + stageStatus[tid] = Blocked; + + if (stageStatus[tid] != Unblocking) { + wroteToTimeBuffer = true; + } + } +} + +bool +PipelineStage::unblock(unsigned tid) +{ + // Stage is done unblocking only if the skid buffer is empty. + if (skidBuffer[tid].empty()) { + DPRINTF(InOrderStage, "[tid:%u]: Done unblocking.\n", tid); + + if (prevStageValid) + toPrevStages->stageUnblock[stageNum][tid] = true; + + wroteToTimeBuffer = true; + + stageStatus[tid] = Running; + + return true; + } + + DPRINTF(InOrderStage, "[tid:%u]: Currently unblocking.\n", tid); + return false; +} + +void +PipelineStage::squashDueToBranch(DynInstPtr &inst, unsigned tid) +{ + if (cpu->squashSeqNum[tid] < inst->seqNum && + cpu->lastSquashCycle[tid] == curTick){ + DPRINTF(Resource, "Ignoring [sn:%i] squash signal due to another stage's squash " + "signal for after [sn:%i].\n", inst->seqNum, cpu->squashSeqNum[tid]); + } else { + // Send back mispredict information. + toPrevStages->stageInfo[stageNum][tid].branchMispredict = true; + toPrevStages->stageInfo[stageNum][tid].predIncorrect = true; + toPrevStages->stageInfo[stageNum][tid].doneSeqNum = inst->seqNum; + toPrevStages->stageInfo[stageNum][tid].squash = true; + toPrevStages->stageInfo[stageNum][tid].nextPC = inst->readPredTarg(); + toPrevStages->stageInfo[stageNum][tid].branchTaken = inst->readNextNPC() != + (inst->readNextPC() + sizeof(TheISA::MachInst)); + toPrevStages->stageInfo[stageNum][tid].bdelayDoneSeqNum = inst->bdelaySeqNum; + + DPRINTF(InOrderStage, "Target being re-set to %08p\n", inst->readPredTarg()); + InstSeqNum squash_seq_num = inst->bdelaySeqNum; + + DPRINTF(InOrderStage, "[tid:%i]: Squashing after [sn:%i], due to [sn:%i] " + "branch.\n", tid, squash_seq_num, inst->seqNum); + + // Save squash num for later stage use + cpu->squashSeqNum[tid] = squash_seq_num; + cpu->lastSquashCycle[tid] = curTick; + } +} + +void +PipelineStage::squashPrevStageInsts(InstSeqNum squash_seq_num, + unsigned tid) +{ + DPRINTF(InOrderStage, "[tid:%i]: Removing instructions from " + "incoming stage queue.\n", tid); + + for (int i=0; i < prevStage->size; i++) { + if (prevStage->insts[i]->threadNumber == tid && + prevStage->insts[i]->seqNum > squash_seq_num) { + DPRINTF(InOrderStage, "[tid:%i]: Squashing instruction, " + "[sn:%i] PC %08p.\n", + tid, + prevStage->insts[i]->seqNum, + prevStage->insts[i]->readPC()); + prevStage->insts[i]->setSquashed(); + } + } +} + +void +PipelineStage::squash(InstSeqNum squash_seq_num, unsigned tid) +{ + // Set status to squashing. + stageStatus[tid] = Squashing; + + squashPrevStageInsts(squash_seq_num, tid); + + DPRINTF(InOrderStage, "[tid:%i]: Removing instructions from incoming stage skidbuffer.\n", + tid); + while (!skidBuffer[tid].empty()) { + if (skidBuffer[tid].front()->seqNum <= squash_seq_num) { + DPRINTF(InOrderStage, "[tid:%i]: Cannot remove skidBuffer " + "instructions before delay slot [sn:%i]. %i insts" + "left.\n", tid, squash_seq_num, + skidBuffer[tid].size()); + break; + } + DPRINTF(InOrderStage, "[tid:%i]: Removing instruction, [sn:%i] PC %08p.\n", + tid, skidBuffer[tid].front()->seqNum, skidBuffer[tid].front()->PC); + skidBuffer[tid].pop(); + } + +} + +int +PipelineStage::stageBufferAvail() +{ + unsigned total = 0; + + for (int i=0; i < ThePipeline::MaxThreads; i++) { + total += skidBuffer[i].size(); + } + + int incoming_insts = (prevStageValid) ? + cpu->pipelineStage[stageNum-1]->nextStage->size : + 0; + + int avail = stageBufferMax - total - incoming_insts; + + assert(avail >= 0); + + return avail; +} + +bool +PipelineStage::canSendInstToNextStage() +{ + bool buffer_avail = false; + + if (nextStageValid) { + buffer_avail = (cpu->pipelineStage[stageNum+1]->stageBufferAvail() >= 1); + } + + if (!buffer_avail && nextStageValid) { + DPRINTF(InOrderStall, "STALL: No room in stage %i buffer.\n", stageNum + 1); + } + + return buffer_avail; +} + +void +PipelineStage::skidInsert(unsigned tid) +{ + DynInstPtr inst = NULL; + + while (!insts[tid].empty()) { + inst = insts[tid].front(); + + insts[tid].pop(); + + assert(tid == inst->threadNumber); + + DPRINTF(InOrderStage,"[tid:%i]: Inserting [sn:%lli] PC:%#x into stage skidBuffer %i\n", + tid, inst->seqNum, inst->readPC(), inst->threadNumber); + + skidBuffer[tid].push(inst); + } +} + + + +bool +PipelineStage::skidsEmpty() +{ + list::iterator threads = (*activeThreads).begin(); + + while (threads != (*activeThreads).end()) { + if (!skidBuffer[*threads++].empty()) + return false; + } + + return true; +} + + + +void +PipelineStage::updateStatus() +{ + bool any_unblocking = false; + + list::iterator threads = (*activeThreads).begin(); + + threads = (*activeThreads).begin(); + + while (threads != (*activeThreads).end()) { + unsigned tid = *threads++; + + if (stageStatus[tid] == Unblocking) { + any_unblocking = true; + break; + } + } + + // Stage will have activity if it's unblocking. + if (any_unblocking) { + if (_status == Inactive) { + _status = Active; + + DPRINTF(Activity, "Activating stage.\n"); + + cpu->activateStage(stageNum); + } + } else { + // If it's not unblocking, then stage will not have any internal + // activity. Switch it to inactive. + if (_status == Active) { + _status = Inactive; + DPRINTF(Activity, "Deactivating stage.\n"); + + cpu->deactivateStage(stageNum); + } + } +} + + + +void +PipelineStage::sortInsts() +{ + if (prevStageValid) { + int insts_from_prev_stage = prevStage->size; + + DPRINTF(InOrderStage, "%i insts available from previous stage.\n", + insts_from_prev_stage); + + for (int i = 0; i < insts_from_prev_stage; ++i) { + + if (prevStage->insts[i]->isSquashed()) { + DPRINTF(InOrderStage, "[tid:%i]: Ignoring squashed [sn:%i], not inserting " + "into stage buffer.\n", + prevStage->insts[i]->readTid(), + prevStage->insts[i]->seqNum); + + continue; + } + + DPRINTF(InOrderStage, "[tid:%i]: Inserting [sn:%i] into stage buffer.\n", + prevStage->insts[i]->readTid(), + prevStage->insts[i]->seqNum); + + int tid = prevStage->insts[i]->threadNumber; + + DynInstPtr inst = prevStage->insts[i]; + + skidBuffer[tid].push(prevStage->insts[i]); + + prevStage->insts[i] = dummyBufferInst; + + } + } +} + + + +void +PipelineStage::readStallSignals(unsigned tid) +{ + for (int stage_idx = stageNum+1; stage_idx <= lastStallingStage[tid]; + stage_idx++) { + + // Check for Stage Blocking Signal + if (fromNextStages->stageBlock[stage_idx][tid]) { + stalls[tid].stage[stage_idx] = true; + } + + // Check for Stage Unblocking Signal + if (fromNextStages->stageUnblock[stage_idx][tid]) { + //assert(fromNextStages->stageBlock[stage_idx][tid]); + stalls[tid].stage[stage_idx] = false; + } + } +} + + + +bool +PipelineStage::checkSignalsAndUpdate(unsigned tid) +{ + // Check if there's a squash signal, squash if there is. + // Check stall signals, block if necessary. + // If status was blocked + // Check if stall conditions have passed + // if so then go to unblocking + // If status was Squashing + // check if squashing is not high. Switch to running this cycle. + + // Update the per thread stall statuses. + readStallSignals(tid); + + // Check for squash from later pipeline stages + for (int stage_idx=stageNum; stage_idx < NumStages; stage_idx++) { + if (fromNextStages->stageInfo[stage_idx][tid].squash) { + DPRINTF(InOrderStage, "[tid:%u]: Squashing instructions due to squash " + "from stage %u.\n", tid, stage_idx); + InstSeqNum squash_seq_num = fromNextStages-> + stageInfo[stage_idx][tid].bdelayDoneSeqNum; + squash(squash_seq_num, tid); + break; //return true; + } + } + + if (checkStall(tid)) { + return block(tid); + } + + if (stageStatus[tid] == Blocked) { + DPRINTF(InOrderStage, "[tid:%u]: Done blocking, switching to unblocking.\n", + tid); + + stageStatus[tid] = Unblocking; + + unblock(tid); + + return true; + } + + if (stageStatus[tid] == Squashing) { + if (!skidBuffer[tid].empty()) { + DPRINTF(InOrderStage, "[tid:%u]: Done squashing, switching to unblocking.\n", + tid); + + stageStatus[tid] = Unblocking; + } else { + // Switch status to running if stage isn't being told to block or + // squash this cycle. + DPRINTF(InOrderStage, "[tid:%u]: Done squashing, switching to running.\n", + tid); + + stageStatus[tid] = Running; + } + + return true; + } + + // If we've reached this point, we have not gotten any signals that + // cause stage to change its status. Stage remains the same as before.*/ + return false; +} + + + +void +PipelineStage::tick() +{ + wroteToTimeBuffer = false; + + bool status_change = false; + + toNextStageIndex = 0; + + sortInsts(); + + processStage(status_change); + + if (status_change) { + updateStatus(); + } + + if (wroteToTimeBuffer) { + DPRINTF(Activity, "Activity this cycle.\n"); + cpu->activityThisCycle(); + } + + DPRINTF(InOrderStage, "\n\n"); +} + +bool +PipelineStage::outOfOrderValid() +{ + //@TODO: Define this function when OOO is valid + return false; +} + +void +PipelineStage::setResStall(ResReqPtr res_req, unsigned tid) +{ + DPRINTF(InOrderStage, "Inserting stall from %s.\n", res_req->res->name()); + stalls[tid].resources.push_back(res_req); +} + +void +PipelineStage::unsetResStall(ResReqPtr res_req, unsigned tid) +{ + // Search through stalls to find stalling request and then + // remove it + vector::iterator req_it = stalls[tid].resources.begin(); + vector::iterator req_end = stalls[tid].resources.end(); + + while (req_it != req_end) { + if( (*req_it)->res == res_req->res && // Same Resource + (*req_it)->inst == res_req->inst && // Same Instruction + (*req_it)->getSlot() == res_req->getSlot()) { + DPRINTF(InOrderStage, "[tid:%u]: Clearing stall by %s.\n", + tid, res_req->res->name()); + stalls[tid].resources.erase(req_it); + break; + } + + req_it++; + } + + if (stalls[tid].resources.size() == 0) { + DPRINTF(InOrderStage, "[tid:%u]: There are no remaining resource stalls.\n", + tid); + } +} + +// @TODO: Update How we handled threads in CPU. Maybe threads shouldnt be handled +// one at a time, but instead first come first serve by instruction? +// Questions are how should a pipeline stage handle thread-specific stalls & +// pipeline squashes +void +PipelineStage::processStage(bool &status_change) +{ + list::iterator threads = (*activeThreads).begin(); + + //Check stall and squash signals. + while (threads != (*activeThreads).end()) { + unsigned tid = *threads++; + + DPRINTF(InOrderStage,"Processing [tid:%i]\n",tid); + status_change = checkSignalsAndUpdate(tid) || status_change; + + processThread(status_change, tid); + } + + if (nextStageValid) { + DPRINTF(InOrderStage, "%i insts now available for stage %i.\n", + nextStage->size, stageNum + 1); + } + + DPRINTF(InOrderStage, "%i insts left in stage buffer.\n", stageBufferMax - stageBufferAvail()); + +} + +void +PipelineStage::processThread(bool &status_change, unsigned tid) +{ + // If status is Running or idle, + // call stageInsts() + // If status is Unblocking, + // buffer any instructions coming from fetch + // continue trying to empty skid buffer + // check if stall conditions have passed + + if (stageStatus[tid] == Blocked) { + ;//++stageBlockedCycles; + } else if (stageStatus[tid] == Squashing) { + ;//++stageSquashCycles; + } + + // Stage should try to stage as many instructions as its bandwidth + // will allow, as long as it is not currently blocked. + if (stageStatus[tid] == Running || + stageStatus[tid] == Idle) { + DPRINTF(InOrderStage, "[tid:%u]: Not blocked, so attempting to run " + "stage.\n",tid); + + processInsts(tid); + } else if (stageStatus[tid] == Unblocking) { + // Make sure that the skid buffer has something in it if the + // status is unblocking. + assert(!skidsEmpty()); + + // If the status was unblocking, then instructions from the skid + // buffer were used. Remove those instructions and handle + // the rest of unblocking. + processInsts(tid); + + if (prevStageValid && prevStageInstsValid()) { + // Add the current inputs to the skid buffer so they can be + // reprocessed when this stage unblocks. + skidInsert(tid); + } + + status_change = unblock(tid) || status_change; + } +} + + +void +PipelineStage::processInsts(unsigned tid) +{ + // Instructions can come either from the skid buffer or the list of + // instructions coming from fetch, depending on stage's status. + int insts_available = skidBuffer[tid].size(); + + std::queue &insts_to_stage = skidBuffer[tid]; + + if (insts_available == 0) { + DPRINTF(InOrderStage, "[tid:%u]: Nothing to do, breaking out" + " early.\n",tid); + // Should I change the status to idle? + //++stageIdleCycles; + return; + } + + DynInstPtr inst; + bool last_req_completed = true; + + int insts_processed = 0; + + DPRINTF(InOrderStage, "[tid:%u]: Sending instructions to stage %u.\n", tid, + stageNum+1); + + //Keep processing instructions while ... these ?s are true: + while (insts_available > 0 && //1. are there instructions to process + insts_processed < stageWidth && //2. can the stage still process this + (canSendInstToNextStage() || !nextStageValid) && //3. is there room in next stage + last_req_completed) { //4. was the last instruction completed + assert(!insts_to_stage.empty()); + + inst = insts_to_stage.front(); + + DPRINTF(InOrderStage, "[tid:%u]: Processing instruction [sn:%lli] with " + "PC %#x\n", + tid, inst->seqNum, inst->readPC()); + + if (inst->isSquashed()) { + DPRINTF(InOrderStage, "[tid:%u]: Instruction %i with PC %#x is " + "squashed, skipping.\n", + tid, inst->seqNum, inst->readPC()); + + //++stageSquashedInsts; + + insts_to_stage.pop(); + + --insts_available; + + continue; + } + + + last_req_completed = processInstSchedule(inst); + + + insts_processed++; + + // Don't let instruction pass to next stage if it hasnt completed + // all of it's requests for this stage. + if (!last_req_completed && !outOfOrderValid()) + continue; + + insts_to_stage.pop(); + + DPRINTF(InOrderStage, "Marking [tid:%i] [sn:%i] for insertion into next stage buffer.\n", + tid, inst->seqNum); + + // Send to Next Stage or Break Loop + if (!sendInstToNextStage(inst)) + break;; + + + //++stageProcessedInsts; + --insts_available; + } + + // If we didn't process all instructions, then we will need to block + // and put all those instructions into the skid buffer. + // @TODO:-IN-PROGRESS-:Evaluating when stages should block/unblock + // for stage stalls... + if (!insts_to_stage.empty()) { + blockDueToBuffer(tid); + } + + // Record that stage has written to the time buffer for activity + // tracking. + if (toNextStageIndex) { + wroteToTimeBuffer = true; + } +} + +bool +PipelineStage::processInstSchedule(DynInstPtr inst) +{ + bool last_req_completed = true; + int tid; + + tid = inst->readTid(); + + if (inst->nextResStage() == stageNum) { + int res_stage_num = inst->nextResStage(); + + while (res_stage_num == stageNum) { + int res_num = inst->nextResource(); + + + DPRINTF(InOrderStage, "[tid:%i]: [sn:%i]: sending request to %s.\n", + tid, inst->seqNum, cpu->resPool->name(res_num)); + + ResReqPtr req = cpu->resPool->request(res_num, inst); + + if (req->isCompleted()) { + DPRINTF(InOrderStage, "[tid:%i]: [sn:%i] request to %s completed.\n", + tid, inst->seqNum, cpu->resPool->name(res_num)); + + if (req->fault == NoFault) { + inst->popSchedEntry(); + } else { + panic("%i: encountered %s fault!\n", + curTick, req->fault->name()); + } + } else { + DPRINTF(InOrderStage, "[tid:%i]: [sn:%i] request to %s failed.\n", + tid, inst->seqNum, cpu->resPool->name(res_num)); + + last_req_completed = false; + + break; + } + + res_stage_num = inst->nextResStage(); + } + } else { + DPRINTF(InOrderStage, "[tid:%u]: Instruction [sn:%i] with PC %#x " + " needed no resources in stage %i.\n", + tid, inst->seqNum, inst->readPC(), stageNum); + } + + return last_req_completed; +} + +bool +PipelineStage::nextStageQueueValid(int stage_num) +{ + return cpu->pipelineStage[stage_num]->nextStageValid; +} + + +bool +PipelineStage::sendInstToNextStage(DynInstPtr inst) +{ + // Update Next Stage Variable in Instruction + if (inst->nextStage == stageNum) + inst->nextStage++; + + bool success = false; + int tid = inst->readTid(); + int next_stage = inst->nextStage; + int prev_stage = next_stage - 1; + + if (nextStageQueueValid(inst->nextStage - 1)) { + if (inst->seqNum > cpu->squashSeqNum[tid] && + curTick == cpu->lastSquashCycle[tid]) { + DPRINTF(InOrderStage, "[tid:%u]: [sn:%i]: squashed, skipping insertion " + "into stage %i queue.\n", tid, inst->seqNum, inst->nextStage); + } else { + DPRINTF(InOrderStage, "[tid:%u] %i slots available in next stage buffer.\n", + tid, cpu->pipelineStage[next_stage]->stageBufferAvail()); + + DPRINTF(InOrderStage, "[tid:%u]: [sn:%i]: being placed into " + "index %i stage %i queue.\n", + tid, inst->seqNum, toNextStageIndex, inst->nextStage); + + int next_stage_idx = cpu->pipelineStage[prev_stage]->nextStage->size; + + // Place instructions in inter-stage communication struct for the next + // pipeline stage to read next cycle + cpu->pipelineStage[prev_stage]->nextStage->insts[next_stage_idx] = inst; + + ++(cpu->pipelineStage[prev_stage]->nextStage->size); + + ++toNextStageIndex; + + success = true; + + // Take note of trace data for this inst & stage + if (inst->traceData) { + inst->traceData->setStageCycle(stageNum, curTick); + } + + } + } + + return success; +} + +void +PipelineStage::dumpInsts() +{ + std::cerr << "Insts in Stage " << stageNum << " skidbuffers:" << endl; + + for (int tid=0; tid < ThePipeline::MaxThreads; tid++) { + + std::queue copy_buff(skidBuffer[tid]); + + while (!copy_buff.empty()) { + DynInstPtr inst = copy_buff.front(); + + cprintf("Inst. PC:%#x\n[tid:%i]\n[sn:%i]\n\n", + inst->readPC(), inst->threadNumber, inst->seqNum); + + copy_buff.pop(); + } + } + +} diff --git a/src/cpu/inorder/pipeline_stage.hh b/src/cpu/inorder/pipeline_stage.hh new file mode 100644 index 000000000..833547704 --- /dev/null +++ b/src/cpu/inorder/pipeline_stage.hh @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __CPU_INORDER_PIPELINE_STAGE_HH__ +#define __CPU_INORDER_PIPELINE_STAGE_HH__ + +#include +#include + +#include "base/statistics.hh" +#include "base/timebuf.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/comm.hh" +#include "params/InOrderCPU.hh" +#include "cpu/inorder/pipeline_traits.hh" + +class InOrderCPU; + +class PipelineStage +{ + protected: + typedef ThePipeline::Params Params; + typedef ThePipeline::DynInstPtr DynInstPtr; + + public: + /** Overall stage status. Used to determine if the CPU can + * deschedule itself due to a lack of activity. + */ + enum StageStatus { + Active, + Inactive + }; + + /** Individual thread status. */ + enum ThreadStatus { + Running, + Idle, + StartSquash, + Squashing, + Blocked, + Unblocking, + MemWaitResponse, + MemWaitRetry, + MemAccessComplete + }; + + protected: + /** The Number of This Pipeline Stage */ + unsigned stageNum; + + /** The width of stage, in instructions. */ + unsigned stageWidth; + + /** Number of Threads*/ + unsigned numThreads; + + /** Stage status. */ + StageStatus _status; + + /** Per-thread status. */ + ThreadStatus stageStatus[ThePipeline::MaxThreads]; + + public: + PipelineStage(Params *params, unsigned stage_num); + + /** MUST use init() function if this constructor is used. */ + PipelineStage() { } + + virtual ~PipelineStage() { } + + /** PipelineStage initialization. */ + void init(Params *params, unsigned stage_num); + + /** Returns the name of stage. */ + std::string name() const; + + /** Registers statistics. */ + void regStats(); + + /** Sets CPU pointer. */ + virtual void setCPU(InOrderCPU *cpu_ptr); + + virtual void scheduleStageStart(int delay, int tid) { } + + /** Sets the main backwards communication time buffer pointer. */ + void setTimeBuffer(TimeBuffer *tb_ptr); + + /** Sets pointer to time buffer coming from fetch. */ + void setPrevStageQueue(TimeBuffer *prev_stage_ptr); + + /** Sets pointer to time buffer used to communicate to the next stage. */ + void setNextStageQueue(TimeBuffer *next_stage_ptr); + + /** Sets pointer to list of active threads. */ + void setActiveThreads(std::list *at_ptr); + + bool nextStageQueueValid(int stage_num); + + bool isBlocked(unsigned tid); + + /** Changes the status of this stage to active, and indicates this + * to the CPU. + */ + //inline void switchToActive(); + + /** Changes the status of this stage to inactive, and indicates + * this to the CPU. + */ + //inline void switchToInactive(); + + /** Switches out the stage stage. */ + void switchOut(); + + /** Takes over from another CPU's thread. */ + void takeOverFrom(); + + /** Ticks stage, processing all input signals and executing as many + * instructions as possible. + */ + virtual void tick(); + + /** Is out of order processing valid? */ + bool outOfOrderValid(); + + /** Set a resource stall in the pipeline-stage */ + void setResStall(ResReqPtr res_req, unsigned tid); + + /** Unset a resource stall in the pipeline-stage */ + void unsetResStall(ResReqPtr res_req, unsigned tid); + + /** Remove all stall signals for a particular thread; */ + virtual void removeStalls(unsigned tid); + + /** Is there room in the stage buffer? */ + int stageBufferAvail(); + + protected: + /** Evaluate Stage Conditions and then process stage */ + virtual void processStage(bool &status_change); + + /** Determines what to do based on stage's current status. + * @param status_change stage() sets this variable if there was a status + * change (ie switching from from blocking to unblocking). + * @param tid Thread id to stage instructions from. + */ + virtual void processThread(bool &status_change, unsigned tid); + + /** Processes instructions from fetch and passes them on to rename. + * Decoding of instructions actually happens when they are created in + * fetch, so this function mostly checks if PC-relative branches are + * correct. + */ + virtual void processInsts(unsigned tid); + + /** Process all resources on an instruction's resource schedule */ + virtual bool processInstSchedule(DynInstPtr inst); + + /** Is there room in the next stage buffer for this instruction? */ + virtual bool canSendInstToNextStage(); + + /** Send an instruction to the next stage buffer */ + virtual bool sendInstToNextStage(DynInstPtr inst); + + /** Inserts a thread's instructions into the skid buffer, to be staged + * once stage unblocks. + */ + virtual void skidInsert(unsigned tid); + + /** Returns if all of the skid buffers are empty. */ + bool skidsEmpty(); + + /** Updates overall stage status based on all of the threads' statuses. */ + virtual void updateStatus(); + + /** Separates instructions from fetch into individual lists of instructions + * sorted by thread. + */ + void sortInsts(); + + /** Reads all stall signals from the backwards communication timebuffer. */ + virtual void readStallSignals(unsigned tid); + + /** Checks all input signals and updates stage's status appropriately. */ + virtual bool checkSignalsAndUpdate(unsigned tid); + + /** Checks all stall signals, and returns if any are true. */ + virtual bool checkStall(unsigned tid) const; + + /** Returns if there any instructions from the previous stage + * on this cycle. + */ + inline bool prevStageInstsValid(); + + /** Switches stage to blocking, and signals back that stage has + * become blocked. + * @return Returns true if there is a status change. + */ + virtual bool block(unsigned tid); + + void blockDueToBuffer(unsigned tid); + + /** Switches stage to unblocking if the skid buffer is empty, and + * signals back that stage has unblocked. + * @return Returns true if there is a status change. + */ + virtual bool unblock(unsigned tid); + + + public: + /** Squashes if there is a PC-relative branch that was predicted + * incorrectly. Sends squash information back to fetch. + */ + virtual void squashDueToBranch(DynInstPtr &inst, unsigned tid); + + /** Squash instructions from stage buffer */ + virtual void squashPrevStageInsts(InstSeqNum squash_seq_num, unsigned tid); + + /** Squashes due to commit signalling a squash. Changes status to + * squashing and clears block/unblock signals as needed. + */ + virtual void squash(InstSeqNum squash_num, unsigned tid); + + void dumpInsts(); + + protected: + /** CPU interface. */ + InOrderCPU *cpu; + + Trace::InOrderTrace *tracer; + + /** List of active thread ids */ + std::list *activeThreads; + + /** Queue of all instructions coming from previous stage on this cycle. */ + std::queue insts[ThePipeline::MaxThreads]; + + /** Queue of instructions that are finished processing and ready to go next stage. + * This is used to prevent from processing an instrution more than once on any + * stage. NOTE: It is up to the PROGRAMMER must manage this as a queue + */ + std::list instsToNextStage; + + /** Skid buffer between previous stage and this one. */ + std::queue skidBuffer[ThePipeline::MaxThreads]; + + /** Instruction used to signify that there is no *real* instruction in buffer slot */ + DynInstPtr dummyBufferInst; + + /** SeqNum of Squashing Branch Delay Instruction (used for MIPS) */ + Addr bdelayDoneSeqNum[ThePipeline::MaxThreads]; + + /** Instruction used for squashing branch (used for MIPS) */ + DynInstPtr squashInst[ThePipeline::MaxThreads]; + + /** Tells when their is a pending delay slot inst. to send + * to rename. If there is, then wait squash after the next + * instruction (used for MIPS). + */ + bool squashAfterDelaySlot[ThePipeline::MaxThreads]; + + /** Maximum size of the inter-stage buffer connecting the previous stage to + * this stage (which we call a skid buffer) */ + unsigned stageBufferMax; + + /** Variable that tracks if stage has written to the time buffer this + * cycle. Used to tell CPU if there is activity this cycle. + */ + bool wroteToTimeBuffer; + + /** Index of instructions being sent to the next stage. */ + unsigned toNextStageIndex; + + /** The last stage that this particular stage should look for stalls */ + int lastStallingStage[ThePipeline::MaxThreads]; + + /** Time buffer interface. */ + TimeBuffer *timeBuffer; + + public: + /** Wire to get rename's output from backwards time buffer. */ + TimeBuffer::wire fromNextStages; + + /** Wire to get iew's information from backwards time buffer. */ + TimeBuffer::wire toPrevStages; + + /** Instruction queue linking previous stage */ + TimeBuffer *prevStageQueue; + + /** Wire to get the previous stage's. */ + TimeBuffer::wire prevStage; + + /** Instruction queue linking next stage */ + TimeBuffer *nextStageQueue; + + /** Wire to write to the next stage */ + TimeBuffer::wire nextStage; + + /** Is Previous Stage Valid? */ + bool prevStageValid; + + /** Is Next Stage Valid? */ + bool nextStageValid; + + /** Source of possible stalls. */ + struct Stalls { + bool stage[ThePipeline::NumStages]; + std::vector resources; + }; + + /** Tracks which stages are telling decode to stall. */ + Stalls stalls[ThePipeline::MaxThreads]; + + //@TODO: Use Stats for the pipeline stages + /** Stat for total number of idle cycles. */ + //Stats::Scalar<> stageIdleCycles; + /** Stat for total number of blocked cycles. */ + //Stats::Scalar<> stageBlockedCycles; + /** Stat for total number of normal running cycles. */ + //Stats::Scalar<> stageRunCycles; + /** Stat for total number of unblocking cycles. */ + //Stats::Scalar<> stageUnblockCycles; + /** Stat for total number of squashing cycles. */ + //Stats::Scalar<> stageSquashCycles; + /** Stat for total number of staged instructions. */ + //Stats::Scalar<> stageProcessedInsts; + /** Stat for total number of squashed instructions. */ + //Stats::Scalar<> stageSquashedInsts; +}; + +#endif diff --git a/src/cpu/inorder/pipeline_traits.5stage.cc b/src/cpu/inorder/pipeline_traits.5stage.cc new file mode 100644 index 000000000..50c30af1e --- /dev/null +++ b/src/cpu/inorder/pipeline_traits.5stage.cc @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/resources/resource_list.hh" + +using namespace std; + +namespace ThePipeline { + +//@TODO: create my own Instruction Schedule Class +//that operates as a Priority QUEUE +int getNextPriority(DynInstPtr &inst, int stage_num) +{ + int cur_pri = 20; + + /* + std::priority_queue, + entryCompare>::iterator sked_it = inst->resSched.begin(); + + std::priority_queue, + entryCompare>::iterator sked_end = inst->resSched.end(); + + while (sked_it != sked_end) { + + if (sked_it.top()->stageNum == stage_num) { + cur_pri = sked_it.top()->priority; + } + + sked_it++; + } + */ + + return cur_pri; +} + +void createFrontEndSchedule(DynInstPtr &inst) +{ + int stNum = 0; + int stPri = 0; + // Get Pointer to Instuction's Schedule + ResSchedule *inst_sched = &inst->resSched; + + // + // IF - Stage 0 + // --------------------------------------- + inst_sched->push(new ScheduleEntry(stNum, stPri++, FetchSeq, FetchSeqUnit::AssignNextPC)); + inst_sched->push(new ScheduleEntry(stNum, stPri++, ITLB, TLBUnit::FetchLookup)); + inst_sched->push(new ScheduleEntry(stNum, stPri++, ICache, CacheUnit::InitiateFetch)); + + // + // DE - Stage 1 + // --------------------------------------- + stNum++; stPri = 0; + inst_sched->push(new ScheduleEntry(stNum, stPri++, ICache, CacheUnit::CompleteFetch)); + inst_sched->push(new ScheduleEntry(stNum, stPri++, Decode, DecodeUnit::DecodeInst)); + inst_sched->push(new ScheduleEntry(stNum, stPri++, BPred, BranchPredictor::PredictBranch)); + inst_sched->push(new ScheduleEntry(stNum, stPri++, FetchSeq, FetchSeqUnit::UpdateTargetPC)); + +} + +bool createBackEndSchedule(DynInstPtr &inst) +{ + if (!inst->staticInst) { + return false; + } + + int stNum = BackEndStartStage; + int stPri = 0; + + // Get Pointer to Instuction's Schedule + ResSchedule *inst_sched = &inst->resSched; + + // + // EX - Stage 2 + // --------------------------------------- + for (int idx=0; idx < inst->numSrcRegs(); idx++) { + if (!idx || !inst->isStore()) + inst_sched->push(new ScheduleEntry(stNum, stPri++, RegManager, UseDefUnit::ReadSrcReg, idx)); + } + + if ( inst->isNonSpeculative() ) { + // skip execution of non speculative insts until later + } else if (inst->isMemRef()) { + inst_sched->push(new ScheduleEntry(stNum, stPri++, AGEN, AGENUnit::GenerateAddr)); + if ( inst->isLoad() ) { + inst_sched->push(new ScheduleEntry(stNum, stPri++, DTLB, TLBUnit::DataLookup)); + inst_sched->push(new ScheduleEntry(stNum, stPri++, DCache, CacheUnit::InitiateReadData)); + } + } else { + inst_sched->push(new ScheduleEntry(stNum, stPri++, ExecUnit, ExecutionUnit::ExecuteInst)); + } + + // + // MEM - Stage 3 + // --------------------------------------- + stPri = 0; stNum++; + if ( inst->isStore() ) { // for store, need src reg at this point + inst_sched->push(new ScheduleEntry(stNum, stPri++, RegManager, UseDefUnit::ReadSrcReg, 1)); + } + if ( inst->isLoad() ) { + inst_sched->push(new ScheduleEntry(stNum, stPri++, DCache, CacheUnit::CompleteReadData)); + } else if ( inst->isStore() ) { + inst_sched->push(new ScheduleEntry(stNum, stPri++, DTLB, TLBUnit::DataLookup)); + inst_sched->push(new ScheduleEntry(stNum, stPri++, DCache, CacheUnit::InitiateWriteData)); + } + + // + // WB - Stage 4 + // --------------------------------------- + stPri = 0; stNum++; + if (inst->isNonSpeculative()) { + if (inst->isMemRef()) + fatal("Schedule doesnt handle Non-Speculative Memory Instructions.\n"); + + if (inst->opClass() == IntMultOp || inst->opClass() == IntDivOp) { + inst_sched->push(new ScheduleEntry(stNum, stPri++, MDU, MultDivUnit::MultDiv)); + } else { + inst_sched->push(new ScheduleEntry(stNum, stPri++, ExecUnit, ExecutionUnit::ExecuteInst)); + } + } + + if ( inst->isStore() ) + inst_sched->push(new ScheduleEntry(stNum, stPri++, DCache, CacheUnit::CompleteWriteData)); + + // Write Back to Register File + for (int idx=0; idx < inst->numDestRegs(); idx++) { + inst_sched->push(new ScheduleEntry(stNum, stPri++, RegManager, UseDefUnit::WriteDestReg, idx)); + } + + // Graduate Instructions + inst_sched->push(new ScheduleEntry(stNum, stPri++, Grad, GraduationUnit::GraduateInst)); + + return true; +} + +}; diff --git a/src/cpu/inorder/pipeline_traits.5stage.hh b/src/cpu/inorder/pipeline_traits.5stage.hh new file mode 100644 index 000000000..aea6eff37 --- /dev/null +++ b/src/cpu/inorder/pipeline_traits.5stage.hh @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __CPU_INORDER_PIPELINE_IMPL_HH__ +#define __CPU_INORDER_PIPELINE_IMPL_HH__ + +#include +#include +#include + +#include "arch/isa_traits.hh" +#include "cpu/inorder/params.hh" + + +class InOrderDynInst; + +/* This Namespace contains constants, typedefs, functions and + * objects specific to the Pipeline Implementation. + */ +namespace ThePipeline { + // Pipeline Constants + const unsigned NumStages = 5; + const unsigned MaxThreads = 3; + const unsigned StageWidth = 1; + const unsigned BackEndStartStage = 2; + + // Enumerated List of Resources The Pipeline Uses + enum ResourceList { + FetchSeq = 0, + ITLB, + ICache, + Decode, + BPred, + FetchBuff, + RegManager, + AGEN, + ExecUnit, + DTLB, + DCache, + Grad, + FetchBuff2 + }; + + // Expand this as necessary for your inter stage buffer sizes + static const unsigned interStageBuffSize[] = { + StageWidth, /* Stage 0 - 1 */ + StageWidth, /* Stage 1 - 2 */ + StageWidth, /* Stage 2 - 3 */ + StageWidth, /* Stage 3 - 4 */ + StageWidth, /* Stage 4 - 5 */ + StageWidth, /* Stage 5 - 6 */ + StageWidth, /* Stage 6 - 7 */ + StageWidth, /* Stage 7 - 8 */ + StageWidth /* Stage 8 - 9 */ + }; + + typedef InOrderCPUParams Params; + typedef RefCountingPtr DynInstPtr; + + ////////////////////////// + // RESOURCE SCHEDULING + ////////////////////////// + struct ScheduleEntry { + ScheduleEntry(int stage_num, int _priority, int res_num, int _cmd = 0, + int _idx = 0) : + stageNum(stage_num), resNum(res_num), cmd(_cmd), + idx(_idx), priority(_priority) + { } + virtual ~ScheduleEntry(){} + + // Stage number to perform this service. + int stageNum; + + // Resource ID to access + int resNum; + + // See specific resource for meaning + unsigned cmd; + + // See specific resource for meaning + unsigned idx; + + // Some Resources May Need Priority? + int priority; + }; + + struct entryCompare { + bool operator()(const ScheduleEntry* lhs, const ScheduleEntry* rhs) const + { + // Prioritize first by stage number that the resource is needed + if (lhs->stageNum > rhs->stageNum) { + return true; + } else if (lhs->stageNum == rhs->stageNum) { + /*if (lhs->resNum > rhs->resNum) { + return true; + } else { + return false; + }*/ + + if (lhs->priority > rhs->priority) { + return true; + } else { + return false; + } + } else { + return false; + } + } + }; + + + typedef std::priority_queue, + entryCompare> ResSchedule; + + void createFrontEndSchedule(DynInstPtr &inst); + bool createBackEndSchedule(DynInstPtr &inst); + int getNextPriority(DynInstPtr &inst, int stage_num); +}; +#endif diff --git a/src/cpu/inorder/pipeline_traits.9stage.cc b/src/cpu/inorder/pipeline_traits.9stage.cc new file mode 100644 index 000000000..d686bb3bc --- /dev/null +++ b/src/cpu/inorder/pipeline_traits.9stage.cc @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/resources/resource_list.hh" + +using namespace std; + +namespace ThePipeline { + + +//@TODO: create my own Instruction Schedule Class +//that operates as a Priority QUEUE +int getNextPriority(DynInstPtr &inst, int stage_num) +{ + int cur_pri = 20; + + /* + std::priority_queue, + entryCompare>::iterator sked_it = inst->resSched.begin(); + + std::priority_queue, + entryCompare>::iterator sked_end = inst->resSched.end(); + + while (sked_it != sked_end) { + + if (sked_it.top()->stageNum == stage_num) { + cur_pri = sked_it.top()->priority; + } + + sked_it++; + } + */ + + return cur_pri; +} + +void createFrontEndSchedule(DynInstPtr &inst) +{ + int stNum = 0; + int stPri = 0; + // Get Pointer to Instuction's Schedule + ResSchedule *inst_sched = &inst->resSched; + + // + // Stage 0 + // --------------------------------------- + inst_sched->push(new ScheduleEntry(stNum, stPri, FetchSeq, FetchSeqUnit::AssignNextPC)); + stPri++; + + inst_sched->push(new ScheduleEntry(stNum, stPri, ITLB, TLBUnit::FetchLookup)); + stPri++; + + inst_sched->push(new ScheduleEntry(stNum, stPri, ICache, CacheUnit::InitiateFetch)); + stPri++; + + // Reset Priority / Update Next Stage Number + stNum++; + stPri = 0; + + // + // Stage 1 + // --------------------------------------- + inst_sched->push(new ScheduleEntry(stNum, stPri, ICache, CacheUnit::CompleteFetch)); + stPri++; + + inst_sched->push(new ScheduleEntry(stNum, stPri, Decode, DecodeUnit::DecodeInst)); + stPri++; + + inst_sched->push(new ScheduleEntry(stNum, stPri, BPred, BranchPredictor::PredictBranch)); + stPri++; + + inst_sched->push(new ScheduleEntry(stNum, stPri, FetchSeq, FetchSeqUnit::UpdateTargetPC)); + stPri++; + + if (inst->readTid() == 0) + inst_sched->push(new ScheduleEntry(stNum, stPri, FetchBuff, InstBuffer::ScheduleOrBypass)); + else //if (inst->readTid() == 1) + inst_sched->push(new ScheduleEntry(stNum, stPri, FetchBuff2, InstBuffer::ScheduleOrBypass)); + stPri++; + + // Reset Priority / Update Next Stage Number + stNum++; + stPri = 0; + + // + // Stage 2 + // --------------------------------------- + // Reset Priority / Update Next Stage Number + stNum++; + stPri = 0; +} + +bool createBackEndSchedule(DynInstPtr &inst) +{ + if (!inst->staticInst) { + return false; + } + + std::string name = inst->staticInst->getName(); + + int stNum = BackEndStartStage; + int stPri = 0; + + // Get Pointer to Instuction's Schedule + ResSchedule *inst_sched = &inst->resSched; + + // + // Stage 3 + // --------------------------------------- + // Set When Source Registers Should be read - Stage 4 + for (int idx=0; idx < inst->numSrcRegs(); idx++) { + inst_sched->push(new ScheduleEntry(stNum, stPri, RegManager, UseDefUnit::ReadSrcReg, idx)); + } + stPri++; + + // Reset Priority / Update Next Stage Number + stPri = 0; + stNum++; + + // + // Stage 4 + // --------------------------------------- + if (inst->isMemRef()) { + inst_sched->push(new ScheduleEntry(stNum, stPri, AGEN, AGENUnit::GenerateAddr)); + } + + // Reset Priority / Update Next Stage Number + stPri = 0; + stNum++; + + // + // Stage 5 + // --------------------------------------- + // Execution Unit + if (!inst->isNonSpeculative() && !inst->isMemRef()) { + if (inst->opClass() == IntMultOp || inst->opClass() == IntDivOp) { + inst_sched->push(new ScheduleEntry(stNum, stPri++, MDU, MultDivUnit::MultDiv)); + } else { + inst_sched->push(new ScheduleEntry(stNum, stPri, ExecUnit, ExecutionUnit::ExecuteInst)); + } + } + stPri++; + + // DCache Initiate Access + if (inst->isMemRef()) { + inst_sched->push(new ScheduleEntry(stNum, stPri, DTLB, TLBUnit::DataLookup)); + stPri++; + + if (inst->isLoad()) { + inst_sched->push(new ScheduleEntry(stNum, stPri, DCache, CacheUnit::InitiateReadData)); + } else if (inst->isStore()) { + inst_sched->push(new ScheduleEntry(stNum, stPri, DCache, CacheUnit::InitiateWriteData)); + } + } + + // Reset Priority / Update Next Stage Number + stPri = 0; + stNum++; + + // + // Stage 6 + // --------------------------------------- + // DCache Complete Access + if (inst->isMemRef()) { + if (inst->isLoad()) { + inst_sched->push(new ScheduleEntry(stNum, stPri, DCache, CacheUnit::CompleteReadData)); + } else if (inst->isStore()) { + inst_sched->push(new ScheduleEntry(stNum, stPri, DCache, CacheUnit::CompleteWriteData)); + } + } + + // Reset Priority / Update Next Stage Number + stPri = 0; + stNum++; + + // + // Stage 7 + // --------------------------------------- + // Reset Priority / Update Next Stage Number + stPri = 0; + stNum++; + + // + // Stage 8 + // --------------------------------------- + // NonSpeculative Execution + if (inst->isNonSpeculative() ) { + if (inst->isMemRef()) + fatal("Schedule doesnt handle Non-Speculative Memory Instructions.\n"); + + inst_sched->push(new ScheduleEntry(stNum, stPri, ExecUnit, ExecutionUnit::ExecuteInst)); + stPri++; + } + + // Write Back to Register File + for (int idx=0; idx < inst->numDestRegs(); idx++) { + inst_sched->push(new ScheduleEntry(stNum, stPri, RegManager, UseDefUnit::WriteDestReg, idx)); + stPri++; + } + + // Graduate Instructions + inst_sched->push(new ScheduleEntry(stNum, stPri, Grad, GraduationUnit::GraduateInst)); + stPri++; + + // Reset Priority / Update Next Stage Number + stPri = 0; + stNum++; + + return true; +} + +}; diff --git a/src/cpu/inorder/pipeline_traits.9stage.hh b/src/cpu/inorder/pipeline_traits.9stage.hh new file mode 100644 index 000000000..91e537366 --- /dev/null +++ b/src/cpu/inorder/pipeline_traits.9stage.hh @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __CPU_INORDER_PIPELINE_IMPL_HH__ +#define __CPU_INORDER_PIPELINE_IMPL_HH__ + +#include +#include +#include +#include + +#include "arch/isa_traits.hh" +#include "cpu/inorder/params.hh" + + +class InOrderDynInst; + +/* This Namespace contains constants, typedefs, functions and + * objects specific to the Pipeline Implementation. + */ +namespace ThePipeline { + // Pipeline Constants + const unsigned NumStages = 9; + const unsigned MaxThreads = 3; + const unsigned StageWidth = 2; + const unsigned BackEndStartStage = 3; + + // Use this to over-ride default stage widths + static std::map stageBufferSizes; + + //static unsigned interStageBuffSize[NumStages]; + + static const unsigned interStageBuffSize[NumStages] = { + StageWidth, /* Stage 0 - 1 */ + StageWidth, /* Stage 1 - 2 */ + 4, /* Stage 2 - 3 */ + StageWidth, /* Stage 3 - 4 */ + StageWidth, /* Stage 4 - 5 */ + StageWidth, /* Stage 5 - 6 */ + StageWidth, /* Stage 6 - 7 */ + StageWidth, /* Stage 7 - 8 */ + StageWidth /* Stage 8 - 9 */ + }; + + + // Enumerated List of Resources The Pipeline Uses + enum ResourceList { + FetchSeq = 0, + ITLB, + ICache, + Decode, + BPred, + FetchBuff, + RegManager, + AGEN, + ExecUnit, + DTLB, + DCache, + Grad, + FetchBuff2 + }; + + typedef InOrderCPUParams Params; + typedef RefCountingPtr DynInstPtr; + +//void initPipelineTraits(); + + ////////////////////////// + // RESOURCE SCHEDULING + ////////////////////////// + struct ScheduleEntry { + ScheduleEntry(int stage_num, int _priority, int res_num, int _cmd = 0, + int _idx = 0) : + stageNum(stage_num), resNum(res_num), cmd(_cmd), + idx(_idx), priority(_priority) + { } + virtual ~ScheduleEntry(){} + + // Stage number to perform this service. + int stageNum; + + // Resource ID to access + int resNum; + + // See specific resource for meaning + unsigned cmd; + + // See specific resource for meaning + unsigned idx; + + // Some Resources May Need Priority? + int priority; + }; + + struct entryCompare { + bool operator()(const ScheduleEntry* lhs, const ScheduleEntry* rhs) const + { + // Prioritize first by stage number that the resource is needed + if (lhs->stageNum > rhs->stageNum) { + return true; + } else if (lhs->stageNum == rhs->stageNum) { + /*if (lhs->resNum > rhs->resNum) { + return true; + } else { + return false; + }*/ + + if (lhs->priority > rhs->priority) { + return true; + } else { + return false; + } + } else { + return false; + } + } + }; + + + typedef std::priority_queue, + entryCompare> ResSchedule; + + void createFrontEndSchedule(DynInstPtr &inst); + bool createBackEndSchedule(DynInstPtr &inst); + int getNextPriority(DynInstPtr &inst, int stage_num); +}; +#endif diff --git a/src/cpu/inorder/pipeline_traits.9stage.smt2.cc b/src/cpu/inorder/pipeline_traits.9stage.smt2.cc new file mode 100644 index 000000000..9d2ed8e61 --- /dev/null +++ b/src/cpu/inorder/pipeline_traits.9stage.smt2.cc @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/resources/resource_list.hh" + +using namespace std; + +namespace ThePipeline { + + +//@TODO: create my own Instruction Schedule Class +//that operates as a Priority QUEUE +int getNextPriority(DynInstPtr &inst, int stage_num) +{ + int cur_pri = 20; + + /* + std::priority_queue, + entryCompare>::iterator sked_it = inst->resSched.begin(); + + std::priority_queue, + entryCompare>::iterator sked_end = inst->resSched.end(); + + while (sked_it != sked_end) { + + if (sked_it.top()->stageNum == stage_num) { + cur_pri = sked_it.top()->priority; + } + + sked_it++; + } + */ + + return cur_pri; +} + +void createFrontEndSchedule(DynInstPtr &inst) +{ + int stNum = 0; + int stPri = 0; + // Get Pointer to Instuction's Schedule + ResSchedule *inst_sched = &inst->resSched; + + // + // Stage 0 + // --------------------------------------- + inst_sched->push(new ScheduleEntry(stNum, stPri, FetchSeq, FetchSeqUnit::AssignNextPC)); + stPri++; + + inst_sched->push(new ScheduleEntry(stNum, stPri, ITLB, TLBUnit::FetchLookup)); + stPri++; + + inst_sched->push(new ScheduleEntry(stNum, stPri, ICache, CacheUnit::InitiateFetch)); + stPri++; + + // Reset Priority / Update Next Stage Number + stNum++; + stPri = 0; + + // + // Stage 1 + // --------------------------------------- + inst_sched->push(new ScheduleEntry(stNum, stPri, ICache, CacheUnit::CompleteFetch)); + stPri++; + + inst_sched->push(new ScheduleEntry(stNum, stPri, Decode, DecodeUnit::DecodeInst)); + stPri++; + + inst_sched->push(new ScheduleEntry(stNum, stPri, BPred, BranchPredictor::PredictBranch)); + stPri++; + + inst_sched->push(new ScheduleEntry(stNum, stPri, FetchSeq, FetchSeqUnit::UpdateTargetPC)); + stPri++; + + int fetch_buff_num = FetchBuff + inst->readTid(); + + inst_sched->push(new ScheduleEntry(stNum, stPri, fetch_buff_num, InstBuffer::ScheduleOrBypass)); + + // Reset Priority / Update Next Stage Number + stNum++; + stPri = 0; + + // + // Stage 2 + // --------------------------------------- + // Reset Priority / Update Next Stage Number + stNum++; + stPri = 0; +} + +bool createBackEndSchedule(DynInstPtr &inst) +{ + if (!inst->staticInst) { + return false; + } + + std::string name = inst->staticInst->getName(); + + int stNum = BackEndStartStage; + int stPri = 0; + + // Get Pointer to Instuction's Schedule + ResSchedule *inst_sched = &inst->resSched; + + // + // Stage 3 + // --------------------------------------- + // Set When Source Registers Should be read - Stage 4 + for (int idx=0; idx < inst->numSrcRegs(); idx++) { + inst_sched->push(new ScheduleEntry(stNum, stPri, RegManager, UseDefUnit::ReadSrcReg, idx)); + } + stPri++; + + // Reset Priority / Update Next Stage Number + stPri = 0; + stNum++; + + // + // Stage 4 + // --------------------------------------- + if (inst->isMemRef()) { + inst_sched->push(new ScheduleEntry(stNum, stPri, AGEN, AGENUnit::GenerateAddr)); + } + + // Reset Priority / Update Next Stage Number + stPri = 0; + stNum++; + + // + // Stage 5 + // --------------------------------------- + // Execution Unit + if (!inst->isNonSpeculative() && !inst->isMemRef()) { + //if (inst->opClass() == IntMultOp || inst->opClass() == IntDivOp) { + //inst_sched->push(new ScheduleEntry(stNum, stPri++, MDU, MultDivUnit::MultDiv)); + //} else { + inst_sched->push(new ScheduleEntry(stNum, stPri, ExecUnit, ExecutionUnit::ExecuteInst)); + //} + } + stPri++; + + // DCache Initiate Access + if (inst->isMemRef()) { + inst_sched->push(new ScheduleEntry(stNum, stPri, DTLB, TLBUnit::DataLookup)); + stPri++; + + if (inst->isLoad()) { + inst_sched->push(new ScheduleEntry(stNum, stPri, DCache, CacheUnit::InitiateReadData)); + } else if (inst->isStore()) { + inst_sched->push(new ScheduleEntry(stNum, stPri, DCache, CacheUnit::InitiateWriteData)); + } + } + + // Reset Priority / Update Next Stage Number + stPri = 0; + stNum++; + + // + // Stage 6 + // --------------------------------------- + // DCache Complete Access + if (inst->isMemRef()) { + if (inst->isLoad()) { + inst_sched->push(new ScheduleEntry(stNum, stPri, DCache, CacheUnit::CompleteReadData)); + } else if (inst->isStore()) { + inst_sched->push(new ScheduleEntry(stNum, stPri, DCache, CacheUnit::CompleteWriteData)); + } + } + + // Reset Priority / Update Next Stage Number + stPri = 0; + stNum++; + + // + // Stage 7 + // --------------------------------------- + // Reset Priority / Update Next Stage Number + stPri = 0; + stNum++; + + // + // Stage 8 + // --------------------------------------- + // NonSpeculative Execution + if (inst->isNonSpeculative() ) { + if (inst->isMemRef()) + fatal("Schedule doesnt handle Non-Speculative Memory Instructions.\n"); + + inst_sched->push(new ScheduleEntry(stNum, stPri, ExecUnit, ExecutionUnit::ExecuteInst)); + stPri++; + } + + // Write Back to Register File + for (int idx=0; idx < inst->numDestRegs(); idx++) { + inst_sched->push(new ScheduleEntry(stNum, stPri, RegManager, UseDefUnit::WriteDestReg, idx)); + stPri++; + } + + // Graduate Instructions + inst_sched->push(new ScheduleEntry(stNum, stPri, Grad, GraduationUnit::GraduateInst)); + stPri++; + + // Reset Priority / Update Next Stage Number + stPri = 0; + stNum++; + + return true; +} + +}; diff --git a/src/cpu/inorder/pipeline_traits.9stage.smt2.hh b/src/cpu/inorder/pipeline_traits.9stage.smt2.hh new file mode 100644 index 000000000..22da4ea0f --- /dev/null +++ b/src/cpu/inorder/pipeline_traits.9stage.smt2.hh @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __CPU_INORDER_PIPELINE_IMPL_HH__ +#define __CPU_INORDER_PIPELINE_IMPL_HH__ + +#include +#include +#include +#include + +#include "arch/isa_traits.hh" +#include "cpu/inorder/params.hh" + + +class InOrderDynInst; + +/* This Namespace contains constants, typedefs, functions and + * objects specific to the Pipeline Implementation. + */ +namespace ThePipeline { + // Pipeline Constants + const unsigned NumStages = 9; + const unsigned MaxThreads = 2; + const unsigned StageWidth = 1; + const unsigned BackEndStartStage = 3; + + // Use this to over-ride default stage widths + static std::map stageBufferSizes; + + //static unsigned interStageBuffSize[NumStages]; + + static const unsigned interStageBuffSize[NumStages] = { + StageWidth, /* Stage 0 - 1 */ + StageWidth, /* Stage 1 - 2 */ + MaxThreads * 4, /* Stage 2 - 3 */ + StageWidth, /* Stage 3 - 4 */ + MaxThreads * 4, /* Stage 4 - 5 */ + StageWidth, /* Stage 5 - 6 */ + StageWidth, /* Stage 6 - 7 */ + StageWidth, /* Stage 7 - 8 */ + MaxThreads /* Stage 8 - 9 */ + }; + + + // Enumerated List of Resources The Pipeline Uses + enum ResourceList { + FetchSeq = 0, + ITLB, + ICache, + Decode, + BPred, + RegManager, + AGEN, + ExecUnit, + DTLB, + DCache, + Grad, + FetchBuff, + FetchBuff2 + }; + + typedef InOrderCPUParams Params; + typedef RefCountingPtr DynInstPtr; + +//void initPipelineTraits(); + + ////////////////////////// + // RESOURCE SCHEDULING + ////////////////////////// + struct ScheduleEntry { + ScheduleEntry(int stage_num, int _priority, int res_num, int _cmd = 0, + int _idx = 0) : + stageNum(stage_num), resNum(res_num), cmd(_cmd), + idx(_idx), priority(_priority) + { } + virtual ~ScheduleEntry(){} + + // Stage number to perform this service. + int stageNum; + + // Resource ID to access + int resNum; + + // See specific resource for meaning + unsigned cmd; + + // See specific resource for meaning + unsigned idx; + + // Some Resources May Need Priority? + int priority; + }; + + struct entryCompare { + bool operator()(const ScheduleEntry* lhs, const ScheduleEntry* rhs) const + { + // Prioritize first by stage number that the resource is needed + if (lhs->stageNum > rhs->stageNum) { + return true; + } else if (lhs->stageNum == rhs->stageNum) { + /*if (lhs->resNum > rhs->resNum) { + return true; + } else { + return false; + }*/ + + if (lhs->priority > rhs->priority) { + return true; + } else { + return false; + } + } else { + return false; + } + } + }; + + + typedef std::priority_queue, + entryCompare> ResSchedule; + + void createFrontEndSchedule(DynInstPtr &inst); + bool createBackEndSchedule(DynInstPtr &inst); + int getNextPriority(DynInstPtr &inst, int stage_num); +}; +#endif diff --git a/src/cpu/inorder/pipeline_traits.cc b/src/cpu/inorder/pipeline_traits.cc new file mode 100644 index 000000000..eb899452a --- /dev/null +++ b/src/cpu/inorder/pipeline_traits.cc @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/resources/resource_list.hh" + +using namespace std; + +namespace ThePipeline { + +//@TODO: create my own Instruction Schedule Class +//that operates as a Priority QUEUE +int getNextPriority(DynInstPtr &inst, int stage_num) +{ + int cur_pri = 20; + + /* + std::priority_queue, + entryCompare>::iterator sked_it = inst->resSched.begin(); + + std::priority_queue, + entryCompare>::iterator sked_end = inst->resSched.end(); + + while (sked_it != sked_end) { + + if (sked_it.top()->stageNum == stage_num) { + cur_pri = sked_it.top()->priority; + } + + sked_it++; + } + */ + + return cur_pri; +} + +void createFrontEndSchedule(DynInstPtr &inst) +{ + InstStage *I = inst->addStage(); + InstStage *E = inst->addStage(); + + I->needs(FetchSeq, FetchSeqUnit::AssignNextPC); + I->needs(ITLB, TLBUnit::FetchLookup); + I->needs(ICache, CacheUnit::InitiateFetch); + + E->needs(ICache, CacheUnit::CompleteFetch); + E->needs(Decode, DecodeUnit::DecodeInst); + E->needs(BPred, BranchPredictor::PredictBranch); + E->needs(FetchSeq, FetchSeqUnit::UpdateTargetPC); +} + +bool createBackEndSchedule(DynInstPtr &inst) +{ + if (!inst->staticInst) { + return false; + } + + InstStage *E = inst->currentStage(); + InstStage *M = inst->addStage(); + InstStage *A = inst->addStage(); + InstStage *W = inst->addStage(); + + for (int idx=0; idx < inst->numSrcRegs(); idx++) { + if (!idx || !inst->isStore()) { + E->needs(RegManager, UseDefUnit::ReadSrcReg, idx); + } + } + + + if ( inst->isNonSpeculative() ) { + // skip execution of non speculative insts until later + } else if ( inst->isMemRef() ) { + E->needs(AGEN, AGENUnit::GenerateAddr); + if ( inst->isLoad() ) { + E->needs(DTLB, TLBUnit::DataLookup); + E->needs(DCache, CacheUnit::InitiateReadData); + } + } else if (inst->opClass() == IntMultOp || inst->opClass() == IntDivOp) { + E->needs(MDU, MultDivUnit::StartMultDiv); + + // ZERO-LATENCY Multiply: + // E->needs(MDU, MultDivUnit::MultDiv); + } else { + E->needs(ExecUnit, ExecutionUnit::ExecuteInst); + } + + if (inst->opClass() == IntMultOp || inst->opClass() == IntDivOp) { + M->needs(MDU, MultDivUnit::EndMultDiv); + } + + if ( inst->isLoad() ) { + M->needs(DCache, CacheUnit::CompleteReadData); + } else if ( inst->isStore() ) { + M->needs(RegManager, UseDefUnit::ReadSrcReg, 1); + M->needs(DTLB, TLBUnit::DataLookup); + M->needs(DCache, CacheUnit::InitiateWriteData); + } + + if ( inst->isStore() ) { + A->needs(DCache, CacheUnit::CompleteWriteData); + } + + if ( inst->isNonSpeculative() ) { + if ( inst->isMemRef() ) fatal("Non-Speculative Memory Instruction"); + W->needs(ExecUnit, ExecutionUnit::ExecuteInst); + } + + for (int idx=0; idx < inst->numDestRegs(); idx++) { + W->needs(RegManager, UseDefUnit::WriteDestReg, idx); + } + + W->needs(Grad, GraduationUnit::GraduateInst); + + return true; +} + +InstStage::InstStage(DynInstPtr inst, int stage_num) +{ + stageNum = stage_num; + nextTaskPriority = 0; + instSched = &inst->resSched; +} + +}; diff --git a/src/cpu/inorder/pipeline_traits.hh b/src/cpu/inorder/pipeline_traits.hh new file mode 100644 index 000000000..c5e4bb228 --- /dev/null +++ b/src/cpu/inorder/pipeline_traits.hh @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __CPU_INORDER_PIPELINE_IMPL_HH__ +#define __CPU_INORDER_PIPELINE_IMPL_HH__ + +#include +#include +#include + +#include "arch/isa_traits.hh" +#include "cpu/base.hh" +//#include "cpu/inorder/params.hh" + +#include "params/InOrderCPU.hh" + +class InOrderDynInst; + +/* This Namespace contains constants, typedefs, functions and + * objects specific to the Pipeline Implementation. + */ +namespace ThePipeline { + // Pipeline Constants + const unsigned NumStages = 5; + const unsigned MaxThreads = 8; + const unsigned StageWidth = 1; + const unsigned BackEndStartStage = 2; + + // Enumerated List of Resources The Pipeline Uses + enum ResourceList { + FetchSeq = 0, + ITLB, + ICache, + Decode, + BPred, + FetchBuff, + RegManager, + AGEN, + ExecUnit, + MDU, + DTLB, + DCache, + Grad, + FetchBuff2 + }; + + // Expand this as necessary for your inter stage buffer sizes + static const unsigned interStageBuffSize[] = { + StageWidth, /* Stage 0 - 1 */ + StageWidth, /* Stage 1 - 2 */ + StageWidth, /* Stage 2 - 3 */ + StageWidth, /* Stage 3 - 4 */ + StageWidth, /* Stage 4 - 5 */ + StageWidth, /* Stage 5 - 6 */ + StageWidth, /* Stage 6 - 7 */ + StageWidth, /* Stage 7 - 8 */ + StageWidth /* Stage 8 - 9 */ + }; + + typedef InOrderCPUParams Params; + typedef RefCountingPtr DynInstPtr; + + ////////////////////////// + // RESOURCE SCHEDULING + ////////////////////////// + struct ScheduleEntry { + ScheduleEntry(int stage_num, int _priority, int res_num, int _cmd = 0, + int _idx = 0) : + stageNum(stage_num), resNum(res_num), cmd(_cmd), + idx(_idx), priority(_priority) + { } + virtual ~ScheduleEntry(){} + + // Stage number to perform this service. + int stageNum; + + // Resource ID to access + int resNum; + + // See specific resource for meaning + unsigned cmd; + + // See specific resource for meaning + unsigned idx; + + // Some Resources May Need Priority? + int priority; + }; + + struct entryCompare { + bool operator()(const ScheduleEntry* lhs, const ScheduleEntry* rhs) const + { + // Prioritize first by stage number that the resource is needed + if (lhs->stageNum > rhs->stageNum) { + return true; + } else if (lhs->stageNum == rhs->stageNum) { + /*if (lhs->resNum > rhs->resNum) { + return true; + } else { + return false; + }*/ + + if (lhs->priority > rhs->priority) { + return true; + } else { + return false; + } + } else { + return false; + } + } + }; + + + typedef std::priority_queue, + entryCompare> ResSchedule; + + void createFrontEndSchedule(DynInstPtr &inst); + bool createBackEndSchedule(DynInstPtr &inst); + int getNextPriority(DynInstPtr &inst, int stage_num); + + class InstStage { + private: + int nextTaskPriority; + int stageNum; + ResSchedule *instSched; + + public: + InstStage(DynInstPtr inst, int stage_num); + + void needs(int unit, int request) { + instSched->push( new ScheduleEntry( + stageNum, nextTaskPriority++, unit, request + )); + } + + void needs(int unit, int request, int param) { + instSched->push( new ScheduleEntry( + stageNum, nextTaskPriority++, unit, request, param + )); + } + + }; +}; + + + + +#endif diff --git a/src/cpu/inorder/reg_dep_map.cc b/src/cpu/inorder/reg_dep_map.cc new file mode 100644 index 000000000..a405b1fb9 --- /dev/null +++ b/src/cpu/inorder/reg_dep_map.cc @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include "arch/isa_traits.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/reg_dep_map.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/cpu.hh" + +using namespace std; +using namespace TheISA; +using namespace ThePipeline; + +RegDepMap::RegDepMap(int size) +{ + regMap.resize(size); +} + +string +RegDepMap::name() +{ + return cpu->name() + ".RegDepMap"; +} + +void +RegDepMap::setCPU(InOrderCPU *_cpu) +{ + cpu = _cpu; +} + +void +RegDepMap::clear() +{ + regMap.clear(); +} + +void +RegDepMap::insert(DynInstPtr inst) +{ + int dest_regs = inst->numDestRegs(); + + DPRINTF(RegDepMap, "Setting Output Dependencies for [sn:%i] " + ", %s (dest. regs = %i).\n", + inst->seqNum, + inst->staticInst->getName(), + dest_regs); + + for (int i = 0; i < dest_regs; i++) { + int idx = inst->destRegIdx(i); + + //if (inst->numFPDestRegs()) + // idx += TheISA::FP_Base_DepTag; + + insert(idx, inst); + } +} + + +void +RegDepMap::insert(unsigned idx, DynInstPtr inst) +{ + DPRINTF(RegDepMap, "Inserting [sn:%i] onto dep. list for reg. idx %i.\n", + inst->seqNum, idx); + + regMap[idx].push_back(inst); + + inst->setRegDepEntry(); +} + +void +RegDepMap::remove(DynInstPtr inst) +{ + if (inst->isRegDepEntry()) { + DPRINTF(RegDepMap, "Removing [sn:%i]'s entries from reg. dep. map.\n", + inst->seqNum); + + int dest_regs = inst->numDestRegs(); + + for (int i = 0; i < dest_regs; i++) { + int idx = inst->destRegIdx(i); + remove(idx, inst); + } + } +} + +void +RegDepMap::remove(unsigned idx, DynInstPtr inst) +{ + std::list::iterator list_it = regMap[idx].begin(); + std::list::iterator list_end = regMap[idx].end(); + + while (list_it != list_end) { + if((*list_it) == inst) { + regMap[idx].erase(list_it); + break; + } + + list_it++; + } +} + +void +RegDepMap::removeFront(unsigned idx, DynInstPtr inst) +{ + std::list::iterator list_it = regMap[idx].begin(); + + DPRINTF(RegDepMap, "[tid:%u]: Removing dependency entry on phys. reg." + "%i for [sn:%i].\n", inst->readTid(), idx, inst->seqNum); + + assert(list_it != regMap[idx].end()); + + assert(inst == (*list_it)); + + regMap[idx].erase(list_it); +} + +bool +RegDepMap::canRead(unsigned idx, DynInstPtr inst) +{ + if (regMap[idx].size() == 0) + return true; + + std::list::iterator list_it = regMap[idx].begin(); + + if (inst->seqNum <= (*list_it)->seqNum) { + return true; + } else { + DPRINTF(RegDepMap, "[sn:%i] Can't read from RegFile, [sn:%i] has not written" + " it's value back yet.\n", inst->seqNum, (*list_it)->seqNum); + return false; + } +} + +ThePipeline::DynInstPtr +RegDepMap::canForward(unsigned reg_idx, unsigned src_idx, DynInstPtr inst) +{ + std::list::iterator list_it = regMap[reg_idx].begin(); + std::list::iterator list_end = regMap[reg_idx].end(); + + DynInstPtr forward_inst = NULL; + + // Look for first, oldest instruction + while (list_it != list_end && + (*list_it)->seqNum < inst->seqNum) { + forward_inst = (*list_it); + list_it++; + } + + if (forward_inst) { + if (forward_inst->isExecuted() && + forward_inst->readResultTime(src_idx) < curTick) { + return forward_inst; + } else { + DPRINTF(RegDepMap, "[sn:%i] Can't get value through forwarding, " + " [sn:%i] has not been executed yet.\n", + inst->seqNum, forward_inst->seqNum); + return NULL; + } + } else { + DPRINTF(RegDepMap, "[sn:%i] No instruction found to forward from.\n", + inst->seqNum); + return NULL; + } +} + +bool +RegDepMap::canWrite(unsigned idx, DynInstPtr inst) +{ + if (regMap[idx].size() == 0) + return true; + + std::list::iterator list_it = regMap[idx].begin(); + + if (inst->seqNum <= (*list_it)->seqNum) { + return true; + } else { + DPRINTF(RegDepMap, "[sn:%i] Can't write from RegFile: [sn:%i] has not written" + " it's value back yet.\n", inst->seqNum, (*list_it)->seqNum); + } + + return false; +} + +int +RegDepMap::depSize(unsigned idx) +{ + return regMap[idx].size(); +} + +ThePipeline::DynInstPtr +RegDepMap::findBypassInst(unsigned idx) +{ + std::list::iterator list_it = regMap[idx].begin(); + + if (depSize(idx) == 1) + return NULL; + + list_it++; + + while (list_it != regMap[idx].end()) { + if((*list_it)->isExecuted()) { + return *list_it; + break; + } + } + + return NULL; +} diff --git a/src/cpu/inorder/reg_dep_map.hh b/src/cpu/inorder/reg_dep_map.hh new file mode 100644 index 000000000..ba2a8c8a3 --- /dev/null +++ b/src/cpu/inorder/reg_dep_map.hh @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef CPU_INORDER_REG_DEP_MAP_HH +#define CPU_INORDER_REG_DEP_MAP_HH + +#include +#include + +#include "arch/isa_traits.hh" +#include "cpu/inorder/pipeline_traits.hh" + +class InOrderCPU; + +class RegDepMap +{ + typedef ThePipeline::DynInstPtr DynInstPtr; + + public: + RegDepMap(int size = TheISA::TotalNumRegs); + + ~RegDepMap() { } + + std::string name(); + + void setCPU(InOrderCPU *_cpu); + + /** Clear the Entire Map */ + void clear(); + + /** Insert all of a instruction's destination registers into map*/ + void insert(DynInstPtr inst); + + /** Insert an instruction into a specific destination register index onto map */ + void insert(unsigned idx, DynInstPtr inst); + + /** Remove all of a instruction's destination registers into map*/ + void remove(DynInstPtr inst); + + /** Remove a specific instruction and destination register index from map */ + void remove(unsigned idx, DynInstPtr inst); + + /** Remove Front instruction from a destination register */ + void removeFront(unsigned idx, DynInstPtr inst); + + /** Is the current instruction able to read from this destination register? */ + bool canRead(unsigned idx, DynInstPtr inst); + + /** Is the current instruction able to get a forwarded value from another instruction + * for this destination register? */ + DynInstPtr canForward(unsigned reg_idx, unsigned src_idx, DynInstPtr inst); + + /** find an instruction to forward/bypass a value from */ + DynInstPtr findBypassInst(unsigned idx); + + /** Is the current instruction able to write to this destination register? */ + bool canWrite(unsigned idx, DynInstPtr inst); + + /** Size of Dependency of Map */ + int depSize(unsigned idx); + + protected: + // Eventually make this a map of lists for + // efficiency sake! + std::vector > regMap; + + InOrderCPU *cpu; +}; + +#endif + + + + + + + diff --git a/src/cpu/inorder/resource.cc b/src/cpu/inorder/resource.cc new file mode 100644 index 000000000..3106628f0 --- /dev/null +++ b/src/cpu/inorder/resource.cc @@ -0,0 +1,434 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include +#include +#include "cpu/inorder/resource.hh" +#include "cpu/inorder/cpu.hh" +using namespace std; + +Resource::Resource(string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu) + : resName(res_name), id(res_id), + width(res_width), latency(res_latency), cpu(_cpu) +{ + // Use to deny a instruction a resource. + deniedReq = new ResourceRequest(this, NULL, 0, 0, 0, 0); +} + +void +Resource::init() +{ + // Set Up Resource Events to Appropriate Resource BandWidth + resourceEvent = new ResourceEvent[width]; + + initSlots(); +} + +void +Resource::initSlots() +{ + // Add available slot numbers for resource + for (int slot_idx = 0; slot_idx < width; slot_idx++) { + availSlots.push_back(slot_idx); + resourceEvent[slot_idx].init(this, slot_idx); + } +} + +std::string +Resource::name() +{ + return cpu->name() + "." + resName; +} + +void +Resource::regStats() +{ + instReqsProcessed + .name(name() + ".instReqsProcessed") + .desc("Number of Instructions Requests that completed in this resource."); +} + +int +Resource::slotsAvail() +{ + return availSlots.size(); +} + +int +Resource::slotsInUse() +{ + return width - availSlots.size(); +} + +void +Resource::freeSlot(int slot_idx) +{ + DPRINTF(RefCount, "Removing [tid:%i] [sn:%i]'s request from resource [slot:%i].\n", + reqMap[slot_idx]->inst->readTid(), + reqMap[slot_idx]->inst->seqNum, + slot_idx); + + // Put slot number on this resource's free list + availSlots.push_back(slot_idx); + + // Erase Request Pointer From Request Map + std::map::iterator req_it = reqMap.find(slot_idx); + + assert(req_it != reqMap.end()); + reqMap.erase(req_it); + +} + +// TODO: More efficiently search for instruction's slot within +// resource. +int +Resource::findSlot(DynInstPtr inst) +{ + map::iterator map_it = reqMap.begin(); + map::iterator map_end = reqMap.end(); + + int slot_num = -1; + + while (map_it != map_end) { + if ((*map_it).second->getInst()->seqNum == + inst->seqNum) { + slot_num = (*map_it).second->getSlot(); + } + map_it++; + } + + return slot_num; +} + +int +Resource::getSlot(DynInstPtr inst) +{ + int slot_num; + + if (slotsAvail() != 0) { + slot_num = availSlots[0]; + + vector::iterator vect_it = availSlots.begin(); + + assert(slot_num == *vect_it); + + availSlots.erase(vect_it); + } else { + DPRINTF(Resource, "[tid:%i]: No slots in resource " + "available to service [sn:%i].\n", inst->readTid(), + inst->seqNum); + slot_num = -1; + + map::iterator map_it = reqMap.begin(); + map::iterator map_end = reqMap.end(); + + while (map_it != map_end) { + if ((*map_it).second) { + DPRINTF(Resource, "Currently Serving request from: [tid:%i] [sn:%i].\n", + (*map_it).second->getInst()->readTid(), + (*map_it).second->getInst()->seqNum); + } + map_it++; + } + } + + return slot_num; +} + +ResReqPtr +Resource::request(DynInstPtr inst) +{ + // See if the resource is already serving this instruction. + // If so, use that request; + bool try_request = false; + int slot_num; + int stage_num; + ResReqPtr inst_req = findRequest(inst); + + if (inst_req) { + // If some preprocessing has to be done on instruction + // that has already requested once, then handle it here. + // update the 'try_request' variable if we should + // re-execute the request. + requestAgain(inst, try_request); + + slot_num = inst_req->getSlot(); + stage_num = inst_req->getStageNum(); + } else { + // Get new slot # for instruction + slot_num = getSlot(inst); + + if (slot_num != -1) { + // Get Stage # from Schedule Entry + stage_num = inst->resSched.top()->stageNum; + unsigned cmd = inst->resSched.top()->cmd; + + // Generate Resource Request + inst_req = getRequest(inst, stage_num, id, slot_num, cmd); + + if (inst->staticInst) { + DPRINTF(Resource, "[tid:%i]: [sn:%i] requesting this resource.\n", + inst->readTid(), inst->seqNum); + } else { + DPRINTF(Resource, "[tid:%i]: instruction requesting this resource.\n", + inst->readTid()); + } + + reqMap[slot_num] = inst_req; + + try_request = true; + } + } + + if (try_request) { + // Schedule execution of resource + scheduleExecution(slot_num); + } else { + inst_req = deniedReq; + rejectRequest(inst); + } + + return inst_req; +} + +void +Resource::requestAgain(DynInstPtr inst, bool &do_request) +{ + do_request = true; + + if (inst->staticInst) { + DPRINTF(Resource, "[tid:%i]: [sn:%i] requesting this resource again.\n", + inst->readTid(), inst->seqNum); + } else { + DPRINTF(Resource, "[tid:%i]: requesting this resource again.\n", + inst->readTid()); + } +} + +ResReqPtr +Resource::getRequest(DynInstPtr inst, int stage_num, int res_idx, + int slot_num, unsigned cmd) +{ + return new ResourceRequest(this, inst, stage_num, id, slot_num, + cmd); +} + +ResReqPtr +Resource::findRequest(DynInstPtr inst) +{ + map::iterator map_it = reqMap.begin(); + map::iterator map_end = reqMap.end(); + + while (map_it != map_end) { + if ((*map_it).second && + (*map_it).second->getInst() == inst) { + return (*map_it).second; + } + map_it++; + } + + return NULL; +} + +void +Resource::rejectRequest(DynInstPtr inst) +{ + DPRINTF(RefCount, "[tid:%i]: Unable to grant request for [sn:%i].\n", + inst->readTid(), inst->seqNum); +} + +void +Resource::execute(int slot_idx) +{ + DPRINTF(Resource, "[tid:%i]: Executing %s resource.\n", + reqMap[slot_idx]->getTid(), name()); + reqMap[slot_idx]->setCompleted(true); + reqMap[slot_idx]->fault = NoFault; + reqMap[slot_idx]->done(); +} + +void +Resource::deactivateThread(unsigned tid) +{ + // In the most basic case, deactivation means squashing everything + // from a particular thread + DynInstPtr dummy_inst = new InOrderDynInst(cpu, NULL, 0, tid); + squash(dummy_inst, 0, 0, tid); +} + +void +Resource::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num, unsigned tid) +{ + std::vector slot_remove_list; + + map::iterator map_it = reqMap.begin(); + map::iterator map_end = reqMap.end(); + + while (map_it != map_end) { + ResReqPtr req_ptr = (*map_it).second; + + if (req_ptr && + req_ptr->getInst()->readTid() == tid && + req_ptr->getInst()->seqNum > squash_seq_num) { + + DPRINTF(Resource, "[tid:%i]: Squashing [sn:%i].\n", + req_ptr->getInst()->readTid(), + req_ptr->getInst()->seqNum); + + int req_slot_num = req_ptr->getSlot(); + + unscheduleEvent(req_slot_num); + + // Mark request for later removal + cpu->reqRemoveList.push(req_ptr); + + // Mark slot for removal from resource + slot_remove_list.push_back(req_ptr->getSlot()); + } + + map_it++; + } + + // Now Delete Slot Entry from Req. Map + for (int i = 0; i < slot_remove_list.size(); i++) { + freeSlot(slot_remove_list[i]); + } +} + + +Tick +Resource::ticks(int num_cycles) +{ + return cpu->ticks(num_cycles); +} + + +void +Resource::scheduleExecution(int slot_num) +{ + int res_latency = getLatency(slot_num); + + if (res_latency >= 1) { + scheduleEvent(slot_num, res_latency); + } else { + execute(slot_num); + } +} + +void +Resource::scheduleEvent(int slot_idx, int delay) +{ + DPRINTF(Resource, "[tid:%i]: Scheduling event for [sn:%i] on tick %i.\n", + reqMap[slot_idx]->inst->readTid(), + reqMap[slot_idx]->inst->seqNum, + cpu->ticks(delay) + curTick); + resourceEvent[slot_idx].scheduleEvent(delay); +} + +bool +Resource::scheduleEvent(DynInstPtr inst, int delay) +{ + int slot_idx = findSlot(inst); + + if(slot_idx != -1) + resourceEvent[slot_idx].scheduleEvent(delay); + + return slot_idx; +} + +void +Resource::unscheduleEvent(int slot_idx) +{ + resourceEvent[slot_idx].unscheduleEvent(); +} + +bool +Resource::unscheduleEvent(DynInstPtr inst) +{ + int slot_idx = findSlot(inst); + + if(slot_idx != -1) + resourceEvent[slot_idx].unscheduleEvent(); + + return slot_idx; +} + +int ResourceRequest::resReqID = 0; + +int ResourceRequest::resReqCount = 0; + +void +ResourceRequest::done(bool completed) +{ + DPRINTF(Resource, "%s done with request from [sn:%i] [tid:%i].\n", + res->name(), inst->seqNum, inst->readTid()); + + setCompleted(completed); + + // Add to remove list + res->cpu->reqRemoveList.push(res->reqMap[slotNum]); + + // Free Slot So Another Instruction Can Use This Resource + res->freeSlot(slotNum); + + res->instReqsProcessed++; +} + +ResourceEvent::ResourceEvent() + : Event((Event::Priority)Resource_Event_Pri) +{ } + +ResourceEvent::ResourceEvent(Resource *res, int slot_idx) + : Event((Event::Priority)Resource_Event_Pri), resource(res), + slotIdx(slot_idx) +{ } + +void +ResourceEvent::init(Resource *res, int slot_idx) +{ + resource = res; + slotIdx = slot_idx; +} + +void +ResourceEvent::process() +{ + resource->execute(slotIdx); +} + +const char * +ResourceEvent::description() +{ + string desc = resource->name() + " event"; + + return desc.c_str(); +} diff --git a/src/cpu/inorder/resource.hh b/src/cpu/inorder/resource.hh new file mode 100644 index 000000000..e3536258d --- /dev/null +++ b/src/cpu/inorder/resource.hh @@ -0,0 +1,404 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __CPU_INORDER_RESOURCE_HH__ +#define __CPU_INORDER_RESOURCE_HH__ + +#include +#include +#include + +#include "cpu/inst_seq.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "sim/eventq.hh" +#include "sim/sim_object.hh" + +class Event; +class InOrderCPU; +class ResourceEvent; +class ResourceRequest; + +typedef ResourceRequest ResReq; +typedef ResourceRequest* ResReqPtr; + +class Resource { + public: + typedef ThePipeline::DynInstPtr DynInstPtr; + + friend class ResourceEvent; + friend class ResourceRequest; + + public: + Resource(std::string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu); + virtual ~Resource() {} + + /** Return name of this resource */ + virtual std::string name(); + + /** Define this function if resource, has a port to connect to an outside + * simulation object. + */ + virtual Port* getPort(const std::string &if_name, int idx) { return NULL; } + + /** Return ID for this resource */ + int getId() { return id; } + + /** Any extra initiliazation stuff can be set up using this function that + * should get called before the simulation starts (tick 0) + */ + virtual void init(); + virtual void initSlots(); + + /** Tasks to perform when simulation starts */ + //virtual void startup() { } + + /** Register Stats for this resource */ + virtual void regStats(); + + /** Resources that care about thread activation override this. */ + virtual void activateThread(unsigned tid) { } + + /** Deactivate Thread. Default action is to squash all instructions + * from deactivated thread. + */ + virtual void deactivateThread(unsigned tid); + + /** Resources that care when an instruction has been graduated + * can override this + */ + virtual void instGraduated(InstSeqNum seq_num,unsigned tid) { } + + /** Request usage of this resource. Returns a ResourceRequest object + * with all the necessary resource information + */ + virtual ResourceRequest* request(DynInstPtr inst); + + /** Get the next available slot in this resource. Instruction is passed + * so that resources can check the instruction before allocating a slot + * if necessary. + */ + virtual int getSlot(DynInstPtr inst); + + /** Find the slot that this instruction is using in a resource */ + virtual int findSlot(DynInstPtr inst); + + /** Free a resource slot */ + virtual void freeSlot(int slot_idx); + + /** Request usage of a resource for this instruction. If this instruction already + * has made this request to this resource, and that request is uncompleted + * this function will just return that request + */ + virtual ResourceRequest* getRequest(DynInstPtr _inst, int stage_num, + int res_idx, int slot_num, + unsigned cmd); + + /** Schedule Execution of This Resource For A Given Slot*/ + virtual void scheduleExecution(int slot_idx); + + /** Execute the function of this resource. The Default is action + * is to do nothing. More specific models will derive from this + * class and define their own execute function. + */ + virtual void execute(int slot_idx); + + /** Fetch on behalf of an instruction. Will check to see + * if instruction is actually in resource before + * trying to fetch. Needs to be defined for derived units. + */ + virtual Fault doFetchAccess(DynInstPtr inst) + { panic("doFetchAccess undefined for %s", name()); return NoFault; } + + /** Read/Write on behalf of an instruction. Will check to see + * if instruction is actually in resource before + * trying to do access.Needs to be defined for derived units. + */ + virtual Fault doDataAccess(DynInstPtr inst) + { panic("doDataAccess undefined for %s", name()); return NoFault; } + + /** Squash All Requests After This Seq Num */ + virtual void squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num, unsigned tid); + + /** The number of instructions available that this resource can + * can still process + */ + int slotsAvail(); + + /** The number of instructions using this resource */ + int slotsInUse(); + + /** Schedule resource event, regardless of its current state. */ + void scheduleEvent(int slot_idx, int delay); + + /** Find instruction in list, Schedule resource event, regardless of its current state. */ + bool scheduleEvent(DynInstPtr inst, int delay); + + /** Unschedule resource event, regardless of its current state. */ + void unscheduleEvent(int slot_idx); + + /** Unschedule resource event, regardless of its current state. */ + bool unscheduleEvent(DynInstPtr inst); + + /** Return the number of cycles in 'Tick' format */ + Tick ticks(int numCycles); + + /** Find the request that corresponds to this instruction */ + virtual ResReqPtr findRequest(DynInstPtr inst); + + /** */ + virtual void rejectRequest(DynInstPtr inst); + + /** Request a Resource again. Some resources have to special process this + * in subsequent accesses. + */ + virtual void requestAgain(DynInstPtr inst, bool &try_request); + + /** Return Latency of Resource */ + /* Can be overridden for complex cases */ + virtual int getLatency(int slot_num) { return latency; } + + protected: + /** The name of this resource */ + std::string resName; + + /** ID of the resource. The Resource Pool uses this # to identify this + * resource. + */ + int id; + + /** The number of instructions the resource can simultaneously + * process. + */ + int width; + + /** Constant latency for this resource. + * Note: Dynamic latency resources set this to 0 and + * manage the latency themselves + */ + const int latency; + + public: + /** Mapping of slot-numbers to the resource-request pointers */ + std::map reqMap; + + /** A list of all the available execution slots for this resource. + * This correlates with the actual resource event idx. + */ + std::vector availSlots; + + /** The CPU(s) that this resource interacts with */ + InOrderCPU *cpu; + + protected: + /** The resource event used for scheduling resource slots on the + * event queue + */ + ResourceEvent *resourceEvent; + + /** Default denied resource request pointer*/ + ResReqPtr deniedReq; + + public: + ///////////////////////////////////////////////////////////////// + // + // DEFAULT RESOURCE STATISTICS + // + ///////////////////////////////////////////////////////////////// + /** Number of Instruction Requests the Resource Processes */ + Stats::Scalar<> instReqsProcessed; +}; + +class ResourceEvent : public Event +{ + public: + /** Pointer to the CPU. */ + Resource *resource; + + + /// Resource events that come before other associated CPU events + /// (for InOrderCPU model). + /// check src/sim/eventq.hh for more event priorities. + enum InOrderPriority { + Resource_Event_Pri = 45, + }; + + /** The Resource Slot that this event is servicing */ + int slotIdx; + + /** Constructs a resource event. */ + ResourceEvent(); + ResourceEvent(Resource *res, int slot_idx); + virtual ~ResourceEvent() { } + + /** Initialize data for this resource event. */ + virtual void init(Resource *res, int slot_idx); + + /** Processes a resource event. */ + virtual void process(); + + /** Returns the description of the resource event. */ + const char *description(); + + /** Set slot idx for event */ + void setSlot(int slot) { slotIdx = slot; } + + /** Schedule resource event, regardless of its current state. */ + void scheduleEvent(int delay) + { + if (squashed()) + mainEventQueue.reschedule(this, curTick + resource->ticks(delay)); + else if (!scheduled()) + mainEventQueue.schedule(this, curTick + resource->ticks(delay)); + } + + /** Unschedule resource event, regardless of its current state. */ + void unscheduleEvent() + { + if (scheduled()) + squash(); + } + +}; + +class ResourceRequest +{ + public: + typedef ThePipeline::DynInstPtr DynInstPtr; + + static int resReqID; + + static int resReqCount; + + public: + ResourceRequest(Resource *_res, DynInstPtr _inst, int stage_num, + int res_idx, int slot_num, unsigned _cmd) + : res(_res), inst(_inst), cmd(_cmd), stageNum(stage_num), + resIdx(res_idx), slotNum(slot_num), completed(false), + squashed(false), processing(false), waiting(false) + { + reqID = resReqID++; + resReqCount++; + DPRINTF(ResReqCount, "Res. Req %i created. resReqCount=%i.\n", reqID, resReqCount); + + if (resReqCount > 100) { + fatal("Too many undeleted resource requests. Memory leak?\n"); + } + } + + virtual ~ResourceRequest() + { + resReqCount--; + DPRINTF(ResReqCount, "Res. Req %i deleted. resReqCount=%i.\n", reqID, resReqCount); + } + + int reqID; + + /** Acknowledge that this is a request is done and remove + * from resource. + */ + void done(bool completed = true); + + ///////////////////////////////////////////// + // + // GET RESOURCE REQUEST IDENTIFICATION / INFO + // + ///////////////////////////////////////////// + /** Get Resource Index */ + int getResIdx() { return resIdx; } + + /** Get Slot Number */ + int getSlot() { return slotNum; } + + /** Get Stage Number */ + int getStageNum() { return stageNum; } + + /** Set/Get Thread Ids */ + void setTid(unsigned _tid) { tid = _tid; } + int getTid() { return tid; } + + /** Instruction this request is for */ + DynInstPtr getInst() { return inst; } + + /** Data from this request. Overridden by Resource-Specific Request + * Objects + */ + virtual PacketDataPtr getData() { return NULL; } + + /** Pointer to Resource that is being used */ + Resource *res; + + /** Instruction being used */ + DynInstPtr inst; + + /** Fault Associated With This Resource Request */ + Fault fault; + + /** Command For This Resource */ + unsigned cmd; + + //////////////////////////////////////// + // + // GET RESOURCE REQUEST STATUS FROM VARIABLES + // + //////////////////////////////////////// + /** Get/Set Completed variables */ + bool isCompleted() { return completed; } + void setCompleted(bool cond = true) { completed = cond; } + + /** Get/Set Squashed variables */ + bool isSquashed() { return squashed; } + void setSquashed() { squashed = true; } + + /** Get/Set IsProcessing variables */ + bool isProcessing() { return processing; } + void setProcessing() { processing = true; } + + /** Get/Set IsWaiting variables */ + bool isWaiting() { return waiting; } + void setWaiting() { waiting = true; } + + protected: + /** Resource Identification */ + int tid; + int stageNum; + int resIdx; + int slotNum; + + /** Resource Status */ + bool completed; + bool squashed; + bool processing; + bool waiting; +}; + +#endif //__CPU_INORDER_RESOURCE_HH__ diff --git a/src/cpu/inorder/resource_pool.9stage.cc b/src/cpu/inorder/resource_pool.9stage.cc new file mode 100644 index 000000000..4a0258e71 --- /dev/null +++ b/src/cpu/inorder/resource_pool.9stage.cc @@ -0,0 +1,357 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include "cpu/inorder/resource_pool.hh" +#include "cpu/inorder/resources/resource_list.hh" + +#include +#include + +using namespace std; +using namespace ThePipeline; + +ResourcePool::ResourcePool(InOrderCPU *_cpu, InOrderCPUParams *params) + : cpu(_cpu) +{ + //@todo: use this function to instantiate the resources in resource pool. This will help in the + //auto-generation of this pipeline model. + //ThePipeline::addResources(resources, memObjects); + + // Declare Resource Objects + // name - id - bandwidth - latency - CPU - Parameters + // -------------------------------------------------- + resources.push_back(new FetchSeqUnit("Fetch-Seq-Unit", FetchSeq, StageWidth * 2, 0, _cpu, params)); + + resources.push_back(new TLBUnit("I-TLB", ITLB, StageWidth, 0, _cpu, params)); + + memObjects.push_back(ICache); + resources.push_back(new CacheUnit("icache_port", ICache, StageWidth * MaxThreads, 0, _cpu, params)); + + resources.push_back(new DecodeUnit("Decode-Unit", Decode, StageWidth, 0, _cpu, params)); + + resources.push_back(new BranchPredictor("Branch-Predictor", BPred, StageWidth, 0, _cpu, params)); + + for (int i = 0; i < params->numberOfThreads; i++) { + char fbuff_name[20]; + sprintf(fbuff_name, "Fetch-Buffer-T%i", i); + resources.push_back(new InstBuffer(fbuff_name, FetchBuff + i, 4, 0, _cpu, params)); + } + + resources.push_back(new UseDefUnit("RegFile-Manager", RegManager, StageWidth * MaxThreads, 0, _cpu, params)); + + resources.push_back(new AGENUnit("AGEN-Unit", AGEN, StageWidth, 0, _cpu, params)); + + resources.push_back(new ExecutionUnit("Execution-Unit", ExecUnit, StageWidth, 0, _cpu, params)); + + resources.push_back(new MultDivUnit("Mult-Div-Unit", MDU, 5, 0, _cpu, params)); + + resources.push_back(new TLBUnit("D-TLB", DTLB, StageWidth, 0, _cpu, params)); + + memObjects.push_back(DCache); + resources.push_back(new CacheUnit("dcache_port", DCache, StageWidth * MaxThreads, 0, _cpu, params)); + + resources.push_back(new GraduationUnit("Graduation-Unit", Grad, StageWidth * MaxThreads, 0, _cpu, params)); +} + +void +ResourcePool::init() +{ + for (int i=0; i < resources.size(); i++) { + resources[i]->init(); + } +} + +string +ResourcePool::name() +{ + return cpu->name() + ".ResourcePool"; +} + + +void +ResourcePool::regStats() +{ + DPRINTF(Resource, "Registering Stats Throughout Resource Pool.\n"); + + int num_resources = resources.size(); + + for (int idx = 0; idx < num_resources; idx++) { + resources[idx]->regStats(); + } +} + +Port * +ResourcePool::getPort(const std::string &if_name, int idx) +{ + for (int i = 0; i < memObjects.size(); i++) { + int obj_idx = memObjects[i]; + Port *port = resources[obj_idx]->getPort(if_name, idx); + if (port != NULL) { + return port; + } + } + + return NULL; +} + +unsigned +ResourcePool::getPortIdx(const std::string &port_name) +{ + for (int i = 0; i < memObjects.size(); i++) { + unsigned obj_idx = memObjects[i]; + Port *port = resources[obj_idx]->getPort(port_name, obj_idx); + if (port != NULL) { + return obj_idx; + } + } + + return 0; +} + +ResReqPtr +ResourcePool::request(int res_idx, DynInstPtr inst) +{ + //Make Sure This is a valid resource ID + assert(res_idx >= 0 && res_idx < resources.size()); + + return resources[res_idx]->request(inst); +} + +void +ResourcePool::squash(DynInstPtr inst, int res_idx, InstSeqNum done_seq_num, int tid) +{ + resources[res_idx]->squash(inst, ThePipeline::NumStages-1, done_seq_num, tid); +} + +int +ResourcePool::slotsAvail(int res_idx) +{ + return resources[res_idx]->slotsAvail(); +} + +int +ResourcePool::slotsInUse(int res_idx) +{ + return resources[res_idx]->slotsInUse(); +} + +void +ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst, + int delay, int res_idx, int tid) +{ + assert(delay >= 0); + + ResPoolEvent *res_pool_event = new ResPoolEvent(this); + + switch (e_type) + { + case InOrderCPU::ActivateThread: + { + DPRINTF(Resource, "Scheduling Activate Thread Resource Pool Event for tick %i.\n", + curTick + delay); + res_pool_event->setEvent(e_type, + inst, + inst->squashingStage, + inst->bdelaySeqNum, + inst->readTid()); + res_pool_event->schedule(curTick + cpu->cycles(delay)); + + } + break; + + case InOrderCPU::SuspendThread: + case InOrderCPU::DeallocateThread: + { + DPRINTF(Resource, "Scheduling Deactivate Thread Resource Pool Event for tick %i.\n", + curTick + delay); + + res_pool_event->setEvent(e_type, + inst, + inst->squashingStage, + inst->bdelaySeqNum, + tid); + + res_pool_event->schedule(curTick + cpu->cycles(delay)); + + } + break; + + case ResourcePool::InstGraduated: + { + DPRINTF(Resource, "Scheduling Inst-Graduated Resource Pool Event for tick %i.\n", + curTick + delay); + + res_pool_event->setEvent(e_type, + inst, + inst->squashingStage, + inst->seqNum, + inst->readTid()); + res_pool_event->schedule(curTick + cpu->cycles(delay)); + + } + break; + + case ResourcePool::SquashAll: + { + DPRINTF(Resource, "Scheduling Squash Resource Pool Event for tick %i.\n", + curTick + delay); + res_pool_event->setEvent(e_type, + inst, + inst->squashingStage, + inst->bdelaySeqNum, + inst->readTid()); + res_pool_event->schedule(curTick + cpu->cycles(delay)); + + } + break; + + default: + DPRINTF(Resource, "Ignoring Unrecognized CPU Event Type #%i.\n", e_type); + ; // If Resource Pool doesnt recognize event, we ignore it. + } +} + +void +ResourcePool::unscheduleEvent(int res_idx, DynInstPtr inst) +{ + resources[res_idx]->unscheduleEvent(inst); +} + +void +ResourcePool::squashAll(DynInstPtr inst, int stage_num, InstSeqNum done_seq_num, unsigned tid) +{ + DPRINTF(Resource, "[tid:%i] Stage %i squashing all instructions above [sn:%i].\n", + stage_num, tid, done_seq_num); + + int num_resources = resources.size(); + + for (int idx = 0; idx < num_resources; idx++) { + resources[idx]->squash(inst, stage_num, done_seq_num, tid); + } +} + +void +ResourcePool::activateAll(unsigned tid) +{ + DPRINTF(Resource, "[tid:%i] Broadcasting Thread Activation to all resources.\n", + tid); + + int num_resources = resources.size(); + + for (int idx = 0; idx < num_resources; idx++) { + resources[idx]->activateThread(tid); + } +} + +void +ResourcePool::deactivateAll(unsigned tid) +{ + DPRINTF(Resource, "[tid:%i] Broadcasting Thread Deactivation to all resources.\n", + tid); + + int num_resources = resources.size(); + + for (int idx = 0; idx < num_resources; idx++) { + resources[idx]->deactivateThread(tid); + } +} + +void +ResourcePool::instGraduated(InstSeqNum seq_num,unsigned tid) +{ + DPRINTF(Resource, "[tid:%i] Broadcasting [sn:%i] graduation to all resources.\n", + tid, seq_num); + + int num_resources = resources.size(); + + for (int idx = 0; idx < num_resources; idx++) { + resources[idx]->instGraduated(seq_num, tid); + } +} + +ResourcePool::ResPoolEvent::ResPoolEvent(ResourcePool *_resPool) + : Event(&mainEventQueue, CPU_Tick_Pri), + resPool(_resPool) +{ eventType = (InOrderCPU::CPUEventType) Default; } + +void +ResourcePool::ResPoolEvent::process() +{ + switch (eventType) + { + case InOrderCPU::ActivateThread: + resPool->activateAll(tid); + break; + + case InOrderCPU::SuspendThread: + case InOrderCPU::DeallocateThread: + resPool->deactivateAll(tid); + break; + + case ResourcePool::InstGraduated: + resPool->instGraduated(seqNum, tid); + break; + + case ResourcePool::SquashAll: + resPool->squashAll(inst, stageNum, seqNum, tid); + break; + + default: + fatal("Unrecognized Event Type"); + } + + resPool->cpu->cpuEventRemoveList.push(this); +} + + +const char * +ResourcePool::ResPoolEvent::description() +{ + return "Resource Pool event"; +} + +/** Schedule resource event, regardless of its current state. */ +void +ResourcePool::ResPoolEvent::scheduleEvent(int delay) +{ + if (squashed()) + reschedule(curTick + resPool->cpu->cycles(delay)); + else if (!scheduled()) + schedule(curTick + resPool->cpu->cycles(delay)); +} + +/** Unschedule resource event, regardless of its current state. */ +void +ResourcePool::ResPoolEvent::unscheduleEvent() +{ + if (scheduled()) + squash(); +} diff --git a/src/cpu/inorder/resource_pool.cc b/src/cpu/inorder/resource_pool.cc new file mode 100644 index 000000000..94af68c7a --- /dev/null +++ b/src/cpu/inorder/resource_pool.cc @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include "cpu/inorder/resource_pool.hh" +#include "cpu/inorder/resources/resource_list.hh" + +#include +#include + +using namespace std; +using namespace ThePipeline; + +ResourcePool::ResourcePool(InOrderCPU *_cpu, ThePipeline::Params *params) + : cpu(_cpu) +{ + //@todo: use this function to instantiate the resources in resource pool. This will help in the + //auto-generation of this pipeline model. + //ThePipeline::addResources(resources, memObjects); + + // Declare Resource Objects + // name - id - bandwidth - latency - CPU - Parameters + // -------------------------------------------------- + resources.push_back(new FetchSeqUnit("Fetch-Seq-Unit", FetchSeq, StageWidth * 2, 0, _cpu, params)); + + resources.push_back(new TLBUnit("I-TLB", ITLB, StageWidth, 0, _cpu, params)); + + memObjects.push_back(ICache); + resources.push_back(new CacheUnit("icache_port", ICache, StageWidth * MaxThreads, 0, _cpu, params)); + + resources.push_back(new DecodeUnit("Decode-Unit", Decode, StageWidth, 0, _cpu, params)); + + resources.push_back(new BranchPredictor("Branch-Predictor", BPred, StageWidth, 0, _cpu, params)); + + resources.push_back(new InstBuffer("Fetch-Buffer-T0", FetchBuff, 4, 0, _cpu, params)); + + resources.push_back(new UseDefUnit("RegFile-Manager", RegManager, StageWidth * MaxThreads, 0, _cpu, params)); + + resources.push_back(new AGENUnit("AGEN-Unit", AGEN, StageWidth, 0, _cpu, params)); + + resources.push_back(new ExecutionUnit("Execution-Unit", ExecUnit, StageWidth, 0, _cpu, params)); + + resources.push_back(new MultDivUnit("Mult-Div-Unit", MDU, 5, 0, _cpu, params)); + + resources.push_back(new TLBUnit("D-TLB", DTLB, StageWidth, 0, _cpu, params)); + + memObjects.push_back(DCache); + resources.push_back(new CacheUnit("dcache_port", DCache, StageWidth * MaxThreads, 0, _cpu, params)); + + resources.push_back(new GraduationUnit("Graduation-Unit", Grad, StageWidth * MaxThreads, 0, _cpu, params)); + + resources.push_back(new InstBuffer("Fetch-Buffer-T1", FetchBuff2, 4, 0, _cpu, params)); +} + +void +ResourcePool::init() +{ + for (int i=0; i < resources.size(); i++) { + DPRINTF(Resource, "Initializing resource: %s.\n", resources[i]->name()); + + resources[i]->init(); + } +} + +string +ResourcePool::name() +{ + return cpu->name() + ".ResourcePool"; +} + + +void +ResourcePool::regStats() +{ + DPRINTF(Resource, "Registering Stats Throughout Resource Pool.\n"); + + int num_resources = resources.size(); + + for (int idx = 0; idx < num_resources; idx++) { + resources[idx]->regStats(); + } +} + +Port * +ResourcePool::getPort(const std::string &if_name, int idx) +{ + DPRINTF(Resource, "Binding %s in Resource Pool.\n", if_name); + + for (int i = 0; i < memObjects.size(); i++) { + int obj_idx = memObjects[i]; + Port *port = resources[obj_idx]->getPort(if_name, idx); + if (port != NULL) { + DPRINTF(Resource, "%s set to resource %s(#%i) in Resource Pool.\n", if_name, + resources[obj_idx]->name(), obj_idx); + return port; + } + } + + return NULL; +} + +unsigned +ResourcePool::getPortIdx(const std::string &port_name) +{ + DPRINTF(Resource, "Finding Port Idx for %s.\n", port_name); + + for (int i = 0; i < memObjects.size(); i++) { + unsigned obj_idx = memObjects[i]; + Port *port = resources[obj_idx]->getPort(port_name, obj_idx); + if (port != NULL) { + DPRINTF(Resource, "Returning Port Idx %i for %s.\n", obj_idx, port_name); + return obj_idx; + } + } + + return 0; +} + +ResReqPtr +ResourcePool::request(int res_idx, DynInstPtr inst) +{ + //Make Sure This is a valid resource ID + assert(res_idx >= 0 && res_idx < resources.size()); + + return resources[res_idx]->request(inst); +} + +void +ResourcePool::squash(DynInstPtr inst, int res_idx, InstSeqNum done_seq_num, int tid) +{ + resources[res_idx]->squash(inst, ThePipeline::NumStages-1, done_seq_num, tid); +} + +int +ResourcePool::slotsAvail(int res_idx) +{ + return resources[res_idx]->slotsAvail(); +} + +int +ResourcePool::slotsInUse(int res_idx) +{ + return resources[res_idx]->slotsInUse(); +} + +void +ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst, + int delay, int res_idx, int tid) +{ + assert(delay >= 0); + + ResPoolEvent *res_pool_event = new ResPoolEvent(this); + + switch (e_type) + { + case InOrderCPU::ActivateThread: + { + DPRINTF(Resource, "Scheduling Activate Thread Resource Pool Event for tick %i.\n", + curTick + delay); + res_pool_event->setEvent(e_type, + inst, + inst->squashingStage, + inst->bdelaySeqNum, + inst->readTid()); + mainEventQueue.schedule(res_pool_event, curTick + cpu->ticks(delay)); + + } + break; + + case InOrderCPU::SuspendThread: + case InOrderCPU::DeallocateThread: + { + DPRINTF(Resource, "Scheduling Deactivate Thread Resource Pool Event for tick %i.\n", + curTick + delay); + + res_pool_event->setEvent(e_type, + inst, + inst->squashingStage, + inst->bdelaySeqNum, + tid); + + mainEventQueue.schedule(res_pool_event, curTick + cpu->ticks(delay)); + + } + break; + + case ResourcePool::InstGraduated: + { + DPRINTF(Resource, "Scheduling Inst-Graduated Resource Pool Event for tick %i.\n", + curTick + delay); + + res_pool_event->setEvent(e_type, + inst, + inst->squashingStage, + inst->seqNum, + inst->readTid()); + mainEventQueue.schedule(res_pool_event, curTick + cpu->ticks(delay)); + + } + break; + + case ResourcePool::SquashAll: + { + DPRINTF(Resource, "Scheduling Squash Resource Pool Event for tick %i.\n", + curTick + delay); + res_pool_event->setEvent(e_type, + inst, + inst->squashingStage, + inst->bdelaySeqNum, + inst->readTid()); + mainEventQueue.schedule(res_pool_event, curTick + cpu->ticks(delay)); + + } + break; + + default: + DPRINTF(Resource, "Ignoring Unrecognized CPU Event Type #%i.\n", e_type); + ; // If Resource Pool doesnt recognize event, we ignore it. + } +} + +void +ResourcePool::unscheduleEvent(int res_idx, DynInstPtr inst) +{ + resources[res_idx]->unscheduleEvent(inst); +} + +void +ResourcePool::squashAll(DynInstPtr inst, int stage_num, InstSeqNum done_seq_num, unsigned tid) +{ + DPRINTF(Resource, "[tid:%i] Stage %i squashing all instructions above [sn:%i].\n", + stage_num, tid, done_seq_num); + + int num_resources = resources.size(); + + for (int idx = 0; idx < num_resources; idx++) { + resources[idx]->squash(inst, stage_num, done_seq_num, tid); + } +} + +void +ResourcePool::activateAll(unsigned tid) +{ + DPRINTF(Resource, "[tid:%i] Broadcasting Thread Activation to all resources.\n", + tid); + + int num_resources = resources.size(); + + for (int idx = 0; idx < num_resources; idx++) { + resources[idx]->activateThread(tid); + } +} + +void +ResourcePool::deactivateAll(unsigned tid) +{ + DPRINTF(Resource, "[tid:%i] Broadcasting Thread Deactivation to all resources.\n", + tid); + + int num_resources = resources.size(); + + for (int idx = 0; idx < num_resources; idx++) { + resources[idx]->deactivateThread(tid); + } +} + +void +ResourcePool::instGraduated(InstSeqNum seq_num,unsigned tid) +{ + DPRINTF(Resource, "[tid:%i] Broadcasting [sn:%i] graduation to all resources.\n", + tid, seq_num); + + int num_resources = resources.size(); + + for (int idx = 0; idx < num_resources; idx++) { + resources[idx]->instGraduated(seq_num, tid); + } +} + +ResourcePool::ResPoolEvent::ResPoolEvent(ResourcePool *_resPool) + : Event(CPU_Tick_Pri), + resPool(_resPool) +{ eventType = (InOrderCPU::CPUEventType) Default; } + +void +ResourcePool::ResPoolEvent::process() +{ + switch (eventType) + { + case InOrderCPU::ActivateThread: + resPool->activateAll(tid); + break; + + case InOrderCPU::SuspendThread: + case InOrderCPU::DeallocateThread: + resPool->deactivateAll(tid); + break; + + case ResourcePool::InstGraduated: + resPool->instGraduated(seqNum, tid); + break; + + case ResourcePool::SquashAll: + resPool->squashAll(inst, stageNum, seqNum, tid); + break; + + default: + fatal("Unrecognized Event Type"); + } + + resPool->cpu->cpuEventRemoveList.push(this); +} + + +const char * +ResourcePool::ResPoolEvent::description() +{ + return "Resource Pool event"; +} + +/** Schedule resource event, regardless of its current state. */ +void +ResourcePool::ResPoolEvent::scheduleEvent(int delay) +{ + if (squashed()) + mainEventQueue.reschedule(this,curTick + resPool->cpu->ticks(delay)); + else if (!scheduled()) + mainEventQueue.schedule(this,curTick + resPool->cpu->ticks(delay)); +} + +/** Unschedule resource event, regardless of its current state. */ +void +ResourcePool::ResPoolEvent::unscheduleEvent() +{ + if (scheduled()) + squash(); +} diff --git a/src/cpu/inorder/resource_pool.hh b/src/cpu/inorder/resource_pool.hh new file mode 100644 index 000000000..35fce7db7 --- /dev/null +++ b/src/cpu/inorder/resource_pool.hh @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __CPU_INORDER_RESOURCE_POOL_HH__ +#define __CPU_INORDER_RESOURCE_POOL_HH__ + +#include +#include +#include + +#include "cpu/inst_seq.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/resource.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/params.hh" +#include "params/InOrderCPU.hh" +#include "cpu/inorder/cpu.hh" +#include "sim/eventq.hh" +#include "sim/sim_object.hh" + +class Event; +class InOrderCPU; +class Resource; +class ResourceEvent; + +class ResourcePool { + public: + typedef InOrderDynInst::DynInstPtr DynInstPtr; + + public: + // List of Resource Pool Events that extends + // the list started by the CPU + // NOTE(1): Resource Pool also uses event list + // CPUEventType defined in inorder/cpu.hh + enum ResPoolEventType { + InstGraduated = InOrderCPU::NumCPUEvents, + SquashAll, + Default + }; + + class ResPoolEvent : public Event + { + protected: + /** Resource Pool */ + ResourcePool *resPool; + + public: + InOrderCPU::CPUEventType eventType; + + DynInstPtr inst; + + InstSeqNum seqNum; + + int stageNum; + + unsigned tid; + + public: + /** Constructs a resource event. */ + ResPoolEvent(ResourcePool *_resPool); + + /** Set Type of Event To Be Scheduled */ + void setEvent(InOrderCPU::CPUEventType e_type, + DynInstPtr _inst, + int stage_num, + InstSeqNum seq_num, + unsigned _tid) + { + eventType = e_type; + inst = _inst; + seqNum = seq_num; + stageNum = stage_num; + tid = _tid; + } + + /** Processes a resource event. */ + virtual void process(); + + /** Returns the description of the resource event. */ + const char *description(); + + /** Schedule Event */ + void scheduleEvent(int delay); + + /** Unschedule This Event */ + void unscheduleEvent(); + }; + + public: + ResourcePool(InOrderCPU *_cpu, ThePipeline::Params *params); + virtual ~ResourcePool() {} + + std::string name(); + + std::string name(int res_idx) { return resources[res_idx]->name(); } + + void init(); + + /** Register Statistics in All Resources */ + void regStats(); + + /** Returns a specific port. */ + Port* getPort(const std::string &if_name, int idx); + + /** Returns a specific port. */ + unsigned getPortIdx(const std::string &if_name); + + Resource* getResource(int res_idx) { return resources[res_idx]; } + + /** Request usage of this resource. Returns -1 if not granted and + * a positive request tag if granted. + */ + ResReqPtr request(int res_idx, DynInstPtr inst); + + /** Squash The Resource */ + void squash(DynInstPtr inst, int res_idx, InstSeqNum done_seq_num, int tid); + + /** Squash All Resources in Pool after Done Seq. Num */ + void squashAll(DynInstPtr inst, int stage_num, + InstSeqNum done_seq_num, unsigned tid); + + /** Activate Thread in all resources */ + void activateAll(unsigned tid); + + /** De-Activate Thread in all resources */ + void deactivateAll(unsigned tid); + + /** Broadcast graduation to all resources */ + void instGraduated(InstSeqNum seq_num,unsigned tid); + + /** The number of instructions available that a resource can + * can still process. + */ + int slotsAvail(int res_idx); + + /** The number of instructions using a resource */ + int slotsInUse(int res_idx); + + /** Schedule resource event, regardless of its current state. */ + void scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst = NULL, + int delay = 0, int res_idx = 0, int tid = 0); + + /** UnSchedule resource event, regardless of its current state. */ + void unscheduleEvent(int res_idx, DynInstPtr inst); + + /** Tasks to perform when simulation starts */ + virtual void startup() { } + + /** The CPU(s) that this resource interacts with */ + InOrderCPU *cpu; + + DynInstPtr dummyInst[ThePipeline::MaxThreads]; + + private: + std::vector resources; + + std::vector memObjects; + +}; + +#endif //__CPU_INORDER_RESOURCE_HH__ diff --git a/src/cpu/inorder/resources/agen_unit.cc b/src/cpu/inorder/resources/agen_unit.cc new file mode 100644 index 000000000..8e3d25656 --- /dev/null +++ b/src/cpu/inorder/resources/agen_unit.cc @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include "cpu/inorder/resources/agen_unit.hh" + +AGENUnit::AGENUnit(std::string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params) + : Resource(res_name, res_id, res_width, res_latency, _cpu) +{ } + +void +AGENUnit::execute(int slot_num) +{ + ResourceRequest* agen_req = reqMap[slot_num]; + DynInstPtr inst = reqMap[slot_num]->inst; + Fault fault = reqMap[slot_num]->fault; + int tid; + int seq_num = inst->seqNum; + + tid = inst->readTid(); + agen_req->fault = NoFault; + + switch (agen_req->cmd) + { + case GenerateAddr: + { + // Load/Store Instruction + if (inst->isMemRef()) { + DPRINTF(Resource, "[tid:%i] Generating Address for [sn:%i] (%s).\n", + tid, inst->seqNum, inst->staticInst->getName()); + + + // We are not handdling Prefetches quite yet + if (inst->isDataPrefetch() || inst->isInstPrefetch()) { + panic("Prefetches arent handled yet.\n"); + } else { + if (inst->isLoad()) { + fault = inst->calcEA(); + inst->setMemAddr(inst->getEA()); + //inst->setExecuted(); + + DPRINTF(Resource, "[tid:%i] [sn:%i] Effective address calculated to be: " + "%#x.\n", tid, inst->seqNum, inst->getEA()); + } else if (inst->isStore()) { + fault = inst->calcEA(); + inst->setMemAddr(inst->getEA()); + + DPRINTF(Resource, "[tid:%i] [sn:%i] Effective address calculated to be: " + "%#x.\n", tid, inst->seqNum, inst->getEA()); + } else { + panic("Unexpected memory type!\n"); + } + + if (fault == NoFault) { + agen_req->done(); + } else { + fatal("%s encountered @ [sn:%i]",fault->name(), seq_num); + } + } + } else { + DPRINTF(Resource, "[tid:] Ignoring non-memory instruction [sn:%i].\n", tid, seq_num); + agen_req->done(); + } + } + break; + + default: + fatal("Unrecognized command to %s", resName); + } +} diff --git a/src/cpu/inorder/resources/agen_unit.hh b/src/cpu/inorder/resources/agen_unit.hh new file mode 100644 index 000000000..2010c9fa6 --- /dev/null +++ b/src/cpu/inorder/resources/agen_unit.hh @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __CPU_INORDER_AGEN_UNIT_HH__ +#define __CPU_INORDER_AGEN_UNIT_HH__ + +#include +#include +#include + +#include "cpu/inorder/resource.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/cpu.hh" +#include "cpu/inorder/params.hh" + +class AGENUnit : public Resource { + public: + typedef InOrderDynInst::DynInstPtr DynInstPtr; + + public: + AGENUnit(std::string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params); + virtual ~AGENUnit() {} + + enum Command { + GenerateAddr + }; + + virtual void execute(int slot_num); + + protected: + /** @todo: Add Resource Stats Here */ +}; + +#endif //__CPU_INORDER_DECODE_UNIT_HH__ diff --git a/src/cpu/inorder/resources/bpred_unit.cc b/src/cpu/inorder/resources/bpred_unit.cc new file mode 100644 index 000000000..66d0779a2 --- /dev/null +++ b/src/cpu/inorder/resources/bpred_unit.cc @@ -0,0 +1,426 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + */ + +#include +#include + +#include "base/trace.hh" +#include "base/traceflags.hh" +#include "cpu/inorder/resources/bpred_unit.hh" + +using namespace std; +using namespace ThePipeline; + +BPredUnit::BPredUnit(ThePipeline::Params *params) + : BTB(params->BTBEntries, + params->BTBTagSize, + params->instShiftAmt) +{ + // Setup the selected predictor. + if (params->predType == "local") { + localBP = new LocalBP(params->localPredictorSize, + params->localCtrBits, + params->instShiftAmt); + predictor = Local; + } else if (params->predType == "tournament") { + tournamentBP = new TournamentBP(params->localPredictorSize, + params->localCtrBits, + params->localHistoryTableSize, + params->localHistoryBits, + params->globalPredictorSize, + params->globalHistoryBits, + params->globalCtrBits, + params->choicePredictorSize, + params->choiceCtrBits, + params->instShiftAmt); + predictor = Tournament; + } else { + fatal("Invalid BP selected!"); + } + + for (int i=0; i < ThePipeline::MaxThreads; i++) + RAS[i].init(params->RASSize); +} + + +void +BPredUnit::regStats() +{ + lookups + .name(name() + ".BPredUnit.lookups") + .desc("Number of BP lookups") + ; + + condPredicted + .name(name() + ".BPredUnit.condPredicted") + .desc("Number of conditional branches predicted") + ; + + condIncorrect + .name(name() + ".BPredUnit.condIncorrect") + .desc("Number of conditional branches incorrect") + ; + + BTBLookups + .name(name() + ".BPredUnit.BTBLookups") + .desc("Number of BTB lookups") + ; + + BTBHits + .name(name() + ".BPredUnit.BTBHits") + .desc("Number of BTB hits") + ; + + BTBCorrect + .name(name() + ".BPredUnit.BTBCorrect") + .desc("Number of correct BTB predictions (this stat may not " + "work properly.") + ; + + usedRAS + .name(name() + ".BPredUnit.usedRAS") + .desc("Number of times the RAS was used to get a target.") + ; + + RASIncorrect + .name(name() + ".BPredUnit.RASInCorrect") + .desc("Number of incorrect RAS predictions.") + ; +} + + +void +BPredUnit::switchOut() +{ + // Clear any state upon switch out. + for (int i = 0; i < ThePipeline::MaxThreads; ++i) { + squash(0, i); + } +} + + +void +BPredUnit::takeOverFrom() +{ + // Can reset all predictor state, but it's not necessarily better + // than leaving it be. +/* + for (int i = 0; i < ThePipeline::MaxThreads; ++i) + RAS[i].reset(); + + BP.reset(); + BTB.reset(); +*/ +} + + +bool +BPredUnit::predict(DynInstPtr &inst, Addr &PC, unsigned tid) +{ + // See if branch predictor predicts taken. + // If so, get its target addr either from the BTB or the RAS. + // Save off record of branch stuff so the RAS can be fixed + // up once it's done. + + using TheISA::MachInst; + + bool pred_taken = false; + Addr target; + + ++lookups; + + void *bp_history = NULL; + + if (inst->isUncondCtrl()) { + DPRINTF(Resource, "BranchPred: [tid:%i] Unconditional control.\n", tid); + pred_taken = true; + // Tell the BP there was an unconditional branch. + BPUncond(bp_history); + + if (inst->isReturn() && RAS[tid].empty()) { + DPRINTF(Resource, "BranchPred: [tid:%i] RAS is empty, predicting " + "false.\n", tid); + pred_taken = false; + } + } else { + ++condPredicted; + + pred_taken = BPLookup(PC, bp_history); + + DPRINTF(Resource, "BranchPred: [tid:%i]: Branch predictor predicted %i " + "for PC %#x\n", + tid, pred_taken, inst->readPC()); + } + + PredictorHistory predict_record(inst->seqNum, PC, pred_taken, + bp_history, tid); + + // Now lookup in the BTB or RAS. + if (pred_taken) { + if (inst->isReturn()) { + ++usedRAS; + + // If it's a function return call, then look up the address + // in the RAS. + target = RAS[tid].top(); + + // Record the top entry of the RAS, and its index. + predict_record.usedRAS = true; + predict_record.RASIndex = RAS[tid].topIdx(); + predict_record.RASTarget = target; + + assert(predict_record.RASIndex < 16); + + RAS[tid].pop(); + + DPRINTF(Resource, "BranchPred: [tid:%i]: Instruction %#x is a return, " + "RAS predicted target: %#x, RAS index: %i.\n", + tid, inst->readPC(), target, predict_record.RASIndex); + } else { + ++BTBLookups; + + if (inst->isCall()) { + RAS[tid].push(PC + sizeof(MachInst)); + + // Record that it was a call so that the top RAS entry can + // be popped off if the speculation is incorrect. + predict_record.wasCall = true; + + DPRINTF(Resource, "BranchPred: [tid:%i] Instruction %#x was a call" + ", adding %#x to the RAS.\n", + tid, inst->readPC(), PC + sizeof(MachInst)); + } + + if (inst->isCall() && + inst->isUncondCtrl() && + inst->isDirectCtrl()) { + target = inst->branchTarget(); + + DPRINTF(Fetch, "BranchPred: [tid:%i]: Setting %#x predicted" + " target to %#x.\n", + tid, inst->readPC(), target); + } else if (BTB.valid(PC, tid)) { + ++BTBHits; + + // If it's not a return, use the BTB to get the target addr. + target = BTB.lookup(PC, tid); + + DPRINTF(Resource, "BranchPred: [tid:%i]: Instruction %#x predicted" + " target is %#x.\n", + tid, inst->readPC(), target); + } else { + DPRINTF(Resource, "BranchPred: [tid:%i]: BTB doesn't have a " + "valid entry.\n",tid); + pred_taken = false; + } + } + } + + if (pred_taken) { + // Set the PC and the instruction's predicted target. + PC = target; + inst->setPredTarg(target); + } else { + PC = PC + sizeof(MachInst); + inst->setPredTarg(PC); + } + + predHist[tid].push_front(predict_record); + + DPRINTF(Resource, "[tid:%i] predHist.size(): %i\n", tid, predHist[tid].size()); + + inst->setBranchPred(pred_taken); + + return pred_taken; +} + + +void +BPredUnit::update(const InstSeqNum &done_sn, unsigned tid) +{ + DPRINTF(Resource, "BranchPred: [tid:%i]: Commiting branches until sequence" + "number %lli.\n", tid, done_sn); + + while (!predHist[tid].empty() && + predHist[tid].back().seqNum <= done_sn) { + // Update the branch predictor with the correct results. + BPUpdate(predHist[tid].back().PC, + predHist[tid].back().predTaken, + predHist[tid].back().bpHistory); + + predHist[tid].pop_back(); + } +} + + +void +BPredUnit::squash(const InstSeqNum &squashed_sn, unsigned tid) +{ + History &pred_hist = predHist[tid]; + + while (!pred_hist.empty() && + pred_hist.front().seqNum > squashed_sn) { + if (pred_hist.front().usedRAS) { + DPRINTF(Resource, "BranchPred: [tid:%i]: Restoring top of RAS to: %i," + " target: %#x.\n", + tid, + pred_hist.front().RASIndex, + pred_hist.front().RASTarget); + + RAS[tid].restore(pred_hist.front().RASIndex, + pred_hist.front().RASTarget); + + } else if (pred_hist.front().wasCall) { + DPRINTF(Resource, "BranchPred: [tid:%i]: Removing speculative entry " + "added to the RAS.\n",tid); + + RAS[tid].pop(); + } + + // This call should delete the bpHistory. + BPSquash(pred_hist.front().bpHistory); + + pred_hist.pop_front(); + } + +} + + +void +BPredUnit::squash(const InstSeqNum &squashed_sn, + const Addr &corr_target, + const bool actually_taken, + unsigned tid) +{ + // Now that we know that a branch was mispredicted, we need to undo + // all the branches that have been seen up until this branch and + // fix up everything. + + History &pred_hist = predHist[tid]; + + ++condIncorrect; + + DPRINTF(Resource, "BranchPred: [tid:%i]: Squashing from sequence number %i, " + "setting target to %#x.\n", + tid, squashed_sn, corr_target); + + squash(squashed_sn, tid); + + // If there's a squash due to a syscall, there may not be an entry + // corresponding to the squash. In that case, don't bother trying to + // fix up the entry. + if (!pred_hist.empty()) { + assert(pred_hist.front().seqNum == squashed_sn); + if (pred_hist.front().usedRAS) { + ++RASIncorrect; + } + + BPUpdate(pred_hist.front().PC, actually_taken, + pred_hist.front().bpHistory); + + BTB.update(pred_hist.front().PC, corr_target, tid); + pred_hist.pop_front(); + } +} + + +void +BPredUnit::BPUncond(void * &bp_history) +{ + // Only the tournament predictor cares about unconditional branches. + if (predictor == Tournament) { + tournamentBP->uncondBr(bp_history); + } +} + + +void +BPredUnit::BPSquash(void *bp_history) +{ + if (predictor == Local) { + localBP->squash(bp_history); + } else if (predictor == Tournament) { + tournamentBP->squash(bp_history); + } else { + panic("Predictor type is unexpected value!"); + } +} + + +bool +BPredUnit::BPLookup(Addr &inst_PC, void * &bp_history) +{ + if (predictor == Local) { + return localBP->lookup(inst_PC, bp_history); + } else if (predictor == Tournament) { + return tournamentBP->lookup(inst_PC, bp_history); + } else { + panic("Predictor type is unexpected value!"); + } +} + + +void +BPredUnit::BPUpdate(Addr &inst_PC, bool taken, void *bp_history) +{ + if (predictor == Local) { + localBP->update(inst_PC, taken, bp_history); + } else if (predictor == Tournament) { + tournamentBP->update(inst_PC, taken, bp_history); + } else { + panic("Predictor type is unexpected value!"); + } +} + + +void +BPredUnit::dump() +{ + /*typename History::iterator pred_hist_it; + + for (int i = 0; i < ThePipeline::MaxThreads; ++i) { + if (!predHist[i].empty()) { + pred_hist_it = predHist[i].begin(); + + cprintf("predHist[%i].size(): %i\n", i, predHist[i].size()); + + while (pred_hist_it != predHist[i].end()) { + cprintf("[sn:%lli], PC:%#x, tid:%i, predTaken:%i, " + "bpHistory:%#x\n", + (*pred_hist_it).seqNum, (*pred_hist_it).PC, + (*pred_hist_it).tid, (*pred_hist_it).predTaken, + (*pred_hist_it).bpHistory); + pred_hist_it++; + } + + cprintf("\n"); + } + }*/ +} diff --git a/src/cpu/inorder/resources/bpred_unit.hh b/src/cpu/inorder/resources/bpred_unit.hh new file mode 100644 index 000000000..b945922a7 --- /dev/null +++ b/src/cpu/inorder/resources/bpred_unit.hh @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + * Korey Sewell + */ + +#ifndef __CPU_INORDER_BPRED_UNIT_HH__ +#define __CPU_INORDER_BPRED_UNIT_HH__ + +// For Addr type. +#include "arch/isa_traits.hh" +#include "base/statistics.hh" +#include "cpu/inst_seq.hh" + +//#include "cpu/inorder/params.hh" +#include "cpu/o3/2bit_local_pred.hh" +#include "cpu/o3/btb.hh" +#include "cpu/o3/ras.hh" +#include "cpu/o3/tournament_pred.hh" +#include "params/InOrderCPU.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/pipeline_traits.hh" + +#include + +/** + * Basically a wrapper class to hold both the branch predictor + * and the BTB. + */ +class BPredUnit +{ + private: + + enum PredType { + Local, + Tournament + }; + + PredType predictor; + + public: + + /** + * @param params The params object, that has the size of the BP and BTB. + */ + BPredUnit(ThePipeline::Params *params); + + /** + * Registers statistics. + */ + void regStats(); + + void switchOut(); + + void takeOverFrom(); + + /** + * Predicts whether or not the instruction is a taken branch, and the + * target of the branch if it is taken. + * @param inst The branch instruction. + * @param PC The predicted PC is passed back through this parameter. + * @param tid The thread id. + * @return Returns if the branch is taken or not. + */ + bool predict(ThePipeline::DynInstPtr &inst, Addr &PC, unsigned tid); + + // @todo: Rename this function. + void BPUncond(void * &bp_history); + + /** + * Tells the branch predictor to commit any updates until the given + * sequence number. + * @param done_sn The sequence number to commit any older updates up until. + * @param tid The thread id. + */ + void update(const InstSeqNum &done_sn, unsigned tid); + + /** + * Squashes all outstanding updates until a given sequence number. + * @param squashed_sn The sequence number to squash any younger updates up + * until. + * @param tid The thread id. + */ + void squash(const InstSeqNum &squashed_sn, unsigned tid); + + /** + * Squashes all outstanding updates until a given sequence number, and + * corrects that sn's update with the proper address and taken/not taken. + * @param squashed_sn The sequence number to squash any younger updates up + * until. + * @param corr_target The correct branch target. + * @param actually_taken The correct branch direction. + * @param tid The thread id. + */ + void squash(const InstSeqNum &squashed_sn, const Addr &corr_target, + bool actually_taken, unsigned tid); + + /** + * @param bp_history Pointer to the history object. The predictor + * will need to update any state and delete the object. + */ + void BPSquash(void *bp_history); + + /** + * Looks up a given PC in the BP to see if it is taken or not taken. + * @param inst_PC The PC to look up. + * @param bp_history Pointer that will be set to an object that + * has the branch predictor state associated with the lookup. + * @return Whether the branch is taken or not taken. + */ + bool BPLookup(Addr &inst_PC, void * &bp_history); + + /** + * Looks up a given PC in the BTB to see if a matching entry exists. + * @param inst_PC The PC to look up. + * @return Whether the BTB contains the given PC. + */ + bool BTBValid(Addr &inst_PC) + { return BTB.valid(inst_PC, 0); } + + /** + * Looks up a given PC in the BTB to get the predicted target. + * @param inst_PC The PC to look up. + * @return The address of the target of the branch. + */ + Addr BTBLookup(Addr &inst_PC) + { return BTB.lookup(inst_PC, 0); } + + /** + * Updates the BP with taken/not taken information. + * @param inst_PC The branch's PC that will be updated. + * @param taken Whether the branch was taken or not taken. + * @param bp_history Pointer to the branch predictor state that is + * associated with the branch lookup that is being updated. + * @todo Make this update flexible enough to handle a global predictor. + */ + void BPUpdate(Addr &inst_PC, bool taken, void *bp_history); + + /** + * Updates the BTB with the target of a branch. + * @param inst_PC The branch's PC that will be updated. + * @param target_PC The branch's target that will be added to the BTB. + */ + void BTBUpdate(Addr &inst_PC, Addr &target_PC) + { BTB.update(inst_PC, target_PC,0); } + + void dump(); + + private: + struct PredictorHistory { + /** + * Makes a predictor history struct that contains any + * information needed to update the predictor, BTB, and RAS. + */ + PredictorHistory(const InstSeqNum &seq_num, const Addr &inst_PC, + const bool pred_taken, void *bp_history, + const unsigned _tid) + : seqNum(seq_num), PC(inst_PC), RASTarget(0), + RASIndex(0), tid(_tid), predTaken(pred_taken), usedRAS(0), + wasCall(0), bpHistory(bp_history) + { } + + /** The sequence number for the predictor history entry. */ + InstSeqNum seqNum; + + /** The PC associated with the sequence number. */ + Addr PC; + + /** The RAS target (only valid if a return). */ + Addr RASTarget; + + /** The RAS index of the instruction (only valid if a call). */ + unsigned RASIndex; + + /** The thread id. */ + unsigned tid; + + /** Whether or not it was predicted taken. */ + bool predTaken; + + /** Whether or not the RAS was used. */ + bool usedRAS; + + /** Whether or not the instruction was a call. */ + bool wasCall; + + /** Pointer to the history object passed back from the branch + * predictor. It is used to update or restore state of the + * branch predictor. + */ + void *bpHistory; + }; + + typedef std::list History; + + /** + * The per-thread predictor history. This is used to update the predictor + * as instructions are committed, or restore it to the proper state after + * a squash. + */ + History predHist[ThePipeline::MaxThreads]; + + /** The local branch predictor. */ + LocalBP *localBP; + + /** The tournament branch predictor. */ + TournamentBP *tournamentBP; + + /** The BTB. */ + DefaultBTB BTB; + + /** The per-thread return address stack. */ + ReturnAddrStack RAS[ThePipeline::MaxThreads]; + + /** Stat for number of BP lookups. */ + Stats::Scalar<> lookups; + /** Stat for number of conditional branches predicted. */ + Stats::Scalar<> condPredicted; + /** Stat for number of conditional branches predicted incorrectly. */ + Stats::Scalar<> condIncorrect; + /** Stat for number of BTB lookups. */ + Stats::Scalar<> BTBLookups; + /** Stat for number of BTB hits. */ + Stats::Scalar<> BTBHits; + /** Stat for number of times the BTB is correct. */ + Stats::Scalar<> BTBCorrect; + /** Stat for number of times the RAS is used to get a target. */ + Stats::Scalar<> usedRAS; + /** Stat for number of times the RAS is incorrect. */ + Stats::Scalar<> RASIncorrect; +}; + +#endif // __CPU_INORDER_BPRED_UNIT_HH__ diff --git a/src/cpu/inorder/resources/branch_predictor.cc b/src/cpu/inorder/resources/branch_predictor.cc new file mode 100644 index 000000000..b563a3057 --- /dev/null +++ b/src/cpu/inorder/resources/branch_predictor.cc @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include "cpu/inorder/resources/branch_predictor.hh" + +using namespace std; +using namespace TheISA; +using namespace ThePipeline; + +BranchPredictor::BranchPredictor(std::string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params) + : Resource(res_name, res_id, res_width, res_latency, _cpu), + branchPred(params) +{ + instSize = sizeof(MachInst); +} + +void +BranchPredictor::regStats() +{ + predictedTaken + .name(name() + ".predictedTaken") + .desc("Number of Branches Predicted As Taken (True)."); + + predictedNotTaken + .name(name() + ".predictedNotTaken") + .desc("Number of Branches Predicted As Not Taken (False)."); + + Resource::regStats(); +} + +void +BranchPredictor::execute(int slot_num) +{ + // After this is working, change this to a reinterpret cast + // for performance considerations + ResourceRequest* bpred_req = reqMap[slot_num]; + + DynInstPtr inst = bpred_req->inst; + int tid = inst->readTid(); + int seq_num = inst->seqNum; + //int stage_num = bpred_req->getStageNum(); + + bpred_req->fault = NoFault; + + switch (bpred_req->cmd) + { + case PredictBranch: + { + Addr pred_PC = inst->readNextPC(); + + if (inst->isControl()) { + // If predicted, the pred_PC will be updated to new target value + // If not, the pred_PC be updated to pc+8 + bool predict_taken = branchPred.predict(inst, pred_PC, tid); + + if (predict_taken) { + DPRINTF(Resource, "[tid:%i]: [sn:%i]: Branch predicted true.\n", + tid, seq_num); + + inst->setPredTarg(pred_PC); + + predictedTaken++; + } else { + DPRINTF(Resource, "[tid:%i]: [sn:%i]: Branch predicted false.\n", + tid, seq_num); + + if (inst->isCondDelaySlot()) + { + inst->setPredTarg(inst->readPC() + (2 * instSize)); + } else { + inst->setPredTarg(pred_PC); + } + + predictedNotTaken++; + } + + inst->setBranchPred(predict_taken); + + DPRINTF(Resource, "[tid:%i]: [sn:%i]: Predicted PC is %08p.\n", + tid, seq_num, pred_PC); + + } else { + DPRINTF(Resource, "[tid:%i]: Ignoring [sn:%i] because this isn't " + "a control instruction.\n", tid, seq_num); + } + + bpred_req->done(); + } + break; + + case UpdatePredictor: + { + DPRINTF(Resource, "[tid:%i]: [sn:%i]: Updating Branch Predictor.\n", + tid, seq_num); + + + branchPred.update(seq_num, tid); + + bpred_req->done(); + } + break; + + default: + fatal("Unrecognized command to %s", resName); + } +} + +void +BranchPredictor::squash(DynInstPtr inst, int squash_stage, + InstSeqNum squash_seq_num, unsigned tid) +{ + DPRINTF(Resource, "Squashing...\n"); + branchPred.squash(squash_seq_num, tid); +} + +void +BranchPredictor::instGraduated(InstSeqNum seq_num,unsigned tid) +{ + branchPred.update(seq_num, tid); +} diff --git a/src/cpu/inorder/resources/branch_predictor.hh b/src/cpu/inorder/resources/branch_predictor.hh new file mode 100644 index 000000000..66eb1afe8 --- /dev/null +++ b/src/cpu/inorder/resources/branch_predictor.hh @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __CPU_INORDER_BRANCH_PREDICTOR_HH__ +#define __CPU_INORDER_BRANCH_PREDICTOR_HH__ + +#include +#include +#include + +#include "cpu/inorder/resource.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/resources/bpred_unit.hh" +#include "cpu/inorder/cpu.hh" +//#include "cpu/inorder/params.hh" + +class BranchPredictor : public Resource { + public: + typedef ThePipeline::DynInstPtr DynInstPtr; + + public: + enum Command { + PredictBranch, + UpdatePredictor + }; + + public: + BranchPredictor(std::string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params); + + virtual void regStats(); + + virtual void execute(int slot_num); + + virtual void squash(DynInstPtr inst, int stage_num, + InstSeqNum squash_seq_num, unsigned tid); + + virtual void instGraduated(InstSeqNum seq_num,unsigned tid); + + protected: + /** List of instructions this resource is currently + * processing. + */ + BPredUnit branchPred; + + int instSize; + + ///////////////////////////////////////////////////////////////// + // + // RESOURCE STATISTICS + // + ///////////////////////////////////////////////////////////////// + Stats::Scalar<> predictedTaken; + Stats::Scalar<> predictedNotTaken; + +}; + +#endif //__CPU_INORDER_INST_BUFF_UNIT_HH__ diff --git a/src/cpu/inorder/resources/cache_unit.cc b/src/cpu/inorder/resources/cache_unit.cc new file mode 100644 index 000000000..79ca7a096 --- /dev/null +++ b/src/cpu/inorder/resources/cache_unit.cc @@ -0,0 +1,609 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include +#include +#include "arch/isa_traits.hh" +#include "arch/mips/locked_mem.hh" +#include "arch/utility.hh" +#include "cpu/inorder/resources/cache_unit.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/cpu.hh" +#include "mem/request.hh" + +using namespace std; +using namespace TheISA; +using namespace ThePipeline; + + +Tick +CacheUnit::CachePort::recvAtomic(PacketPtr pkt) +{ + panic("DefaultFetch doesn't expect recvAtomic callback!"); + return curTick; +} + +void +CacheUnit::CachePort::recvFunctional(PacketPtr pkt) +{ + panic("DefaultFetch doesn't expect recvFunctional callback!"); +} + +void +CacheUnit::CachePort::recvStatusChange(Status status) +{ + if (status == RangeChange) + return; + + panic("DefaultFetch doesn't expect recvStatusChange callback!"); +} + +bool +CacheUnit::CachePort::recvTiming(Packet *pkt) +{ + cachePortUnit->processCacheCompletion(pkt); + return true; +} + +void +CacheUnit::CachePort::recvRetry() +{ + cachePortUnit->recvRetry(); +} + +CacheUnit::CacheUnit(string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params) + : Resource(res_name, res_id, res_width, res_latency, _cpu), + retryPkt(NULL), retrySlot(-1) +{ + //cacheData.resize(res_width); + //slotStatus = new CachePortStatus[width]; + //fetchPC = new Addr[width]; + cachePort = new CachePort(this); + + cacheBlocked = false; +} + + +Port * +CacheUnit::getPort(const std::string &if_name, int idx) +{ + if (if_name == resName) + return cachePort; + else + return NULL; +} + +int +CacheUnit::getSlot(DynInstPtr inst) +{ + if (!inst->validMemAddr()) { + panic("Mem. Addr. must be set before requesting cache access.\n"); + } + + Addr req_addr = inst->getMemAddr(); + + if (resName == "icache_port" || + find(addrList.begin(), addrList.end(), req_addr) == addrList.end()) { + + int new_slot = Resource::getSlot(inst); + + if (new_slot != -1) { + inst->memTime = curTick; + addrList.push_back(req_addr); + addrMap[req_addr] = inst->seqNum; + DPRINTF(InOrderCachePort, "[tid:%i]: [sn:%i]: Address %08p added to dependency list.\n", + inst->readTid(), inst->seqNum, req_addr); + return new_slot; + } else { + return -1; + } + + + } else { + DPRINTF(InOrderCachePort,"Denying request because there is an outstanding" + " request to/for addr. %08p. by [sn:%i] @ tick %i\n", + req_addr, addrMap[req_addr], inst->memTime); + return -1; + } +} + +void +CacheUnit::freeSlot(int slot_num) +{ + std::vector::iterator vect_it = find(addrList.begin(), addrList.end(), + reqMap[slot_num]->inst->getMemAddr()); + assert(vect_it != addrList.end()); + + DPRINTF(InOrderCachePort, "[tid:%i]: Address %08p removed from dependency list.\n", + reqMap[slot_num]->inst->readTid(), (*vect_it)); + + addrList.erase(vect_it); + + Resource::freeSlot(slot_num); +} + +ResReqPtr +CacheUnit::getRequest(DynInstPtr inst, int stage_num, int res_idx, + int slot_num, unsigned cmd) +{ + ScheduleEntry* sched_entry = inst->resSched.top(); + + if (!inst->validMemAddr()) { + panic("Mem. Addr. must be set before requesting cache access.\n"); + } + + int req_size = 0; + MemCmd::Command pkt_cmd; + + if (sched_entry->cmd == InitiateReadData) { + pkt_cmd = MemCmd::ReadReq; + req_size = inst->getMemAccSize(); + + DPRINTF(InOrderCachePort, "[tid:%i]: %i byte Read request from [sn:%i] for addr %08p.\n", + inst->readTid(), req_size, inst->seqNum, inst->getMemAddr()); + } else if (sched_entry->cmd == InitiateWriteData) { + pkt_cmd = MemCmd::WriteReq; + req_size = inst->getMemAccSize(); + + + DPRINTF(InOrderCachePort, "[tid:%i]: %i byte Write request from [sn:%i] for addr %08p.\n", + inst->readTid(), req_size, inst->seqNum, inst->getMemAddr()); + } else if (sched_entry->cmd == InitiateFetch){ + pkt_cmd = MemCmd::ReadReq; + req_size = sizeof(MachInst); //@TODO: mips16e + + DPRINTF(InOrderCachePort, "[tid:%i]: %i byte Fetch request from [sn:%i] for addr %08p.\n", + inst->readTid(), req_size, inst->seqNum, inst->getMemAddr()); + } else { + panic("%i: Unexpected request type (%i) to %s", curTick, sched_entry->cmd, name()); + } + + return new CacheRequest(this, inst, stage_num, id, slot_num, + sched_entry->cmd, req_size, pkt_cmd, + 0/*flags*/, this->cpu->readCpuId()); +} + +void +CacheUnit::requestAgain(DynInstPtr inst, bool &service_request) +{ + //service_request = false; + + CacheReqPtr cache_req = dynamic_cast(findRequest(inst)); + assert(cache_req); + + // Check to see if this instruction is requesting the same command + // or a different one + if (cache_req->cmd != inst->resSched.top()->cmd) { + // If different, then update command in the request + cache_req->cmd = inst->resSched.top()->cmd; + DPRINTF(InOrderCachePort, "[tid:%i]: [sn:%i]: Updating the command for this " + "instruction.\n", inst->readTid(), inst->seqNum); + + service_request = true; + } else { + // If same command, just check to see if memory access was completed + // but dont try to re-execute + DPRINTF(InOrderCachePort, "[tid:%i]: [sn:%i]: requesting this resource again.\n", + inst->readTid(), inst->seqNum); + + service_request = true; + } + +} + +void +CacheUnit::execute(int slot_num) +{ + if (cacheBlocked) { + DPRINTF(InOrderCachePort, "Cache Blocked. Cannot Access.\n"); + return; + } + + CacheReqPtr cache_req = dynamic_cast(reqMap[slot_num]); + assert(cache_req); + + DynInstPtr inst = cache_req->inst; + int tid; + tid = inst->readTid(); + int seq_num; + seq_num = inst->seqNum; + //int stage_num = cache_req->getStageNum(); + + cache_req->fault = NoFault; + + switch (cache_req->cmd) + { + case InitiateFetch: + { + DPRINTF(InOrderCachePort, + "[tid:%u]: Initiating fetch access to %s for addr. %08p\n", + tid, name(), cache_req->inst->getMemAddr()); + + DPRINTF(InOrderCachePort, + "[tid:%u]: Fetching new cache block from addr: %08p\n", + tid, cache_req->memReq->getVaddr()); + + inst->setCurResSlot(slot_num); + doDataAccess(inst); + } + break; + + case CompleteFetch: + { + if (cache_req->isMemAccComplete()) { + DPRINTF(InOrderCachePort, + "[tid:%i]: Completing Fetch Access for [sn:%i]\n", + tid, inst->seqNum); + + MachInst mach_inst = cache_req->dataPkt->get(); + + //@TODO: May Need This Function for Endianness-Compatibility + //mach_inst = gtoh(*reinterpret_cast(&cacheData[tid][offset])); + + DPRINTF(InOrderCachePort, + "[tid:%i]: Fetched instruction is %08p\n", + tid, mach_inst); + + //ExtMachInst ext_inst + // = TheISA::makeExtMI(mach_inst, cpu->tcBase(tid)); + + inst->setMachInst(mach_inst); + inst->setASID(tid); + inst->setThreadState(cpu->thread[tid]); + + DPRINTF(InOrderStage, "[tid:%i]: Instruction [sn:%i] is: %s\n", + tid, seq_num, inst->staticInst->disassemble(inst->PC)); + + // Set Up More TraceData info + if (inst->traceData) { + inst->traceData->setStaticInst(inst->staticInst); + inst->traceData->setPC(inst->readPC()); + } + + cache_req->done(); + } else { + DPRINTF(InOrderCachePort, "[tid:%i]: [sn:%i]: Unable to Complete Fetch Access.\n", + tid, inst->seqNum); + DPRINTF(InOrderStall, "STALL: [tid:%i]: Fetch miss from %08p.\n", + tid, cache_req->inst->readPC()); + cache_req->setCompleted(false); + } + } + break; + + case InitiateReadData: + case InitiateWriteData: + { + DPRINTF(InOrderCachePort, "[tid:%u]: Initiating data access to %s " + "for addr. %08p\n", + tid, name(), cache_req->inst->getMemAddr()); + + inst->setCurResSlot(slot_num); + //inst->memAccess(); + inst->initiateAcc(); + } + break; + + case CompleteReadData: + case CompleteWriteData: + { + DPRINTF(InOrderCachePort, + "[tid:%i]: [sn:%i]: Trying to Complete Data Access.\n", + tid, inst->seqNum); + if (cache_req->isMemAccComplete()) { + cache_req->done(); + } else { + DPRINTF(InOrderStall, "STALL: [tid:%i]: Data miss from %08p\n", + tid, cache_req->inst->getMemAddr()); + cache_req->setCompleted(false); + } + } + break; + + default: + fatal("Unrecognized command to %s", resName); + } +} + +Fault +CacheUnit::doDataAccess(DynInstPtr inst) +{ + Fault fault = NoFault; + int tid = 0; + + tid = inst->readTid(); + + CacheReqPtr cache_req + = dynamic_cast(reqMap[inst->getCurResSlot()]); + assert(cache_req); + + cache_req->dataPkt = new CacheReqPacket(cache_req, cache_req->pktCmd, + Packet::Broadcast); + + if (cache_req->dataPkt->isRead()) { + cache_req->dataPkt->dataStatic(cache_req->reqData); + } else if (cache_req->dataPkt->isWrite()) { + cache_req->dataPkt->dataStatic(&cache_req->inst->storeData); + + } + + cache_req->dataPkt->time = curTick; + + bool do_access = true; // flag to suppress cache access + + Request *memReq = cache_req->dataPkt->req; + + if (cache_req->dataPkt->isWrite() && memReq->isLocked()) { + assert(cache_req->inst->isStoreConditional()); + DPRINTF(InOrderCachePort, "Evaluating Store Conditional access.\n"); + do_access = TheISA::handleLockedWrite(cpu, memReq); + } + + + DPRINTF(InOrderCachePort, "[tid:%i] [sn:%i] attempting to access cache..\n", tid, inst->seqNum); + + //@TODO: If you want to ignore failed store conditional accesses, then + // enable this. However, this might skew memory stats because + // the failed store conditional access will get ignored. + // - Remove optionality here ... + if (1/*do_access*/) { + if (!cachePort->sendTiming(cache_req->dataPkt)) { + DPRINTF(InOrderCachePort, "[tid:%i] [sn:%i] is waiting to retry request.\n", tid, inst->seqNum); + + retrySlot = cache_req->getSlot(); + retryReq = cache_req; + retryPkt = cache_req->dataPkt; + + cacheStatus = cacheWaitRetry; + + //cacheBlocked = true; + + DPRINTF(InOrderStall, "STALL: \n"); + + cache_req->setCompleted(false); + } else { + DPRINTF(InOrderCachePort, "[tid:%i] [sn:%i] is now waiting for cache response.\n", tid, inst->seqNum); + cache_req->setCompleted(); + cache_req->setMemAccPending(); + cacheStatus = cacheWaitResponse; + cacheBlocked = false; + } + } else if (!do_access && memReq->isLocked()){ + // Store-Conditional instructions complete even if they "failed" + assert(cache_req->inst->isStoreConditional()); + cache_req->setCompleted(true); + + DPRINTF(LLSC, "[tid:%i]: T%i Ignoring Failed Store Conditional Access.\n", + tid, tid); + + cache_req->dataPkt->req->setExtraData(0); + + processCacheCompletion(cache_req->dataPkt); + + // Automatically set these since we ignored the memory access + //cache_req->setMemAccPending(false); + //cache_req->setMemAccCompleted(); + } else { + // Make cache request again since access due to + // inability to access + DPRINTF(InOrderStall, "STALL: \n"); + cache_req->setCompleted(false); + } + + return fault; +} + +void +CacheUnit::processCacheCompletion(PacketPtr pkt) +{ + // Cast to correct packet type + CacheReqPacket* cache_pkt = dynamic_cast(pkt); + assert(cache_pkt); + + if (cache_pkt->cacheReq->isSquashed()) { + DPRINTF(InOrderCachePort, + "Ignoring completion of squashed access, [tid:%i] [sn:%i].\n", + cache_pkt->cacheReq->getInst()->readTid(), + cache_pkt->cacheReq->getInst()->seqNum); + + cache_pkt->cacheReq->done(); + return; + } else { + DPRINTF(InOrderCachePort, + "[tid:%u]: [sn:%i]: Waking from cache access to addr. %08p.\n", + cache_pkt->cacheReq->getInst()->readTid(), + cache_pkt->cacheReq->getInst()->seqNum, + cache_pkt->cacheReq->getInst()->getMemAddr()); + } + + // Cast to correct request type + CacheRequest *cache_req = dynamic_cast( + findRequest(cache_pkt->cacheReq->getInst())); + assert(cache_req); + +#if TRACING_ON + // Get resource request info + unsigned tid = 0; +#endif + + //tid = pkt->req->getThreadNum(); + unsigned stage_num = cache_req->getStageNum(); + DynInstPtr inst = cache_req->inst; + + if (!cache_req->isSquashed()) { + if (inst->resSched.top()->cmd == CompleteFetch) { + DPRINTF(InOrderCachePort, + "[tid:%u]: [sn:%i]: Processing fetch access.\n", + tid, inst->seqNum); + } else if (inst->staticInst && inst->isMemRef()) { + DPRINTF(InOrderCachePort, + "[tid:%u]: [sn:%i]: Processing cache access.\n", + tid, inst->seqNum); + + inst->completeAcc(pkt); + + if (inst->isLoad()) { + assert(cache_pkt->isRead()); + + if (cache_pkt->req->isLocked()) { + DPRINTF(InOrderCachePort, "[tid:%u]: Handling Load-Linked " + "access for [sn:%u].\n", tid, inst->seqNum); + TheISA::handleLockedRead(cpu, cache_pkt->req); + } + + // @TODO: Hardcoded to for load instructions. Assumes that + // the dest. idx 0 is always where the data is loaded to. + DPRINTF(InOrderCachePort, + "[tid:%u]: [sn:%i]: Data loaded was: %08p.\n", + tid, inst->seqNum, inst->readIntResult(0)); + } else if(inst->isStore()) { + assert(cache_pkt->isWrite()); + + DPRINTF(InOrderCachePort, + "[tid:%u]: [sn:%i]: Data stored was: %08p.\n", + tid, inst->seqNum, + getMemData(cache_pkt)); + + } + } + + cache_req->setMemAccPending(false); + cache_req->setMemAccCompleted(); + + // Wake up the CPU (if it went to sleep and was waiting on this + // completion event). + cpu->wakeCPU(); + + DPRINTF(Activity, "[tid:%u] Activating %s due to cache completion\n", + tid, cpu->pipelineStage[stage_num]->name()); + + cpu->switchToActive(stage_num); + } else { + DPRINTF(InOrderCachePort, + "[tid:%u] Cache miss on memory access to block @ %08p " + "completed, but squashed.\n", tid, cache_req->inst->readPC()); + cache_req->setMemAccCompleted(); + } + + inst->unsetMemAddr(); +} + +void +CacheUnit::recvRetry() +{ + DPRINTF(InOrderCachePort, "Retrying Request for [tid:%i] [sn:%i].\n", + retryReq->inst->readTid(), retryReq->inst->seqNum); + + assert(retryPkt != NULL); + assert(cacheBlocked); + assert(cacheStatus == cacheWaitRetry); + + if (cachePort->sendTiming(retryPkt)) { + cacheStatus = cacheWaitResponse; + retryPkt = NULL; + cacheBlocked = false; + } else { + DPRINTF(InOrderCachePort, "Retry Request for [tid:%i] [sn:%i] failed.\n", + retryReq->inst->readTid(), retryReq->inst->seqNum); + } + +} + +void +CacheUnit::squash(DynInstPtr inst, int stage_num, + InstSeqNum squash_seq_num, unsigned tid) +{ + std::vector slot_remove_list; + + std::map::iterator map_it = reqMap.begin(); + std::map::iterator map_end = reqMap.end(); + + while (map_it != map_end) { + ResReqPtr req_ptr = (*map_it).second; + + if (req_ptr && + req_ptr->getInst()->readTid() == tid && + req_ptr->getInst()->seqNum > squash_seq_num) { + + DPRINTF(InOrderCachePort, + "[tid:%i] Squashing request from [sn:%i].\n", + req_ptr->getInst()->readTid(), req_ptr->getInst()->seqNum); + + req_ptr->setSquashed(); + + req_ptr->getInst()->setSquashed(); + + CacheReqPtr cache_req = dynamic_cast(req_ptr); + assert(cache_req); + + if (!cache_req->isMemAccPending()) { + // Mark request for later removal + cpu->reqRemoveList.push(req_ptr); + + // Mark slot for removal from resource + slot_remove_list.push_back(req_ptr->getSlot()); + } + } + + map_it++; + } + + // Now Delete Slot Entry from Req. Map + for (int i = 0; i < slot_remove_list.size(); i++) { + freeSlot(slot_remove_list[i]); + } + +} + +uint64_t CacheUnit::getMemData(Packet *packet) { + switch (packet->getSize()) + { + case 8: + return packet->get(); + + case 16: + return packet->get(); + + case 32: + return packet->get(); + + case 864: + return packet->get(); + + default: + std::cerr << "bad store data size = " << packet->getSize() << std::endl; + + assert(0); + return 0; + } +} + diff --git a/src/cpu/inorder/resources/cache_unit.hh b/src/cpu/inorder/resources/cache_unit.hh new file mode 100644 index 000000000..9d048d789 --- /dev/null +++ b/src/cpu/inorder/resources/cache_unit.hh @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __CPU_INORDER_CACHE_UNIT_HH__ +#define __CPU_INORDER_CACHE_UNIT_HH__ + +#include +#include +#include + +//#include "cpu/inorder/params.hh" + +#include "cpu/inorder/resource.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" +#include "mem/port.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "sim/sim_object.hh" + +#include "params/InOrderCPU.hh" + +class CacheRequest; +typedef CacheRequest* CacheReqPtr; + +class CacheReqPacket; +typedef CacheReqPacket* CacheReqPktPtr; + +class CacheUnit : public Resource { + public: + typedef ThePipeline::DynInstPtr DynInstPtr; + + public: + CacheUnit(std::string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params); + virtual ~CacheUnit() {} + + enum Command { + InitiateFetch, + CompleteFetch, + InitiateReadData, + CompleteReadData, + InitiateWriteData, + CompleteWriteData, + Fetch, + ReadData, + WriteData + }; + + public: + /** CachePort class for the Cache Unit. Handles doing the + * communication with the cache/memory. + */ + class CachePort : public Port + { + protected: + /** Pointer to cache port unit */ + CacheUnit *cachePortUnit; + + public: + /** Default constructor. */ + CachePort(CacheUnit *_cachePortUnit) + : Port(_cachePortUnit->name() + "-cache-port", (MemObject*)_cachePortUnit->cpu), + cachePortUnit(_cachePortUnit) + { } + + bool snoopRangeSent; + + 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, + AddrRangeList &snoop) + { resp.clear(); snoop.clear(); } + + /** 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(); + }; + + enum CachePortStatus { + cacheWaitResponse, + cacheWaitRetry, + cacheAccessComplete + }; + + ///virtual void init(); + + virtual ResourceRequest* getRequest(DynInstPtr _inst, int stage_num, + int res_idx, int slot_num, + unsigned cmd); + + void requestAgain(DynInstPtr inst, bool &try_request); + + int getSlot(DynInstPtr inst); + + void freeSlot(int slot_num); + + /** Execute the function of this resource. The Default is action + * is to do nothing. More specific models will derive from this + * class and define their own execute function. + */ + void execute(int slot_num); + + void squash(DynInstPtr inst, int stage_num, + InstSeqNum squash_seq_num, unsigned tid); + + /** Processes cache completion event. */ + void processCacheCompletion(PacketPtr pkt); + + void recvRetry(); + + /** Align a PC to the start of an I-cache block. */ + Addr cacheBlockAlignPC(Addr addr) + { + //addr = TheISA::realPCToFetchPC(addr); + return (addr & ~(cacheBlkMask)); + } + + /** Returns a specific port. */ + Port *getPort(const std::string &if_name, int idx); + + /** Fetch on behalf of an instruction. Will check to see + * if instruction is actually in resource before + * trying to fetch. + */ + //Fault doFetchAccess(DynInstPtr inst); + + /** Read/Write on behalf of an instruction. + * curResSlot needs to be a valid value in instruction. + */ + Fault doDataAccess(DynInstPtr inst); + + uint64_t getMemData(Packet *packet); + + protected: + /** Cache interface. */ + CachePort *cachePort; + + CachePortStatus cacheStatus; + + CacheReqPtr retryReq; + + PacketPtr retryPkt; + + int retrySlot; + + bool cacheBlocked; + + std::vector addrList; + + std::map addrMap; + + public: + int cacheBlkSize; + + int cacheBlkMask; + + /** Align a PC to the start of the Cache block. */ + Addr cacheBlockAlign(Addr addr) + { + return (addr & ~(cacheBlkMask)); + } + + /** THINGS USED FOR FETCH */ + // NO LONGER USED BY COMMENT OUT UNTIL FULL VERIFICATION + /** The mem line being fetched. */ + //uint8_t *cacheData[ThePipeline::MaxThreads]; + + /** The Addr of the cacheline that has been loaded. */ + //Addr cacheBlockAddr[ThePipeline::MaxThreads]; + + //unsigned fetchOffset[ThePipeline::MaxThreads]; + + /** @todo: Add Resource Stats Here */ +}; + +struct CacheSchedEntry : public ThePipeline::ScheduleEntry { + enum EntryType { + FetchAccess, + DataAccess + }; + + CacheSchedEntry(int stage_num, int _priority, int res_num, MemCmd::Command pkt_cmd, + EntryType _type = FetchAccess) : + ScheduleEntry(stage_num, _priority, res_num), pktCmd(pkt_cmd), + type(_type) + { } + + MemCmd::Command pktCmd; + EntryType type; +}; + +class CacheRequest : public ResourceRequest { + public: + CacheRequest(CacheUnit *cres, DynInstPtr inst, int stage_num, int res_idx, + int slot_num, unsigned cmd, int req_size, + MemCmd::Command pkt_cmd, unsigned flags, int cpu_id) + : ResourceRequest(cres, inst, stage_num, res_idx, slot_num, cmd), + pktCmd(pkt_cmd), memAccComplete(false), memAccPending(false) + { + memReq = inst->memReq; + + reqData = new uint8_t[req_size]; + retryPkt = NULL; + } + + virtual ~CacheRequest() + { + /* + delete reqData; + + Can get rid of packet and packet request now + if (*dataPkt) { + if (*dataPkt->req) { + delete dataPkt->req; + } + delete dataPkt; + } + + // Can get rid of packet and packet request now + if (retryPkt) { + if (retryPkt->req) { + delete retryPkt->req; + } + delete retryPkt; + }*/ + + if (memReq) { + delete memReq; + } + } + + virtual PacketDataPtr getData() + { return reqData; } + + void setMemAccCompleted(bool completed = true) { memAccComplete = completed; } + bool isMemAccComplete() { return memAccComplete; } + + void setMemAccPending(bool pending = true) { memAccPending = pending; } + bool isMemAccPending() { return memAccPending; } + + //Make this data private/protected! + MemCmd::Command pktCmd; + RequestPtr memReq; + PacketDataPtr reqData; + PacketPtr dataPkt; + PacketPtr retryPkt; + + bool memAccComplete; + bool memAccPending; +}; + +class CacheReqPacket : public Packet { + public: + CacheReqPacket(CacheRequest *_req, + Command _cmd, short _dest) + : Packet(_req->memReq, _cmd, _dest), cacheReq(_req) + { + + } + + CacheRequest *cacheReq; +}; + +#endif //__CPU_CACHE_UNIT_HH__ diff --git a/src/cpu/inorder/resources/decode_unit.cc b/src/cpu/inorder/resources/decode_unit.cc new file mode 100644 index 000000000..1628c32d0 --- /dev/null +++ b/src/cpu/inorder/resources/decode_unit.cc @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include "cpu/inorder/resources/decode_unit.hh" + +using namespace TheISA; +using namespace ThePipeline; +using namespace std; + +DecodeUnit::DecodeUnit(std::string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params) + : Resource(res_name, res_id, res_width, res_latency, _cpu) +{ + for (int tid = 0; tid < MaxThreads; tid++) { + regDepMap[tid] = &cpu->archRegDepMap[tid]; + } +} + +void +DecodeUnit::execute(int slot_num) +{ + ResourceRequest* decode_req = reqMap[slot_num]; + DynInstPtr inst = reqMap[slot_num]->inst; + Fault fault = reqMap[slot_num]->fault; + int tid, seq_num; + + tid = inst->readTid(); + seq_num = inst->seqNum; + decode_req->fault = NoFault; + + switch (decode_req->cmd) + { + case DecodeInst: + { + bool done_sked = ThePipeline::createBackEndSchedule(inst); + + if (done_sked) { + DPRINTF(Resource, "[tid:%i]: Setting Destination Register(s) for [sn:%i].\n", + tid, seq_num); + regDepMap[tid]->insert(inst); + decode_req->done(); + } else { + DPRINTF(Resource,"[tid:%i] Static Inst not available to decode. Unable to create " + "schedule for instruction [sn:%i] \n", tid, inst->seqNum); + DPRINTF(InOrderStall, "STALL: \n"); + decode_req->done(false); + } + } + break; + + default: + fatal("Unrecognized command to %s", resName); + } +} + + +void +DecodeUnit::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num, unsigned tid) +{ + DPRINTF(Resource, "[tid:%i]: Updating due to squash from stage %i after [sn:%i].\n", + tid, stage_num, squash_seq_num); + + //cpu->removeInstsUntil(squash_seq_num, tid); +} diff --git a/src/cpu/inorder/resources/decode_unit.hh b/src/cpu/inorder/resources/decode_unit.hh new file mode 100644 index 000000000..3813de6c4 --- /dev/null +++ b/src/cpu/inorder/resources/decode_unit.hh @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __CPU_INORDER_DECODE_UNIT_HH__ +#define __CPU_INORDER_DECODE_UNIT_HH__ + +#include +#include +#include + +#include "cpu/inorder/resource.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/cpu.hh" +#include "cpu/inorder/reg_dep_map.hh" + +class DecodeUnit : public Resource { + public: + typedef ThePipeline::DynInstPtr DynInstPtr; + + public: + DecodeUnit(std::string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params); + virtual ~DecodeUnit() {} + + enum Command { + DecodeInst + }; + + virtual void execute(int slot_num); + + void squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num, unsigned tid); + + RegDepMap *regDepMap[ThePipeline::MaxThreads]; + + protected: + /** @todo: Add Resource Stats Here */ +}; + +#endif //__CPU_INORDER_DECODE_UNIT_HH__ diff --git a/src/cpu/inorder/resources/execution_unit.cc b/src/cpu/inorder/resources/execution_unit.cc new file mode 100644 index 000000000..e41291103 --- /dev/null +++ b/src/cpu/inorder/resources/execution_unit.cc @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include +#include +#include "cpu/inorder/resources/execution_unit.hh" +#include "cpu/inorder/resource_pool.hh" +#include "cpu/inorder/cpu.hh" + +using namespace std; +using namespace ThePipeline; + +ExecutionUnit::ExecutionUnit(string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params) + : Resource(res_name, res_id, res_width, res_latency, _cpu) +{ } + +void +ExecutionUnit::regStats() +{ + predictedTakenIncorrect + .name(name() + ".predictedTakenIncorrect") + .desc("Number of Branches Incorrectly Predicted As Taken."); + + predictedNotTakenIncorrect + .name(name() + ".predictedNotTakenIncorrect") + .desc("Number of Branches Incorrectly Predicted As Not Taken)."); + + Resource::regStats(); +} + +void +ExecutionUnit::execute(int slot_num) +{ + ResourceRequest* exec_req = reqMap[slot_num]; + DynInstPtr inst = reqMap[slot_num]->inst; + Fault fault = reqMap[slot_num]->fault; + int tid = inst->readTid(); + int seq_num = inst->seqNum; + + exec_req->fault = NoFault; + + DPRINTF(Resource, "[tid:%i] Executing [sn:%i] [PC:%#x] .\n", + tid, seq_num, inst->readPC()); + + switch (exec_req->cmd) + { + case ExecuteInst: + { + if (inst->isMemRef()) { + fatal("%s not configured to handle memory ops.\n", resName); + } else if (inst->isControl()) { + // Evaluate Branch + fault = inst->execute(); + + inst->setExecuted(); + + if (fault == NoFault) { + // If branch is mispredicted, then signal squash + // throughout all stages behind the pipeline stage + // that got squashed. + if (inst->mispredicted()) { + int stage_num = exec_req->getStageNum(); + int tid = inst->readTid(); + + // If it's a branch ... + if (inst->isDirectCtrl()) { + assert(!inst->isIndirectCtrl()); + + if (inst->predTaken() && inst->isCondDelaySlot()) { + inst->bdelaySeqNum = seq_num; + inst->setPredTarg(inst->nextPC); + + DPRINTF(Resource, "[tid:%i]: Conditional branch inst" + "[sn:%i] PC %#x mispredicted as taken.\n", tid, + seq_num, inst->PC); + } else if (!inst->predTaken() && inst->isCondDelaySlot()) { + inst->bdelaySeqNum = seq_num; + inst->setPredTarg(inst->nextPC); + inst->procDelaySlotOnMispred = true; + + DPRINTF(Resource, "[tid:%i]: Conditional branch inst." + "[sn:%i] PC %#x mispredicted as not taken.\n", tid, + seq_num, inst->PC); + } else { + inst->bdelaySeqNum = seq_num + 1; + + DPRINTF(Resource, "[tid:%i]: Misprediction detected at " + "[sn:%i] PC %#x,\n\t squashing after delay slot " + "instruction [sn:%i].\n", + tid, seq_num, inst->PC, inst->bdelaySeqNum); + DPRINTF(InOrderStall, "STALL: [tid:%i]: Branch " + "misprediction at %#x\n", tid, inst->PC); + inst->setPredTarg(inst->nextNPC); + } + + DPRINTF(Resource, "[tid:%i] Redirecting fetch to %#x.\n", tid, + inst->readPredTarg()); + + } else if(inst->isIndirectCtrl()){ + inst->setPredTarg(inst->nextNPC); + inst->bdelaySeqNum = seq_num + 1; + DPRINTF(Resource, "[tid:%i] Redirecting fetch to %#x.\n", tid, + inst->readPredTarg()); + } else { + panic("Non-control instruction (%s) mispredicting?!!", + inst->staticInst->getName()); + } + + DPRINTF(Resource, "[tid:%i] Squashing will start from stage %i.\n", + tid, stage_num); + + cpu->pipelineStage[stage_num]->squashDueToBranch(inst, tid); + + inst->squashingStage = stage_num; + + // Squash throughout other resources + cpu->resPool->scheduleEvent((InOrderCPU::CPUEventType)ResourcePool::SquashAll, + inst, 0, 0, tid); + + if (inst->predTaken()) { + predictedTakenIncorrect++; + } else { + predictedNotTakenIncorrect++; + } + } + exec_req->done(); + } else { + warn("inst [sn:%i] had a %s fault", seq_num, fault->name()); + } + } else { + // Regular ALU instruction + fault = inst->execute(); + + if (fault == NoFault) { + inst->setExecuted(); + exec_req->done(); + + DPRINTF(Resource, "[tid:%i]: The result of execution is 0x%x.\n", + inst->readTid(), inst->readIntResult(0)); + } else { + warn("inst [sn:%i] had a %s fault", seq_num, fault->name()); + cpu->trap(fault, tid); + } + } + } + break; + + default: + fatal("Unrecognized command to %s", resName); + } +} + + diff --git a/src/cpu/inorder/resources/execution_unit.hh b/src/cpu/inorder/resources/execution_unit.hh new file mode 100644 index 000000000..e969497a2 --- /dev/null +++ b/src/cpu/inorder/resources/execution_unit.hh @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __CPU_INORDER_EXECUTION_UNIT_HH__ +#define __CPU_INORDER_EXECUTION_UNIT_HH__ + +#include +#include +#include + +#include "cpu/func_unit.hh" +#include "cpu/inorder/first_stage.hh" +#include "cpu/inorder/resource.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" + +class ExecutionUnit : public Resource { + public: + typedef ThePipeline::DynInstPtr DynInstPtr; + + enum Command { + ExecuteInst + }; + + public: + ExecutionUnit(std::string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params); + virtual ~ExecutionUnit() {} + + public: + virtual void regStats(); + + /** Execute the function of this resource. The Default is action + * is to do nothing. More specific models will derive from this + * class and define their own execute function. + */ + virtual void execute(int slot_num); + + protected: + ///////////////////////////////////////////////////////////////// + // + // RESOURCE STATISTICS + // + ///////////////////////////////////////////////////////////////// + Stats::Scalar<> predictedTakenIncorrect; + Stats::Scalar<> predictedNotTakenIncorrect; +}; + + +#endif //__CPU_INORDER_EXCUTION_UNIT_HH__ diff --git a/src/cpu/inorder/resources/fetch_seq_unit.cc b/src/cpu/inorder/resources/fetch_seq_unit.cc new file mode 100644 index 000000000..00f76f74b --- /dev/null +++ b/src/cpu/inorder/resources/fetch_seq_unit.cc @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include "cpu/inorder/resources/fetch_seq_unit.hh" +#include "cpu/inorder/resource_pool.hh" + +using namespace std; +using namespace TheISA; +using namespace ThePipeline; + +FetchSeqUnit::FetchSeqUnit(std::string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params) + : Resource(res_name, res_id, res_width, res_latency, _cpu) +{ + instSize = sizeof(MachInst); + + for (int tid = 0; tid < ThePipeline::MaxThreads; tid++) { + delaySlotInfo[tid].numInsts = 0; + delaySlotInfo[tid].targetReady = false; + + pcValid[tid] = false; + pcBlockStage[tid] = 0; + + squashSeqNum[tid] = (InstSeqNum)-1; + lastSquashCycle[tid] = 0; + } +} + +void +FetchSeqUnit::init() +{ + resourceEvent = new FetchSeqEvent[width]; + + initSlots(); +} + +void +FetchSeqUnit::execute(int slot_num) +{ + // After this is working, change this to a reinterpret cast + // for performance considerations + ResourceRequest* fs_req = reqMap[slot_num]; + DynInstPtr inst = fs_req->inst; + int tid = inst->readTid(); + int stage_num = fs_req->getStageNum(); + int seq_num = inst->seqNum; + + fs_req->fault = NoFault; + + switch (fs_req->cmd) + { + case AssignNextPC: + { + if (pcValid[tid]) { + + if (delaySlotInfo[tid].targetReady && + delaySlotInfo[tid].numInsts == 0) { + // Set PC to target + PC[tid] = delaySlotInfo[tid].targetAddr; //next_PC + nextPC[tid] = PC[tid] + instSize; //next_NPC + nextNPC[tid] = PC[tid] + (2 * instSize); + + delaySlotInfo[tid].targetReady = false; + + DPRINTF(Resource, "[tid:%i]: Setting PC to delay slot target\n",tid); + } + + inst->setPC(PC[tid]); + inst->setNextPC(PC[tid] + instSize); + inst->setNextNPC(PC[tid] + (instSize * 2)); + + inst->setPredTarg(inst->readNextNPC()); + + inst->setMemAddr(PC[tid]); + inst->setSeqNum(cpu->getAndIncrementInstSeq(tid)); + + DPRINTF(Resource, "[tid:%i]: Assigning [sn:%i] to PC %08p\n", tid, + inst->seqNum, inst->readPC()); + + if (delaySlotInfo[tid].numInsts > 0) { + --delaySlotInfo[tid].numInsts; + + // It's OK to set PC to target of branch + if (delaySlotInfo[tid].numInsts == 0) { + delaySlotInfo[tid].targetReady = true; + } + + DPRINTF(Resource, "[tid:%i]: %i delay slot inst(s) left to" + " process.\n", tid, delaySlotInfo[tid].numInsts); + } + + PC[tid] = nextPC[tid]; + nextPC[tid] = nextNPC[tid]; + nextNPC[tid] += instSize; + + fs_req->done(); + } else { + DPRINTF(InOrderStall, "STALL: [tid:%i]: NPC not valid\n", tid); + fs_req->setCompleted(false); + } + } + break; + + case UpdateTargetPC: + { + if (inst->isControl()) { + // If it's a return, then we must wait for resolved address. + if (inst->isReturn() && !inst->predTaken()) { + cpu->pipelineStage[stage_num]->toPrevStages->stageBlock[stage_num][tid] = true; + pcValid[tid] = false; + pcBlockStage[tid] = stage_num; + } else if (inst->isCondDelaySlot() && !inst->predTaken()) { + // Not-Taken AND Conditional Control + DPRINTF(Resource, "[tid:%i]: [sn:%i]: [PC:%08p] Predicted Not-Taken Cond. " + "Delay inst. Skipping delay slot and Updating PC to %08p\n", + tid, inst->seqNum, inst->readPC(), inst->readPredTarg()); + + DPRINTF(Resource, "[tid:%i] Setting up squash to start from stage %i, after [sn:%i].\n", + tid, stage_num, seq_num); + + inst->bdelaySeqNum = seq_num; + inst->squashingStage = stage_num; + + squashAfterInst(inst, stage_num, tid); + } else if (!inst->isCondDelaySlot() && !inst->predTaken()) { + // Not-Taken Control + DPRINTF(Resource, "[tid:%i]: [sn:%i]: Predicted Not-Taken Control " + "inst. updating PC to %08p\n", tid, inst->seqNum, + inst->readNextPC()); + + ++delaySlotInfo[tid].numInsts; + delaySlotInfo[tid].targetReady = false; + delaySlotInfo[tid].targetAddr = inst->readNextNPC(); + + } else if (inst->predTaken()) { + // Taken Control + ++delaySlotInfo[tid].numInsts; + delaySlotInfo[tid].targetReady = false; + delaySlotInfo[tid].targetAddr = inst->readPredTarg(); + + DPRINTF(Resource, "[tid:%i]: [sn:%i] Updating delay slot target " + "to PC %08p\n", tid, inst->seqNum, inst->readPredTarg()); + + // Set-Up Squash Through-Out Pipeline + DPRINTF(Resource, "[tid:%i] Setting up squash to start from stage %i, after [sn:%i].\n", + tid, stage_num, seq_num + 1); + inst->bdelaySeqNum = seq_num + 1; + inst->squashingStage = stage_num; + + // Do Squashing + squashAfterInst(inst, stage_num, tid); + } + } else { + DPRINTF(Resource, "[tid:%i]: [sn:%i]: Ignoring branch target update " + "since then is not a control instruction.\n", tid, inst->seqNum); + } + + fs_req->done(); + } + break; + + default: + fatal("Unrecognized command to %s", resName); + } +} + +inline void +FetchSeqUnit::squashAfterInst(DynInstPtr inst, int stage_num, unsigned tid) +{ + // Squash In Pipeline Stage + cpu->pipelineStage[stage_num]->squashDueToBranch(inst, tid); + + // Squash inside current resource, so if there needs to be fetching on same cycle + // the fetch information will be correct. + // squash(inst, stage_num, inst->bdelaySeqNum, tid); + + // Schedule Squash Through-out Resource Pool + cpu->resPool->scheduleEvent((InOrderCPU::CPUEventType)ResourcePool::SquashAll, inst, 0); +} +void +FetchSeqUnit::squash(DynInstPtr inst, int squash_stage, + InstSeqNum squash_seq_num, unsigned tid) +{ + DPRINTF(Resource, "[tid:%i]: Updating due to squash from stage %i.\n", + tid, squash_stage); + + InstSeqNum done_seq_num = inst->bdelaySeqNum; + Addr new_PC = inst->readPredTarg(); + + if (squashSeqNum[tid] <= done_seq_num && + lastSquashCycle[tid] == curTick) { + DPRINTF(Resource, "[tid:%i]: Ignoring squash from stage %i, since" + "there is an outstanding squash that is older.\n", + tid, squash_stage); + } else { + squashSeqNum[tid] = done_seq_num; + lastSquashCycle[tid] = curTick; + + // If The very next instruction number is the done seq. num, + // then we haven't seen the delay slot yet ... if it isn't + // the last done_seq_num then this is the delay slot inst. + if (cpu->nextInstSeqNum(tid) != done_seq_num && + !inst->procDelaySlotOnMispred) { + delaySlotInfo[tid].numInsts = 0; + delaySlotInfo[tid].targetReady = false; + + // Reset PC + PC[tid] = new_PC; + nextPC[tid] = new_PC + instSize; + nextNPC[tid] = new_PC + (2 * instSize); + + DPRINTF(Resource, "[tid:%i]: Setting PC to %08p.\n", + tid, PC[tid]); + } else { + delaySlotInfo[tid].numInsts = 1; + delaySlotInfo[tid].targetReady = false; + delaySlotInfo[tid].targetAddr = (inst->procDelaySlotOnMispred) ? inst->branchTarget() : new_PC; + + // Reset PC to Delay Slot Instruction + if (inst->procDelaySlotOnMispred) { + PC[tid] = new_PC; + nextPC[tid] = new_PC + instSize; + nextNPC[tid] = new_PC + (2 * instSize); + } + + } + + // Unblock Any Stages Waiting for this information to be updated ... + if (!pcValid[tid]) { + cpu->pipelineStage[pcBlockStage[tid]]->toPrevStages->stageUnblock[pcBlockStage[tid]][tid] = true; + } + + pcValid[tid] = true; + } + + Resource::squash(inst, squash_stage, squash_seq_num, tid); +} + +FetchSeqUnit::FetchSeqEvent::FetchSeqEvent() + : ResourceEvent() +{ } + +void +FetchSeqUnit::FetchSeqEvent::process() +{ + FetchSeqUnit* fs_res = dynamic_cast(resource); + assert(fs_res); + + for (int i=0; i < MaxThreads; i++) { + fs_res->PC[i] = fs_res->cpu->readPC(i); + fs_res->nextPC[i] = fs_res->cpu->readNextPC(i); + fs_res->nextNPC[i] = fs_res->cpu->readNextNPC(i); + DPRINTF(Resource, "[tid:%i]: Setting PC:%08p NPC:%08p NNPC:%08p.\n", + fs_res->PC[i], fs_res->nextPC[i], fs_res->nextNPC[i]); + + fs_res->pcValid[i] = true; + } + + //cpu->fetchPriorityList.push_back(tid); +} + + +void +FetchSeqUnit::activateThread(unsigned tid) +{ + pcValid[tid] = true; + + PC[tid] = cpu->readPC(tid); + nextPC[tid] = cpu->readNextPC(tid); + nextNPC[tid] = cpu->readNextNPC(tid); + + cpu->fetchPriorityList.push_back(tid); + + DPRINTF(Resource, "[tid:%i]: Reading PC:%08p NPC:%08p NNPC:%08p.\n", + tid, PC[tid], nextPC[tid], nextNPC[tid]); +} + +void +FetchSeqUnit::deactivateThread(unsigned tid) +{ + delaySlotInfo[tid].numInsts = 0; + delaySlotInfo[tid].targetReady = false; + + pcValid[tid] = false; + pcBlockStage[tid] = 0; + + squashSeqNum[tid] = (InstSeqNum)-1; + lastSquashCycle[tid] = 0; + + std::list::iterator thread_it = find(cpu->fetchPriorityList.begin(), + cpu->fetchPriorityList.end(), + tid); + + if (thread_it != cpu->fetchPriorityList.end()) + cpu->fetchPriorityList.erase(thread_it); +} diff --git a/src/cpu/inorder/resources/fetch_seq_unit.hh b/src/cpu/inorder/resources/fetch_seq_unit.hh new file mode 100644 index 000000000..2b074bbaa --- /dev/null +++ b/src/cpu/inorder/resources/fetch_seq_unit.hh @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __CPU_INORDER_FETCH_SEQ_UNIT_HH__ +#define __CPU_INORDER_FETCH_SEQ_UNIT_HH__ + +#include +#include +#include + +#include "cpu/inorder/resource.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/cpu.hh" + +using namespace ThePipeline; + +class FetchSeqUnit : public Resource { + public: + typedef ThePipeline::DynInstPtr DynInstPtr; + + enum Command { + AssignNextPC, + UpdateTargetPC + }; + + public: + FetchSeqUnit(std::string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params); + virtual ~FetchSeqUnit() {} + + virtual void init(); + virtual void activateThread(unsigned tid); + virtual void deactivateThread(unsigned tid); + virtual void execute(int slot_num); + + /** Override default Resource squash sequence. This actually, + * looks in the global communication buffer to get squash + * info + */ + virtual void squash(DynInstPtr inst, int squash_stage, + InstSeqNum squash_seq_num, unsigned tid); + + + inline void squashAfterInst(DynInstPtr inst, int stage_num, unsigned tid); + + protected: + unsigned instSize; + + bool pcValid[ThePipeline::MaxThreads]; + int pcBlockStage[ThePipeline::MaxThreads]; + + TheISA::IntReg PC[ThePipeline::MaxThreads]; + TheISA::IntReg nextPC[ThePipeline::MaxThreads]; + TheISA::IntReg nextNPC[ThePipeline::MaxThreads]; + + /** Tracks delay slot information for threads in ISAs which use + * delay slots; + */ + struct DelaySlotInfo { + InstSeqNum delaySlotSeqNum; + InstSeqNum branchSeqNum; + int numInsts; + Addr targetAddr; + bool targetReady; + }; + + DelaySlotInfo delaySlotInfo[ThePipeline::MaxThreads]; + + /** Squash Seq. Nums*/ + InstSeqNum squashSeqNum[ThePipeline::MaxThreads]; + + /** Squash Seq. Nums*/ + Tick lastSquashCycle[ThePipeline::MaxThreads]; + + /** @todo: Add Resource Stats Here */ + + public: + class FetchSeqEvent : public ResourceEvent { + public: + /** Constructs a resource event. */ + FetchSeqEvent(); + virtual ~FetchSeqEvent() {} + + /** Processes a resource event. */ + virtual void process(); + }; + +}; + +#endif diff --git a/src/cpu/inorder/resources/graduation_unit.cc b/src/cpu/inorder/resources/graduation_unit.cc new file mode 100644 index 000000000..f4bbf3f5d --- /dev/null +++ b/src/cpu/inorder/resources/graduation_unit.cc @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include "cpu/inorder/resources/graduation_unit.hh" + +using namespace ThePipeline; + +GraduationUnit::GraduationUnit(std::string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params) + : Resource(res_name, res_id, res_width, res_latency, _cpu) +{ + lastCycleGrad = 0; + numCycleGrad = 0; + + for (int tid = 0; tid < ThePipeline::MaxThreads; tid++) { + nonSpecInstActive[tid] = &cpu->nonSpecInstActive[tid]; + nonSpecSeqNum[tid] = &cpu->nonSpecSeqNum[tid]; + } +} + +void +GraduationUnit::execute(int slot_num) +{ + ResourceRequest* grad_req = reqMap[slot_num]; + DynInstPtr inst = reqMap[slot_num]->inst; + Fault fault = reqMap[slot_num]->fault; + int tid, seq_num; + + tid = inst->readTid(); + seq_num = inst->seqNum; + int stage_num = inst->resSched.top()->stageNum; + + grad_req->fault = NoFault; + + switch (grad_req->cmd) + { + case GraduateInst: + { + // @TODO: Instructions should never really get to this point since this should be handled + // through the request interface. Check to make sure this happens and delete this + // code. + if (lastCycleGrad != curTick) { + lastCycleGrad = curTick; + numCycleGrad = 0; + } else if (numCycleGrad > width) { + DPRINTF(Resource, "Graduation bandwidth reached for this cycle.\n"); + return; + } + + // Make sure this is the last thing on the resource schedule + assert(inst->resSched.size() == 1); + + DPRINTF(Resource, "[tid:%i] Graduating instruction [sn:%i].\n", + tid, seq_num); + + DPRINTF(RefCount, "Refcount = %i.\n", 0/*inst->curCount()*/); + + // Release Non-Speculative "Block" on instructions that could not execute + // because there was a non-speculative inst. active. + // @TODO: Fix this functionality. Probably too conservative. + if (inst->isNonSpeculative()) { + *nonSpecInstActive[tid] = false; + DPRINTF(Resource, "[tid:%i] Non-speculative instruction [sn:%i] has graduated.\n", + tid, seq_num); + } + + if (inst->traceData) { + inst->traceData->setStageCycle(stage_num, curTick); + } + + // Tell CPU that instruction is finished processing + cpu->instDone(inst, tid); + + //cpu->pipelineStage[stage_num]->toPrevStages-> + //stageInfo[stage_num][tid].doneSeqNum = inst->seqNum; + + grad_req->done(); + } + break; + + default: + fatal("Unrecognized command to %s", resName); + } + +} diff --git a/src/cpu/inorder/resources/graduation_unit.hh b/src/cpu/inorder/resources/graduation_unit.hh new file mode 100644 index 000000000..ad222b119 --- /dev/null +++ b/src/cpu/inorder/resources/graduation_unit.hh @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __CPU_INORDER_GRAD_UNIT_HH__ +#define __CPU_INORDER_GRAD_UNIT_HH__ + +#include +#include +#include + +#include "cpu/inorder/resource.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/cpu.hh" + +class GraduationUnit : public Resource { + public: + typedef ThePipeline::DynInstPtr DynInstPtr; + + enum Command { + GraduateInst + }; + + public: + GraduationUnit(std::string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params); + virtual ~GraduationUnit() {} + + virtual void execute(int slot_num); + + protected: + Tick lastCycleGrad; + int numCycleGrad; + + bool *nonSpecInstActive[ThePipeline::MaxThreads]; + + InstSeqNum *nonSpecSeqNum[ThePipeline::MaxThreads]; + + /** @todo: Add Resource Stats Here */ +}; + +#endif //__CPU_INORDER_GRAD_UNIT_HH__ diff --git a/src/cpu/inorder/resources/inst_buffer.cc b/src/cpu/inorder/resources/inst_buffer.cc new file mode 100644 index 000000000..97924d2d3 --- /dev/null +++ b/src/cpu/inorder/resources/inst_buffer.cc @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include +#include +#include "arch/isa_traits.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/resources/inst_buffer.hh" +#include "cpu/inorder/cpu.hh" + +using namespace std; +using namespace TheISA; +using namespace ThePipeline; + +InstBuffer::InstBuffer(string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params) + : Resource(res_name, res_id, res_width, res_latency, _cpu) +{ } + +void +InstBuffer::regStats() +{ + instsBypassed + .name(name() + ".instsBypassed") + .desc("Number of Instructions Bypassed."); + + Resource::regStats(); +} + +void +InstBuffer::execute(int slot_idx) +{ + ResReqPtr ib_req = reqMap[slot_idx]; + DynInstPtr inst = ib_req->inst; + int tid, seq_num, stage_num; + + tid = inst->readTid(); + seq_num = inst->seqNum; + stage_num = ib_req->getStageNum(); + ib_req->fault = NoFault; + + switch (ib_req->cmd) + { + case ScheduleOrBypass: + { + int next_stage = stage_num + 1; + int bypass_stage = stage_num + 2; + bool do_bypass = true; + + if (!instList.empty()) { + DPRINTF(Resource, "[sn:%i] cannot bypass stage %i because buffer isn't empty.\n", + inst->seqNum, next_stage); + do_bypass = false; + } else if(cpu->pipelineStage[bypass_stage]->isBlocked(tid)) { + DPRINTF(Resource, "[sn:%i] cannot bypass stage %i because stage %i is blocking.\n", + inst->seqNum, next_stage); + do_bypass = false; + } else if(cpu->pipelineStage[bypass_stage]->stageBufferAvail() <= 0) { + DPRINTF(Resource, "[sn:%i] cannot bypass stage %i because there is no room in " + "stage %i incoming stage buffer.\n", inst->seqNum, next_stage); + do_bypass = false; + } + + if (!do_bypass) { // SCHEDULE USAGE OF BUFFER + DPRINTF(Resource, "Scheduling [sn:%i] for buffer insertion in stage %i\n", + inst->seqNum, next_stage); + + // Add to schedule: Insert into buffer in next stage + int stage_pri = ThePipeline::getNextPriority(inst, next_stage); + + inst->resSched.push(new ScheduleEntry(next_stage, stage_pri, id, + InstBuffer::InsertInst)); + + // Add to schedule: Remove from buffer in next next (bypass) stage + stage_pri = ThePipeline::getNextPriority(inst, bypass_stage); + + inst->resSched.push(new ScheduleEntry(bypass_stage, stage_pri, id, + InstBuffer::RemoveInst)); + } else { // BYPASS BUFFER & NEXT STAGE + DPRINTF(Resource, "Setting [sn:%i] to bypass stage %i and enter stage %i.\n", + inst->seqNum, next_stage, bypass_stage); + inst->setNextStage(bypass_stage); + instsBypassed++; + } + + ib_req->done(); + } + break; + + case InsertInst: + { + bool inserted = false; + + if (instList.size() < width) { + DPRINTF(Resource, "[tid:%i]: Inserting [sn:%i] into buffer.\n", + tid, seq_num); + insert(inst); + inserted = true; + } else { + DPRINTF(Resource, "[tid:%i]: Denying [sn:%i] request because " + "buffer is full.\n", tid, seq_num); + + + std::list::iterator list_it = instList.begin(); + std::list::iterator list_end = instList.end(); + + while (list_it != list_end) { + DPRINTF(Resource,"Serving [tid:%i] [sn:%i].\n", (*list_it)->readTid(), (*list_it)->seqNum); + list_it++; + } + } + + ib_req->done(inserted); + } + break; + + case RemoveInst: + { + DPRINTF(Resource, "[tid:%i]: Removing [sn:%i] from buffer.\n", + tid, seq_num); + remove(inst); + ib_req->done(); + } + break; + + default: + fatal("Unrecognized command to %s", resName); + } + + DPRINTF(Resource, "Buffer now contains %i insts.\n", instList.size()); +} + +void +InstBuffer::insert(DynInstPtr inst) +{ + instList.push_back(inst); +} + +void +InstBuffer::remove(DynInstPtr inst) +{ + std::list::iterator list_it = instList.begin(); + std::list::iterator list_end = instList.end(); + + while (list_it != list_end) { + if((*list_it) == inst) { + instList.erase(list_it); + break; + } + list_it++; + } +} + +void +InstBuffer::pop(unsigned tid) +{ + instList.pop_front(); +} + +ThePipeline::DynInstPtr +InstBuffer::top(unsigned tid) +{ + return instList.front(); +} + +void +InstBuffer::squash(DynInstPtr inst, int stage_num, + InstSeqNum squash_seq_num, unsigned tid) +{ + queue::iterator> remove_list; + list::iterator list_it = instList.begin(); + list::iterator list_end = instList.end(); + + // Collect All Instructions to be Removed in Remove List + while (list_it != list_end) { + if((*list_it)->readTid() == tid && + (*list_it)->seqNum > squash_seq_num) { + (*list_it)->setSquashed(); + remove_list.push(list_it); + } + + list_it++; + } + + // Removed Instructions from InstList & Clear Remove List + while (!remove_list.empty()) { + DPRINTF(Resource, "[tid:%i]: Removing squashed [sn:%i] from buffer.\n", + tid, (*remove_list.front())->seqNum); + instList.erase(remove_list.front()); + remove_list.pop(); + } + + Resource::squash(inst, stage_num, squash_seq_num, tid); +} diff --git a/src/cpu/inorder/resources/inst_buffer.hh b/src/cpu/inorder/resources/inst_buffer.hh new file mode 100644 index 000000000..f4851e868 --- /dev/null +++ b/src/cpu/inorder/resources/inst_buffer.hh @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __CPU_INORDER_INST_BUFF_UNIT_HH__ +#define __CPU_INORDER_INST_BUFF_UNIT_HH__ + +#include +#include +#include + +#include "cpu/inorder/resource.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/cpu.hh" + +class InstBuffer : public Resource { + public: + typedef ThePipeline::DynInstPtr DynInstPtr; + + public: + enum Command { + InsertInst, + InsertAddr, + RemoveInst, + RemoveAddr, + ScheduleOrBypass + }; + + public: + InstBuffer(std::string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params); + virtual ~InstBuffer() {} + + virtual void regStats(); + + virtual void execute(int slot_num); + + virtual void insert(DynInstPtr inst); + + virtual void remove(DynInstPtr inst); + + virtual void pop(unsigned tid); + + virtual DynInstPtr top(unsigned tid); + + virtual void squash(DynInstPtr inst, int stage_num, + InstSeqNum squash_seq_num, unsigned tid); + protected: + /** List of instructions this resource is currently + * processing. + */ + std::list instList; + + public: + ///////////////////////////////////////////////////////////////// + // + // RESOURCE STATISTICS + // + ///////////////////////////////////////////////////////////////// + /** Number of Instruction Requests the Resource Processes */ + Stats::Scalar<> instsBypassed; + +}; + +#endif //__CPU_INORDER_INST_BUFF_UNIT_HH__ diff --git a/src/cpu/inorder/resources/inst_buffer_new.cc b/src/cpu/inorder/resources/inst_buffer_new.cc new file mode 100644 index 000000000..7e2c98837 --- /dev/null +++ b/src/cpu/inorder/resources/inst_buffer_new.cc @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include +#include +#include "arch/isa_traits.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/resources/inst_buffer.hh" +#include "cpu/inorder/cpu.hh" + +using namespace std; +using namespace TheISA; +using namespace ThePipeline; + +InstBuffer::InstBuffer(string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu) + : Resource(res_name, res_id, res_width, res_latency, _cpu) +{ } + +ResReqPtr +InstBuffer::getRequest(DynInstPtr inst, int stage_num, int res_idx, + int slot_num) +{ + // After this is working, change this to a reinterpret cast + // for performance considerations + InstBufferEntry* ib_entry = dynamic_cast(inst->resSched.top()); + assert(ib_entry); + + return new InstBufferRequest(this, inst, stage_num, id, slot_num, + ib_entry->cmd); +} + +void +InstBuffer::execute(int slot_idx) +{ + // After this is working, change this to a reinterpret cast + // for performance considerations + InstBufferRequest* ib_req = dynamic_cast(reqMap[slot_idx]); + assert(ib_req); + + DynInstPtr inst = ib_req->inst; + int tid = inst->readTid(); + int seq_num = inst->seqNum; + ib_req->fault = NoFault; + + switch (ib_req->cmd) + { + case InsertInst: + { + DPRINTF(Resource, "[tid:%i]: Inserting [sn:%i] into buffer.\n", + tid, seq_num); + insert(inst); + ib_req->done(); + } + break; + + case RemoveInst: + { + DPRINTF(Resource, "[tid:%i]: Removing [sn:%i] from buffer.\n", + tid, seq_num); + remove(inst); + ib_req->done(); + } + break; + + default: + fatal("Unrecognized command to %s", resName); + } + + DPRINTF(Resource, "Buffer now contains %i insts.\n", instList.size()); +} + +void +InstBuffer::insert(DynInstPtr inst) +{ + instList.push_back(inst); +} + +void +InstBuffer::remove(DynInstPtr inst) +{ + std::list::iterator list_it = instList.begin(); + std::list::iterator list_end = instList.end(); + + while (list_it != list_end) { + if((*list_it) == inst) { + instList.erase(list_it); + break; + } + list_it++; + } +} + +void +InstBuffer::pop() +{ instList.pop_front(); } + +ThePipeline::DynInstPtr +InstBuffer::top() +{ return instList.front(); } + +void +InstBuffer::squash(InstSeqNum squash_seq_num, unsigned tid) +{ + list::iterator list_it = instList.begin(); + list::iterator list_end = instList.end(); + queue::iterator> remove_list; + + // Collect All Instructions to be Removed in Remove List + while (list_it != list_end) { + if((*list_it)->seqNum > squash_seq_num) { + DPRINTF(Resource, "[tid:%i]: Squashing [sn:%i] in resource.\n", + tid, (*list_it)->seqNum); + (*list_it)->setSquashed(); + remove_list.push(list_it); + } + + list_it++; + } + + // Removed Instructions from InstList & Clear Remove List + while (!remove_list.empty()) { + instList.erase(remove_list.front()); + remove_list.pop(); + } + + Resource::squash(squash_seq_num, tid); +} diff --git a/src/cpu/inorder/resources/inst_buffer_new.hh b/src/cpu/inorder/resources/inst_buffer_new.hh new file mode 100644 index 000000000..e374fa109 --- /dev/null +++ b/src/cpu/inorder/resources/inst_buffer_new.hh @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __CPU_INORDER_INST_BUFF_UNIT_HH__ +#define __CPU_INORDER_INST_BUFF_UNIT_HH__ + +#include +#include +#include + +#include "cpu/inorder/resource.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/cpu.hh" + +class InstBuffer : public Resource { + public: + typedef InOrderDynInst::DynInstPtr DynInstPtr; + + public: + enum Command { + InsertInst, + InsertAddr, + RemoveInst, + RemoveAddr + }; + + public: + InstBuffer(std::string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu); + virtual ~InstBuffer() {} + + virtual ResourceRequest* getRequest(DynInstPtr _inst, int stage_num, + int res_idx, int slot_num); + + virtual void execute(int slot_num); + + virtual void insert(DynInstPtr inst); + + virtual void remove(DynInstPtr inst); + + virtual void pop(); + + virtual DynInstPtr top(); + + virtual void squash(InstSeqNum squash_seq_num, unsigned tid); + + protected: + /** List of instructions this resource is currently + * processing. + */ + std::list instList; + + /** @todo: Add Resource Stats Here */ + +}; + +struct InstBufferEntry : public ThePipeline::ScheduleEntry { + InstBufferEntry(int stage_num, int res_num, InstBuffer::Command _cmd) : + ScheduleEntry(stage_num, res_num), cmd(_cmd) + { } + + InstBuffer::Command cmd; +}; + +class InstBufferRequest : public ResourceRequest { + public: + typedef InOrderDynInst::DynInstPtr DynInstPtr; + + public: + InstBufferRequest(InstBuffer *res, DynInstPtr inst, int stage_num, int res_idx, int slot_num, + InstBuffer::Command _cmd) + : ResourceRequest(res, inst, stage_num, res_idx, slot_num), + cmd(_cmd) + { } + + InstBuffer::Command cmd; +}; + + +#endif //__CPU_INORDER_INST_BUFF_UNIT_HH__ diff --git a/src/cpu/inorder/resources/mem_dep_unit.hh b/src/cpu/inorder/resources/mem_dep_unit.hh new file mode 100644 index 000000000..0bd850c5c --- /dev/null +++ b/src/cpu/inorder/resources/mem_dep_unit.hh @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __CPU_INORDER_GRAD_UNIT_HH__ +#define __CPU_INORDER_GRAD_UNIT_HH__ + +#include +#include +#include + +#include "cpu/inorder/resource.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/cpu.hh" + +class MemDepUnit : public Resource { + public: + typedef ThePipeline::DynInstPtr DynInstPtr; + + public: + MemDepUnit(std::string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu); + virtual ~MemDepUnit() {} + + virtual void execute(int slot_num); + + protected: + Tick lastCycleGrad; + int numCycleGrad; + + bool *nonSpecInstActive[ThePipeline::MaxThreads]; + + InstSeqNum *nonSpecSeqNum[ThePipeline::MaxThreads]; + + /** @todo: Add Resource Stats Here */ +}; + +#endif //__CPU_INORDER_GRAD_UNIT_HH__ diff --git a/src/cpu/inorder/resources/mult_div_unit.cc b/src/cpu/inorder/resources/mult_div_unit.cc new file mode 100644 index 000000000..abef11247 --- /dev/null +++ b/src/cpu/inorder/resources/mult_div_unit.cc @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include +#include +#include "cpu/inorder/resources/mult_div_unit.hh" +#include "cpu/inorder/resource_pool.hh" +#include "cpu/inorder/cpu.hh" +#include "cpu/op_class.hh" + +using namespace std; +using namespace ThePipeline; + +MultDivUnit::MultDivUnit(string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params) + : Resource(res_name, res_id, res_width, res_latency, _cpu) +{ + multRepeatRate = params->multRepeatRate; + multLatency = params->multLatency; + + div8RepeatRate = params->div8RepeatRate; + div8Latency = params->div8Latency; + + div16RepeatRate = params->div16RepeatRate; + div16Latency = params->div16Latency; + + div24RepeatRate = params->div24RepeatRate; + div24Latency = params->div24Latency; + + div32RepeatRate = params->div32RepeatRate; + div32Latency = params->div32Latency; +} + +void +MultDivUnit::regStats() +{ + multInstReqsProcessed + .name(name() + ".multInstReqsProcessed") + .desc("Number of Multiply Requests Processed."); + + divInstReqsProcessed + .name(name() + ".divInstReqsProcessed") + .desc("Number of Divide Requests Processed."); + + Resource::regStats(); +} + +void +MultDivUnit::init() +{ + // Set Up Resource Events to Appropriate Resource BandWidth + resourceEvent = new MDUEvent[width]; + + initSlots(); +} + +int +MultDivUnit::findSlot(DynInstPtr inst) +{ + DPRINTF(InOrderMDU, "Finding slot for inst:%i\n | slots-free:%i | slots-used:%i\n", + inst->seqNum, slotsAvail(), slotsInUse()); + + return Resource::findSlot(inst); +} + +void +MultDivUnit::freeSlot(int slot_idx) +{ + DPRINTF(InOrderMDU, "Freeing slot for inst:%i\n | slots-free:%i | slots-used:%i\n", + reqMap[slot_idx]->getInst()->seqNum, slotsAvail(), slotsInUse()); + + Resource::freeSlot(slot_idx); +} + + +int +MultDivUnit::getSlot(DynInstPtr inst) +{ + // If MDU already has instruction, return current slot. + int slot_num = findSlot(inst); + + // If we have this instruction's request already then return + if (slot_num != -1 && + inst->resSched.top()->cmd == reqMap[slot_num]->cmd) + return slot_num; + + unsigned repeat_rate = 0; + + /** Enforce MDU dependencies after a multiply is seen last */ + if (lastOpType == IntMultOp) { + repeat_rate = multRepeatRate; + } + + /** Enforce dependencies after a divide is seen last */ + if (lastOpType == IntDivOp) { + switch (lastDivSize) { + case 8: + repeat_rate = div8RepeatRate; + break; + + case 16: + repeat_rate = div16RepeatRate; + break; + + case 24: + repeat_rate = div24RepeatRate; + break; + + case 32: + repeat_rate = div32RepeatRate; + break; + } + } + + if (lastMDUCycle + repeat_rate > curTick) { + DPRINTF(InOrderMDU, "MDU not ready to process another inst. until %i, denying request.\n", + lastMDUCycle + repeat_rate); + return -1; + } else { + int rval = Resource::getSlot(inst); + DPRINTF(InOrderMDU, "MDU request should pass: %i.\n", + rval); + + if (rval != -1) { + } + + return rval; + } +} + +int +MultDivUnit::getDivOpSize(DynInstPtr inst) +{ + // Get RT Register from instruction (index #1) + uint32_t div_op = inst->readIntSrc(1); + + if (div_op <= 0xFF) { + return 8; + } else if (div_op <= 0xFFFF) { + return 16; + } else if (div_op <= 0xFFFFFF) { + return 24; + } else { + return 32; + } +} + +void +MultDivUnit::execute(int slot_num) +{ + ResourceRequest* mult_div_req = reqMap[slot_num]; + DynInstPtr inst = reqMap[slot_num]->inst; + Fault fault = reqMap[slot_num]->fault; + + //int tid = inst->readTid(); + //int seq_num = inst->seqNum; + + switch (mult_div_req->cmd) + { + case StartMultDiv: + DPRINTF(InOrderMDU, "Start MDU called ...\n"); + + if (inst->opClass() == IntMultOp) { + scheduleEvent(slot_num, multLatency); + multInstReqsProcessed++; + } else if (inst->opClass() == IntDivOp) { + int op_size = getDivOpSize(inst); + + switch (op_size) + { + case 8: + scheduleEvent(slot_num, div8Latency); + break; + + case 16: + scheduleEvent(slot_num, div16Latency); + break; + + case 24: + scheduleEvent(slot_num, div24Latency); + break; + + case 32: + scheduleEvent(slot_num, div32Latency); + break; + } + + lastDivSize = op_size; + + divInstReqsProcessed++; + } + + // Allow to pass through to next stage while + // event processes + mult_div_req->setCompleted(); + break; + + case MultDiv: + DPRINTF(InOrderMDU, "Execute MDU called ...\n"); + exeMulDiv(slot_num); + mult_div_req->done(); + break; + + + case EndMultDiv: + //@TODO: Why not allow high-latency requests to sleep + // within stage until event wakes up???? + // Seems wasteful to continually check to see if + // this is done when we have a event in parallel + // counting down the time + { + DPRINTF(InOrderMDU, "End MDU called ...\n"); + if (mult_div_req->getInst()->isExecuted()) + mult_div_req->done(); + } + break; + + default: + fatal("Unrecognized command to %s", resName); + } +} + +void +MultDivUnit::exeMulDiv(int slot_num) +{ + ResourceRequest* mult_div_req = reqMap[slot_num]; + DynInstPtr inst = reqMap[slot_num]->inst; + Fault fault = reqMap[slot_num]->fault; + int tid = inst->readTid(); + int seq_num = inst->seqNum; + + fault = inst->execute(); + + if (fault == NoFault) { + inst->setExecuted(); + mult_div_req->setCompleted(); + + DPRINTF(Resource, "[tid:%i]: The result of execution is 0x%x.\n", + inst->readTid(), inst->readIntResult(0)); + } else { + warn("inst [sn:%i] had a %s fault", seq_num, fault->name()); + cpu->trap(fault, tid); + } +} + + +MDUEvent::MDUEvent() + : ResourceEvent() +{ } + +void +MDUEvent::process() +{ + MultDivUnit* mdu_res = reinterpret_cast(resource); + + mdu_res->exeMulDiv(slotIdx); + + ResourceRequest* mult_div_req = resource->reqMap[slotIdx]; + + mult_div_req->done(); +} + + diff --git a/src/cpu/inorder/resources/mult_div_unit.hh b/src/cpu/inorder/resources/mult_div_unit.hh new file mode 100644 index 000000000..762442c4b --- /dev/null +++ b/src/cpu/inorder/resources/mult_div_unit.hh @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __CPU_INORDER_MULT_DIV_UNIT_HH__ +#define __CPU_INORDER_MULT_DIV_UNIT_HH__ + +#include +#include +#include + +#include "cpu/func_unit.hh" +#include "cpu/op_class.hh" +#include "cpu/inorder/first_stage.hh" +#include "cpu/inorder/resource.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" + +class MDUEvent; + +class MultDivUnit : public Resource { + public: + typedef ThePipeline::DynInstPtr DynInstPtr; + + enum Command { + StartMultDiv, + EndMultDiv, + MultDiv + }; + + public: + MultDivUnit(std::string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params); + virtual ~MultDivUnit() {} + + public: + /** Override default Resource getSlot(). Will only getSlot if + * valid mult/div sequence is being maintained + */ + virtual int getSlot(DynInstPtr inst); + + virtual int findSlot(DynInstPtr inst); + + virtual void freeSlot(int slot_idx); + + virtual void init(); + + /** Get Operand Size For A Division Operation */ + int getDivOpSize(DynInstPtr inst); + + /** Override default Resource execute */ + virtual void execute(int slot_num); + + void exeMulDiv(int slot_num); + + /** Register extra resource stats */ + virtual void regStats(); + + protected: + /** Latency & Repeat Rate for Multiply Insts */ + unsigned multLatency; + unsigned multRepeatRate; + + /** Latency & Repeat Rate for 8-bit Divide Insts */ + unsigned div8Latency; + unsigned div8RepeatRate; + + /** Latency & Repeat Rate for 16-bit Divide Insts */ + unsigned div16Latency; + unsigned div16RepeatRate; + + /** Latency & Repeat Rate for 24-bit Divide Insts */ + unsigned div24Latency; + unsigned div24RepeatRate; + + /** Latency & Repeat Rate for 32-bit Divide Insts */ + unsigned div32Latency; + unsigned div32RepeatRate; + + /** Last cycle that MDU was used */ + Tick lastMDUCycle; + + /** Last type of instruction MDU started processing */ + OpClass lastOpType; + + /** Last Division Operand of instruction MDU was processing */ + uint32_t lastDivSize; + + /** Last instruction name the MDU used */ + std::string lastInstName; + + /** Number of Instruction Requests the Resource Processes */ + Stats::Scalar<> multInstReqsProcessed; + + /** Number of Instruction Requests the Resource Processes */ + Stats::Scalar<> divInstReqsProcessed; + + MDUEvent *mduEvent; +}; + +class MDUEvent : public ResourceEvent +{ + public: + MDUEvent(); + virtual ~MDUEvent() { } + + + virtual void process(); +}; + + +#endif //__CPU_INORDER_MULT_DIV_UNIT_HH__ diff --git a/src/cpu/inorder/resources/resource_list.hh b/src/cpu/inorder/resources/resource_list.hh new file mode 100644 index 000000000..cbe2ad8c3 --- /dev/null +++ b/src/cpu/inorder/resources/resource_list.hh @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef CPU_INORDER_RESOURCE_LIST_HH +#define CPU_INORDER_RESOURCE_LIST_HH + +#include "cpu/inorder/resources/cache_unit.hh" +#include "cpu/inorder/resources/execution_unit.hh" +#include "cpu/inorder/resources/use_def.hh" +#include "cpu/inorder/resources/inst_buffer.hh" +#include "cpu/inorder/resources/decode_unit.hh" +#include "cpu/inorder/resources/graduation_unit.hh" +#include "cpu/inorder/resources/tlb_unit.hh" +#include "cpu/inorder/resources/fetch_seq_unit.hh" +#include "cpu/inorder/resources/branch_predictor.hh" +#include "cpu/inorder/resources/agen_unit.hh" +#include "cpu/inorder/resources/mult_div_unit.hh" + +#endif diff --git a/src/cpu/inorder/resources/tlb_unit.cc b/src/cpu/inorder/resources/tlb_unit.cc new file mode 100644 index 000000000..9b0decedb --- /dev/null +++ b/src/cpu/inorder/resources/tlb_unit.cc @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include +#include +#include "arch/isa_traits.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/resources/tlb_unit.hh" +#include "cpu/inorder/cpu.hh" + +using namespace std; +using namespace TheISA; +using namespace ThePipeline; + +TLBUnit::TLBUnit(string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params) + : InstBuffer(res_name, res_id, res_width, res_latency, _cpu, params) +{ + for (int i=0; i < MaxThreads; i++) { + tlbBlocked[i] = false; + } +} + +void +TLBUnit::init() +{ + resourceEvent = new TLBUnitEvent[width]; + + initSlots(); +} + +int +TLBUnit::getSlot(DynInstPtr inst) +{ + if (tlbBlocked[inst->threadNumber]) { + return -1; + } else { + return Resource::getSlot(inst); + } +} + +ResourceRequest* +TLBUnit::getRequest(DynInstPtr _inst, int stage_num, + int res_idx, int slot_num, + unsigned cmd) +{ + return new TLBUnitRequest(this, _inst, stage_num, res_idx, slot_num, + cmd); +} + +void +TLBUnit::execute(int slot_idx) +{ + // After this is working, change this to a reinterpret cast + // for performance considerations + TLBUnitRequest* tlb_req = dynamic_cast(reqMap[slot_idx]); + assert(tlb_req); + + DynInstPtr inst = tlb_req->inst; + int tid, seq_num, stage_num; + + tid = inst->readTid(); + seq_num = inst->seqNum; + stage_num = tlb_req->getStageNum(); + + tlb_req->fault = NoFault; + + switch (tlb_req->cmd) + { + case FetchLookup: + { + tlb_req->fault = + this->cpu->translateInstReq(tlb_req->memReq, cpu->thread[tid]); + + if (tlb_req->fault != NoFault) { + DPRINTF(Resource, "[tid:%i]: %s encountered while translating " + "addr:%08p for [sn:%i].\n", tid, tlb_req->fault->name(), + tlb_req->memReq->getVaddr(), seq_num); + //insert(inst); + cpu->pipelineStage[stage_num]->setResStall(tlb_req, tid); + tlbBlocked[tid] = true; + scheduleEvent(slot_idx, 1); + + // @TODO: SHOULDNT BREAK EXECUTION at misspeculated PC Fault + // Let CPU handle the fault + cpu->trap(tlb_req->fault, tid); + } else { + DPRINTF(Resource, "[tid:%i]: [sn:%i] virt. addr %08p translated " + "to phys. addr:%08p.\n", tid, seq_num, + tlb_req->memReq->getVaddr(), + tlb_req->memReq->getPaddr()); + tlb_req->done(); + } + } + break; + + case DataLookup: + { + DPRINTF(Resource, "[tid:%i]: [sn:%i]: Attempting to translate %08p.\n", + tid, seq_num, tlb_req->memReq->getVaddr()); + + tlb_req->fault = + this->cpu->translateInstReq(tlb_req->memReq, cpu->thread[tid]); + + if (tlb_req->fault != NoFault) { + DPRINTF(Resource, "[tid:%i]: %s encountered while translating " + "addr:%08p for [sn:%i].\n", tid, tlb_req->fault->name(), + tlb_req->memReq->getVaddr(), seq_num); + //insert(inst); + cpu->pipelineStage[stage_num]->setResStall(tlb_req, tid); + tlbBlocked[tid] = true; + scheduleEvent(slot_idx, 1); + + // Let CPU handle the fault + cpu->trap(tlb_req->fault, tid); + } else { + DPRINTF(Resource, "[tid:%i]: [sn:%i] virt. addr %08p translated " + "to phys. addr:%08p.\n", tid, seq_num, + tlb_req->memReq->getVaddr(), + tlb_req->memReq->getPaddr()); + tlb_req->done(); + } + } + break; + + default: + fatal("Unrecognized command to %s", resName); + } +} + +TLBUnitEvent::TLBUnitEvent() + : ResourceEvent() +{ } + +void +TLBUnitEvent::process() +{ + DynInstPtr inst = resource->reqMap[slotIdx]->inst; + int stage_num = resource->reqMap[slotIdx]->getStageNum(); + int tid = inst->threadNumber; + + DPRINTF(Resource, "Waking up from TLB Miss caused by [sn:%i].\n", + inst->seqNum); + + TLBUnit* tlb_res = dynamic_cast(resource); + assert(tlb_res); + + tlb_res->tlbBlocked[tid] = false; + + tlb_res->cpu->pipelineStage[stage_num]->unsetResStall(resource->reqMap[slotIdx], tid); + + // Effectively NOP the instruction but still allow it + // to commit + //while (!inst->resSched.empty() && + // inst->resSched.top()->stageNum != ThePipeline::NumStages - 1) { + //inst->resSched.pop(); + //} +} diff --git a/src/cpu/inorder/resources/tlb_unit.hh b/src/cpu/inorder/resources/tlb_unit.hh new file mode 100644 index 000000000..c7fee6030 --- /dev/null +++ b/src/cpu/inorder/resources/tlb_unit.hh @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __CPU_INORDER_TLB_UNIT_HH__ +#define __CPU_INORDER_TLB_UNIT_HH__ + +#include +#include +#include + +#include "cpu/inorder/resources/inst_buffer.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/cpu.hh" + +class TLBUnit : public InstBuffer { + public: + typedef ThePipeline::DynInstPtr DynInstPtr; + + enum TLBCommand { + FetchLookup, + DataLookup + }; + + public: + TLBUnit(std::string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params); + virtual ~TLBUnit() {} + + void init(); + + int getSlot(DynInstPtr inst); + + virtual ResourceRequest* getRequest(DynInstPtr _inst, int stage_num, + int res_idx, int slot_num, + unsigned cmd); + + virtual void execute(int slot_num); + + bool tlbBlocked[ThePipeline::MaxThreads]; + + protected: + /** List of instructions this resource is currently + * processing. + */ + std::list instList; + + /** @todo: Add Resource Stats Here */ + +}; + +class TLBUnitEvent : public ResourceEvent { + public: + /** Constructs a resource event. */ + TLBUnitEvent(); + virtual ~TLBUnitEvent() {} + + /** Processes a resource event. */ + virtual void process(); +}; + +class TLBUnitRequest : public ResourceRequest { + public: + typedef ThePipeline::DynInstPtr DynInstPtr; + + public: + TLBUnitRequest(TLBUnit *res, DynInstPtr inst, int stage_num, int res_idx, int slot_num, + unsigned _cmd) + : ResourceRequest(res, inst, stage_num, res_idx, slot_num, _cmd) + { + Addr aligned_addr; + int req_size; + unsigned flags; + + if (_cmd == TLBUnit::FetchLookup) { + aligned_addr = inst->getMemAddr(); + req_size = sizeof(MachInst); + flags = 0; + } else { + aligned_addr = inst->getMemAddr();; + req_size = inst->getMemAccSize(); + flags = inst->getMemFlags(); + } + + // @TODO: Add Vaddr & Paddr functions + inst->memReq = new Request(inst->readTid(), aligned_addr, req_size, + flags, inst->readPC(), res->cpu->readCpuId(), inst->readTid()); + + memReq = inst->memReq; + } + + RequestPtr memReq; +}; + + +#endif //__CPU_INORDER_TLB_UNIT_HH__ diff --git a/src/cpu/inorder/resources/use_def.cc b/src/cpu/inorder/resources/use_def.cc new file mode 100644 index 000000000..ed697c4ca --- /dev/null +++ b/src/cpu/inorder/resources/use_def.cc @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include +#include +#include "arch/isa_traits.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/resources/use_def.hh" +#include "cpu/inorder/cpu.hh" + +using namespace std; +using namespace TheISA; +using namespace ThePipeline; + +UseDefUnit::UseDefUnit(string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params) + : Resource(res_name, res_id, res_width, res_latency, _cpu), + maxSeqNum((InstSeqNum)-1) +{ + for (int tid = 0; tid < ThePipeline::MaxThreads; tid++) { + nonSpecInstActive[tid] = &cpu->nonSpecInstActive[tid]; + nonSpecSeqNum[tid] = &cpu->nonSpecSeqNum[tid]; + + outReadSeqNum[tid] = maxSeqNum; + outWriteSeqNum[tid] = maxSeqNum; + + regDepMap[tid] = &cpu->archRegDepMap[tid]; + } +} + +ResReqPtr +UseDefUnit::getRequest(DynInstPtr inst, int stage_num, int res_idx, + int slot_num, unsigned cmd) +{ + return new UseDefRequest(this, inst, stage_num, id, slot_num, cmd, + inst->resSched.top()->idx); +} + + +ResReqPtr +UseDefUnit::findRequest(DynInstPtr inst) +{ + map::iterator map_it = reqMap.begin(); + map::iterator map_end = reqMap.end(); + + while (map_it != map_end) { + UseDefRequest* ud_req = dynamic_cast((*map_it).second); + assert(ud_req); + + if (ud_req && + ud_req->getInst() == inst && + ud_req->cmd == inst->resSched.top()->cmd && + ud_req->useDefIdx == inst->resSched.top()->idx) { + return ud_req; + } + map_it++; + } + + return NULL; +} + +void +UseDefUnit::execute(int slot_idx) +{ + // After this is working, change this to a reinterpret cast + // for performance considerations + UseDefRequest* ud_req = dynamic_cast(reqMap[slot_idx]); + assert(ud_req); + + DynInstPtr inst = ud_req->inst; + int tid = inst->readTid(); + int seq_num = inst->seqNum; + int ud_idx = ud_req->useDefIdx; + + // If there is a non-speculative instruction + // in the pipeline then stall instructions here + if (*nonSpecInstActive[tid] == true && + seq_num > *nonSpecSeqNum[tid]) { + DPRINTF(Resource, "[tid:%i]: [sn:%i] cannot execute because there is " + "non-speculative instruction [sn:%i] has not graduated.\n", + tid, seq_num, *nonSpecSeqNum[tid]); + return; + } else if (inst->isNonSpeculative()) { + *nonSpecInstActive[tid] = true; + *nonSpecSeqNum[tid] = seq_num; + } + + switch (ud_req->cmd) + { + case ReadSrcReg: + { + int reg_idx = inst->_srcRegIdx[ud_idx]; + + DPRINTF(Resource, "[tid:%i]: Attempting to read source register idx %i.\n", + tid, ud_idx); + + // Ask register dependency map if it is OK to read from Arch. Reg. File + if (regDepMap[tid]->canRead(reg_idx, inst)) { + // Read From Register File + if (inst->seqNum <= outReadSeqNum[tid]) { + if (reg_idx <= FP_Base_DepTag) { + DPRINTF(Resource, "[tid:%i]: Reading Int Reg %i from Register File.\n", + tid, reg_idx); + inst->setIntSrc(ud_idx, + cpu->readIntReg(reg_idx,inst->readTid())); + } else if (reg_idx <= Ctrl_Base_DepTag) { + reg_idx -= FP_Base_DepTag; + DPRINTF(Resource, "[tid:%i]: Reading Float Reg %i from Register File.\n", + tid, reg_idx); + inst->setIntSrc(ud_idx, // Always Read FloatRegBits For Now + cpu->readFloatRegBits(reg_idx, inst->readTid())); + } else { + reg_idx -= Ctrl_Base_DepTag; + DPRINTF(Resource, "[tid:%i]: Reading Misc Reg %i from Register File.\n", + tid, reg_idx); + inst->setIntSrc(ud_idx, + cpu->readMiscReg(reg_idx, inst->readTid())); + } + + outReadSeqNum[tid] = maxSeqNum; + + ud_req->done(); + } else { + DPRINTF(Resource, "[tid:%i]: Unable to read because of [sn:%i] hasnt read it's" + " registers yet.\n", tid, outReadSeqNum[tid]); + DPRINTF(InOrderStall, "STALL: [tid:%i]: waiting for [sn:%i] to write\n", + tid, outReadSeqNum[tid]); + } + + } else { + DynInstPtr forward_inst = regDepMap[tid]->canForward(reg_idx, ud_idx, inst); + + if (forward_inst) { + + if (inst->seqNum <= outReadSeqNum[tid]) { + int dest_reg_idx = forward_inst->getDestIdxNum(reg_idx); + + if (reg_idx <= FP_Base_DepTag) { + DPRINTF(Resource, "[tid:%i]: Forwarding dest. reg value 0x%x from " + "[sn:%i] to [sn:%i] source #%i.\n", + tid, forward_inst->readIntResult(dest_reg_idx) , + forward_inst->seqNum, inst->seqNum, ud_idx); + inst->setIntSrc(ud_idx, forward_inst->readIntResult(dest_reg_idx)); + } else if (reg_idx <= Ctrl_Base_DepTag) { + DPRINTF(Resource, "[tid:%i]: Forwarding dest. reg value 0x%x from " + "[sn:%i] to [sn:%i] source #%i.\n", + tid, forward_inst->readFloatResult(dest_reg_idx) , + forward_inst->seqNum, inst->seqNum, ud_idx); + inst->setFloatSrc(ud_idx, forward_inst->readFloatResult(dest_reg_idx)); + } else { + DPRINTF(Resource, "[tid:%i]: Forwarding dest. reg value 0x%x from " + "[sn:%i] to [sn:%i] source #%i.\n", + tid, forward_inst->readIntResult(dest_reg_idx) , + forward_inst->seqNum, inst->seqNum, ud_idx); + inst->setIntSrc(ud_idx, forward_inst->readIntResult(dest_reg_idx)); + } + + outReadSeqNum[tid] = maxSeqNum; + + ud_req->done(); + } else { + DPRINTF(Resource, "[tid:%i]: Unable to read because of [sn:%i] hasnt read it's" + " registers yet.\n", tid, outReadSeqNum[tid]); + DPRINTF(InOrderStall, "STALL: [tid:%i]: waiting for [sn:%i] to forward\n", + tid, outReadSeqNum[tid]); + } + } else { + DPRINTF(Resource, "[tid:%i]: Source register idx: %i is not ready to read.\n", + tid, reg_idx); + DPRINTF(InOrderStall, "STALL: [tid:%i]: waiting to read register (idx=%i)\n", + tid, reg_idx); + outReadSeqNum[tid] = inst->seqNum; + } + } + } + break; + + case WriteDestReg: + { + int reg_idx = inst->_destRegIdx[ud_idx]; + + if (regDepMap[tid]->canWrite(reg_idx, inst)) { + DPRINTF(Resource, "[tid:%i]: Attempting to write to Register File.\n", + tid); + + if (inst->seqNum <= outReadSeqNum[tid]) { + if (reg_idx <= FP_Base_DepTag) { + DPRINTF(Resource, "[tid:%i]: Writing 0x%x to register idx %i.\n", + tid, inst->readIntResult(ud_idx), reg_idx); + + // Remove Dependencies + regDepMap[tid]->removeFront(reg_idx, inst); + + cpu->setIntReg(reg_idx, + inst->readIntResult(ud_idx), + inst->readTid()); + } else if(reg_idx <= Ctrl_Base_DepTag) { + + // Remove Dependencies + regDepMap[tid]->removeFront(reg_idx, inst); + + reg_idx -= FP_Base_DepTag; + + cpu->setFloatReg(reg_idx, // Check for FloatRegBits Here + inst->readFloatResult(ud_idx), + inst->readTid()); + } else { + // Remove Dependencies + regDepMap[tid]->removeFront(reg_idx, inst); + + reg_idx -= Ctrl_Base_DepTag; + cpu->setMiscReg(reg_idx, + inst->readIntResult(ud_idx), + inst->readTid()); + } + + outWriteSeqNum[tid] = maxSeqNum; + + ud_req->done(); + } else { + DPRINTF(Resource, "[tid:%i]: Unable to write because of [sn:%i] hasnt read it's" + " registers yet.\n", tid, outReadSeqNum); + DPRINTF(InOrderStall, "STALL: [tid:%i]: waiting for [sn:%i] to read\n", + tid, outReadSeqNum); + } + } else { + DPRINTF(Resource, "[tid:%i]: Dest. register idx: %i is not ready to write.\n", + tid, reg_idx); + DPRINTF(InOrderStall, "STALL: [tid:%i]: waiting to write register (idx=%i)\n", + tid, reg_idx); + outWriteSeqNum[tid] = inst->seqNum; + } + } + break; + + default: + fatal("Unrecognized command to %s", resName); + } + +} + +void +UseDefUnit::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num, unsigned tid) +{ + DPRINTF(Resource, "[tid:%i]: Updating Due To Squash After [sn:%i].\n", + tid, squash_seq_num); + + std::vector slot_remove_list; + + map::iterator map_it = reqMap.begin(); + map::iterator map_end = reqMap.end(); + + while (map_it != map_end) { + ResReqPtr req_ptr = (*map_it).second; + + if (req_ptr && + req_ptr->getInst()->readTid() == tid && + req_ptr->getInst()->seqNum > squash_seq_num) { + + DPRINTF(Resource, "[tid:%i]: Squashing [sn:%i].\n", + req_ptr->getInst()->readTid(), + req_ptr->getInst()->seqNum); + + regDepMap[tid]->remove(req_ptr->getInst()); + + int req_slot_num = req_ptr->getSlot(); + + if (latency > 0) + unscheduleEvent(req_slot_num); + + // Mark slot for removal from resource + slot_remove_list.push_back(req_ptr->getSlot()); + } + + map_it++; + } + + // Now Delete Slot Entry from Req. Map + for (int i = 0; i < slot_remove_list.size(); i++) { + freeSlot(slot_remove_list[i]); + } + + if (outReadSeqNum[tid] >= squash_seq_num) { + DPRINTF(Resource, "[tid:%i]: Outstanding Read Seq Num Reset.\n", tid); + outReadSeqNum[tid] = maxSeqNum; + } else if (outReadSeqNum[tid] != maxSeqNum) { + DPRINTF(Resource, "[tid:%i]: No need to reset Outstanding Read Seq Num %i\n", + tid, outReadSeqNum[tid]); + } + + if (outWriteSeqNum[tid] >= squash_seq_num) { + DPRINTF(Resource, "[tid:%i]: Outstanding Write Seq Num Reset.\n", tid); + outWriteSeqNum[tid] = maxSeqNum; + } else if (outWriteSeqNum[tid] != maxSeqNum) { + DPRINTF(Resource, "[tid:%i]: No need to reset Outstanding Write Seq Num %i\n", + tid, outWriteSeqNum[tid]); + } +} diff --git a/src/cpu/inorder/resources/use_def.hh b/src/cpu/inorder/resources/use_def.hh new file mode 100644 index 000000000..238591117 --- /dev/null +++ b/src/cpu/inorder/resources/use_def.hh @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __CPU_INORDER_USE_DEF_UNIT_HH__ +#define __CPU_INORDER_USE_DEF_UNIT_HH__ + +#include +#include +#include + +#include "cpu/func_unit.hh" +#include "cpu/inorder/first_stage.hh" +#include "cpu/inorder/resource.hh" +#include "cpu/inorder/inorder_dyn_inst.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/reg_dep_map.hh" + +class UseDefUnit : public Resource { + public: + typedef ThePipeline::DynInstPtr DynInstPtr; + + enum Command { + ReadSrcReg, + WriteDestReg + }; + + public: + UseDefUnit(std::string res_name, int res_id, int res_width, + int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params); + virtual ~UseDefUnit() {} + + virtual ResourceRequest* getRequest(DynInstPtr _inst, int stage_num, + int res_idx, int slot_num, + unsigned cmd); + + virtual ResReqPtr findRequest(DynInstPtr inst); + + virtual void execute(int slot_num); + + virtual void squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num, unsigned tid); + + const InstSeqNum maxSeqNum; + + protected: + RegDepMap *regDepMap[ThePipeline::MaxThreads]; + + /** Outstanding Seq. Num. Trying to Read from Register File */ + InstSeqNum outReadSeqNum[ThePipeline::MaxThreads]; + + InstSeqNum outWriteSeqNum[ThePipeline::MaxThreads]; + + bool *nonSpecInstActive[ThePipeline::MaxThreads]; + + InstSeqNum *nonSpecSeqNum[ThePipeline::MaxThreads]; + + /** @todo: Add Resource Stats Here */ + + public: + class UseDefRequest : public ResourceRequest { + public: + typedef ThePipeline::DynInstPtr DynInstPtr; + + public: + UseDefRequest(UseDefUnit *res, DynInstPtr inst, int stage_num, int res_idx, + int slot_num, unsigned cmd, int use_def_idx) + : ResourceRequest(res, inst, stage_num, res_idx, slot_num, cmd), + useDefIdx(use_def_idx) + { } + + int useDefIdx; + }; +}; + +#endif //__CPU_INORDER_USE_DEF_UNIT_HH__ diff --git a/src/cpu/inorder/thread_context.cc b/src/cpu/inorder/thread_context.cc new file mode 100644 index 000000000..5e2c789cb --- /dev/null +++ b/src/cpu/inorder/thread_context.cc @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include "arch/isa_traits.hh" +#include "cpu/exetrace.hh" +#include "cpu/inorder/thread_context.hh" + +using namespace TheISA; + +void +InOrderThreadContext::takeOverFrom(ThreadContext *old_context) +{ + // some things should already be set up + assert(getProcessPtr() == old_context->getProcessPtr()); + + // copy over functional state + setStatus(old_context->status()); + copyArchRegs(old_context); + //setCpuId(0/*old_context->readCpuId()*/); + + thread->funcExeInst = old_context->readFuncExeInst(); + old_context->setStatus(ThreadContext::Unallocated); + thread->inSyscall = false; + thread->trapPending = false; +} + +void +InOrderThreadContext::activate(int delay) +{ + DPRINTF(InOrderCPU, "Calling activate on Thread Context %d\n", + getThreadNum()); + + if (thread->status() == ThreadContext::Active) + return; + + // @TODO: Make this process useful again... + //if (thread->status() == ThreadContext::Unallocated) { + // Allows the CPU to drain partitioned resources + // before inserting thread into the CPU + // (e.g. bind physical registers) + //cpu->activateWhenReady(thread->readTid()); + //return; + //} + + thread->setStatus(ThreadContext::Active); + + // status() == Suspended + cpu->activateContext(thread->readTid(), delay); +} + + +void +InOrderThreadContext::suspend(int delay) +{ + DPRINTF(InOrderCPU, "Calling suspend on Thread Context %d\n", + getThreadNum()); + + if (thread->status() == ThreadContext::Suspended) + return; + + thread->setStatus(ThreadContext::Suspended); + cpu->suspendContext(thread->readTid(), delay); +} + +void +InOrderThreadContext::deallocate(int delay) +{ + DPRINTF(InOrderCPU, "Calling deallocate on Thread Context %d\n", + getThreadNum()); + + if (thread->status() == ThreadContext::Unallocated) + return; + + thread->setStatus(ThreadContext::Unallocated); + cpu->deallocateContext(thread->readTid(), delay); +} + +void +InOrderThreadContext::halt(int delay) +{ + DPRINTF(InOrderCPU, "Calling halt on Thread Context %d\n", + getThreadNum()); + + if (thread->status() == ThreadContext::Halted) + return; + + thread->setStatus(ThreadContext::Halted); + cpu->haltContext(thread->readTid(), delay); +} + + +void +InOrderThreadContext::regStats(const std::string &name) +{ +#if FULL_SYSTEM + thread->kernelStats = new Kernel::Statistics(cpu->system); + thread->kernelStats->regStats(name + ".kern"); +#endif + ; +} + + +void +InOrderThreadContext::serialize(std::ostream &os) +{ +#if FULL_SYSTEM + if (thread->kernelStats) + thread->kernelStats->serialize(os); +#endif + ; +} + + +void +InOrderThreadContext::unserialize(Checkpoint *cp, const std::string §ion) +{ +#if FULL_SYSTEM + if (thread->kernelStats) + thread->kernelStats->unserialize(cp, section); +#endif + ; +} + +TheISA::MachInst +InOrderThreadContext:: getInst() +{ + return thread->getInst(); +} + + +void +InOrderThreadContext::copyArchRegs(ThreadContext *tc) +{ + unsigned tid = thread->readTid(); + PhysRegIndex renamed_reg; + + // First loop through the integer registers. + for (int i = 0; i < TheISA::NumIntRegs; ++i) { + renamed_reg = cpu->renameMap[tid].lookup(i); + + DPRINTF(InOrderCPU, "Copying over register %i, had data %lli, " + "now has data %lli.\n", + renamed_reg, cpu->readIntReg(renamed_reg, tid), + tc->readIntReg(i)); + + cpu->setIntReg(renamed_reg, tc->readIntReg(i), tid); + } + + // Then loop through the floating point registers. + for (int i = 0; i < TheISA::NumFloatRegs; ++i) { + renamed_reg = cpu->renameMap[tid].lookup(i + TheISA::FP_Base_DepTag); + cpu->setFloatRegBits(renamed_reg, tc->readFloatRegBits(i), tid); + } + + // Copy the misc regs. + TheISA::copyMiscRegs(tc, this); + + // Then finally set the PC and the next PC. + cpu->setPC(tc->readPC(), tid); + cpu->setNextPC(tc->readNextPC(), tid); + cpu->setNextNPC(tc->readNextNPC(), tid); + this->thread->funcExeInst = tc->readFuncExeInst(); +} + + +void +InOrderThreadContext::clearArchRegs() +{} + + +uint64_t +InOrderThreadContext::readIntReg(int reg_idx) +{ + return cpu->readIntReg(reg_idx, thread->readTid()); +} + +FloatReg +InOrderThreadContext::readFloatReg(int reg_idx, int width) +{ + return cpu->readFloatReg(reg_idx, thread->readTid(), width); +} + +FloatReg +InOrderThreadContext::readFloatReg(int reg_idx) +{ + return cpu->readFloatReg(reg_idx, thread->readTid()); +} + +FloatRegBits +InOrderThreadContext::readFloatRegBits(int reg_idx, int width) +{ + return cpu->readFloatRegBits(reg_idx, thread->readTid(), width); +} + +FloatRegBits +InOrderThreadContext::readFloatRegBits(int reg_idx) +{ + return cpu->readFloatRegBits(reg_idx, thread->readTid()); +} + +uint64_t +InOrderThreadContext::readRegOtherThread(int reg_idx, unsigned tid) +{ + return cpu->readRegOtherThread(reg_idx, tid); +} + +void +InOrderThreadContext::setIntReg(int reg_idx, uint64_t val) +{ + cpu->setIntReg(reg_idx, val, thread->readTid()); + + // Squash if we're not already in a state update mode. + //if (!thread->trapPending && !thread->inSyscall) { + // cpu->squashFromTC(thread->readTid()); + //} +} + +void +InOrderThreadContext::setFloatReg(int reg_idx, FloatReg val, int width) +{ + cpu->setFloatReg(reg_idx, val, thread->readTid(), width); + + // Squash if we're not already in a state update mode. + //if (!thread->trapPending && !thread->inSyscall) { + //cpu->squashFromTC(thread->readTid()); + //} +} + +void +InOrderThreadContext::setFloatReg(int reg_idx, FloatReg val) +{ + cpu->setFloatReg(reg_idx, val, thread->readTid()); + + // Squash if we're not already in a state update mode. + //if (!thread->trapPending && !thread->inSyscall) { + //cpu->squashFromTC(thread->readTid()); + //} +} + +void +InOrderThreadContext::setFloatRegBits(int reg_idx, FloatRegBits val, + int width) +{ + cpu->setFloatRegBits(reg_idx, val, thread->readTid(), width); + + // Squash if we're not already in a state update mode. + //if (!thread->trapPending && !thread->inSyscall) { + //cpu->squashFromTC(thread->readTid()); + //} +} + +void +InOrderThreadContext::setFloatRegBits(int reg_idx, FloatRegBits val) +{ + cpu->setFloatRegBits(reg_idx, val, thread->readTid()); + + // Squash if we're not already in a state update mode. + //if (!thread->trapPending && !thread->inSyscall) { + //cpu->squashFromTC(thread->readTid()); + //} +} + +void +InOrderThreadContext::setRegOtherThread(int misc_reg, const MiscReg &val, unsigned tid) +{ + cpu->setRegOtherThread(misc_reg, val, tid); +} + +void +InOrderThreadContext::setPC(uint64_t val) +{ + DPRINTF(InOrderCPU, "Setting PC to %08p\n", val); + cpu->setPC(val, thread->readTid()); + + // Squash if we're not already in a state update mode. + //if (!thread->trapPending && !thread->inSyscall) { + //cpu->squashFromTC(thread->readTid()); + //} +} + +void +InOrderThreadContext::setNextPC(uint64_t val) +{ + DPRINTF(InOrderCPU, "Setting NPC to %08p\n", val); + cpu->setNextPC(val, thread->readTid()); + + // Squash if we're not already in a state update mode. + //if (!thread->trapPending && !thread->inSyscall) { + //cpu->squashFromTC(thread->readTid()); + //} +} + +void +InOrderThreadContext::setNextNPC(uint64_t val) +{ + DPRINTF(InOrderCPU, "Setting NNPC to %08p\n", val); + cpu->setNextNPC(val, thread->readTid()); + + // Squash if we're not already in a state update mode. + //if (!thread->trapPending && !thread->inSyscall) { + //cpu->squashFromTC(thread->readTid()); + //} +} + +void +InOrderThreadContext::setMiscRegNoEffect(int misc_reg, const MiscReg &val) +{ + cpu->setMiscRegNoEffect(misc_reg, val, thread->readTid()); + + // Squash if we're not already in a state update mode. + //if (!thread->trapPending && !thread->inSyscall) { + //cpu->squashFromTC(thread->readTid()); + //} +} + +void +InOrderThreadContext::setMiscReg(int misc_reg, const MiscReg &val) +{ + cpu->setMiscReg(misc_reg, val, thread->readTid()); + + // Squash if we're not already in a state update mode. + //if (!thread->trapPending && !thread->inSyscall) { + //cpu->squashFromTC(thread->readTid()); + //} +} + +TheISA::IntReg +InOrderThreadContext::getSyscallArg(int i) +{ + return cpu->getSyscallArg(i, thread->readTid()); +} + +void +InOrderThreadContext::setSyscallArg(int i, IntReg val) +{ + cpu->setSyscallArg(i, val, thread->readTid()); +} + +void +InOrderThreadContext::setSyscallReturn(SyscallReturn return_value) +{ + cpu->setSyscallReturn(return_value, thread->readTid()); +} diff --git a/src/cpu/inorder/thread_context.hh b/src/cpu/inorder/thread_context.hh new file mode 100644 index 000000000..919d5d2b6 --- /dev/null +++ b/src/cpu/inorder/thread_context.hh @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#ifndef __CPU_INORDER_THREAD_CONTEXT_HH__ +#define __CPU_INORDER_THREAD_CONTEXT_HH__ + +#include "cpu/exetrace.hh" +#include "cpu/thread_context.hh" +#include "cpu/inorder/thread_state.hh" +#include "cpu/inorder/cpu.hh" + +class TranslatingPort; + +/** + * Derived ThreadContext class for use with the InOrderCPU. It + * provides the interface for any external objects to access a + * single thread's state and some general CPU state. Any time + * external objects try to update state through this interface, + * the CPU will create an event to squash all in-flight + * instructions in order to ensure state is maintained correctly. + * It must be defined specifically for the InOrderCPU because + * not all architectural state is located within the O3ThreadState + * (such as the commit PC, and registers), and specific actions + * must be taken when using this interface (such as squashing all + * in-flight instructions when doing a write to this interface). + */ +class InOrderThreadContext : public ThreadContext +{ + public: + InOrderThreadContext() { } + + /** Pointer to the CPU. */ + InOrderCPU *cpu; + + /** Pointer to the thread state that this TC corrseponds to. */ + InOrderThreadState *thread; + + + /** Returns a pointer to the ITB. */ + TheISA::ITB *getITBPtr() { return cpu->itb; } + + /** Returns a pointer to the DTB. */ + TheISA::DTB *getDTBPtr() { return cpu->dtb; } + + System *getSystemPtr() { return cpu->system; } + + /** Returns a pointer to this CPU. */ + virtual BaseCPU *getCpuPtr() { return cpu; } + + /** Returns a pointer to this CPU. */ + virtual std::string getCpuName() { return cpu->name(); } + + /** Reads this CPU's ID. */ + virtual int cpuId() { return cpu->cpuId(); } + + virtual int contextId() { return thread->contextId(); } + + virtual void setContextId(int id) { thread->setContextId(id); } + + /** Returns this thread's ID number. */ + virtual int threadId() { return thread->threadId(); } + virtual void setThreadId(int id) { return thread->setThreadId(id); } + + virtual uint64_t readMicroPC() + { return 0; } + + virtual void setMicroPC(uint64_t val) { }; + + virtual uint64_t readNextMicroPC() + { return 0; } + + virtual void setNextMicroPC(uint64_t val) { }; + + virtual TranslatingPort *getMemPort() { return thread->getMemPort(); } + + /** Returns a pointer to this thread's process. */ + virtual Process *getProcessPtr() { return thread->getProcessPtr(); } + + /** Returns this thread's status. */ + virtual Status status() const { return thread->status(); } + + /** Sets this thread's status. */ + virtual void setStatus(Status new_status) + { thread->setStatus(new_status); } + + /** Returns a pointer to the last graduated/committed instruction in the thread */ + //DynInstPtr getLastGradInst() { return thread->getLastGradInst(); } + + /** Set the status to Active. Optional delay indicates number of + * cycles to wait before beginning execution. */ + virtual void activate(int delay = 1); + + /** Set the status to Suspended. */ + virtual void suspend(int delay = 0); + + /** Set the status to Unallocated. */ + virtual void deallocate(int delay = 1); + + /** Set the status to Halted. */ + virtual void halt(int delay = 0); + + /** Takes over execution of a thread from another CPU. */ + virtual void takeOverFrom(ThreadContext *old_context); + + /** Registers statistics associated with this TC. */ + virtual void regStats(const std::string &name); + + /** Serializes state. */ + virtual void serialize(std::ostream &os); + /** Unserializes state. */ + virtual void unserialize(Checkpoint *cp, const std::string §ion); + + /** Returns this thread's ID number. */ + virtual int getThreadNum() { return thread->readTid(); } + + /** Returns the instruction this thread is currently committing. + * Only used when an instruction faults. + */ + virtual TheISA::MachInst getInst(); + + /** Copies the architectural registers from another TC into this TC. */ + virtual void copyArchRegs(ThreadContext *tc); + + /** Resets all architectural registers to 0. */ + virtual void clearArchRegs(); + + /** Reads an integer register. */ + virtual uint64_t readIntReg(int reg_idx); + + virtual FloatReg readFloatReg(int reg_idx, int width); + + virtual FloatReg readFloatReg(int reg_idx); + + virtual FloatRegBits readFloatRegBits(int reg_idx, int width); + + virtual FloatRegBits readFloatRegBits(int reg_idx); + + virtual uint64_t readRegOtherThread(int misc_reg, unsigned tid); + + /** Sets an integer register to a value. */ + virtual void setIntReg(int reg_idx, uint64_t val); + + virtual void setFloatReg(int reg_idx, FloatReg val, int width); + + virtual void setFloatReg(int reg_idx, FloatReg val); + + virtual void setFloatRegBits(int reg_idx, FloatRegBits val, int width); + + virtual void setFloatRegBits(int reg_idx, FloatRegBits val); + + virtual void setRegOtherThread(int misc_reg, const MiscReg &val, unsigned tid); + + /** Reads this thread's PC. */ + virtual uint64_t readPC() + { return cpu->readPC(thread->readTid()); } + + /** Sets this thread's PC. */ + virtual void setPC(uint64_t val); + + /** Reads this thread's next PC. */ + virtual uint64_t readNextPC() + { return cpu->readNextPC(thread->readTid()); } + + /** Sets this thread's next PC. */ + virtual void setNextPC(uint64_t val); + + virtual uint64_t readNextNPC() + { return cpu->readNextNPC(thread->readTid()); } + + virtual void setNextNPC(uint64_t val); + + /** Reads a miscellaneous register. */ + virtual MiscReg readMiscRegNoEffect(int misc_reg) + { return cpu->readMiscRegNoEffect(misc_reg, thread->readTid()); } + + /** Reads a misc. register, including any side-effects the + * read might have as defined by the architecture. */ + virtual MiscReg readMiscReg(int misc_reg) + { return cpu->readMiscReg(misc_reg, thread->readTid()); } + + /** Sets a misc. register. */ + virtual void setMiscRegNoEffect(int misc_reg, const MiscReg &val); + + /** Sets a misc. register, including any side-effects the + * write might have as defined by the architecture. */ + virtual void setMiscReg(int misc_reg, const MiscReg &val); + + virtual void activateContext(int delay) + { cpu->activateContext(thread->readTid(), delay); } + + virtual void deallocateContext() + { cpu->deallocateContext(thread->readTid()); } + + /** Returns the number of consecutive store conditional failures. */ + // @todo: Figure out where these store cond failures should go. + virtual unsigned readStCondFailures() + { return thread->storeCondFailures; } + + /** Sets the number of consecutive store conditional failures. */ + virtual void setStCondFailures(unsigned sc_failures) + { thread->storeCondFailures = sc_failures; } + + // Only really makes sense for old CPU model. Lots of code + // outside the CPU still checks this function, so it will + // always return false to keep everything working. + /** Checks if the thread is misspeculating. Because it is + * very difficult to determine if the thread is + * misspeculating, this is set as false. */ + virtual bool misspeculating() { return false; } + + /** Gets a syscall argument by index. */ + virtual IntReg getSyscallArg(int i); + + /** Sets a syscall argument. */ + virtual void setSyscallArg(int i, IntReg val); + + /** Sets the syscall return value. */ + virtual void setSyscallReturn(SyscallReturn return_value); + + /** Executes a syscall in SE mode. */ + virtual void syscall(int64_t callnum) + { return cpu->syscall(callnum, thread->readTid()); } + + /** Reads the funcExeInst counter. */ + virtual Counter readFuncExeInst() { return thread->funcExeInst; } + + virtual void changeRegFileContext(unsigned param, + unsigned val) + { panic("Not supported!"); } + + /** This function exits the thread context in the CPU and returns + * 1 if the CPU has no more active threads (meaning it's OK to exit); + * Used in syscall-emulation mode when a thread executes the 'exit' + * syscall. + */ + virtual int exit() + { + this->deallocate(); + + // If there are still threads executing in the system (for now + // this single cpu) + if (this->cpu->numActiveThreads() - 1 > 0) + return 0; // don't exit simulation + else + return 1; // exit simulation + } + + virtual void setThreadRescheduleCondition(uint64_t cond) + { + this->deallocate(); + + this->setStatus(ThreadContext::Suspended); + + activateContext(cond); + } +}; + +#endif diff --git a/src/cpu/inorder/thread_state.hh b/src/cpu/inorder/thread_state.hh new file mode 100644 index 000000000..eb4fe40b2 --- /dev/null +++ b/src/cpu/inorder/thread_state.hh @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Kevin Lim + */ + +#ifndef __CPU_INORDER_THREAD_STATE_HH__ +#define __CPU_INORDER_THREAD_STATE_HH__ + +#include "arch/faults.hh" +#include "arch/isa_traits.hh" +#include "cpu/thread_context.hh" +#include "cpu/thread_state.hh" + +class Event; +class FunctionalMemory; +class Process; +class InOrderCPU; + +/** + * Class that has various thread state, such as the status, the + * current instruction being processed, whether or not the thread has + * a trap pending or is being externally updated, the ThreadContext + * pointer, etc. It also handles anything related to a specific + * thread's process, such as syscalls and checking valid addresses. + */ +class InOrderThreadState : public ThreadState { + typedef ThreadContext::Status Status; + + private: + /** Pointer to the CPU. */ + InOrderCPU *cpu; + + public: + /** Whether or not the thread is currently in syscall mode, and + * thus able to be externally updated without squashing. + */ + bool inSyscall; + + /** Whether or not the thread is currently waiting on a trap, and + * thus able to be externally updated without squashing. + */ + bool trapPending; + + + InOrderThreadState(InOrderCPU *_cpu, int _thread_num, Process *_process, int _asid) + : ThreadState(reinterpret_cast(_cpu), 0/*_thread_num*/, _process, 0/*_asid*/), + cpu(_cpu), inSyscall(0), trapPending(0) + { } + + /** Handles the syscall. */ + void syscall(int64_t callnum) { process->syscall(callnum, tc); } + + /** Pointer to the ThreadContext of this thread. */ + ThreadContext *tc; + + /** Returns a pointer to the TC of this thread. */ + ThreadContext *getTC() { return tc; } + + int readTid() { return 0; } + + /** Pointer to the last graduated instruction in the thread */ + //DynInstPtr lastGradInst; +}; + +#endif // __CPU_INORDER_THREAD_STATE_HH__ -- cgit v1.2.3 From cf4a00ca410226d3fd1b4db816938b7ddf78a333 Mon Sep 17 00:00:00 2001 From: Korey Sewell Date: Tue, 10 Feb 2009 15:49:29 -0800 Subject: Configs: Add support for the InOrder CPU model --- src/cpu/inorder/cpu.hh | 15 +- src/cpu/inorder/inorder_dyn_inst.cc | 10 +- src/cpu/inorder/resources/cache_unit.cc | 254 ++++++++++++++++---------------- src/cpu/inorder/resources/cache_unit.hh | 42 ++++-- 4 files changed, 169 insertions(+), 152 deletions(-) (limited to 'src') diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh index cd1eb6f92..34eabbad4 100644 --- a/src/cpu/inorder/cpu.hh +++ b/src/cpu/inorder/cpu.hh @@ -312,6 +312,13 @@ class InOrderCPU : public BaseCPU void deallocateThread(unsigned tid); void deactivateThread(unsigned tid); + int + contextId() + { + hack_once("return a bogus context id"); + return 0; + } + /** Remove Thread from Active Threads List && * Remove Thread Context from CPU. */ @@ -414,20 +421,20 @@ class InOrderCPU : public BaseCPU int width = TheISA::SingleWidth); /** Reads a miscellaneous register. */ - MiscReg readMiscRegNoEffect(int misc_reg, unsigned tid); + MiscReg readMiscRegNoEffect(int misc_reg, unsigned tid = 0); /** Reads a misc. register, including any side effects the read * might have as defined by the architecture. */ - MiscReg readMiscReg(int misc_reg, unsigned tid); + MiscReg readMiscReg(int misc_reg, unsigned tid = 0); /** Sets a miscellaneous register. */ - void setMiscRegNoEffect(int misc_reg, const MiscReg &val, unsigned tid); + void setMiscRegNoEffect(int misc_reg, const MiscReg &val, unsigned tid = 0); /** Sets a misc. register, including any side effects the write * might have as defined by the architecture. */ - void setMiscReg(int misc_reg, const MiscReg &val, unsigned tid); + void setMiscReg(int misc_reg, const MiscReg &val, unsigned tid = 0); /** Reads a int/fp/misc reg. from another thread depending on ISA-defined * target thread diff --git a/src/cpu/inorder/inorder_dyn_inst.cc b/src/cpu/inorder/inorder_dyn_inst.cc index 89362c656..3a45bd01e 100644 --- a/src/cpu/inorder/inorder_dyn_inst.cc +++ b/src/cpu/inorder/inorder_dyn_inst.cc @@ -454,9 +454,8 @@ InOrderDynInst::readMiscRegNoEffect(int misc_reg) MiscReg InOrderDynInst::readMiscRegOperandNoEffect(const StaticInst *si, int idx) { - return this->cpu->readMiscRegNoEffect( - si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, - this->threadNumber); + int reg = si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag; + return cpu->readMiscRegNoEffect(reg, this->threadNumber); } /** Reads a misc. register, including any side-effects the read @@ -465,9 +464,8 @@ InOrderDynInst::readMiscRegOperandNoEffect(const StaticInst *si, int idx) MiscReg InOrderDynInst::readMiscRegOperand(const StaticInst *si, int idx) { - return this->cpu->readMiscReg( - si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, - this->threadNumber); + int reg = si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag; + return this->cpu->readMiscReg(reg, this->threadNumber); } /** Sets a misc. register. */ diff --git a/src/cpu/inorder/resources/cache_unit.cc b/src/cpu/inorder/resources/cache_unit.cc index 79ca7a096..6b62c864a 100644 --- a/src/cpu/inorder/resources/cache_unit.cc +++ b/src/cpu/inorder/resources/cache_unit.cc @@ -43,7 +43,6 @@ using namespace std; using namespace TheISA; using namespace ThePipeline; - Tick CacheUnit::CachePort::recvAtomic(PacketPtr pkt) { @@ -80,7 +79,7 @@ CacheUnit::CachePort::recvRetry() } CacheUnit::CacheUnit(string res_name, int res_id, int res_width, - int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params) + int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params) : Resource(res_name, res_id, res_width, res_latency, _cpu), retryPkt(NULL), retrySlot(-1) { @@ -92,9 +91,8 @@ CacheUnit::CacheUnit(string res_name, int res_id, int res_width, cacheBlocked = false; } - Port * -CacheUnit::getPort(const std::string &if_name, int idx) +CacheUnit::getPort(const string &if_name, int idx) { if (if_name == resName) return cachePort; @@ -106,7 +104,7 @@ int CacheUnit::getSlot(DynInstPtr inst) { if (!inst->validMemAddr()) { - panic("Mem. Addr. must be set before requesting cache access.\n"); + panic("Mem. Addr. must be set before requesting cache access\n"); } Addr req_addr = inst->getMemAddr(); @@ -116,20 +114,19 @@ CacheUnit::getSlot(DynInstPtr inst) int new_slot = Resource::getSlot(inst); - if (new_slot != -1) { - inst->memTime = curTick; - addrList.push_back(req_addr); - addrMap[req_addr] = inst->seqNum; - DPRINTF(InOrderCachePort, "[tid:%i]: [sn:%i]: Address %08p added to dependency list.\n", - inst->readTid(), inst->seqNum, req_addr); - return new_slot; - } else { + if (new_slot == -1) return -1; - } - + inst->memTime = curTick; + addrList.push_back(req_addr); + addrMap[req_addr] = inst->seqNum; + DPRINTF(InOrderCachePort, + "[tid:%i]: [sn:%i]: Address %08p added to dependency list\n", + inst->readTid(), inst->seqNum, req_addr); + return new_slot; } else { - DPRINTF(InOrderCachePort,"Denying request because there is an outstanding" + DPRINTF(InOrderCachePort, + "Denying request because there is an outstanding" " request to/for addr. %08p. by [sn:%i] @ tick %i\n", req_addr, addrMap[req_addr], inst->memTime); return -1; @@ -139,11 +136,12 @@ CacheUnit::getSlot(DynInstPtr inst) void CacheUnit::freeSlot(int slot_num) { - std::vector::iterator vect_it = find(addrList.begin(), addrList.end(), - reqMap[slot_num]->inst->getMemAddr()); + vector::iterator vect_it = find(addrList.begin(), addrList.end(), + reqMap[slot_num]->inst->getMemAddr()); assert(vect_it != addrList.end()); - DPRINTF(InOrderCachePort, "[tid:%i]: Address %08p removed from dependency list.\n", + DPRINTF(InOrderCachePort, + "[tid:%i]: Address %08p removed from dependency list\n", reqMap[slot_num]->inst->readTid(), (*vect_it)); addrList.erase(vect_it); @@ -158,7 +156,7 @@ CacheUnit::getRequest(DynInstPtr inst, int stage_num, int res_idx, ScheduleEntry* sched_entry = inst->resSched.top(); if (!inst->validMemAddr()) { - panic("Mem. Addr. must be set before requesting cache access.\n"); + panic("Mem. Addr. must be set before requesting cache access\n"); } int req_size = 0; @@ -168,23 +166,26 @@ CacheUnit::getRequest(DynInstPtr inst, int stage_num, int res_idx, pkt_cmd = MemCmd::ReadReq; req_size = inst->getMemAccSize(); - DPRINTF(InOrderCachePort, "[tid:%i]: %i byte Read request from [sn:%i] for addr %08p.\n", + DPRINTF(InOrderCachePort, + "[tid:%i]: %i byte Read request from [sn:%i] for addr %08p\n", inst->readTid(), req_size, inst->seqNum, inst->getMemAddr()); } else if (sched_entry->cmd == InitiateWriteData) { pkt_cmd = MemCmd::WriteReq; req_size = inst->getMemAccSize(); - - DPRINTF(InOrderCachePort, "[tid:%i]: %i byte Write request from [sn:%i] for addr %08p.\n", + DPRINTF(InOrderCachePort, + "[tid:%i]: %i byte Write request from [sn:%i] for addr %08p\n", inst->readTid(), req_size, inst->seqNum, inst->getMemAddr()); } else if (sched_entry->cmd == InitiateFetch){ pkt_cmd = MemCmd::ReadReq; req_size = sizeof(MachInst); //@TODO: mips16e - DPRINTF(InOrderCachePort, "[tid:%i]: %i byte Fetch request from [sn:%i] for addr %08p.\n", + DPRINTF(InOrderCachePort, + "[tid:%i]: %i byte Fetch request from [sn:%i] for addr %08p\n", inst->readTid(), req_size, inst->seqNum, inst->getMemAddr()); } else { - panic("%i: Unexpected request type (%i) to %s", curTick, sched_entry->cmd, name()); + panic("%i: Unexpected request type (%i) to %s", curTick, + sched_entry->cmd, name()); } return new CacheRequest(this, inst, stage_num, id, slot_num, @@ -205,26 +206,27 @@ CacheUnit::requestAgain(DynInstPtr inst, bool &service_request) if (cache_req->cmd != inst->resSched.top()->cmd) { // If different, then update command in the request cache_req->cmd = inst->resSched.top()->cmd; - DPRINTF(InOrderCachePort, "[tid:%i]: [sn:%i]: Updating the command for this " - "instruction.\n", inst->readTid(), inst->seqNum); + DPRINTF(InOrderCachePort, + "[tid:%i]: [sn:%i]: the command for this instruction\n", + inst->readTid(), inst->seqNum); service_request = true; } else { // If same command, just check to see if memory access was completed // but dont try to re-execute - DPRINTF(InOrderCachePort, "[tid:%i]: [sn:%i]: requesting this resource again.\n", + DPRINTF(InOrderCachePort, + "[tid:%i]: [sn:%i]: requesting this resource again\n", inst->readTid(), inst->seqNum); service_request = true; } - } void CacheUnit::execute(int slot_num) { if (cacheBlocked) { - DPRINTF(InOrderCachePort, "Cache Blocked. Cannot Access.\n"); + DPRINTF(InOrderCachePort, "Cache Blocked. Cannot Access\n"); return; } @@ -243,89 +245,85 @@ CacheUnit::execute(int slot_num) switch (cache_req->cmd) { case InitiateFetch: - { - DPRINTF(InOrderCachePort, - "[tid:%u]: Initiating fetch access to %s for addr. %08p\n", - tid, name(), cache_req->inst->getMemAddr()); + DPRINTF(InOrderCachePort, + "[tid:%u]: Initiating fetch access to %s for addr. %08p\n", + tid, name(), cache_req->inst->getMemAddr()); - DPRINTF(InOrderCachePort, - "[tid:%u]: Fetching new cache block from addr: %08p\n", - tid, cache_req->memReq->getVaddr()); + DPRINTF(InOrderCachePort, + "[tid:%u]: Fetching new cache block from addr: %08p\n", + tid, cache_req->memReq->getVaddr()); - inst->setCurResSlot(slot_num); - doDataAccess(inst); - } + inst->setCurResSlot(slot_num); + doDataAccess(inst); break; case CompleteFetch: - { - if (cache_req->isMemAccComplete()) { - DPRINTF(InOrderCachePort, - "[tid:%i]: Completing Fetch Access for [sn:%i]\n", - tid, inst->seqNum); + if (cache_req->isMemAccComplete()) { + DPRINTF(InOrderCachePort, + "[tid:%i]: Completing Fetch Access for [sn:%i]\n", + tid, inst->seqNum); - MachInst mach_inst = cache_req->dataPkt->get(); + MachInst mach_inst = cache_req->dataPkt->get(); - //@TODO: May Need This Function for Endianness-Compatibility - //mach_inst = gtoh(*reinterpret_cast(&cacheData[tid][offset])); + /** + * @TODO: May Need This Function for Endianness-Compatibility + * mach_inst = + * gtoh(*reinterpret_cast(&cacheData[tid][offset])); + */ - DPRINTF(InOrderCachePort, - "[tid:%i]: Fetched instruction is %08p\n", - tid, mach_inst); + DPRINTF(InOrderCachePort, + "[tid:%i]: Fetched instruction is %08p\n", + tid, mach_inst); - //ExtMachInst ext_inst - // = TheISA::makeExtMI(mach_inst, cpu->tcBase(tid)); + // ExtMachInst ext_inst = makeExtMI(mach_inst, cpu->tcBase(tid)); - inst->setMachInst(mach_inst); - inst->setASID(tid); - inst->setThreadState(cpu->thread[tid]); + inst->setMachInst(mach_inst); + inst->setASID(tid); + inst->setThreadState(cpu->thread[tid]); - DPRINTF(InOrderStage, "[tid:%i]: Instruction [sn:%i] is: %s\n", - tid, seq_num, inst->staticInst->disassemble(inst->PC)); + DPRINTF(InOrderStage, "[tid:%i]: Instruction [sn:%i] is: %s\n", + tid, seq_num, inst->staticInst->disassemble(inst->PC)); - // Set Up More TraceData info - if (inst->traceData) { - inst->traceData->setStaticInst(inst->staticInst); - inst->traceData->setPC(inst->readPC()); - } + // Set Up More TraceData info + if (inst->traceData) { + inst->traceData->setStaticInst(inst->staticInst); + inst->traceData->setPC(inst->readPC()); + } - cache_req->done(); - } else { - DPRINTF(InOrderCachePort, "[tid:%i]: [sn:%i]: Unable to Complete Fetch Access.\n", + cache_req->done(); + } else { + DPRINTF(InOrderCachePort, + "[tid:%i]: [sn:%i]: Unable to Complete Fetch Access\n", tid, inst->seqNum); - DPRINTF(InOrderStall, "STALL: [tid:%i]: Fetch miss from %08p.\n", - tid, cache_req->inst->readPC()); - cache_req->setCompleted(false); - } + DPRINTF(InOrderStall, + "STALL: [tid:%i]: Fetch miss from %08p\n", + tid, cache_req->inst->readPC()); + cache_req->setCompleted(false); } break; case InitiateReadData: case InitiateWriteData: - { - DPRINTF(InOrderCachePort, "[tid:%u]: Initiating data access to %s " - "for addr. %08p\n", - tid, name(), cache_req->inst->getMemAddr()); - - inst->setCurResSlot(slot_num); - //inst->memAccess(); - inst->initiateAcc(); - } + DPRINTF(InOrderCachePort, + "[tid:%u]: Initiating data access to %s for addr. %08p\n", + tid, name(), cache_req->inst->getMemAddr()); + + inst->setCurResSlot(slot_num); + //inst->memAccess(); + inst->initiateAcc(); break; case CompleteReadData: case CompleteWriteData: - { - DPRINTF(InOrderCachePort, - "[tid:%i]: [sn:%i]: Trying to Complete Data Access.\n", - tid, inst->seqNum); - if (cache_req->isMemAccComplete()) { - cache_req->done(); - } else { - DPRINTF(InOrderStall, "STALL: [tid:%i]: Data miss from %08p\n", - tid, cache_req->inst->getMemAddr()); - cache_req->setCompleted(false); - } + DPRINTF(InOrderCachePort, + "[tid:%i]: [sn:%i]: Trying to Complete Data Access\n", + tid, inst->seqNum); + if (cache_req->isMemAccComplete()) { + cache_req->done(); + } else { + DPRINTF(InOrderStall, "STALL: [tid:%i]: Data miss from %08p\n", + tid, cache_req->inst->getMemAddr()); + cache_req->setCompleted(false); } break; @@ -364,12 +362,13 @@ CacheUnit::doDataAccess(DynInstPtr inst) if (cache_req->dataPkt->isWrite() && memReq->isLocked()) { assert(cache_req->inst->isStoreConditional()); - DPRINTF(InOrderCachePort, "Evaluating Store Conditional access.\n"); + DPRINTF(InOrderCachePort, "Evaluating Store Conditional access\n"); do_access = TheISA::handleLockedWrite(cpu, memReq); } - - DPRINTF(InOrderCachePort, "[tid:%i] [sn:%i] attempting to access cache..\n", tid, inst->seqNum); + DPRINTF(InOrderCachePort, + "[tid:%i] [sn:%i] attempting to access cache\n", + tid, inst->seqNum); //@TODO: If you want to ignore failed store conditional accesses, then // enable this. However, this might skew memory stats because @@ -377,7 +376,9 @@ CacheUnit::doDataAccess(DynInstPtr inst) // - Remove optionality here ... if (1/*do_access*/) { if (!cachePort->sendTiming(cache_req->dataPkt)) { - DPRINTF(InOrderCachePort, "[tid:%i] [sn:%i] is waiting to retry request.\n", tid, inst->seqNum); + DPRINTF(InOrderCachePort, + "[tid:%i] [sn:%i] is waiting to retry request\n", + tid, inst->seqNum); retrySlot = cache_req->getSlot(); retryReq = cache_req; @@ -391,7 +392,9 @@ CacheUnit::doDataAccess(DynInstPtr inst) cache_req->setCompleted(false); } else { - DPRINTF(InOrderCachePort, "[tid:%i] [sn:%i] is now waiting for cache response.\n", tid, inst->seqNum); + DPRINTF(InOrderCachePort, + "[tid:%i] [sn:%i] is now waiting for cache response\n", + tid, inst->seqNum); cache_req->setCompleted(); cache_req->setMemAccPending(); cacheStatus = cacheWaitResponse; @@ -402,7 +405,8 @@ CacheUnit::doDataAccess(DynInstPtr inst) assert(cache_req->inst->isStoreConditional()); cache_req->setCompleted(true); - DPRINTF(LLSC, "[tid:%i]: T%i Ignoring Failed Store Conditional Access.\n", + DPRINTF(LLSC, + "[tid:%i]: T%i Ignoring Failed Store Conditional Access\n", tid, tid); cache_req->dataPkt->req->setExtraData(0); @@ -431,20 +435,20 @@ CacheUnit::processCacheCompletion(PacketPtr pkt) if (cache_pkt->cacheReq->isSquashed()) { DPRINTF(InOrderCachePort, - "Ignoring completion of squashed access, [tid:%i] [sn:%i].\n", + "Ignoring completion of squashed access, [tid:%i] [sn:%i]\n", cache_pkt->cacheReq->getInst()->readTid(), cache_pkt->cacheReq->getInst()->seqNum); cache_pkt->cacheReq->done(); return; - } else { - DPRINTF(InOrderCachePort, - "[tid:%u]: [sn:%i]: Waking from cache access to addr. %08p.\n", - cache_pkt->cacheReq->getInst()->readTid(), - cache_pkt->cacheReq->getInst()->seqNum, - cache_pkt->cacheReq->getInst()->getMemAddr()); } + DPRINTF(InOrderCachePort, + "[tid:%u]: [sn:%i]: Waking from cache access to addr. %08p\n", + cache_pkt->cacheReq->getInst()->readTid(), + cache_pkt->cacheReq->getInst()->seqNum, + cache_pkt->cacheReq->getInst()->getMemAddr()); + // Cast to correct request type CacheRequest *cache_req = dynamic_cast( findRequest(cache_pkt->cacheReq->getInst())); @@ -462,11 +466,11 @@ CacheUnit::processCacheCompletion(PacketPtr pkt) if (!cache_req->isSquashed()) { if (inst->resSched.top()->cmd == CompleteFetch) { DPRINTF(InOrderCachePort, - "[tid:%u]: [sn:%i]: Processing fetch access.\n", + "[tid:%u]: [sn:%i]: Processing fetch access\n", tid, inst->seqNum); } else if (inst->staticInst && inst->isMemRef()) { DPRINTF(InOrderCachePort, - "[tid:%u]: [sn:%i]: Processing cache access.\n", + "[tid:%u]: [sn:%i]: Processing cache access\n", tid, inst->seqNum); inst->completeAcc(pkt); @@ -475,21 +479,22 @@ CacheUnit::processCacheCompletion(PacketPtr pkt) assert(cache_pkt->isRead()); if (cache_pkt->req->isLocked()) { - DPRINTF(InOrderCachePort, "[tid:%u]: Handling Load-Linked " - "access for [sn:%u].\n", tid, inst->seqNum); + DPRINTF(InOrderCachePort, + "[tid:%u]: Handling Load-Linked for [sn:%u]\n", + tid, inst->seqNum); TheISA::handleLockedRead(cpu, cache_pkt->req); } // @TODO: Hardcoded to for load instructions. Assumes that // the dest. idx 0 is always where the data is loaded to. DPRINTF(InOrderCachePort, - "[tid:%u]: [sn:%i]: Data loaded was: %08p.\n", + "[tid:%u]: [sn:%i]: Data loaded was: %08p\n", tid, inst->seqNum, inst->readIntResult(0)); } else if(inst->isStore()) { assert(cache_pkt->isWrite()); DPRINTF(InOrderCachePort, - "[tid:%u]: [sn:%i]: Data stored was: %08p.\n", + "[tid:%u]: [sn:%i]: Data stored was: %08p\n", tid, inst->seqNum, getMemData(cache_pkt)); @@ -509,8 +514,8 @@ CacheUnit::processCacheCompletion(PacketPtr pkt) cpu->switchToActive(stage_num); } else { DPRINTF(InOrderCachePort, - "[tid:%u] Cache miss on memory access to block @ %08p " - "completed, but squashed.\n", tid, cache_req->inst->readPC()); + "[tid:%u] Miss on block @ %08p completed, but squashed\n", + tid, cache_req->inst->readPC()); cache_req->setMemAccCompleted(); } @@ -520,7 +525,7 @@ CacheUnit::processCacheCompletion(PacketPtr pkt) void CacheUnit::recvRetry() { - DPRINTF(InOrderCachePort, "Retrying Request for [tid:%i] [sn:%i].\n", + DPRINTF(InOrderCachePort, "Retrying Request for [tid:%i] [sn:%i]\n", retryReq->inst->readTid(), retryReq->inst->seqNum); assert(retryPkt != NULL); @@ -532,20 +537,20 @@ CacheUnit::recvRetry() retryPkt = NULL; cacheBlocked = false; } else { - DPRINTF(InOrderCachePort, "Retry Request for [tid:%i] [sn:%i] failed.\n", + DPRINTF(InOrderCachePort, + "Retry Request for [tid:%i] [sn:%i] failed\n", retryReq->inst->readTid(), retryReq->inst->seqNum); } - } void CacheUnit::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num, unsigned tid) { - std::vector slot_remove_list; + vector slot_remove_list; - std::map::iterator map_it = reqMap.begin(); - std::map::iterator map_end = reqMap.end(); + map::iterator map_it = reqMap.begin(); + map::iterator map_end = reqMap.end(); while (map_it != map_end) { ResReqPtr req_ptr = (*map_it).second; @@ -555,7 +560,7 @@ CacheUnit::squash(DynInstPtr inst, int stage_num, req_ptr->getInst()->seqNum > squash_seq_num) { DPRINTF(InOrderCachePort, - "[tid:%i] Squashing request from [sn:%i].\n", + "[tid:%i] Squashing request from [sn:%i]\n", req_ptr->getInst()->readTid(), req_ptr->getInst()->seqNum); req_ptr->setSquashed(); @@ -578,13 +583,13 @@ CacheUnit::squash(DynInstPtr inst, int stage_num, } // Now Delete Slot Entry from Req. Map - for (int i = 0; i < slot_remove_list.size(); i++) { + for (int i = 0; i < slot_remove_list.size(); i++) freeSlot(slot_remove_list[i]); - } - } -uint64_t CacheUnit::getMemData(Packet *packet) { +uint64_t +CacheUnit::getMemData(Packet *packet) +{ switch (packet->getSize()) { case 8: @@ -600,10 +605,7 @@ uint64_t CacheUnit::getMemData(Packet *packet) { return packet->get(); default: - std::cerr << "bad store data size = " << packet->getSize() << std::endl; - - assert(0); - return 0; + panic("bad store data size = %d\n", packet->getSize()); } } diff --git a/src/cpu/inorder/resources/cache_unit.hh b/src/cpu/inorder/resources/cache_unit.hh index 9d048d789..8cd2b89cb 100644 --- a/src/cpu/inorder/resources/cache_unit.hh +++ b/src/cpu/inorder/resources/cache_unit.hh @@ -54,7 +54,8 @@ typedef CacheRequest* CacheReqPtr; class CacheReqPacket; typedef CacheReqPacket* CacheReqPktPtr; -class CacheUnit : public Resource { +class CacheUnit : public Resource +{ public: typedef ThePipeline::DynInstPtr DynInstPtr; @@ -88,8 +89,9 @@ class CacheUnit : public Resource { public: /** Default constructor. */ CachePort(CacheUnit *_cachePortUnit) - : Port(_cachePortUnit->name() + "-cache-port", (MemObject*)_cachePortUnit->cpu), - cachePortUnit(_cachePortUnit) + : Port(_cachePortUnit->name() + "-cache-port", + (MemObject*)_cachePortUnit->cpu), + cachePortUnit(_cachePortUnit) { } bool snoopRangeSent; @@ -214,23 +216,25 @@ class CacheUnit : public Resource { /** @todo: Add Resource Stats Here */ }; -struct CacheSchedEntry : public ThePipeline::ScheduleEntry { +struct CacheSchedEntry : public ThePipeline::ScheduleEntry +{ enum EntryType { FetchAccess, DataAccess }; - CacheSchedEntry(int stage_num, int _priority, int res_num, MemCmd::Command pkt_cmd, - EntryType _type = FetchAccess) : - ScheduleEntry(stage_num, _priority, res_num), pktCmd(pkt_cmd), - type(_type) + CacheSchedEntry(int stage_num, int _priority, int res_num, + MemCmd::Command pkt_cmd, EntryType _type = FetchAccess) + : ScheduleEntry(stage_num, _priority, res_num), pktCmd(pkt_cmd), + type(_type) { } MemCmd::Command pktCmd; EntryType type; }; -class CacheRequest : public ResourceRequest { +class CacheRequest : public ResourceRequest +{ public: CacheRequest(CacheUnit *cres, DynInstPtr inst, int stage_num, int res_idx, int slot_num, unsigned cmd, int req_size, @@ -246,10 +250,10 @@ class CacheRequest : public ResourceRequest { virtual ~CacheRequest() { - /* +#if 0 delete reqData; - Can get rid of packet and packet request now + // Can get rid of packet and packet request now if (*dataPkt) { if (*dataPkt->req) { delete dataPkt->req; @@ -263,17 +267,22 @@ class CacheRequest : public ResourceRequest { delete retryPkt->req; } delete retryPkt; - }*/ + } +#endif - if (memReq) { + if (memReq) delete memReq; - } } virtual PacketDataPtr getData() { return reqData; } - void setMemAccCompleted(bool completed = true) { memAccComplete = completed; } + void + setMemAccCompleted(bool completed = true) + { + memAccComplete = completed; + } + bool isMemAccComplete() { return memAccComplete; } void setMemAccPending(bool pending = true) { memAccPending = pending; } @@ -290,7 +299,8 @@ class CacheRequest : public ResourceRequest { bool memAccPending; }; -class CacheReqPacket : public Packet { +class CacheReqPacket : public Packet +{ public: CacheReqPacket(CacheRequest *_req, Command _cmd, short _dest) -- cgit v1.2.3 From f255957b902e8d7c0a274d8a2f5afe326a813be8 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Tue, 10 Feb 2009 22:19:27 -0800 Subject: style --- src/cpu/static_inst.cc | 43 +++++++++++++++++++++++++++++--- src/cpu/static_inst.hh | 67 +++++++++++++++++--------------------------------- 2 files changed, 63 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/cpu/static_inst.cc b/src/cpu/static_inst.cc index 52a7ede03..01136bda1 100644 --- a/src/cpu/static_inst.cc +++ b/src/cpu/static_inst.cc @@ -40,11 +40,17 @@ StaticInst::DecodeCache StaticInst::decodeCache; StaticInst::AddrDecodeCache StaticInst::addrDecodeCache; StaticInst::cacheElement StaticInst::recentDecodes[2]; +using namespace std; + +StaticInst::~StaticInst() +{ + if (cachedDisassembly) + delete cachedDisassembly; +} + void StaticInst::dumpDecodeCacheStats() { - using namespace std; - cerr << "Decode hash table stats @ " << curTick << ":" << endl; cerr << "\tnum entries = " << decodeCache.size() << endl; cerr << "\tnum buckets = " << decodeCache.bucket_count() << endl; @@ -81,6 +87,37 @@ StaticInstPtr StaticInst::fetchMicroop(MicroPC micropc) { panic("StaticInst::fetchMicroop() called on instruction " - "that is not microcoded."); + "that is not microcoded."); } +Addr +StaticInst::branchTarget(Addr branchPC) const +{ + panic("StaticInst::branchTarget() called on instruction " + "that is not a PC-relative branch."); + M5_DUMMY_RETURN; +} + +Addr +StaticInst::branchTarget(ThreadContext *tc) const +{ + panic("StaticInst::branchTarget() called on instruction " + "that is not an indirect branch."); + M5_DUMMY_RETURN; +} + +Request::Flags +StaticInst::memAccFlags() +{ + panic("StaticInst::memAccFlags called on non-memory instruction"); + return 0; +} + +const string & +StaticInst::disassemble(Addr pc, const SymbolTable *symtab) const +{ + if (!cachedDisassembly) + cachedDisassembly = new string(generateDisassembly(pc, symtab)); + + return *cachedDisassembly; +} diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index f28b53ccf..bf07e06c7 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -382,12 +382,7 @@ class StaticInst : public StaticInstBase { } public: - - virtual ~StaticInst() - { - if (cachedDisassembly) - delete cachedDisassembly; - } + virtual ~StaticInst(); /** * The execute() signatures are auto-generated by scons based on the @@ -406,12 +401,7 @@ class StaticInst : public StaticInstBase * Invalid if not a PC-relative branch (i.e. isDirectCtrl() * should be true). */ - virtual Addr branchTarget(Addr branchPC) const - { - panic("StaticInst::branchTarget() called on instruction " - "that is not a PC-relative branch."); - M5_DUMMY_RETURN - } + virtual Addr branchTarget(Addr branchPC) const; /** * Return the target address for an indirect branch (jump). The @@ -420,12 +410,7 @@ class StaticInst : public StaticInstBase * execute the branch in question. Invalid if not an indirect * branch (i.e. isIndirectCtrl() should be true). */ - virtual Addr branchTarget(ThreadContext *tc) const - { - panic("StaticInst::branchTarget() called on instruction " - "that is not an indirect branch."); - M5_DUMMY_RETURN - } + virtual Addr branchTarget(ThreadContext *tc) const; /** * Return true if the instruction is a control transfer, and if so, @@ -433,11 +418,7 @@ class StaticInst : public StaticInstBase */ bool hasBranchTarget(Addr pc, ThreadContext *tc, Addr &tgt) const; - virtual Request::Flags memAccFlags() - { - panic("StaticInst::memAccFlags called on non-memory instruction"); - return 0; - }; + virtual Request::Flags memAccFlags(); /** * Return string representation of disassembled instruction. @@ -447,14 +428,7 @@ class StaticInst : public StaticInstBase * should not be cached, this function should be overridden directly. */ virtual const std::string &disassemble(Addr pc, - const SymbolTable *symtab = 0) const - { - if (!cachedDisassembly) - cachedDisassembly = - new std::string(generateDisassembly(pc, symtab)); - - return *cachedDisassembly; - } + const SymbolTable *symtab = 0) const; /// Decoded instruction cache type. /// For now we're using a generic hash_map; this seems to work @@ -486,13 +460,13 @@ class StaticInst : public StaticInstBase /// A cache of decoded instruction objects from addresses. static AddrDecodeCache addrDecodeCache; - struct cacheElement { + struct cacheElement + { Addr page_addr; AddrDecodePage *decodePage; - cacheElement() - :decodePage(NULL) { } - } ; + cacheElement() : decodePage(NULL) { } + }; /// An array of recently decoded instructions. // might not use an array if there is only two elements @@ -521,7 +495,7 @@ class StaticInst : public StaticInstBase /// @retval A pointer to the corresponding StaticInst object. //This is defined as inlined below. static StaticInstPtr searchCache(ExtMachInst mach_inst, Addr addr, - AddrDecodePage * decodePage); + AddrDecodePage *decodePage); }; typedef RefCountingPtr StaticInstBasePtr; @@ -575,7 +549,8 @@ class AddrDecodePage public: /// Constructor - AddrDecodePage() { + AddrDecodePage() + { lowerMask = TheISA::PageBytes - 1; memset(valid, 0, TheISA::PageBytes); } @@ -585,7 +560,8 @@ class AddrDecodePage /// related to the address /// @param mach_inst The binary instruction to check /// @param addr The address containing the instruction - inline bool decoded(ExtMachInst mach_inst, Addr addr) + bool + decoded(ExtMachInst mach_inst, Addr addr) { return (valid[addr & lowerMask] && (instructions[addr & lowerMask]->machInst == mach_inst)); @@ -595,19 +571,22 @@ class AddrDecodePage /// to check if the instruction is valid. /// @param addr The address of the instruction. /// @retval A pointer to the corresponding StaticInst object. - inline StaticInstPtr getInst(Addr addr) - { return instructions[addr & lowerMask]; } + StaticInstPtr + getInst(Addr addr) + { + return instructions[addr & lowerMask]; + } /// Inserts a pointer to a StaticInst object into the list of decoded /// instructions on the page. /// @param addr The address of the instruction. /// @param si A pointer to the corresponding StaticInst object. - inline void insert(Addr addr, StaticInstPtr &si) + void + insert(Addr addr, StaticInstPtr &si) { instructions[addr & lowerMask] = si; valid[addr & lowerMask] = true; } - }; @@ -656,7 +635,7 @@ StaticInst::decode(StaticInst::ExtMachInst mach_inst, Addr addr) } // creates a new object for a page of decoded instructions - AddrDecodePage * decodePage = new AddrDecodePage; + AddrDecodePage *decodePage = new AddrDecodePage; addrDecodeCache[page_addr] = decodePage; updateCache(page_addr, decodePage); return searchCache(mach_inst, addr, decodePage); @@ -664,7 +643,7 @@ StaticInst::decode(StaticInst::ExtMachInst mach_inst, Addr addr) inline StaticInstPtr StaticInst::searchCache(ExtMachInst mach_inst, Addr addr, - AddrDecodePage * decodePage) + AddrDecodePage *decodePage) { DecodeCache::iterator iter = decodeCache.find(mach_inst); if (iter != decodeCache.end()) { -- cgit v1.2.3 From e0f425bb94a5b67c1128cc05c490dc78f0841290 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sun, 15 Feb 2009 20:39:12 -0800 Subject: traceflags: fix --trace-help --- src/python/m5/main.py | 13 ------------- src/python/m5/trace.py | 11 ++++++----- src/python/m5/util/__init__.py | 13 +++++++++++++ 3 files changed, 19 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 3edeccc10..09847c093 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -38,19 +38,6 @@ from options import OptionParser __all__ = [ 'options', 'arguments', 'main' ] -def print_list(items, indent=4): - line = ' ' * indent - for i,item in enumerate(items): - if len(line) + len(item) > 76: - print line - line = ' ' * indent - - if i < len(items) - 1: - line += '%s, ' % item - else: - line += item - print line - usage="%prog [m5 options] script.py [script options]" version="%prog 2.0" brief_copyright=''' diff --git a/src/python/m5/trace.py b/src/python/m5/trace.py index c97263c9b..14bab77a3 100644 --- a/src/python/m5/trace.py +++ b/src/python/m5/trace.py @@ -28,6 +28,7 @@ import internal import traceflags as flags +import util from internal.trace import clear, output, set, ignore @@ -36,13 +37,13 @@ def enable(): def help(): print "Base Flags:" - for flag in trace.flags.basic: - print " %s: %s" % (flag, trace.flags.descriptions[flag]) + for flag in flags.basic: + print " %s: %s" % (flag, flags.descriptions[flag]) print print "Compound Flags:" - for flag in trace.flags.compound: + for flag in flags.compound: if flag == 'All': continue - print " %s: %s" % (flag, trace.flags.descriptions[flag]) - print_list(trace.flags.compoundMap[flag], indent=8) + print " %s: %s" % (flag, flags.descriptions[flag]) + util.print_list(flags.compoundMap[flag], indent=8) print diff --git a/src/python/m5/util/__init__.py b/src/python/m5/util/__init__.py index f82de696a..5c4a066c6 100644 --- a/src/python/m5/util/__init__.py +++ b/src/python/m5/util/__init__.py @@ -30,3 +30,16 @@ from attrdict import attrdict, optiondict from misc import * from multidict import multidict import jobfile + +def print_list(items, indent=4): + line = ' ' * indent + for i,item in enumerate(items): + if len(line) + len(item) > 76: + print line + line = ' ' * indent + + if i < len(items) - 1: + line += '%s, ' % item + else: + line += item + print line -- cgit v1.2.3 From 6923282fb5a9ba6af14d19be094839eefe1c34be Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 15 Feb 2009 23:43:39 -0800 Subject: X86: Make the loader recognize 32 bit x86 processes. --- src/base/loader/elf_object.cc | 8 ++++---- src/base/loader/object_file.hh | 3 ++- src/sim/process.cc | 9 +++++++-- 3 files changed, 13 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/base/loader/elf_object.cc b/src/base/loader/elf_object.cc index edaf323c7..16fc698dd 100644 --- a/src/base/loader/elf_object.cc +++ b/src/base/loader/elf_object.cc @@ -89,10 +89,10 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data) } } else if (ehdr.e_machine == EM_X86_64 && ehdr.e_ident[EI_CLASS] == ELFCLASS64) { - //In the future, we might want to differentiate between 32 bit - //and 64 bit x86 processes in case there are differences in their - //initial stack frame. - arch = ObjectFile::X86; + arch = ObjectFile::X86_64; + } else if (ehdr.e_machine == EM_386 && + ehdr.e_ident[EI_CLASS] == ELFCLASS32) { + arch = ObjectFile::I386; } else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) { arch = ObjectFile::Alpha; } else if (ehdr.e_machine == EM_ARM) { diff --git a/src/base/loader/object_file.hh b/src/base/loader/object_file.hh index cc806ca81..d363cde84 100644 --- a/src/base/loader/object_file.hh +++ b/src/base/loader/object_file.hh @@ -50,7 +50,8 @@ class ObjectFile SPARC64, SPARC32, Mips, - X86, + X86_64, + I386, Arm }; diff --git a/src/sim/process.cc b/src/sim/process.cc index b335d0cf2..7383611c0 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -708,14 +708,19 @@ LiveProcess::create(LiveProcessParams * params) fatal("Unknown/unsupported operating system."); } #elif THE_ISA == X86_ISA - if (objFile->getArch() != ObjectFile::X86) + if (objFile->getArch() != ObjectFile::X86_64 && + objFile->getArch() != ObjectFile::I386) fatal("Object file architecture does not match compiled ISA (x86)."); switch (objFile->getOpSys()) { case ObjectFile::UnknownOpSys: warn("Unknown operating system; assuming Linux."); // fall through case ObjectFile::Linux: - process = new X86LinuxProcess(params, objFile); + if (objFile->getArch() == ObjectFile::X86_64) { + process = new X86LinuxProcess(params, objFile); + } else { + panic("32 bit x86 Linux process aren't implemented.\n"); + } break; default: -- cgit v1.2.3 From 89a7fb03934b3e38c7d8b2c4818794b3ec874fdf Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Mon, 16 Feb 2009 08:56:40 -0800 Subject: Fixes to get prefetching working again. Apparently we broke it with the cache rewrite and never noticed. Thanks to Bao Yungang for a significant part of these changes (and for inspiring me to work on the rest). Some other overdue cleanup on the prefetch code too. --- src/cpu/base.cc | 6 +- src/mem/cache/BaseCache.py | 12 ++- src/mem/cache/base.hh | 15 ++-- src/mem/cache/blk.hh | 2 +- src/mem/cache/builder.cc | 92 +++++------------------ src/mem/cache/cache.hh | 12 ++- src/mem/cache/cache_impl.hh | 91 ++++++++++++++++------- src/mem/cache/mshr.cc | 34 ++++++--- src/mem/cache/mshr.hh | 19 +++-- src/mem/cache/prefetch/base.cc | 156 ++++++++++++++++++++++----------------- src/mem/cache/prefetch/base.hh | 24 +++++- src/mem/cache/prefetch/ghb.cc | 35 ++++----- src/mem/cache/prefetch/ghb.hh | 6 +- src/mem/cache/prefetch/stride.cc | 119 ++++++++++++++++++----------- src/mem/cache/prefetch/stride.hh | 30 ++++---- src/mem/cache/prefetch/tagged.cc | 19 ++--- src/mem/config/prefetch.hh | 41 ---------- src/mem/request.hh | 6 ++ 18 files changed, 377 insertions(+), 342 deletions(-) delete mode 100644 src/mem/config/prefetch.hh (limited to 'src') diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 06fcebad8..0ef206d90 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -344,8 +344,12 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc) assert(newTC->threadId() == oldTC->threadId()); system->replaceThreadContext(newTC, newTC->contextId()); - if (DTRACE(Context)) + /* This code no longer works since the zero register (e.g., + * r31 on Alpha) doesn't necessarily contain zero at this + * point. + if (DTRACE(Context)) ThreadContext::compare(oldTC, newTC); + */ } #if FULL_SYSTEM diff --git a/src/mem/cache/BaseCache.py b/src/mem/cache/BaseCache.py index 936107b7f..bef1b45d2 100644 --- a/src/mem/cache/BaseCache.py +++ b/src/mem/cache/BaseCache.py @@ -52,12 +52,10 @@ class BaseCache(MemObject): two_queue = Param.Bool(False, "whether the lifo should have two queue replacement") write_buffers = Param.Int(8, "number of write buffers") - prefetch_miss = Param.Bool(False, - "wheter you are using the hardware prefetcher from Miss stream") - prefetch_access = Param.Bool(False, - "wheter you are using the hardware prefetcher from Access stream") + prefetch_on_access = Param.Bool(False, + "notify the hardware prefetcher on every access (not just misses)") prefetcher_size = Param.Int(100, - "Number of entries in the harware prefetch queue") + "Number of entries in the hardware prefetch queue") prefetch_past_page = Param.Bool(False, "Allow prefetches to cross virtual page boundaries") prefetch_serial_squash = Param.Bool(False, @@ -69,9 +67,9 @@ class BaseCache(MemObject): prefetch_policy = Param.Prefetch('none', "Type of prefetcher to use") prefetch_cache_check_push = Param.Bool(True, - "Check if in cash on push or pop of prefetch queue") + "Check if in cache on push or pop of prefetch queue") prefetch_use_cpu_id = Param.Bool(True, - "Use the CPU ID to seperate calculations of prefetches") + "Use the CPU ID to separate calculations of prefetches") prefetch_data_accesses_only = Param.Bool(False, "Only prefetch on data not on instruction accesses") cpu_side = Port("Port on side closer to CPU") diff --git a/src/mem/cache/base.hh b/src/mem/cache/base.hh index 601e9bd48..fe191fb1c 100644 --- a/src/mem/cache/base.hh +++ b/src/mem/cache/base.hh @@ -445,12 +445,6 @@ class BaseCache : public MemObject } } - Tick nextMSHRReadyTime() - { - return std::min(mshrQueue.nextMSHRReadyTime(), - writeBuffer.nextMSHRReadyTime()); - } - /** * Request the master bus for the given cause and time. * @param cause The reason for the request. @@ -467,10 +461,11 @@ class BaseCache : public MemObject */ void deassertMemSideBusRequest(RequestCause cause) { - // obsolete!! - assert(false); - // memSidePort->deassertBusRequest(cause); - // checkDrain(); + // Obsolete... we no longer signal bus requests explicitly so + // we can't deassert them. Leaving this in as a no-op since + // the prefetcher calls it to indicate that it no longer wants + // to request a prefetch, and someday that might be + // interesting again. } virtual unsigned int drain(Event *de); diff --git a/src/mem/cache/blk.hh b/src/mem/cache/blk.hh index bdf323d87..fe65672d6 100644 --- a/src/mem/cache/blk.hh +++ b/src/mem/cache/blk.hh @@ -205,7 +205,7 @@ class CacheBlk * be touched. * @return True if the block was a hardware prefetch, unaccesed. */ - bool isPrefetch() const + bool wasPrefetched() const { return (status & BlkHWPrefetched) != 0; } diff --git a/src/mem/cache/builder.cc b/src/mem/cache/builder.cc index 27daa4025..599353b88 100644 --- a/src/mem/cache/builder.cc +++ b/src/mem/cache/builder.cc @@ -38,7 +38,6 @@ // Must be included first to determine which caches we want #include "enums/Prefetch.hh" #include "mem/config/cache.hh" -#include "mem/config/prefetch.hh" #include "mem/cache/base.hh" #include "mem/cache/cache.hh" #include "mem/bus.hh" @@ -58,38 +57,32 @@ #endif //Prefetcher Headers -#if defined(USE_GHB) #include "mem/cache/prefetch/ghb.hh" -#endif -#if defined(USE_TAGGED) #include "mem/cache/prefetch/tagged.hh" -#endif -#if defined(USE_STRIDED) #include "mem/cache/prefetch/stride.hh" -#endif using namespace std; using namespace TheISA; -#define BUILD_CACHE(TAGS, tags) \ - do { \ - BasePrefetcher *pf; \ - if (prefetch_policy == Enums::tagged) { \ - BUILD_TAGGED_PREFETCHER(TAGS); \ - } \ - else if (prefetch_policy == Enums::stride) { \ - BUILD_STRIDED_PREFETCHER(TAGS); \ - } \ - else if (prefetch_policy == Enums::ghb) { \ - BUILD_GHB_PREFETCHER(TAGS); \ - } \ - else { \ - BUILD_NULL_PREFETCHER(TAGS); \ - } \ - Cache *retval = \ - new Cache(this, tags, pf); \ - return retval; \ +#define BUILD_CACHE(TAGS, tags) \ + do { \ + BasePrefetcher *pf; \ + if (prefetch_policy == Enums::tagged) { \ + pf = new TaggedPrefetcher(this); \ + } \ + else if (prefetch_policy == Enums::stride) { \ + pf = new StridePrefetcher(this); \ + } \ + else if (prefetch_policy == Enums::ghb) { \ + pf = new GHBPrefetcher(this); \ + } \ + else { \ + pf = NULL; \ + } \ + Cache *retval = \ + new Cache(this, tags, pf); \ + return retval; \ } while (0) #define BUILD_CACHE_PANIC(x) do { \ @@ -135,37 +128,6 @@ using namespace TheISA; } \ } while (0) -#define BUILD_COHERENCE(b) do { \ - } while (0) - -#if defined(USE_TAGGED) -#define BUILD_TAGGED_PREFETCHER(t) \ - pf = new TaggedPrefetcher(this) -#else -#define BUILD_TAGGED_PREFETCHER(t) BUILD_CACHE_PANIC("Tagged Prefetcher") -#endif - -#if defined(USE_STRIDED) -#define BUILD_STRIDED_PREFETCHER(t) \ - pf = new StridePrefetcher(this) -#else -#define BUILD_STRIDED_PREFETCHER(t) BUILD_CACHE_PANIC("Stride Prefetcher") -#endif - -#if defined(USE_GHB) -#define BUILD_GHB_PREFETCHER(t) \ - pf = new GHBPrefetcher(this) -#else -#define BUILD_GHB_PREFETCHER(t) BUILD_CACHE_PANIC("GHB Prefetcher") -#endif - -#if defined(USE_TAGGED) -#define BUILD_NULL_PREFETCHER(t) \ - pf = new TaggedPrefetcher(this) -#else -#define BUILD_NULL_PREFETCHER(t) BUILD_CACHE_PANIC("NULL Prefetcher (uses Tagged)") -#endif - BaseCache * BaseCacheParams::create() { @@ -174,24 +136,6 @@ BaseCacheParams::create() subblock_size = block_size; } - //Warnings about prefetcher policy - if (prefetch_policy == Enums::none) { - if (prefetch_miss || prefetch_access) - panic("With no prefetcher, you shouldn't prefetch from" - " either miss or access stream\n"); - } - - if (prefetch_policy == Enums::tagged || prefetch_policy == Enums::stride || - prefetch_policy == Enums::ghb) { - - if (!prefetch_miss && !prefetch_access) - warn("With this prefetcher you should chose a prefetch" - " stream (miss or access)\nNo Prefetching will occur\n"); - - if (prefetch_miss && prefetch_access) - panic("Can't do prefetches from both miss and access stream"); - } - #if defined(USE_CACHE_IIC) // Build IIC params IIC::Params iic_params; diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh index 4db5230f8..4570b067b 100644 --- a/src/mem/cache/cache.hh +++ b/src/mem/cache/cache.hh @@ -64,8 +64,6 @@ class Cache : public BaseCache /** A typedef for a list of BlkType pointers. */ typedef typename TagStore::BlkList BlkList; - bool prefetchAccess; - protected: class CpuSidePort : public CachePort @@ -141,7 +139,10 @@ class Cache : public BaseCache */ const bool doFastWrites; - const bool prefetchMiss; + /** + * Notify the prefetcher on every access, not just misses. + */ + const bool prefetchOnAccess; /** * Does all the processing necessary to perform the provided request. @@ -320,6 +321,11 @@ class Cache : public BaseCache bool inMissQueue(Addr addr) { return (mshrQueue.findMatch(addr) != 0); } + + /** + * Find next request ready time from among possible sources. + */ + Tick nextMSHRReadyTime(); }; #endif // __CACHE_HH__ diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index c4a19ad5c..618e00569 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -53,11 +53,10 @@ template Cache::Cache(const Params *p, TagStore *tags, BasePrefetcher *pf) : BaseCache(p), - prefetchAccess(p->prefetch_access), tags(tags), prefetcher(pf), doFastWrites(true), - prefetchMiss(p->prefetch_miss) + prefetchOnAccess(p->prefetch_on_access) { tempBlock = new BlkType(); tempBlock->data = new uint8_t[blkSize]; @@ -72,7 +71,8 @@ Cache::Cache(const Params *p, TagStore *tags, BasePrefetcher *pf) memSidePort->setOtherPort(cpuSidePort); tags->setCache(this); - prefetcher->setCache(this); + if (prefetcher) + prefetcher->setCache(this); } template @@ -81,7 +81,8 @@ Cache::regStats() { BaseCache::regStats(); tags->regStats(name()); - prefetcher->regStats(name()); + if (prefetcher) + prefetcher->regStats(name()); } template @@ -271,29 +272,11 @@ Cache::access(PacketPtr pkt, BlkType *&blk, blk = tags->accessBlock(pkt->getAddr(), lat); - if (prefetchAccess) { - //We are determining prefetches on access stream, call prefetcher - prefetcher->handleMiss(pkt, curTick); - } - DPRINTF(Cache, "%s %x %s\n", pkt->cmdString(), pkt->getAddr(), (blk) ? "hit" : "miss"); if (blk != NULL) { - if (blk->isPrefetch()) { - //Signal that this was a hit under prefetch (no need for - //use prefetch (only can get here if true) - DPRINTF(HWPrefetch, "Hit a block that was prefetched\n"); - blk->status &= ~BlkHWPrefetched; - if (prefetchMiss) { - //If we are using the miss stream, signal the - //prefetcher otherwise the access stream would have - //already signaled this hit - prefetcher->handleMiss(pkt, curTick); - } - } - if (pkt->needsExclusive() ? blk->isWritable() : blk->isReadable()) { // OK to satisfy access hits[pkt->cmdToIndex()][0/*pkt->req->threadId()*/]++; @@ -448,6 +431,9 @@ Cache::timingAccess(PacketPtr pkt) } #endif + // track time of availability of next prefetch, if any + Tick next_pf_time = 0; + bool needsResponse = pkt->needsResponse(); if (satisfied) { @@ -457,10 +443,14 @@ Cache::timingAccess(PacketPtr pkt) } else { delete pkt; } + + if (prefetcher && (prefetchOnAccess || (blk && blk->wasPrefetched()))) { + if (blk) + blk->status &= ~BlkHWPrefetched; + next_pf_time = prefetcher->notify(pkt, time); + } } else { // miss - if (prefetchMiss) - prefetcher->handleMiss(pkt, time); Addr blk_addr = pkt->getAddr() & ~(Addr(blkSize-1)); MSHR *mshr = mshrQueue.findMatch(blk_addr); @@ -512,9 +502,16 @@ Cache::timingAccess(PacketPtr pkt) allocateMissBuffer(pkt, time, true); } + + if (prefetcher) { + next_pf_time = prefetcher->notify(pkt, time); + } } } + if (next_pf_time != 0) + requestMemSideBus(Request_PF, std::max(time, next_pf_time)); + // copy writebacks to write buffer while (!writebacks.empty()) { PacketPtr wbPkt = writebacks.front(); @@ -663,6 +660,17 @@ Cache::atomicAccess(PacketPtr pkt) } } + // Note that we don't invoke the prefetcher at all in atomic mode. + // It's not clear how to do it properly, particularly for + // prefetchers that aggressively generate prefetch candidates and + // rely on bandwidth contention to throttle them; these will tend + // to pollute the cache in atomic mode since there is no bandwidth + // contention. If we ever do want to enable prefetching in atomic + // mode, though, this is the place to do it... see timingAccess() + // for an example (though we'd want to issue the prefetch(es) + // immediately rather than calling requestMemSideBus() as we do + // there). + // Handle writebacks if needed while (!writebacks.empty()){ PacketPtr wbPkt = writebacks.front(); @@ -787,7 +795,8 @@ Cache::handleResponse(PacketPtr pkt) while (mshr->hasTargets()) { MSHR::Target *target = mshr->getTarget(); - if (target->isCpuSide()) { + switch (target->source) { + case MSHR::Target::FromCPU: Tick completion_time; if (is_fill) { satisfyCpuSideRequest(target->pkt, blk); @@ -825,13 +834,27 @@ Cache::handleResponse(PacketPtr pkt) target->pkt->cmd = MemCmd::ReadRespWithInvalidate; } cpuSidePort->respond(target->pkt, completion_time); - } else { + break; + + case MSHR::Target::FromPrefetcher: + assert(target->pkt->cmd == MemCmd::HardPFReq); + if (blk) + blk->status |= BlkHWPrefetched; + delete target->pkt->req; + delete target->pkt; + break; + + case MSHR::Target::FromSnoop: // I don't believe that a snoop can be in an error state assert(!is_error); // response to snoop request DPRINTF(Cache, "processing deferred snoop...\n"); handleSnoop(target->pkt, blk, true, true, mshr->pendingInvalidate || pkt->isInvalidate()); + break; + + default: + panic("Illegal target->source enum %d\n", target->source); } mshr->popTarget(); @@ -1333,6 +1356,22 @@ Cache::getTimingPacket() } +template +Tick +Cache::nextMSHRReadyTime() +{ + Tick nextReady = std::min(mshrQueue.nextMSHRReadyTime(), + writeBuffer.nextMSHRReadyTime()); + + if (prefetcher) { + nextReady = std::min(nextReady, + prefetcher->nextPrefetchReadyTime()); + } + + return nextReady; +} + + /////////////// // // CpuSidePort diff --git a/src/mem/cache/mshr.cc b/src/mem/cache/mshr.cc index 04b2b8d77..9ec9c090c 100644 --- a/src/mem/cache/mshr.cc +++ b/src/mem/cache/mshr.cc @@ -64,9 +64,9 @@ MSHR::TargetList::TargetList() inline void MSHR::TargetList::add(PacketPtr pkt, Tick readyTime, - Counter order, bool cpuSide, bool markPending) + Counter order, Target::Source source, bool markPending) { - if (cpuSide) { + if (source != Target::FromSnoop) { if (pkt->needsExclusive()) { needsExclusive = true; } @@ -84,7 +84,7 @@ MSHR::TargetList::add(PacketPtr pkt, Tick readyTime, } } - push_back(Target(pkt, readyTime, order, cpuSide, markPending)); + push_back(Target(pkt, readyTime, order, source, markPending)); } @@ -141,7 +141,14 @@ print(std::ostream &os, int verbosity, const std::string &prefix) const { ConstIterator end_i = end(); for (ConstIterator i = begin(); i != end_i; ++i) { - ccprintf(os, "%s%s: ", prefix, i->isCpuSide() ? "cpu" : "mem"); + const char *s; + switch (i->source) { + case Target::FromCPU: s = "FromCPU"; + case Target::FromSnoop: s = "FromSnoop"; + case Target::FromPrefetcher: s = "FromPrefetcher"; + default: s = ""; + } + ccprintf(os, "%s%s: ", prefix, s); i->pkt->print(os, verbosity, ""); } } @@ -162,10 +169,12 @@ MSHR::allocate(Addr _addr, int _size, PacketPtr target, downstreamPending = false; threadNum = 0; ntargets = 1; - // Don't know of a case where we would allocate a new MSHR for a - // snoop (mem-side request), so set cpuSide to true here. assert(targets->isReset()); - targets->add(target, whenReady, _order, true, true); + // Don't know of a case where we would allocate a new MSHR for a + // snoop (mem-side request), so set source according to request here + Target::Source source = (target->cmd == MemCmd::HardPFReq) ? + Target::FromPrefetcher : Target::FromCPU; + targets->add(target, whenReady, _order, source, true); assert(deferredTargets->isReset()); pendingInvalidate = false; pendingShared = false; @@ -230,17 +239,22 @@ MSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order) // comes back (but before this target is processed) // - the outstanding request is for a non-exclusive block and this // target requires an exclusive block + + // assume we'd never issue a prefetch when we've got an + // outstanding miss + assert(pkt->cmd != MemCmd::HardPFReq); + if (inService && (!deferredTargets->empty() || pendingInvalidate || (!targets->needsExclusive && pkt->needsExclusive()))) { // need to put on deferred list - deferredTargets->add(pkt, whenReady, _order, true, true); + deferredTargets->add(pkt, whenReady, _order, Target::FromCPU, true); } else { // No request outstanding, or still OK to append to // outstanding request: append to regular target list. Only // mark pending if current request hasn't been issued yet // (isn't in service). - targets->add(pkt, whenReady, _order, true, !inService); + targets->add(pkt, whenReady, _order, Target::FromCPU, !inService); } ++ntargets; @@ -291,7 +305,7 @@ MSHR::handleSnoop(PacketPtr pkt, Counter _order) // actual target device (typ. PhysicalMemory) will delete the // packet on reception, so we need to save a copy here PacketPtr cp_pkt = new Packet(pkt, true); - targets->add(cp_pkt, curTick, _order, false, + targets->add(cp_pkt, curTick, _order, Target::FromSnoop, downstreamPending && targets->needsExclusive); ++ntargets; diff --git a/src/mem/cache/mshr.hh b/src/mem/cache/mshr.hh index 2ff1c2489..bed7012b0 100644 --- a/src/mem/cache/mshr.hh +++ b/src/mem/cache/mshr.hh @@ -55,20 +55,25 @@ class MSHR : public Packet::SenderState, public Printable class Target { public: + + enum Source { + FromCPU, + FromSnoop, + FromPrefetcher + }; + Tick recvTime; //!< Time when request was received (for stats) Tick readyTime; //!< Time when request is ready to be serviced Counter order; //!< Global order (for memory consistency mgmt) PacketPtr pkt; //!< Pending request packet. - bool cpuSide; //!< Did request come from cpu side or mem side? + Source source; //!< Did request come from cpu, memory, or prefetcher? bool markedPending; //!< Did we mark upstream MSHR //!< as downstreamPending? - bool isCpuSide() const { return cpuSide; } - Target(PacketPtr _pkt, Tick _readyTime, Counter _order, - bool _cpuSide, bool _markedPending) + Source _source, bool _markedPending) : recvTime(curTick), readyTime(_readyTime), order(_order), - pkt(_pkt), cpuSide(_cpuSide), markedPending(_markedPending) + pkt(_pkt), source(_source), markedPending(_markedPending) {} }; @@ -85,7 +90,7 @@ class MSHR : public Packet::SenderState, public Printable void resetFlags() { needsExclusive = hasUpgrade = false; } bool isReset() { return !needsExclusive && !hasUpgrade; } void add(PacketPtr pkt, Tick readyTime, Counter order, - bool cpuSide, bool markPending); + Target::Source source, bool markPending); void replaceUpgrades(); void clearDownstreamPending(); bool checkFunctional(PacketPtr pkt); @@ -238,7 +243,7 @@ public: if (getNumTargets() != 1) return false; Target *tgt = getTarget(); - return tgt->isCpuSide() && !tgt->pkt->needsResponse(); + return tgt->source == Target::FromCPU && !tgt->pkt->needsResponse(); } bool promoteDeferredTargets(); diff --git a/src/mem/cache/prefetch/base.cc b/src/mem/cache/prefetch/base.cc index a7e6cfdfc..365ce6727 100644 --- a/src/mem/cache/prefetch/base.cc +++ b/src/mem/cache/prefetch/base.cc @@ -33,6 +33,7 @@ * Hardware Prefetcher Definition. */ +#include "arch/isa_traits.hh" #include "base/trace.hh" #include "mem/cache/base.hh" #include "mem/cache/prefetch/base.hh" @@ -43,7 +44,7 @@ BasePrefetcher::BasePrefetcher(const BaseCacheParams *p) : size(p->prefetcher_size), pageStop(!p->prefetch_past_page), serialSquash(p->prefetch_serial_squash), cacheCheckPush(p->prefetch_cache_check_push), - only_data(p->prefetch_data_accesses_only) + onlyData(p->prefetch_data_accesses_only) { } @@ -52,6 +53,7 @@ BasePrefetcher::setCache(BaseCache *_cache) { cache = _cache; blkSize = cache->getBlockSize(); + _name = cache->name() + "-pf"; } void @@ -99,7 +101,8 @@ BasePrefetcher::regStats(const std::string &name) pfSquashed .name(name + ".prefetcher.num_hwpf_squashed_from_miss") - .desc("number of hwpf that got squashed due to a miss aborting calculation time") + .desc("number of hwpf that got squashed due to a miss " + "aborting calculation time") ; } @@ -126,60 +129,79 @@ BasePrefetcher::inMissQueue(Addr addr) PacketPtr BasePrefetcher::getPacket() { - DPRINTF(HWPrefetch, "%s:Requesting a hw_pf to issue\n", cache->name()); + DPRINTF(HWPrefetch, "Requesting a hw_pf to issue\n"); if (pf.empty()) { - DPRINTF(HWPrefetch, "%s:No HW_PF found\n", cache->name()); + DPRINTF(HWPrefetch, "No HW_PF found\n"); return NULL; } PacketPtr pkt; - bool keepTrying = false; + bool keep_trying = false; do { pkt = *pf.begin(); pf.pop_front(); if (!cacheCheckPush) { - keepTrying = cache->inCache(pkt->getAddr()); + keep_trying = cache->inCache(pkt->getAddr()); } + + if (keep_trying) { + DPRINTF(HWPrefetch, "addr 0x%x in cache, skipping\n", + pkt->getAddr()); + delete pkt->req; + delete pkt; + } + if (pf.empty()) { cache->deassertMemSideBusRequest(BaseCache::Request_PF); - if (keepTrying) return NULL; //None left, all were in cache + if (keep_trying) { + return NULL; // None left, all were in cache + } } - } while (keepTrying); + } while (keep_trying); pfIssued++; + assert(pkt != NULL); + DPRINTF(HWPrefetch, "returning 0x%x\n", pkt->getAddr()); return pkt; } -void -BasePrefetcher::handleMiss(PacketPtr &pkt, Tick time) + +Tick +BasePrefetcher::notify(PacketPtr &pkt, Tick time) { - if (!pkt->req->isUncacheable() && !(pkt->req->isInstRead() && only_data)) - { - //Calculate the blk address - Addr blkAddr = pkt->getAddr() & ~(Addr)(blkSize-1); + if (!pkt->req->isUncacheable() && !(pkt->req->isInstRead() && onlyData)) { + // Calculate the blk address + Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1); - //Check if miss is in pfq, if so remove it - std::list::iterator iter = inPrefetch(blkAddr); + // Check if miss is in pfq, if so remove it + std::list::iterator iter = inPrefetch(blk_addr); if (iter != pf.end()) { - DPRINTF(HWPrefetch, "%s:Saw a miss to a queued prefetch, removing it\n", cache->name()); + DPRINTF(HWPrefetch, "Saw a miss to a queued prefetch addr: " + "0x%x, removing it\n", blk_addr); pfRemovedMSHR++; + delete (*iter)->req; + delete (*iter); pf.erase(iter); if (pf.empty()) cache->deassertMemSideBusRequest(BaseCache::Request_PF); } - //Remove anything in queue with delay older than time - //since everything is inserted in time order, start from end - //and work until pf.empty() or time is earlier - //This is done to emulate Aborting the previous work on a new miss - //Needed for serial calculators like GHB + // Remove anything in queue with delay older than time + // since everything is inserted in time order, start from end + // and work until pf.empty() or time is earlier + // This is done to emulate Aborting the previous work on a new miss + // Needed for serial calculators like GHB if (serialSquash) { iter = pf.end(); iter--; while (!pf.empty() && ((*iter)->time >= time)) { pfSquashed++; - pf.pop_back(); + DPRINTF(HWPrefetch, "Squashing old prefetch addr: 0x%x\n", + (*iter)->getAddr()); + delete (*iter)->req; + delete (*iter); + pf.erase(iter); iter--; } if (pf.empty()) @@ -191,74 +213,70 @@ BasePrefetcher::handleMiss(PacketPtr &pkt, Tick time) std::list delays; calculatePrefetch(pkt, addresses, delays); - std::list::iterator addr = addresses.begin(); - std::list::iterator delay = delays.begin(); - while (addr != addresses.end()) - { - DPRINTF(HWPrefetch, "%s:Found a pf canidate, inserting into prefetch queue\n", cache->name()); - //temp calc this here... + std::list::iterator addrIter = addresses.begin(); + std::list::iterator delayIter = delays.begin(); + for (; addrIter != addresses.end(); ++addrIter, ++delayIter) { + Addr addr = *addrIter; + pfIdentified++; - //create a prefetch memreq - Request * prefetchReq = new Request(*addr, blkSize, 0); - PacketPtr prefetch; - prefetch = new Packet(prefetchReq, MemCmd::HardPFReq, -1); - prefetch->allocate(); - prefetch->req->setThreadContext(pkt->req->contextId(), - pkt->req->threadId()); - prefetch->time = time + (*delay); //@todo ADD LATENCY HERE - //... initialize + DPRINTF(HWPrefetch, "Found a pf candidate addr: 0x%x, " + "inserting into prefetch queue with delay %d time %d\n", + addr, *delayIter, time); - //Check if it is already in the cache - if (cacheCheckPush) { - if (cache->inCache(prefetch->getAddr())) { - addr++; - delay++; - continue; - } + // Check if it is already in the cache + if (cacheCheckPush && cache->inCache(addr)) { + DPRINTF(HWPrefetch, "Prefetch addr already in cache\n"); + continue; } - //Check if it is already in the miss_queue - if (cache->inMissQueue(prefetch->getAddr())) { - addr++; - delay++; + // Check if it is already in the miss_queue + if (cache->inMissQueue(addr)) { + DPRINTF(HWPrefetch, "Prefetch addr already in miss queue\n"); continue; } - //Check if it is already in the pf buffer - if (inPrefetch(prefetch->getAddr()) != pf.end()) { + // Check if it is already in the pf buffer + if (inPrefetch(addr) != pf.end()) { pfBufferHit++; - addr++; - delay++; + DPRINTF(HWPrefetch, "Prefetch addr already in pf buffer\n"); continue; } - //We just remove the head if we are full - if (pf.size() == size) - { - DPRINTF(HWPrefetch, "%s:Inserting into prefetch queue, it was full removing oldest\n", cache->name()); + // create a prefetch memreq + Request *prefetchReq = new Request(*addrIter, blkSize, 0); + PacketPtr prefetch = + new Packet(prefetchReq, MemCmd::HardPFReq, Packet::Broadcast); + prefetch->allocate(); + prefetch->req->setThreadContext(pkt->req->contextId(), + pkt->req->threadId()); + + prefetch->time = time + (*delayIter); // @todo ADD LATENCY HERE + + // We just remove the head if we are full + if (pf.size() == size) { pfRemovedFull++; + PacketPtr old_pkt = *pf.begin(); + DPRINTF(HWPrefetch, "Prefetch queue full, " + "removing oldest 0x%x\n", old_pkt->getAddr()); + delete old_pkt->req; + delete old_pkt; pf.pop_front(); } pf.push_back(prefetch); - - //Make sure to request the bus, with proper delay - cache->requestMemSideBus(BaseCache::Request_PF, prefetch->time); - - //Increment through the list - addr++; - delay++; } } + + return pf.empty() ? 0 : pf.front()->time; } std::list::iterator BasePrefetcher::inPrefetch(Addr address) { - //Guaranteed to only be one match, we always check before inserting + // Guaranteed to only be one match, we always check before inserting std::list::iterator iter; - for (iter=pf.begin(); iter != pf.end(); iter++) { + for (iter = pf.begin(); iter != pf.end(); iter++) { if (((*iter)->getAddr() & ~(Addr)(blkSize-1)) == address) { return iter; } @@ -266,4 +284,8 @@ BasePrefetcher::inPrefetch(Addr address) return pf.end(); } - +bool +BasePrefetcher::samePage(Addr a, Addr b) +{ + return roundDown(a, TheISA::VMPageSize) == roundDown(b, TheISA::VMPageSize); +} diff --git a/src/mem/cache/prefetch/base.hh b/src/mem/cache/prefetch/base.hh index 1515d8a93..92040e899 100644 --- a/src/mem/cache/prefetch/base.hh +++ b/src/mem/cache/prefetch/base.hh @@ -73,7 +73,9 @@ class BasePrefetcher bool cacheCheckPush; /** Do we prefetch on only data reads, or on inst reads as well. */ - bool only_data; + bool onlyData; + + std::string _name; public: @@ -90,13 +92,21 @@ class BasePrefetcher void regStats(const std::string &name); public: + BasePrefetcher(const BaseCacheParams *p); virtual ~BasePrefetcher() {} + const std::string name() const { return _name; } + void setCache(BaseCache *_cache); - void handleMiss(PacketPtr &pkt, Tick time); + /** + * Notify prefetcher of cache access (may be any access or just + * misses, depending on cache parameters.) + * @retval Time of next prefetch availability, or 0 if none. + */ + Tick notify(PacketPtr &pkt, Tick time); bool inCache(Addr addr); @@ -109,11 +119,21 @@ class BasePrefetcher return !pf.empty(); } + Tick nextPrefetchReadyTime() + { + return pf.empty() ? MaxTick : pf.front()->time; + } + virtual void calculatePrefetch(PacketPtr &pkt, std::list &addresses, std::list &delays) = 0; std::list::iterator inPrefetch(Addr address); + + /** + * Utility function: are addresses a and b on the same VM page? + */ + bool samePage(Addr a, Addr b); }; diff --git a/src/mem/cache/prefetch/ghb.cc b/src/mem/cache/prefetch/ghb.cc index c8b87e99d..c27165248 100644 --- a/src/mem/cache/prefetch/ghb.cc +++ b/src/mem/cache/prefetch/ghb.cc @@ -41,32 +41,25 @@ void GHBPrefetcher::calculatePrefetch(PacketPtr &pkt, std::list &addresses, std::list &delays) { - Addr blkAddr = pkt->getAddr() & ~(Addr)(this->blkSize-1); - int contextId = pkt->req->contextId(); - if (!useContextId) contextId = 0; + Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1); + int ctx_id = useContextId ? pkt->req->contextId() : 0; + assert(ctx_id < Max_Contexts); + int new_stride = blk_addr - lastMissAddr[ctx_id]; + int old_stride = lastMissAddr[ctx_id] - secondLastMissAddr[ctx_id]; - int new_stride = blkAddr - last_miss_addr[contextId]; - int old_stride = last_miss_addr[contextId] - - second_last_miss_addr[contextId]; - - second_last_miss_addr[contextId] = last_miss_addr[contextId]; - last_miss_addr[contextId] = blkAddr; + secondLastMissAddr[ctx_id] = lastMissAddr[ctx_id]; + lastMissAddr[ctx_id] = blk_addr; if (new_stride == old_stride) { - for (int d=1; d <= degree; d++) { - Addr newAddr = blkAddr + d * new_stride; - if (this->pageStop && - (blkAddr & ~(TheISA::VMPageSize - 1)) != - (newAddr & ~(TheISA::VMPageSize - 1))) - { - //Spanned the page, so now stop - this->pfSpanPage += degree - d + 1; + for (int d = 1; d <= degree; d++) { + Addr new_addr = blk_addr + d * new_stride; + if (pageStop && !samePage(blk_addr, new_addr)) { + // Spanned the page, so now stop + pfSpanPage += degree - d + 1; return; - } - else - { - addresses.push_back(newAddr); + } else { + addresses.push_back(new_addr); delays.push_back(latency); } } diff --git a/src/mem/cache/prefetch/ghb.hh b/src/mem/cache/prefetch/ghb.hh index 156a74afa..c85221a39 100644 --- a/src/mem/cache/prefetch/ghb.hh +++ b/src/mem/cache/prefetch/ghb.hh @@ -42,8 +42,10 @@ class GHBPrefetcher : public BasePrefetcher { protected: - Addr second_last_miss_addr[64/*MAX_CPUS*/]; - Addr last_miss_addr[64/*MAX_CPUS*/]; + static const int Max_Contexts = 64; + + Addr secondLastMissAddr[Max_Contexts]; + Addr lastMissAddr[Max_Contexts]; Tick latency; int degree; diff --git a/src/mem/cache/prefetch/stride.cc b/src/mem/cache/prefetch/stride.cc index ad5846daa..cfd2469fa 100644 --- a/src/mem/cache/prefetch/stride.cc +++ b/src/mem/cache/prefetch/stride.cc @@ -34,59 +34,92 @@ * Stride Prefetcher template instantiations. */ +#include "base/trace.hh" #include "mem/cache/prefetch/stride.hh" void StridePrefetcher::calculatePrefetch(PacketPtr &pkt, std::list &addresses, std::list &delays) { -// Addr blkAddr = pkt->paddr & ~(Addr)(this->blkSize-1); - int contextId = pkt->req->contextId(); - if (!useContextId) contextId = 0; + if (!pkt->req->hasPC()) { + DPRINTF(HWPrefetch, "ignoring request with no PC"); + return; + } - /* Scan Table for IAddr Match */ -/* std::list::iterator iter; - for (iter=table[contextId].begin(); - iter !=table[contextId].end(); - iter++) { - if ((*iter)->IAddr == pkt->pc) break; - } + Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1); + int ctx_id = useContextId ? pkt->req->contextId() : 0; + Addr pc = pkt->req->getPC(); + assert(ctx_id < Max_Contexts); + std::list &tab = table[ctx_id]; - if (iter != table[contextId].end()) { - //Hit in table + /* Scan Table for instAddr Match */ + std::list::iterator iter; + for (iter = tab.begin(); iter != tab.end(); iter++) { + if ((*iter)->instAddr == pc) + break; + } - int newStride = blkAddr - (*iter)->MAddr; - if (newStride == (*iter)->stride) { - (*iter)->confidence++; - } - else { - (*iter)->stride = newStride; - (*iter)->confidence--; - } + if (iter != tab.end()) { + // Hit in table - (*iter)->MAddr = blkAddr; + int new_stride = blk_addr - (*iter)->missAddr; + bool stride_match = (new_stride == (*iter)->stride); - for (int d=1; d <= degree; d++) { - Addr newAddr = blkAddr + d * newStride; - if (this->pageStop && - (blkAddr & ~(TheISA::VMPageSize - 1)) != - (newAddr & ~(TheISA::VMPageSize - 1))) - { - //Spanned the page, so now stop - this->pfSpanPage += degree - d + 1; - return; - } - else - { - addresses.push_back(newAddr); - delays.push_back(latency); - } - } - } - else { - //Miss in table - //Find lowest confidence and replace + if (stride_match && new_stride != 0) { + if ((*iter)->confidence < Max_Conf) + (*iter)->confidence++; + } else { + (*iter)->stride = new_stride; + if ((*iter)->confidence > Min_Conf) + (*iter)->confidence = 0; + } - } -*/ + DPRINTF(HWPrefetch, "hit: PC %x blk_addr %x stride %d (%s), conf %d\n", + pc, blk_addr, new_stride, stride_match ? "match" : "change", + (*iter)->confidence); + + (*iter)->missAddr = blk_addr; + + if ((*iter)->confidence <= 0) + return; + + for (int d = 1; d <= degree; d++) { + Addr new_addr = blk_addr + d * new_stride; + if (pageStop && !samePage(blk_addr, new_addr)) { + // Spanned the page, so now stop + pfSpanPage += degree - d + 1; + return; + } else { + DPRINTF(HWPrefetch, " queuing prefetch to %x @ %d\n", + new_addr, latency); + addresses.push_back(new_addr); + delays.push_back(latency); + } + } + } else { + // Miss in table + // Find lowest confidence and replace + + DPRINTF(HWPrefetch, "miss: PC %x blk_addr %x\n", pc, blk_addr); + + if (tab.size() >= 256) { //set default table size is 256 + std::list::iterator min_pos = tab.begin(); + int min_conf = (*min_pos)->confidence; + for (iter = min_pos, ++iter; iter != tab.end(); ++iter) { + if ((*iter)->confidence < min_conf){ + min_pos = iter; + min_conf = (*iter)->confidence; + } + } + DPRINTF(HWPrefetch, " replacing PC %x\n", (*min_pos)->instAddr); + tab.erase(min_pos); + } + + StrideEntry *new_entry = new StrideEntry; + new_entry->instAddr = pc; + new_entry->missAddr = blk_addr; + new_entry->stride = 0; + new_entry->confidence = 0; + tab.push_back(new_entry); + } } diff --git a/src/mem/cache/prefetch/stride.hh b/src/mem/cache/prefetch/stride.hh index 4738fd9bc..6ccd32b91 100644 --- a/src/mem/cache/prefetch/stride.hh +++ b/src/mem/cache/prefetch/stride.hh @@ -36,36 +36,36 @@ #ifndef __MEM_CACHE_PREFETCH_STRIDE_PREFETCHER_HH__ #define __MEM_CACHE_PREFETCH_STRIDE_PREFETCHER_HH__ +#include #include "mem/cache/prefetch/base.hh" class StridePrefetcher : public BasePrefetcher { protected: - class strideEntry + static const int Max_Contexts = 64; + + // These constants need to be changed with the type of the + // 'confidence' field below. + static const int Max_Conf = INT_MAX; + static const int Min_Conf = INT_MIN; + + class StrideEntry { public: - Addr IAddr; - Addr MAddr; + Addr instAddr; + Addr missAddr; int stride; - int64_t confidence; - -/* bool operator < (strideEntry a,strideEntry b) - { - if (a.confidence == b.confidence) { - return true; //?????? - } - else return a.confidence < b.confidence; - }*/ + int confidence; }; - Addr* lastMissAddr[64/*MAX_CPUS*/]; - std::list table[64/*MAX_CPUS*/]; + Addr *lastMissAddr[Max_Contexts]; + + std::list table[Max_Contexts]; Tick latency; int degree; bool useContextId; - public: StridePrefetcher(const BaseCacheParams *p) diff --git a/src/mem/cache/prefetch/tagged.cc b/src/mem/cache/prefetch/tagged.cc index 6afe1c6c2..a6c2403ba 100644 --- a/src/mem/cache/prefetch/tagged.cc +++ b/src/mem/cache/prefetch/tagged.cc @@ -47,20 +47,15 @@ TaggedPrefetcher:: calculatePrefetch(PacketPtr &pkt, std::list &addresses, std::list &delays) { - Addr blkAddr = pkt->getAddr() & ~(Addr)(this->blkSize-1); + Addr blkAddr = pkt->getAddr() & ~(Addr)(blkSize-1); - for (int d=1; d <= degree; d++) { - Addr newAddr = blkAddr + d*(this->blkSize); - if (this->pageStop && - (blkAddr & ~(TheISA::VMPageSize - 1)) != - (newAddr & ~(TheISA::VMPageSize - 1))) - { - //Spanned the page, so now stop - this->pfSpanPage += degree - d + 1; + for (int d = 1; d <= degree; d++) { + Addr newAddr = blkAddr + d*(blkSize); + if (pageStop && !samePage(blkAddr, newAddr)) { + // Spanned the page, so now stop + pfSpanPage += degree - d + 1; return; - } - else - { + } else { addresses.push_back(newAddr); delays.push_back(latency); } diff --git a/src/mem/config/prefetch.hh b/src/mem/config/prefetch.hh deleted file mode 100644 index d24db79da..000000000 --- a/src/mem/config/prefetch.hh +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Ron Dreslinski - */ - -/** - * @file - * Central location to configure which prefetch types we want to build - * into the simulator. In the future, this should probably be - * autogenerated by some sort of configuration script. - */ -#define USE_TAGGED 1 //Be sure not to turn this off, it is also used for no - //prefetching case unless you always want to use a - //different prefetcher -//#define USE_STRIDED 1 -//#define USE_GHB 1 diff --git a/src/mem/request.hh b/src/mem/request.hh index f60eb17fa..761405aa6 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -424,6 +424,12 @@ class Request : public FastAlloc } /** Accessor function for pc.*/ + bool + hasPC() const + { + return flags.isSet(VALID_PC); + } + Addr getPC() const { -- cgit v1.2.3 From 5d029ff11e88ba0ab89c88e500c5d0d2edaf744e Mon Sep 17 00:00:00 2001 From: Lisa Hsu Date: Mon, 16 Feb 2009 17:47:39 -0500 Subject: sycalls: implement mremap() and add DATA flag for getrlimit(). mremap has been tested on Alpha, compiles for the rest but not tested. I don't see why it wouldn't work though. --- src/arch/alpha/linux/process.cc | 2 +- src/arch/alpha/pagetable.hh | 7 +++++ src/arch/mips/linux/process.cc | 2 +- src/arch/mips/tlb.hh | 3 +++ src/arch/sparc/linux/syscalls.cc | 4 +-- src/arch/sparc/pagetable.hh | 6 +++++ src/arch/x86/linux/syscalls.cc | 2 +- src/arch/x86/pagetable.hh | 6 +++++ src/mem/page_table.cc | 38 +++++++++++++++++++++++++++ src/mem/page_table.hh | 2 ++ src/sim/syscall_emul.hh | 55 +++++++++++++++++++++++++++++++++++++++- 11 files changed, 121 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/linux/process.cc b/src/arch/alpha/linux/process.cc index 6684051af..605e40627 100644 --- a/src/arch/alpha/linux/process.cc +++ b/src/arch/alpha/linux/process.cc @@ -463,7 +463,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = { /* 338 */ SyscallDesc("afs_syscall", unimplementedFunc), /* 339 */ SyscallDesc("uname", unameFunc), /* 340 */ SyscallDesc("nanosleep", unimplementedFunc), - /* 341 */ SyscallDesc("mremap", unimplementedFunc), + /* 341 */ SyscallDesc("mremap", mremapFunc), /* 342 */ SyscallDesc("nfsservctl", unimplementedFunc), /* 343 */ SyscallDesc("setresuid", unimplementedFunc), /* 344 */ SyscallDesc("getresuid", unimplementedFunc), diff --git a/src/arch/alpha/pagetable.hh b/src/arch/alpha/pagetable.hh index 6cf11be56..59df93bef 100644 --- a/src/arch/alpha/pagetable.hh +++ b/src/arch/alpha/pagetable.hh @@ -123,6 +123,13 @@ struct TlbEntry TlbEntry() {} + void + updateVaddr(Addr new_vaddr) + { + VAddr vaddr(new_vaddr); + tag = vaddr.vpn(); + } + Addr pageStart() { diff --git a/src/arch/mips/linux/process.cc b/src/arch/mips/linux/process.cc index ce09e1628..9d9d33325 100644 --- a/src/arch/mips/linux/process.cc +++ b/src/arch/mips/linux/process.cc @@ -288,7 +288,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = { /* 164 */ SyscallDesc("sched_get_priority_min", unimplementedFunc), /* 165 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc), /* 166 */ SyscallDesc("nanosleep", unimplementedFunc), - /* 167 */ SyscallDesc("mremap", unimplementedFunc), + /* 167 */ SyscallDesc("mremap", mremapFunc), /* 168 */ SyscallDesc("accept", unimplementedFunc), /* 169 */ SyscallDesc("bind", unimplementedFunc), /* 170 */ SyscallDesc("connect", unimplementedFunc), diff --git a/src/arch/mips/tlb.hh b/src/arch/mips/tlb.hh index feb2509c5..4a8fc32ac 100644 --- a/src/arch/mips/tlb.hh +++ b/src/arch/mips/tlb.hh @@ -68,6 +68,9 @@ struct TlbEntry return _pageStart; } + void + updateVaddr(Addr new_vaddr) {} + void serialize(std::ostream &os) { SERIALIZE_SCALAR(_pageStart); diff --git a/src/arch/sparc/linux/syscalls.cc b/src/arch/sparc/linux/syscalls.cc index 2845f7bec..3e8c603cd 100644 --- a/src/arch/sparc/linux/syscalls.cc +++ b/src/arch/sparc/linux/syscalls.cc @@ -339,7 +339,7 @@ SyscallDesc SparcLinuxProcess::syscall32Descs[] = { /* 247 */ SyscallDesc("sched_get_priority_min", unimplementedFunc), //32 bit /* 248 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc), //32 bit /* 249 */ SyscallDesc("nanosleep", unimplementedFunc), - /* 250 */ SyscallDesc("mremap", unimplementedFunc), //32 bit + /* 250 */ SyscallDesc("mremap", mremapFunc), //32 bit /* 251 */ SyscallDesc("_sysctl", unimplementedFunc), //32 bit /* 252 */ SyscallDesc("getsid", unimplementedFunc), //32 bit /* 253 */ SyscallDesc("fdatasync", unimplementedFunc), @@ -642,7 +642,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = { /* 247 */ SyscallDesc("sched_get_priority_min", unimplementedFunc), /* 248 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc), /* 249 */ SyscallDesc("nanosleep", unimplementedFunc), - /* 250 */ SyscallDesc("mremap", unimplementedFunc), + /* 250 */ SyscallDesc("mremap", mremapFunc), /* 251 */ SyscallDesc("_sysctl", unimplementedFunc), /* 252 */ SyscallDesc("getsid", unimplementedFunc), /* 253 */ SyscallDesc("fdatasync", unimplementedFunc), diff --git a/src/arch/sparc/pagetable.hh b/src/arch/sparc/pagetable.hh index ee4ca0c2c..cbdabe4c3 100644 --- a/src/arch/sparc/pagetable.hh +++ b/src/arch/sparc/pagetable.hh @@ -266,6 +266,12 @@ struct TlbEntry return pte.paddr(); } + void + updateVaddr(Addr new_vaddr) + { + range.va = new_vaddr; + } + void serialize(std::ostream &os); void unserialize(Checkpoint *cp, const std::string §ion); }; diff --git a/src/arch/x86/linux/syscalls.cc b/src/arch/x86/linux/syscalls.cc index 754fb2eaf..ca35a5dd6 100644 --- a/src/arch/x86/linux/syscalls.cc +++ b/src/arch/x86/linux/syscalls.cc @@ -148,7 +148,7 @@ SyscallDesc X86LinuxProcess::syscallDescs[] = { /* 22 */ SyscallDesc("pipe", unimplementedFunc), /* 23 */ SyscallDesc("select", unimplementedFunc), /* 24 */ SyscallDesc("sched_yield", unimplementedFunc), - /* 25 */ SyscallDesc("mremap", unimplementedFunc), + /* 25 */ SyscallDesc("mremap", mremapFunc), /* 26 */ SyscallDesc("msync", unimplementedFunc), /* 27 */ SyscallDesc("mincore", unimplementedFunc), /* 28 */ SyscallDesc("madvise", unimplementedFunc), diff --git a/src/arch/x86/pagetable.hh b/src/arch/x86/pagetable.hh index e42693c03..1a7a945e4 100644 --- a/src/arch/x86/pagetable.hh +++ b/src/arch/x86/pagetable.hh @@ -113,6 +113,12 @@ namespace X86ISA TlbEntry(Addr asn, Addr _vaddr, Addr _paddr); TlbEntry() {} + void + updateVaddr(Addr new_vaddr) + { + vaddr = new_vaddr; + } + Addr pageStart() { return paddr; diff --git a/src/mem/page_table.cc b/src/mem/page_table.cc index 54165f293..bdcbbfec3 100644 --- a/src/mem/page_table.cc +++ b/src/mem/page_table.cc @@ -87,6 +87,44 @@ PageTable::allocate(Addr vaddr, int64_t size) } } +void +PageTable::remap(Addr vaddr, int64_t size, Addr new_vaddr) +{ + assert(pageOffset(vaddr) == 0); + assert(pageOffset(new_vaddr) == 0); + + DPRINTF(MMU, "moving pages from vaddr %08p to %08p, size = %d\n", vaddr, + new_vaddr, size); + + for (; size > 0; size -= pageSize, vaddr += pageSize, new_vaddr += pageSize) { + PTableItr iter = pTable.find(vaddr); + + assert(iter != pTable.end()); + + pTable[new_vaddr] = pTable[vaddr]; + pTable.erase(vaddr); + pTable[new_vaddr].updateVaddr(new_vaddr); + updateCache(new_vaddr, pTable[new_vaddr]); + } +} + +void +PageTable::deallocate(Addr vaddr, int64_t size) +{ + assert(pageOffset(vaddr) == 0); + + DPRINTF(MMU, "Deallocating page: %#x-%#x\n", vaddr, vaddr+ size); + + for (; size > 0; size -= pageSize, vaddr += pageSize) { + PTableItr iter = pTable.find(vaddr); + + assert(iter != pTable.end()); + + pTable.erase(vaddr); + } + +} + bool PageTable::lookup(Addr vaddr, TheISA::TlbEntry &entry) { diff --git a/src/mem/page_table.hh b/src/mem/page_table.hh index 6ff0be082..d4101c6bf 100644 --- a/src/mem/page_table.hh +++ b/src/mem/page_table.hh @@ -80,6 +80,8 @@ class PageTable Addr pageOffset(Addr a) { return (a & offsetMask); } void allocate(Addr vaddr, int64_t size); + void remap(Addr vaddr, int64_t size, Addr new_vaddr); + void deallocate(Addr vaddr, int64_t size); /** * Lookup function diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index c334c1e26..0e34a835e 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -607,6 +607,51 @@ fchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, return 0; } +/// Target mremap() handler. +template +SyscallReturn +mremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) +{ + Addr start = tc->getSyscallArg(0); + uint64_t old_length = tc->getSyscallArg(1); + uint64_t new_length = tc->getSyscallArg(2); + uint64_t flags = tc->getSyscallArg(3); + + if ((start % TheISA::VMPageSize != 0) || + (new_length % TheISA::VMPageSize != 0)) { + warn("mremap failing: arguments not page aligned"); + return -EINVAL; + } + + if (new_length > old_length) { + if ((start + old_length) == process->mmap_end) { + uint64_t diff = new_length - old_length; + process->pTable->allocate(process->mmap_end, diff); + process->mmap_end += diff; + return start; + } else { + // sys/mman.h defined MREMAP_MAYMOVE + if (!(flags & 1)) { + warn("can't remap here and MREMAP_MAYMOVE flag not set\n"); + return -ENOMEM; + } else { + process->pTable->remap(start, old_length, process->mmap_end); + warn("mremapping to totally new vaddr %08p-%08p, adding %d\n", + process->mmap_end, process->mmap_end + new_length, new_length); + start = process->mmap_end; + // add on the remaining unallocated pages + process->pTable->allocate(start + old_length, new_length - old_length); + process->mmap_end += new_length; + warn("returning %08p as start\n", start); + return start; + } + } + } else { + process->pTable->deallocate(start + new_length, old_length - + new_length); + return start; + } +} /// Target stat() handler. template @@ -892,6 +937,7 @@ mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) // int fd = p->sim_fd(tc->getSyscallArg(4)); // int offset = tc->getSyscallArg(5); + if ((start % TheISA::VMPageSize) != 0 || (length % TheISA::VMPageSize) != 0) { warn("mmap failing: arguments not page-aligned: " @@ -929,12 +975,19 @@ getrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, switch (resource) { case OS::TGT_RLIMIT_STACK: - // max stack size in bytes: make up a number (2MB for now) + // max stack size in bytes: make up a number (8MB for now) rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; rlp->rlim_cur = htog(rlp->rlim_cur); rlp->rlim_max = htog(rlp->rlim_max); break; + case OS::TGT_RLIMIT_DATA: + // max data segment size in bytes: make up a number + rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024; + rlp->rlim_cur = htog(rlp->rlim_cur); + rlp->rlim_max = htog(rlp->rlim_max); + break; + default: std::cerr << "getrlimitFunc: unimplemented resource " << resource << std::endl; -- cgit v1.2.3 From 6cfff91d43885f60cbe30a7b237c69fcc85e31a2 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Tue, 17 Feb 2009 19:24:46 -0800 Subject: Make etherdump timestamps zero-based. We previously used the actual wall time for the base timestamps, making etherdumps non-deterministic. This fixes that problem and gets rid of the "malformed packet" at the front that we needed to provide the right base timestamp to wireshark/tcpdump. --- src/dev/etherdump.cc | 17 ++--------------- src/dev/etherdump.hh | 2 -- 2 files changed, 2 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/dev/etherdump.cc b/src/dev/etherdump.cc index 57da8a7f0..c41ce4e1f 100644 --- a/src/dev/etherdump.cc +++ b/src/dev/etherdump.cc @@ -75,31 +75,18 @@ struct pcap_pkthdr { void EtherDump::init() { - curtime = time(NULL); struct pcap_file_header hdr; hdr.magic = TCPDUMP_MAGIC; hdr.version_major = PCAP_VERSION_MAJOR; hdr.version_minor = PCAP_VERSION_MINOR; - hdr.thiszone = -5 * 3600; + hdr.thiszone = 0; hdr.snaplen = 1500; hdr.sigfigs = 0; hdr.linktype = DLT_EN10MB; stream->write(reinterpret_cast(&hdr), sizeof(hdr)); - /* - * output an empty packet with the current time so that we know - * when the simulation began. This allows us to correlate packets - * to sim_cycles. - */ - pcap_pkthdr pkthdr; - pkthdr.seconds = curtime; - pkthdr.microseconds = 0; - pkthdr.caplen = 0; - pkthdr.len = 0; - stream->write(reinterpret_cast(&pkthdr), sizeof(pkthdr)); - stream->flush(); } @@ -107,7 +94,7 @@ void EtherDump::dumpPacket(EthPacketPtr &packet) { pcap_pkthdr pkthdr; - pkthdr.seconds = curtime + (curTick / Clock::Int::s); + pkthdr.seconds = curTick / Clock::Int::s; pkthdr.microseconds = (curTick / Clock::Int::us) % ULL(1000000); pkthdr.caplen = std::min(packet->length, maxlen); pkthdr.len = packet->length; diff --git a/src/dev/etherdump.hh b/src/dev/etherdump.hh index 733e61c97..18a5d2c44 100644 --- a/src/dev/etherdump.hh +++ b/src/dev/etherdump.hh @@ -51,8 +51,6 @@ class EtherDump : public SimObject void dumpPacket(EthPacketPtr &packet); void init(); - Tick curtime; - public: typedef EtherDumpParams Params; EtherDump(const Params *p); -- cgit v1.2.3 From c41c9cf3a68bbda47b2304daeb145555dd63e5d3 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Wed, 18 Feb 2009 10:00:15 -0800 Subject: events: Make trace events happen at the right priority. Also, while we're at it, remember that priorities are in the Event class and add a disable method to disable tracing. --- src/python/m5/event.py | 7 +++++-- src/python/m5/main.py | 2 +- src/python/m5/trace.py | 3 +++ 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/python/m5/event.py b/src/python/m5/event.py index ce003defb..35095599d 100644 --- a/src/python/m5/event.py +++ b/src/python/m5/event.py @@ -35,13 +35,16 @@ mainq = internal.event.cvar.mainEventQueue def create(obj, priority=None): if priority is None: - priority = internal.event.Event.Default_Pri + priority = Event.Default_Pri return PythonEvent(obj, priority) + +# As a reminder, priorities found in sim/eventq.hh are stuck into the +# Event class by swig class Event(PythonEvent): def __init__(self, priority=None): if priority is None: - priority = internal.event.Event.Default_Pri + priority = Event.Default_Pri super(Event, self).__init__(self, priority) class ProgressEvent(Event): diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 09847c093..f562835da 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -312,7 +312,7 @@ def main(): if options.trace_start: check_tracing() - e = event.create(trace.enable) + e = event.create(trace.enable, Event.Trace_Enable_Pri) event.mainq.schedule(e, options.trace_start) else: trace.enable() diff --git a/src/python/m5/trace.py b/src/python/m5/trace.py index 14bab77a3..17aa6196c 100644 --- a/src/python/m5/trace.py +++ b/src/python/m5/trace.py @@ -32,6 +32,9 @@ import util from internal.trace import clear, output, set, ignore +def disable(): + internal.trace.cvar.enabled = False + def enable(): internal.trace.cvar.enabled = True -- cgit v1.2.3 From 6c5afe6346b31edf6af245002c270a3c26618833 Mon Sep 17 00:00:00 2001 From: Korey Sewell Date: Fri, 20 Feb 2009 11:02:48 -0500 Subject: Remove unnecessary building of FreeList/RenameMap in InOrder. Clean-up comments and O3 extensions InOrder Thread Context --- src/arch/mips/regfile.cc | 6 --- src/cpu/inorder/SConscript | 5 +-- src/cpu/inorder/cpu.hh | 9 ---- src/cpu/inorder/thread_context.cc | 93 +-------------------------------------- src/cpu/inorder/thread_context.hh | 2 +- 5 files changed, 4 insertions(+), 111 deletions(-) (limited to 'src') diff --git a/src/arch/mips/regfile.cc b/src/arch/mips/regfile.cc index e05bfe2df..663115bb6 100644 --- a/src/arch/mips/regfile.cc +++ b/src/arch/mips/regfile.cc @@ -199,12 +199,6 @@ MipsISA::copyRegs(ThreadContext *src, ThreadContext *dest) panic("Copy Regs Not Implemented Yet\n"); } -void -MipsISA::copyRegs(ThreadContext *src, ThreadContext *dest); -{ - panic("Copy Regs Not Implemented Yet\n"); -} - void MipsISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest) { diff --git a/src/cpu/inorder/SConscript b/src/cpu/inorder/SConscript index c7edd1d76..dc5ff6f46 100644 --- a/src/cpu/inorder/SConscript +++ b/src/cpu/inorder/SConscript @@ -42,13 +42,12 @@ if 'InOrderCPU' in env['CPU_MODELS']: TraceFlag('InOrderCPU') TraceFlag('InOrderMDU') TraceFlag('RegDepMap') - TraceFlag('Rename') TraceFlag('InOrderDynInst') TraceFlag('Resource') TraceFlag('RefCount') CompoundFlag('InOrderCPUAll', [ 'InOrderStage', 'InOrderStall', 'InOrderCPU', - 'InOrderMDU', 'RegDepMap', 'Resource', 'Rename']) + 'InOrderMDU', 'RegDepMap', 'Resource']) Source('pipeline_traits.cc') Source('inorder_dyn_inst.cc') @@ -74,8 +73,6 @@ if 'InOrderCPU' in env['CPU_MODELS']: Source('../o3/btb.cc') Source('../o3/tournament_pred.cc') Source('../o3/2bit_local_pred.cc') - Source('../o3/free_list.cc') - Source('../o3/rename_map.cc') Source('../o3/ras.cc') Source('thread_context.cc') Source('cpu.cc') diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh index 34eabbad4..6c1cdc9dc 100644 --- a/src/cpu/inorder/cpu.hh +++ b/src/cpu/inorder/cpu.hh @@ -77,7 +77,6 @@ class InOrderCPU : public BaseCPU typedef TheISA::FloatRegBits FloatRegBits; typedef TheISA::MiscReg MiscReg; typedef TheISA::RegFile RegFile; - typedef SimpleRenameMap RenameMap; //DynInstPtr TypeDefs typedef ThePipeline::DynInstPtr DynInstPtr; @@ -586,14 +585,6 @@ class InOrderCPU : public BaseCPU std::list fetchPriorityList; - /** Rename Map for architectural-to-physical register mappings. - * In a In-order processor, the mapping is fixed - * (e.g. Thread 1: 0-31, Thread 1: 32-63, etc.) - * In a Out-of-Order processor, this is used to maintain - * sequential consistency (?right word here?). - */ - RenameMap renameMap[ThePipeline::MaxThreads]; - protected: /** Active Threads List */ std::list activeThreads; diff --git a/src/cpu/inorder/thread_context.cc b/src/cpu/inorder/thread_context.cc index 5e2c789cb..2470ee676 100644 --- a/src/cpu/inorder/thread_context.cc +++ b/src/cpu/inorder/thread_context.cc @@ -44,7 +44,6 @@ InOrderThreadContext::takeOverFrom(ThreadContext *old_context) // copy over functional state setStatus(old_context->status()); copyArchRegs(old_context); - //setCpuId(0/*old_context->readCpuId()*/); thread->funcExeInst = old_context->readFuncExeInst(); old_context->setStatus(ThreadContext::Unallocated); @@ -61,18 +60,8 @@ InOrderThreadContext::activate(int delay) if (thread->status() == ThreadContext::Active) return; - // @TODO: Make this process useful again... - //if (thread->status() == ThreadContext::Unallocated) { - // Allows the CPU to drain partitioned resources - // before inserting thread into the CPU - // (e.g. bind physical registers) - //cpu->activateWhenReady(thread->readTid()); - //return; - //} - thread->setStatus(ThreadContext::Active); - // status() == Suspended cpu->activateContext(thread->readTid(), delay); } @@ -157,37 +146,9 @@ InOrderThreadContext:: getInst() void -InOrderThreadContext::copyArchRegs(ThreadContext *tc) +InOrderThreadContext::copyArchRegs(ThreadContext *src_tc) { - unsigned tid = thread->readTid(); - PhysRegIndex renamed_reg; - - // First loop through the integer registers. - for (int i = 0; i < TheISA::NumIntRegs; ++i) { - renamed_reg = cpu->renameMap[tid].lookup(i); - - DPRINTF(InOrderCPU, "Copying over register %i, had data %lli, " - "now has data %lli.\n", - renamed_reg, cpu->readIntReg(renamed_reg, tid), - tc->readIntReg(i)); - - cpu->setIntReg(renamed_reg, tc->readIntReg(i), tid); - } - - // Then loop through the floating point registers. - for (int i = 0; i < TheISA::NumFloatRegs; ++i) { - renamed_reg = cpu->renameMap[tid].lookup(i + TheISA::FP_Base_DepTag); - cpu->setFloatRegBits(renamed_reg, tc->readFloatRegBits(i), tid); - } - - // Copy the misc regs. - TheISA::copyMiscRegs(tc, this); - - // Then finally set the PC and the next PC. - cpu->setPC(tc->readPC(), tid); - cpu->setNextPC(tc->readNextPC(), tid); - cpu->setNextNPC(tc->readNextNPC(), tid); - this->thread->funcExeInst = tc->readFuncExeInst(); + TheISA::copyRegs(src_tc, this); } @@ -236,33 +197,18 @@ void InOrderThreadContext::setIntReg(int reg_idx, uint64_t val) { cpu->setIntReg(reg_idx, val, thread->readTid()); - - // Squash if we're not already in a state update mode. - //if (!thread->trapPending && !thread->inSyscall) { - // cpu->squashFromTC(thread->readTid()); - //} } void InOrderThreadContext::setFloatReg(int reg_idx, FloatReg val, int width) { cpu->setFloatReg(reg_idx, val, thread->readTid(), width); - - // Squash if we're not already in a state update mode. - //if (!thread->trapPending && !thread->inSyscall) { - //cpu->squashFromTC(thread->readTid()); - //} } void InOrderThreadContext::setFloatReg(int reg_idx, FloatReg val) { cpu->setFloatReg(reg_idx, val, thread->readTid()); - - // Squash if we're not already in a state update mode. - //if (!thread->trapPending && !thread->inSyscall) { - //cpu->squashFromTC(thread->readTid()); - //} } void @@ -270,22 +216,12 @@ InOrderThreadContext::setFloatRegBits(int reg_idx, FloatRegBits val, int width) { cpu->setFloatRegBits(reg_idx, val, thread->readTid(), width); - - // Squash if we're not already in a state update mode. - //if (!thread->trapPending && !thread->inSyscall) { - //cpu->squashFromTC(thread->readTid()); - //} } void InOrderThreadContext::setFloatRegBits(int reg_idx, FloatRegBits val) { cpu->setFloatRegBits(reg_idx, val, thread->readTid()); - - // Squash if we're not already in a state update mode. - //if (!thread->trapPending && !thread->inSyscall) { - //cpu->squashFromTC(thread->readTid()); - //} } void @@ -299,11 +235,6 @@ InOrderThreadContext::setPC(uint64_t val) { DPRINTF(InOrderCPU, "Setting PC to %08p\n", val); cpu->setPC(val, thread->readTid()); - - // Squash if we're not already in a state update mode. - //if (!thread->trapPending && !thread->inSyscall) { - //cpu->squashFromTC(thread->readTid()); - //} } void @@ -311,11 +242,6 @@ InOrderThreadContext::setNextPC(uint64_t val) { DPRINTF(InOrderCPU, "Setting NPC to %08p\n", val); cpu->setNextPC(val, thread->readTid()); - - // Squash if we're not already in a state update mode. - //if (!thread->trapPending && !thread->inSyscall) { - //cpu->squashFromTC(thread->readTid()); - //} } void @@ -323,33 +249,18 @@ InOrderThreadContext::setNextNPC(uint64_t val) { DPRINTF(InOrderCPU, "Setting NNPC to %08p\n", val); cpu->setNextNPC(val, thread->readTid()); - - // Squash if we're not already in a state update mode. - //if (!thread->trapPending && !thread->inSyscall) { - //cpu->squashFromTC(thread->readTid()); - //} } void InOrderThreadContext::setMiscRegNoEffect(int misc_reg, const MiscReg &val) { cpu->setMiscRegNoEffect(misc_reg, val, thread->readTid()); - - // Squash if we're not already in a state update mode. - //if (!thread->trapPending && !thread->inSyscall) { - //cpu->squashFromTC(thread->readTid()); - //} } void InOrderThreadContext::setMiscReg(int misc_reg, const MiscReg &val) { cpu->setMiscReg(misc_reg, val, thread->readTid()); - - // Squash if we're not already in a state update mode. - //if (!thread->trapPending && !thread->inSyscall) { - //cpu->squashFromTC(thread->readTid()); - //} } TheISA::IntReg diff --git a/src/cpu/inorder/thread_context.hh b/src/cpu/inorder/thread_context.hh index 919d5d2b6..708dcf6b3 100644 --- a/src/cpu/inorder/thread_context.hh +++ b/src/cpu/inorder/thread_context.hh @@ -147,7 +147,7 @@ class InOrderThreadContext : public ThreadContext virtual TheISA::MachInst getInst(); /** Copies the architectural registers from another TC into this TC. */ - virtual void copyArchRegs(ThreadContext *tc); + virtual void copyArchRegs(ThreadContext *src_tc); /** Resets all architectural registers to 0. */ virtual void clearArchRegs(); -- cgit v1.2.3 From e8c1c3e72eb01409f7ec110eee3b32c07347bf6f Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Mon, 23 Feb 2009 00:20:34 -0800 Subject: X86: Pass whether an access was a read/write/fetch so faults can behave accordingly. --- src/arch/x86/faults.cc | 4 ++-- src/arch/x86/faults.hh | 12 ++++++++---- src/arch/x86/pagetable_walker.cc | 4 +++- src/arch/x86/pagetable_walker.hh | 5 ++++- src/arch/x86/tlb.cc | 6 +++--- src/arch/x86/tlb.hh | 2 +- 6 files changed, 21 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/arch/x86/faults.cc b/src/arch/x86/faults.cc index 1234e68e5..f01197f36 100644 --- a/src/arch/x86/faults.cc +++ b/src/arch/x86/faults.cc @@ -166,13 +166,13 @@ namespace X86ISA void FakeITLBFault::invoke(ThreadContext * tc) { // Start the page table walker. - tc->getITBPtr()->walk(tc, vaddr); + tc->getITBPtr()->walk(tc, vaddr, write, execute); } void FakeDTLBFault::invoke(ThreadContext * tc) { // Start the page table walker. - tc->getDTBPtr()->walk(tc, vaddr); + tc->getDTBPtr()->walk(tc, vaddr, write, execute); } #else // !FULL_SYSTEM diff --git a/src/arch/x86/faults.hh b/src/arch/x86/faults.hh index 6a6dfc80a..ae4314434 100644 --- a/src/arch/x86/faults.hh +++ b/src/arch/x86/faults.hh @@ -429,10 +429,12 @@ namespace X86ISA { protected: Addr vaddr; + bool write; + bool execute; public: - FakeITLBFault(Addr _vaddr) : + FakeITLBFault(Addr _vaddr, bool _write, bool _execute) : X86Fault("fake instruction tlb fault", "itlb", 0), - vaddr(_vaddr) + vaddr(_vaddr), write(_write), execute(_execute) {} void invoke(ThreadContext * tc); @@ -442,10 +444,12 @@ namespace X86ISA { protected: Addr vaddr; + bool write; + bool execute; public: - FakeDTLBFault(Addr _vaddr) : + FakeDTLBFault(Addr _vaddr, bool _write, bool _execute) : X86Fault("fake data tlb fault", "dtlb", 0), - vaddr(_vaddr) + vaddr(_vaddr), write(_write), execute(_execute) {} void invoke(ThreadContext * tc); diff --git a/src/arch/x86/pagetable_walker.cc b/src/arch/x86/pagetable_walker.cc index 564a04b38..b0b9209b5 100644 --- a/src/arch/x86/pagetable_walker.cc +++ b/src/arch/x86/pagetable_walker.cc @@ -319,11 +319,13 @@ Walker::doNext(PacketPtr &read, PacketPtr &write) } void -Walker::start(ThreadContext * _tc, Addr vaddr) +Walker::start(ThreadContext * _tc, Addr vaddr, bool _write, bool _execute) { assert(state == Ready); assert(!tc); tc = _tc; + execute = _execute; + write = _write; VAddr addr = vaddr; diff --git a/src/arch/x86/pagetable_walker.hh b/src/arch/x86/pagetable_walker.hh index 324f16f3c..de3f21195 100644 --- a/src/arch/x86/pagetable_walker.hh +++ b/src/arch/x86/pagetable_walker.hh @@ -95,7 +95,7 @@ namespace X86ISA void doNext(PacketPtr &read, PacketPtr &write); // Kick off the state machine. - void start(ThreadContext * _tc, Addr vaddr); + void start(ThreadContext * _tc, Addr vaddr, bool write, bool execute); protected: @@ -165,7 +165,10 @@ namespace X86ISA State nextState; int size; bool enableNX; + bool write, execute; TlbEntry entry; + + Fault pageFault(bool present); public: diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index 1009386d7..34829848c 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -140,9 +140,9 @@ TLB::lookup(Addr va, bool update_lru) #if FULL_SYSTEM void -TLB::walk(ThreadContext * _tc, Addr vaddr) +TLB::walk(ThreadContext * _tc, Addr vaddr, bool write, bool execute) { - walker->start(_tc, vaddr); + walker->start(_tc, vaddr, write, execute); } #endif @@ -616,7 +616,7 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) // The vaddr already has the segment base applied. TlbEntry *entry = lookup(vaddr); if (!entry) { - return new TlbFault(vaddr); + return new TlbFault(vaddr, write, execute); } else { // Do paging protection checks. DPRINTF(TLB, "Entry found with paddr %#x, doing protection checks.\n", entry->paddr); diff --git a/src/arch/x86/tlb.hh b/src/arch/x86/tlb.hh index 89b965e97..56d635a90 100644 --- a/src/arch/x86/tlb.hh +++ b/src/arch/x86/tlb.hh @@ -119,7 +119,7 @@ namespace X86ISA Walker * walker; - void walk(ThreadContext * _tc, Addr vaddr); + void walk(ThreadContext * _tc, Addr vaddr, bool write, bool execute); #endif public: -- cgit v1.2.3 From 3fa9812e1d572cd06f95cec138b87d590160e4b4 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 23 Feb 2009 11:48:40 -0800 Subject: debug: Move debug_break into src/base --- src/arch/alpha/ev5.cc | 2 +- src/base/SConscript | 1 + src/base/debug.cc | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/base/debug.hh | 36 ++++++++++++++++++++++++++++++++++++ src/cpu/pc_event.cc | 2 +- src/dev/ns_gige.cc | 2 +- src/dev/sinic.cc | 2 +- src/sim/debug.cc | 14 +------------- src/sim/debug.hh | 7 +++---- src/sim/pseudo_inst.cc | 2 +- 10 files changed, 91 insertions(+), 22 deletions(-) create mode 100644 src/base/debug.cc create mode 100644 src/base/debug.hh (limited to 'src') diff --git a/src/arch/alpha/ev5.cc b/src/arch/alpha/ev5.cc index 7dc02a611..b3ef8f5d8 100644 --- a/src/arch/alpha/ev5.cc +++ b/src/arch/alpha/ev5.cc @@ -35,13 +35,13 @@ #include "arch/alpha/osfpal.hh" #include "arch/alpha/tlb.hh" #include "arch/alpha/kgdb.h" +#include "base/debug.hh" #include "base/remote_gdb.hh" #include "base/stats/events.hh" #include "config/full_system.hh" #include "cpu/base.hh" #include "cpu/simple_thread.hh" #include "cpu/thread_context.hh" -#include "sim/debug.hh" #include "sim/sim_exit.hh" namespace AlphaISA { diff --git a/src/base/SConscript b/src/base/SConscript index 000060e93..80a58cca9 100644 --- a/src/base/SConscript +++ b/src/base/SConscript @@ -36,6 +36,7 @@ Source('bigint.cc') Source('circlebuf.cc') Source('cprintf.cc') Source('crc.cc') +Source('debug.cc') Source('fast_alloc.cc') if env['USE_FENV']: Source('fenv.c') diff --git a/src/base/debug.cc b/src/base/debug.cc new file mode 100644 index 000000000..de201af18 --- /dev/null +++ b/src/base/debug.cc @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +#include +#include +#include + +#include "base/cprintf.hh" + +void +debug_break() +{ +#ifndef NDEBUG + kill(getpid(), SIGTRAP); +#else + cprintf("debug_break suppressed, compiled with NDEBUG\n"); +#endif +} diff --git a/src/base/debug.hh b/src/base/debug.hh new file mode 100644 index 000000000..b1577f782 --- /dev/null +++ b/src/base/debug.hh @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +#ifndef __BASE_DEBUG_HH__ +#define __BASE_DEBUG_HH__ + +void debug_break(); + +#endif // __BASE_DEBUG_HH__ diff --git a/src/cpu/pc_event.cc b/src/cpu/pc_event.cc index 438218df2..79f5277d5 100644 --- a/src/cpu/pc_event.cc +++ b/src/cpu/pc_event.cc @@ -34,12 +34,12 @@ #include #include +#include "base/debug.hh" #include "base/trace.hh" #include "config/full_system.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" #include "cpu/pc_event.hh" -#include "sim/debug.hh" #include "sim/core.hh" #include "sim/system.hh" diff --git a/src/dev/ns_gige.cc b/src/dev/ns_gige.cc index d326b103f..fb3446299 100644 --- a/src/dev/ns_gige.cc +++ b/src/dev/ns_gige.cc @@ -36,6 +36,7 @@ #include #include +#include "base/debug.hh" #include "base/inet.hh" #include "cpu/thread_context.hh" #include "dev/etherlink.hh" @@ -44,7 +45,6 @@ #include "mem/packet.hh" #include "mem/packet_access.hh" #include "params/NSGigE.hh" -#include "sim/debug.hh" #include "sim/host.hh" #include "sim/system.hh" diff --git a/src/dev/sinic.cc b/src/dev/sinic.cc index bf7398e62..37c6a8259 100644 --- a/src/dev/sinic.cc +++ b/src/dev/sinic.cc @@ -33,6 +33,7 @@ #include #include "arch/vtophys.hh" +#include "base/debug.hh" #include "base/inet.hh" #include "cpu/thread_context.hh" #include "cpu/intr_control.hh" @@ -40,7 +41,6 @@ #include "dev/sinic.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" -#include "sim/debug.hh" #include "sim/eventq.hh" #include "sim/host.hh" #include "sim/stats.hh" diff --git a/src/sim/debug.cc b/src/sim/debug.cc index 57ca0458c..f8a3215d0 100644 --- a/src/sim/debug.cc +++ b/src/sim/debug.cc @@ -30,29 +30,17 @@ */ #include -#include -#include -#include #include #include +#include "base/debug.hh" #include "sim/debug.hh" #include "sim/eventq.hh" #include "sim/sim_events.hh" using namespace std; -void -debug_break() -{ -#ifndef NDEBUG - kill(getpid(), SIGTRAP); -#else - cprintf("debug_break suppressed, compiled with NDEBUG\n"); -#endif -} - // // Debug event: place a breakpoint on the process function and // schedule the event to break at a particular cycle diff --git a/src/sim/debug.hh b/src/sim/debug.hh index 937864e69..7dafb8394 100644 --- a/src/sim/debug.hh +++ b/src/sim/debug.hh @@ -28,16 +28,15 @@ * Authors: Nathan Binkert */ -#ifndef __DEBUG_HH__ -#define __DEBUG_HH__ +#ifndef __SIM_DEBUG_HH__ +#define __SIM_DEBUG_HH__ #include "sim/host.hh" void schedBreakCycle(Tick when); -void debug_break(); int getRemoteGDBPort(); // Remote gdb base port. 0 disables remote gdb. void setRemoteGDBPort(int port); -#endif // __DEBUG_HH__ +#endif // __SIM_DEBUG_HH__ diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index f1cf2835d..00d0dbe7a 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -38,6 +38,7 @@ #include "arch/kernel_stats.hh" #include "arch/vtophys.hh" #include "base/annotate.hh" +#include "base/debug.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" #include "cpu/quiesce_event.hh" @@ -49,7 +50,6 @@ #include "sim/stat_control.hh" #include "sim/stats.hh" #include "sim/system.hh" -#include "sim/debug.hh" #if FULL_SYSTEM #include "sim/vptr.hh" #endif -- cgit v1.2.3 From f69ea20fc64c240b9f97ce584716693aa9b79d58 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 23 Feb 2009 12:03:06 -0800 Subject: stats: cleanup static stats to make startup work. This is mainly to allow the unit test to run without requiring the standard M5 stats from being initialized (e.g. sim_seconds, sim_ticks, host_seconds) --- src/sim/stat_control.cc | 31 +++++++++++++++++++++---------- src/sim/stats.hh | 1 - 2 files changed, 21 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/sim/stat_control.cc b/src/sim/stat_control.cc index 25c5be104..2dcf4798d 100644 --- a/src/sim/stat_control.cc +++ b/src/sim/stat_control.cc @@ -44,14 +44,6 @@ using namespace std; -Stats::Formula hostInstRate; -Stats::Formula hostTickRate; -Stats::Value hostMemory; -Stats::Value hostSeconds; - -Stats::Value simTicks; -Stats::Value simInsts; -Stats::Value simFreq; Stats::Formula simSeconds; namespace Stats { @@ -84,8 +76,21 @@ statElapsedTicks() SimTicksReset simTicksReset; -void -initSimStats() +struct Global +{ + Stats::Formula hostInstRate; + Stats::Formula hostTickRate; + Stats::Value hostMemory; + Stats::Value hostSeconds; + + Stats::Value simTicks; + Stats::Value simInsts; + Stats::Value simFreq; + + Global(); +}; + +Global::Global() { simInsts .functor(BaseCPU::numSimulatedInstructions) @@ -146,6 +151,12 @@ initSimStats() registerResetCallback(&simTicksReset); } +void +initSimStats() +{ + static Global global; +} + class _StatEvent : public Event { private: diff --git a/src/sim/stats.hh b/src/sim/stats.hh index 97251283d..481c36cf6 100644 --- a/src/sim/stats.hh +++ b/src/sim/stats.hh @@ -34,6 +34,5 @@ #include "base/statistics.hh" extern Stats::Formula simSeconds; -extern Stats::Value simTicks; #endif // __SIM_SIM_STATS_HH__ -- cgit v1.2.3 From d940a2b74180221dd32ad43d07b099a024f6b52e Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 23 Feb 2009 12:04:50 -0800 Subject: stats: fix text printout for distributions --- src/base/stats/text.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/base/stats/text.cc b/src/base/stats/text.cc index 84336f5e4..00efd977b 100644 --- a/src/base/stats/text.cc +++ b/src/base/stats/text.cc @@ -450,7 +450,7 @@ DistPrint::operator()(ostream &stream) const if (!compat) { for (off_type i = 0; i < size; ++i) { stringstream namestr; - namestr << name; + namestr << base; Counter low = i * bucket_size + min; Counter high = ::min(low + bucket_size, max); -- cgit v1.2.3 From bcb7e70178d2d15a8c30561311634df7a2c24c70 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 23 Feb 2009 12:04:52 -0800 Subject: stats: clean up the statistics unittest --- src/unittest/stattest.cc | 105 +++++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/unittest/stattest.cc b/src/unittest/stattest.cc index 78d43c6f3..30b7f8a6c 100644 --- a/src/unittest/stattest.cc +++ b/src/unittest/stattest.cc @@ -42,31 +42,6 @@ using namespace std; using namespace Stats; -Scalar<> s1; -Scalar<> s2; -Average<> s3; -Scalar<> s4; -Vector<> s5; -Distribution<> s6; -Vector<> s7; -AverageVector<> s8; -StandardDeviation<> s9; -AverageDeviation<> s10; -Scalar<> s11; -Distribution<> s12; -VectorDistribution<> s13; -VectorStandardDeviation<> s14; -VectorAverageDeviation<> s15; -Vector2d<> s16; - -Formula f1; -Formula f2; -Formula f3; -Value f4; -Value f5; -Formula f6; -Formula f7; - double testfunc() { @@ -141,15 +116,34 @@ main(int argc, char *argv[]) if (!text && (compat || descriptions)) usage(); - s5.init(5); - s6.init(1, 100, 13); - s7.init(7); - s8.init(10); - s12.init(1, 100, 13); - s13.init(4, 0, 99, 10); - s14.init(9); - s15.init(10); - s16.init(2, 9); + Scalar<> s1; + Scalar<> s2; + Average<> s3; + Scalar<> s4; + Vector<> s5; + Distribution<> s6; + Vector<> s7; + AverageVector<> s8; + StandardDeviation<> s9; + AverageDeviation<> s10; + Scalar<> s11; + Distribution<> s12; + VectorDistribution<> s13; + VectorStandardDeviation<> s14; + VectorAverageDeviation<> s15; + Vector2d<> s16; + Value s17; + Value s18; + + Formula f1; + Formula f2; + Formula f3; + Formula f4; + Formula f5; + + cprintf("sizeof(Scalar<>) = %d\n", sizeof(Scalar<>)); + cprintf("sizeof(Vector<>) = %d\n", sizeof(Vector<>)); + cprintf("sizeof(Distribution<>) = %d\n", sizeof(Distribution<>)); s1 .name("Stat01") @@ -165,7 +159,7 @@ main(int argc, char *argv[]) s3 .name("Stat03") .desc("this is statistic 3") - .prereq(f7) + .prereq(f5) ; s4 @@ -175,6 +169,7 @@ main(int argc, char *argv[]) ; s5 + .init(5) .name("Stat05") .desc("this is statistic 5") .prereq(s11) @@ -186,12 +181,14 @@ main(int argc, char *argv[]) ; s6 + .init(1, 100, 13) .name("Stat06") .desc("this is statistic 6") .prereq(s11) ; s7 + .init(7) .name("Stat07") .desc("this is statistic 7") .precision(1) @@ -200,6 +197,7 @@ main(int argc, char *argv[]) ; s8 + .init(10) .name("Stat08") .desc("this is statistic 8") .precision(2) @@ -221,26 +219,31 @@ main(int argc, char *argv[]) ; s12 + .init(1, 100, 13) .name("Stat12") .desc("this is statistic 12") ; s13 + .init(4, 0, 99, 10) .name("Stat13") .desc("this is statistic 13") ; s14 + .init(9) .name("Stat14") .desc("this is statistic 14") ; s15 + .init(10) .name("Stat15") .desc("this is statistic 15") ; s16 + .init(2, 9) .name("Stat16") .desc("this is statistic 16") .flags(total) @@ -250,6 +253,20 @@ main(int argc, char *argv[]) .ysubname(1, "y1") ; + s17 + .functor(testfunc) + .name("Stat17") + .desc("this is stat 17") + ; + + TestClass testclass; + s18 + .functor(testclass) + .name("Stat18") + .desc("this is stat 18") + ; + + f1 .name("Formula1") .desc("this is formula 1") @@ -275,29 +292,17 @@ main(int argc, char *argv[]) ; f4 - .functor(testfunc) .name("Formula4") .desc("this is formula 4") ; - TestClass testclass; - f5 - .functor(testclass) - .name("Formula5") - .desc("this is formula 5") - ; - - f6 - .name("Formula6") - .desc("this is formula 6") - ; f1 = s1 + s2; f2 = (-s1) / (-s2) * (-s3 + ULL(100) + s4); f3 = sum(s5) * s7; - f6 += constant(10.0); - f6 += s5[3]; - f7 = constant(1); + f4 += constant(10.0); + f4 += s5[3]; + f5 = constant(1); check(); reset(); -- cgit v1.2.3 From fb74987c522a141b2f61d303377453cbbfae0788 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 23 Feb 2009 12:22:15 -0800 Subject: stats: Try to make the names of things more intuitive. Basically, this means renaming several things called data to info, which is information about the statistics. Things that are named data now are actual data stored for the statistic. --- src/base/statistics.cc | 74 ++++++------- src/base/statistics.hh | 263 +++++++++++++++++++++++++---------------------- src/base/stats/mysql.cc | 211 +++++++++++++++++++------------------ src/base/stats/mysql.hh | 42 ++++---- src/base/stats/statdb.cc | 6 +- src/base/stats/statdb.hh | 10 +- src/base/stats/text.cc | 182 ++++++++++++++++---------------- src/base/stats/text.hh | 14 +-- src/base/stats/visit.hh | 28 ++--- 9 files changed, 422 insertions(+), 408 deletions(-) (limited to 'src') diff --git a/src/base/statistics.cc b/src/base/statistics.cc index cf2e6d4e7..93c1742b0 100644 --- a/src/base/statistics.cc +++ b/src/base/statistics.cc @@ -48,65 +48,59 @@ using namespace std; namespace Stats { -StatData * -DataAccess::find() const +Info * +InfoAccess::find() const { return Database::find(const_cast((const void *)this)); } -const StatData * -getStatData(const void *stat) +const Info * +getInfo(const void *stat) { return Database::find(const_cast(stat)); } void -DataAccess::map(StatData *data) +InfoAccess::setInfo(Info *info) { - Database::regStat(this, data); + Database::regStat(this, info); } -StatData * -DataAccess::statData() -{ - StatData *ptr = find(); - assert(ptr); - return ptr; -} - -const StatData * -DataAccess::statData() const +void +InfoAccess::setInit() { - const StatData *ptr = find(); - assert(ptr); - return ptr; + info()->flags |= init; } -void -DataAccess::setInit() +Info * +InfoAccess::info() { - statData()->flags |= init; + Info *info = find(); + assert(info); + return info; } -void -DataAccess::setPrint() +const Info * +InfoAccess::info() const { - Database::regPrint(this); + const Info *info = find(); + assert(info); + return info; } -StatData::StatData() +Info::Info() : flags(none), precision(-1), prereq(0) { static int count = 0; id = count++; } -StatData::~StatData() +Info::~Info() { } bool -StatData::less(StatData *stat1, StatData *stat2) +Info::less(Info *stat1, Info *stat2) { const string &name1 = stat1->name; const string &name2 = stat2->name; @@ -132,7 +126,7 @@ StatData::less(StatData *stat1, StatData *stat2) } bool -StatData::baseCheck() const +Info::baseCheck() const { if (!(flags & init)) { #ifdef DEBUG @@ -190,7 +184,7 @@ FormulaBase::zero() const } void -FormulaBase::update(StatData *) +FormulaBase::update(Info *) { } @@ -238,20 +232,20 @@ check() iter_t i, end = Database::stats().end(); for (i = Database::stats().begin(); i != end; ++i) { - StatData *data = *i; - assert(data); - if (!data->check() || !data->baseCheck()) - panic("stat check failed for %s\n", data->name); + Info *info = *i; + assert(info); + if (!info->check() || !info->baseCheck()) + panic("stat check failed for %s\n", info->name); } off_t j = 0; for (i = Database::stats().begin(); i != end; ++i) { - StatData *data = *i; - if (!(data->flags & print)) - data->name = "__Stat" + to_string(j++); + Info *info = *i; + if (!(info->flags & print)) + info->name = "__Stat" + to_string(j++); } - Database::stats().sort(StatData::less); + Database::stats().sort(Info::less); if (i == end) return; @@ -275,8 +269,8 @@ reset() Database::stat_list_t::iterator i = Database::stats().begin(); Database::stat_list_t::iterator end = Database::stats().end(); while (i != end) { - StatData *data = *i; - data->reset(); + Info *info = *i; + info->reset(); ++i; } diff --git a/src/base/statistics.hh b/src/base/statistics.hh index d50302d49..0bc770899 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -26,7 +26,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Nathan Binkert - * Erik Hallnor */ /** @file @@ -60,6 +59,7 @@ #include #include +#include "base/cast.hh" #include "base/cprintf.hh" #include "base/intmath.hh" #include "base/refcnt.hh" @@ -85,8 +85,9 @@ typedef std::numeric_limits CounterLimits; // Statistics Framework Base classes // ////////////////////////////////////////////////////////////////////// -struct StatData +class Info { + public: /** The name of the stat. */ std::string name; /** The description of the stat. */ @@ -96,15 +97,16 @@ struct StatData /** The display precision. */ int precision; /** A pointer to a prerequisite Stat. */ - const StatData *prereq; + const Info *prereq; /** * A unique stat ID for each stat in the simulator. * Can be used externally for lookups as well as for debugging. */ int id; - StatData(); - virtual ~StatData(); + public: + Info(); + virtual ~Info(); /** * Reset the corresponding stat to the default state. @@ -138,10 +140,10 @@ struct StatData * @param stat2 The second stat. * @return stat1's name is alphabetically before stat2's */ - static bool less(StatData *stat1, StatData *stat2); + static bool less(Info *stat1, Info *stat2); }; -class ScalarData : public StatData +class ScalarInfoBase : public Info { public: virtual Counter value() const = 0; @@ -151,13 +153,13 @@ class ScalarData : public StatData }; template -class ScalarStatData : public ScalarData +class ScalarInfo : public ScalarInfoBase { protected: Stat &s; public: - ScalarStatData(Stat &stat) : s(stat) {} + ScalarInfo(Stat &stat) : s(stat) {} virtual bool check() const { return s.check(); } virtual Counter value() const { return s.value(); } @@ -167,12 +169,14 @@ class ScalarStatData : public ScalarData virtual bool zero() const { return s.zero(); } }; -struct VectorData : public StatData +class VectorInfoBase : public Info { + public: /** Names and descriptions of subfields. */ mutable std::vector subnames; mutable std::vector subdescs; + public: virtual size_type size() const = 0; virtual const VCounter &value() const = 0; virtual const VResult &result() const = 0; @@ -193,7 +197,7 @@ struct VectorData : public StatData }; template -class VectorStatData : public VectorData +class VectorInfo : public VectorInfoBase { protected: Stat &s; @@ -201,7 +205,7 @@ class VectorStatData : public VectorData mutable VResult rvec; public: - VectorStatData(Stat &stat) : s(stat) {} + VectorInfo(Stat &stat) : s(stat) {} virtual bool check() const { return s.check(); } virtual bool zero() const { return s.zero(); } @@ -234,7 +238,7 @@ class VectorStatData : public VectorData } }; -struct DistDataData +struct DistData { Counter min_val; Counter max_val; @@ -252,20 +256,21 @@ struct DistDataData bool fancy; }; -struct DistData : public StatData +class DistInfoBase : public Info { + public: /** Local storage for the entry values, used for printing. */ - DistDataData data; + DistData data; }; template -class DistStatData : public DistData +class DistInfo : public DistInfoBase { protected: Stat &s; public: - DistStatData(Stat &stat) : s(stat) {} + DistInfo(Stat &stat) : s(stat) {} virtual bool check() const { return s.check(); } virtual void reset() { s.reset(); } @@ -279,17 +284,20 @@ class DistStatData : public DistData } }; -struct VectorDistData : public StatData +class VectorDistInfoBase : public Info { - std::vector data; + public: + std::vector data; /** Names and descriptions of subfields. */ mutable std::vector subnames; mutable std::vector subdescs; + protected: /** Local storage for the entry values, used for printing. */ mutable VResult rvec; + public: virtual size_type size() const = 0; void @@ -305,13 +313,13 @@ struct VectorDistData : public StatData }; template -class VectorDistStatData : public VectorDistData +class VectorDistInfo : public VectorDistInfoBase { protected: Stat &s; public: - VectorDistStatData(Stat &stat) : s(stat) {} + VectorDistInfo(Stat &stat) : s(stat) {} virtual bool check() const { return s.check(); } virtual void reset() { s.reset(); } @@ -327,8 +335,9 @@ class VectorDistStatData : public VectorDistData } }; -struct Vector2dData : public StatData +class Vector2dInfoBase : public Info { + public: /** Names and descriptions of subfields. */ std::vector subnames; std::vector subdescs; @@ -339,6 +348,7 @@ struct Vector2dData : public StatData mutable size_type x; mutable size_type y; + public: void update() { @@ -348,13 +358,13 @@ struct Vector2dData : public StatData }; template -class Vector2dStatData : public Vector2dData +class Vector2dInfo : public Vector2dInfoBase { protected: Stat &s; public: - Vector2dStatData(Stat &stat) : s(stat) {} + Vector2dInfo(Stat &stat) : s(stat) {} virtual bool check() const { return s.check(); } virtual void reset() { s.reset(); } @@ -369,43 +379,42 @@ class Vector2dStatData : public Vector2dData } }; -class DataAccess +class InfoAccess { protected: - StatData *find() const; - void map(StatData *data); - - StatData *statData(); - const StatData *statData() const; - + Info *find() const; + /** Set up an info class for this statistic */ + void setInfo(Info *info); + /** Save Storage class parameters if any */ void setInit(); - void setPrint(); + + Info *info(); + const Info *info() const; }; -template class Data> +template class Info> class Wrap : public Child { + public: + typedef Parent ParentType; + typedef Child ChildType; + typedef Info InfoType; + protected: Parent &self() { return *reinterpret_cast(this); } protected: - Data * - statData() + InfoType * + info() { - StatData *__data = DataAccess::statData(); - Data *ptr = dynamic_cast *>(__data); - assert(ptr); - return ptr; + return safe_cast(InfoAccess::info()); } public: - const Data * - statData() const + const InfoType * + info() const { - const StatData *__data = DataAccess::statData(); - const Data *ptr = dynamic_cast *>(__data); - assert(ptr); - return ptr; + return safe_cast(InfoAccess::info()); } protected: @@ -422,7 +431,7 @@ class Wrap : public Child public: Wrap() { - this->map(new Data(*this)); + this->setInfo(new InfoType(*this)); } /** @@ -433,9 +442,9 @@ class Wrap : public Child Parent & name(const std::string &_name) { - Data *data = this->statData(); - data->name = _name; - this->setPrint(); + InfoType *info = this->info(); + info->name = _name; + info->flags |= print; return this->self(); } @@ -448,7 +457,7 @@ class Wrap : public Child Parent & desc(const std::string &_desc) { - this->statData()->desc = _desc; + this->info()->desc = _desc; return this->self(); } @@ -460,7 +469,7 @@ class Wrap : public Child Parent & precision(int _precision) { - this->statData()->precision = _precision; + this->info()->precision = _precision; return this->self(); } @@ -472,7 +481,7 @@ class Wrap : public Child Parent & flags(StatFlags _flags) { - this->statData()->flags |= _flags; + this->info()->flags |= _flags; return this->self(); } @@ -486,14 +495,19 @@ class Wrap : public Child Parent & prereq(const Stat &prereq) { - this->statData()->prereq = prereq.statData(); + this->info()->prereq = prereq.info(); return this->self(); } }; -template class Data> -class WrapVec : public Wrap +template class Info> +class WrapVec : public Wrap { + public: + typedef Parent ParentType; + typedef Child ChildType; + typedef Info InfoType; + public: // The following functions are specific to vectors. If you use them // in a non vector context, you will get a nice compiler error! @@ -508,7 +522,7 @@ class WrapVec : public Wrap Parent & subname(off_type index, const std::string &name) { - std::vector &subn = this->statData()->subnames; + std::vector &subn = this->info()->subnames; if (subn.size() <= index) subn.resize(index + 1); subn[index] = name; @@ -525,7 +539,7 @@ class WrapVec : public Wrap Parent & subdesc(off_type index, const std::string &desc) { - std::vector &subd = this->statData()->subdescs; + std::vector &subd = this->info()->subdescs; if (subd.size() <= index) subd.resize(index + 1); subd[index] = desc; @@ -535,9 +549,14 @@ class WrapVec : public Wrap }; -template class Data> -class WrapVec2d : public WrapVec +template class Info> +class WrapVec2d : public WrapVec { + public: + typedef Parent ParentType; + typedef Child ChildType; + typedef Info InfoType; + public: /** * @warning This makes the assumption that if you're gonna subnames a 2d @@ -546,20 +565,20 @@ class WrapVec2d : public WrapVec Parent & ysubnames(const char **names) { - Data *data = this->statData(); - data->y_subnames.resize(this->y); + InfoType *info = this->info(); + info->y_subnames.resize(this->y); for (off_type i = 0; i < this->y; ++i) - data->y_subnames[i] = names[i]; + info->y_subnames[i] = names[i]; return this->self(); } Parent & ysubname(off_type index, const std::string subname) { - Data *data = this->statData(); + InfoType *info = this->info(); assert(index < this->y); - data->y_subnames.resize(this->y); - data->y_subnames[index] = subname.c_str(); + info->y_subnames.resize(this->y); + info->y_subnames[index] = subname.c_str(); return this->self(); } }; @@ -573,7 +592,7 @@ class WrapVec2d : public WrapVec /** * Templatized storage and interface for a simple scalar stat. */ -struct StatStor +class StatStor { public: /** The paramaters for this storage type, none for a scalar. */ @@ -638,7 +657,7 @@ struct StatStor * being watched. This is good for keeping track of residencies in structures * among other things. */ -struct AvgStor +class AvgStor { public: /** The paramaters for this storage type */ @@ -665,7 +684,8 @@ struct AvgStor * @param p The parameters for this storage. */ void - set(Counter val, Params &p) { + set(Counter val, Params &p) + { total += current * (curTick - last); last = curTick; current = val; @@ -726,7 +746,7 @@ struct AvgStor * Storage template. */ template -class ScalarBase : public DataAccess +class ScalarBase : public InfoAccess { public: typedef Stor Storage; @@ -851,7 +871,7 @@ class ScalarBase : public DataAccess }; -class ProxyData : public ScalarData +class ProxyInfo : public ScalarInfoBase { public: virtual void visit(Visit &visitor) { visitor.visit(*this); } @@ -863,7 +883,7 @@ class ProxyData : public ScalarData }; template -class ValueProxy : public ProxyData +class ValueProxy : public ProxyInfo { private: T *scalar; @@ -876,7 +896,7 @@ class ValueProxy : public ProxyData }; template -class FunctorProxy : public ProxyData +class FunctorProxy : public ProxyInfo { private: T *functor; @@ -888,10 +908,10 @@ class FunctorProxy : public ProxyData virtual Result total() const { return (*functor)(); } }; -class ValueBase : public DataAccess +class ValueBase : public InfoAccess { private: - ProxyData *proxy; + ProxyInfo *proxy; public: ValueBase() : proxy(NULL) { } @@ -983,7 +1003,8 @@ class ScalarProxy * @return A reference to this proxy. */ const ScalarProxy & - operator=(const ScalarProxy &sp) { + operator=(const ScalarProxy &sp) + { stat = sp.stat; index = sp.index; return *this; @@ -1058,7 +1079,7 @@ class ScalarProxy std::string str() const { - return csprintf("%s[%d]", stat->statData()->name, index); + return csprintf("%s[%d]", stat->info()->name, index); } }; @@ -1067,7 +1088,7 @@ class ScalarProxy * Storage class. @sa ScalarBase */ template -class VectorBase : public DataAccess +class VectorBase : public InfoAccess { public: typedef Stor Storage; @@ -1207,7 +1228,7 @@ class VectorBase : public DataAccess return Proxy(this, index); } - void update(StatData *data) {} + void update(Info *data) {} }; template @@ -1292,7 +1313,7 @@ class VectorProxy }; template -class Vector2dBase : public DataAccess +class Vector2dBase : public InfoAccess { public: typedef Stor Storage; @@ -1318,12 +1339,12 @@ class Vector2dBase : public DataAccess assert(_x > 0 && _y > 0 && "sizes must be positive!"); assert(!storage && "already initialized"); - Vector2dData *statdata = dynamic_cast(find()); + Vector2dInfoBase *info = dynamic_cast(find()); x = _x; y = _y; - statdata->x = _x; - statdata->y = _y; + info->x = _x; + info->y = _y; _size = x * y; char *ptr = new char[_size * sizeof(Storage)]; @@ -1351,12 +1372,12 @@ class Vector2dBase : public DataAccess } void - update(Vector2dData *newdata) + update(Vector2dInfoBase *newinfo) { size_type size = this->size(); - newdata->cvec.resize(size); + newinfo->cvec.resize(size); for (off_type i = 0; i < size; ++i) - newdata->cvec[i] = data(i)->value(params); + newinfo->cvec[i] = data(i)->value(); } std::string ysubname(off_type i) const { return (*this->y_subnames)[i]; } @@ -1414,7 +1435,7 @@ class Vector2dBase : public DataAccess /** * Templatized storage and interface for a distrbution stat. */ -struct DistStor +class DistStor { public: /** The parameters for a distribution stat. */ @@ -1507,7 +1528,7 @@ struct DistStor } void - update(DistDataData *data, const Params ¶ms) + update(DistData *data, const Params ¶ms) { data->min = params.min; data->max = params.max; @@ -1552,7 +1573,7 @@ struct DistStor * Templatized storage and interface for a distribution that calculates mean * and variance. */ -struct FancyStor +class FancyStor { public: /** @@ -1595,7 +1616,7 @@ struct FancyStor } void - update(DistDataData *data, const Params ¶ms) + update(DistData *data, const Params ¶ms) { data->sum = sum; data->squares = squares; @@ -1630,7 +1651,7 @@ struct FancyStor * Templatized storage for distribution that calculates per tick mean and * variance. */ -struct AvgFancy +class AvgFancy { public: /** No parameters for this storage. */ @@ -1665,7 +1686,7 @@ struct AvgFancy } void - update(DistDataData *data, const Params ¶ms) + update(DistData *data, const Params ¶ms) { data->sum = sum; data->squares = squares; @@ -1700,7 +1721,7 @@ struct AvgFancy * determined by the Storage template. @sa ScalarBase */ template -class DistBase : public DataAccess +class DistBase : public InfoAccess { public: typedef Stor Storage; @@ -1766,7 +1787,7 @@ class DistBase : public DataAccess bool zero() const { return data()->zero(params); } void - update(DistData *base) + update(DistInfoBase *base) { base->data.fancy = Storage::fancy; data()->update(&(base->data), params); @@ -1792,7 +1813,7 @@ template class DistProxy; template -class VectorDistBase : public DataAccess +class VectorDistBase : public InfoAccess { public: typedef Stor Storage; @@ -1886,7 +1907,7 @@ class VectorDistBase : public DataAccess } void - update(VectorDistData *base) + update(VectorDistInfoBase *base) { size_type size = this->size(); base->data.resize(size); @@ -2011,11 +2032,11 @@ typedef RefCountingPtr NodePtr; class ScalarStatNode : public Node { private: - const ScalarData *data; + const ScalarInfoBase *data; mutable VResult vresult; public: - ScalarStatNode(const ScalarData *d) : data(d), vresult(1) {} + ScalarStatNode(const ScalarInfoBase *d) : data(d), vresult(1) {} virtual const VResult & result() const @@ -2078,10 +2099,10 @@ class ScalarProxyNode : public Node class VectorStatNode : public Node { private: - const VectorData *data; + const VectorInfoBase *data; public: - VectorStatNode(const VectorData *d) : data(d) { } + VectorStatNode(const VectorInfoBase *d) : data(d) { } virtual const VResult &result() const { return data->result(); } virtual Result total() const { return data->total(); }; @@ -2364,7 +2385,7 @@ class SumNode : public Node * @sa Stat, ScalarBase, StatStor */ template -class Scalar : public Wrap, ScalarBase, ScalarStatData> +class Scalar : public Wrap, ScalarBase, ScalarInfo> { public: /** The base implementation. */ @@ -2384,7 +2405,7 @@ class Scalar : public Wrap, ScalarBase, ScalarStatData> void operator=(const U &v) { Base::operator=(v); } }; -class Value : public Wrap +class Value : public Wrap { public: /** The base implementation. */ @@ -2412,7 +2433,7 @@ class Value : public Wrap * @sa Stat, ScalarBase, AvgStor */ template -class Average : public Wrap, ScalarBase, ScalarStatData> +class Average : public Wrap, ScalarBase, ScalarInfo> { public: /** The base implementation. */ @@ -2441,7 +2462,7 @@ class Average : public Wrap, ScalarBase, ScalarStatData> * @sa Stat, VectorBase, StatStor */ template -class Vector : public WrapVec, VectorBase, VectorStatData> +class Vector : public WrapVec, VectorBase, VectorInfo> { public: /** The base implementation. */ @@ -2466,7 +2487,7 @@ class Vector : public WrapVec, VectorBase, VectorStatData> */ template class AverageVector - : public WrapVec, VectorBase, VectorStatData> + : public WrapVec, VectorBase, VectorInfo> { public: /** @@ -2488,7 +2509,7 @@ class AverageVector */ template class Vector2d - : public WrapVec2d, Vector2dBase, Vector2dStatData> + : public WrapVec2d, Vector2dBase, Vector2dInfo> { public: Vector2d & @@ -2505,7 +2526,7 @@ class Vector2d */ template class Distribution - : public Wrap, DistBase, DistStatData> + : public Wrap, DistBase, DistInfo> { public: /** Base implementation. */ @@ -2539,7 +2560,7 @@ class Distribution */ template class StandardDeviation - : public Wrap, DistBase, DistStatData> + : public Wrap, DistBase, DistInfo> { public: /** The base implementation */ @@ -2563,7 +2584,7 @@ class StandardDeviation */ template class AverageDeviation - : public Wrap, DistBase, DistStatData> + : public Wrap, DistBase, DistInfo> { public: /** The base implementation */ @@ -2589,7 +2610,7 @@ template class VectorDistribution : public WrapVec, VectorDistBase, - VectorDistStatData> + VectorDistInfo> { public: /** The base implementation */ @@ -2626,7 +2647,7 @@ template class VectorStandardDeviation : public WrapVec, VectorDistBase, - VectorDistStatData> + VectorDistInfo> { public: /** The base implementation */ @@ -2656,7 +2677,7 @@ template class VectorAverageDeviation : public WrapVec, VectorDistBase, - VectorDistStatData> + VectorDistInfo> { public: /** The base implementation */ @@ -2683,7 +2704,7 @@ class VectorAverageDeviation * stored as a tree of Nodes that represent the equation to calculate. * @sa Stat, ScalarStat, VectorStat, Node, Temp */ -class FormulaBase : public DataAccess +class FormulaBase : public InfoAccess { protected: /** The root of the tree which represents the Formula */ @@ -2732,12 +2753,12 @@ class FormulaBase : public DataAccess /** * */ - void update(StatData *); + void update(Info *); std::string str() const; }; -class FormulaData : public VectorData +class FormulaInfoBase : public VectorInfoBase { public: virtual std::string str() const = 0; @@ -2745,7 +2766,7 @@ class FormulaData : public VectorData }; template -class FormulaStatData : public FormulaData +class FormulaInfo : public FormulaInfoBase { protected: Stat &s; @@ -2753,7 +2774,7 @@ class FormulaStatData : public FormulaData mutable VCounter cvec; public: - FormulaStatData(Stat &stat) : s(stat) {} + FormulaInfo(Stat &stat) : s(stat) {} virtual bool zero() const { return s.zero(); } virtual void reset() { s.reset(); } @@ -2784,7 +2805,7 @@ class Temp; class Formula : public WrapVec + FormulaInfo> { public: /** @@ -2861,7 +2882,7 @@ class Temp */ template Temp(const Scalar &s) - : node(new ScalarStatNode(s.statData())) + : node(new ScalarStatNode(s.info())) { } /** @@ -2869,7 +2890,7 @@ class Temp * @param s The ScalarStat to place in a node. */ Temp(const Value &s) - : node(new ScalarStatNode(s.statData())) + : node(new ScalarStatNode(s.info())) { } /** @@ -2878,7 +2899,7 @@ class Temp */ template Temp(const Average &s) - : node(new ScalarStatNode(s.statData())) + : node(new ScalarStatNode(s.info())) { } /** @@ -2887,7 +2908,7 @@ class Temp */ template Temp(const Vector &s) - : node(new VectorStatNode(s.statData())) + : node(new VectorStatNode(s.info())) { } /** diff --git a/src/base/stats/mysql.cc b/src/base/stats/mysql.cc index 8d263d2b9..2f096765f 100644 --- a/src/base/stats/mysql.cc +++ b/src/base/stats/mysql.cc @@ -503,11 +503,11 @@ MySql::configure() } for (i = stats().begin(); i != end; ++i) { - StatData *data = *i; - if (data->prereq) { + Info *info = *i; + if (info->prereq) { // update the prerequisite - uint16_t stat_id = find(data->id); - uint16_t prereq_id = find(data->prereq->id); + uint16_t stat_id = find(info->id); + uint16_t prereq_id = find(info->prereq->id); assert(stat_id && prereq_id); stringstream update; @@ -528,153 +528,152 @@ MySql::configure() configured = true; } - bool -MySql::configure(const StatData &data, string type) +MySql::configure(const Info &info, string type) { stat.init(); - stat.name = data.name; - stat.descr = data.desc; + stat.name = info.name; + stat.descr = info.desc; stat.type = type; - stat.print = data.flags & print; - stat.prec = data.precision; - stat.nozero = data.flags & nozero; - stat.nonan = data.flags & nonan; - stat.total = data.flags & total; - stat.pdf = data.flags & pdf; - stat.cdf = data.flags & cdf; + stat.print = info.flags & print; + stat.prec = info.precision; + stat.nozero = info.flags & nozero; + stat.nonan = info.flags & nonan; + stat.total = info.flags & total; + stat.pdf = info.flags & pdf; + stat.cdf = info.flags & cdf; return stat.print; } void -MySql::configure(const ScalarData &data) +MySql::configure(const ScalarInfoBase &info) { - if (!configure(data, "SCALAR")) + if (!configure(info, "SCALAR")) return; - insert(data.id, stat.setup(run)); + insert(info.id, stat.setup(run)); } void -MySql::configure(const VectorData &data) +MySql::configure(const VectorInfoBase &info) { - if (!configure(data, "VECTOR")) + if (!configure(info, "VECTOR")) return; uint16_t statid = stat.setup(run); - if (!data.subnames.empty()) { + if (!info.subnames.empty()) { InsertSubData subdata; subdata.stat = statid; subdata.y = 0; - for (off_type i = 0; i < data.subnames.size(); ++i) { + for (off_type i = 0; i < info.subnames.size(); ++i) { subdata.x = i; - subdata.name = data.subnames[i]; - subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i]; + subdata.name = info.subnames[i]; + subdata.descr = info.subdescs.empty() ? "" : info.subdescs[i]; if (!subdata.name.empty() || !subdata.descr.empty()) subdata.setup(run); } } - insert(data.id, statid); + insert(info.id, statid); } void -MySql::configure(const DistData &data) +MySql::configure(const DistInfoBase &info) { - if (!configure(data, "DIST")) + if (!configure(info, "DIST")) return; - if (!data.data.fancy) { - stat.size = data.data.size; - stat.min = data.data.min; - stat.max = data.data.max; - stat.bktsize = data.data.bucket_size; + if (!info.data.fancy) { + stat.size = info.data.size; + stat.min = info.data.min; + stat.max = info.data.max; + stat.bktsize = info.data.bucket_size; } - insert(data.id, stat.setup(run)); + insert(info.id, stat.setup(run)); } void -MySql::configure(const VectorDistData &data) +MySql::configure(const VectorDistInfoBase &info) { - if (!configure(data, "VECTORDIST")) + if (!configure(info, "VECTORDIST")) return; - if (!data.data[0].fancy) { - stat.size = data.data[0].size; - stat.min = data.data[0].min; - stat.max = data.data[0].max; - stat.bktsize = data.data[0].bucket_size; + if (!info.data[0].fancy) { + stat.size = info.data[0].size; + stat.min = info.data[0].min; + stat.max = info.data[0].max; + stat.bktsize = info.data[0].bucket_size; } uint16_t statid = stat.setup(run); - if (!data.subnames.empty()) { + if (!info.subnames.empty()) { InsertSubData subdata; subdata.stat = statid; subdata.y = 0; - for (off_type i = 0; i < data.subnames.size(); ++i) { + for (off_type i = 0; i < info.subnames.size(); ++i) { subdata.x = i; - subdata.name = data.subnames[i]; - subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i]; + subdata.name = info.subnames[i]; + subdata.descr = info.subdescs.empty() ? "" : info.subdescs[i]; if (!subdata.name.empty() || !subdata.descr.empty()) subdata.setup(run); } } - insert(data.id, statid); + insert(info.id, statid); } void -MySql::configure(const Vector2dData &data) +MySql::configure(const Vector2dInfoBase &info) { - if (!configure(data, "VECTOR2D")) + if (!configure(info, "VECTOR2D")) return; uint16_t statid = stat.setup(run); - if (!data.subnames.empty()) { + if (!info.subnames.empty()) { InsertSubData subdata; subdata.stat = statid; subdata.y = -1; - for (off_type i = 0; i < data.subnames.size(); ++i) { + for (off_type i = 0; i < info.subnames.size(); ++i) { subdata.x = i; - subdata.name = data.subnames[i]; - subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i]; + subdata.name = info.subnames[i]; + subdata.descr = info.subdescs.empty() ? "" : info.subdescs[i]; if (!subdata.name.empty() || !subdata.descr.empty()) subdata.setup(run); } } - if (!data.y_subnames.empty()) { + if (!info.y_subnames.empty()) { InsertSubData subdata; subdata.stat = statid; subdata.x = -1; subdata.descr = ""; - for (off_type i = 0; i < data.y_subnames.size(); ++i) { + for (off_type i = 0; i < info.y_subnames.size(); ++i) { subdata.y = i; - subdata.name = data.y_subnames[i]; + subdata.name = info.y_subnames[i]; if (!subdata.name.empty()) subdata.setup(run); } } - insert(data.id, statid); + insert(info.id, statid); } void -MySql::configure(const FormulaData &data) +MySql::configure(const FormulaInfoBase &info) { MySQL::Connection &mysql = run->conn(); assert(mysql.connected()); - configure(data, "FORMULA"); - insert(data.id, stat.setup(run)); + configure(info, "FORMULA"); + insert(info.id, stat.setup(run)); - uint16_t stat = find(data.id); - string formula = data.str(); + uint16_t stat = find(info.id); + string formula = info.str(); stringstream insert_formula; ccprintf(insert_formula, @@ -720,7 +719,7 @@ MySql::output() Database::stat_list_t::const_iterator i, end = Database::stats().end(); for (i = Database::stats().begin(); i != end; ++i) { - StatData *stat = *i; + Info *stat = *i; stat->visit(*this); if (mysql.commit()) panic("could not commit transaction\n%s\n", mysql.error); @@ -735,32 +734,31 @@ MySql::event(const std::string &event) newevent.insert(event); } - void -MySql::output(const ScalarData &data) +MySql::output(const ScalarInfoBase &info) { - if (!(data.flags & print)) + if (!(info.flags & print)) return; - newdata.stat = find(data.id); + newdata.stat = find(info.id); newdata.x = 0; newdata.y = 0; - newdata.data = data.value(); + newdata.data = info.value(); newdata.insert(); } void -MySql::output(const VectorData &data) +MySql::output(const VectorInfoBase &info) { - if (!(data.flags & print)) + if (!(info.flags & print)) return; - newdata.stat = find(data.id); + newdata.stat = find(info.id); newdata.y = 0; - const VCounter &cvec = data.value(); - size_type size = data.size(); + const VCounter &cvec = info.value(); + size_type size = info.size(); for (off_type x = 0; x < size; x++) { newdata.x = x; newdata.data = cvec[x]; @@ -769,7 +767,7 @@ MySql::output(const VectorData &data) } void -MySql::output(const DistDataData &data) +MySql::output(const DistData &data) { const int db_sum = -1; const int db_squares = -2; @@ -817,54 +815,53 @@ MySql::output(const DistDataData &data) } } - void -MySql::output(const DistData &data) +MySql::output(const DistInfoBase &info) { - if (!(data.flags & print)) + if (!(info.flags & print)) return; - newdata.stat = find(data.id); + newdata.stat = find(info.id); newdata.y = 0; - output(data.data); + output(info.data); } void -MySql::output(const VectorDistData &data) +MySql::output(const VectorDistInfoBase &info) { - if (!(data.flags & print)) + if (!(info.flags & print)) return; - newdata.stat = find(data.id); + newdata.stat = find(info.id); - size_type size = data.data.size(); + size_type size = info.data.size(); for (off_type y = 0; y < size; ++y) { newdata.y = y; - output(data.data[y]); + output(info.data[y]); } } void -MySql::output(const Vector2dData &data) +MySql::output(const Vector2dInfoBase &info) { - if (!(data.flags & print)) + if (!(info.flags & print)) return; - newdata.stat = find(data.id); + newdata.stat = find(info.id); off_type index = 0; - for (off_type x = 0; x < data.x; x++) { + for (off_type x = 0; x < info.x; x++) { newdata.x = x; - for (off_type y = 0; y < data.y; y++) { + for (off_type y = 0; y < info.y; y++) { newdata.y = y; - newdata.data = data.cvec[index++]; + newdata.data = info.cvec[index++]; newdata.insert(); } } } void -MySql::output(const FormulaData &data) +MySql::output(const FormulaInfoBase &info) { } @@ -872,60 +869,60 @@ MySql::output(const FormulaData &data) * Implement the visitor */ void -MySql::visit(const ScalarData &data) +MySql::visit(const ScalarInfoBase &info) { if (!configured) - configure(data); + configure(info); else - output(data); + output(info); } void -MySql::visit(const VectorData &data) +MySql::visit(const VectorInfoBase &info) { if (!configured) - configure(data); + configure(info); else - output(data); + output(info); } void -MySql::visit(const DistData &data) +MySql::visit(const DistInfoBase &info) { return; if (!configured) - configure(data); + configure(info); else - output(data); + output(info); } void -MySql::visit(const VectorDistData &data) +MySql::visit(const VectorDistInfoBase &info) { return; if (!configured) - configure(data); + configure(info); else - output(data); + output(info); } void -MySql::visit(const Vector2dData &data) +MySql::visit(const Vector2dInfoBase &info) { return; if (!configured) - configure(data); + configure(info); else - output(data); + output(info); } void -MySql::visit(const FormulaData &data) +MySql::visit(const FormulaInfoBase &info) { if (!configured) - configure(data); + configure(info); else - output(data); + output(info); } bool diff --git a/src/base/stats/mysql.hh b/src/base/stats/mysql.hh index 6e47719ce..f0f79bebd 100644 --- a/src/base/stats/mysql.hh +++ b/src/base/stats/mysql.hh @@ -40,7 +40,7 @@ namespace MySQL { class Connection; } namespace Stats { -class DistDataData; +class DistInfoBase; class MySqlRun; struct SetupStat @@ -121,7 +121,7 @@ class MySql : public Output SetupStat stat; InsertData newdata; InsertEvent newevent; - std::list formulas; + std::list formulas; bool configured; protected: @@ -155,12 +155,12 @@ class MySql : public Output public: // Implement Visit - virtual void visit(const ScalarData &data); - virtual void visit(const VectorData &data); - virtual void visit(const DistData &data); - virtual void visit(const VectorDistData &data); - virtual void visit(const Vector2dData &data); - virtual void visit(const FormulaData &data); + virtual void visit(const ScalarInfoBase &info); + virtual void visit(const VectorInfoBase &info); + virtual void visit(const DistInfoBase &info); + virtual void visit(const VectorDistInfoBase &info); + virtual void visit(const Vector2dInfoBase &info); + virtual void visit(const FormulaInfoBase &info); // Implement Output virtual bool valid() const; @@ -171,22 +171,22 @@ class MySql : public Output protected: // Output helper - void output(const DistDataData &data); - void output(const ScalarData &data); - void output(const VectorData &data); + void output(const ScalarInfoBase &info); + void output(const VectorInfoBase &info); + void output(const DistInfoBase &info); + void output(const VectorDistInfoBase &info); + void output(const Vector2dInfoBase &info); + void output(const FormulaInfoBase &info); void output(const DistData &data); - void output(const VectorDistData &data); - void output(const Vector2dData &data); - void output(const FormulaData &data); void configure(); - bool configure(const StatData &data, std::string type); - void configure(const ScalarData &data); - void configure(const VectorData &data); - void configure(const DistData &data); - void configure(const VectorDistData &data); - void configure(const Vector2dData &data); - void configure(const FormulaData &data); + bool configure(const Info &info, std::string type); + void configure(const ScalarInfoBase &info); + void configure(const VectorInfoBase &info); + void configure(const DistInfoBase &info); + void configure(const VectorDistInfoBase &info); + void configure(const Vector2dInfoBase &info); + void configure(const FormulaInfoBase &info); }; bool initMySQL(std::string host, std::string database, std::string user, diff --git a/src/base/stats/statdb.cc b/src/base/stats/statdb.cc index c54dbb8ec..8ead17c52 100644 --- a/src/base/stats/statdb.cc +++ b/src/base/stats/statdb.cc @@ -38,7 +38,7 @@ using namespace std; namespace Stats { namespace Database { -StatData * +Info * find(void *stat) { stat_map_t::const_iterator i = map().find(stat); @@ -50,7 +50,7 @@ find(void *stat) } void -regStat(void *stat, StatData *data) +regStat(void *stat, Info *data) { if (map().find(stat) != map().end()) panic("shouldn't register stat twice!"); @@ -68,7 +68,7 @@ regStat(void *stat, StatData *data) void regPrint(void *stat) { - StatData *data = find(stat); + Info *data = find(stat); assert(data); data->flags |= print; } diff --git a/src/base/stats/statdb.hh b/src/base/stats/statdb.hh index a5b9be7eb..d12c6166b 100644 --- a/src/base/stats/statdb.hh +++ b/src/base/stats/statdb.hh @@ -40,12 +40,12 @@ class Python; namespace Stats { -class StatData; +class Info; namespace Database { -typedef std::map stat_map_t; -typedef std::list stat_list_t; +typedef std::map stat_map_t; +typedef std::list stat_list_t; // We wrap the database in a struct to make sure it is built in time. struct TheDatabase @@ -58,8 +58,8 @@ TheDatabase &db(); inline stat_map_t &map() { return db().map; } inline stat_list_t &stats() { return db().stats; } -StatData *find(void *stat); -void regStat(void *stat, StatData *data); +Info *find(void *stat); +void regStat(void *stat, Info *data); void regPrint(void *stat); inline std::string name() { return "Statistics Database"; } diff --git a/src/base/stats/text.cc b/src/base/stats/text.cc index 00efd977b..877c4c650 100644 --- a/src/base/stats/text.cc +++ b/src/base/stats/text.cc @@ -143,12 +143,12 @@ Text::output() } bool -Text::noOutput(const StatData &data) +Text::noOutput(const Info &info) { - if (!(data.flags & print)) + if (!(info.flags & print)) return true; - if (data.prereq && data.prereq->zero()) + if (info.prereq && info.prereq->zero()) return true; return false; @@ -535,19 +535,19 @@ DistPrint::operator()(ostream &stream) const } void -Text::visit(const ScalarData &data) +Text::visit(const ScalarInfoBase &info) { - if (noOutput(data)) + if (noOutput(info)) return; ScalarPrint print; - print.value = data.result(); - print.name = data.name; - print.desc = data.desc; - print.flags = data.flags; + print.value = info.result(); + print.name = info.name; + print.desc = info.desc; + print.flags = info.flags; print.compat = compat; print.descriptions = descriptions; - print.precision = data.precision; + print.precision = info.precision; print.pdf = NAN; print.cdf = NAN; @@ -555,32 +555,32 @@ Text::visit(const ScalarData &data) } void -Text::visit(const VectorData &data) +Text::visit(const VectorInfoBase &info) { - if (noOutput(data)) + if (noOutput(info)) return; - size_type size = data.size(); + size_type size = info.size(); VectorPrint print; - print.name = data.name; - print.desc = data.desc; - print.flags = data.flags; + print.name = info.name; + print.desc = info.desc; + print.flags = info.flags; print.compat = compat; print.descriptions = descriptions; - print.precision = data.precision; - print.vec = data.result(); - print.total = data.total(); + print.precision = info.precision; + print.vec = info.result(); + print.total = info.total(); - if (!data.subnames.empty()) { + if (!info.subnames.empty()) { for (off_type i = 0; i < size; ++i) { - if (!data.subnames[i].empty()) { - print.subnames = data.subnames; + if (!info.subnames[i].empty()) { + print.subnames = info.subnames; print.subnames.resize(size); for (off_type i = 0; i < size; ++i) { - if (!data.subnames[i].empty() && - !data.subdescs[i].empty()) { - print.subdescs = data.subdescs; + if (!info.subnames[i].empty() && + !info.subdescs[i].empty()) { + print.subdescs = info.subdescs; print.subdescs.resize(size); break; } @@ -594,54 +594,54 @@ Text::visit(const VectorData &data) } void -Text::visit(const Vector2dData &data) +Text::visit(const Vector2dInfoBase &info) { - if (noOutput(data)) + if (noOutput(info)) return; bool havesub = false; VectorPrint print; - print.subnames = data.y_subnames; - print.flags = data.flags; + print.subnames = info.y_subnames; + print.flags = info.flags; print.compat = compat; print.descriptions = descriptions; - print.precision = data.precision; + print.precision = info.precision; - if (!data.subnames.empty()) { - for (off_type i = 0; i < data.x; ++i) - if (!data.subnames[i].empty()) + if (!info.subnames.empty()) { + for (off_type i = 0; i < info.x; ++i) + if (!info.subnames[i].empty()) havesub = true; } - VResult tot_vec(data.y); + VResult tot_vec(info.y); Result super_total = 0.0; - for (off_type i = 0; i < data.x; ++i) { - if (havesub && (i >= data.subnames.size() || data.subnames[i].empty())) + for (off_type i = 0; i < info.x; ++i) { + if (havesub && (i >= info.subnames.size() || info.subnames[i].empty())) continue; - off_type iy = i * data.y; - VResult yvec(data.y); + off_type iy = i * info.y; + VResult yvec(info.y); Result total = 0.0; - for (off_type j = 0; j < data.y; ++j) { - yvec[j] = data.cvec[iy + j]; + for (off_type j = 0; j < info.y; ++j) { + yvec[j] = info.cvec[iy + j]; tot_vec[j] += yvec[j]; total += yvec[j]; super_total += yvec[j]; } - print.name = data.name + "_" + - (havesub ? data.subnames[i] : to_string(i)); - print.desc = data.desc; + print.name = info.name + "_" + + (havesub ? info.subnames[i] : to_string(i)); + print.desc = info.desc; print.vec = yvec; print.total = total; print(*stream); } - if ((data.flags & ::Stats::total) && (data.x > 1)) { - print.name = data.name; - print.desc = data.desc; + if ((info.flags & ::Stats::total) && (info.x > 1)) { + print.name = info.name; + print.desc = info.desc; print.vec = tot_vec; print.total = super_total; print(*stream); @@ -649,82 +649,84 @@ Text::visit(const Vector2dData &data) } void -Text::visit(const DistData &data) +Text::visit(const DistInfoBase &info) { - if (noOutput(data)) + if (noOutput(info)) return; DistPrint print; - print.name = data.name; - print.desc = data.desc; - print.flags = data.flags; + print.name = info.name; + print.desc = info.desc; + print.flags = info.flags; print.compat = compat; print.descriptions = descriptions; - print.precision = data.precision; + print.precision = info.precision; - print.min_val = data.data.min_val; - print.max_val = data.data.max_val; - print.underflow = data.data.underflow; - print.overflow = data.data.overflow; - print.vec.resize(data.data.cvec.size()); + const DistData &data = info.data; + + print.min_val = data.min_val; + print.max_val = data.max_val; + print.underflow = data.underflow; + print.overflow = data.overflow; + print.vec.resize(data.cvec.size()); for (off_type i = 0; i < print.vec.size(); ++i) - print.vec[i] = (Result)data.data.cvec[i]; - print.sum = data.data.sum; - print.squares = data.data.squares; - print.samples = data.data.samples; + print.vec[i] = (Result)data.cvec[i]; + print.sum = data.sum; + print.squares = data.squares; + print.samples = data.samples; - print.min = data.data.min; - print.max = data.data.max; - print.bucket_size = data.data.bucket_size; - print.size = data.data.size; - print.fancy = data.data.fancy; + print.min = data.min; + print.max = data.max; + print.bucket_size = data.bucket_size; + print.size = data.size; + print.fancy = data.fancy; print(*stream); } void -Text::visit(const VectorDistData &data) +Text::visit(const VectorDistInfoBase &info) { - if (noOutput(data)) + if (noOutput(info)) return; - for (off_type i = 0; i < data.size(); ++i) { + for (off_type i = 0; i < info.size(); ++i) { DistPrint print; - print.name = data.name + "_" + - (data.subnames[i].empty() ? (to_string(i)) : data.subnames[i]); - print.desc = data.subdescs[i].empty() ? data.desc : data.subdescs[i]; - print.flags = data.flags; + print.name = info.name + "_" + + (info.subnames[i].empty() ? (to_string(i)) : info.subnames[i]); + print.desc = info.subdescs[i].empty() ? info.desc : info.subdescs[i]; + print.flags = info.flags; print.compat = compat; print.descriptions = descriptions; - print.precision = data.precision; + print.precision = info.precision; - print.min_val = data.data[i].min_val; - print.max_val = data.data[i].max_val; - print.underflow = data.data[i].underflow; - print.overflow = data.data[i].overflow; - print.vec.resize(data.data[i].cvec.size()); + print.min_val = info.data[i].min_val; + print.max_val = info.data[i].max_val; + print.underflow = info.data[i].underflow; + print.overflow = info.data[i].overflow; + print.vec.resize(info.data[i].cvec.size()); for (off_type j = 0; j < print.vec.size(); ++j) - print.vec[j] = (Result)data.data[i].cvec[j]; - print.sum = data.data[i].sum; - print.squares = data.data[i].squares; - print.samples = data.data[i].samples; + print.vec[j] = (Result)info.data[i].cvec[j]; + print.sum = info.data[i].sum; + print.squares = info.data[i].squares; + print.samples = info.data[i].samples; - print.min = data.data[i].min; - print.max = data.data[i].max; - print.bucket_size = data.data[i].bucket_size; - print.size = data.data[i].size; - print.fancy = data.data[i].fancy; + print.min = info.data[i].min; + print.max = info.data[i].max; + print.bucket_size = info.data[i].bucket_size; + print.size = info.data[i].size; + print.fancy = info.data[i].fancy; print(*stream); } } void -Text::visit(const FormulaData &data) +Text::visit(const FormulaInfoBase &info) { - visit((const VectorData &)data); + visit((const VectorInfoBase &)info); } bool diff --git a/src/base/stats/text.hh b/src/base/stats/text.hh index 781d1083d..38e0202eb 100644 --- a/src/base/stats/text.hh +++ b/src/base/stats/text.hh @@ -46,7 +46,7 @@ class Text : public Output std::ostream *stream; protected: - bool noOutput(const StatData &data); + bool noOutput(const Info &info); public: bool compat; @@ -62,12 +62,12 @@ class Text : public Output void open(const std::string &file); // Implement Visit - virtual void visit(const ScalarData &data); - virtual void visit(const VectorData &data); - virtual void visit(const DistData &data); - virtual void visit(const VectorDistData &data); - virtual void visit(const Vector2dData &data); - virtual void visit(const FormulaData &data); + virtual void visit(const ScalarInfoBase &info); + virtual void visit(const VectorInfoBase &info); + virtual void visit(const DistInfoBase &info); + virtual void visit(const VectorDistInfoBase &info); + virtual void visit(const Vector2dInfoBase &info); + virtual void visit(const FormulaInfoBase &info); // Implement Output virtual bool valid() const; diff --git a/src/base/stats/visit.hh b/src/base/stats/visit.hh index 0087c227c..9d6996689 100644 --- a/src/base/stats/visit.hh +++ b/src/base/stats/visit.hh @@ -38,26 +38,26 @@ namespace Stats { -class StatData; -class ScalarData; -class VectorData; -class DistDataData; -class DistData; -class VectorDistData; -class Vector2dData; -class FormulaData; +class Info; +class ScalarInfoBase; +class VectorInfoBase; +class DistInfoBase; +class DistInfoBase; +class VectorDistInfoBase; +class Vector2dInfoBase; +class FormulaInfoBase; struct Visit { Visit(); virtual ~Visit(); - virtual void visit(const ScalarData &data) = 0; - virtual void visit(const VectorData &data) = 0; - virtual void visit(const DistData &data) = 0; - virtual void visit(const VectorDistData &data) = 0; - virtual void visit(const Vector2dData &data) = 0; - virtual void visit(const FormulaData &data) = 0; + virtual void visit(const ScalarInfoBase &info) = 0; + virtual void visit(const VectorInfoBase &info) = 0; + virtual void visit(const DistInfoBase &info) = 0; + virtual void visit(const VectorDistInfoBase &info) = 0; + virtual void visit(const Vector2dInfoBase &info) = 0; + virtual void visit(const FormulaInfoBase &info) = 0; }; /* namespace Stats */ } -- cgit v1.2.3 From 80d5f34da6788d63e2be6458a5d2a548b459d0d0 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 23 Feb 2009 12:22:17 -0800 Subject: stats: get rid of the convoluted 'database' code. Just use the stuff directly and things ought to be more clear --- src/base/SConscript | 1 - src/base/statistics.cc | 58 ++++++++++++++++++++------------- src/base/statistics.hh | 6 ++-- src/base/stats/mysql.cc | 14 +++----- src/base/stats/statdb.cc | 84 ------------------------------------------------ src/base/stats/statdb.hh | 70 ---------------------------------------- src/base/stats/text.cc | 7 ++-- 7 files changed, 47 insertions(+), 193 deletions(-) delete mode 100644 src/base/stats/statdb.cc delete mode 100644 src/base/stats/statdb.hh (limited to 'src') diff --git a/src/base/SConscript b/src/base/SConscript index 80a58cca9..ffad1929a 100644 --- a/src/base/SConscript +++ b/src/base/SConscript @@ -74,7 +74,6 @@ Source('loader/symtab.cc') Source('stats/events.cc') Source('stats/output.cc') -Source('stats/statdb.cc') Source('stats/text.cc') Source('stats/visit.cc') diff --git a/src/base/statistics.cc b/src/base/statistics.cc index 93c1742b0..63741d4c6 100644 --- a/src/base/statistics.cc +++ b/src/base/statistics.cc @@ -42,28 +42,42 @@ #include "base/str.hh" #include "base/time.hh" #include "base/trace.hh" -#include "base/stats/statdb.hh" using namespace std; namespace Stats { -Info * -InfoAccess::find() const +typedef map MapType; + +// We wrap these in a function to make sure they're built in time. +list & +statsList() { - return Database::find(const_cast((const void *)this)); + static list the_list; + return the_list; } -const Info * -getInfo(const void *stat) +MapType & +statsMap() { - return Database::find(const_cast(stat)); + static MapType the_map; + return the_map; } void InfoAccess::setInfo(Info *info) { - Database::regStat(this, info); + if (statsMap().find(this) != statsMap().end()) + panic("shouldn't register stat twice!"); + + statsList().push_back(info); + +#ifndef NDEBUG + pair result = +#endif + statsMap().insert(make_pair(this, info)); + assert(result.second && "this should never fail"); + assert(statsMap().find(this) != statsMap().end()); } void @@ -75,17 +89,17 @@ InfoAccess::setInit() Info * InfoAccess::info() { - Info *info = find(); - assert(info); - return info; + MapType::const_iterator i = statsMap().find(this); + assert(i != statsMap().end()); + return (*i).second; } const Info * InfoAccess::info() const { - const Info *info = find(); - assert(info); - return info; + MapType::const_iterator i = statsMap().find(this); + assert(i != statsMap().end()); + return (*i).second; } Info::Info() @@ -228,10 +242,10 @@ Formula::operator+=(Temp r) void check() { - typedef Database::stat_list_t::iterator iter_t; + typedef list::iterator iter_t; - iter_t i, end = Database::stats().end(); - for (i = Database::stats().begin(); i != end; ++i) { + iter_t i, end = statsList().end(); + for (i = statsList().begin(); i != end; ++i) { Info *info = *i; assert(info); if (!info->check() || !info->baseCheck()) @@ -239,13 +253,13 @@ check() } off_t j = 0; - for (i = Database::stats().begin(); i != end; ++i) { + for (i = statsList().begin(); i != end; ++i) { Info *info = *i; if (!(info->flags & print)) info->name = "__Stat" + to_string(j++); } - Database::stats().sort(Info::less); + statsList().sort(Info::less); if (i == end) return; @@ -253,7 +267,7 @@ check() iter_t last = i; ++i; - for (i = Database::stats().begin(); i != end; ++i) { + for (i = statsList().begin(); i != end; ++i) { if ((*i)->name == (*last)->name) panic("same name used twice! name=%s\n", (*i)->name); @@ -266,8 +280,8 @@ CallbackQueue resetQueue; void reset() { - Database::stat_list_t::iterator i = Database::stats().begin(); - Database::stat_list_t::iterator end = Database::stats().end(); + list::iterator i = statsList().begin(); + list::iterator end = statsList().end(); while (i != end) { Info *info = *i; info->reset(); diff --git a/src/base/statistics.hh b/src/base/statistics.hh index 0bc770899..5d894e8e1 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -56,6 +56,7 @@ #include #include #include +#include #include #include @@ -382,7 +383,6 @@ class Vector2dInfo : public Vector2dInfoBase class InfoAccess { protected: - Info *find() const; /** Set up an info class for this statistic */ void setInfo(Info *info); /** Save Storage class parameters if any */ @@ -1339,7 +1339,7 @@ class Vector2dBase : public InfoAccess assert(_x > 0 && _y > 0 && "sizes must be positive!"); assert(!storage && "already initialized"); - Vector2dInfoBase *info = dynamic_cast(find()); + Vector2dInfoBase *info = safe_cast(this->info()); x = _x; y = _y; @@ -3084,6 +3084,8 @@ sum(Temp val) return NodePtr(new SumNode >(val)); } +std::list &statsList(); + /* namespace Stats */ } #endif // __BASE_STATISTICS_HH__ diff --git a/src/base/stats/mysql.cc b/src/base/stats/mysql.cc index 2f096765f..42464993d 100644 --- a/src/base/stats/mysql.cc +++ b/src/base/stats/mysql.cc @@ -40,7 +40,6 @@ #include "base/stats/flags.hh" #include "base/stats/mysql.hh" #include "base/stats/mysql_run.hh" -#include "base/stats/statdb.hh" #include "base/stats/types.hh" #include "base/str.hh" #include "base/userinfo.hh" @@ -493,16 +492,14 @@ MySql::configure() /* * set up all stats! */ - using namespace Database; - MySQL::Connection &mysql = run->conn(); - stat_list_t::const_iterator i, end = stats().end(); - for (i = stats().begin(); i != end; ++i) { + list::const_iterator i, end = statsList().end(); + for (i = statsList().begin(); i != end; ++i) { (*i)->visit(*this); } - for (i = stats().begin(); i != end; ++i) { + for (i = statsList().begin(); i != end; ++i) { Info *info = *i; if (info->prereq) { // update the prerequisite @@ -706,7 +703,6 @@ MySql::valid() const void MySql::output() { - using namespace Database; assert(valid()); if (!configured) @@ -717,8 +713,8 @@ MySql::output() MySQL::Connection &mysql = run->conn(); - Database::stat_list_t::const_iterator i, end = Database::stats().end(); - for (i = Database::stats().begin(); i != end; ++i) { + list::const_iterator i, end = statsList().end(); + for (i = statsList().begin(); i != end; ++i) { Info *stat = *i; stat->visit(*this); if (mysql.commit()) diff --git a/src/base/stats/statdb.cc b/src/base/stats/statdb.cc deleted file mode 100644 index 8ead17c52..000000000 --- a/src/base/stats/statdb.cc +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Nathan Binkert - */ - -#include "base/misc.hh" -#include "base/trace.hh" -#include "base/statistics.hh" -#include "base/stats/statdb.hh" - -using namespace std; - -namespace Stats { -namespace Database { - -Info * -find(void *stat) -{ - stat_map_t::const_iterator i = map().find(stat); - - if (i == map().end()) - return NULL; - - return (*i).second; -} - -void -regStat(void *stat, Info *data) -{ - if (map().find(stat) != map().end()) - panic("shouldn't register stat twice!"); - - stats().push_back(data); - -#ifndef NDEBUG - pair result = -#endif - map().insert(make_pair(stat, data)); - assert(result.second && "this should never fail"); - assert(map().find(stat) != map().end()); -} - -void -regPrint(void *stat) -{ - Info *data = find(stat); - assert(data); - data->flags |= print; -} - -TheDatabase & -db() -{ - static TheDatabase db; - return db; -} - -/* namespace Database */ } -/* namespace Stats */ } diff --git a/src/base/stats/statdb.hh b/src/base/stats/statdb.hh deleted file mode 100644 index d12c6166b..000000000 --- a/src/base/stats/statdb.hh +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Nathan Binkert - */ - -#ifndef __BASE_STATS_STATDB_HH__ -#define __BASE_STATS_STATDB_HH__ - -#include -#include -#include -#include - -class Python; - -namespace Stats { - -class Info; - -namespace Database { - -typedef std::map stat_map_t; -typedef std::list stat_list_t; - -// We wrap the database in a struct to make sure it is built in time. -struct TheDatabase -{ - stat_map_t map; - stat_list_t stats; -}; - -TheDatabase &db(); -inline stat_map_t &map() { return db().map; } -inline stat_list_t &stats() { return db().stats; } - -Info *find(void *stat); -void regStat(void *stat, Info *data); -void regPrint(void *stat); - -inline std::string name() { return "Statistics Database"; } - -/* namespace Database */ } -/* namespace Stats */ } - -#endif // __BASE_STATS_STATDB_HH__ diff --git a/src/base/stats/text.cc b/src/base/stats/text.cc index 877c4c650..14300a0f8 100644 --- a/src/base/stats/text.cc +++ b/src/base/stats/text.cc @@ -43,7 +43,6 @@ #include "base/misc.hh" #include "base/statistics.hh" -#include "base/stats/statdb.hh" #include "base/stats/text.hh" #include "base/stats/visit.hh" @@ -132,11 +131,9 @@ Text::valid() const void Text::output() { - using namespace Database; - ccprintf(*stream, "\n---------- Begin Simulation Statistics ----------\n"); - stat_list_t::const_iterator i, end = stats().end(); - for (i = stats().begin(); i != end; ++i) + list::const_iterator i, end = statsList().end(); + for (i = statsList().begin(); i != end; ++i) (*i)->visit(*this); ccprintf(*stream, "\n---------- End Simulation Statistics ----------\n"); stream->flush(); -- cgit v1.2.3 From aaf98aaa326e79710af0fdcb2425ef2f6a5e82f1 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 23 Feb 2009 12:22:18 -0800 Subject: stats: move the limits stuff into the types.hh file --- src/base/statistics.hh | 3 --- src/base/stats/types.hh | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/base/statistics.hh b/src/base/statistics.hh index 5d894e8e1..d8145ddc4 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -55,7 +55,6 @@ #include #include #include -#include #include #include #include @@ -78,9 +77,7 @@ extern Tick curTick; /* A namespace for all of the Statistics */ namespace Stats { -typedef std::numeric_limits CounterLimits; -/* Contains the statistic implementation details */ ////////////////////////////////////////////////////////////////////// // // Statistics Framework Base classes diff --git a/src/base/stats/types.hh b/src/base/stats/types.hh index 6f56aec9a..e561f94ad 100644 --- a/src/base/stats/types.hh +++ b/src/base/stats/types.hh @@ -31,6 +31,7 @@ #ifndef __BASE_STATS_TYPES_HH__ #define __BASE_STATS_TYPES_HH__ +#include #include #include "sim/host.hh" @@ -42,6 +43,8 @@ typedef double Counter; /** vector of counters. */ typedef std::vector VCounter; +typedef std::numeric_limits CounterLimits; + /** All results are doubles. */ typedef double Result; /** vector of results. */ -- cgit v1.2.3 From f3090e5b704a2b7a02a736ec8601cd961fe3a865 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 23 Feb 2009 12:22:19 -0800 Subject: stats: reorganize how parameters are stored and accessed. --- src/base/statistics.cc | 24 +++- src/base/statistics.hh | 337 +++++++++++++++++++++++------------------------- src/base/stats/mysql.cc | 18 +-- src/base/stats/text.cc | 27 ++-- 4 files changed, 209 insertions(+), 197 deletions(-) (limited to 'src') diff --git a/src/base/statistics.cc b/src/base/statistics.cc index 63741d4c6..032cbf689 100644 --- a/src/base/statistics.cc +++ b/src/base/statistics.cc @@ -36,6 +36,7 @@ #include "base/callback.hh" #include "base/cprintf.hh" +#include "base/debug.hh" #include "base/hostinfo.hh" #include "base/misc.hh" #include "base/statistics.hh" @@ -80,6 +81,12 @@ InfoAccess::setInfo(Info *info) assert(statsMap().find(this) != statsMap().end()); } +void +InfoAccess::setParams(const StorageParams *params) +{ + info()->storageParams = params; +} + void InfoAccess::setInit() { @@ -102,11 +109,20 @@ InfoAccess::info() const return (*i).second; } +StorageParams::~StorageParams() +{ +} + +int Info::id_count = 0; + +int debug_break_id = -1; + Info::Info() - : flags(none), precision(-1), prereq(0) + : flags(none), precision(-1), prereq(0), storageParams(NULL) { - static int count = 0; - id = count++; + id = id_count++; + if (debug_break_id >= 0 and debug_break_id == id) + debug_break(); } Info::~Info() @@ -249,7 +265,7 @@ check() Info *info = *i; assert(info); if (!info->check() || !info->baseCheck()) - panic("stat check failed for %s\n", info->name); + panic("stat check failed for '%s' %d\n", info->name, info->id); } off_t j = 0; diff --git a/src/base/statistics.hh b/src/base/statistics.hh index d8145ddc4..15b6c032a 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -77,6 +77,10 @@ extern Tick curTick; /* A namespace for all of the Statistics */ namespace Stats { +struct StorageParams +{ + virtual ~StorageParams(); +}; ////////////////////////////////////////////////////////////////////// // @@ -100,8 +104,12 @@ class Info * A unique stat ID for each stat in the simulator. * Can be used externally for lookups as well as for debugging. */ + static int id_count; int id; + public: + const StorageParams *storageParams; + public: Info(); virtual ~Info(); @@ -247,10 +255,6 @@ struct DistData Counter squares; Counter samples; - Counter min; - Counter max; - Counter bucket_size; - size_type size; bool fancy; }; @@ -383,9 +387,13 @@ class InfoAccess /** Set up an info class for this statistic */ void setInfo(Info *info); /** Save Storage class parameters if any */ + void setParams(const StorageParams *params); + /** Save Storage class parameters if any */ void setInit(); + /** Grab the information class for this statistic */ Info *info(); + /** Grab the information class for this statistic */ const Info *info() const; }; @@ -591,55 +599,51 @@ class WrapVec2d : public WrapVec */ class StatStor { - public: - /** The paramaters for this storage type, none for a scalar. */ - struct Params { }; - private: /** The statistic value. */ Counter data; + public: + struct Params : public StorageParams {}; + public: /** * Builds this storage element and calls the base constructor of the * datatype. */ - StatStor(const Params &) : data(Counter()) {} + StatStor(Info *info) + : data(Counter()) + { } /** * The the stat to the given value. * @param val The new value. - * @param p The paramters of this storage type. */ - void set(Counter val, const Params &p) { data = val; } + void set(Counter val) { data = val; } /** * Increment the stat by the given value. * @param val The new value. - * @param p The paramters of this storage type. */ - void inc(Counter val, const Params &p) { data += val; } + void inc(Counter val) { data += val; } /** * Decrement the stat by the given value. * @param val The new value. - * @param p The paramters of this storage type. */ - void dec(Counter val, const Params &p) { data -= val; } + void dec(Counter val) { data -= val; } /** * Return the value of this stat as its base type. - * @param p The params of this storage type. * @return The value of this stat. */ - Counter value(const Params &p) const { return data; } + Counter value() const { return data; } /** * Return the value of this stat as a result type. - * @param p The parameters of this storage type. * @return The value of this stat. */ - Result result(const Params &p) const { return (Result)data; } + Result result() const { return (Result)data; } /** * Reset stat value to default */ - void reset() { data = Counter(); } + void reset(Info *info) { data = Counter(); } /** * @return true if zero value @@ -656,10 +660,6 @@ class StatStor */ class AvgStor { - public: - /** The paramaters for this storage type */ - struct Params { }; - private: /** The current count. */ Counter current; @@ -668,20 +668,24 @@ class AvgStor /** The tick that current last changed. */ mutable Tick last; + public: + struct Params : public StorageParams {}; + public: /** * Build and initializes this stat storage. */ - AvgStor(Params &p) : current(0), total(0), last(0) { } + AvgStor(Info *info) + : current(0), total(0), last(0) + { } /** * Set the current count to the one provided, update the total and last * set values. * @param val The new count. - * @param p The parameters for this storage. */ void - set(Counter val, Params &p) + set(Counter val) { total += current * (curTick - last); last = curTick; @@ -691,31 +695,27 @@ class AvgStor /** * Increment the current count by the provided value, calls set. * @param val The amount to increment. - * @param p The parameters for this storage. */ - void inc(Counter val, Params &p) { set(current + val, p); } + void inc(Counter val) { set(current + val); } /** * Deccrement the current count by the provided value, calls set. * @param val The amount to decrement. - * @param p The parameters for this storage. */ - void dec(Counter val, Params &p) { set(current - val, p); } + void dec(Counter val) { set(current - val); } /** * Return the current count. - * @param p The parameters for this storage. * @return The current count. */ - Counter value(const Params &p) const { return current; } + Counter value() const { return current; } /** * Return the current average. - * @param p The parameters for this storage. * @return The current average. */ Result - result(const Params &p) const + result() const { total += current * (curTick - last); last = curTick; @@ -726,7 +726,7 @@ class AvgStor * Reset stat value to default */ void - reset() + reset(Info *info) { total = 0; last = curTick; @@ -747,17 +747,12 @@ class ScalarBase : public InfoAccess { public: typedef Stor Storage; - - /** Define the params of the storage class. */ - typedef typename Storage::Params Params; + typedef typename Stor::Params Params; protected: /** The storage of this stat. */ char storage[sizeof(Storage)] __attribute__ ((aligned (8))); - /** The parameters for this stat. */ - Params params; - protected: /** * Retrieve the storage. @@ -785,7 +780,7 @@ class ScalarBase : public InfoAccess void doInit() { - new (storage) Storage(params); + new (storage) Storage(info()); setInit(); } @@ -794,14 +789,10 @@ class ScalarBase : public InfoAccess * Return the current value of this stat as its base type. * @return The current value. */ - Counter value() const { return data()->value(params); } + Counter value() const { return data()->value(); } public: - /** - * Create and initialize this stat, register it with the database. - */ - ScalarBase() - { } + ScalarBase() { } public: // Common operators for stats @@ -809,12 +800,12 @@ class ScalarBase : public InfoAccess * Increment the stat by 1. This calls the associated storage object inc * function. */ - void operator++() { data()->inc(1, params); } + void operator++() { data()->inc(1); } /** * Decrement the stat by 1. This calls the associated storage object dec * function. */ - void operator--() { data()->dec(1, params); } + void operator--() { data()->dec(1); } /** Increment the stat by 1. */ void operator++(int) { ++*this; } @@ -827,7 +818,7 @@ class ScalarBase : public InfoAccess * @param v The new value. */ template - void operator=(const U &v) { data()->set(v, params); } + void operator=(const U &v) { data()->set(v); } /** * Increment the stat by the given value. This calls the associated @@ -835,7 +826,7 @@ class ScalarBase : public InfoAccess * @param v The value to add. */ template - void operator+=(const U &v) { data()->inc(v, params); } + void operator+=(const U &v) { data()->inc(v); } /** * Decrement the stat by the given value. This calls the associated @@ -843,7 +834,7 @@ class ScalarBase : public InfoAccess * @param v The value to substract. */ template - void operator-=(const U &v) { data()->dec(v, params); } + void operator-=(const U &v) { data()->dec(v); } /** * Return the number of elements, always 1 for a scalar. @@ -856,11 +847,11 @@ class ScalarBase : public InfoAccess /** * Reset stat value to default */ - void reset() { data()->reset(); } + void reset() { data()->reset(info()); } - Counter value() { return data()->value(params); } + Counter value() { return data()->value(); } - Result result() { return data()->result(params); } + Result result() { return data()->result(); } Result total() { return result(); } @@ -966,18 +957,17 @@ class ScalarProxy * Return the current value of this stat as its base type. * @return The current value. */ - Counter value() const { return stat->data(index)->value(stat->params); } + Counter value() const { return stat->data(index)->value(); } /** * Return the current value of this statas a result type. * @return The current value. */ - Result result() const { return stat->data(index)->result(stat->params); } + Result result() const { return stat->data(index)->result(); } public: /** * Create and initialize this proxy, do not register it with the database. - * @param p The params to use. * @param i The index to access. */ ScalarProxy(Stat *s, off_type i) @@ -1013,12 +1003,12 @@ class ScalarProxy * Increment the stat by 1. This calls the associated storage object inc * function. */ - void operator++() { stat->data(index)->inc(1, stat->params); } + void operator++() { stat->data(index)->inc(1); } /** * Decrement the stat by 1. This calls the associated storage object dec * function. */ - void operator--() { stat->data(index)->dec(1, stat->params); } + void operator--() { stat->data(index)->dec(1); } /** Increment the stat by 1. */ void operator++(int) { ++*this; } @@ -1034,7 +1024,7 @@ class ScalarProxy void operator=(const U &v) { - stat->data(index)->set(v, stat->params); + stat->data(index)->set(v); } /** @@ -1046,7 +1036,7 @@ class ScalarProxy void operator+=(const U &v) { - stat->data(index)->inc(v, stat->params); + stat->data(index)->inc(v); } /** @@ -1058,7 +1048,7 @@ class ScalarProxy void operator-=(const U &v) { - stat->data(index)->dec(v, stat->params); + stat->data(index)->dec(v); } /** @@ -1089,9 +1079,7 @@ class VectorBase : public InfoAccess { public: typedef Stor Storage; - - /** Define the params of the storage class. */ - typedef typename Storage::Params Params; + typedef typename Stor::Params Params; /** Proxy type */ typedef ScalarProxy > Proxy; @@ -1103,9 +1091,6 @@ class VectorBase : public InfoAccess Storage *storage; size_type _size; - /** The parameters for this stat. */ - Params params; - protected: /** * Retrieve the storage. @@ -1132,7 +1117,7 @@ class VectorBase : public InfoAccess storage = reinterpret_cast(ptr); for (off_type i = 0; i < _size; ++i) - new (&storage[i]) Storage(params); + new (&storage[i]) Storage(info()); setInit(); } @@ -1143,7 +1128,7 @@ class VectorBase : public InfoAccess { vec.resize(size()); for (off_type i = 0; i < size(); ++i) - vec[i] = data(i)->value(params); + vec[i] = data(i)->value(); } /** @@ -1155,7 +1140,7 @@ class VectorBase : public InfoAccess { vec.resize(size()); for (off_type i = 0; i < size(); ++i) - vec[i] = data(i)->result(params); + vec[i] = data(i)->result(); } /** @@ -1167,7 +1152,7 @@ class VectorBase : public InfoAccess { Result total = 0.0; for (off_type i = 0; i < size(); ++i) - total += data(i)->result(params); + total += data(i)->result(); return total; } @@ -1195,7 +1180,7 @@ class VectorBase : public InfoAccess reset() { for (off_type i = 0; i < size(); ++i) - data(i)->reset(); + data(i)->reset(info()); } public: @@ -1260,7 +1245,7 @@ class VectorProxy vec.resize(size()); for (off_type i = 0; i < size(); ++i) - vec[i] = data(i)->result(stat->params); + vec[i] = data(i)->result(); return vec; } @@ -1270,7 +1255,7 @@ class VectorProxy { Result total = 0; for (off_type i = 0; i < size(); ++i) - total += data(i)->result(stat->params); + total += data(i)->result(); return total; } @@ -1314,7 +1299,7 @@ class Vector2dBase : public InfoAccess { public: typedef Stor Storage; - typedef typename Storage::Params Params; + typedef typename Stor::Params Params; typedef VectorProxy > Proxy; friend class ScalarProxy >; friend class VectorProxy >; @@ -1324,7 +1309,6 @@ class Vector2dBase : public InfoAccess size_type y; size_type _size; Storage *storage; - Params params; protected: Storage *data(off_type index) { return &storage[index]; } @@ -1348,7 +1332,7 @@ class Vector2dBase : public InfoAccess storage = reinterpret_cast(ptr); for (off_type i = 0; i < _size; ++i) - new (&storage[i]) Storage(params); + new (&storage[i]) Storage(info); setInit(); } @@ -1413,7 +1397,7 @@ class Vector2dBase : public InfoAccess reset() { for (off_type i = 0; i < size(); ++i) - data(i)->reset(); + data(i)->reset(info()); } bool @@ -1436,7 +1420,7 @@ class DistStor { public: /** The parameters for a distribution stat. */ - struct Params + struct Params : public StorageParams { /** The minimum value to track. */ Counter min; @@ -1445,11 +1429,20 @@ class DistStor /** The number of entries in each bucket. */ Counter bucket_size; /** The number of buckets. Equal to (max-min)/bucket_size. */ - size_type size; + size_type buckets; }; enum { fancy = false }; private: + /** The minimum value to track. */ + Counter min_track; + /** The maximum value to track. */ + Counter max_track; + /** The number of entries in each bucket. */ + Counter bucket_size; + /** The number of buckets. Equal to (max-min)/bucket_size. */ + size_type buckets; + /** The smallest value sampled. */ Counter min_val; /** The largest value sampled. */ @@ -1468,10 +1461,10 @@ class DistStor VCounter cvec; public: - DistStor(const Params ¶ms) - : cvec(params.size) + DistStor(Info *info) + : cvec(safe_cast(info->storageParams)->buckets) { - reset(); + reset(info); } /** @@ -1481,16 +1474,16 @@ class DistStor * @param params The paramters of the distribution. */ void - sample(Counter val, int number, const Params ¶ms) + sample(Counter val, int number) { - if (val < params.min) + if (val < min_track) underflow += number; - else if (val > params.max) + else if (val > max_track) overflow += number; else { size_type index = - (size_type)std::floor((val - params.min) / params.bucket_size); - assert(index < size(params)); + (size_type)std::floor((val - min_track) / bucket_size); + assert(index < size()); cvec[index] += number; } @@ -1509,48 +1502,50 @@ class DistStor /** * Return the number of buckets in this distribution. * @return the number of buckets. - * @todo Is it faster to return the size from the parameters? */ - size_type size(const Params &) const { return cvec.size(); } + size_type size() const { return cvec.size(); } /** * Returns true if any calls to sample have been made. - * @param params The paramters of the distribution. * @return True if any values have been sampled. */ bool - zero(const Params ¶ms) const + zero() const { return samples == Counter(); } void - update(DistData *data, const Params ¶ms) + update(Info *info, DistData &data) { - data->min = params.min; - data->max = params.max; - data->bucket_size = params.bucket_size; - data->size = params.size; + const Params *params = safe_cast(info->storageParams); - data->min_val = (min_val == CounterLimits::max()) ? 0 : min_val; - data->max_val = (max_val == CounterLimits::min()) ? 0 : max_val; - data->underflow = underflow; - data->overflow = overflow; - data->cvec.resize(params.size); - for (off_type i = 0; i < params.size; ++i) - data->cvec[i] = cvec[i]; + data.min_val = (min_val == CounterLimits::max()) ? 0 : min_val; + data.max_val = (max_val == CounterLimits::min()) ? 0 : max_val; + data.underflow = underflow; + data.overflow = overflow; - data->sum = sum; - data->squares = squares; - data->samples = samples; + int buckets = params->buckets; + data.cvec.resize(buckets); + for (off_type i = 0; i < buckets; ++i) + data.cvec[i] = cvec[i]; + + data.sum = sum; + data.squares = squares; + data.samples = samples; } /** * Reset stat value to default */ void - reset() + reset(Info *info) { + const Params *params = safe_cast(info->storageParams); + min_track = params->min; + max_track = params->max; + bucket_size = params->bucket_size; + min_val = CounterLimits::max(); max_val = CounterLimits::min(); underflow = 0; @@ -1573,10 +1568,9 @@ class DistStor class FancyStor { public: - /** - * No paramters for this storage. - */ - struct Params {}; + struct Params : public StorageParams {}; + + public: enum { fancy = true }; private: @@ -1591,7 +1585,7 @@ class FancyStor /** * Create and initialize this storage. */ - FancyStor(const Params &) + FancyStor(Info *info) : sum(Counter()), squares(Counter()), samples(Counter()) { } @@ -1604,7 +1598,7 @@ class FancyStor * @param p The parameters of this stat. */ void - sample(Counter val, int number, const Params &p) + sample(Counter val, int number) { Counter value = val * number; sum += value; @@ -1613,30 +1607,30 @@ class FancyStor } void - update(DistData *data, const Params ¶ms) + update(Info *info, DistData &data) { - data->sum = sum; - data->squares = squares; - data->samples = samples; + data.sum = sum; + data.squares = squares; + data.samples = samples; } /** * Return the number of entries in this stat, 1 * @return 1. */ - size_type size(const Params &) const { return 1; } + size_type size() const { return 1; } /** * Return true if no samples have been added. * @return True if no samples have been added. */ - bool zero(const Params &) const { return samples == Counter(); } + bool zero() const { return samples == Counter(); } /** * Reset stat value to default */ void - reset() + reset(Info *info) { sum = Counter(); squares = Counter(); @@ -1651,8 +1645,9 @@ class FancyStor class AvgFancy { public: - /** No parameters for this storage. */ - struct Params {}; + struct Params : public StorageParams {}; + + public: enum { fancy = true }; private: @@ -1665,17 +1660,18 @@ class AvgFancy /** * Create and initialize this storage. */ - AvgFancy(const Params &) : sum(Counter()), squares(Counter()) {} + AvgFancy(Info *info) + : sum(Counter()), squares(Counter()) + {} /** * Add a value to the distribution for the given number of times. * Update the running sum and sum of squares. * @param val The value to add. * @param number The number of times to add the value. - * @param p The paramters of the distribution. */ void - sample(Counter val, int number, const Params &p) + sample(Counter val, int number) { Counter value = val * number; sum += value; @@ -1683,30 +1679,30 @@ class AvgFancy } void - update(DistData *data, const Params ¶ms) + update(Info *info, DistData &data) { - data->sum = sum; - data->squares = squares; - data->samples = curTick; + data.sum = sum; + data.squares = squares; + data.samples = curTick; } /** * Return the number of entries, in this case 1. * @return 1. */ - size_type size(const Params ¶ms) const { return 1; } + size_type size() const { return 1; } /** * Return true if no samples have been added. * @return True if the sum is zero. */ - bool zero(const Params ¶ms) const { return sum == Counter(); } + bool zero() const { return sum == Counter(); } /** * Reset stat value to default */ void - reset() + reset(Info *info) { sum = Counter(); squares = Counter(); @@ -1722,16 +1718,12 @@ class DistBase : public InfoAccess { public: typedef Stor Storage; - /** Define the params of the storage class. */ - typedef typename Storage::Params Params; + typedef typename Stor::Params Params; protected: /** The storage for this stat. */ char storage[sizeof(Storage)] __attribute__ ((aligned (8))); - /** The parameters for this stat. */ - Params params; - protected: /** * Retrieve the storage. @@ -1756,7 +1748,7 @@ class DistBase : public InfoAccess void doInit() { - new (storage) Storage(params); + new (storage) Storage(info()); setInit(); } @@ -1770,24 +1762,24 @@ class DistBase : public InfoAccess * @param n The number of times to add it, defaults to 1. */ template - void sample(const U &v, int n = 1) { data()->sample(v, n, params); } + void sample(const U &v, int n = 1) { data()->sample(v, n); } /** * Return the number of entries in this stat. * @return The number of entries. */ - size_type size() const { return data()->size(params); } + size_type size() const { return data()->size(); } /** * Return true if no samples have been added. * @return True if there haven't been any samples. */ - bool zero() const { return data()->zero(params); } + bool zero() const { return data()->zero(); } void update(DistInfoBase *base) { base->data.fancy = Storage::fancy; - data()->update(&(base->data), params); + data()->update(info(), base->data); } /** @@ -1796,7 +1788,7 @@ class DistBase : public InfoAccess void reset() { - data()->reset(); + data()->reset(info()); } bool @@ -1814,14 +1806,13 @@ class VectorDistBase : public InfoAccess { public: typedef Stor Storage; - typedef typename Storage::Params Params; + typedef typename Stor::Params Params; typedef DistProxy > Proxy; friend class DistProxy >; protected: Storage *storage; size_type _size; - Params params; protected: Storage * @@ -1847,7 +1838,7 @@ class VectorDistBase : public InfoAccess storage = reinterpret_cast(ptr); for (off_type i = 0; i < _size; ++i) - new (&storage[i]) Storage(params); + new (&storage[i]) Storage(info()); setInit(); } @@ -1881,7 +1872,7 @@ class VectorDistBase : public InfoAccess return false; #if 0 for (off_type i = 0; i < size(); ++i) - if (!data(i)->zero(params)) + if (!data(i)->zero()) return false; return true; #endif @@ -1894,7 +1885,7 @@ class VectorDistBase : public InfoAccess reset() { for (off_type i = 0; i < size(); ++i) - data(i)->reset(); + data(i)->reset(info()); } bool @@ -1910,7 +1901,7 @@ class VectorDistBase : public InfoAccess base->data.resize(size); for (off_type i = 0; i < size; ++i) { base->data[i].fancy = Storage::fancy; - data(i)->update(&(base->data[i]), params); + data(i)->update(info(), base->data[i]); } } }; @@ -1948,7 +1939,7 @@ class DistProxy void sample(const U &v, int n = 1) { - data()->sample(v, n, stat->params); + data()->sample(v, n); } size_type @@ -1960,7 +1951,7 @@ class DistProxy bool zero() const { - return data()->zero(stat->params); + return data()->zero(); } /** @@ -1984,7 +1975,7 @@ VectorDistBase::total(off_type index) const { Result total = 0; for (off_type i = 0; i < x_size(); ++i) - total += data(i)->result(stat->params); + total += data(i)->result(); } #endif @@ -2528,8 +2519,6 @@ class Distribution public: /** Base implementation. */ typedef DistBase Base; - /** The Parameter type. */ - typedef DistStor::Params Params; public: /** @@ -2542,10 +2531,12 @@ class Distribution Distribution & init(Counter min, Counter max, Counter bkt) { - this->params.min = min; - this->params.max = max; - this->params.bucket_size = bkt; - this->params.size = (size_type)rint((max - min) / bkt + 1.0); + DistStor::Params *params = new DistStor::Params; + params->min = min; + params->max = max; + params->bucket_size = bkt; + params->buckets = (size_type)rint((max - min) / bkt + 1.0); + this->setParams(params); this->doInit(); return *this; } @@ -2562,8 +2553,6 @@ class StandardDeviation public: /** The base implementation */ typedef DistBase Base; - /** The parameter type. */ - typedef DistStor::Params Params; public: /** @@ -2586,8 +2575,6 @@ class AverageDeviation public: /** The base implementation */ typedef DistBase Base; - /** The parameter type. */ - typedef DistStor::Params Params; public: /** @@ -2612,8 +2599,6 @@ class VectorDistribution public: /** The base implementation */ typedef VectorDistBase Base; - /** The parameter type. */ - typedef DistStor::Params Params; public: /** @@ -2627,10 +2612,12 @@ class VectorDistribution VectorDistribution & init(size_type size, Counter min, Counter max, Counter bkt) { - this->params.min = min; - this->params.max = max; - this->params.bucket_size = bkt; - this->params.size = rint((max - min) / bkt + 1.0); + DistStor::Params *params = new DistStor::Params; + params->min = min; + params->max = max; + params->bucket_size = bkt; + params->buckets = rint((max - min) / bkt + 1.0); + this->setParams(params); this->doInit(size); return *this; } @@ -2649,8 +2636,6 @@ class VectorStandardDeviation public: /** The base implementation */ typedef VectorDistBase Base; - /** The parameter type. */ - typedef DistStor::Params Params; public: /** @@ -2679,8 +2664,6 @@ class VectorAverageDeviation public: /** The base implementation */ typedef VectorDistBase Base; - /** The parameter type. */ - typedef DistStor::Params Params; public: /** diff --git a/src/base/stats/mysql.cc b/src/base/stats/mysql.cc index 42464993d..72f31240d 100644 --- a/src/base/stats/mysql.cc +++ b/src/base/stats/mysql.cc @@ -584,10 +584,11 @@ MySql::configure(const DistInfoBase &info) return; if (!info.data.fancy) { - stat.size = info.data.size; - stat.min = info.data.min; - stat.max = info.data.max; - stat.bktsize = info.data.bucket_size; + const Params *params = safe_cast(info.storageParams); + stat.size = params->buckets; + stat.min = params->min; + stat.max = params->max; + stat.bktsize = params->bucket_size; } insert(info.id, stat.setup(run)); } @@ -599,10 +600,11 @@ MySql::configure(const VectorDistInfoBase &info) return; if (!info.data[0].fancy) { - stat.size = info.data[0].size; - stat.min = info.data[0].min; - stat.max = info.data[0].max; - stat.bktsize = info.data[0].bucket_size; + const Params *params = safe_cast(info.storageParams); + stat.size = params->buckets; + stat.min = params->min; + stat.max = params->max; + stat.bktsize = params->bucket_size; } uint16_t statid = stat.setup(run); diff --git a/src/base/stats/text.cc b/src/base/stats/text.cc index 14300a0f8..3a00620c7 100644 --- a/src/base/stats/text.cc +++ b/src/base/stats/text.cc @@ -673,12 +673,18 @@ Text::visit(const DistInfoBase &info) print.squares = data.squares; print.samples = data.samples; - print.min = data.min; - print.max = data.max; - print.bucket_size = data.bucket_size; - print.size = data.size; print.fancy = data.fancy; + if (!data.fancy) { + const DistStor::Params *params = + safe_cast(info.storageParams); + + print.min = params->min; + print.max = params->max; + print.bucket_size = params->bucket_size; + print.size = params->buckets; + } + print(*stream); } @@ -710,11 +716,16 @@ Text::visit(const VectorDistInfoBase &info) print.squares = info.data[i].squares; print.samples = info.data[i].samples; - print.min = info.data[i].min; - print.max = info.data[i].max; - print.bucket_size = info.data[i].bucket_size; - print.size = info.data[i].size; print.fancy = info.data[i].fancy; + if (!print.fancy) { + const DistStor::Params *params = + safe_cast(info.storageParams); + + print.min = params->min; + print.max = params->max; + print.bucket_size = params->bucket_size; + print.size = params->buckets; + } print(*stream); } -- cgit v1.2.3 From a1aba01a02a8c1261120de83d8fbfd6624f0cb17 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:15:34 -0800 Subject: CPU: Get rid of translate... functions from various interface classes. --- src/arch/x86/isa/microops/ldstop.isa | 13 +--- src/cpu/base_dyn_inst.hh | 56 +--------------- src/cpu/checker/cpu.cc | 55 +--------------- src/cpu/checker/cpu.hh | 4 -- src/cpu/checker/cpu_impl.hh | 2 +- src/cpu/inorder/cpu.hh | 18 ------ src/cpu/inorder/resources/tlb_unit.cc | 6 +- src/cpu/o3/cpu.hh | 18 ------ src/cpu/o3/fetch_impl.hh | 2 +- src/cpu/ozone/cpu.hh | 47 ++------------ src/cpu/ozone/front_end_impl.hh | 2 +- src/cpu/ozone/inorder_back_end.hh | 4 +- src/cpu/simple/atomic.cc | 117 +-------------------------------- src/cpu/simple/atomic.hh | 5 -- src/cpu/simple/base.cc | 2 +- src/cpu/simple/timing.cc | 118 ++++++++++++++-------------------- src/cpu/simple/timing.hh | 6 -- src/cpu/simple_thread.hh | 15 ----- src/mem/request.hh | 2 + 19 files changed, 73 insertions(+), 419 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/microops/ldstop.isa b/src/arch/x86/isa/microops/ldstop.isa index 8a0af14be..cdebe9613 100644 --- a/src/arch/x86/isa/microops/ldstop.isa +++ b/src/arch/x86/isa/microops/ldstop.isa @@ -454,7 +454,7 @@ let {{ Mem = Data; Base = merge(Base, EA - SegBase, addressSize); '''); - + defineMicroStoreOp('Cda', 'Mem = 0;', "Request::NO_ACCESS") iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp', {"code": "Data = merge(Data, EA, dataSize);", @@ -493,17 +493,6 @@ let {{ microopClasses["tia"] = TiaOp - iop = InstObjParams("cda", "Cda", 'X86ISA::LdStOp', - {"code": ''' - Addr paddr; - fault = xc->translateDataWriteAddr(EA, paddr, - dataSize, (1 << segment)); - ''', - "ea_code": calculateEA}) - header_output += MicroLeaDeclare.subst(iop) - decoder_output += MicroLdStOpConstructor.subst(iop) - exec_output += MicroLeaExecute.subst(iop) - class CdaOp(LdStOp): def __init__(self, segment, addr, disp = 0, dataSize="env.dataSize", addressSize="env.addressSize"): diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index f40616e54..f58bf7cf8 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -115,9 +115,6 @@ class BaseDynInst : public FastAlloc, public RefCounted template Fault read(Addr addr, T &data, unsigned flags); - Fault translateDataReadAddr(Addr vaddr, Addr &paddr, - int size, unsigned flags); - /** * Does a write to a given address. * @param data The data to be written. @@ -130,9 +127,6 @@ class BaseDynInst : public FastAlloc, public RefCounted Fault write(T data, Addr addr, unsigned flags, uint64_t *res); - Fault translateDataWriteAddr(Addr vaddr, Addr &paddr, - int size, unsigned flags); - void prefetch(Addr addr, unsigned flags); void writeHint(Addr addr, int size, unsigned flags); Fault copySrcTranslate(Addr src); @@ -856,29 +850,6 @@ class BaseDynInst : public FastAlloc, public RefCounted { thread->storeCondFailures = sc_failures; } }; -template -Fault -BaseDynInst::translateDataReadAddr(Addr vaddr, Addr &paddr, - int size, unsigned flags) -{ - if (traceData) { - traceData->setAddr(vaddr); - } - - reqMade = true; - Request *req = new Request(); - req->setVirt(asid, vaddr, size, flags, PC); - req->setThreadContext(thread->contextId(), threadNumber); - - fault = cpu->translateDataReadReq(req, thread); - - if (fault == NoFault) - paddr = req->getPaddr(); - - delete req; - return fault; -} - template template inline Fault @@ -889,7 +860,7 @@ BaseDynInst::read(Addr addr, T &data, unsigned flags) req->setVirt(asid, addr, sizeof(T), flags, this->PC); req->setThreadContext(thread->contextId(), threadNumber); - fault = cpu->translateDataReadReq(req, thread); + fault = cpu->dtb->translate(req, thread->getTC(), false); if (req->isUncacheable()) isUncacheable = true; @@ -930,29 +901,6 @@ BaseDynInst::read(Addr addr, T &data, unsigned flags) return fault; } -template -Fault -BaseDynInst::translateDataWriteAddr(Addr vaddr, Addr &paddr, - int size, unsigned flags) -{ - if (traceData) { - traceData->setAddr(vaddr); - } - - reqMade = true; - Request *req = new Request(); - req->setVirt(asid, vaddr, size, flags, PC); - req->setThreadContext(thread->contextId(), threadNumber); - - fault = cpu->translateDataWriteReq(req, thread); - - if (fault == NoFault) - paddr = req->getPaddr(); - - delete req; - return fault; -} - template template inline Fault @@ -968,7 +916,7 @@ BaseDynInst::write(T data, Addr addr, unsigned flags, uint64_t *res) req->setVirt(asid, addr, sizeof(T), flags, this->PC); req->setThreadContext(thread->contextId(), threadNumber); - fault = cpu->translateDataWriteReq(req, thread); + fault = cpu->dtb->translate(req, thread->getTC(), true); if (req->isUncacheable()) isUncacheable = true; diff --git a/src/cpu/checker/cpu.cc b/src/cpu/checker/cpu.cc index a6af98d66..e530e6014 100644 --- a/src/cpu/checker/cpu.cc +++ b/src/cpu/checker/cpu.cc @@ -159,7 +159,7 @@ CheckerCPU::read(Addr addr, T &data, unsigned flags) memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); // translate to physical address - translateDataReadReq(memReq); + dtb->translate(memReq, tc, false); PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); @@ -229,7 +229,7 @@ CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); // translate to physical address - thread->translateDataWriteReq(memReq); + dtb->translate(memReq, tc, true); // Can compare the write data and result only if it's cacheable, // not a store conditional, or is a store conditional that @@ -324,57 +324,6 @@ CheckerCPU::dbg_vtophys(Addr addr) } #endif // FULL_SYSTEM -bool -CheckerCPU::translateInstReq(Request *req) -{ -#if FULL_SYSTEM - return (thread->translateInstReq(req) == NoFault); -#else - thread->translateInstReq(req); - return true; -#endif -} - -void -CheckerCPU::translateDataReadReq(Request *req) -{ - thread->translateDataReadReq(req); - - if (req->getVaddr() != unverifiedReq->getVaddr()) { - warn("%lli: Request virtual addresses do not match! Inst: %#x, " - "checker: %#x", - curTick, unverifiedReq->getVaddr(), req->getVaddr()); - handleError(); - } - req->setPaddr(unverifiedReq->getPaddr()); - - if (checkFlags(req)) { - warn("%lli: Request flags do not match! Inst: %#x, checker: %#x", - curTick, unverifiedReq->getFlags(), req->getFlags()); - handleError(); - } -} - -void -CheckerCPU::translateDataWriteReq(Request *req) -{ - thread->translateDataWriteReq(req); - - if (req->getVaddr() != unverifiedReq->getVaddr()) { - warn("%lli: Request virtual addresses do not match! Inst: %#x, " - "checker: %#x", - curTick, unverifiedReq->getVaddr(), req->getVaddr()); - handleError(); - } - req->setPaddr(unverifiedReq->getPaddr()); - - if (checkFlags(req)) { - warn("%lli: Request flags do not match! Inst: %#x, checker: %#x", - curTick, unverifiedReq->getFlags(), req->getFlags()); - handleError(); - } -} - bool CheckerCPU::checkFlags(Request *req) { diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh index 5b3c4582c..0d3dddded 100644 --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@ -331,10 +331,6 @@ class CheckerCPU : public BaseCPU this->dtb->demapPage(vaddr, asn); } - bool translateInstReq(Request *req); - void translateDataWriteReq(Request *req); - void translateDataReadReq(Request *req); - #if FULL_SYSTEM Fault hwrei() { return thread->hwrei(); } void ev5_trap(Fault fault) { fault->invoke(tc); } diff --git a/src/cpu/checker/cpu_impl.hh b/src/cpu/checker/cpu_impl.hh index 0428e8806..e1ecc151c 100644 --- a/src/cpu/checker/cpu_impl.hh +++ b/src/cpu/checker/cpu_impl.hh @@ -155,7 +155,7 @@ Checker::verify(DynInstPtr &completed_inst) fetch_PC, thread->contextId(), inst->threadNumber); - bool succeeded = translateInstReq(memReq); + bool succeeded = itb->translate(memReq, thread); if (!succeeded) { if (inst->getFault() == NoFault) { diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh index 6c1cdc9dc..4a7dfb404 100644 --- a/src/cpu/inorder/cpu.hh +++ b/src/cpu/inorder/cpu.hh @@ -498,24 +498,6 @@ class InOrderCPU : public BaseCPU /** Debug function to print all instructions on the list. */ void dumpInsts(); - /** Translates instruction requestion in syscall emulation mode. */ - Fault translateInstReq(RequestPtr &req, Thread *thread) - { - return thread->getProcessPtr()->pTable->translate(req); - } - - /** Translates data read request in syscall emulation mode. */ - Fault translateDataReadReq(RequestPtr &req, Thread *thread) - { - return thread->getProcessPtr()->pTable->translate(req); - } - - /** Translates data write request in syscall emulation mode. */ - Fault translateDataWriteReq(RequestPtr &req, Thread *thread) - { - return thread->getProcessPtr()->pTable->translate(req); - } - /** Forwards an instruction read to the appropriate data * resource (indexes into Resource Pool thru "dataPortIdx") */ diff --git a/src/cpu/inorder/resources/tlb_unit.cc b/src/cpu/inorder/resources/tlb_unit.cc index 9b0decedb..4eeb4727b 100644 --- a/src/cpu/inorder/resources/tlb_unit.cc +++ b/src/cpu/inorder/resources/tlb_unit.cc @@ -98,7 +98,8 @@ TLBUnit::execute(int slot_idx) case FetchLookup: { tlb_req->fault = - this->cpu->translateInstReq(tlb_req->memReq, cpu->thread[tid]); + this->cpu->itb->translate(tlb_req->memReq, + cpu->thread[tid]->getTC()); if (tlb_req->fault != NoFault) { DPRINTF(Resource, "[tid:%i]: %s encountered while translating " @@ -128,7 +129,8 @@ TLBUnit::execute(int slot_idx) tid, seq_num, tlb_req->memReq->getVaddr()); tlb_req->fault = - this->cpu->translateInstReq(tlb_req->memReq, cpu->thread[tid]); + this->cpu->itb->translate(tlb_req->memReq, + cpu->thread[tid]->getTC()); if (tlb_req->fault != NoFault) { DPRINTF(Resource, "[tid:%i]: %s encountered while translating " diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index d14001d0d..683e4284f 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -279,24 +279,6 @@ class FullO3CPU : public BaseO3CPU this->dtb->demapPage(vaddr, asn); } - /** Translates instruction requestion. */ - Fault translateInstReq(RequestPtr &req, Thread *thread) - { - return this->itb->translate(req, thread->getTC()); - } - - /** Translates data read request. */ - Fault translateDataReadReq(RequestPtr &req, Thread *thread) - { - return this->dtb->translate(req, thread->getTC(), false); - } - - /** Translates data write request. */ - Fault translateDataWriteReq(RequestPtr &req, Thread *thread) - { - return this->dtb->translate(req, thread->getTC(), true); - } - /** Returns a specific port. */ Port *getPort(const std::string &if_name, int idx); diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index cff6db299..4beb34a85 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -599,7 +599,7 @@ DefaultFetch::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid memReq[tid] = mem_req; // Translate the instruction request. - fault = cpu->translateInstReq(mem_req, cpu->thread[tid]); + fault = cpu->itb->translate(mem_req, cpu->thread[tid]->getTC()); // In the case of faults, the fetch stage may need to stall and wait // for the ITB miss to be handled. diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index 55ad7b3fb..0eb4b31f7 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -415,59 +415,20 @@ class OzoneCPU : public BaseCPU void demapPage(Addr vaddr, uint64_t asn) { - itb->demap(vaddr, asn); - dtb->demap(vaddr, asn); + cpu->itb->demap(vaddr, asn); + cpu->dtb->demap(vaddr, asn); } void demapInstPage(Addr vaddr, uint64_t asn) { - itb->demap(vaddr, asn); + cpu->itb->demap(vaddr, asn); } void demapDataPage(Addr vaddr, uint64_t asn) { - dtb->demap(vaddr, asn); + cpu->dtb->demap(vaddr, asn); } -#if FULL_SYSTEM - /** Translates instruction requestion. */ - Fault translateInstReq(RequestPtr &req, OzoneThreadState *thread) - { - return itb->translate(req, thread->getTC()); - } - - /** Translates data read request. */ - Fault translateDataReadReq(RequestPtr &req, OzoneThreadState *thread) - { - return dtb->translate(req, thread->getTC(), false); - } - - /** Translates data write request. */ - Fault translateDataWriteReq(RequestPtr &req, OzoneThreadState *thread) - { - return dtb->translate(req, thread->getTC(), true); - } - -#else - /** Translates instruction requestion in syscall emulation mode. */ - Fault translateInstReq(RequestPtr &req, OzoneThreadState *thread) - { - return thread->getProcessPtr()->pTable->translate(req); - } - - /** Translates data read request in syscall emulation mode. */ - Fault translateDataReadReq(RequestPtr &req, OzoneThreadState *thread) - { - return thread->getProcessPtr()->pTable->translate(req); - } - - /** Translates data write request in syscall emulation mode. */ - Fault translateDataWriteReq(RequestPtr &req, OzoneThreadState *thread) - { - return thread->getProcessPtr()->pTable->translate(req); - } -#endif - /** CPU read function, forwards read to LSQ. */ template Fault read(Request *req, T &data, int load_idx) diff --git a/src/cpu/ozone/front_end_impl.hh b/src/cpu/ozone/front_end_impl.hh index b1e131115..2a9b107d4 100644 --- a/src/cpu/ozone/front_end_impl.hh +++ b/src/cpu/ozone/front_end_impl.hh @@ -480,7 +480,7 @@ FrontEnd::fetchCacheLine() PC, cpu->thread->contextId()); // Translate the instruction request. - fault = cpu->translateInstReq(memReq, thread); + fault = cpu->itb->translate(memReq, thread); // Now do the timing access to see whether or not the instruction // exists within the cache. diff --git a/src/cpu/ozone/inorder_back_end.hh b/src/cpu/ozone/inorder_back_end.hh index c23d801ba..8850fa737 100644 --- a/src/cpu/ozone/inorder_back_end.hh +++ b/src/cpu/ozone/inorder_back_end.hh @@ -204,7 +204,7 @@ InorderBackEnd::read(Addr addr, T &data, unsigned flags) memReq->reset(addr, sizeof(T), flags); // translate to physical address - Fault fault = cpu->translateDataReadReq(memReq); + Fault fault = cpu->dtb->translate(memReq, thread->getTC(), false); // if we have a cache, do cache access too if (fault == NoFault && dcacheInterface) { @@ -245,7 +245,7 @@ InorderBackEnd::write(T data, Addr addr, unsigned flags, uint64_t *res) memReq->reset(addr, sizeof(T), flags); // translate to physical address - Fault fault = cpu->translateDataWriteReq(memReq); + Fault fault = cpu->dtb->translate(memReq, thread->getTC(), true); if (fault == NoFault && dcacheInterface) { memReq->cmd = Write; diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index feb8a7fc5..cd07a9fe3 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -314,7 +314,7 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags) req->setVirt(0, addr, dataSize, flags, thread->readPC()); // translate to physical address - Fault fault = thread->translateDataReadReq(req); + Fault fault = thread->dtb->translate(req, tc, false); // Now do the access. if (fault == NoFault) { @@ -370,61 +370,6 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags) } } -Fault -AtomicSimpleCPU::translateDataReadAddr(Addr vaddr, Addr & paddr, - int size, unsigned flags) -{ - // use the CPU's statically allocated read request and packet objects - Request *req = &data_read_req; - - if (traceData) { - traceData->setAddr(vaddr); - } - - //The block size of our peer. - int blockSize = dcachePort.peerBlockSize(); - //The size of the data we're trying to read. - int dataSize = size; - - bool firstTimeThrough = true; - - //The address of the second part of this access if it needs to be split - //across a cache line boundary. - Addr secondAddr = roundDown(vaddr + dataSize - 1, blockSize); - - if(secondAddr > vaddr) - dataSize = secondAddr - vaddr; - - while(1) { - req->setVirt(0, vaddr, dataSize, flags, thread->readPC()); - - // translate to physical address - Fault fault = thread->translateDataReadReq(req); - - //If there's a fault, return it - if (fault != NoFault) - return fault; - - if (firstTimeThrough) { - paddr = req->getPaddr(); - firstTimeThrough = false; - } - - //If we don't need to access a second cache line, stop now. - if (secondAddr <= vaddr) - return fault; - - /* - * Set up for accessing the second cache line. - */ - - //Adjust the size to get the remaining bytes. - dataSize = vaddr + size - secondAddr; - //And access the right address. - vaddr = secondAddr; - } -} - #ifndef DOXYGEN_SHOULD_SKIP_THIS template @@ -507,7 +452,7 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) req->setVirt(0, addr, dataSize, flags, thread->readPC()); // translate to physical address - Fault fault = thread->translateDataWriteReq(req); + Fault fault = thread->dtb->translate(req, tc, true); // Now do the access. if (fault == NoFault) { @@ -586,64 +531,6 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) } } -Fault -AtomicSimpleCPU::translateDataWriteAddr(Addr vaddr, Addr &paddr, - int size, unsigned flags) -{ - // use the CPU's statically allocated write request and packet objects - Request *req = &data_write_req; - - if (traceData) { - traceData->setAddr(vaddr); - } - - //The block size of our peer. - int blockSize = dcachePort.peerBlockSize(); - - //The address of the second part of this access if it needs to be split - //across a cache line boundary. - Addr secondAddr = roundDown(vaddr + size - 1, blockSize); - - //The size of the data we're trying to read. - int dataSize = size; - - bool firstTimeThrough = true; - - if(secondAddr > vaddr) - dataSize = secondAddr - vaddr; - - dcache_latency = 0; - - while(1) { - req->setVirt(0, vaddr, dataSize, flags, thread->readPC()); - - // translate to physical address - Fault fault = thread->translateDataWriteReq(req); - - //If there's a fault or we don't need to access a second cache line, - //stop now. - if (fault != NoFault) - return fault; - - if (firstTimeThrough) { - paddr = req->getPaddr(); - firstTimeThrough = false; - } - - if (secondAddr <= vaddr) - return fault; - - /* - * Set up for accessing the second cache line. - */ - - //Adjust the size to get the remaining bytes. - dataSize = vaddr + size - secondAddr; - //And access the right address. - vaddr = secondAddr; - } -} - #ifndef DOXYGEN_SHOULD_SKIP_THIS diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh index 24400df22..190097637 100644 --- a/src/cpu/simple/atomic.hh +++ b/src/cpu/simple/atomic.hh @@ -136,11 +136,6 @@ class AtomicSimpleCPU : public BaseSimpleCPU template Fault write(T data, Addr addr, unsigned flags, uint64_t *res); - Fault translateDataReadAddr(Addr vaddr, Addr &paddr, - int size, unsigned flags); - Fault translateDataWriteAddr(Addr vaddr, Addr &paddr, - int size, unsigned flags); - /** * Print state of address in memory system via PrintReq (for * debugging). diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index b1a77247f..f9fa8d835 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -347,7 +347,7 @@ BaseSimpleCPU::setupFetchRequest(Request *req) Addr fetchPC = (threadPC & PCMask) + fetchOffset; req->setVirt(0, fetchPC, sizeof(MachInst), 0, threadPC); - Fault fault = thread->translateInstReq(req); + Fault fault = thread->itb->translate(req, tc); return fault; } diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 5da08db47..844eccc75 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -275,6 +275,7 @@ TimingSimpleCPU::buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2, if ((fault = buildPacket(pkt1, req1, read)) != NoFault || (fault = buildPacket(pkt2, req2, read)) != NoFault) { delete req; + delete req1; delete pkt1; req = NULL; pkt1 = NULL; @@ -286,6 +287,15 @@ TimingSimpleCPU::buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2, req->setPhys(req1->getPaddr(), req->getSize(), req1->getFlags()); PacketPtr pkt = new Packet(req, pkt1->cmd.responseCommand(), Packet::Broadcast); + if (req->getFlags().isSet(Request::NO_ACCESS)) { + delete req1; + delete pkt1; + delete req2; + delete pkt2; + pkt1 = pkt; + pkt2 = NULL; + return NoFault; + } pkt->dataDynamic(data); pkt1->dataStatic(data); @@ -304,8 +314,7 @@ TimingSimpleCPU::buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2, Fault TimingSimpleCPU::buildPacket(PacketPtr &pkt, RequestPtr &req, bool read) { - Fault fault = read ? thread->translateDataReadReq(req) : - thread->translateDataWriteReq(req); + Fault fault = thread->dtb->translate(req, tc, !read); MemCmd cmd; if (fault != NoFault) { delete req; @@ -348,9 +357,13 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) if (split_addr > addr) { PacketPtr pkt1, pkt2; - this->buildSplitPacket(pkt1, pkt2, req, + Fault fault = this->buildSplitPacket(pkt1, pkt2, req, split_addr, (uint8_t *)(new T), true); - if (handleReadPacket(pkt1)) { + if (fault != NoFault) + return fault; + if (req->getFlags().isSet(Request::NO_ACCESS)) { + dcache_pkt = pkt1; + } else if (handleReadPacket(pkt1)) { SplitFragmentSenderState * send_state = dynamic_cast(pkt1->senderState); send_state->clearFromParent(); @@ -365,9 +378,12 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) if (fault != NoFault) { return fault; } - pkt->dataDynamic(new T); - - handleReadPacket(pkt); + if (req->getFlags().isSet(Request::NO_ACCESS)) { + dcache_pkt = pkt; + } else { + pkt->dataDynamic(new T); + handleReadPacket(pkt); + } } if (traceData) { @@ -382,26 +398,6 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) return NoFault; } -Fault -TimingSimpleCPU::translateDataReadAddr(Addr vaddr, Addr &paddr, - int size, unsigned flags) -{ - Request *req = - new Request(0, vaddr, size, flags, thread->readPC(), _cpuId, 0); - - if (traceData) { - traceData->setAddr(vaddr); - } - - Fault fault = thread->translateDataWriteReq(req); - - if (fault == NoFault) - paddr = req->getPaddr(); - - delete req; - return fault; -} - #ifndef DOXYGEN_SHOULD_SKIP_THIS template @@ -497,15 +493,19 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) if (fault != NoFault) return fault; dcache_pkt = pkt1; - if (handleWritePacket()) { - SplitFragmentSenderState * send_state = - dynamic_cast(pkt1->senderState); - send_state->clearFromParent(); - dcache_pkt = pkt2; - if (handleReadPacket(pkt2)) { - send_state = - dynamic_cast(pkt1->senderState); + if (!req->getFlags().isSet(Request::NO_ACCESS)) { + if (handleWritePacket()) { + SplitFragmentSenderState * send_state = + dynamic_cast( + pkt1->senderState); send_state->clearFromParent(); + dcache_pkt = pkt2; + if (handleReadPacket(pkt2)) { + send_state = + dynamic_cast( + pkt1->senderState); + send_state->clearFromParent(); + } } } } else { @@ -515,21 +515,23 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) if (fault != NoFault) return fault; - if (req->isLocked()) { - do_access = TheISA::handleLockedWrite(thread, req); - } else if (req->isCondSwap()) { - assert(res); - req->setExtraData(*res); - } + if (!req->getFlags().isSet(Request::NO_ACCESS)) { + if (req->isLocked()) { + do_access = TheISA::handleLockedWrite(thread, req); + } else if (req->isCondSwap()) { + assert(res); + req->setExtraData(*res); + } - dcache_pkt->allocate(); - if (req->isMmapedIpr()) - dcache_pkt->set(htog(data)); - else - dcache_pkt->set(data); + dcache_pkt->allocate(); + if (req->isMmapedIpr()) + dcache_pkt->set(htog(data)); + else + dcache_pkt->set(data); - if (do_access) - handleWritePacket(); + if (do_access) + handleWritePacket(); + } } if (traceData) { @@ -546,26 +548,6 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) return NoFault; } -Fault -TimingSimpleCPU::translateDataWriteAddr(Addr vaddr, Addr &paddr, - int size, unsigned flags) -{ - Request *req = - new Request(0, vaddr, size, flags, thread->readPC(), _cpuId, 0); - - if (traceData) { - traceData->setAddr(vaddr); - } - - Fault fault = thread->translateDataWriteReq(req); - - if (fault == NoFault) - paddr = req->getPaddr(); - - delete req; - return fault; -} - #ifndef DOXYGEN_SHOULD_SKIP_THIS template diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index c305d0361..0a639a627 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -224,15 +224,9 @@ class TimingSimpleCPU : public BaseSimpleCPU template Fault read(Addr addr, T &data, unsigned flags); - Fault translateDataReadAddr(Addr vaddr, Addr &paddr, - int size, unsigned flags); - template Fault write(T data, Addr addr, unsigned flags, uint64_t *res); - Fault translateDataWriteAddr(Addr vaddr, Addr &paddr, - int size, unsigned flags); - void fetch(); void completeIfetch(PacketPtr ); void completeDataAccess(PacketPtr ); diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index 678bb42bb..c2ddeca06 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -148,21 +148,6 @@ class SimpleThread : public ThreadState */ ThreadContext *getTC() { return tc; } - Fault translateInstReq(RequestPtr &req) - { - return itb->translate(req, tc); - } - - Fault translateDataReadReq(RequestPtr &req) - { - return dtb->translate(req, tc, false); - } - - Fault translateDataWriteReq(RequestPtr &req) - { - return dtb->translate(req, tc, true); - } - void demapPage(Addr vaddr, uint64_t asn) { itb->demapPage(vaddr, asn); diff --git a/src/mem/request.hh b/src/mem/request.hh index 761405aa6..dde68ca37 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -73,6 +73,8 @@ class Request : public FastAlloc static const FlagsType UNCACHEABLE = 0x00001000; /** The request should not cause a page fault. */ static const FlagsType NO_FAULT = 0x00002000; + /** The request should not cause a memory access. */ + static const FlagsType NO_ACCESS = 0x00004000; /** The request should be prefetched into the exclusive state. */ static const FlagsType PF_EXCLUSIVE = 0x00010000; /** The request should be marked as LRU. */ -- cgit v1.2.3 From 5605079b1f20bc7f6a4a80c8d1e4daabe7125270 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:15:44 -0800 Subject: ISA: Replace the translate functions in the TLBs with translateAtomic. --- src/arch/alpha/tlb.cc | 4 ++-- src/arch/alpha/tlb.hh | 4 ++-- src/arch/mips/tlb.cc | 4 ++-- src/arch/mips/tlb.hh | 5 +++-- src/arch/sparc/tlb.cc | 4 ++-- src/arch/sparc/tlb.hh | 4 ++-- src/arch/x86/tlb.cc | 11 ++++++----- src/arch/x86/tlb.hh | 6 +++--- src/cpu/base_dyn_inst.hh | 4 ++-- src/cpu/checker/cpu.cc | 4 ++-- src/cpu/checker/cpu_impl.hh | 2 +- src/cpu/inorder/resources/tlb_unit.cc | 4 ++-- src/cpu/o3/fetch_impl.hh | 2 +- src/cpu/ozone/front_end_impl.hh | 2 +- src/cpu/ozone/inorder_back_end.hh | 4 ++-- src/cpu/simple/atomic.cc | 4 ++-- src/cpu/simple/base.cc | 2 +- src/cpu/simple/timing.cc | 2 +- src/cpu/simple_thread.hh | 2 +- src/sim/tlb.cc | 2 +- src/sim/tlb.hh | 2 +- 21 files changed, 40 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc index be02293d6..82d410987 100644 --- a/src/arch/alpha/tlb.cc +++ b/src/arch/alpha/tlb.cc @@ -317,7 +317,7 @@ ITB::regStats() } Fault -ITB::translate(RequestPtr &req, ThreadContext *tc) +ITB::translateAtomic(RequestPtr &req, ThreadContext *tc) { //If this is a pal pc, then set PHYSICAL if (FULL_SYSTEM && PcPAL(req->getPC())) @@ -479,7 +479,7 @@ DTB::regStats() } Fault -DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) +DTB::translateAtomic(RequestPtr &req, ThreadContext *tc, bool write) { Addr pc = tc->readPC(); diff --git a/src/arch/alpha/tlb.hh b/src/arch/alpha/tlb.hh index 9267aa573..f5d2dbca9 100644 --- a/src/arch/alpha/tlb.hh +++ b/src/arch/alpha/tlb.hh @@ -131,7 +131,7 @@ class ITB : public TLB ITB(const Params *p); virtual void regStats(); - Fault translate(RequestPtr &req, ThreadContext *tc); + Fault translateAtomic(RequestPtr &req, ThreadContext *tc); }; class DTB : public TLB @@ -155,7 +155,7 @@ class DTB : public TLB DTB(const Params *p); virtual void regStats(); - Fault translate(RequestPtr &req, ThreadContext *tc, bool write); + Fault translateAtomic(RequestPtr &req, ThreadContext *tc, bool write); }; } // namespace AlphaISA diff --git a/src/arch/mips/tlb.cc b/src/arch/mips/tlb.cc index e91da4eea..db21c7919 100644 --- a/src/arch/mips/tlb.cc +++ b/src/arch/mips/tlb.cc @@ -310,7 +310,7 @@ TLB::regStats() } Fault -ITB::translate(RequestPtr &req, ThreadContext *tc) +ITB::translateAtomic(RequestPtr &req, ThreadContext *tc) { #if !FULL_SYSTEM Process * p = tc->getProcessPtr(); @@ -427,7 +427,7 @@ ITB::translate(RequestPtr &req, ThreadContext *tc) } Fault -DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) +DTB::translateAtomic(RequestPtr &req, ThreadContext *tc, bool write) { #if !FULL_SYSTEM Process * p = tc->getProcessPtr(); diff --git a/src/arch/mips/tlb.hh b/src/arch/mips/tlb.hh index 4a8fc32ac..acb393116 100644 --- a/src/arch/mips/tlb.hh +++ b/src/arch/mips/tlb.hh @@ -145,7 +145,7 @@ class ITB : public TLB { typedef MipsTLBParams Params; ITB(const Params *p); - Fault translate(RequestPtr &req, ThreadContext *tc); + Fault translateAtomic(RequestPtr &req, ThreadContext *tc); }; class DTB : public TLB { @@ -153,7 +153,8 @@ class DTB : public TLB { typedef MipsTLBParams Params; DTB(const Params *p); - Fault translate(RequestPtr &req, ThreadContext *tc, bool write = false); + Fault translateAtomic(RequestPtr &req, ThreadContext *tc, + bool write = false); }; class UTB : public ITB, public DTB { diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc index 9e5230674..683d916df 100644 --- a/src/arch/sparc/tlb.cc +++ b/src/arch/sparc/tlb.cc @@ -436,7 +436,7 @@ DTB::writeSfsr(Addr a, bool write, ContextType ct, } Fault -ITB::translate(RequestPtr &req, ThreadContext *tc) +ITB::translateAtomic(RequestPtr &req, ThreadContext *tc) { uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA); @@ -549,7 +549,7 @@ ITB::translate(RequestPtr &req, ThreadContext *tc) } Fault -DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) +DTB::translateAtomic(RequestPtr &req, ThreadContext *tc, bool write) { /* * @todo this could really use some profiling and fixing to make diff --git a/src/arch/sparc/tlb.hh b/src/arch/sparc/tlb.hh index 504a40cbb..d563772e6 100644 --- a/src/arch/sparc/tlb.hh +++ b/src/arch/sparc/tlb.hh @@ -177,7 +177,7 @@ class ITB : public TLB cacheEntry = NULL; } - Fault translate(RequestPtr &req, ThreadContext *tc); + Fault translateAtomic(RequestPtr &req, ThreadContext *tc); private: void writeSfsr(bool write, ContextType ct, bool se, FaultTypes ft, int asi); @@ -199,7 +199,7 @@ class DTB : public TLB cacheEntry[1] = NULL; } - Fault translate(RequestPtr &req, ThreadContext *tc, bool write); + Fault translateAtomic(RequestPtr &req, ThreadContext *tc, bool write); #if FULL_SYSTEM Tick doMmuRegRead(ThreadContext *tc, Packet *pkt); Tick doMmuRegWrite(ThreadContext *tc, Packet *pkt); diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index 34829848c..33017a6aa 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -190,7 +190,8 @@ TLB::demapPage(Addr va, uint64_t asn) template Fault -TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) +TLB::translateAtomic(RequestPtr &req, ThreadContext *tc, + bool write, bool execute) { Addr vaddr = req->getVaddr(); DPRINTF(TLB, "Translating vaddr %#x.\n", vaddr); @@ -662,15 +663,15 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute) }; Fault -DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) +DTB::translateAtomic(RequestPtr &req, ThreadContext *tc, bool write) { - return TLB::translate(req, tc, write, false); + return TLB::translateAtomic(req, tc, write, false); } Fault -ITB::translate(RequestPtr &req, ThreadContext *tc) +ITB::translateAtomic(RequestPtr &req, ThreadContext *tc) { - return TLB::translate(req, tc, false, true); + return TLB::translateAtomic(req, tc, false, true); } #if FULL_SYSTEM diff --git a/src/arch/x86/tlb.hh b/src/arch/x86/tlb.hh index 56d635a90..91bb4a761 100644 --- a/src/arch/x86/tlb.hh +++ b/src/arch/x86/tlb.hh @@ -138,7 +138,7 @@ namespace X86ISA EntryList entryList; template - Fault translate(RequestPtr &req, ThreadContext *tc, + Fault translateAtomic(RequestPtr &req, ThreadContext *tc, bool write, bool execute); public: @@ -159,7 +159,7 @@ namespace X86ISA _allowNX = false; } - Fault translate(RequestPtr &req, ThreadContext *tc); + Fault translateAtomic(RequestPtr &req, ThreadContext *tc); friend class DTB; }; @@ -172,7 +172,7 @@ namespace X86ISA { _allowNX = true; } - Fault translate(RequestPtr &req, ThreadContext *tc, bool write); + Fault translateAtomic(RequestPtr &req, ThreadContext *tc, bool write); #if FULL_SYSTEM Tick doMmuRegRead(ThreadContext *tc, Packet *pkt); Tick doMmuRegWrite(ThreadContext *tc, Packet *pkt); diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index f58bf7cf8..41c57cf39 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -860,7 +860,7 @@ BaseDynInst::read(Addr addr, T &data, unsigned flags) req->setVirt(asid, addr, sizeof(T), flags, this->PC); req->setThreadContext(thread->contextId(), threadNumber); - fault = cpu->dtb->translate(req, thread->getTC(), false); + fault = cpu->dtb->translateAtomic(req, thread->getTC(), false); if (req->isUncacheable()) isUncacheable = true; @@ -916,7 +916,7 @@ BaseDynInst::write(T data, Addr addr, unsigned flags, uint64_t *res) req->setVirt(asid, addr, sizeof(T), flags, this->PC); req->setThreadContext(thread->contextId(), threadNumber); - fault = cpu->dtb->translate(req, thread->getTC(), true); + fault = cpu->dtb->translateAtomic(req, thread->getTC(), true); if (req->isUncacheable()) isUncacheable = true; diff --git a/src/cpu/checker/cpu.cc b/src/cpu/checker/cpu.cc index e530e6014..14777bc12 100644 --- a/src/cpu/checker/cpu.cc +++ b/src/cpu/checker/cpu.cc @@ -159,7 +159,7 @@ CheckerCPU::read(Addr addr, T &data, unsigned flags) memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); // translate to physical address - dtb->translate(memReq, tc, false); + dtb->translateAtomic(memReq, tc, false); PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); @@ -229,7 +229,7 @@ CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); // translate to physical address - dtb->translate(memReq, tc, true); + dtb->translateAtomic(memReq, tc, true); // Can compare the write data and result only if it's cacheable, // not a store conditional, or is a store conditional that diff --git a/src/cpu/checker/cpu_impl.hh b/src/cpu/checker/cpu_impl.hh index e1ecc151c..26571ed68 100644 --- a/src/cpu/checker/cpu_impl.hh +++ b/src/cpu/checker/cpu_impl.hh @@ -155,7 +155,7 @@ Checker::verify(DynInstPtr &completed_inst) fetch_PC, thread->contextId(), inst->threadNumber); - bool succeeded = itb->translate(memReq, thread); + bool succeeded = itb->translateAtomic(memReq, thread); if (!succeeded) { if (inst->getFault() == NoFault) { diff --git a/src/cpu/inorder/resources/tlb_unit.cc b/src/cpu/inorder/resources/tlb_unit.cc index 4eeb4727b..321ac90f8 100644 --- a/src/cpu/inorder/resources/tlb_unit.cc +++ b/src/cpu/inorder/resources/tlb_unit.cc @@ -98,7 +98,7 @@ TLBUnit::execute(int slot_idx) case FetchLookup: { tlb_req->fault = - this->cpu->itb->translate(tlb_req->memReq, + this->cpu->itb->translateAtomic(tlb_req->memReq, cpu->thread[tid]->getTC()); if (tlb_req->fault != NoFault) { @@ -129,7 +129,7 @@ TLBUnit::execute(int slot_idx) tid, seq_num, tlb_req->memReq->getVaddr()); tlb_req->fault = - this->cpu->itb->translate(tlb_req->memReq, + this->cpu->itb->translateAtomic(tlb_req->memReq, cpu->thread[tid]->getTC()); if (tlb_req->fault != NoFault) { diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 4beb34a85..06df46c2b 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -599,7 +599,7 @@ DefaultFetch::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid memReq[tid] = mem_req; // Translate the instruction request. - fault = cpu->itb->translate(mem_req, cpu->thread[tid]->getTC()); + fault = cpu->itb->translateAtomic(mem_req, cpu->thread[tid]->getTC()); // In the case of faults, the fetch stage may need to stall and wait // for the ITB miss to be handled. diff --git a/src/cpu/ozone/front_end_impl.hh b/src/cpu/ozone/front_end_impl.hh index 2a9b107d4..6b47ef539 100644 --- a/src/cpu/ozone/front_end_impl.hh +++ b/src/cpu/ozone/front_end_impl.hh @@ -480,7 +480,7 @@ FrontEnd::fetchCacheLine() PC, cpu->thread->contextId()); // Translate the instruction request. - fault = cpu->itb->translate(memReq, thread); + fault = cpu->itb->translateAtomic(memReq, thread); // Now do the timing access to see whether or not the instruction // exists within the cache. diff --git a/src/cpu/ozone/inorder_back_end.hh b/src/cpu/ozone/inorder_back_end.hh index 8850fa737..0840591e0 100644 --- a/src/cpu/ozone/inorder_back_end.hh +++ b/src/cpu/ozone/inorder_back_end.hh @@ -204,7 +204,7 @@ InorderBackEnd::read(Addr addr, T &data, unsigned flags) memReq->reset(addr, sizeof(T), flags); // translate to physical address - Fault fault = cpu->dtb->translate(memReq, thread->getTC(), false); + Fault fault = cpu->dtb->translateAtomic(memReq, thread->getTC(), false); // if we have a cache, do cache access too if (fault == NoFault && dcacheInterface) { @@ -245,7 +245,7 @@ InorderBackEnd::write(T data, Addr addr, unsigned flags, uint64_t *res) memReq->reset(addr, sizeof(T), flags); // translate to physical address - Fault fault = cpu->dtb->translate(memReq, thread->getTC(), true); + Fault fault = cpu->dtb->translateAtomic(memReq, thread->getTC(), true); if (fault == NoFault && dcacheInterface) { memReq->cmd = Write; diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index cd07a9fe3..7a1cf71c4 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -314,7 +314,7 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags) req->setVirt(0, addr, dataSize, flags, thread->readPC()); // translate to physical address - Fault fault = thread->dtb->translate(req, tc, false); + Fault fault = thread->dtb->translateAtomic(req, tc, false); // Now do the access. if (fault == NoFault) { @@ -452,7 +452,7 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) req->setVirt(0, addr, dataSize, flags, thread->readPC()); // translate to physical address - Fault fault = thread->dtb->translate(req, tc, true); + Fault fault = thread->dtb->translateAtomic(req, tc, true); // Now do the access. if (fault == NoFault) { diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index f9fa8d835..ddeb9a7c8 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -347,7 +347,7 @@ BaseSimpleCPU::setupFetchRequest(Request *req) Addr fetchPC = (threadPC & PCMask) + fetchOffset; req->setVirt(0, fetchPC, sizeof(MachInst), 0, threadPC); - Fault fault = thread->itb->translate(req, tc); + Fault fault = thread->itb->translateAtomic(req, tc); return fault; } diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 844eccc75..65222266e 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -314,7 +314,7 @@ TimingSimpleCPU::buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2, Fault TimingSimpleCPU::buildPacket(PacketPtr &pkt, RequestPtr &req, bool read) { - Fault fault = thread->dtb->translate(req, tc, !read); + Fault fault = thread->dtb->translateAtomic(req, tc, !read); MemCmd cmd; if (fault != NoFault) { delete req; diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index c2ddeca06..4eba493c3 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -139,7 +139,7 @@ class SimpleThread : public ThreadState /*************************************************************** * SimpleThread functions to provide CPU with access to various - * state, and to provide address translation methods. + * state. **************************************************************/ /** Returns the pointer to this SimpleThread's ThreadContext. Used diff --git a/src/sim/tlb.cc b/src/sim/tlb.cc index 7292a69e0..f7b57cbbc 100644 --- a/src/sim/tlb.cc +++ b/src/sim/tlb.cc @@ -34,7 +34,7 @@ #include "sim/tlb.hh" Fault -GenericTLB::translate(RequestPtr req, ThreadContext * tc, bool) +GenericTLB::translateAtomic(RequestPtr req, ThreadContext * tc, bool) { #if FULL_SYSTEM panic("Generic translation shouldn't be used in full system mode.\n"); diff --git a/src/sim/tlb.hh b/src/sim/tlb.hh index 011cc1144..8429c0df5 100644 --- a/src/sim/tlb.hh +++ b/src/sim/tlb.hh @@ -58,7 +58,7 @@ class GenericTLB : public BaseTLB public: void demapPage(Addr vaddr, uint64_t asn); - Fault translate(RequestPtr req, ThreadContext *tc, bool=false); + Fault translateAtomic(RequestPtr req, ThreadContext *tc, bool=false); }; #endif // __ARCH_SPARC_TLB_HH__ -- cgit v1.2.3 From 1b336a8fe713dad2e77c5f973d9eb2f5fbcfb585 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:15:56 -0800 Subject: X86: Make the stupd microop not update registers in initiateAcc. --- src/arch/x86/isa/microops/ldstop.isa | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/microops/ldstop.isa b/src/arch/x86/isa/microops/ldstop.isa index cdebe9613..5697f781b 100644 --- a/src/arch/x86/isa/microops/ldstop.isa +++ b/src/arch/x86/isa/microops/ldstop.isa @@ -228,6 +228,7 @@ def template MicroStoreExecute {{ fault = write(xc, Mem, EA, (%(mem_flags)s) | segment); if(fault == NoFault) { + %(post_code)s; %(op_wb)s; } } @@ -252,20 +253,20 @@ def template MicroStoreInitiateAcc {{ if(fault == NoFault) { - fault = write(xc, Mem, EA, (%(mem_flags)s) | segment); - if(fault == NoFault) - { - %(op_wb)s; - } + write(xc, Mem, EA, (%(mem_flags)s) | segment); } return fault; } }}; def template MicroStoreCompleteAcc {{ - Fault %(class_name)s::completeAcc(PacketPtr, %(CPU_exec_context)s * xc, - Trace::InstRecord * traceData) const + Fault %(class_name)s::completeAcc(PacketPtr pkt, + %(CPU_exec_context)s * xc, Trace::InstRecord * traceData) const { + %(op_decl)s; + %(op_rd)s; + %(complete_code)s; + %(op_wb)s; return NoFault; } }}; @@ -419,7 +420,8 @@ let {{ defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);', 'StoreCheck') defineMicroLoadOp('Ldfp', 'FpData.uqw = Mem;') - def defineMicroStoreOp(mnemonic, code, mem_flags=0): + def defineMicroStoreOp(mnemonic, code, \ + postCode="", completeCode="", mem_flags=0): global header_output global decoder_output global exec_output @@ -430,6 +432,8 @@ let {{ # Build up the all register version of this micro op iop = InstObjParams(name, Name, 'X86ISA::LdStOp', {"code": code, + "post_code": postCode, + "complete_code": completeCode, "ea_code": calculateEA, "mem_flags": mem_flags}) header_output += MicroLdStOpDeclare.subst(iop) @@ -450,11 +454,10 @@ let {{ defineMicroStoreOp('St', 'Mem = Data;') defineMicroStoreOp('Stfp', 'Mem = FpData.uqw;') - defineMicroStoreOp('Stupd', ''' - Mem = Data; - Base = merge(Base, EA - SegBase, addressSize); - '''); - defineMicroStoreOp('Cda', 'Mem = 0;', "Request::NO_ACCESS") + defineMicroStoreOp('Stupd', 'Mem = Data;', + 'Base = merge(Base, EA - SegBase, addressSize);', + 'Base = merge(Base, pkt->req->getVaddr() - SegBase, addressSize);'); + defineMicroStoreOp('Cda', 'Mem = 0;', mem_flags="Request::NO_ACCESS") iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp', {"code": "Data = merge(Data, EA, dataSize);", -- cgit v1.2.3 From 15940d06b5f6aabbe917a2a8c4cc4bb1cab991e2 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:16:04 -0800 Subject: SPARC: Adjust a few instructions to not write registers in initiateAcc. --- src/arch/sparc/isa/decoder.isa | 18 ++++++++---------- src/arch/sparc/isa/formats/mem/basicmem.isa | 10 ++++++++++ src/arch/sparc/isa/formats/mem/util.isa | 14 +++++++++----- 3 files changed, 27 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index c35b231ff..e34ca033f 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -1231,16 +1231,14 @@ decode OP default Unknown::unknown() 0x23: Load::lddf({{Frd.udw = Mem.udw;}}); 0x24: Store::stf({{Mem.uw = Frds.uw;}}); 0x25: decode RD { - 0x0: Store::stfsr({{fault = checkFpEnableFault(xc); - if (fault) - return fault; - Mem.uw = Fsr<31:0>; - Fsr = insertBits(Fsr,16,14,0);}}); - 0x1: Store::stxfsr({{fault = checkFpEnableFault(xc); - if (fault) - return fault; - Mem.udw = Fsr; - Fsr = insertBits(Fsr,16,14,0);}}); + 0x0: StoreFsr::stfsr({{fault = checkFpEnableFault(xc); + if (fault) + return fault; + Mem.uw = Fsr<31:0>;}}); + 0x1: StoreFsr::stxfsr({{fault = checkFpEnableFault(xc); + if (fault) + return fault; + Mem.udw = Fsr;}}); default: FailUnimpl::stfsrOther(); } 0x26: stqf({{fault = new FpDisabled;}}); diff --git a/src/arch/sparc/isa/formats/mem/basicmem.isa b/src/arch/sparc/isa/formats/mem/basicmem.isa index e3c043cf3..c7bb3e435 100644 --- a/src/arch/sparc/isa/formats/mem/basicmem.isa +++ b/src/arch/sparc/isa/formats/mem/basicmem.isa @@ -108,6 +108,16 @@ def format Store(code, *opt_flags) {{ StoreFuncs, '', name, Name, 0, opt_flags) }}; +def format StoreFsr(code, *opt_flags) {{ + code = filterDoubles(code) + (header_output, + decoder_output, + exec_output, + decode_block) = doMemFormat(code, + StoreFuncs, '', name, Name, 0, opt_flags, + 'Fsr = insertBits(Fsr,16,14,0);') +}}; + def format TwinLoad(code, *opt_flags) {{ (header_output, decoder_output, diff --git a/src/arch/sparc/isa/formats/mem/util.isa b/src/arch/sparc/isa/formats/mem/util.isa index f2a2327ee..31efb9cf6 100644 --- a/src/arch/sparc/isa/formats/mem/util.isa +++ b/src/arch/sparc/isa/formats/mem/util.isa @@ -264,11 +264,6 @@ def template StoreInitiateAcc {{ fault = xc->write((%(mem_acc_type)s%(mem_acc_size)s_t)Mem, EA, %(asi_val)s, 0); } - if(fault == NoFault) - { - //Write the resulting state to the execution context - %(op_wb)s; - } return fault; } }}; @@ -277,6 +272,15 @@ def template StoreCompleteAcc {{ Fault %(class_name)s::completeAcc(PacketPtr, %(CPU_exec_context)s * xc, Trace::InstRecord * traceData) const { + Fault fault = NoFault; + %(op_decl)s; + + %(op_rd)s; + %(postacc_code)s; + if (fault == NoFault) + { + %(op_wb)s; + } return NoFault; } }}; -- cgit v1.2.3 From 6ed47e94644f854baa33d1e9f367cc9eebd99abf Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:16:15 -0800 Subject: CPU: Implement translateTiming which defers to translateAtomic, and convert the timing simple CPU to use it. --- src/arch/alpha/tlb.cc | 20 ++- src/arch/alpha/tlb.hh | 8 +- src/arch/mips/tlb.cc | 20 ++- src/arch/mips/tlb.hh | 8 +- src/arch/sparc/tlb.cc | 20 ++- src/arch/sparc/tlb.hh | 9 +- src/arch/x86/tlb.cc | 22 ++- src/arch/x86/tlb.hh | 12 +- src/cpu/simple/atomic.cc | 6 +- src/cpu/simple/base.cc | 6 +- src/cpu/simple/base.hh | 4 +- src/cpu/simple/timing.cc | 364 ++++++++++++++++++++++++++--------------------- src/cpu/simple/timing.hh | 114 ++++++++++++++- src/sim/tlb.cc | 8 ++ src/sim/tlb.hh | 17 +++ 15 files changed, 447 insertions(+), 191 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc index 82d410987..2b0afacfe 100644 --- a/src/arch/alpha/tlb.cc +++ b/src/arch/alpha/tlb.cc @@ -317,7 +317,7 @@ ITB::regStats() } Fault -ITB::translateAtomic(RequestPtr &req, ThreadContext *tc) +ITB::translateAtomic(RequestPtr req, ThreadContext *tc) { //If this is a pal pc, then set PHYSICAL if (FULL_SYSTEM && PcPAL(req->getPC())) @@ -401,6 +401,14 @@ ITB::translateAtomic(RequestPtr &req, ThreadContext *tc) } +void +ITB::translateTiming(RequestPtr req, ThreadContext *tc, + Translation *translation) +{ + assert(translation); + translation->finish(translateAtomic(req, tc), req, tc, false); +} + /////////////////////////////////////////////////////////////////////// // // Alpha DTB @@ -479,7 +487,7 @@ DTB::regStats() } Fault -DTB::translateAtomic(RequestPtr &req, ThreadContext *tc, bool write) +DTB::translateAtomic(RequestPtr req, ThreadContext *tc, bool write) { Addr pc = tc->readPC(); @@ -616,6 +624,14 @@ DTB::translateAtomic(RequestPtr &req, ThreadContext *tc, bool write) return checkCacheability(req); } +void +DTB::translateTiming(RequestPtr req, ThreadContext *tc, + Translation *translation, bool write) +{ + assert(translation); + translation->finish(translateAtomic(req, tc, write), req, tc, write); +} + TlbEntry & TLB::index(bool advance) { diff --git a/src/arch/alpha/tlb.hh b/src/arch/alpha/tlb.hh index f5d2dbca9..877533797 100644 --- a/src/arch/alpha/tlb.hh +++ b/src/arch/alpha/tlb.hh @@ -131,7 +131,9 @@ class ITB : public TLB ITB(const Params *p); virtual void regStats(); - Fault translateAtomic(RequestPtr &req, ThreadContext *tc); + Fault translateAtomic(RequestPtr req, ThreadContext *tc); + void translateTiming(RequestPtr req, ThreadContext *tc, + Translation *translation); }; class DTB : public TLB @@ -155,7 +157,9 @@ class DTB : public TLB DTB(const Params *p); virtual void regStats(); - Fault translateAtomic(RequestPtr &req, ThreadContext *tc, bool write); + Fault translateAtomic(RequestPtr req, ThreadContext *tc, bool write); + void translateTiming(RequestPtr req, ThreadContext *tc, + Translation *translation, bool write); }; } // namespace AlphaISA diff --git a/src/arch/mips/tlb.cc b/src/arch/mips/tlb.cc index db21c7919..eac44eba8 100644 --- a/src/arch/mips/tlb.cc +++ b/src/arch/mips/tlb.cc @@ -310,7 +310,7 @@ TLB::regStats() } Fault -ITB::translateAtomic(RequestPtr &req, ThreadContext *tc) +ITB::translateAtomic(RequestPtr req, ThreadContext *tc) { #if !FULL_SYSTEM Process * p = tc->getProcessPtr(); @@ -426,8 +426,16 @@ ITB::translateAtomic(RequestPtr &req, ThreadContext *tc) #endif } +void +ITB::translateTiming(RequestPtr req, ThreadContext *tc, + Translation *translation) +{ + assert(translation); + translation->finish(translateAtomic(req, tc), req, tc, false); +} + Fault -DTB::translateAtomic(RequestPtr &req, ThreadContext *tc, bool write) +DTB::translateAtomic(RequestPtr req, ThreadContext *tc, bool write) { #if !FULL_SYSTEM Process * p = tc->getProcessPtr(); @@ -564,6 +572,14 @@ DTB::translateAtomic(RequestPtr &req, ThreadContext *tc, bool write) #endif } +void +DTB::translateTiming(RequestPtr req, ThreadContext *tc, + Translation *translation, bool write) +{ + assert(translation); + translation->finish(translateAtomic(req, tc, write), req, tc, write); +} + /////////////////////////////////////////////////////////////////////// // // Mips ITB diff --git a/src/arch/mips/tlb.hh b/src/arch/mips/tlb.hh index acb393116..1ab9d77e5 100644 --- a/src/arch/mips/tlb.hh +++ b/src/arch/mips/tlb.hh @@ -145,7 +145,9 @@ class ITB : public TLB { typedef MipsTLBParams Params; ITB(const Params *p); - Fault translateAtomic(RequestPtr &req, ThreadContext *tc); + Fault translateAtomic(RequestPtr req, ThreadContext *tc); + void translateTiming(RequestPtr req, ThreadContext *tc, + Translation *translation); }; class DTB : public TLB { @@ -153,8 +155,10 @@ class DTB : public TLB { typedef MipsTLBParams Params; DTB(const Params *p); - Fault translateAtomic(RequestPtr &req, ThreadContext *tc, + Fault translateAtomic(RequestPtr req, ThreadContext *tc, bool write = false); + void translateTiming(RequestPtr req, ThreadContext *tc, + Translation *translation, bool write = false); }; class UTB : public ITB, public DTB { diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc index 683d916df..95ad0229e 100644 --- a/src/arch/sparc/tlb.cc +++ b/src/arch/sparc/tlb.cc @@ -436,7 +436,7 @@ DTB::writeSfsr(Addr a, bool write, ContextType ct, } Fault -ITB::translateAtomic(RequestPtr &req, ThreadContext *tc) +ITB::translateAtomic(RequestPtr req, ThreadContext *tc) { uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA); @@ -548,8 +548,16 @@ ITB::translateAtomic(RequestPtr &req, ThreadContext *tc) return NoFault; } +void +ITB::translateTiming(RequestPtr req, ThreadContext *tc, + Translation *translation) +{ + assert(translation); + translation->finish(translateAtomic(req, tc), req, tc, false); +} + Fault -DTB::translateAtomic(RequestPtr &req, ThreadContext *tc, bool write) +DTB::translateAtomic(RequestPtr req, ThreadContext *tc, bool write) { /* * @todo this could really use some profiling and fixing to make @@ -847,6 +855,14 @@ handleMmuRegAccess: return NoFault; }; +void +DTB::translateTiming(RequestPtr req, ThreadContext *tc, + Translation *translation, bool write) +{ + assert(translation); + translation->finish(translateAtomic(req, tc, write), req, tc, write); +} + #if FULL_SYSTEM Tick diff --git a/src/arch/sparc/tlb.hh b/src/arch/sparc/tlb.hh index d563772e6..4fe532d4a 100644 --- a/src/arch/sparc/tlb.hh +++ b/src/arch/sparc/tlb.hh @@ -177,7 +177,9 @@ class ITB : public TLB cacheEntry = NULL; } - Fault translateAtomic(RequestPtr &req, ThreadContext *tc); + Fault translateAtomic(RequestPtr req, ThreadContext *tc); + void translateTiming(RequestPtr req, ThreadContext *tc, + Translation *translation); private: void writeSfsr(bool write, ContextType ct, bool se, FaultTypes ft, int asi); @@ -199,7 +201,10 @@ class DTB : public TLB cacheEntry[1] = NULL; } - Fault translateAtomic(RequestPtr &req, ThreadContext *tc, bool write); + Fault translateAtomic(RequestPtr req, + ThreadContext *tc, bool write=false); + void translateTiming(RequestPtr req, ThreadContext *tc, + Translation *translation, bool write=false); #if FULL_SYSTEM Tick doMmuRegRead(ThreadContext *tc, Packet *pkt); Tick doMmuRegWrite(ThreadContext *tc, Packet *pkt); diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index 33017a6aa..a34922b44 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -190,7 +190,7 @@ TLB::demapPage(Addr va, uint64_t asn) template Fault -TLB::translateAtomic(RequestPtr &req, ThreadContext *tc, +TLB::translateAtomic(RequestPtr req, ThreadContext *tc, bool write, bool execute) { Addr vaddr = req->getVaddr(); @@ -663,17 +663,33 @@ TLB::translateAtomic(RequestPtr &req, ThreadContext *tc, }; Fault -DTB::translateAtomic(RequestPtr &req, ThreadContext *tc, bool write) +DTB::translateAtomic(RequestPtr req, ThreadContext *tc, bool write) { return TLB::translateAtomic(req, tc, write, false); } +void +DTB::translateTiming(RequestPtr req, ThreadContext *tc, + Translation *translation, bool write) +{ + assert(translation); + translation->finish(translateAtomic(req, tc, write), req, tc, write); +} + Fault -ITB::translateAtomic(RequestPtr &req, ThreadContext *tc) +ITB::translateAtomic(RequestPtr req, ThreadContext *tc) { return TLB::translateAtomic(req, tc, false, true); } +void +ITB::translateTiming(RequestPtr req, ThreadContext *tc, + Translation *translation) +{ + assert(translation); + translation->finish(translateAtomic(req, tc), req, tc, false); +} + #if FULL_SYSTEM Tick diff --git a/src/arch/x86/tlb.hh b/src/arch/x86/tlb.hh index 91bb4a761..56730983a 100644 --- a/src/arch/x86/tlb.hh +++ b/src/arch/x86/tlb.hh @@ -138,8 +138,10 @@ namespace X86ISA EntryList entryList; template - Fault translateAtomic(RequestPtr &req, ThreadContext *tc, + Fault translateAtomic(RequestPtr req, ThreadContext *tc, bool write, bool execute); + void translateTiming(RequestPtr req, ThreadContext *tc, + Translation *translation, bool write, bool execute); public: @@ -159,7 +161,9 @@ namespace X86ISA _allowNX = false; } - Fault translateAtomic(RequestPtr &req, ThreadContext *tc); + Fault translateAtomic(RequestPtr req, ThreadContext *tc); + void translateTiming(RequestPtr req, ThreadContext *tc, + Translation *translation); friend class DTB; }; @@ -172,7 +176,9 @@ namespace X86ISA { _allowNX = true; } - Fault translateAtomic(RequestPtr &req, ThreadContext *tc, bool write); + Fault translateAtomic(RequestPtr req, ThreadContext *tc, bool write); + void translateTiming(RequestPtr req, ThreadContext *tc, + Translation *translation, bool write); #if FULL_SYSTEM Tick doMmuRegRead(ThreadContext *tc, Packet *pkt); Tick doMmuRegWrite(ThreadContext *tc, Packet *pkt); diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 7a1cf71c4..2ada12b8d 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -607,8 +607,10 @@ AtomicSimpleCPU::tick() Fault fault = NoFault; bool fromRom = isRomMicroPC(thread->readMicroPC()); - if (!fromRom) - fault = setupFetchRequest(&ifetch_req); + if (!fromRom) { + setupFetchRequest(&ifetch_req); + fault = thread->itb->translateAtomic(&ifetch_req, tc); + } if (fault == NoFault) { Tick icache_latency = 0; diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index ddeb9a7c8..9372ff43d 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -330,7 +330,7 @@ BaseSimpleCPU::checkForInterrupts() } -Fault +void BaseSimpleCPU::setupFetchRequest(Request *req) { Addr threadPC = thread->readPC(); @@ -346,10 +346,6 @@ BaseSimpleCPU::setupFetchRequest(Request *req) Addr fetchPC = (threadPC & PCMask) + fetchOffset; req->setVirt(0, fetchPC, sizeof(MachInst), 0, threadPC); - - Fault fault = thread->itb->translateAtomic(req, tc); - - return fault; } diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index 34d0f5954..d2ccc0ff1 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -125,9 +125,11 @@ class BaseSimpleCPU : public BaseCPU enum Status { Idle, Running, + ITBWaitResponse, IcacheRetry, IcacheWaitResponse, IcacheWaitSwitch, + DTBWaitResponse, DcacheRetry, DcacheWaitResponse, DcacheWaitSwitch, @@ -160,7 +162,7 @@ class BaseSimpleCPU : public BaseCPU bool stayAtPC; void checkForInterrupts(); - Fault setupFetchRequest(Request *req); + void setupFetchRequest(Request *req); void preExecute(); void postExecute(); void advancePC(Fault fault); diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 65222266e..3f5778138 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -104,7 +104,8 @@ TimingSimpleCPU::CpuPort::TickEvent::schedule(PacketPtr _pkt, Tick t) } TimingSimpleCPU::TimingSimpleCPU(TimingSimpleCPUParams *p) - : BaseSimpleCPU(p), icachePort(this, p->clock), dcachePort(this, p->clock), fetchEvent(this) + : BaseSimpleCPU(p), fetchTranslation(this), icachePort(this, p->clock), + dcachePort(this, p->clock), fetchEvent(this) { _status = Idle; @@ -262,66 +263,123 @@ TimingSimpleCPU::handleReadPacket(PacketPtr pkt) return dcache_pkt == NULL; } -Fault -TimingSimpleCPU::buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2, - RequestPtr &req, Addr split_addr, uint8_t *data, bool read) +void +TimingSimpleCPU::sendData(Fault fault, RequestPtr req, + uint8_t *data, uint64_t *res, bool read) { - Fault fault; - RequestPtr req1, req2; - assert(!req->isLocked() && !req->isSwap()); - req->splitOnVaddr(split_addr, req1, req2); - - pkt1 = pkt2 = NULL; - if ((fault = buildPacket(pkt1, req1, read)) != NoFault || - (fault = buildPacket(pkt2, req2, read)) != NoFault) { + _status = Running; + if (fault != NoFault) { + delete data; delete req; - delete req1; - delete pkt1; - req = NULL; - pkt1 = NULL; - return fault; + + translationFault(fault); + return; } + PacketPtr pkt; + buildPacket(pkt, req, read); + pkt->dataDynamic(data); + if (req->getFlags().isSet(Request::NO_ACCESS)) { + assert(!dcache_pkt); + pkt->makeResponse(); + completeDataAccess(pkt); + } else if (read) { + handleReadPacket(pkt); + } else { + bool do_access = true; // flag to suppress cache access - assert(!req1->isMmapedIpr() && !req2->isMmapedIpr()); + if (req->isLocked()) { + do_access = TheISA::handleLockedWrite(thread, req); + } else if (req->isCondSwap()) { + assert(res); + req->setExtraData(*res); + } - req->setPhys(req1->getPaddr(), req->getSize(), req1->getFlags()); - PacketPtr pkt = new Packet(req, pkt1->cmd.responseCommand(), - Packet::Broadcast); - if (req->getFlags().isSet(Request::NO_ACCESS)) { + if (do_access) { + dcache_pkt = pkt; + handleWritePacket(); + } else { + _status = DcacheWaitResponse; + completeDataAccess(pkt); + } + } +} + +void +TimingSimpleCPU::sendSplitData(Fault fault1, Fault fault2, + RequestPtr req1, RequestPtr req2, RequestPtr req, + uint8_t *data, bool read) +{ + _status = Running; + if (fault1 != NoFault || fault2 != NoFault) { + delete data; delete req1; - delete pkt1; delete req2; - delete pkt2; - pkt1 = pkt; - pkt2 = NULL; - return NoFault; + if (fault1 != NoFault) + translationFault(fault1); + else if (fault2 != NoFault) + translationFault(fault2); + return; + } + PacketPtr pkt1, pkt2; + buildSplitPacket(pkt1, pkt2, req1, req2, req, data, read); + if (req->getFlags().isSet(Request::NO_ACCESS)) { + assert(!dcache_pkt); + pkt1->makeResponse(); + completeDataAccess(pkt1); + } else if (read) { + if (handleReadPacket(pkt1)) { + SplitFragmentSenderState * send_state = + dynamic_cast(pkt1->senderState); + send_state->clearFromParent(); + if (handleReadPacket(pkt2)) { + send_state = dynamic_cast( + pkt1->senderState); + send_state->clearFromParent(); + } + } + } else { + dcache_pkt = pkt1; + if (handleWritePacket()) { + SplitFragmentSenderState * send_state = + dynamic_cast(pkt1->senderState); + send_state->clearFromParent(); + dcache_pkt = pkt2; + if (handleWritePacket()) { + send_state = dynamic_cast( + pkt1->senderState); + send_state->clearFromParent(); + } + } } +} - pkt->dataDynamic(data); - pkt1->dataStatic(data); - pkt2->dataStatic(data + req1->getSize()); +void +TimingSimpleCPU::translationFault(Fault fault) +{ + numCycles += tickToCycles(curTick - previousTick); + previousTick = curTick; - SplitMainSenderState * main_send_state = new SplitMainSenderState; - pkt->senderState = main_send_state; - main_send_state->fragments[0] = pkt1; - main_send_state->fragments[1] = pkt2; - main_send_state->outstanding = 2; - pkt1->senderState = new SplitFragmentSenderState(pkt, 0); - pkt2->senderState = new SplitFragmentSenderState(pkt, 1); - return fault; + if (traceData) { + // Since there was a fault, we shouldn't trace this instruction. + delete traceData; + traceData = NULL; + } + + postExecute(); + + if (getState() == SimObject::Draining) { + advancePC(fault); + completeDrain(); + } else { + advanceInst(fault); + } } -Fault -TimingSimpleCPU::buildPacket(PacketPtr &pkt, RequestPtr &req, bool read) +void +TimingSimpleCPU::buildPacket(PacketPtr &pkt, RequestPtr req, bool read) { - Fault fault = thread->dtb->translateAtomic(req, tc, !read); MemCmd cmd; - if (fault != NoFault) { - delete req; - req = NULL; - pkt = NULL; - return fault; - } else if (read) { + if (read) { cmd = MemCmd::ReadReq; if (req->isLocked()) cmd = MemCmd::LoadLockedReq; @@ -334,7 +392,40 @@ TimingSimpleCPU::buildPacket(PacketPtr &pkt, RequestPtr &req, bool read) } } pkt = new Packet(req, cmd, Packet::Broadcast); - return NoFault; +} + +void +TimingSimpleCPU::buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2, + RequestPtr req1, RequestPtr req2, RequestPtr req, + uint8_t *data, bool read) +{ + pkt1 = pkt2 = NULL; + + assert(!req1->isMmapedIpr() && !req2->isMmapedIpr()); + + if (req->getFlags().isSet(Request::NO_ACCESS)) { + buildPacket(pkt1, req, read); + return; + } + + buildPacket(pkt1, req1, read); + buildPacket(pkt2, req2, read); + + req->setPhys(req1->getPaddr(), req->getSize(), req1->getFlags()); + PacketPtr pkt = new Packet(req, pkt1->cmd.responseCommand(), + Packet::Broadcast); + + pkt->dataDynamic(data); + pkt1->dataStatic(data); + pkt2->dataStatic(data + req1->getSize()); + + SplitMainSenderState * main_send_state = new SplitMainSenderState; + pkt->senderState = main_send_state; + main_send_state->fragments[0] = pkt1; + main_send_state->fragments[1] = pkt2; + main_send_state->outstanding = 2; + pkt1->senderState = new SplitFragmentSenderState(pkt, 0); + pkt2->senderState = new SplitFragmentSenderState(pkt, 1); } template @@ -348,42 +439,30 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) int block_size = dcachePort.peerBlockSize(); int data_size = sizeof(T); - PacketPtr pkt; RequestPtr req = new Request(asid, addr, data_size, flags, pc, _cpuId, thread_id); Addr split_addr = roundDown(addr + data_size - 1, block_size); assert(split_addr <= addr || split_addr - addr < block_size); + + _status = DTBWaitResponse; if (split_addr > addr) { - PacketPtr pkt1, pkt2; - Fault fault = this->buildSplitPacket(pkt1, pkt2, req, - split_addr, (uint8_t *)(new T), true); - if (fault != NoFault) - return fault; - if (req->getFlags().isSet(Request::NO_ACCESS)) { - dcache_pkt = pkt1; - } else if (handleReadPacket(pkt1)) { - SplitFragmentSenderState * send_state = - dynamic_cast(pkt1->senderState); - send_state->clearFromParent(); - if (handleReadPacket(pkt2)) { - send_state = - dynamic_cast(pkt1->senderState); - send_state->clearFromParent(); - } - } + RequestPtr req1, req2; + assert(!req->isLocked() && !req->isSwap()); + req->splitOnVaddr(split_addr, req1, req2); + + typedef SplitDataTranslation::WholeTranslationState WholeState; + WholeState *state = new WholeState(req1, req2, req, + (uint8_t *)(new T), true); + thread->dtb->translateTiming(req1, tc, + new SplitDataTranslation(this, 0, state), false); + thread->dtb->translateTiming(req2, tc, + new SplitDataTranslation(this, 1, state), false); } else { - Fault fault = buildPacket(pkt, req, true); - if (fault != NoFault) { - return fault; - } - if (req->getFlags().isSet(Request::NO_ACCESS)) { - dcache_pkt = pkt; - } else { - pkt->dataDynamic(new T); - handleReadPacket(pkt); - } + thread->dtb->translateTiming(req, tc, + new DataTranslation(this, (uint8_t *)(new T), NULL, true), + false); } if (traceData) { @@ -484,54 +563,25 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) Addr split_addr = roundDown(addr + data_size - 1, block_size); assert(split_addr <= addr || split_addr - addr < block_size); + T *dataP = new T; + *dataP = TheISA::gtoh(data); + _status = DTBWaitResponse; if (split_addr > addr) { - PacketPtr pkt1, pkt2; - T *dataP = new T; - *dataP = data; - Fault fault = this->buildSplitPacket(pkt1, pkt2, req, split_addr, - (uint8_t *)dataP, false); - if (fault != NoFault) - return fault; - dcache_pkt = pkt1; - if (!req->getFlags().isSet(Request::NO_ACCESS)) { - if (handleWritePacket()) { - SplitFragmentSenderState * send_state = - dynamic_cast( - pkt1->senderState); - send_state->clearFromParent(); - dcache_pkt = pkt2; - if (handleReadPacket(pkt2)) { - send_state = - dynamic_cast( - pkt1->senderState); - send_state->clearFromParent(); - } - } - } + RequestPtr req1, req2; + assert(!req->isLocked() && !req->isSwap()); + req->splitOnVaddr(split_addr, req1, req2); + + typedef SplitDataTranslation::WholeTranslationState WholeState; + WholeState *state = new WholeState(req1, req2, req, + (uint8_t *)dataP, false); + thread->dtb->translateTiming(req1, tc, + new SplitDataTranslation(this, 0, state), true); + thread->dtb->translateTiming(req2, tc, + new SplitDataTranslation(this, 1, state), true); } else { - bool do_access = true; // flag to suppress cache access - - Fault fault = buildPacket(dcache_pkt, req, false); - if (fault != NoFault) - return fault; - - if (!req->getFlags().isSet(Request::NO_ACCESS)) { - if (req->isLocked()) { - do_access = TheISA::handleLockedWrite(thread, req); - } else if (req->isCondSwap()) { - assert(res); - req->setExtraData(*res); - } - - dcache_pkt->allocate(); - if (req->isMmapedIpr()) - dcache_pkt->set(htog(data)); - else - dcache_pkt->set(data); - - if (do_access) - handleWritePacket(); - } + thread->dtb->translateTiming(req, tc, + new DataTranslation(this, (uint8_t *)dataP, res, false), + true); } if (traceData) { @@ -620,30 +670,39 @@ TimingSimpleCPU::fetch() if (!fromRom) { Request *ifetch_req = new Request(); ifetch_req->setThreadContext(_cpuId, /* thread ID */ 0); - Fault fault = setupFetchRequest(ifetch_req); + setupFetchRequest(ifetch_req); + thread->itb->translateTiming(ifetch_req, tc, + &fetchTranslation); + } else { + _status = IcacheWaitResponse; + completeIfetch(NULL); - ifetch_pkt = new Packet(ifetch_req, MemCmd::ReadReq, Packet::Broadcast); + numCycles += tickToCycles(curTick - previousTick); + previousTick = curTick; + } +} + + +void +TimingSimpleCPU::sendFetch(Fault fault, RequestPtr req, ThreadContext *tc) +{ + if (fault == NoFault) { + ifetch_pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast); ifetch_pkt->dataStatic(&inst); - if (fault == NoFault) { - if (!icachePort.sendTiming(ifetch_pkt)) { - // Need to wait for retry - _status = IcacheRetry; - } else { - // Need to wait for cache to respond - _status = IcacheWaitResponse; - // ownership of packet transferred to memory system - ifetch_pkt = NULL; - } + if (!icachePort.sendTiming(ifetch_pkt)) { + // Need to wait for retry + _status = IcacheRetry; } else { - delete ifetch_req; - delete ifetch_pkt; - // fetch fault: advance directly to next instruction (fault handler) - advanceInst(fault); + // Need to wait for cache to respond + _status = IcacheWaitResponse; + // ownership of packet transferred to memory system + ifetch_pkt = NULL; } } else { - _status = IcacheWaitResponse; - completeIfetch(NULL); + delete req; + // fetch fault: advance directly to next instruction (fault handler) + advanceInst(fault); } numCycles += tickToCycles(curTick - previousTick); @@ -699,28 +758,11 @@ TimingSimpleCPU::completeIfetch(PacketPtr pkt) Fault fault = curStaticInst->initiateAcc(this, traceData); if (_status != Running) { // instruction will complete in dcache response callback - assert(_status == DcacheWaitResponse || _status == DcacheRetry); + assert(_status == DcacheWaitResponse || + _status == DcacheRetry || DTBWaitResponse); assert(fault == NoFault); } else { - if (fault == NoFault) { - // Note that ARM can have NULL packets if the instruction gets - // squashed due to predication - // early fail on store conditional: complete now - assert(dcache_pkt != NULL || THE_ISA == ARM_ISA); - - fault = curStaticInst->completeAcc(dcache_pkt, this, - traceData); - if (dcache_pkt != NULL) - { - delete dcache_pkt->req; - delete dcache_pkt; - dcache_pkt = NULL; - } - - // keep an instruction count - if (fault == NoFault) - countInst(); - } else if (traceData) { + if (fault != NoFault && traceData) { // If there was a fault, we shouldn't trace this instruction. delete traceData; traceData = NULL; @@ -843,7 +885,7 @@ TimingSimpleCPU::completeDataAccess(PacketPtr pkt) } } - assert(_status == DcacheWaitResponse); + assert(_status == DcacheWaitResponse || _status == DTBWaitResponse); _status = Running; Fault fault = curStaticInst->completeAcc(pkt, this, traceData); diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index 0a639a627..a02ec48c9 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -96,9 +96,114 @@ class TimingSimpleCPU : public BaseSimpleCPU } }; - Fault buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2, RequestPtr &req, - Addr split_addr, uint8_t *data, bool read); - Fault buildPacket(PacketPtr &pkt, RequestPtr &req, bool read); + class FetchTranslation : public BaseTLB::Translation + { + protected: + TimingSimpleCPU *cpu; + + public: + FetchTranslation(TimingSimpleCPU *_cpu) : cpu(_cpu) + {} + + void finish(Fault fault, RequestPtr req, + ThreadContext *tc, bool write) + { + cpu->sendFetch(fault, req, tc); + } + }; + FetchTranslation fetchTranslation; + + class DataTranslation : public BaseTLB::Translation + { + protected: + TimingSimpleCPU *cpu; + uint8_t *data; + uint64_t *res; + bool read; + + public: + DataTranslation(TimingSimpleCPU *_cpu, + uint8_t *_data, uint64_t *_res, bool _read) : + cpu(_cpu), data(_data), res(_res), read(_read) + {} + + void + finish(Fault fault, RequestPtr req, + ThreadContext *tc, bool write) + { + cpu->sendData(fault, req, data, res, read); + delete this; + } + }; + + class SplitDataTranslation : public BaseTLB::Translation + { + public: + struct WholeTranslationState + { + public: + int outstanding; + RequestPtr requests[2]; + RequestPtr mainReq; + Fault faults[2]; + uint8_t *data; + bool read; + + WholeTranslationState(RequestPtr req1, RequestPtr req2, + RequestPtr main, uint8_t *_data, bool _read) + { + outstanding = 2; + requests[0] = req1; + requests[1] = req2; + mainReq = main; + faults[0] = faults[1] = NoFault; + data = _data; + read = _read; + } + }; + + TimingSimpleCPU *cpu; + int index; + WholeTranslationState *state; + + SplitDataTranslation(TimingSimpleCPU *_cpu, int _index, + WholeTranslationState *_state) : + cpu(_cpu), index(_index), state(_state) + {} + + void + finish(Fault fault, RequestPtr req, + ThreadContext *tc, bool write) + { + assert(state); + assert(state->outstanding); + state->faults[index] = fault; + if (--state->outstanding == 0) { + cpu->sendSplitData(state->faults[0], + state->faults[1], + state->requests[0], + state->requests[1], + state->mainReq, + state->data, + state->read); + delete state; + } + delete this; + } + }; + + void sendData(Fault fault, RequestPtr req, + uint8_t *data, uint64_t *res, bool read); + void sendSplitData(Fault fault1, Fault fault2, + RequestPtr req1, RequestPtr req2, RequestPtr req, + uint8_t *data, bool read); + + void translationFault(Fault fault); + + void buildPacket(PacketPtr &pkt, RequestPtr req, bool read); + void buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2, + RequestPtr req1, RequestPtr req2, RequestPtr req, + uint8_t *data, bool read); bool handleReadPacket(PacketPtr pkt); // This function always implicitly uses dcache_pkt. @@ -228,8 +333,9 @@ class TimingSimpleCPU : public BaseSimpleCPU Fault write(T data, Addr addr, unsigned flags, uint64_t *res); void fetch(); + void sendFetch(Fault fault, RequestPtr req, ThreadContext *tc); void completeIfetch(PacketPtr ); - void completeDataAccess(PacketPtr ); + void completeDataAccess(PacketPtr pkt); void advanceInst(Fault fault); /** diff --git a/src/sim/tlb.cc b/src/sim/tlb.cc index f7b57cbbc..e82e4f277 100644 --- a/src/sim/tlb.cc +++ b/src/sim/tlb.cc @@ -49,6 +49,14 @@ GenericTLB::translateAtomic(RequestPtr req, ThreadContext * tc, bool) #endif } +void +GenericTLB::translateTiming(RequestPtr req, ThreadContext *tc, + Translation *translation, bool write) +{ + assert(translation); + translation->finish(translateAtomic(req, tc, write), req, tc, write); +} + void GenericTLB::demapPage(Addr vaddr, uint64_t asn) { diff --git a/src/sim/tlb.hh b/src/sim/tlb.hh index 8429c0df5..8893f8c97 100644 --- a/src/sim/tlb.hh +++ b/src/sim/tlb.hh @@ -47,6 +47,21 @@ class BaseTLB : public SimObject public: virtual void demapPage(Addr vaddr, uint64_t asn) = 0; + + class Translation + { + public: + virtual ~Translation() + {} + + /* + * The memory for this object may be dynamically allocated, and it may + * be responsible for cleaning itself up which will happen in this + * function. Once it's called, the object is no longer valid. + */ + virtual void finish(Fault fault, RequestPtr req, + ThreadContext *tc, bool write=false) = 0; + }; }; class GenericTLB : public BaseTLB @@ -59,6 +74,8 @@ class GenericTLB : public BaseTLB void demapPage(Addr vaddr, uint64_t asn); Fault translateAtomic(RequestPtr req, ThreadContext *tc, bool=false); + void translateTiming(RequestPtr req, ThreadContext *tc, + Translation *translation, bool=false); }; #endif // __ARCH_SPARC_TLB_HH__ -- cgit v1.2.3 From 40fdba2454c219902db7ad1abd28593de8611c2b Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:16:21 -0800 Subject: X86: Make the X86 TLB take advantage of delayed translations, and get rid of the fake TLB miss faults. --- src/arch/x86/faults.cc | 50 ------------ src/arch/x86/faults.hh | 32 -------- src/arch/x86/pagetable_walker.cc | 170 ++++++++++++++++++++++----------------- src/arch/x86/pagetable_walker.hh | 26 +++++- src/arch/x86/tlb.cc | 86 ++++++++++++++------ src/arch/x86/tlb.hh | 15 ++-- 6 files changed, 187 insertions(+), 192 deletions(-) (limited to 'src') diff --git a/src/arch/x86/faults.cc b/src/arch/x86/faults.cc index f01197f36..964eb0a7f 100644 --- a/src/arch/x86/faults.cc +++ b/src/arch/x86/faults.cc @@ -163,56 +163,6 @@ namespace X86ISA } } - void FakeITLBFault::invoke(ThreadContext * tc) - { - // Start the page table walker. - tc->getITBPtr()->walk(tc, vaddr, write, execute); - } - - void FakeDTLBFault::invoke(ThreadContext * tc) - { - // Start the page table walker. - tc->getDTBPtr()->walk(tc, vaddr, write, execute); - } - -#else // !FULL_SYSTEM - void FakeITLBFault::invoke(ThreadContext * tc) - { - DPRINTF(TLB, "Invoking an ITLB fault for address %#x at pc %#x.\n", - vaddr, tc->readPC()); - Process *p = tc->getProcessPtr(); - TlbEntry entry; - bool success = p->pTable->lookup(vaddr, entry); - if(!success) { - panic("Tried to execute unmapped address %#x.\n", vaddr); - } else { - Addr alignedVaddr = p->pTable->pageAlign(vaddr); - DPRINTF(TLB, "Mapping %#x to %#x\n", alignedVaddr, - entry.pageStart()); - tc->getITBPtr()->insert(alignedVaddr, entry); - } - } - - void FakeDTLBFault::invoke(ThreadContext * tc) - { - DPRINTF(TLB, "Invoking an DTLB fault for address %#x at pc %#x.\n", - vaddr, tc->readPC()); - Process *p = tc->getProcessPtr(); - TlbEntry entry; - bool success = p->pTable->lookup(vaddr, entry); - if(!success) { - p->checkAndAllocNextPage(vaddr); - success = p->pTable->lookup(vaddr, entry); - } - if(!success) { - panic("Tried to access unmapped address %#x.\n", vaddr); - } else { - Addr alignedVaddr = p->pTable->pageAlign(vaddr); - DPRINTF(TLB, "Mapping %#x to %#x\n", alignedVaddr, - entry.pageStart()); - tc->getDTBPtr()->insert(alignedVaddr, entry); - } - } #endif } // namespace X86ISA diff --git a/src/arch/x86/faults.hh b/src/arch/x86/faults.hh index ae4314434..3753e60e5 100644 --- a/src/arch/x86/faults.hh +++ b/src/arch/x86/faults.hh @@ -422,38 +422,6 @@ namespace X86ISA return true; } }; - - // These faults aren't part of the ISA definition. They trigger filling - // the tlb on a miss and are to take the place of a hardware table walker. - class FakeITLBFault : public X86Fault - { - protected: - Addr vaddr; - bool write; - bool execute; - public: - FakeITLBFault(Addr _vaddr, bool _write, bool _execute) : - X86Fault("fake instruction tlb fault", "itlb", 0), - vaddr(_vaddr), write(_write), execute(_execute) - {} - - void invoke(ThreadContext * tc); - }; - - class FakeDTLBFault : public X86Fault - { - protected: - Addr vaddr; - bool write; - bool execute; - public: - FakeDTLBFault(Addr _vaddr, bool _write, bool _execute) : - X86Fault("fake data tlb fault", "dtlb", 0), - vaddr(_vaddr), write(_write), execute(_execute) - {} - - void invoke(ThreadContext * tc); - }; }; #endif // __ARCH_X86_FAULTS_HH__ diff --git a/src/arch/x86/pagetable_walker.cc b/src/arch/x86/pagetable_walker.cc index b0b9209b5..fe3a4c3bb 100644 --- a/src/arch/x86/pagetable_walker.cc +++ b/src/arch/x86/pagetable_walker.cc @@ -84,7 +84,7 @@ BitUnion64(PageTableEntry) Bitfield<0> p; EndBitUnion(PageTableEntry) -void +Fault Walker::doNext(PacketPtr &read, PacketPtr &write) { assert(state != Ready && state != Waiting); @@ -106,11 +106,11 @@ Walker::doNext(PacketPtr &read, PacketPtr &write) pte.a = 1; entry.writable = pte.w; entry.user = pte.u; - if (badNX) - panic("NX violation!\n"); + if (badNX || !pte.p) { + stop(); + return pageFault(pte.p); + } entry.noExec = pte.nx; - if (!pte.p) - panic("Page at %#x not present!\n", entry.vaddr); nextState = LongPDP; break; case LongPDP: @@ -119,10 +119,10 @@ Walker::doNext(PacketPtr &read, PacketPtr &write) pte.a = 1; entry.writable = entry.writable && pte.w; entry.user = entry.user && pte.u; - if (badNX) - panic("NX violation!\n"); - if (!pte.p) - panic("Page at %#x not present!\n", entry.vaddr); + if (badNX || !pte.p) { + stop(); + return pageFault(pte.p); + } nextState = LongPD; break; case LongPD: @@ -130,10 +130,10 @@ Walker::doNext(PacketPtr &read, PacketPtr &write) pte.a = 1; entry.writable = entry.writable && pte.w; entry.user = entry.user && pte.u; - if (badNX) - panic("NX violation!\n"); - if (!pte.p) - panic("Page at %#x not present!\n", entry.vaddr); + if (badNX || !pte.p) { + stop(); + return pageFault(pte.p); + } if (!pte.ps) { // 4 KB page entry.size = 4 * (1 << 10); @@ -150,36 +150,32 @@ Walker::doNext(PacketPtr &read, PacketPtr &write) entry.patBit = bits(pte, 12); entry.vaddr = entry.vaddr & ~((2 * (1 << 20)) - 1); tlb->insert(entry.vaddr, entry); - nextState = Ready; - delete read->req; - delete read; - read = NULL; - return; + stop(); + return NoFault; } case LongPTE: doWrite = !pte.a; pte.a = 1; entry.writable = entry.writable && pte.w; entry.user = entry.user && pte.u; - if (badNX) - panic("NX violation!\n"); - if (!pte.p) - panic("Page at %#x not present!\n", entry.vaddr); + if (badNX || !pte.p) { + stop(); + return pageFault(pte.p); + } entry.paddr = (uint64_t)pte & (mask(40) << 12); entry.uncacheable = uncacheable; entry.global = pte.g; entry.patBit = bits(pte, 12); entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1); tlb->insert(entry.vaddr, entry); - nextState = Ready; - delete read->req; - delete read; - read = NULL; - return; + stop(); + return NoFault; case PAEPDP: nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.pael2 * size; - if (!pte.p) - panic("Page at %#x not present!\n", entry.vaddr); + if (!pte.p) { + stop(); + return pageFault(pte.p); + } nextState = PAEPD; break; case PAEPD: @@ -187,10 +183,10 @@ Walker::doNext(PacketPtr &read, PacketPtr &write) pte.a = 1; entry.writable = pte.w; entry.user = pte.u; - if (badNX) - panic("NX violation!\n"); - if (!pte.p) - panic("Page at %#x not present!\n", entry.vaddr); + if (badNX || !pte.p) { + stop(); + return pageFault(pte.p); + } if (!pte.ps) { // 4 KB page entry.size = 4 * (1 << 10); @@ -206,39 +202,35 @@ Walker::doNext(PacketPtr &read, PacketPtr &write) entry.patBit = bits(pte, 12); entry.vaddr = entry.vaddr & ~((2 * (1 << 20)) - 1); tlb->insert(entry.vaddr, entry); - nextState = Ready; - delete read->req; - delete read; - read = NULL; - return; + stop(); + return NoFault; } case PAEPTE: doWrite = !pte.a; pte.a = 1; entry.writable = entry.writable && pte.w; entry.user = entry.user && pte.u; - if (badNX) - panic("NX violation!\n"); - if (!pte.p) - panic("Page at %#x not present!\n", entry.vaddr); + if (badNX || !pte.p) { + stop(); + return pageFault(pte.p); + } entry.paddr = (uint64_t)pte & (mask(40) << 12); entry.uncacheable = uncacheable; entry.global = pte.g; entry.patBit = bits(pte, 7); entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1); tlb->insert(entry.vaddr, entry); - nextState = Ready; - delete read->req; - delete read; - read = NULL; - return; + stop(); + return NoFault; case PSEPD: doWrite = !pte.a; pte.a = 1; entry.writable = pte.w; entry.user = pte.u; - if (!pte.p) - panic("Page at %#x not present!\n", entry.vaddr); + if (!pte.p) { + stop(); + return pageFault(pte.p); + } if (!pte.ps) { // 4 KB page entry.size = 4 * (1 << 10); @@ -255,44 +247,40 @@ Walker::doNext(PacketPtr &read, PacketPtr &write) entry.patBit = bits(pte, 12); entry.vaddr = entry.vaddr & ~((4 * (1 << 20)) - 1); tlb->insert(entry.vaddr, entry); - nextState = Ready; - delete read->req; - delete read; - read = NULL; - return; + stop(); + return NoFault; } case PD: doWrite = !pte.a; pte.a = 1; entry.writable = pte.w; entry.user = pte.u; - if (!pte.p) - panic("Page at %#x not present!\n", entry.vaddr); + if (!pte.p) { + stop(); + return pageFault(pte.p); + } // 4 KB page entry.size = 4 * (1 << 10); nextRead = ((uint64_t)pte & (mask(20) << 12)) + vaddr.norml2 * size; nextState = PTE; break; - nextState = PTE; - break; case PTE: doWrite = !pte.a; pte.a = 1; entry.writable = pte.w; entry.user = pte.u; - if (!pte.p) - panic("Page at %#x not present!\n", entry.vaddr); + if (!pte.p) { + stop(); + return pageFault(pte.p); + } entry.paddr = (uint64_t)pte & (mask(20) << 12); entry.uncacheable = uncacheable; entry.global = pte.g; entry.patBit = bits(pte, 7); entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1); tlb->insert(entry.vaddr, entry); - nextState = Ready; - delete read->req; - delete read; - read = NULL; - return; + stop(); + return NoFault; default: panic("Unknown page table walker state %d!\n"); } @@ -316,16 +304,21 @@ Walker::doNext(PacketPtr &read, PacketPtr &write) delete oldRead->req; delete oldRead; } + return NoFault; } -void -Walker::start(ThreadContext * _tc, Addr vaddr, bool _write, bool _execute) +Fault +Walker::start(ThreadContext * _tc, BaseTLB::Translation *_translation, + RequestPtr _req, bool _write, bool _execute) { assert(state == Ready); assert(!tc); tc = _tc; + req = _req; + Addr vaddr = req->getVaddr(); execute = _execute; write = _write; + translation = _translation; VAddr addr = vaddr; @@ -339,6 +332,7 @@ Walker::start(ThreadContext * _tc, Addr vaddr, bool _write, bool _execute) // Do long mode. state = LongPML4; top = (cr3.longPdtb << 12) + addr.longl4 * size; + enableNX = efer.nxe; } else { // We're in some flavor of legacy mode. CR4 cr4 = tc->readMiscRegNoEffect(MISCREG_CR4); @@ -346,6 +340,7 @@ Walker::start(ThreadContext * _tc, Addr vaddr, bool _write, bool _execute) // Do legacy PAE. state = PAEPDP; top = (cr3.paePdtb << 5) + addr.pael3 * size; + enableNX = efer.nxe; } else { size = 4; top = (cr3.pdtb << 12) + addr.norml2 * size; @@ -356,14 +351,13 @@ Walker::start(ThreadContext * _tc, Addr vaddr, bool _write, bool _execute) // Do legacy non PSE. state = PD; } + enableNX = false; } } nextState = Ready; entry.vaddr = vaddr; - enableNX = efer.nxe; - Request::Flags flags = Request::PHYSICAL; if (cr3.pcd) flags.set(Request::UNCACHEABLE); @@ -372,13 +366,15 @@ Walker::start(ThreadContext * _tc, Addr vaddr, bool _write, bool _execute) read->allocate(); Enums::MemoryMode memMode = sys->getMemoryMode(); if (memMode == Enums::timing) { - tc->suspend(); + timingFault = NoFault; port.sendTiming(read); } else if (memMode == Enums::atomic) { + Fault fault; do { port.sendAtomic(read); PacketPtr write = NULL; - doNext(read, write); + fault = doNext(read, write); + assert(fault == NoFault || read == NULL); state = nextState; nextState = Ready; if (write) @@ -387,9 +383,11 @@ Walker::start(ThreadContext * _tc, Addr vaddr, bool _write, bool _execute) tc = NULL; state = Ready; nextState = Waiting; + return fault; } else { panic("Unrecognized memory system mode.\n"); } + return NoFault; } bool @@ -410,9 +408,10 @@ Walker::recvTiming(PacketPtr pkt) state = nextState; nextState = Ready; PacketPtr write = NULL; - doNext(pkt, write); + timingFault = doNext(pkt, write); state = Waiting; read = pkt; + assert(timingFault == NoFault || read == NULL); if (write) { writes.push_back(write); } @@ -421,10 +420,27 @@ Walker::recvTiming(PacketPtr pkt) sendPackets(); } if (inflight == 0 && read == NULL && writes.size() == 0) { - tc->activate(0); tc = NULL; state = Ready; nextState = Waiting; + if (timingFault == NoFault) { + /* + * Finish the translation. Now that we now the right entry is + * in the TLB, this should work with no memory accesses. + * There could be new faults unrelated to the table walk like + * permissions violations, so we'll need the return value as + * well. + */ + bool delayedResponse; + Fault fault = tlb->translate(req, tc, NULL, write, execute, + delayedResponse, true); + assert(!delayedResponse); + // Let the CPU continue. + translation->finish(fault, req, tc, write); + } else { + // There was a fault during the walk. Let the CPU know. + translation->finish(timingFault, req, tc, write); + } } } else if (pkt->wasNacked()) { pkt->reinitNacked(); @@ -525,6 +541,14 @@ Walker::getPort(const std::string &if_name, int idx) panic("No page table walker port named %s!\n", if_name); } +Fault +Walker::pageFault(bool present) +{ + HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); + return new PageFault(entry.vaddr, present, write, + m5reg.cpl == 3, false, execute && enableNX); +} + } X86ISA::Walker * diff --git a/src/arch/x86/pagetable_walker.hh b/src/arch/x86/pagetable_walker.hh index de3f21195..992711acd 100644 --- a/src/arch/x86/pagetable_walker.hh +++ b/src/arch/x86/pagetable_walker.hh @@ -91,11 +91,22 @@ namespace X86ISA // if the machine is finished, or points to a packet to initiate // the next read. If any write is required to update an "accessed" // bit, write will point to a packet to do the write. Otherwise it - // will be NULL. - void doNext(PacketPtr &read, PacketPtr &write); + // will be NULL. The return value is whatever fault was incurred + // during this stage of the lookup. + Fault doNext(PacketPtr &read, PacketPtr &write); // Kick off the state machine. - void start(ThreadContext * _tc, Addr vaddr, bool write, bool execute); + Fault start(ThreadContext * _tc, BaseTLB::Translation *translation, + RequestPtr req, bool write, bool execute); + // Clean up after the state machine. + void + stop() + { + nextState = Ready; + delete read->req; + delete read; + read = NULL; + } protected: @@ -110,6 +121,11 @@ namespace X86ISA bool retrying; + /* + * The fault, if any, that's waiting to be delivered in timing mode. + */ + Fault timingFault; + /* * Functions for dealing with packets. */ @@ -156,16 +172,18 @@ namespace X86ISA // The TLB we're supposed to load. TLB * tlb; System * sys; + BaseTLB::Translation * translation; /* * State machine state. */ ThreadContext * tc; + RequestPtr req; State state; State nextState; int size; bool enableNX; - bool write, execute; + bool write, execute, user; TlbEntry entry; Fault pageFault(bool present); diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index a34922b44..3962cd607 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -72,6 +72,9 @@ #if FULL_SYSTEM #include "arch/x86/pagetable_walker.hh" +#else +#include "mem/page_table.hh" +#include "sim/process.hh" #endif namespace X86ISA { @@ -90,7 +93,7 @@ TLB::TLB(const Params *p) : BaseTLB(p), configAddress(0), size(p->size) #endif } -void +TlbEntry * TLB::insert(Addr vpn, TlbEntry &entry) { //TODO Deal with conflicting entries @@ -106,6 +109,7 @@ TLB::insert(Addr vpn, TlbEntry &entry) *newEntry = entry; newEntry->vaddr = vpn; entryList.push_front(newEntry); + return newEntry; } TLB::EntryList::iterator @@ -138,14 +142,6 @@ TLB::lookup(Addr va, bool update_lru) return *entry; } -#if FULL_SYSTEM -void -TLB::walk(ThreadContext * _tc, Addr vaddr, bool write, bool execute) -{ - walker->start(_tc, vaddr, write, execute); -} -#endif - void TLB::invalidateAll() { @@ -188,11 +184,12 @@ TLB::demapPage(Addr va, uint64_t asn) } } -template Fault -TLB::translateAtomic(RequestPtr req, ThreadContext *tc, - bool write, bool execute) +TLB::translate(RequestPtr req, ThreadContext *tc, + Translation *translation, bool write, bool execute, + bool &delayedResponse, bool timing) { + delayedResponse = false; Addr vaddr = req->getVaddr(); DPRINTF(TLB, "Translating vaddr %#x.\n", vaddr); uint32_t flags = req->getFlags(); @@ -617,14 +614,45 @@ TLB::translateAtomic(RequestPtr req, ThreadContext *tc, // The vaddr already has the segment base applied. TlbEntry *entry = lookup(vaddr); if (!entry) { - return new TlbFault(vaddr, write, execute); - } else { - // Do paging protection checks. - DPRINTF(TLB, "Entry found with paddr %#x, doing protection checks.\n", entry->paddr); - Addr paddr = entry->paddr | (vaddr & (entry->size-1)); - DPRINTF(TLB, "Translated %#x -> %#x.\n", vaddr, paddr); - req->setPaddr(paddr); +#if FULL_SYSTEM + Fault fault = walker->start(tc, translation, req, + write, execute); + if (timing || fault != NoFault) { + // This gets ignored in atomic mode. + delayedResponse = true; + return fault; + } + entry = lookup(vaddr); + assert(entry); +#else + DPRINTF(TLB, "Handling a TLB miss for " + "address %#x at pc %#x.\n", + vaddr, tc->readPC()); + + Process *p = tc->getProcessPtr(); + TlbEntry newEntry; + bool success = p->pTable->lookup(vaddr, newEntry); + if(!success && !execute) { + p->checkAndAllocNextPage(vaddr); + success = p->pTable->lookup(vaddr, newEntry); + } + if(!success) { + panic("Tried to execute unmapped address %#x.\n", vaddr); + } else { + Addr alignedVaddr = p->pTable->pageAlign(vaddr); + DPRINTF(TLB, "Mapping %#x to %#x\n", alignedVaddr, + newEntry.pageStart()); + entry = insert(alignedVaddr, newEntry); + } + DPRINTF(TLB, "Miss was serviced.\n"); +#endif } + // Do paging protection checks. + DPRINTF(TLB, "Entry found with paddr %#x, " + "doing protection checks.\n", entry->paddr); + Addr paddr = entry->paddr | (vaddr & (entry->size-1)); + DPRINTF(TLB, "Translated %#x -> %#x.\n", vaddr, paddr); + req->setPaddr(paddr); } else { //Use the address which already has segmentation applied. DPRINTF(TLB, "Paging disabled.\n"); @@ -665,29 +693,41 @@ TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Fault DTB::translateAtomic(RequestPtr req, ThreadContext *tc, bool write) { - return TLB::translateAtomic(req, tc, write, false); + bool delayedResponse; + return TLB::translate(req, tc, NULL, write, + false, delayedResponse, false); } void DTB::translateTiming(RequestPtr req, ThreadContext *tc, Translation *translation, bool write) { + bool delayedResponse; assert(translation); - translation->finish(translateAtomic(req, tc, write), req, tc, write); + Fault fault = TLB::translate(req, tc, translation, + write, false, delayedResponse, true); + if (!delayedResponse) + translation->finish(fault, req, tc, write); } Fault ITB::translateAtomic(RequestPtr req, ThreadContext *tc) { - return TLB::translateAtomic(req, tc, false, true); + bool delayedResponse; + return TLB::translate(req, tc, NULL, false, + true, delayedResponse, false); } void ITB::translateTiming(RequestPtr req, ThreadContext *tc, Translation *translation) { + bool delayedResponse; assert(translation); - translation->finish(translateAtomic(req, tc), req, tc, false); + Fault fault = TLB::translate(req, tc, translation, + false, true, delayedResponse, true); + if (!delayedResponse) + translation->finish(fault, req, tc, false); } #if FULL_SYSTEM diff --git a/src/arch/x86/tlb.hh b/src/arch/x86/tlb.hh index 56730983a..2467bc472 100644 --- a/src/arch/x86/tlb.hh +++ b/src/arch/x86/tlb.hh @@ -87,8 +87,7 @@ namespace X86ISA class TLB : public BaseTLB { protected: - friend class FakeITLBFault; - friend class FakeDTLBFault; + friend class Walker; typedef std::list EntryList; @@ -118,8 +117,6 @@ namespace X86ISA protected: Walker * walker; - - void walk(ThreadContext * _tc, Addr vaddr, bool write, bool execute); #endif public: @@ -137,15 +134,13 @@ namespace X86ISA EntryList freeList; EntryList entryList; - template - Fault translateAtomic(RequestPtr req, ThreadContext *tc, - bool write, bool execute); - void translateTiming(RequestPtr req, ThreadContext *tc, - Translation *translation, bool write, bool execute); + Fault translate(RequestPtr req, ThreadContext *tc, + Translation *translation, bool write, bool execute, + bool &delayedResponse, bool timing); public: - void insert(Addr vpn, TlbEntry &entry); + TlbEntry * insert(Addr vpn, TlbEntry &entry); // Checkpointing virtual void serialize(std::ostream &os); -- cgit v1.2.3 From 7462cb0842b9963d137cb578be6a0f7c619712d1 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:16:34 -0800 Subject: X86: Fix the timing mode of the page table walker. --- src/arch/x86/pagetable_walker.cc | 47 +++++++++++++++++++--------------------- src/arch/x86/pagetable_walker.hh | 6 ++--- 2 files changed, 25 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/arch/x86/pagetable_walker.cc b/src/arch/x86/pagetable_walker.cc index fe3a4c3bb..87f00dcbe 100644 --- a/src/arch/x86/pagetable_walker.cc +++ b/src/arch/x86/pagetable_walker.cc @@ -85,7 +85,7 @@ BitUnion64(PageTableEntry) EndBitUnion(PageTableEntry) Fault -Walker::doNext(PacketPtr &read, PacketPtr &write) +Walker::doNext(PacketPtr &write) { assert(state != Ready && state != Waiting); write = NULL; @@ -312,7 +312,6 @@ Walker::start(ThreadContext * _tc, BaseTLB::Translation *_translation, RequestPtr _req, bool _write, bool _execute) { assert(state == Ready); - assert(!tc); tc = _tc; req = _req; Addr vaddr = req->getVaddr(); @@ -366,21 +365,22 @@ Walker::start(ThreadContext * _tc, BaseTLB::Translation *_translation, read->allocate(); Enums::MemoryMode memMode = sys->getMemoryMode(); if (memMode == Enums::timing) { + nextState = state; + state = Waiting; timingFault = NoFault; - port.sendTiming(read); + sendPackets(); } else if (memMode == Enums::atomic) { Fault fault; do { port.sendAtomic(read); PacketPtr write = NULL; - fault = doNext(read, write); + fault = doNext(write); assert(fault == NoFault || read == NULL); state = nextState; nextState = Ready; if (write) port.sendAtomic(write); } while(read); - tc = NULL; state = Ready; nextState = Waiting; return fault; @@ -399,18 +399,18 @@ Walker::WalkerPort::recvTiming(PacketPtr pkt) bool Walker::recvTiming(PacketPtr pkt) { - inflight--; if (pkt->isResponse() && !pkt->wasNacked()) { + assert(inflight); + assert(state == Waiting); + assert(!read); + inflight--; if (pkt->isRead()) { - assert(inflight); - assert(state == Waiting); - assert(!read); state = nextState; nextState = Ready; PacketPtr write = NULL; - timingFault = doNext(pkt, write); - state = Waiting; read = pkt; + timingFault = doNext(write); + state = Waiting; assert(timingFault == NoFault || read == NULL); if (write) { writes.push_back(write); @@ -420,7 +420,6 @@ Walker::recvTiming(PacketPtr pkt) sendPackets(); } if (inflight == 0 && read == NULL && writes.size() == 0) { - tc = NULL; state = Ready; nextState = Waiting; if (timingFault == NoFault) { @@ -445,6 +444,7 @@ Walker::recvTiming(PacketPtr pkt) } else if (pkt->wasNacked()) { pkt->reinitNacked(); if (!port.sendTiming(pkt)) { + inflight--; retrying = true; if (pkt->isWrite()) { writes.push_back(pkt); @@ -452,8 +452,6 @@ Walker::recvTiming(PacketPtr pkt) assert(!read); read = pkt; } - } else { - inflight++; } } return true; @@ -507,27 +505,26 @@ Walker::sendPackets() //Reads always have priority if (read) { - if (!port.sendTiming(read)) { + PacketPtr pkt = read; + read = NULL; + inflight++; + if (!port.sendTiming(pkt)) { retrying = true; + read = pkt; + inflight--; return; - } else { - inflight++; - delete read->req; - delete read; - read = NULL; } } //Send off as many of the writes as we can. while (writes.size()) { PacketPtr write = writes.back(); + writes.pop_back(); + inflight++; if (!port.sendTiming(write)) { retrying = true; + writes.push_back(write); + inflight--; return; - } else { - inflight++; - delete write->req; - delete write; - writes.pop_back(); } } } diff --git a/src/arch/x86/pagetable_walker.hh b/src/arch/x86/pagetable_walker.hh index 992711acd..f73774a45 100644 --- a/src/arch/x86/pagetable_walker.hh +++ b/src/arch/x86/pagetable_walker.hh @@ -85,15 +85,15 @@ namespace X86ISA PSEPD, PD, PTE }; - // Act on the current state and determine what to do next. read - // should be the packet that just came back from a read and write + // Act on the current state and determine what to do next. The global + // read should be the packet that just came back from a read and write // should be NULL. When the function returns, read is either NULL // if the machine is finished, or points to a packet to initiate // the next read. If any write is required to update an "accessed" // bit, write will point to a packet to do the write. Otherwise it // will be NULL. The return value is whatever fault was incurred // during this stage of the lookup. - Fault doNext(PacketPtr &read, PacketPtr &write); + Fault doNext(PacketPtr &write); // Kick off the state machine. Fault start(ThreadContext * _tc, BaseTLB::Translation *translation, -- cgit v1.2.3 From 82288e7c3eea0fc62746d746e325c888a13c0a22 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:16:43 -0800 Subject: X86: Add makeAtomicResponse to the read/write functions of x86 devices. --- src/arch/x86/interrupts.cc | 2 ++ src/dev/x86/cmos.cc | 2 ++ src/dev/x86/i8042.cc | 2 ++ src/dev/x86/i82094aa.cc | 2 ++ src/dev/x86/i8237.cc | 2 ++ src/dev/x86/i8254.cc | 2 ++ src/dev/x86/i8259.cc | 2 ++ src/dev/x86/speaker.cc | 2 ++ 8 files changed, 16 insertions(+) (limited to 'src') diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc index 29157b3f5..30c532c2b 100644 --- a/src/arch/x86/interrupts.cc +++ b/src/arch/x86/interrupts.cc @@ -221,6 +221,7 @@ X86ISA::Interrupts::read(PacketPtr pkt) "Reading Local APIC register %d at offset %#x as %#x.\n", reg, offset, val); pkt->setData(((uint8_t *)&val) + (offset & mask(3))); + pkt->makeAtomicResponse(); return latency; } @@ -238,6 +239,7 @@ X86ISA::Interrupts::write(PacketPtr pkt) "Writing Local APIC register %d at offset %#x as %#x.\n", reg, offset, gtoh(val)); setReg(reg, gtoh(val)); + pkt->makeAtomicResponse(); return latency; } void diff --git a/src/dev/x86/cmos.cc b/src/dev/x86/cmos.cc index 6bdc78a4b..e08c56e8c 100644 --- a/src/dev/x86/cmos.cc +++ b/src/dev/x86/cmos.cc @@ -56,6 +56,7 @@ X86ISA::Cmos::read(PacketPtr pkt) default: panic("Read from undefined CMOS port.\n"); } + pkt->makeAtomicResponse(); return latency; } @@ -74,6 +75,7 @@ X86ISA::Cmos::write(PacketPtr pkt) default: panic("Write to undefined CMOS port.\n"); } + pkt->makeAtomicResponse(); return latency; } diff --git a/src/dev/x86/i8042.cc b/src/dev/x86/i8042.cc index 78ce307ae..afcbfdfb4 100644 --- a/src/dev/x86/i8042.cc +++ b/src/dev/x86/i8042.cc @@ -303,6 +303,7 @@ X86ISA::I8042::read(PacketPtr pkt) } else { panic("Read from unrecognized port %#x.\n", addr); } + pkt->makeAtomicResponse(); return latency; } @@ -434,6 +435,7 @@ X86ISA::I8042::write(PacketPtr pkt) } else { panic("Write to unrecognized port %#x.\n", addr); } + pkt->makeAtomicResponse(); return latency; } diff --git a/src/dev/x86/i82094aa.cc b/src/dev/x86/i82094aa.cc index 03944c190..d160fcb24 100644 --- a/src/dev/x86/i82094aa.cc +++ b/src/dev/x86/i82094aa.cc @@ -67,6 +67,7 @@ X86ISA::I82094AA::read(PacketPtr pkt) default: panic("Illegal read from I/O APIC.\n"); } + pkt->makeAtomicResponse(); return latency; } @@ -85,6 +86,7 @@ X86ISA::I82094AA::write(PacketPtr pkt) default: panic("Illegal write to I/O APIC.\n"); } + pkt->makeAtomicResponse(); return latency; } diff --git a/src/dev/x86/i8237.cc b/src/dev/x86/i8237.cc index 5afe6b91a..f6ea9d75f 100644 --- a/src/dev/x86/i8237.cc +++ b/src/dev/x86/i8237.cc @@ -63,6 +63,7 @@ X86ISA::I8237::read(PacketPtr pkt) default: panic("Read from undefined i8237 register %d.\n", offset); } + pkt->makeAtomicResponse(); return latency; } @@ -120,6 +121,7 @@ X86ISA::I8237::write(PacketPtr pkt) default: panic("Write to undefined i8254 register.\n"); } + pkt->makeAtomicResponse(); return latency; } diff --git a/src/dev/x86/i8254.cc b/src/dev/x86/i8254.cc index 4f37eebad..5eb28844a 100644 --- a/src/dev/x86/i8254.cc +++ b/src/dev/x86/i8254.cc @@ -56,6 +56,7 @@ X86ISA::I8254::read(PacketPtr pkt) } else { panic("Read from undefined i8254 register.\n"); } + pkt->makeAtomicResponse(); return latency; } @@ -71,6 +72,7 @@ X86ISA::I8254::write(PacketPtr pkt) } else { panic("Write to undefined i8254 register.\n"); } + pkt->makeAtomicResponse(); return latency; } diff --git a/src/dev/x86/i8259.cc b/src/dev/x86/i8259.cc index f9e0a0c93..b868295eb 100644 --- a/src/dev/x86/i8259.cc +++ b/src/dev/x86/i8259.cc @@ -65,6 +65,7 @@ X86ISA::I8259::read(PacketPtr pkt) pkt->set(IMR); break; } + pkt->makeAtomicResponse(); return latency; } @@ -210,6 +211,7 @@ X86ISA::I8259::write(PacketPtr pkt) } break; } + pkt->makeAtomicResponse(); return latency; } diff --git a/src/dev/x86/speaker.cc b/src/dev/x86/speaker.cc index 25014d0c6..c6eb9db9e 100644 --- a/src/dev/x86/speaker.cc +++ b/src/dev/x86/speaker.cc @@ -47,6 +47,7 @@ X86ISA::Speaker::read(PacketPtr pkt) controlVal.speaker ? "on" : "off", controlVal.timer ? "on" : "off"); pkt->set((uint8_t)controlVal); + pkt->makeAtomicResponse(); return latency; } @@ -67,6 +68,7 @@ X86ISA::Speaker::write(PacketPtr pkt) controlVal.speaker = val.speaker; DPRINTF(PcSpeaker, "Writing to speaker device: gate %s, speaker %s.\n", controlVal.gate ? "on" : "off", controlVal.speaker ? "on" : "off"); + pkt->makeAtomicResponse(); return latency; } -- cgit v1.2.3 From 7b1cb74ac3c2b9a2a22f64ed88bd60fb353c76d7 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:16:54 -0800 Subject: X86: Add a check to chks which raises #GP(selector) if selector is NULL or not in the GDT. --- src/arch/x86/isa/microasm.isa | 3 ++- src/arch/x86/isa/microops/regop.isa | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa index 778754e0c..354ee089e 100644 --- a/src/arch/x86/isa/microasm.isa +++ b/src/arch/x86/isa/microasm.isa @@ -86,7 +86,8 @@ let {{ # Add in symbols for the various checks of segment selectors. for check in ("NoCheck", "CSCheck", "CallGateCheck", "IntGateCheck", - "SoftIntGateCheck", "SSCheck", "IretCheck", "IntCSCheck"): + "SoftIntGateCheck", "SSCheck", "IretCheck", "IntCSCheck", + "TRCheck"): assembler.symbols[check] = "Seg%s" % check for reg in ("TR", "IDTR"): diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 567335b7f..9fb8b2f92 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -234,7 +234,8 @@ output header {{ enum SegmentSelectorCheck { SegNoCheck, SegCSCheck, SegCallGateCheck, SegIntGateCheck, - SegSoftIntGateCheck, SegSSCheck, SegIretCheck, SegIntCSCheck + SegSoftIntGateCheck, SegSSCheck, SegIretCheck, SegIntCSCheck, + SegTRCheck }; enum LongModeDescriptorType { @@ -1118,6 +1119,11 @@ let {{ "in legacy mode.\\n"); } break; + case SegTRCheck: + if (!selector.si || selector.ti) { + fault = new GeneralProtection(selector); + } + break; default: panic("Undefined segment check type.\\n"); } -- cgit v1.2.3 From 2f31643db52927d5c2e06d14e21846f1137d915a Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:17:02 -0800 Subject: X86: Add a check to chks to verify a task state segment descriptor. --- src/arch/x86/isa/microasm.isa | 2 +- src/arch/x86/isa/microops/regop.isa | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa index 354ee089e..d1025b137 100644 --- a/src/arch/x86/isa/microasm.isa +++ b/src/arch/x86/isa/microasm.isa @@ -87,7 +87,7 @@ let {{ # Add in symbols for the various checks of segment selectors. for check in ("NoCheck", "CSCheck", "CallGateCheck", "IntGateCheck", "SoftIntGateCheck", "SSCheck", "IretCheck", "IntCSCheck", - "TRCheck"): + "TRCheck", "TSSCheck"): assembler.symbols[check] = "Seg%s" % check for reg in ("TR", "IDTR"): diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 9fb8b2f92..0d569d403 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -235,7 +235,7 @@ output header {{ enum SegmentSelectorCheck { SegNoCheck, SegCSCheck, SegCallGateCheck, SegIntGateCheck, SegSoftIntGateCheck, SegSSCheck, SegIretCheck, SegIntCSCheck, - SegTRCheck + SegTRCheck, SegTSSCheck }; enum LongModeDescriptorType { @@ -1124,6 +1124,15 @@ let {{ fault = new GeneralProtection(selector); } break; + case SegTSSCheck: + if (!desc.p) { + fault = new SegmentNotPresent(selector); + } else if (!(desc.type == 0x9 || + (desc.type == 1 && + m5reg.mode != LongMode))) { + + } + break; default: panic("Undefined segment check type.\\n"); } -- cgit v1.2.3 From 08f3a126d540a88474a654720ecc7ceab9e0c246 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:17:08 -0800 Subject: X86: Fix segment limit checking. --- src/arch/x86/isa/microops/regop.isa | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 0d569d403..f21621e30 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -1192,10 +1192,12 @@ let {{ attr.dpl = desc.dpl; attr.defaultSize = desc.d; if (!desc.s) { - SegBaseDest = SegBaseDest; - SegLimitDest = SegLimitDest; - SegAttrDest = SegAttrDest; - panic("System segment encountered.\\n"); + // The expand down bit happens to be set for gates. + if (desc.type.e) { + panic("Gate descriptor encountered.\\n"); + } + attr.readable = 1; + attr.writable = 1; } else { if (!desc.p) panic("Segment not present.\\n"); @@ -1207,14 +1209,14 @@ let {{ attr.readable = 1; attr.writable = desc.type.w; } - Addr base = desc.baseLow | (desc.baseHigh << 24); - Addr limit = desc.limitLow | (desc.limitHigh << 16); - if (desc.g) - limit = (limit << 12) | mask(12); - SegBaseDest = base; - SegLimitDest = limit; - SegAttrDest = attr; } + Addr base = desc.baseLow | (desc.baseHigh << 24); + Addr limit = desc.limitLow | (desc.limitHigh << 16); + if (desc.g) + limit = (limit << 12) | mask(12); + SegBaseDest = base; + SegLimitDest = limit; + SegAttrDest = attr; } else { SegBaseDest = SegBaseDest; SegLimitDest = SegLimitDest; -- cgit v1.2.3 From aa7bc1be74beac674cc4feb4fece534de10379e3 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:17:14 -0800 Subject: X86: Implement the LTR instruction. --- src/arch/x86/isa/decoder/two_byte_opcodes.isa | 2 +- src/arch/x86/isa/insts/system/segmentation.py | 48 +++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index 3cdfa48bb..67845fe8d 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -94,7 +94,7 @@ 0x0: sldt_Mw_or_Rv(); 0x1: str_Mw_or_Rv(); 0x2: lldt_Mw_or_Rv(); - 0x3: ltr_Mw_or_Rv(); + 0x3: Inst::LTR(Ew); 0x4: verr_Mw_or_Rv(); 0x5: verw_Mw_or_Rv(); //0x6: jmpe_Ev(); // IA-64 diff --git a/src/arch/x86/isa/insts/system/segmentation.py b/src/arch/x86/isa/insts/system/segmentation.py index 49d8eb110..c2bb46b7c 100644 --- a/src/arch/x86/isa/insts/system/segmentation.py +++ b/src/arch/x86/isa/insts/system/segmentation.py @@ -168,6 +168,54 @@ def macroop LIDT_16_P wrlimit idtr, t1 }; +def macroop LTR_R +{ + chks reg, t0, TRCheck + limm t4, 0 + srli t4, reg, 3, dataSize=2 + ldst t1, tsg, [8, t4, t0], dataSize=8 + ld t2, tsg, [8, t4, t0], 8, dataSize=8 + chks reg, t1, TSSCheck + wrdh t3, t1, t2 + wrdl tr, t1, reg + wrbase tr, t3, dataSize=8 + ori t1, t1, (1 << 9) + st t1, tsg, [8, t4, t0], dataSize=8 +}; + +def macroop LTR_M +{ + ld t5, seg, sib, disp, dataSize=2 + chks t5, t0, TRCheck + limm t4, 0 + srli t4, t5, 3, dataSize=2 + ldst t1, tsg, [8, t4, t0], dataSize=8 + ld t2, tsg, [8, t4, t0], 8, dataSize=8 + chks t5, t1, TSSCheck + wrdh t3, t1, t2 + wrdl tr, t1, t5 + wrbase tr, t3, dataSize=8 + ori t1, t1, (1 << 9) + st t1, tsg, [8, t4, t0], dataSize=8 +}; + +def macroop LTR_P +{ + rdip t7 + ld t5, seg, riprel, disp, dataSize=2 + chks t5, t0, TRCheck + limm t4, 0 + srli t4, t5, 3, dataSize=2 + ldst t1, tsg, [8, t4, t0], dataSize=8 + ld t2, tsg, [8, t4, t0], 8, dataSize=8 + chks t5, t1, TSSCheck + wrdh t3, t1, t2 + wrdl tr, t1, t5 + wrbase tr, t3, dataSize=8 + ori t1, t1, (1 << 9) + st t1, tsg, [8, t4, t0], dataSize=8 +}; + def macroop SWAPGS { rdval t1, kernel_gs_base, dataSize=8 -- cgit v1.2.3 From 99aa121fca8c893fb9f5b83b2568893033818ae3 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:17:19 -0800 Subject: X86: Make exceptions handle stack switching. --- src/arch/x86/isa/insts/romutil.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/romutil.py b/src/arch/x86/isa/insts/romutil.py index 1345c3d05..a39ba202f 100644 --- a/src/arch/x86/isa/insts/romutil.py +++ b/src/arch/x86/isa/insts/romutil.py @@ -80,29 +80,22 @@ def rom andi t10, t10, 3, dataSize=8 rdattr t5, cs, dataSize=8 srli t5, t5, 3, dataSize=8 - sub t5, t5, t10, dataSize=8 - andi t0, t5, 0x3, flags=(EZF,), dataSize=8 + andi t5, t5, 0x3, dataSize=8 + sub t0, t5, t10, flags=(EZF,), dataSize=8 # We're going to change priviledge, so zero out the stack selector. We # need to let the IST have priority so we don't branch yet. wrsel t11, t0, flags=(nCEZF,) # Check the IST field of the gate descriptor - srli t10, t4, 32, dataSize=8 - andi t10, t10, 0x7, dataSize=8 - subi t0, t10, 1, flags=(ECF,), dataSize=8 + srli t12, t4, 32, dataSize=8 + andi t12, t12, 0x7, dataSize=8 + subi t0, t12, 1, flags=(ECF,), dataSize=8 br rom_local_label("%(startLabel)s_istStackSwitch"), flags=(nCECF,) br rom_local_label("%(startLabel)s_cplStackSwitch"), flags=(nCEZF,) # If we're here, it's because the stack isn't being switched. # Set t6 to the new aligned rsp. mov t6, t6, rsp, dataSize=8 - andi t6, t6, 0xF0, dataSize=1 - subi t6, t6, 40 + %(errorCodeSize)d, dataSize=8 - - # Check that we can access everything we need to on the stack - ldst t0, hs, [1, t0, t6], dataSize=8, addressSize=8 - ldst t0, hs, [1, t0, t6], \ - 32 + %(errorCodeSize)d, dataSize=8, addressSize=8 br rom_local_label("%(startLabel)s_stackSwitched") %(startLabel)s_istStackSwitch: @@ -110,10 +103,18 @@ def rom br rom_local_label("%(startLabel)s_stackSwitched") %(startLabel)s_cplStackSwitch: - panic "CPL change initiated stack switching isn't implemented" + # Get the new rsp from the TSS + ld t6, tr, [8, t10, t0], 4, dataSize=8, addressSize=8 %(startLabel)s_stackSwitched: + andi t6, t6, 0xF0, dataSize=1 + subi t6, t6, 40 + %(errorCodeSize)d, dataSize=8 + + # Check that we can access everything we need to on the stack + ldst t0, hs, [1, t0, t6], dataSize=8, addressSize=8 + ldst t0, hs, [1, t0, t6], \ + 32 + %(errorCodeSize)d, dataSize=8, addressSize=8 ## ## Point of no return. -- cgit v1.2.3 From e4ede69b2f97206d836719839221531f3e01149e Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:17:27 -0800 Subject: X86: Add a trace flag for the page table walker. --- src/arch/x86/SConscript | 2 ++ src/arch/x86/pagetable_walker.cc | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+) (limited to 'src') diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript index a57e388ea..8c1aec7a7 100644 --- a/src/arch/x86/SConscript +++ b/src/arch/x86/SConscript @@ -111,6 +111,8 @@ if env['TARGET_ISA'] == 'x86': if env['FULL_SYSTEM']: TraceFlag('LocalApic', "Local APIC debugging") + TraceFlag('PageTableWalker', \ + "Page table walker state machine debugging") SimObject('X86LocalApic.py') SimObject('X86System.py') diff --git a/src/arch/x86/pagetable_walker.cc b/src/arch/x86/pagetable_walker.cc index 87f00dcbe..f625cf4bd 100644 --- a/src/arch/x86/pagetable_walker.cc +++ b/src/arch/x86/pagetable_walker.cc @@ -101,6 +101,8 @@ Walker::doNext(PacketPtr &write) bool badNX = pte.nx && (!tlb->allowNX() || !enableNX); switch(state) { case LongPML4: + DPRINTF(PageTableWalker, + "Got long mode PML4 entry %#016x.\n", (uint64_t)pte); nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.longl3 * size; doWrite = !pte.a; pte.a = 1; @@ -114,6 +116,8 @@ Walker::doNext(PacketPtr &write) nextState = LongPDP; break; case LongPDP: + DPRINTF(PageTableWalker, + "Got long mode PDP entry %#016x.\n", (uint64_t)pte); nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.longl2 * size; doWrite = !pte.a; pte.a = 1; @@ -126,6 +130,8 @@ Walker::doNext(PacketPtr &write) nextState = LongPD; break; case LongPD: + DPRINTF(PageTableWalker, + "Got long mode PD entry %#016x.\n", (uint64_t)pte); doWrite = !pte.a; pte.a = 1; entry.writable = entry.writable && pte.w; @@ -154,6 +160,8 @@ Walker::doNext(PacketPtr &write) return NoFault; } case LongPTE: + DPRINTF(PageTableWalker, + "Got long mode PTE entry %#016x.\n", (uint64_t)pte); doWrite = !pte.a; pte.a = 1; entry.writable = entry.writable && pte.w; @@ -171,6 +179,8 @@ Walker::doNext(PacketPtr &write) stop(); return NoFault; case PAEPDP: + DPRINTF(PageTableWalker, + "Got legacy mode PAE PDP entry %#08x.\n", (uint32_t)pte); nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.pael2 * size; if (!pte.p) { stop(); @@ -179,6 +189,8 @@ Walker::doNext(PacketPtr &write) nextState = PAEPD; break; case PAEPD: + DPRINTF(PageTableWalker, + "Got legacy mode PAE PD entry %#08x.\n", (uint32_t)pte); doWrite = !pte.a; pte.a = 1; entry.writable = pte.w; @@ -206,6 +218,8 @@ Walker::doNext(PacketPtr &write) return NoFault; } case PAEPTE: + DPRINTF(PageTableWalker, + "Got legacy mode PAE PTE entry %#08x.\n", (uint32_t)pte); doWrite = !pte.a; pte.a = 1; entry.writable = entry.writable && pte.w; @@ -223,6 +237,8 @@ Walker::doNext(PacketPtr &write) stop(); return NoFault; case PSEPD: + DPRINTF(PageTableWalker, + "Got legacy mode PSE PD entry %#08x.\n", (uint32_t)pte); doWrite = !pte.a; pte.a = 1; entry.writable = pte.w; @@ -251,6 +267,8 @@ Walker::doNext(PacketPtr &write) return NoFault; } case PD: + DPRINTF(PageTableWalker, + "Got legacy mode PD entry %#08x.\n", (uint32_t)pte); doWrite = !pte.a; pte.a = 1; entry.writable = pte.w; @@ -265,6 +283,8 @@ Walker::doNext(PacketPtr &write) nextState = PTE; break; case PTE: + DPRINTF(PageTableWalker, + "Got legacy mode PTE entry %#08x.\n", (uint32_t)pte); doWrite = !pte.a; pte.a = 1; entry.writable = pte.w; @@ -541,6 +561,7 @@ Walker::getPort(const std::string &if_name, int idx) Fault Walker::pageFault(bool present) { + DPRINTF(PageTableWalker, "Raising page fault.\n"); HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); return new PageFault(entry.vaddr, present, write, m5reg.cpl == 3, false, execute && enableNX); -- cgit v1.2.3 From fcad6e3b13410ab6c7263ce42b5e657c16f79e1d Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:17:38 -0800 Subject: X86: Add a wrattr microop. --- src/arch/x86/isa/microops/regop.isa | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index f21621e30..4434f9e74 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -1009,6 +1009,11 @@ let {{ SegSelDest = psrc1; ''' + class WrAttr(SegOp): + code = ''' + SegAttrDest = psrc1; + ''' + class Rdbase(SegOp): code = ''' DestReg = SegBaseSrc1; -- cgit v1.2.3 From dadc30b0a4dcf50c20c9d2b33890b94323fa0394 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:17:43 -0800 Subject: X86: Make the microcode assembler recognize r8-r15. --- src/arch/x86/isa/microasm.isa | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa index d1025b137..fe1d38ff1 100644 --- a/src/arch/x86/isa/microasm.isa +++ b/src/arch/x86/isa/microasm.isa @@ -138,7 +138,8 @@ let {{ # like the internal segment above assembler.symbols["flatseg"] = "SEGMENT_REG_LS" - for reg in ('ax', 'bx', 'cx', 'dx', 'sp', 'bp', 'si', 'di'): + for reg in ('ax', 'bx', 'cx', 'dx', 'sp', 'bp', 'si', 'di', \ + '8', '9', '10', '11', '12', '13', '14', '15'): assembler.symbols["r%s" % reg] = "INTREG_R%s" % reg.upper() for reg in range(16): -- cgit v1.2.3 From 6325245e3ea7fae6609d0e9854c5ee7279140c02 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:17:49 -0800 Subject: X86: Implement the longmode versions of the syscall instruction. --- src/arch/x86/isa/decoder/two_byte_opcodes.isa | 8 +- .../x86/isa/insts/general_purpose/system_calls.py | 107 ++++++++++++++++++++- 2 files changed, 111 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index 67845fe8d..887b5bb14 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -254,7 +254,13 @@ } } #if FULL_SYSTEM - 0x05: syscall(); + 0x05: decode MODE_MODE { + 0x0: decode MODE_SUBMODE { + 0x0: Inst::SYSCALL_64(); + 0x1: Inst::SYSCALL_COMPAT(); + } + 0x1: Inst::SYSCALL_LEGACY(); + } #else 0x05: SyscallInst::syscall('xc->syscall(Rax)', IsSyscall); #endif diff --git a/src/arch/x86/isa/insts/general_purpose/system_calls.py b/src/arch/x86/isa/insts/general_purpose/system_calls.py index b3a57eca9..bb08282d2 100644 --- a/src/arch/x86/isa/insts/general_purpose/system_calls.py +++ b/src/arch/x86/isa/insts/general_purpose/system_calls.py @@ -53,14 +53,115 @@ # # Authors: Gabe Black -microcode = "" +microcode = ''' +def macroop SYSCALL_64 +{ + # All 1s. + limm t1, "(uint64_t)(-1)" + + # Save the next RIP. + rdip rcx + + # Stick rflags with RF masked into r11. + rflags t2 + limm t3, "~RFBit" + andi r11, t2, t3, dataSize=8 + + rdval t3, star + srli t3, t3, 32, dataSize=8 + andi t3, t3, 0xFC, dataSize=1 + + # Set up CS. + wrsel cs, t3 + wrbase cs, t0, dataSize=8 + wrlimit cs, t1, dataSize=4 + # Not writable, read/execute-able, not expandDown, + # dpl=0, defaultSize=0, long mode + limm t4, ((0 << 0) | (1 << 1) | (0 << 2) | \ + (0 << 3) | (0 << 5) | (1 << 6)) + wrattr cs, t4 + + # Set up SS. + addi t3, t3, 8 + wrsel ss, t3 + wrbase ss, t0, dataSize=8 + wrlimit ss, t1, dataSize=4 + # Writable, readable, not expandDown, + # dpl=0, defaultSize=0, not long mode + limm t4, ((1 << 0) | (1 << 1) | (0 << 2) | \ + (0 << 3) | (0 << 5) | (0 << 6)) + wrattr ss, t4 + + # Set the new rip. + rdval t7, lstar + wrip t0, t7 + + # Mask the flags against sf_mask and leave RF turned off. + rdval t3, sf_mask, dataSize=8 + xor t3, t3, t1, dataSize=8 + and t3, t3, r11, dataSize=8 + wrflags t3, t0 +}; + +def macroop SYSCALL_COMPAT +{ + # All 1s. + limm t1, "(uint64_t)(-1)" + + # Save the next RIP. + rdip rcx + + # Stick rflags with RF masked into r11. + rflags t2 + limm t3, "~RFBit" + andi r11, t2, t3, dataSize=8 + + rdval t3, star + srli t3, t3, 32, dataSize=8 + andi t3, t3, 0xFC, dataSize=1 + + # Set up CS. + wrsel cs, t3 + wrbase cs, t0, dataSize=8 + wrlimit cs, t1, dataSize=4 + # Not writable, read/execute-able, not expandDown, + # dpl=0, defaultSize=0, long mode + limm t4, ((0 << 0) | (1 << 1) | (0 << 2) | \ + (0 << 3) | (0 << 5) | (1 << 6)) + wrattr cs, t4 + + # Set up SS. + addi t3, t3, 8 + wrsel ss, t3 + wrbase ss, t0, dataSize=8 + wrlimit ss, t1, dataSize=4 + # Writable, readable, not expandDown, + # dpl=0, defaultSize=0, not long mode + limm t4, ((1 << 0) | (1 << 1) | (0 << 2) | \ + (0 << 3) | (0 << 5) | (0 << 6)) + wrattr ss, t4 + + # Set the new rip. + rdval t7, cstar + wrip t0, t7 + + # Mask the flags against sf_mask and leave RF turned off. + rdval t3, sf_mask, dataSize=8 + xor t3, t3, t1, dataSize=8 + and t3, t3, r11, dataSize=8 + wrflags t3, t0 +}; + +def macroop SYSCALL_LEGACY +{ + panic "The syscall instruction isn't implemented in legacy mode." +}; +''' #let {{ # class SYSENTER(Inst): # "GenFault ${new UnimpInstFault}" # class SYSEXIT(Inst): # "GenFault ${new UnimpInstFault}" -# class SYSCALL(Inst): -# "GenFault ${new UnimpInstFault}" # class SYSRET(Inst): # "GenFault ${new UnimpInstFault}" #}}; -- cgit v1.2.3 From eec3f49a57aca83e492e72b9cf55a8c6c6ebae73 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:17:54 -0800 Subject: X86: Implement the sysret instruction in long mode. --- src/arch/x86/isa/decoder/two_byte_opcodes.isa | 12 +++- .../x86/isa/insts/general_purpose/system_calls.py | 72 +++++++++++++++++++++- 2 files changed, 79 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index 887b5bb14..fa49c55d3 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -265,9 +265,15 @@ 0x05: SyscallInst::syscall('xc->syscall(Rax)', IsSyscall); #endif 0x06: clts(); - //sandpile.org says (AMD) after sysret, so I might want to check - //if that means amd64 or AMD machines - 0x07: loadall_or_sysret(); + 0x07: decode MODE_SUBMODE { + 0x0: decode OPSIZE { + // Return to 64 bit mode. + 0x8: Inst::SYSRET_TO_64(); + // Return to compatibility mode. + default: Inst::SYSRET_TO_COMPAT(); + } + default: Inst::SYSRET_NON_64(); + } } 0x01: decode OPCODE_OP_BOTTOM3 { 0x0: invd(); diff --git a/src/arch/x86/isa/insts/general_purpose/system_calls.py b/src/arch/x86/isa/insts/general_purpose/system_calls.py index bb08282d2..67607d5f8 100644 --- a/src/arch/x86/isa/insts/general_purpose/system_calls.py +++ b/src/arch/x86/isa/insts/general_purpose/system_calls.py @@ -156,12 +156,80 @@ def macroop SYSCALL_LEGACY { panic "The syscall instruction isn't implemented in legacy mode." }; + +def macroop SYSRET_TO_64 +{ + # All 1s. + limm t1, "(uint64_t)(-1)" + + rdval t3, star + srli t3, t3, 48, dataSize=8 + ori t3, t3, 3, dataSize=1 + + # Set rflags to r11 with RF and VM cleared. + limm t4, "~(RFBit | VMBit)" + and t4, t4, r11, dataSize=8 + wrflags t4, t0 + + # Set up CS. + addi t4, t3, 16, dataSize=8 + wrsel cs, t4 + wrbase cs, t0, dataSize=8 + wrlimit cs, t1, dataSize=4 + # Not writable, read/execute-able, not expandDown, + # dpl=3, defaultSize=0, long mode + limm t4, ((0 << 0) | (1 << 1) | (0 << 2) | \ + (3 << 3) | (0 << 5) | (1 << 6)) + wrattr cs, t4 + + # Only the selector is changed for SS. + addi t4, t3, 8, dataSize=8 + wrsel ss, t4 + + # Set the RIP back. + wrip rcx, t0, dataSize=8 +}; + +def macroop SYSRET_TO_COMPAT +{ + # All 1s. + limm t1, "(uint64_t)(-1)" + + rdval t3, star + srli t3, t3, 48, dataSize=8 + ori t3, t3, 3, dataSize=1 + + # Set rflags to r11 with RF and VM cleared. + limm t4, "~(RFBit | VMBit)" + and t4, t4, r11, dataSize=8 + wrflags t4, t0 + + # Set up CS. + wrsel cs, t3 + wrbase cs, t0, dataSize=8 + wrlimit cs, t1, dataSize=4 + # Not writable, read/execute-able, not expandDown, + # dpl=3, defaultSize=1, not long mode + limm t4, ((0 << 0) | (1 << 1) | (0 << 2) | \ + (3 << 3) | (1 << 5) | (0 << 6)) + wrattr cs, t4 + + # Only the selector is changed for SS. + addi t4, t3, 8, dataSize=8 + wrsel ss, t4 + + # Set the RIP back. + wrip rcx, t0, dataSize=8 +}; + +def macroop SYSRET_NON_64 +{ + panic "The sysret instruction isn't implemented in legacy mode." +}; ''' #let {{ # class SYSENTER(Inst): # "GenFault ${new UnimpInstFault}" # class SYSEXIT(Inst): # "GenFault ${new UnimpInstFault}" -# class SYSRET(Inst): -# "GenFault ${new UnimpInstFault}" #}}; -- cgit v1.2.3 From 1cedc748d413513c1bb98a454cc035f35b30f0f9 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:17:59 -0800 Subject: X86: Add a trace flag for tracing faults. --- src/arch/x86/SConscript | 1 + src/arch/x86/faults.cc | 24 +++++++++++++++++++++++- src/arch/x86/faults.hh | 8 +++++++- 3 files changed, 31 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript index 8c1aec7a7..0e13d3104 100644 --- a/src/arch/x86/SConscript +++ b/src/arch/x86/SConscript @@ -113,6 +113,7 @@ if env['TARGET_ISA'] == 'x86': TraceFlag('LocalApic', "Local APIC debugging") TraceFlag('PageTableWalker', \ "Page table walker state machine debugging") + TraceFlag('Faults', "Trace all faults/exceptions/traps") SimObject('X86LocalApic.py') SimObject('X86System.py') diff --git a/src/arch/x86/faults.cc b/src/arch/x86/faults.cc index 964eb0a7f..b81400cc3 100644 --- a/src/arch/x86/faults.cc +++ b/src/arch/x86/faults.cc @@ -103,6 +103,8 @@ namespace X86ISA #if FULL_SYSTEM void X86FaultBase::invoke(ThreadContext * tc) { + Addr pc = tc->readPC(); + DPRINTF(Faults, "RIP %#x: vector %d: %s\n", pc, vector, describe()); using namespace X86ISAInst::RomLabels; HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); MicroPC entry; @@ -116,7 +118,7 @@ namespace X86ISA entry = extern_label_legacyModeInterrupt; } tc->setIntReg(INTREG_MICRO(1), vector); - tc->setIntReg(INTREG_MICRO(7), tc->readPC()); + tc->setIntReg(INTREG_MICRO(7), pc); if (errorCode != (uint64_t)(-1)) { if (m5reg.mode == LongMode) { entry = extern_label_longModeInterruptWithError; @@ -132,6 +134,18 @@ namespace X86ISA tc->setMicroPC(romMicroPC(entry)); tc->setNextMicroPC(romMicroPC(entry) + 1); } + + std::string + X86FaultBase::describe() const + { + std::stringstream ss; + ccprintf(ss, "%s", mnemonic()); + if (errorCode != (uint64_t)(-1)) { + ccprintf(ss, "(%#x)", errorCode); + } + + return ss.str(); + } void X86Trap::invoke(ThreadContext * tc) { @@ -163,6 +177,14 @@ namespace X86ISA } } + std::string + PageFault::describe() const + { + std::stringstream ss; + ccprintf(ss, "%s at %#x", X86FaultBase::describe(), addr); + return ss.str(); + } + #endif } // namespace X86ISA diff --git a/src/arch/x86/faults.hh b/src/arch/x86/faults.hh index 3753e60e5..cb1a3f18a 100644 --- a/src/arch/x86/faults.hh +++ b/src/arch/x86/faults.hh @@ -62,6 +62,8 @@ #include "base/misc.hh" #include "sim/faults.hh" +#include + namespace X86ISA { // Base class for all x86 "faults" where faults is in the m5 sense @@ -102,6 +104,8 @@ namespace X86ISA #if FULL_SYSTEM void invoke(ThreadContext * tc); + + virtual std::string describe() const; #endif }; @@ -342,6 +346,8 @@ namespace X86ISA #if FULL_SYSTEM void invoke(ThreadContext * tc); + + virtual std::string describe() const; #endif }; @@ -414,7 +420,7 @@ namespace X86ISA { public: SoftwareInterrupt(uint8_t _vector) : - X86Interrupt("Software Interrupt", "INTn", _vector) + X86Interrupt("Software Interrupt", "#INTR", _vector) {} bool isSoft() -- cgit v1.2.3 From 710b43dfbdbbaf0588d182ce0bc82a0b7db0b550 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:18:06 -0800 Subject: X86: Implement inUserMode for x86. --- src/arch/x86/utility.hh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/utility.hh b/src/arch/x86/utility.hh index 477a76e0b..6f0812a6a 100644 --- a/src/arch/x86/utility.hh +++ b/src/arch/x86/utility.hh @@ -93,7 +93,12 @@ namespace X86ISA static inline bool inUserMode(ThreadContext *tc) { - return false; +#if FULL_SYSTEM + HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); + return m5reg.cpl == 3; +#else + return true; +#endif } inline bool isCallerSaveIntegerRegister(unsigned int reg) { -- cgit v1.2.3 From 897c3748925e83301027d85dbc4c0479d972fda4 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:18:16 -0800 Subject: X86: Move where CS is set so CPL checks work out. --- src/arch/x86/isa/insts/romutil.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/romutil.py b/src/arch/x86/isa/insts/romutil.py index a39ba202f..93276addc 100644 --- a/src/arch/x86/isa/insts/romutil.py +++ b/src/arch/x86/isa/insts/romutil.py @@ -124,6 +124,18 @@ def rom ## wrip t0, t9, dataSize=8 + # + # Set up the target code segment. Do this now so we have the right + # permissions when setting up the stack frame. + # + srli t5, t4, 16, dataSize=8 + andi t5, t5, 0xFF, dataSize=8 + wrdl cs, t3, t5, dataSize=8 + # Tuck away the old CS for use below + limm t10, 0, dataSize=8 + rdsel t10, cs, dataSize=2 + wrsel cs, t5, dataSize=2 + # # Build up the interrupt stack frame @@ -133,9 +145,7 @@ def rom # Write out the contents of memory %(errorCodeCode)s st t7, hs, [1, t0, t6], %(errorCodeSize)d, dataSize=8, addressSize=8 - limm t5, 0, dataSize=8 - rdsel t5, cs, dataSize=2 - st t5, hs, [1, t0, t6], 8 + %(errorCodeSize)d, dataSize=8, addressSize=8 + st t10, hs, [1, t0, t6], 8 + %(errorCodeSize)d, dataSize=8, addressSize=8 rflags t10, dataSize=8 st t10, hs, [1, t0, t6], 16 + %(errorCodeSize)d, dataSize=8, addressSize=8 st rsp, hs, [1, t0, t6], 24 + %(errorCodeSize)d, dataSize=8, addressSize=8 @@ -146,14 +156,6 @@ def rom mov rsp, rsp, t6, dataSize=8 wrsel ss, t11, dataSize=2 - # - # Set up the target code segment - # - srli t5, t4, 16, dataSize=8 - andi t5, t5, 0xFF, dataSize=8 - wrdl cs, t3, t5, dataSize=8 - wrsel cs, t5, dataSize=2 - # # Adjust rflags which is still in t10 from above # -- cgit v1.2.3 From dc53ca89f685155ff00103ed013b1ed6a6ad91a6 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:18:22 -0800 Subject: X86: Add a flag to force memory accesses to happen at CPL 0. --- src/arch/x86/insts/microldstop.hh | 12 ++++- src/arch/x86/isa/includes.isa | 1 + src/arch/x86/isa/microops/ldstop.isa | 86 +++++++++++++++++++++--------------- src/arch/x86/tlb.cc | 3 +- 4 files changed, 64 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/arch/x86/insts/microldstop.hh b/src/arch/x86/insts/microldstop.hh index eccd37dc2..f0051e2cf 100644 --- a/src/arch/x86/insts/microldstop.hh +++ b/src/arch/x86/insts/microldstop.hh @@ -60,9 +60,16 @@ #include "arch/x86/insts/microop.hh" #include "mem/packet.hh" +#include "mem/request.hh" namespace X86ISA { + static const Request::FlagsType SegmentFlagMask = mask(4); + static const int FlagShift = 4; + enum FlagBit { + CPL0FlagBit = 1 + }; + /** * Base class for load and store ops */ @@ -77,6 +84,7 @@ namespace X86ISA const RegIndex data; const uint8_t dataSize; const uint8_t addressSize; + const Request::FlagsType memFlags; RegIndex foldOBit, foldABit; //Constructor @@ -87,13 +95,15 @@ namespace X86ISA uint64_t _disp, uint8_t _segment, RegIndex _data, uint8_t _dataSize, uint8_t _addressSize, + Request::FlagsType _memFlags, OpClass __opClass) : X86MicroopBase(machInst, mnem, _instMnem, isMicro, isDelayed, isFirst, isLast, __opClass), scale(_scale), index(_index), base(_base), disp(_disp), segment(_segment), data(_data), - dataSize(_dataSize), addressSize(_addressSize) + dataSize(_dataSize), addressSize(_addressSize), + memFlags(_memFlags | _segment) { foldOBit = (dataSize == 1 && !_machInst.rex.present) ? 1 << 6 : 0; foldABit = diff --git a/src/arch/x86/isa/includes.isa b/src/arch/x86/isa/includes.isa index 909f2f389..10bac86ed 100644 --- a/src/arch/x86/isa/includes.isa +++ b/src/arch/x86/isa/includes.isa @@ -117,6 +117,7 @@ output decoder {{ #include "arch/x86/microcode_rom.hh" #include "arch/x86/miscregs.hh" #include "arch/x86/segmentregs.hh" +#include "arch/x86/tlb.hh" #include "base/cprintf.hh" #include "base/loader/symtab.hh" #include "base/misc.hh" diff --git a/src/arch/x86/isa/microops/ldstop.isa b/src/arch/x86/isa/microops/ldstop.isa index 5697f781b..097b0e311 100644 --- a/src/arch/x86/isa/microops/ldstop.isa +++ b/src/arch/x86/isa/microops/ldstop.isa @@ -124,14 +124,16 @@ def template MicroLeaDeclare {{ uint8_t _scale, RegIndex _index, RegIndex _base, uint64_t _disp, uint8_t _segment, RegIndex _data, - uint8_t _dataSize, uint8_t _addressSize); + uint8_t _dataSize, uint8_t _addressSize, + Request::FlagsType _memFlags); %(class_name)s(ExtMachInst _machInst, const char * instMnem, uint8_t _scale, RegIndex _index, RegIndex _base, uint64_t _disp, uint8_t _segment, RegIndex _data, - uint8_t _dataSize, uint8_t _addressSize); + uint8_t _dataSize, uint8_t _addressSize, + Request::FlagsType _memFlags); %(BasicExecDeclare)s }; @@ -151,7 +153,7 @@ def template MicroLoadExecute {{ %(ea_code)s; DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); - fault = read(xc, EA, Mem, (%(mem_flags)s) | segment); + fault = read(xc, EA, Mem, memFlags); if(fault == NoFault) { @@ -178,7 +180,7 @@ def template MicroLoadInitiateAcc {{ %(ea_code)s; DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); - fault = read(xc, EA, Mem, (%(mem_flags)s) | segment); + fault = read(xc, EA, Mem, memFlags); return fault; } @@ -225,7 +227,7 @@ def template MicroStoreExecute {{ if(fault == NoFault) { - fault = write(xc, Mem, EA, (%(mem_flags)s) | segment); + fault = write(xc, Mem, EA, memFlags); if(fault == NoFault) { %(post_code)s; @@ -253,7 +255,7 @@ def template MicroStoreInitiateAcc {{ if(fault == NoFault) { - write(xc, Mem, EA, (%(mem_flags)s) | segment); + write(xc, Mem, EA, memFlags); } return fault; } @@ -296,14 +298,16 @@ def template MicroLdStOpDeclare {{ uint8_t _scale, RegIndex _index, RegIndex _base, uint64_t _disp, uint8_t _segment, RegIndex _data, - uint8_t _dataSize, uint8_t _addressSize); + uint8_t _dataSize, uint8_t _addressSize, + Request::FlagsType _memFlags); %(class_name)s(ExtMachInst _machInst, const char * instMnem, uint8_t _scale, RegIndex _index, RegIndex _base, uint64_t _disp, uint8_t _segment, RegIndex _data, - uint8_t _dataSize, uint8_t _addressSize); + uint8_t _dataSize, uint8_t _addressSize, + Request::FlagsType _memFlags); %(BasicExecDeclare)s @@ -325,12 +329,13 @@ def template MicroLdStOpConstructor {{ uint8_t _scale, RegIndex _index, RegIndex _base, uint64_t _disp, uint8_t _segment, RegIndex _data, - uint8_t _dataSize, uint8_t _addressSize) : + uint8_t _dataSize, uint8_t _addressSize, + Request::FlagsType _memFlags) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, false, false, false, false, _scale, _index, _base, _disp, _segment, _data, - _dataSize, _addressSize, %(op_class)s) + _dataSize, _addressSize, _memFlags, %(op_class)s) { buildMe(); } @@ -341,12 +346,13 @@ def template MicroLdStOpConstructor {{ uint8_t _scale, RegIndex _index, RegIndex _base, uint64_t _disp, uint8_t _segment, RegIndex _data, - uint8_t _dataSize, uint8_t _addressSize) : + uint8_t _dataSize, uint8_t _addressSize, + Request::FlagsType _memFlags) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, isMicro, isDelayed, isFirst, isLast, _scale, _index, _base, _disp, _segment, _data, - _dataSize, _addressSize, %(op_class)s) + _dataSize, _addressSize, _memFlags, %(op_class)s) { buildMe(); } @@ -354,26 +360,31 @@ def template MicroLdStOpConstructor {{ let {{ class LdStOp(X86Microop): - def __init__(self, data, segment, addr, disp, dataSize, addressSize): + def __init__(self, data, segment, addr, disp, + dataSize, addressSize, baseFlags, atCPL0): self.data = data [self.scale, self.index, self.base] = addr self.disp = disp self.segment = segment self.dataSize = dataSize self.addressSize = addressSize + self.memFlags = baseFlags + if atCPL0: + self.memFlags += " | (CPL0FlagBit << FlagShift)" def getAllocator(self, *microFlags): allocator = '''new %(class_name)s(machInst, macrocodeBlock %(flags)s, %(scale)s, %(index)s, %(base)s, %(disp)s, %(segment)s, %(data)s, - %(dataSize)s, %(addressSize)s)''' % { + %(dataSize)s, %(addressSize)s, %(memFlags)s)''' % { "class_name" : self.className, "flags" : self.microFlagsText(microFlags), "scale" : self.scale, "index" : self.index, "base" : self.base, "disp" : self.disp, "segment" : self.segment, "data" : self.data, - "dataSize" : self.dataSize, "addressSize" : self.addressSize} + "dataSize" : self.dataSize, "addressSize" : self.addressSize, + "memFlags" : self.memFlags} return allocator }}; @@ -387,7 +398,7 @@ let {{ calculateEA = "EA = SegBase + scale * Index + Base + disp;" - def defineMicroLoadOp(mnemonic, code, mem_flags=0): + def defineMicroLoadOp(mnemonic, code, mem_flags="0"): global header_output global decoder_output global exec_output @@ -398,8 +409,7 @@ let {{ # Build up the all register version of this micro op iop = InstObjParams(name, Name, 'X86ISA::LdStOp', {"code": code, - "ea_code": calculateEA, - "mem_flags": mem_flags}) + "ea_code": calculateEA}) header_output += MicroLdStOpDeclare.subst(iop) decoder_output += MicroLdStOpConstructor.subst(iop) exec_output += MicroLoadExecute.subst(iop) @@ -408,16 +418,19 @@ let {{ class LoadOp(LdStOp): def __init__(self, data, segment, addr, disp = 0, - dataSize="env.dataSize", addressSize="env.addressSize"): - super(LoadOp, self).__init__(data, segment, - addr, disp, dataSize, addressSize) + dataSize="env.dataSize", + addressSize="env.addressSize", + atCPL0=False): + super(LoadOp, self).__init__(data, segment, addr, + disp, dataSize, addressSize, mem_flags, atCPL0) self.className = Name self.mnemonic = name microopClasses[name] = LoadOp defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);') - defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);', 'StoreCheck') + defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);', + 'X86ISA::StoreCheck') defineMicroLoadOp('Ldfp', 'FpData.uqw = Mem;') def defineMicroStoreOp(mnemonic, code, \ @@ -434,8 +447,7 @@ let {{ {"code": code, "post_code": postCode, "complete_code": completeCode, - "ea_code": calculateEA, - "mem_flags": mem_flags}) + "ea_code": calculateEA}) header_output += MicroLdStOpDeclare.subst(iop) decoder_output += MicroLdStOpConstructor.subst(iop) exec_output += MicroStoreExecute.subst(iop) @@ -444,9 +456,11 @@ let {{ class StoreOp(LdStOp): def __init__(self, data, segment, addr, disp = 0, - dataSize="env.dataSize", addressSize="env.addressSize"): - super(StoreOp, self).__init__(data, segment, - addr, disp, dataSize, addressSize) + dataSize="env.dataSize", + addressSize="env.addressSize", + atCPL0=False): + super(StoreOp, self).__init__(data, segment, addr, + disp, dataSize, addressSize, mem_flags, atCPL0) self.className = Name self.mnemonic = name @@ -461,8 +475,7 @@ let {{ iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp', {"code": "Data = merge(Data, EA, dataSize);", - "ea_code": calculateEA, - "mem_flags": 0}) + "ea_code": calculateEA}) header_output += MicroLeaDeclare.subst(iop) decoder_output += MicroLdStOpConstructor.subst(iop) exec_output += MicroLeaExecute.subst(iop) @@ -471,7 +484,7 @@ let {{ def __init__(self, data, segment, addr, disp = 0, dataSize="env.dataSize", addressSize="env.addressSize"): super(LeaOp, self).__init__(data, segment, - addr, disp, dataSize, addressSize) + addr, disp, dataSize, addressSize, "0", False) self.className = "Lea" self.mnemonic = "lea" @@ -480,17 +493,17 @@ let {{ iop = InstObjParams("tia", "Tia", 'X86ISA::LdStOp', {"code": "xc->demapPage(EA, 0);", - "ea_code": calculateEA, - "mem_flags": 0}) + "ea_code": calculateEA}) header_output += MicroLeaDeclare.subst(iop) decoder_output += MicroLdStOpConstructor.subst(iop) exec_output += MicroLeaExecute.subst(iop) class TiaOp(LdStOp): def __init__(self, segment, addr, disp = 0, - dataSize="env.dataSize", addressSize="env.addressSize"): + dataSize="env.dataSize", + addressSize="env.addressSize"): super(TiaOp, self).__init__("NUM_INTREGS", segment, - addr, disp, dataSize, addressSize) + addr, disp, dataSize, addressSize, "0", False) self.className = "Tia" self.mnemonic = "tia" @@ -498,9 +511,10 @@ let {{ class CdaOp(LdStOp): def __init__(self, segment, addr, disp = 0, - dataSize="env.dataSize", addressSize="env.addressSize"): + dataSize="env.dataSize", + addressSize="env.addressSize", atCPL0=False): super(CdaOp, self).__init__("NUM_INTREGS", segment, - addr, disp, dataSize, addressSize) + addr, disp, dataSize, addressSize, "0", atCPL0) self.className = "Cda" self.mnemonic = "cda" diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index 3962cd607..372c8b997 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -59,6 +59,7 @@ #include "config/full_system.hh" +#include "arch/x86/insts/microldstop.hh" #include "arch/x86/pagetable.hh" #include "arch/x86/tlb.hh" #include "arch/x86/x86_traits.hh" @@ -195,7 +196,7 @@ TLB::translate(RequestPtr req, ThreadContext *tc, uint32_t flags = req->getFlags(); bool storeCheck = flags & StoreCheck; - int seg = flags & mask(4); + int seg = flags & SegmentFlagMask; //XXX Junk code to surpress the warning if (storeCheck); -- cgit v1.2.3 From ba6918463049c5a60d4375348c99e46d9901d1e8 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:18:29 -0800 Subject: X86: Use atCPL0 for accesses that are part of CPU machinery. --- src/arch/x86/isa/insts/romutil.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/romutil.py b/src/arch/x86/isa/insts/romutil.py index 93276addc..beeda3d12 100644 --- a/src/arch/x86/isa/insts/romutil.py +++ b/src/arch/x86/isa/insts/romutil.py @@ -40,8 +40,8 @@ def rom # Load the gate descriptor from the IDT slli t4, t1, 4, dataSize=8 - ld t2, idtr, [1, t0, t4], 8, dataSize=8, addressSize=8 - ld t4, idtr, [1, t0, t4], dataSize=8, addressSize=8 + ld t2, idtr, [1, t0, t4], 8, dataSize=8, addressSize=8, atCPL0=True + ld t4, idtr, [1, t0, t4], dataSize=8, addressSize=8, atCPL0=True # Make sure the descriptor is a legal gate. chks t1, t4, %(gateCheckType)s @@ -54,10 +54,10 @@ def rom andi t5, t10, 0xF8, dataSize=8 andi t0, t10, 0x4, flags=(EZF,), dataSize=2 br rom_local_label("%(startLabel)s_globalDescriptor"), flags=(CEZF,) - ld t3, tsl, [1, t0, t5], dataSize=8, addressSize=8 + ld t3, tsl, [1, t0, t5], dataSize=8, addressSize=8, atCPL0=True br rom_local_label("%(startLabel)s_processDescriptor") %(startLabel)s_globalDescriptor: - ld t3, tsg, [1, t0, t5], dataSize=8, addressSize=8 + ld t3, tsg, [1, t0, t5], dataSize=8, addressSize=8, atCPL0=True %(startLabel)s_processDescriptor: chks t10, t3, IntCSCheck, dataSize=8 wrdl hs, t3, t10, dataSize=8 @@ -104,18 +104,13 @@ def rom %(startLabel)s_cplStackSwitch: # Get the new rsp from the TSS - ld t6, tr, [8, t10, t0], 4, dataSize=8, addressSize=8 + ld t6, tr, [8, t10, t0], 4, dataSize=8, addressSize=8, atCPL0=True %(startLabel)s_stackSwitched: andi t6, t6, 0xF0, dataSize=1 subi t6, t6, 40 + %(errorCodeSize)d, dataSize=8 - # Check that we can access everything we need to on the stack - ldst t0, hs, [1, t0, t6], dataSize=8, addressSize=8 - ldst t0, hs, [1, t0, t6], \ - 32 + %(errorCodeSize)d, dataSize=8, addressSize=8 - ## ## Point of no return. ## We're now going to irrevocably modify visible state. @@ -136,6 +131,11 @@ def rom rdsel t10, cs, dataSize=2 wrsel cs, t5, dataSize=2 + # Check that we can access everything we need to on the stack + ldst t0, hs, [1, t0, t6], dataSize=8, addressSize=8 + ldst t0, hs, [1, t0, t6], \ + 32 + %(errorCodeSize)d, dataSize=8, addressSize=8 + # # Build up the interrupt stack frame -- cgit v1.2.3 From da61c4b3ee4571d43f7133640eeda2cf51e21cd9 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:18:36 -0800 Subject: CPU: Don't fetch when executing a macroop. If the CPL changes mid macroop, the end of the instruction might not be priveleged enough to execute the beginning. --- src/cpu/simple/atomic.cc | 4 ++-- src/cpu/simple/timing.cc | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 2ada12b8d..acda552d9 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -607,7 +607,7 @@ AtomicSimpleCPU::tick() Fault fault = NoFault; bool fromRom = isRomMicroPC(thread->readMicroPC()); - if (!fromRom) { + if (!fromRom && !curMacroStaticInst) { setupFetchRequest(&ifetch_req); fault = thread->itb->translateAtomic(&ifetch_req, tc); } @@ -617,7 +617,7 @@ AtomicSimpleCPU::tick() bool icache_access = false; dcache_access = false; // assume no dcache access - if (!fromRom) { + if (!fromRom && !curMacroStaticInst) { // This is commented out because the predecoder would act like // a tiny cache otherwise. It wouldn't be flushed when needed // like the I cache. It should be flushed, and when that works diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 3f5778138..f398365d3 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -667,7 +667,7 @@ TimingSimpleCPU::fetch() bool fromRom = isRomMicroPC(thread->readMicroPC()); - if (!fromRom) { + if (!fromRom && !curMacroStaticInst) { Request *ifetch_req = new Request(); ifetch_req->setThreadContext(_cpuId, /* thread ID */ 0); setupFetchRequest(ifetch_req); -- cgit v1.2.3 From f35a37ca9eb7ff25c0da5ec14b83f77f5321222c Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:18:51 -0800 Subject: X86: Update CS later so stack accesses have the right permission checks. --- .../control_transfer/interrupts_and_exceptions.py | 31 +++++++++++----------- 1 file changed, 15 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py b/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py index 1f14eb95c..8d66cc445 100644 --- a/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py +++ b/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py @@ -118,20 +118,13 @@ protToVirtFallThrough: andi t6, t2, 0xF8, dataSize=8 andi t0, t2, 0x4, flags=(EZF,), dataSize=2 br label("globalCSDescriptor"), flags=(CEZF,) - ld t6, tsl, [1, t0, t6], dataSize=8 + ld t8, tsl, [1, t0, t6], dataSize=8 br label("processCSDescriptor") globalCSDescriptor: - ld t6, tsg, [1, t0, t6], dataSize=8 + ld t8, tsg, [1, t0, t6], dataSize=8 processCSDescriptor: chks t2, t6, dataSize=8 - # This actually updates state which is wrong. It should wait until we know - # we're not going to fault. Unfortunately, that's hard to do. - wrdl cs, t6, t2 - wrsel cs, t2 - - #CPL = temp_CPL - ### ### Get the new stack pointer and stack segment off the old stack if necessary, @@ -175,24 +168,24 @@ doPopStackStuff: # POP.v temp_RSP ld t6, ss, [1, t0, rsp], "3 * env.dataSize", dataSize=ssz # POP.v temp_SS - ld t2, ss, [1, t0, rsp], "4 * env.dataSize", dataSize=ssz + ld t9, ss, [1, t0, rsp], "4 * env.dataSize", dataSize=ssz # SS = READ_DESCRIPTOR (temp_SS, ss_chk) - andi t0, t2, 0xFC, flags=(EZF,), dataSize=2 + andi t0, t9, 0xFC, flags=(EZF,), dataSize=2 br label("processSSDescriptor"), flags=(CEZF,) - andi t7, t2, 0xF8, dataSize=8 - andi t0, t2, 0x4, flags=(EZF,), dataSize=2 + andi t7, t9, 0xF8, dataSize=8 + andi t0, t9, 0x4, flags=(EZF,), dataSize=2 br label("globalSSDescriptor"), flags=(CEZF,) ld t7, tsl, [1, t0, t7], dataSize=8 br label("processSSDescriptor") globalSSDescriptor: ld t7, tsg, [1, t0, t7], dataSize=8 processSSDescriptor: - chks t2, t7, dataSize=8 + chks t9, t7, dataSize=8 # This actually updates state which is wrong. It should wait until we know # we're not going to fault. Unfortunately, that's hard to do. - wrdl ss, t7, t2 - wrsel ss, t2 + wrdl ss, t7, t9 + wrsel ss, t9 ### ### From this point downwards, we can't fault. We can update user visible state. @@ -204,6 +197,12 @@ processSSDescriptor: fallThroughPopStackStuff: + # Update CS + wrdl cs, t8, t2 + wrsel cs, t2 + + #CPL = temp_CPL + #IF (changing CPL) #{ srli t7, t4, 4 -- cgit v1.2.3 From c849ef58c05e00e8523d6f2a9d8f0da6315e75d9 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:18:58 -0800 Subject: X86: Actually check page protections. --- src/arch/x86/tlb.cc | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src') diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index 372c8b997..603d4e45f 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -649,6 +649,18 @@ TLB::translate(RequestPtr req, ThreadContext *tc, #endif } // Do paging protection checks. + bool inUser = (csAttr.dpl == 3 && + !(flags & (CPL0FlagBit << FlagShift))); + if (inUser && !entry->user || + write && !entry->writable) { + // The page must have been present to get into the TLB in + // the first place. We'll assume the reserved bits are + // fine even though we're not checking them. + return new PageFault(vaddr, true, write, + inUser, false, execute); + } + + DPRINTF(TLB, "Entry found with paddr %#x, " "doing protection checks.\n", entry->paddr); Addr paddr = entry->paddr | (vaddr & (entry->size-1)); -- cgit v1.2.3 From 5f0428ef9fc7acc5b1315f6c87202c1ee13f0b8b Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:19:14 -0800 Subject: X86: Use the right portion of a register for stores. --- src/arch/x86/isa/microops/ldstop.isa | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/microops/ldstop.isa b/src/arch/x86/isa/microops/ldstop.isa index 097b0e311..a1aaddfe2 100644 --- a/src/arch/x86/isa/microops/ldstop.isa +++ b/src/arch/x86/isa/microops/ldstop.isa @@ -466,9 +466,9 @@ let {{ microopClasses[name] = StoreOp - defineMicroStoreOp('St', 'Mem = Data;') + defineMicroStoreOp('St', 'Mem = pick(Data, 2, dataSize);') defineMicroStoreOp('Stfp', 'Mem = FpData.uqw;') - defineMicroStoreOp('Stupd', 'Mem = Data;', + defineMicroStoreOp('Stupd', 'Mem = pick(Data, 2, dataSize);', 'Base = merge(Base, EA - SegBase, addressSize);', 'Base = merge(Base, pkt->req->getVaddr() - SegBase, addressSize);'); defineMicroStoreOp('Cda', 'Mem = 0;', mem_flags="Request::NO_ACCESS") -- cgit v1.2.3 From 06ff83e1b9aa2a00af4f66fae7c9fce2ac36394a Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:19:22 -0800 Subject: X86: Implement a basic prefetch instruction. --- src/arch/x86/isa/decoder/two_byte_opcodes.isa | 4 ++-- src/arch/x86/isa/includes.isa | 1 + .../general_purpose/cache_and_memory_management.py | 28 +++++++++++++++++++--- src/arch/x86/isa/microops/ldstop.isa | 23 +++++++++++------- 4 files changed, 42 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index fa49c55d3..a0a08df8f 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -281,7 +281,7 @@ 0x2: Inst::UD2(); 0x3: Inst::UD2(); 0x4: Inst::UD2(); - 0x5: prefetch(); + 0x5: Inst::PREFETCH(Mb); 0x6: FailUnimpl::femms(); 0x7: FailUnimpl::threednow(); } @@ -335,7 +335,7 @@ //group17(); 0x0: decode MODRM_REG { 0x0: prefetch_nta(); - 0x1: prefetch_t0(); + 0x1: Inst::PREFETCH_T0(Mb); 0x2: prefetch_t1(); 0x3: prefetch_t2(); default: Inst::HINT_NOP(); diff --git a/src/arch/x86/isa/includes.isa b/src/arch/x86/isa/includes.isa index 10bac86ed..8626f117a 100644 --- a/src/arch/x86/isa/includes.isa +++ b/src/arch/x86/isa/includes.isa @@ -157,6 +157,7 @@ output exec {{ #include "sim/sim_exit.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" +#include "mem/request.hh" #include "sim/pseudo_inst.hh" using namespace X86ISA; diff --git a/src/arch/x86/isa/insts/general_purpose/cache_and_memory_management.py b/src/arch/x86/isa/insts/general_purpose/cache_and_memory_management.py index 08b842825..dbd2d8b84 100644 --- a/src/arch/x86/isa/insts/general_purpose/cache_and_memory_management.py +++ b/src/arch/x86/isa/insts/general_purpose/cache_and_memory_management.py @@ -53,7 +53,31 @@ # # Authors: Gabe Black -microcode = "" +microcode = ''' +def macroop PREFETCH_M +{ + ld t0, seg, sib, disp, dataSize=1, prefetch=True +}; + +def macroop PREFETCH_P +{ + rdip t7 + ld t0, seg, riprel, disp, dataSize=1, prefetch=True +}; + +def macroop PREFETCH_T0_M +{ + ld t0, seg, sib, disp, dataSize=1, prefetch=True +}; + +def macroop PREFETCH_T0_P +{ + rdip t7 + ld t0, seg, riprel, disp, dataSize=1, prefetch=True +}; + +''' + #let {{ # class LFENCE(Inst): # "GenFault ${new UnimpInstFault}" @@ -63,8 +87,6 @@ microcode = "" # "GenFault ${new UnimpInstFault}" # class PREFETCHlevel(Inst): # "GenFault ${new UnimpInstFault}" -# class PREFETCH(Inst): -# "GenFault ${new UnimpInstFault}" # class PREFETCHW(Inst): # "GenFault ${new UnimpInstFault}" # class CLFLUSH(Inst): diff --git a/src/arch/x86/isa/microops/ldstop.isa b/src/arch/x86/isa/microops/ldstop.isa index a1aaddfe2..3bc238174 100644 --- a/src/arch/x86/isa/microops/ldstop.isa +++ b/src/arch/x86/isa/microops/ldstop.isa @@ -155,9 +155,11 @@ def template MicroLoadExecute {{ fault = read(xc, EA, Mem, memFlags); - if(fault == NoFault) - { + if (fault == NoFault) { %(code)s; + } else if (memFlags & Request::PF_EXCLUSIVE) { + // For prefetches, ignore any faults/exceptions. + return NoFault; } if(fault == NoFault) { @@ -361,7 +363,7 @@ def template MicroLdStOpConstructor {{ let {{ class LdStOp(X86Microop): def __init__(self, data, segment, addr, disp, - dataSize, addressSize, baseFlags, atCPL0): + dataSize, addressSize, baseFlags, atCPL0, prefetch): self.data = data [self.scale, self.index, self.base] = addr self.disp = disp @@ -371,6 +373,8 @@ let {{ self.memFlags = baseFlags if atCPL0: self.memFlags += " | (CPL0FlagBit << FlagShift)" + if prefetch: + self.memFlags += " | Request::PF_EXCLUSIVE" def getAllocator(self, *microFlags): allocator = '''new %(class_name)s(machInst, macrocodeBlock @@ -420,9 +424,10 @@ let {{ def __init__(self, data, segment, addr, disp = 0, dataSize="env.dataSize", addressSize="env.addressSize", - atCPL0=False): + atCPL0=False, prefetch=False): super(LoadOp, self).__init__(data, segment, addr, - disp, dataSize, addressSize, mem_flags, atCPL0) + disp, dataSize, addressSize, mem_flags, + atCPL0, prefetch) self.className = Name self.mnemonic = name @@ -460,7 +465,7 @@ let {{ addressSize="env.addressSize", atCPL0=False): super(StoreOp, self).__init__(data, segment, addr, - disp, dataSize, addressSize, mem_flags, atCPL0) + disp, dataSize, addressSize, mem_flags, atCPL0, False) self.className = Name self.mnemonic = name @@ -484,7 +489,7 @@ let {{ def __init__(self, data, segment, addr, disp = 0, dataSize="env.dataSize", addressSize="env.addressSize"): super(LeaOp, self).__init__(data, segment, - addr, disp, dataSize, addressSize, "0", False) + addr, disp, dataSize, addressSize, "0", False, False) self.className = "Lea" self.mnemonic = "lea" @@ -503,7 +508,7 @@ let {{ dataSize="env.dataSize", addressSize="env.addressSize"): super(TiaOp, self).__init__("NUM_INTREGS", segment, - addr, disp, dataSize, addressSize, "0", False) + addr, disp, dataSize, addressSize, "0", False, False) self.className = "Tia" self.mnemonic = "tia" @@ -514,7 +519,7 @@ let {{ dataSize="env.dataSize", addressSize="env.addressSize", atCPL0=False): super(CdaOp, self).__init__("NUM_INTREGS", segment, - addr, disp, dataSize, addressSize, "0", atCPL0) + addr, disp, dataSize, addressSize, "0", atCPL0, False) self.className = "Cda" self.mnemonic = "cda" -- cgit v1.2.3 From 9940e21fa98950c477c0fb7488376005b2ca71df Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:19:33 -0800 Subject: CPU: Add a flag to identify a read barrier to the static inst class. --- src/cpu/static_inst.hh | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index bf07e06c7..cb32f2333 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -159,6 +159,7 @@ class StaticInstBase : public RefCounted IsSerializeAfter, IsMemBarrier, ///< Is a memory barrier IsWriteBarrier, ///< Is a write barrier + IsReadBarrier, ///< Is a read barrier IsERET, /// <- Causes the IFU to stall (MIPS ISA) IsNonSpeculative, ///< Should not be executed speculatively -- cgit v1.2.3 From d48214a6560049643f39873a533f27d5c8895a4e Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:19:41 -0800 Subject: X86: Implement the fence instructions. These are not microcoded. --- src/arch/x86/isa/decoder/two_byte_opcodes.isa | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index a0a08df8f..edacf5bcb 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -831,9 +831,12 @@ //0x6: group16(); 0x6: decode MODRM_MOD { 0x3: decode MODRM_REG { - 0x5: lfence(); - 0x6: mfence(); - 0x7: sfence(); + 0x5: BasicOperate::LFENCE( + {{/*Nothing*/}}, IsReadBarrier); + 0x6: BasicOperate::MFENCE( + {{/*Nothing*/}}, IsMemBarrier); + 0x7: BasicOperate::SFENCE( + {{/*Nothing*/}}, IsWriteBarrier); default: Inst::UD2(); } default: decode MODRM_REG { -- cgit v1.2.3 From cb4141f6e679db9725ad152df89941998535ad95 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:19:47 -0800 Subject: X86: Check src1 for illegal values since that's the index we actually use. --- src/arch/x86/isa/microops/regop.isa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 4434f9e74..74c93a20a 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -928,7 +928,7 @@ let {{ super(Rdcr, self).__init__(dest, \ src1, "NUM_INTREGS", flags, dataSize) code = ''' - if (dest == 1 || (dest > 4 && dest < 8) || (dest > 8)) { + if (src1 == 1 || (src1 > 4 && src1 < 8) || (src1 > 8)) { fault = new InvalidOpcode(); } else { DestReg = ControlSrc1; -- cgit v1.2.3 From 11fbed02ea88f72d61f16922ff17ceb8221bef6b Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:19:54 -0800 Subject: X86: Add classes that break out the bits of the DR6 and DR7 registers. --- src/arch/x86/miscregs.hh | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'src') diff --git a/src/arch/x86/miscregs.hh b/src/arch/x86/miscregs.hh index a536d9e3b..af02e9422 100644 --- a/src/arch/x86/miscregs.hh +++ b/src/arch/x86/miscregs.hh @@ -572,6 +572,38 @@ namespace X86ISA Bitfield<3, 0> tpr; // Task Priority Register EndBitUnion(CR8) + BitUnion64(DR6) + Bitfield<0> b0; + Bitfield<1> b1; + Bitfield<2> b2; + Bitfield<3> b3; + Bitfield<13> bd; + Bitfield<14> bs; + Bitfield<15> bt; + EndBitUnion(DR6) + + BitUnion64(DR7) + Bitfield<0> l0; + Bitfield<1> g0; + Bitfield<2> l1; + Bitfield<3> g1; + Bitfield<4> l2; + Bitfield<5> g2; + Bitfield<6> l3; + Bitfield<7> g3; + Bitfield<8> le; + Bitfield<9> ge; + Bitfield<13> gd; + Bitfield<17, 16> rw0; + Bitfield<19, 18> len0; + Bitfield<21, 20> rw1; + Bitfield<23, 22> len1; + Bitfield<25, 24> rw2; + Bitfield<27, 26> len2; + Bitfield<29, 28> rw3; + Bitfield<31, 30> len3; + EndBitUnion(DR7) + // MTRR capabilities BitUnion64(MTRRcap) Bitfield<7, 0> vcnt; // Variable-Range Register Count -- cgit v1.2.3 From 28a35a6adbe083bbe7ff34dfe29d57a408f18bdb Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:20:01 -0800 Subject: X86: Add microops for reading/writing debug registers. --- src/arch/x86/isa/microops/regop.isa | 36 ++++++++++++++++++++++++++++++++ src/arch/x86/isa/operands.isa | 41 ++++++++++++++++++++----------------- 2 files changed, 58 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 74c93a20a..ceecfbf1c 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -923,6 +923,42 @@ let {{ class Zext(RegOp): code = 'DestReg = bits(psrc1, op2, 0);' + class Rddr(RegOp): + def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): + super(Rddr, self).__init__(dest, \ + src1, "NUM_INTREGS", flags, dataSize) + code = ''' + CR4 cr4 = CR4Op; + DR7 dr7 = DR7Op; + if ((cr4.de == 1 && (src1 == 4 || src1 == 5)) || src1 >= 8) { + fault = new InvalidOpcode(); + } else if (dr7.gd) { + fault = new DebugException(); + } else { + DestReg = merge(DestReg, DebugSrc1, dataSize); + } + ''' + + class Wrdr(RegOp): + def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): + super(Wrdr, self).__init__(dest, \ + src1, "NUM_INTREGS", flags, dataSize) + code = ''' + CR4 cr4 = CR4Op; + DR7 dr7 = DR7Op; + if ((cr4.de == 1 && (dest == 4 || dest == 5)) || dest >= 8) { + fault = new InvalidOpcode(); + } else if ((dest == 6 || dest == 7) && + bits(psrc1, 63, 32) && + machInst.mode.mode == LongMode) { + fault = new GeneralProtection(0); + } else if (dr7.gd) { + fault = new DebugException(); + } else { + DebugDest = psrc1; + } + ''' + class Rdcr(RegOp): def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): super(Rdcr, self).__init__(dest, \ diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa index d46741f00..ab1e9a851 100644 --- a/src/arch/x86/isa/operands.isa +++ b/src/arch/x86/isa/operands.isa @@ -138,28 +138,31 @@ def operands {{ # original instruction. 'ControlDest': ('ControlReg', 'uqw', 'MISCREG_CR(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 100), 'ControlSrc1': ('ControlReg', 'uqw', 'MISCREG_CR(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 101), - 'SegBaseDest': ('ControlReg', 'uqw', 'MISCREG_SEG_BASE(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 102), - 'SegBaseSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_BASE(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 103), - 'SegLimitDest': ('ControlReg', 'uqw', 'MISCREG_SEG_LIMIT(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 104), - 'SegLimitSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_LIMIT(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 105), - 'SegSelDest': ('ControlReg', 'uqw', 'MISCREG_SEG_SEL(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 106), - 'SegSelSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_SEL(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 107), - 'SegAttrDest': ('ControlReg', 'uqw', 'MISCREG_SEG_ATTR(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 108), - 'SegAttrSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_ATTR(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 109), + 'DebugDest': ('ControlReg', 'uqw', 'MISCREG_DR(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 102), + 'DebugSrc1': ('ControlReg', 'uqw', 'MISCREG_DR(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 103), + 'SegBaseDest': ('ControlReg', 'uqw', 'MISCREG_SEG_BASE(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 104), + 'SegBaseSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_BASE(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 105), + 'SegLimitDest': ('ControlReg', 'uqw', 'MISCREG_SEG_LIMIT(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 106), + 'SegLimitSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_LIMIT(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 107), + 'SegSelDest': ('ControlReg', 'uqw', 'MISCREG_SEG_SEL(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 108), + 'SegSelSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_SEL(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 109), + 'SegAttrDest': ('ControlReg', 'uqw', 'MISCREG_SEG_ATTR(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 110), + 'SegAttrSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_ATTR(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 111), # Operands to access specific control registers directly. 'EferOp': ('ControlReg', 'uqw', 'MISCREG_EFER', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 200), 'CR4Op': ('ControlReg', 'uqw', 'MISCREG_CR4', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 201), - 'LDTRBase': ('ControlReg', 'uqw', 'MISCREG_TSL_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 202), - 'LDTRLimit': ('ControlReg', 'uqw', 'MISCREG_TSL_LIMIT', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 203), - 'LDTRSel': ('ControlReg', 'uqw', 'MISCREG_TSL', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 204), - 'GDTRBase': ('ControlReg', 'uqw', 'MISCREG_TSG_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 205), - 'GDTRLimit': ('ControlReg', 'uqw', 'MISCREG_TSG_LIMIT', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 206), - 'CSBase': ('ControlReg', 'udw', 'MISCREG_CS_EFF_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 207), - 'CSAttr': ('ControlReg', 'udw', 'MISCREG_CS_ATTR', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 208), - 'MiscRegDest': ('ControlReg', 'uqw', 'dest', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 209), - 'MiscRegSrc1': ('ControlReg', 'uqw', 'src1', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 210), - 'TscOp': ('ControlReg', 'uqw', 'MISCREG_TSC', (None, None, ['IsSerializeAfter', 'IsSerializing', 'IsNonSpeculative']), 211), - 'M5Reg': ('ControlReg', 'uqw', 'MISCREG_M5_REG', (None, None, None), 212), + 'DR7Op': ('ControlReg', 'uqw', 'MISCREG_DR7', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 202), + 'LDTRBase': ('ControlReg', 'uqw', 'MISCREG_TSL_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 203), + 'LDTRLimit': ('ControlReg', 'uqw', 'MISCREG_TSL_LIMIT', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 204), + 'LDTRSel': ('ControlReg', 'uqw', 'MISCREG_TSL', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 205), + 'GDTRBase': ('ControlReg', 'uqw', 'MISCREG_TSG_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 206), + 'GDTRLimit': ('ControlReg', 'uqw', 'MISCREG_TSG_LIMIT', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 207), + 'CSBase': ('ControlReg', 'udw', 'MISCREG_CS_EFF_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 208), + 'CSAttr': ('ControlReg', 'udw', 'MISCREG_CS_ATTR', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 209), + 'MiscRegDest': ('ControlReg', 'uqw', 'dest', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 210), + 'MiscRegSrc1': ('ControlReg', 'uqw', 'src1', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 211), + 'TscOp': ('ControlReg', 'uqw', 'MISCREG_TSC', (None, None, ['IsSerializeAfter', 'IsSerializing', 'IsNonSpeculative']), 212), + 'M5Reg': ('ControlReg', 'uqw', 'MISCREG_M5_REG', (None, None, None), 213), 'Mem': ('Mem', 'uqw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 300) }}; -- cgit v1.2.3 From 8813168b5a3830b0b0a65b0342aca7b607e74b42 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:20:10 -0800 Subject: X86: Do a merge for the zero extension microop. --- .../x86/isa/insts/general_purpose/data_conversion/translate.py | 2 +- src/arch/x86/isa/insts/general_purpose/data_transfer/move.py | 6 +++--- .../isa/insts/general_purpose/data_transfer/stack_operations.py | 4 ++-- src/arch/x86/isa/insts/general_purpose/input_output/general_io.py | 4 ++-- src/arch/x86/isa/insts/general_purpose/input_output/string_io.py | 8 ++++---- src/arch/x86/isa/insts/system/segmentation.py | 8 ++++---- src/arch/x86/isa/microops/regop.isa | 2 +- 7 files changed, 17 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/data_conversion/translate.py b/src/arch/x86/isa/insts/general_purpose/data_conversion/translate.py index d6ae7885a..c334693e5 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_conversion/translate.py +++ b/src/arch/x86/isa/insts/general_purpose/data_conversion/translate.py @@ -55,7 +55,7 @@ microcode = ''' def macroop XLAT { - zexti t1, rax, 7 + zexti t1, rax, 7, dataSize=8 # Here, t1 can be used directly. The value of al is supposed to be treated # as unsigned. Since we zero extended it from 8 bits above and the address # size has to be at least 16 bits, t1 will not be sign extended. diff --git a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py index 1e2c0c42f..0e3e9f270 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py +++ b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py @@ -215,7 +215,7 @@ def macroop MOV_P_S { }; def macroop MOV_REAL_S_R { - zext t2, regm, 15 + zext t2, regm, 15, dataSize=8 slli t3, t2, 2, dataSize=8 wrsel reg, regm wrbase reg, t3 @@ -223,7 +223,7 @@ def macroop MOV_REAL_S_R { def macroop MOV_REAL_S_M { ld t1, seg, sib, disp, dataSize=2 - zext t2, t1, 15 + zext t2, t1, 15, dataSize=8 slli t3, t2, 2, dataSize=8 wrsel reg, t1 wrbase reg, t3 @@ -232,7 +232,7 @@ def macroop MOV_REAL_S_M { def macroop MOV_REAL_S_P { rdip t7 ld t1, seg, riprel, disp, dataSize=2 - zext t2, t1, 15 + zext t2, t1, 15, dataSize=8 slli t3, t2, 2, dataSize=8 wrsel reg, t1 wrbase reg, t3 diff --git a/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py b/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py index 8ec957d11..82fdffc63 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py +++ b/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py @@ -162,9 +162,9 @@ def macroop ENTER_I_I { # Pull the different components out of the immediate limm t1, imm - zexti t2, t1, 15, dataSize=2 + zexti t2, t1, 15, dataSize=8 srl t1, t1, 16 - zexti t1, t1, 5 + zexti t1, t1, 5, dataSize=8 # t1 is now the masked nesting level, and t2 is the amount of storage. # Push rbp. diff --git a/src/arch/x86/isa/insts/general_purpose/input_output/general_io.py b/src/arch/x86/isa/insts/general_purpose/input_output/general_io.py index aba318d73..924bfcb6e 100644 --- a/src/arch/x86/isa/insts/general_purpose/input_output/general_io.py +++ b/src/arch/x86/isa/insts/general_purpose/input_output/general_io.py @@ -89,7 +89,7 @@ microcode = ''' }; def macroop IN_R_R { - zexti t2, regm, 15, dataSize=2 + zexti t2, regm, 15, dataSize=8 ld reg, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=4 }; @@ -100,7 +100,7 @@ microcode = ''' }; def macroop OUT_R_R { - zexti t2, reg, 15, dataSize=2 + zexti t2, reg, 15, dataSize=8 st regm, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=4 }; ''' diff --git a/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py b/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py index 9d1d4e724..b3bc5ab67 100644 --- a/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py +++ b/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py @@ -61,7 +61,7 @@ def macroop INS_M_R { subi t4, t0, dsz, dataSize=asz mov t3, t3, t4, flags=(nCEZF,), dataSize=asz - zexti t2, reg, 15, dataSize=2 + zexti t2, reg, 15, dataSize=8 ld t6, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8 st t6, es, [1, t0, rdi] @@ -78,7 +78,7 @@ def macroop INS_E_M_R { subi t4, t0, dsz, dataSize=asz mov t3, t3, t4, flags=(nCEZF,), dataSize=asz - zexti t2, reg, 15, dataSize=2 + zexti t2, reg, 15, dataSize=8 topOfLoop: ld t6, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8 @@ -98,7 +98,7 @@ def macroop OUTS_R_M { subi t4, t0, dsz, dataSize=asz mov t3, t3, t4, flags=(nCEZF,), dataSize=asz - zexti t2, reg, 15, dataSize=2 + zexti t2, reg, 15, dataSize=8 ld t6, ds, [1, t0, rsi] st t6, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8 @@ -115,7 +115,7 @@ def macroop OUTS_E_R_M { subi t4, t0, dsz, dataSize=asz mov t3, t3, t4, flags=(nCEZF,), dataSize=asz - zexti t2, reg, 15, dataSize=2 + zexti t2, reg, 15, dataSize=8 topOfLoop: ld t6, ds, [1, t0, rsi] diff --git a/src/arch/x86/isa/insts/system/segmentation.py b/src/arch/x86/isa/insts/system/segmentation.py index c2bb46b7c..2de79f935 100644 --- a/src/arch/x86/isa/insts/system/segmentation.py +++ b/src/arch/x86/isa/insts/system/segmentation.py @@ -92,7 +92,7 @@ def macroop LGDT_16_M ld t1, seg, sib, disp, dataSize=2 # Get the base ld t2, seg, sib, 'adjustedDisp + 2', dataSize=4 - zexti t2, t2, 23 + zexti t2, t2, 23, dataSize=8 wrbase tsg, t2 wrlimit tsg, t1 }; @@ -106,7 +106,7 @@ def macroop LGDT_16_P ld t1, seg, riprel, disp, dataSize=2 # Get the base ld t2, seg, riprel, 'adjustedDisp + 2', dataSize=4 - zexti t2, t2, 23 + zexti t2, t2, 23, dataSize=8 wrbase tsg, t2 wrlimit tsg, t1 }; @@ -149,7 +149,7 @@ def macroop LIDT_16_M ld t1, seg, sib, disp, dataSize=2 # Get the base ld t2, seg, sib, 'adjustedDisp + 2', dataSize=4 - zexti t2, t2, 23 + zexti t2, t2, 23, dataSize=8 wrbase idtr, t2 wrlimit idtr, t1 }; @@ -163,7 +163,7 @@ def macroop LIDT_16_P ld t1, seg, riprel, disp, dataSize=2 # Get the base ld t2, seg, riprel, 'adjustedDisp + 2', dataSize=4 - zexti t2, t2, 23 + zexti t2, t2, 23, dataSize=8 wrbase idtr, t2 wrlimit idtr, t1 }; diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index ceecfbf1c..fd2a3a64f 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -921,7 +921,7 @@ let {{ ''' class Zext(RegOp): - code = 'DestReg = bits(psrc1, op2, 0);' + code = 'DestReg = merge(DestReg, bits(psrc1, op2, 0), dataSize);' class Rddr(RegOp): def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): -- cgit v1.2.3 From 1e70401c08c5976b9ef01b95e100625bdbaf5f3d Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:20:19 -0800 Subject: X86: Fix a few bugs with the segment register instructions in real mode. Fix a few instances where the register form of zext was used where zexti was intended. Also get rid of the 64 bit only rip relative addressed version since 64 bit and real mode are mutually exclusive. --- src/arch/x86/isa/insts/general_purpose/data_transfer/move.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py index 0e3e9f270..82c076216 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py +++ b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py @@ -215,7 +215,7 @@ def macroop MOV_P_S { }; def macroop MOV_REAL_S_R { - zext t2, regm, 15, dataSize=8 + zexti t2, regm, 15, dataSize=8 slli t3, t2, 2, dataSize=8 wrsel reg, regm wrbase reg, t3 @@ -223,19 +223,14 @@ def macroop MOV_REAL_S_R { def macroop MOV_REAL_S_M { ld t1, seg, sib, disp, dataSize=2 - zext t2, t1, 15, dataSize=8 + zexti t2, t1, 15, dataSize=8 slli t3, t2, 2, dataSize=8 wrsel reg, t1 wrbase reg, t3 }; def macroop MOV_REAL_S_P { - rdip t7 - ld t1, seg, riprel, disp, dataSize=2 - zext t2, t1, 15, dataSize=8 - slli t3, t2, 2, dataSize=8 - wrsel reg, t1 - wrbase reg, t3 + panic "RIP relative addressing shouldn't happen in real mode" }; def macroop MOV_S_R { -- cgit v1.2.3 From 3ca2451d811ae7dc2e27923e1af575b6b784ceb9 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:20:25 -0800 Subject: X86: Add code to interpret debug register values. --- src/arch/x86/miscregfile.cc | 74 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc index 388a83e8d..01aac14b1 100644 --- a/src/arch/x86/miscregfile.cc +++ b/src/arch/x86/miscregfile.cc @@ -104,8 +104,11 @@ string X86ISA::getMiscRegName(RegIndex index) void MiscRegFile::clear() { - // Blank everything. 0 might not be an appropriate value for some things. + // Blank everything. 0 might not be an appropriate value for some things, + // but it is for most. memset(regVal, 0, NumMiscRegs * sizeof(MiscReg)); + regVal[MISCREG_DR6] = (mask(8) << 4) | (mask(16) << 16); + regVal[MISCREG_DR7] = 1 << 10; } MiscReg MiscRegFile::readRegNoEffect(MiscRegIndex miscReg) @@ -267,6 +270,75 @@ void MiscRegFile::setReg(MiscRegIndex miscReg, case MISCREG_TSC: regVal[MISCREG_TSC] = val - tc->getCpuPtr()->curCycle(); return; + case MISCREG_DR0: + case MISCREG_DR1: + case MISCREG_DR2: + case MISCREG_DR3: + /* These should eventually set up breakpoints. */ + break; + case MISCREG_DR4: + miscReg = MISCREG_DR6; + /* Fall through to have the same effects as DR6. */ + case MISCREG_DR6: + { + DR6 dr6 = regVal[MISCREG_DR6]; + DR6 newDR6 = val; + dr6.b0 = newDR6.b0; + dr6.b1 = newDR6.b1; + dr6.b2 = newDR6.b2; + dr6.b3 = newDR6.b3; + dr6.bd = newDR6.bd; + dr6.bs = newDR6.bs; + dr6.bt = newDR6.bt; + newVal = dr6; + } + break; + case MISCREG_DR5: + miscReg = MISCREG_DR7; + /* Fall through to have the same effects as DR7. */ + case MISCREG_DR7: + { + DR7 dr7 = regVal[MISCREG_DR7]; + DR7 newDR7 = val; + dr7.l0 = newDR7.l0; + dr7.g0 = newDR7.g0; + if (dr7.l0 || dr7.g0) { + panic("Debug register breakpoints not implemented.\n"); + } else { + /* Disable breakpoint 0. */ + } + dr7.l1 = newDR7.l1; + dr7.g1 = newDR7.g1; + if (dr7.l1 || dr7.g1) { + panic("Debug register breakpoints not implemented.\n"); + } else { + /* Disable breakpoint 1. */ + } + dr7.l2 = newDR7.l2; + dr7.g2 = newDR7.g2; + if (dr7.l2 || dr7.g2) { + panic("Debug register breakpoints not implemented.\n"); + } else { + /* Disable breakpoint 2. */ + } + dr7.l3 = newDR7.l3; + dr7.g3 = newDR7.g3; + if (dr7.l3 || dr7.g3) { + panic("Debug register breakpoints not implemented.\n"); + } else { + /* Disable breakpoint 3. */ + } + dr7.gd = newDR7.gd; + dr7.rw0 = newDR7.rw0; + dr7.len0 = newDR7.len0; + dr7.rw1 = newDR7.rw1; + dr7.len1 = newDR7.len1; + dr7.rw2 = newDR7.rw2; + dr7.len2 = newDR7.len2; + dr7.rw3 = newDR7.rw3; + dr7.len3 = newDR7.len3; + } + break; default: break; } -- cgit v1.2.3 From c39ed53d05be42a83b0bd9b4cc3e12fb8864f469 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:20:30 -0800 Subject: X86: Rename oszForPseudoDesc maxOsz to reflect its more general use. --- src/arch/x86/isa/insts/system/segmentation.py | 16 ++++++++-------- src/arch/x86/isa/microasm.isa | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/system/segmentation.py b/src/arch/x86/isa/insts/system/segmentation.py index 2de79f935..7c13765ca 100644 --- a/src/arch/x86/isa/insts/system/segmentation.py +++ b/src/arch/x86/isa/insts/system/segmentation.py @@ -56,7 +56,7 @@ microcode = ''' def macroop LGDT_M { - .adjust_env oszForPseudoDesc + .adjust_env maxOsz # Get the limit ld t1, seg, sib, disp, dataSize=2 @@ -68,7 +68,7 @@ def macroop LGDT_M def macroop LGDT_P { - .adjust_env oszForPseudoDesc + .adjust_env maxOsz rdip t7 # Get the limit @@ -86,7 +86,7 @@ def macroop LGDT_P def macroop LGDT_16_M { - .adjust_env oszForPseudoDesc + .adjust_env maxOsz # Get the limit ld t1, seg, sib, disp, dataSize=2 @@ -99,7 +99,7 @@ def macroop LGDT_16_M def macroop LGDT_16_P { - .adjust_env oszForPseudoDesc + .adjust_env maxOsz rdip t7 # Get the limit @@ -113,7 +113,7 @@ def macroop LGDT_16_P def macroop LIDT_M { - .adjust_env oszForPseudoDesc + .adjust_env maxOsz # Get the limit ld t1, seg, sib, disp, dataSize=2 @@ -125,7 +125,7 @@ def macroop LIDT_M def macroop LIDT_P { - .adjust_env oszForPseudoDesc + .adjust_env maxOsz rdip t7 # Get the limit @@ -143,7 +143,7 @@ def macroop LIDT_P def macroop LIDT_16_M { - .adjust_env oszForPseudoDesc + .adjust_env maxOsz # Get the limit ld t1, seg, sib, disp, dataSize=2 @@ -156,7 +156,7 @@ def macroop LIDT_16_M def macroop LIDT_16_P { - .adjust_env oszForPseudoDesc + .adjust_env maxOsz rdip t7 # Get the limit diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa index fe1d38ff1..00baed768 100644 --- a/src/arch/x86/isa/microasm.isa +++ b/src/arch/x86/isa/microasm.isa @@ -173,7 +173,7 @@ let {{ env.dataSize = 8; ''' - assembler.symbols["oszForPseudoDesc"] = ''' + assembler.symbols["maxOsz"] = ''' if (machInst.mode.submode == SixtyFourBitMode) env.dataSize = 8; else -- cgit v1.2.3 From 28efb3c6e3c13b9673e9077fcc9d54d2d512f72a Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:20:42 -0800 Subject: X86: Implement the mov to debug register intructions. --- src/arch/x86/isa/decoder/two_byte_opcodes.isa | 4 ++-- src/arch/x86/isa/insts/general_purpose/data_transfer/move.py | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index edacf5bcb..f4a007282 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -352,9 +352,9 @@ // no prefix 0x0: decode OPCODE_OP_BOTTOM3 { 0x0: Inst::MOV(Rd,Cd); - 0x1: mov_Rd_Dd(); + 0x1: Inst::MOV(Rd,Dd); 0x2: Inst::MOV(Cd,Rd); - 0x3: mov_Dd_Rd(); + 0x3: Inst::MOV(Dd,Rd); 0x4: mov_Rd_Td(); 0x6: mov_Td_Rd(); default: Inst::UD2(); diff --git a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py index 82c076216..abe44ae59 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py +++ b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py @@ -199,6 +199,16 @@ def macroop MOV_R_C { rdcr reg, regm }; +def macroop MOV_D_R { + .adjust_env maxOsz + wrdr reg, regm +}; + +def macroop MOV_R_D { + .adjust_env maxOsz + rddr reg, regm +}; + def macroop MOV_R_S { rdsel reg, regm }; -- cgit v1.2.3 From b035c917a5e0749cb4068d2de66331beda52d222 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:20:47 -0800 Subject: X86: Make the segment register reading microops use merge. --- .../general_purpose/control_transfer/interrupts_and_exceptions.py | 2 +- src/arch/x86/isa/microops/regop.isa | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py b/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py index 8d66cc445..8203f7c2c 100644 --- a/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py +++ b/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py @@ -142,7 +142,7 @@ processCSDescriptor: # Here, we know we're -not- in 64 bit mode, so we should do the # appropriate/other RIP checks. # if temp_RIP > CS.limit throw #GP(0) - rdlimit t6, cs + rdlimit t6, cs, dataSize=8 subi t0, t1, t6, flags=(ECF,) fault "new GeneralProtection(0)", flags=(CECF,) diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index fd2a3a64f..1349a64c2 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -1052,22 +1052,22 @@ let {{ class Rdbase(SegOp): code = ''' - DestReg = SegBaseSrc1; + DestReg = merge(DestReg, SegBaseSrc1, dataSize); ''' class Rdlimit(SegOp): code = ''' - DestReg = SegLimitSrc1; + DestReg = merge(DestReg, SegLimitSrc1, dataSize); ''' class RdAttr(SegOp): code = ''' - DestReg = SegAttrSrc1; + DestReg = merge(DestReg, SegAttrSrc1, dataSize); ''' class Rdsel(SegOp): code = ''' - DestReg = SegSelSrc1; + DestReg = merge(DestReg, SegSelSrc1, dataSize); ''' class Rdval(RegOp): -- cgit v1.2.3 From 9842f1ca9d3de48d6bc990248be14b119dca9891 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:21:02 -0800 Subject: X86: Implement CLTS. --- src/arch/x86/SConscript | 1 + src/arch/x86/isa/decoder/two_byte_opcodes.isa | 2 +- src/arch/x86/isa/insts/system/__init__.py | 3 +- src/arch/x86/isa/insts/system/control_registers.py | 35 ++++++++++++++++++++++ 4 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 src/arch/x86/isa/insts/system/control_registers.py (limited to 'src') diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript index 0e13d3104..4c0460e28 100644 --- a/src/arch/x86/SConscript +++ b/src/arch/x86/SConscript @@ -190,6 +190,7 @@ if env['TARGET_ISA'] == 'x86': 'general_purpose/system_calls.py', 'romutil.py', 'system/__init__.py', + 'system/control_registers.py', 'system/halt.py', 'system/invlpg.py', 'system/undefined_operation.py', diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index f4a007282..c127ff458 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -264,7 +264,7 @@ #else 0x05: SyscallInst::syscall('xc->syscall(Rax)', IsSyscall); #endif - 0x06: clts(); + 0x06: Inst::CLTS(); 0x07: decode MODE_SUBMODE { 0x0: decode OPSIZE { // Return to 64 bit mode. diff --git a/src/arch/x86/isa/insts/system/__init__.py b/src/arch/x86/isa/insts/system/__init__.py index 409a929f5..0dec9ebda 100644 --- a/src/arch/x86/isa/insts/system/__init__.py +++ b/src/arch/x86/isa/insts/system/__init__.py @@ -81,7 +81,8 @@ # # Authors: Gabe Black -categories = ["halt", +categories = ["control_registers", + "halt", "invlpg", "undefined_operation", "msrs", diff --git a/src/arch/x86/isa/insts/system/control_registers.py b/src/arch/x86/isa/insts/system/control_registers.py new file mode 100644 index 000000000..902c01abb --- /dev/null +++ b/src/arch/x86/isa/insts/system/control_registers.py @@ -0,0 +1,35 @@ +# Copyright (c) 2009 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +microcode = ''' +def macroop CLTS { + rdcr t1, 0, dataSize=8 + andi t1, t1, 0xF7, dataSize=1 + wrcr 0, t1, dataSize=8 +}; +''' -- cgit v1.2.3 From 68300cfb8c6099cc84cb3e544950c0e6a154ff07 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:21:08 -0800 Subject: X86: Make rdcr use merge and the mov to control register instructions use the right operand size. --- src/arch/x86/isa/insts/general_purpose/data_transfer/move.py | 2 ++ src/arch/x86/isa/microops/regop.isa | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py index abe44ae59..dded94968 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py +++ b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py @@ -192,10 +192,12 @@ def macroop MOVZX_W_R_P { }; def macroop MOV_C_R { + .adjust_env maxOsz wrcr reg, regm }; def macroop MOV_R_C { + .adjust_env maxOsz rdcr reg, regm }; diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 1349a64c2..7c2feb398 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -967,7 +967,7 @@ let {{ if (src1 == 1 || (src1 > 4 && src1 < 8) || (src1 > 8)) { fault = new InvalidOpcode(); } else { - DestReg = ControlSrc1; + DestReg = merge(DestReg, ControlSrc1, dataSize); } ''' -- cgit v1.2.3 From e08d60389d8ddbe64d22834dbd327229822dac10 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:21:14 -0800 Subject: X86: Make the TSS type check actually return a fault if it fails. --- src/arch/x86/isa/microops/regop.isa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 7c2feb398..d5eb59f11 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -1171,7 +1171,7 @@ let {{ } else if (!(desc.type == 0x9 || (desc.type == 1 && m5reg.mode != LongMode))) { - + fault = new GeneralProtection(selector); } break; default: -- cgit v1.2.3 From bda7077c6408542f0a1d766019b91a0c8eb2147b Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:21:21 -0800 Subject: X86: Add segmentation checks for ldt related descriptors and selectors. --- src/arch/x86/isa/microasm.isa | 2 +- src/arch/x86/isa/microops/regop.isa | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa index 00baed768..c7c6dae2e 100644 --- a/src/arch/x86/isa/microasm.isa +++ b/src/arch/x86/isa/microasm.isa @@ -87,7 +87,7 @@ let {{ # Add in symbols for the various checks of segment selectors. for check in ("NoCheck", "CSCheck", "CallGateCheck", "IntGateCheck", "SoftIntGateCheck", "SSCheck", "IretCheck", "IntCSCheck", - "TRCheck", "TSSCheck"): + "TRCheck", "TSSCheck", "InGDTCheck", "LDTCheck"): assembler.symbols[check] = "Seg%s" % check for reg in ("TR", "IDTR"): diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index d5eb59f11..f9bc82119 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -235,7 +235,7 @@ output header {{ enum SegmentSelectorCheck { SegNoCheck, SegCSCheck, SegCallGateCheck, SegIntGateCheck, SegSoftIntGateCheck, SegSSCheck, SegIretCheck, SegIntCSCheck, - SegTRCheck, SegTSSCheck + SegTRCheck, SegTSSCheck, SegInGDTCheck, SegLDTCheck }; enum LongModeDescriptorType { @@ -1174,6 +1174,18 @@ let {{ fault = new GeneralProtection(selector); } break; + case SegInGDTCheck: + if (selector.ti) { + fault = new GeneralProtection(selector); + } + break; + case SegLDTCheck: + if (!desc.p) { + fault = new SegmentNotPresent(selector); + } else if (desc.type != 0x2) { + fault = new GeneralProtection(selector); + } + break; default: panic("Undefined segment check type.\\n"); } -- cgit v1.2.3 From 7aa875f4f3598c8ca6e3ba8946cf6eb3697a7696 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:21:27 -0800 Subject: X86: Implement the lldt instruction. --- src/arch/x86/isa/decoder/two_byte_opcodes.isa | 2 +- src/arch/x86/isa/insts/system/segmentation.py | 51 +++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index c127ff458..9c376e2c4 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -93,7 +93,7 @@ 0x00: decode MODRM_REG { 0x0: sldt_Mw_or_Rv(); 0x1: str_Mw_or_Rv(); - 0x2: lldt_Mw_or_Rv(); + 0x2: Inst::LLDT(Ew); 0x3: Inst::LTR(Ew); 0x4: verr_Mw_or_Rv(); 0x5: verw_Mw_or_Rv(); diff --git a/src/arch/x86/isa/insts/system/segmentation.py b/src/arch/x86/isa/insts/system/segmentation.py index 7c13765ca..acbca9f6e 100644 --- a/src/arch/x86/isa/insts/system/segmentation.py +++ b/src/arch/x86/isa/insts/system/segmentation.py @@ -216,6 +216,57 @@ def macroop LTR_P st t1, tsg, [8, t4, t0], dataSize=8 }; +def macroop LLDT_R +{ + chks reg, t0, InGDTCheck, flags=(EZF,) + br label("end"), flags=(CEZF,) + limm t4, 0 + srli t4, reg, 3, dataSize=2 + ldst t1, tsg, [8, t4, t0], dataSize=8 + ld t2, tsg, [8, t4, t0], 8, dataSize=8 + chks reg, t1, LDTCheck + wrdh t3, t1, t2 + wrdl tr, t1, reg + wrbase tr, t3, dataSize=8 +end: + fault "NoFault" +}; + +def macroop LLDT_M +{ + ld t5, seg, sib, disp, dataSize=2 + chks t5, t0, InGDTCheck, flags=(EZF,) + br label("end"), flags=(CEZF,) + limm t4, 0 + srli t4, t5, 3, dataSize=2 + ldst t1, tsg, [8, t4, t0], dataSize=8 + ld t2, tsg, [8, t4, t0], 8, dataSize=8 + chks t5, t1, LDTCheck + wrdh t3, t1, t2 + wrdl tr, t1, t5 + wrbase tr, t3, dataSize=8 +end: + fault "NoFault" +}; + +def macroop LLDT_P +{ + rdip t7 + ld t5, seg, riprel, disp, dataSize=2 + chks t5, t0, InGDTCheck, flags=(EZF,) + br label("end"), flags=(CEZF,) + limm t4, 0 + srli t4, t5, 3, dataSize=2 + ldst t1, tsg, [8, t4, t0], dataSize=8 + ld t2, tsg, [8, t4, t0], 8, dataSize=8 + chks t5, t1, LDTCheck + wrdh t3, t1, t2 + wrdl tr, t1, t5 + wrbase tr, t3, dataSize=8 +end: + fault "NoFault" +}; + def macroop SWAPGS { rdval t1, kernel_gs_base, dataSize=8 -- cgit v1.2.3 From 88ee7d4c32854608a9887ecbd60139dc20ab1974 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:21:33 -0800 Subject: SPARC: Add a traceflag for register windows. --- src/arch/sparc/SConscript | 1 + src/arch/sparc/intregfile.cc | 6 +++--- src/arch/sparc/regfile.cc | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/arch/sparc/SConscript b/src/arch/sparc/SConscript index 148277358..940cf2076 100644 --- a/src/arch/sparc/SConscript +++ b/src/arch/sparc/SConscript @@ -45,6 +45,7 @@ if env['TARGET_ISA'] == 'sparc': SimObject('SparcTLB.py') TraceFlag('Sparc', "Generic SPARC ISA stuff") + TraceFlag('RegisterWindows', "Register window manipulation") if env['FULL_SYSTEM']: SimObject('SparcSystem.py') diff --git a/src/arch/sparc/intregfile.cc b/src/arch/sparc/intregfile.cc index 39a613a0d..6419f0f93 100644 --- a/src/arch/sparc/intregfile.cc +++ b/src/arch/sparc/intregfile.cc @@ -55,7 +55,7 @@ int IntRegFile::flattenIndex(int reg) { int flatIndex = offset[reg >> FrameOffsetBits] | (reg & FrameOffsetMask); - DPRINTF(Sparc, "Flattened index %d into %d.\n", reg, flatIndex); + DPRINTF(RegisterWindows, "Flattened index %d into %d.\n", reg, flatIndex); return flatIndex; } @@ -135,12 +135,12 @@ void IntRegFile::setCWP(int cwp) regView[Locals] = regSegments[index+1]; regView[Inputs] = regSegments[(index+2) % (NWindows * 2)]; - DPRINTF(Sparc, "Changed the CWP value to %d\n", cwp); + DPRINTF(RegisterWindows, "Changed the CWP value to %d\n", cwp); } void IntRegFile::setGlobals(int gl) { - DPRINTF(Sparc, "Now using %d globals\n", gl); + DPRINTF(RegisterWindows, "Now using %d globals\n", gl); regView[Globals] = regGlobals[gl]; offset[Globals] = RegGlobalOffset + gl * RegsPerFrame; diff --git a/src/arch/sparc/regfile.cc b/src/arch/sparc/regfile.cc index f390be508..1c172a4d5 100644 --- a/src/arch/sparc/regfile.cc +++ b/src/arch/sparc/regfile.cc @@ -155,7 +155,7 @@ int SparcISA::flattenIntIndex(ThreadContext * tc, int reg) { int gl = tc->readMiscRegNoEffect(MISCREG_GL); int cwp = tc->readMiscRegNoEffect(MISCREG_CWP); - //DPRINTF(Sparc, "Global Level = %d, Current Window Pointer = %d\n", gl, cwp); + //DPRINTF(RegisterWindows, "Global Level = %d, Current Window Pointer = %d\n", gl, cwp); int newReg; //The total number of global registers int numGlobals = (MaxGL + 1) * 8; @@ -214,7 +214,7 @@ int SparcISA::flattenIntIndex(ThreadContext * tc, int reg) } else panic("Tried to flatten invalid register index %d!\n", reg); - DPRINTF(Sparc, "Flattened register %d to %d.\n", reg, newReg); + DPRINTF(RegisterWindows, "Flattened register %d to %d.\n", reg, newReg); return newReg; //return intRegFile.flattenIndex(reg); } -- cgit v1.2.3 From f41ce6b5e9d606826c9519cf355f992f53bb4dbf Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:21:40 -0800 Subject: SPARC: Get rid of the setCWP function. --- src/arch/sparc/intregfile.cc | 20 -------------------- src/arch/sparc/intregfile.hh | 5 ----- 2 files changed, 25 deletions(-) (limited to 'src') diff --git a/src/arch/sparc/intregfile.cc b/src/arch/sparc/intregfile.cc index 6419f0f93..28299c9b3 100644 --- a/src/arch/sparc/intregfile.cc +++ b/src/arch/sparc/intregfile.cc @@ -73,7 +73,6 @@ IntRegFile::IntRegFile() { offset[Globals] = 0; regView[Globals] = regGlobals[0]; - setCWP(0); clear(); } @@ -119,25 +118,6 @@ void IntRegFile::setReg(int intReg, const IntReg &val) } */ } -//This doesn't effect the actual CWP register. -//It's purpose is to adjust the view of the register file -//to what it would be if CWP = cwp. -void IntRegFile::setCWP(int cwp) -{ - int index = ((NWindows - cwp) % NWindows) * 2; - if (index < 0) - panic("Index less than 0. cwp=%d nwin=%d\n", cwp, NWindows); - offset[Outputs] = FrameOffset + (index * RegsPerFrame); - offset[Locals] = FrameOffset + ((index+1) * RegsPerFrame); - offset[Inputs] = FrameOffset + - (((index+2) % (NWindows * 2)) * RegsPerFrame); - regView[Outputs] = regSegments[index]; - regView[Locals] = regSegments[index+1]; - regView[Inputs] = regSegments[(index+2) % (NWindows * 2)]; - - DPRINTF(RegisterWindows, "Changed the CWP value to %d\n", cwp); -} - void IntRegFile::setGlobals(int gl) { DPRINTF(RegisterWindows, "Now using %d globals\n", gl); diff --git a/src/arch/sparc/intregfile.hh b/src/arch/sparc/intregfile.hh index 83ef1d17b..0d1fe413e 100644 --- a/src/arch/sparc/intregfile.hh +++ b/src/arch/sparc/intregfile.hh @@ -102,11 +102,6 @@ namespace SparcISA void unserialize(Checkpoint *cp, const std::string §ion); protected: - //This doesn't effect the actual CWP register. - //It's purpose is to adjust the view of the register file - //to what it would be if CWP = cwp. - void setCWP(int cwp); - void setGlobals(int gl); }; } -- cgit v1.2.3 From 9d5b6e377ffca79e0dabe3fb63215d2f51a4eb7b Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:21:46 -0800 Subject: SPARC: Get rid of the setGlobals function. --- src/arch/sparc/intregfile.cc | 13 ------------- src/arch/sparc/intregfile.hh | 3 --- 2 files changed, 16 deletions(-) (limited to 'src') diff --git a/src/arch/sparc/intregfile.cc b/src/arch/sparc/intregfile.cc index 28299c9b3..26637ddad 100644 --- a/src/arch/sparc/intregfile.cc +++ b/src/arch/sparc/intregfile.cc @@ -118,19 +118,6 @@ void IntRegFile::setReg(int intReg, const IntReg &val) } */ } -void IntRegFile::setGlobals(int gl) -{ - DPRINTF(RegisterWindows, "Now using %d globals\n", gl); - - regView[Globals] = regGlobals[gl]; - offset[Globals] = RegGlobalOffset + gl * RegsPerFrame; - - if (regView[Globals] == regView[Inputs] || - regView[Globals] == regView[Locals] || - regView[Globals] == regView[Outputs] ) - panic("Two register arrays set to the same thing!\n"); -} - void IntRegFile::serialize(std::ostream &os) { SERIALIZE_ARRAY(regs, NumIntRegs); diff --git a/src/arch/sparc/intregfile.hh b/src/arch/sparc/intregfile.hh index 0d1fe413e..ce9bcadb6 100644 --- a/src/arch/sparc/intregfile.hh +++ b/src/arch/sparc/intregfile.hh @@ -100,9 +100,6 @@ namespace SparcISA void serialize(std::ostream &os); void unserialize(Checkpoint *cp, const std::string §ion); - - protected: - void setGlobals(int gl); }; } -- cgit v1.2.3 From ce2e50a64cf69a41e030e8c3ba8a53612dd32c48 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:21:52 -0800 Subject: ISA: Use the "Stack" traceflag for DPRINTFs about the initial stack frame. --- src/arch/sparc/process.cc | 24 ++++++++++++------------ src/arch/x86/process.cc | 20 ++++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index 91baea40c..515389687 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -338,18 +338,18 @@ SparcLiveProcess::argsInit(int pageSize) IntType window_save_base = argc_base - window_save_size; #endif - DPRINTF(Sparc, "The addresses of items on the initial stack:\n"); - DPRINTF(Sparc, "%#x - sentry NULL\n", sentry_base); - DPRINTF(Sparc, "filename = %s\n", filename); - DPRINTF(Sparc, "%#x - file name\n", file_name_base); - DPRINTF(Sparc, "%#x - env data\n", env_data_base); - DPRINTF(Sparc, "%#x - arg data\n", arg_data_base); - DPRINTF(Sparc, "%#x - auxv array\n", auxv_array_base); - DPRINTF(Sparc, "%#x - envp array\n", envp_array_base); - DPRINTF(Sparc, "%#x - argv array\n", argv_array_base); - DPRINTF(Sparc, "%#x - argc \n", argc_base); - DPRINTF(Sparc, "%#x - window save\n", window_save_base); - DPRINTF(Sparc, "%#x - stack min\n", stack_min); + DPRINTF(Stack, "The addresses of items on the initial stack:\n"); + DPRINTF(Stack, "%#x - sentry NULL\n", sentry_base); + DPRINTF(Stack, "filename = %s\n", filename); + DPRINTF(Stack, "%#x - file name\n", file_name_base); + DPRINTF(Stack, "%#x - env data\n", env_data_base); + DPRINTF(Stack, "%#x - arg data\n", arg_data_base); + DPRINTF(Stack, "%#x - auxv array\n", auxv_array_base); + DPRINTF(Stack, "%#x - envp array\n", envp_array_base); + DPRINTF(Stack, "%#x - argv array\n", argv_array_base); + DPRINTF(Stack, "%#x - argc \n", argc_base); + DPRINTF(Stack, "%#x - window save\n", window_save_base); + DPRINTF(Stack, "%#x - stack min\n", stack_min); assert(window_save_base == stack_min); diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index 2013190eb..d6f3b2371 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -406,16 +406,16 @@ X86LiveProcess::argsInit(int intSize, int pageSize) Addr argv_array_base = envp_array_base - argv_array_size; Addr argc_base = argv_array_base - argc_size; - DPRINTF(X86, "The addresses of items on the initial stack:\n"); - DPRINTF(X86, "0x%x - file name\n", file_name_base); - DPRINTF(X86, "0x%x - env data\n", env_data_base); - DPRINTF(X86, "0x%x - arg data\n", arg_data_base); - DPRINTF(X86, "0x%x - aux data\n", aux_data_base); - DPRINTF(X86, "0x%x - auxv array\n", auxv_array_base); - DPRINTF(X86, "0x%x - envp array\n", envp_array_base); - DPRINTF(X86, "0x%x - argv array\n", argv_array_base); - DPRINTF(X86, "0x%x - argc \n", argc_base); - DPRINTF(X86, "0x%x - stack min\n", stack_min); + DPRINTF(Stack, "The addresses of items on the initial stack:\n"); + DPRINTF(Stack, "0x%x - file name\n", file_name_base); + DPRINTF(Stack, "0x%x - env data\n", env_data_base); + DPRINTF(Stack, "0x%x - arg data\n", arg_data_base); + DPRINTF(Stack, "0x%x - aux data\n", aux_data_base); + DPRINTF(Stack, "0x%x - auxv array\n", auxv_array_base); + DPRINTF(Stack, "0x%x - envp array\n", envp_array_base); + DPRINTF(Stack, "0x%x - argv array\n", argv_array_base); + DPRINTF(Stack, "0x%x - argc \n", argc_base); + DPRINTF(Stack, "0x%x - stack min\n", stack_min); // write contents to stack -- cgit v1.2.3 From c1c61d52a0d7e00361fb6fa69fd7c4ea2f528de8 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:21:59 -0800 Subject: SPARC: Get rid of flattenIndex in the int register file. --- src/arch/sparc/intregfile.cc | 8 -------- src/arch/sparc/intregfile.hh | 2 -- 2 files changed, 10 deletions(-) (limited to 'src') diff --git a/src/arch/sparc/intregfile.cc b/src/arch/sparc/intregfile.cc index 26637ddad..c111172a9 100644 --- a/src/arch/sparc/intregfile.cc +++ b/src/arch/sparc/intregfile.cc @@ -51,14 +51,6 @@ string SparcISA::getIntRegName(RegIndex index) return intRegName[index]; } -int IntRegFile::flattenIndex(int reg) -{ - int flatIndex = offset[reg >> FrameOffsetBits] - | (reg & FrameOffsetMask); - DPRINTF(RegisterWindows, "Flattened index %d into %d.\n", reg, flatIndex); - return flatIndex; -} - void IntRegFile::clear() { int x; diff --git a/src/arch/sparc/intregfile.hh b/src/arch/sparc/intregfile.hh index ce9bcadb6..9a086f08a 100644 --- a/src/arch/sparc/intregfile.hh +++ b/src/arch/sparc/intregfile.hh @@ -87,8 +87,6 @@ namespace SparcISA public: - int flattenIndex(int reg); - void clear(); IntRegFile(); -- cgit v1.2.3 From 44d5351071d3f9ec80f2fab7876d757cfbd5bacf Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:22:09 -0800 Subject: ISA: Get rid of FlattenIntIndex function. --- src/arch/sparc/regfile.hh | 2 -- src/arch/x86/regfile.hh | 2 -- 2 files changed, 4 deletions(-) (limited to 'src') diff --git a/src/arch/sparc/regfile.hh b/src/arch/sparc/regfile.hh index dd4e1f684..505d7c8d7 100644 --- a/src/arch/sparc/regfile.hh +++ b/src/arch/sparc/regfile.hh @@ -71,8 +71,6 @@ namespace SparcISA void clear(); - int FlattenIntIndex(int reg); - MiscReg readMiscRegNoEffect(int miscReg); MiscReg readMiscReg(int miscReg, ThreadContext *tc); diff --git a/src/arch/x86/regfile.hh b/src/arch/x86/regfile.hh index 75c0290d3..8938ab0bc 100644 --- a/src/arch/x86/regfile.hh +++ b/src/arch/x86/regfile.hh @@ -97,8 +97,6 @@ namespace X86ISA void clear(); - int FlattenIntIndex(int reg); - MiscReg readMiscRegNoEffect(int miscReg); MiscReg readMiscReg(int miscReg, ThreadContext *tc); -- cgit v1.2.3 From 4633677145225a76ee3826ef97a24b1e427f61f8 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:22:17 -0800 Subject: ISA: Set up common trace flags for tracing registers. --- src/arch/SConscript | 5 +++++ src/arch/sparc/floatregfile.cc | 24 ++++++++++++++++-------- src/arch/sparc/intregfile.cc | 8 ++++---- src/arch/sparc/miscregfile.cc | 4 ++-- src/arch/x86/floatregfile.cc | 8 ++++---- src/arch/x86/intregfile.cc | 6 ++++-- 6 files changed, 35 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/arch/SConscript b/src/arch/SConscript index 932cf7509..2b0af2816 100644 --- a/src/arch/SConscript +++ b/src/arch/SConscript @@ -126,3 +126,8 @@ else: emitter = isa_desc_emitter) env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder }) + +TraceFlag('IntRegs') +TraceFlag('FloatRegs') +TraceFlag('MiscRegs') +CompoundFlag('Registers', [ 'IntRegs', 'FloatRegs', 'MiscRegs' ]) diff --git a/src/arch/sparc/floatregfile.cc b/src/arch/sparc/floatregfile.cc index e1b5ea7c8..cf33b6a77 100644 --- a/src/arch/sparc/floatregfile.cc +++ b/src/arch/sparc/floatregfile.cc @@ -75,7 +75,8 @@ FloatReg FloatRegFile::readReg(int floatReg, int width) result32 = htog(result32); memcpy(&fresult32, &result32, sizeof(result32)); result = fresult32; - DPRINTF(Sparc, "Read FP32 register %d = [%f]0x%x\n", floatReg, result, result32); + DPRINTF(FloatRegs, "Read FP32 register %d = [%f]0x%x\n", + floatReg, result, result32); break; case DoubleWidth: uint64_t result64; @@ -84,7 +85,8 @@ FloatReg FloatRegFile::readReg(int floatReg, int width) result64 = htog(result64); memcpy(&fresult64, &result64, sizeof(result64)); result = fresult64; - DPRINTF(Sparc, "Read FP64 register %d = [%f]0x%x\n", floatReg, result, result64); + DPRINTF(FloatRegs, "Read FP64 register %d = [%f]0x%x\n", + floatReg, result, result64); break; case QuadWidth: panic("Quad width FP not implemented."); @@ -107,13 +109,15 @@ FloatRegBits FloatRegFile::readRegBits(int floatReg, int width) uint32_t result32; memcpy(&result32, regSpace + 4 * floatReg, sizeof(result32)); result = htog(result32); - DPRINTF(Sparc, "Read FP32 bits register %d = 0x%x\n", floatReg, result); + DPRINTF(FloatRegs, "Read FP32 bits register %d = 0x%x\n", + floatReg, result); break; case DoubleWidth: uint64_t result64; memcpy(&result64, regSpace + 4 * floatReg, sizeof(result64)); result = htog(result64); - DPRINTF(Sparc, "Read FP64 bits register %d = 0x%x\n", floatReg, result); + DPRINTF(FloatRegs, "Read FP64 bits register %d = 0x%x\n", + floatReg, result); break; case QuadWidth: panic("Quad width FP not implemented."); @@ -141,14 +145,16 @@ Fault FloatRegFile::setReg(int floatReg, const FloatReg &val, int width) memcpy(&result32, &fresult32, sizeof(result32)); result32 = gtoh(result32); memcpy(regSpace + 4 * floatReg, &result32, sizeof(result32)); - DPRINTF(Sparc, "Write FP64 register %d = 0x%x\n", floatReg, result32); + DPRINTF(FloatRegs, "Write FP64 register %d = 0x%x\n", + floatReg, result32); break; case DoubleWidth: fresult64 = val; memcpy(&result64, &fresult64, sizeof(result64)); result64 = gtoh(result64); memcpy(regSpace + 4 * floatReg, &result64, sizeof(result64)); - DPRINTF(Sparc, "Write FP64 register %d = 0x%x\n", floatReg, result64); + DPRINTF(FloatRegs, "Write FP64 register %d = 0x%x\n", + floatReg, result64); break; case QuadWidth: panic("Quad width FP not implemented."); @@ -171,12 +177,14 @@ Fault FloatRegFile::setRegBits(int floatReg, const FloatRegBits &val, int width) case SingleWidth: result32 = gtoh((uint32_t)val); memcpy(regSpace + 4 * floatReg, &result32, sizeof(result32)); - DPRINTF(Sparc, "Write FP64 bits register %d = 0x%x\n", floatReg, result32); + DPRINTF(FloatRegs, "Write FP64 bits register %d = 0x%x\n", + floatReg, result32); break; case DoubleWidth: result64 = gtoh((uint64_t)val); memcpy(regSpace + 4 * floatReg, &result64, sizeof(result64)); - DPRINTF(Sparc, "Write FP64 bits register %d = 0x%x\n", floatReg, result64); + DPRINTF(FloatRegs, "Write FP64 bits register %d = 0x%x\n", + floatReg, result64); break; case QuadWidth: panic("Quad width FP not implemented."); diff --git a/src/arch/sparc/intregfile.cc b/src/arch/sparc/intregfile.cc index c111172a9..7c20d5169 100644 --- a/src/arch/sparc/intregfile.cc +++ b/src/arch/sparc/intregfile.cc @@ -70,7 +70,7 @@ IntRegFile::IntRegFile() IntReg IntRegFile::readReg(int intReg) { - DPRINTF(Sparc, "Read register %d = 0x%x\n", intReg, regs[intReg]); + DPRINTF(IntRegs, "Read register %d = 0x%x\n", intReg, regs[intReg]); return regs[intReg]; /* XXX Currently not used. When used again regView/offset need to be * serialized! @@ -83,7 +83,7 @@ IntReg IntRegFile::readReg(int intReg) panic("Tried to read non-existant integer register %d, %d\n", NumIntArchRegs + NumMicroIntRegs + intReg, intReg); - DPRINTF(Sparc, "Read register %d = 0x%x\n", intReg, val); + DPRINTF(IntRegs, "Read register %d = 0x%x\n", intReg, val); return val; */ } @@ -92,7 +92,7 @@ void IntRegFile::setReg(int intReg, const IntReg &val) { if(intReg) { - DPRINTF(Sparc, "Wrote register %d = 0x%x\n", intReg, val); + DPRINTF(IntRegs, "Wrote register %d = 0x%x\n", intReg, val); regs[intReg] = val; } return; @@ -100,7 +100,7 @@ void IntRegFile::setReg(int intReg, const IntReg &val) * serialized! if(intReg) { - DPRINTF(Sparc, "Wrote register %d = 0x%x\n", intReg, val); + DPRINTF(IntRegs, "Wrote register %d = 0x%x\n", intReg, val); if(intReg < NumIntArchRegs) regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask] = val; else if((intReg -= NumIntArchRegs) < NumMicroIntRegs) diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc index b22ceb657..e06d4b15a 100644 --- a/src/arch/sparc/miscregfile.cc +++ b/src/arch/sparc/miscregfile.cc @@ -227,7 +227,7 @@ MiscReg MiscRegFile::readRegNoEffect(int miscReg) /** Floating Point Status Register */ case MISCREG_FSR: - DPRINTF(Sparc, "FSR read as: %#x\n", fsr); + DPRINTF(MiscRegs, "FSR read as: %#x\n", fsr); return fsr; case MISCREG_MMU_P_CONTEXT: @@ -446,7 +446,7 @@ void MiscRegFile::setRegNoEffect(int miscReg, const MiscReg &val) /** Floating Point Status Register */ case MISCREG_FSR: fsr = val; - DPRINTF(Sparc, "FSR written with: %#x\n", fsr); + DPRINTF(MiscRegs, "FSR written with: %#x\n", fsr); break; case MISCREG_MMU_P_CONTEXT: diff --git a/src/arch/x86/floatregfile.cc b/src/arch/x86/floatregfile.cc index 1c49ea9c6..da5372c69 100644 --- a/src/arch/x86/floatregfile.cc +++ b/src/arch/x86/floatregfile.cc @@ -113,27 +113,27 @@ void FloatRegFile::clear() FloatReg FloatRegFile::readReg(int floatReg, int width) { FloatReg reg = d[floatReg]; - DPRINTF(X86, "Reading %f from register %d.\n", reg, floatReg); + DPRINTF(FloatRegs, "Reading %f from register %d.\n", reg, floatReg); return reg; } FloatRegBits FloatRegFile::readRegBits(int floatReg, int width) { FloatRegBits reg = q[floatReg]; - DPRINTF(X86, "Reading %#x from register %d.\n", reg, floatReg); + DPRINTF(FloatRegs, "Reading %#x from register %d.\n", reg, floatReg); return reg; } Fault FloatRegFile::setReg(int floatReg, const FloatReg &val, int width) { - DPRINTF(X86, "Writing %f to register %d.\n", val, floatReg); + DPRINTF(FloatRegs, "Writing %f to register %d.\n", val, floatReg); d[floatReg] = val; return NoFault; } Fault FloatRegFile::setRegBits(int floatReg, const FloatRegBits &val, int width) { - DPRINTF(X86, "Writing bits %#x to register %d.\n", val, floatReg); + DPRINTF(FloatRegs, "Writing bits %#x to register %d.\n", val, floatReg); q[floatReg] = val; return NoFault; } diff --git a/src/arch/x86/intregfile.cc b/src/arch/x86/intregfile.cc index 9c9ea134e..43cfb8082 100644 --- a/src/arch/x86/intregfile.cc +++ b/src/arch/x86/intregfile.cc @@ -120,13 +120,15 @@ void IntRegFile::clear() IntReg IntRegFile::readReg(int intReg) { - DPRINTF(X86, "Read int reg %d and got value %#x\n", intReg, regs[intReg]); + DPRINTF(IntRegs, "Read int reg %d and got value %#x\n", + intReg, regs[intReg]); return regs[intReg]; } void IntRegFile::setReg(int intReg, const IntReg &val) { - DPRINTF(X86, "Setting int reg %d to value %#x\n", intReg, val); + DPRINTF(IntRegs, "Setting int reg %d to value %#x\n", + intReg, val); regs[intReg] = val; } -- cgit v1.2.3 From 3b01535ec1ea6f51738675b3caf36e3f100ad128 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:22:25 -0800 Subject: SPARC: Get rid of the state keeping track of register frames. --- src/arch/sparc/intregfile.cc | 47 -------------------------------------------- src/arch/sparc/intregfile.hh | 31 ----------------------------- 2 files changed, 78 deletions(-) (limited to 'src') diff --git a/src/arch/sparc/intregfile.cc b/src/arch/sparc/intregfile.cc index 7c20d5169..49e41ed93 100644 --- a/src/arch/sparc/intregfile.cc +++ b/src/arch/sparc/intregfile.cc @@ -53,18 +53,11 @@ string SparcISA::getIntRegName(RegIndex index) void IntRegFile::clear() { - int x; - for (x = 0; x < MaxGL; x++) - memset(regGlobals[x], 0, sizeof(IntReg) * RegsPerFrame); - for(int x = 0; x < 2 * NWindows; x++) - memset(regSegments[x], 0, sizeof(IntReg) * RegsPerFrame); memset(regs, 0, sizeof(IntReg) * NumIntRegs); } IntRegFile::IntRegFile() { - offset[Globals] = 0; - regView[Globals] = regGlobals[0]; clear(); } @@ -72,20 +65,6 @@ IntReg IntRegFile::readReg(int intReg) { DPRINTF(IntRegs, "Read register %d = 0x%x\n", intReg, regs[intReg]); return regs[intReg]; - /* XXX Currently not used. When used again regView/offset need to be - * serialized! - IntReg val; - if(intReg < NumIntArchRegs) - val = regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask]; - else if((intReg -= NumIntArchRegs) < NumMicroIntRegs) - val = microRegs[intReg]; - else - panic("Tried to read non-existant integer register %d, %d\n", - NumIntArchRegs + NumMicroIntRegs + intReg, intReg); - - DPRINTF(IntRegs, "Read register %d = 0x%x\n", intReg, val); - return val; - */ } void IntRegFile::setReg(int intReg, const IntReg &val) @@ -96,42 +75,16 @@ void IntRegFile::setReg(int intReg, const IntReg &val) regs[intReg] = val; } return; - /* XXX Currently not used. When used again regView/offset need to be - * serialized! - if(intReg) - { - DPRINTF(IntRegs, "Wrote register %d = 0x%x\n", intReg, val); - if(intReg < NumIntArchRegs) - regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask] = val; - else if((intReg -= NumIntArchRegs) < NumMicroIntRegs) - microRegs[intReg] = val; - else - panic("Tried to set non-existant integer register\n"); - } */ } void IntRegFile::serialize(std::ostream &os) { SERIALIZE_ARRAY(regs, NumIntRegs); SERIALIZE_ARRAY(microRegs, NumMicroIntRegs); - - /* the below doesn't seem needed unless gabe makes regview work*/ - unsigned int x; - for(x = 0; x < MaxGL; x++) - SERIALIZE_ARRAY(regGlobals[x], RegsPerFrame); - for(x = 0; x < 2 * NWindows; x++) - SERIALIZE_ARRAY(regSegments[x], RegsPerFrame); } void IntRegFile::unserialize(Checkpoint *cp, const std::string §ion) { UNSERIALIZE_ARRAY(regs, NumIntRegs); UNSERIALIZE_ARRAY(microRegs, NumMicroIntRegs); - - /* the below doesn't seem needed unless gabe makes regview work*/ - unsigned int x; - for(x = 0; x < MaxGL; x++) - UNSERIALIZE_ARRAY(regGlobals[x], RegsPerFrame); - for(unsigned int x = 0; x < 2 * NWindows; x++) - UNSERIALIZE_ARRAY(regSegments[x], RegsPerFrame); } diff --git a/src/arch/sparc/intregfile.hh b/src/arch/sparc/intregfile.hh index 9a086f08a..9bbb469ef 100644 --- a/src/arch/sparc/intregfile.hh +++ b/src/arch/sparc/intregfile.hh @@ -42,8 +42,6 @@ class Checkpoint; namespace SparcISA { - class RegFile; - //This function translates integer register file indices into names std::string getIntRegName(RegIndex); @@ -52,39 +50,10 @@ namespace SparcISA class IntRegFile { - private: - friend class RegFile; protected: - //The number of bits needed to index into each 8 register frame - static const int FrameOffsetBits = 3; - //The number of bits to choose between the 4 sets of 8 registers - static const int FrameNumBits = 2; - - //The number of registers per "frame" (8) - static const int RegsPerFrame = 1 << FrameOffsetBits; - //A mask to get the frame number - static const uint64_t FrameNumMask = - (FrameNumBits == sizeof(int)) ? - (unsigned int)(-1) : - (1 << FrameNumBits) - 1; - static const uint64_t FrameOffsetMask = - (FrameOffsetBits == sizeof(int)) ? - (unsigned int)(-1) : - (1 << FrameOffsetBits) - 1; - - IntReg regGlobals[MaxGL+1][RegsPerFrame]; - IntReg regSegments[2 * NWindows][RegsPerFrame]; IntReg microRegs[NumMicroIntRegs]; IntReg regs[NumIntRegs]; - enum regFrame {Globals, Outputs, Locals, Inputs, NumFrames}; - - IntReg * regView[NumFrames]; - - static const int RegGlobalOffset = 0; - static const int FrameOffset = (MaxGL + 1) * RegsPerFrame; - int offset[NumFrames]; - public: void clear(); -- cgit v1.2.3 From 437b02884dedccc6f72f3e5d9c05d3a2dd6c6a2d Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:22:31 -0800 Subject: ISA: Get rid of the get*RegName functions. --- src/arch/alpha/floatregfile.hh | 6 ------ src/arch/alpha/intregfile.hh | 6 ------ src/arch/alpha/miscregfile.hh | 6 ------ src/arch/mips/regfile/float_regfile.hh | 5 ----- src/arch/mips/regfile/int_regfile.hh | 5 ----- src/arch/mips/regfile/misc_regfile.cc | 16 +++++----------- src/arch/mips/regfile/misc_regfile.hh | 2 -- src/arch/sparc/floatregfile.cc | 14 -------------- src/arch/sparc/floatregfile.hh | 2 -- src/arch/sparc/intregfile.cc | 10 ---------- src/arch/sparc/intregfile.hh | 3 --- src/arch/sparc/miscregfile.cc | 28 +++------------------------- src/arch/sparc/miscregfile.hh | 3 --- src/arch/sparc/ua2005.cc | 21 +++++++++++++++++++++ src/arch/x86/floatregfile.cc | 9 --------- src/arch/x86/floatregfile.hh | 2 -- src/arch/x86/intregfile.cc | 11 ----------- src/arch/x86/intregfile.hh | 3 --- src/arch/x86/miscregfile.cc | 6 ------ src/arch/x86/miscregfile.hh | 3 --- 20 files changed, 29 insertions(+), 132 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/floatregfile.hh b/src/arch/alpha/floatregfile.hh index 82592d80d..d5f9eec0f 100644 --- a/src/arch/alpha/floatregfile.hh +++ b/src/arch/alpha/floatregfile.hh @@ -42,12 +42,6 @@ class Checkpoint; namespace AlphaISA { -static inline std::string -getFloatRegName(RegIndex) -{ - return ""; -} - class FloatRegFile { public: diff --git a/src/arch/alpha/intregfile.hh b/src/arch/alpha/intregfile.hh index f6ba72e79..3aa7d92c4 100644 --- a/src/arch/alpha/intregfile.hh +++ b/src/arch/alpha/intregfile.hh @@ -41,12 +41,6 @@ class Checkpoint; namespace AlphaISA { -static inline std::string -getIntRegName(RegIndex) -{ - return ""; -} - // redirected register map, really only used for the full system case. extern const int reg_redir[NumIntRegs]; diff --git a/src/arch/alpha/miscregfile.hh b/src/arch/alpha/miscregfile.hh index 752099d01..6105ce683 100644 --- a/src/arch/alpha/miscregfile.hh +++ b/src/arch/alpha/miscregfile.hh @@ -53,12 +53,6 @@ enum MiscRegIndex MISCREG_INTR }; -static inline std::string -getMiscRegName(RegIndex) -{ - return ""; -} - class MiscRegFile { public: diff --git a/src/arch/mips/regfile/float_regfile.hh b/src/arch/mips/regfile/float_regfile.hh index 1537855df..0c0ecc7eb 100644 --- a/src/arch/mips/regfile/float_regfile.hh +++ b/src/arch/mips/regfile/float_regfile.hh @@ -44,11 +44,6 @@ class Checkpoint; namespace MipsISA { - static inline std::string getFloatRegName(RegIndex) - { - return ""; - } - const uint32_t MIPS32_QNAN = 0x7fbfffff; const uint64_t MIPS64_QNAN = ULL(0x7fbfffffffffffff); diff --git a/src/arch/mips/regfile/int_regfile.hh b/src/arch/mips/regfile/int_regfile.hh index 0f453a382..c5a6bb345 100644 --- a/src/arch/mips/regfile/int_regfile.hh +++ b/src/arch/mips/regfile/int_regfile.hh @@ -42,11 +42,6 @@ class Checkpoint; namespace MipsISA { - static inline std::string getIntRegName(RegIndex) - { - return ""; - } - enum MiscIntRegNums { LO = NumIntArchRegs, HI, diff --git a/src/arch/mips/regfile/misc_regfile.cc b/src/arch/mips/regfile/misc_regfile.cc index 08487db90..ea858abf0 100644 --- a/src/arch/mips/regfile/misc_regfile.cc +++ b/src/arch/mips/regfile/misc_regfile.cc @@ -437,12 +437,6 @@ MiscRegFile::reset(std::string core_name, unsigned num_threads, } -inline std::string -MipsISA::getMiscRegName(unsigned reg_idx) -{ - return MiscRegFile::miscRegNames[reg_idx]; -} - inline unsigned MiscRegFile::getVPENum(unsigned tid) { @@ -457,7 +451,7 @@ MiscRegFile::readRegNoEffect(int reg_idx, unsigned tid) unsigned reg_sel = (bankType[misc_reg] == perThreadContext) ? tid : getVPENum(tid); DPRINTF(MipsPRA, "Reading CP0 Register:%u Select:%u (%s) (%lx).\n", - misc_reg / 8, misc_reg % 8, getMiscRegName(misc_reg), + misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg], miscRegFile[misc_reg][reg_sel]); return miscRegFile[misc_reg][reg_sel]; } @@ -474,7 +468,7 @@ MiscRegFile::readReg(int reg_idx, ? tid : getVPENum(tid); DPRINTF(MipsPRA, "Reading CP0 Register:%u Select:%u (%s) with effect (%lx).\n", - misc_reg / 8, misc_reg % 8, getMiscRegName(misc_reg), + misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg], miscRegFile[misc_reg][reg_sel]); @@ -494,7 +488,7 @@ MiscRegFile::setRegNoEffect(int reg_idx, const MiscReg &val, unsigned tid) DPRINTF(MipsPRA, "[tid:%i]: Setting (direct set) CP0 Register:%u " "Select:%u (%s) to %#x.\n", - tid, misc_reg / 8, misc_reg % 8, getMiscRegName(misc_reg), val); + tid, misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg], val); miscRegFile[misc_reg][reg_sel] = val; } @@ -507,7 +501,7 @@ MiscRegFile::setRegMask(int reg_idx, const MiscReg &val, unsigned tid) ? tid : getVPENum(tid); DPRINTF(MipsPRA, "[tid:%i]: Setting CP0 Register: %u Select: %u (%s) to %#x\n", - tid, misc_reg / 8, misc_reg % 8, getMiscRegName(misc_reg), val); + tid, misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg], val); miscRegFile_WriteMask[misc_reg][reg_sel] = val; } @@ -527,7 +521,7 @@ MiscRegFile::setReg(int reg_idx, const MiscReg &val, DPRINTF(MipsPRA, "[tid:%i]: Setting CP0 Register:%u " "Select:%u (%s) to %#x, with effect.\n", - tid, misc_reg / 8, misc_reg % 8, getMiscRegName(misc_reg), val); + tid, misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg], val); MiscReg cp0_val = filterCP0Write(misc_reg, reg_sel, val); diff --git a/src/arch/mips/regfile/misc_regfile.hh b/src/arch/mips/regfile/misc_regfile.hh index 4bec9a49e..c611d94cc 100644 --- a/src/arch/mips/regfile/misc_regfile.hh +++ b/src/arch/mips/regfile/misc_regfile.hh @@ -162,8 +162,6 @@ namespace MipsISA static std::string miscRegNames[NumMiscRegs]; }; - - inline std::string getMiscRegName(unsigned reg_idx); } // namespace MipsISA #endif diff --git a/src/arch/sparc/floatregfile.cc b/src/arch/sparc/floatregfile.cc index cf33b6a77..2d1af2218 100644 --- a/src/arch/sparc/floatregfile.cc +++ b/src/arch/sparc/floatregfile.cc @@ -41,20 +41,6 @@ using namespace std; class Checkpoint; -string SparcISA::getFloatRegName(RegIndex index) -{ - static std::string floatRegName[NumFloatRegs] = - {"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", - "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", - "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", - "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", - "f32", "f33", "f34", "f35", "f36", "f37", "f38", "f39", - "f40", "f41", "f42", "f43", "f44", "f45", "f46", "f47", - "f48", "f49", "f50", "f51", "f52", "f53", "f54", "f55", - "f56", "f57", "f58", "f59", "f60", "f61", "f62", "f63"}; - return floatRegName[index]; -} - void FloatRegFile::clear() { memset(regSpace, 0, sizeof(regSpace)); diff --git a/src/arch/sparc/floatregfile.hh b/src/arch/sparc/floatregfile.hh index 72803a5e0..265e71b4a 100644 --- a/src/arch/sparc/floatregfile.hh +++ b/src/arch/sparc/floatregfile.hh @@ -42,8 +42,6 @@ class Checkpoint; namespace SparcISA { - std::string getFloatRegName(RegIndex); - const int NumFloatArchRegs = 64; const int NumFloatRegs = 64; diff --git a/src/arch/sparc/intregfile.cc b/src/arch/sparc/intregfile.cc index 49e41ed93..54c30d1cc 100644 --- a/src/arch/sparc/intregfile.cc +++ b/src/arch/sparc/intregfile.cc @@ -41,16 +41,6 @@ using namespace std; class Checkpoint; -string SparcISA::getIntRegName(RegIndex index) -{ - static std::string intRegName[NumIntArchRegs] = - {"g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", - "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7", - "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", - "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7"}; - return intRegName[index]; -} - void IntRegFile::clear() { memset(regs, 0, sizeof(IntReg) * NumIntRegs); diff --git a/src/arch/sparc/intregfile.hh b/src/arch/sparc/intregfile.hh index 9bbb469ef..f669f6b0d 100644 --- a/src/arch/sparc/intregfile.hh +++ b/src/arch/sparc/intregfile.hh @@ -42,9 +42,6 @@ class Checkpoint; namespace SparcISA { - //This function translates integer register file indices into names - std::string getIntRegName(RegIndex); - const int NumIntArchRegs = 32; const int NumIntRegs = (MaxGL + 1) * 8 + NWindows * 16 + NumMicroIntRegs; diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc index e06d4b15a..38eba3862 100644 --- a/src/arch/sparc/miscregfile.cc +++ b/src/arch/sparc/miscregfile.cc @@ -42,27 +42,6 @@ using namespace std; class Checkpoint; -//These functions map register indices to names -string SparcISA::getMiscRegName(RegIndex index) -{ - static::string miscRegName[NumMiscRegs] = - {/*"y", "ccr",*/ "asi", "tick", "fprs", "pcr", "pic", - "gsr", "softint_set", "softint_clr", "softint", "tick_cmpr", - "stick", "stick_cmpr", - "tpc", "tnpc", "tstate", "tt", "privtick", "tba", "pstate", "tl", - "pil", "cwp", /*"cansave", "canrestore", "cleanwin", "otherwin", - "wstate",*/ "gl", - "hpstate", "htstate", "hintp", "htba", "hver", "strand_sts_reg", - "hstick_cmpr", - "fsr", "prictx", "secctx", "partId", "lsuCtrlReg", - "scratch0", "scratch1", "scratch2", "scratch3", "scratch4", - "scratch5", "scratch6", "scratch7", "cpuMondoHead", "cpuMondoTail", - "devMondoHead", "devMondoTail", "resErrorHead", "resErrorTail", - "nresErrorHead", "nresErrorTail", "TlbData" }; - - return miscRegName[index]; -} - enum RegMask { PSTATE_MASK = (((1 << 4) - 1) << 1) | (((1 << 4) - 1) << 6) | (1 << 12) @@ -328,8 +307,7 @@ MiscReg MiscRegFile::readReg(int miscReg, ThreadContext * tc) //isn't, instead of panicing. return 0; - panic("Accessing Fullsystem register %s in SE mode\n", - getMiscRegName(miscReg)); + panic("Accessing Fullsystem register %d in SE mode\n", miscReg); #endif } @@ -583,8 +561,8 @@ void MiscRegFile::setReg(int miscReg, //HPSTATE is special because normal trap processing saves HPSTATE when //it goes into a trap, and restores it when it returns. return; - panic("Accessing Fullsystem register %s to %#x in SE mode\n", - getMiscRegName(miscReg), val); + panic("Accessing Fullsystem register %d to %#x in SE mode\n", + miscReg, val); #endif } setRegNoEffect(miscReg, new_val); diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh index 6a010f529..9eff7fcac 100644 --- a/src/arch/sparc/miscregfile.hh +++ b/src/arch/sparc/miscregfile.hh @@ -43,9 +43,6 @@ class Checkpoint; namespace SparcISA { - //These functions map register indices to names - std::string getMiscRegName(RegIndex); - enum MiscRegIndex { /** Ancillary State Registers */ diff --git a/src/arch/sparc/ua2005.cc b/src/arch/sparc/ua2005.cc index 2389c963d..880d2c3eb 100644 --- a/src/arch/sparc/ua2005.cc +++ b/src/arch/sparc/ua2005.cc @@ -35,6 +35,7 @@ #include "sim/system.hh" using namespace SparcISA; +using namespace std; void @@ -61,6 +62,26 @@ MiscRegFile::checkSoftInt(ThreadContext *tc) } } +//These functions map register indices to names +static inline string +getMiscRegName(RegIndex index) +{ + static string miscRegName[NumMiscRegs] = + {/*"y", "ccr",*/ "asi", "tick", "fprs", "pcr", "pic", + "gsr", "softint_set", "softint_clr", "softint", "tick_cmpr", + "stick", "stick_cmpr", + "tpc", "tnpc", "tstate", "tt", "privtick", "tba", "pstate", "tl", + "pil", "cwp", /*"cansave", "canrestore", "cleanwin", "otherwin", + "wstate",*/ "gl", + "hpstate", "htstate", "hintp", "htba", "hver", "strand_sts_reg", + "hstick_cmpr", + "fsr", "prictx", "secctx", "partId", "lsuCtrlReg", + "scratch0", "scratch1", "scratch2", "scratch3", "scratch4", + "scratch5", "scratch6", "scratch7", "cpuMondoHead", "cpuMondoTail", + "devMondoHead", "devMondoTail", "resErrorHead", "resErrorTail", + "nresErrorHead", "nresErrorTail", "TlbData" }; + return miscRegName[index]; +} void MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc) diff --git a/src/arch/x86/floatregfile.cc b/src/arch/x86/floatregfile.cc index da5372c69..fce7f4868 100644 --- a/src/arch/x86/floatregfile.cc +++ b/src/arch/x86/floatregfile.cc @@ -96,15 +96,6 @@ using namespace std; class Checkpoint; -string X86ISA::getFloatRegName(RegIndex index) -{ - static std::string floatRegName[NumFloatRegs] = - {"mmx0", "mmx1", "mmx2", "mmx3", "mmx4", "mmx5", "mmx6", "mmx7", - "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", - "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"}; - return floatRegName[index]; -} - void FloatRegFile::clear() { memset(q, 0, sizeof(FloatReg) * NumFloatRegs); diff --git a/src/arch/x86/floatregfile.hh b/src/arch/x86/floatregfile.hh index b77ddb0eb..ab239dd7d 100644 --- a/src/arch/x86/floatregfile.hh +++ b/src/arch/x86/floatregfile.hh @@ -98,8 +98,6 @@ class Checkpoint; namespace X86ISA { - std::string getFloatRegName(RegIndex); - //Each 128 bit xmm register is broken into two effective 64 bit registers. const int NumFloatRegs = NumMMXRegs + 2 * NumXMMRegs + NumMicroFpRegs; diff --git a/src/arch/x86/intregfile.cc b/src/arch/x86/intregfile.cc index 43cfb8082..58a37cb9e 100644 --- a/src/arch/x86/intregfile.cc +++ b/src/arch/x86/intregfile.cc @@ -97,17 +97,6 @@ using namespace std; class Checkpoint; -string X86ISA::getIntRegName(RegIndex index) -{ - //These might appear to be out of order, but they match - //the encoding for the registers. Who knows why the indexes - //are out of order - static std::string intRegName[NumIntArchRegs] = - {"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}; - return intRegName[index]; -} - int IntRegFile::flattenIndex(int reg) { return reg; diff --git a/src/arch/x86/intregfile.hh b/src/arch/x86/intregfile.hh index b4d256a04..131245352 100644 --- a/src/arch/x86/intregfile.hh +++ b/src/arch/x86/intregfile.hh @@ -100,9 +100,6 @@ namespace X86ISA { class Regfile; - //This function translates integer register file indices into names - std::string getIntRegName(RegIndex); - const int NumIntArchRegs = NUM_INTREGS; const int NumIntRegs = NumIntArchRegs + NumMicroIntRegs + diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc index 01aac14b1..0316603e5 100644 --- a/src/arch/x86/miscregfile.cc +++ b/src/arch/x86/miscregfile.cc @@ -96,12 +96,6 @@ using namespace std; class Checkpoint; -//These functions map register indices to names -string X86ISA::getMiscRegName(RegIndex index) -{ - panic("No misc registers in x86 yet!\n"); -} - void MiscRegFile::clear() { // Blank everything. 0 might not be an appropriate value for some things, diff --git a/src/arch/x86/miscregfile.hh b/src/arch/x86/miscregfile.hh index e59b8d3b1..6d3ae4e92 100644 --- a/src/arch/x86/miscregfile.hh +++ b/src/arch/x86/miscregfile.hh @@ -99,9 +99,6 @@ class Checkpoint; namespace X86ISA { - - std::string getMiscRegName(RegIndex); - //These will have to be updated in the future. const int NumMiscArchRegs = NUM_MISCREGS; const int NumMiscRegs = NUM_MISCREGS; -- cgit v1.2.3 From 5c546e35046a0b7260dec0b4d979e05f29505785 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:22:36 -0800 Subject: CPU: Only look up the nearest symbol in the kernel if you're actually in kernel code. --- src/cpu/exetrace.cc | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc index 5897d1dbc..ea53fb6f5 100644 --- a/src/cpu/exetrace.cc +++ b/src/cpu/exetrace.cc @@ -71,6 +71,9 @@ Trace::ExeTracerRecord::traceInst(StaticInstPtr inst, bool ran) Addr sym_addr; if (debugSymbolTable && IsOn(ExecSymbol) +#if FULL_SYSTEM + && !inUserMode(thread) +#endif && debugSymbolTable->findNearestSymbol(PC, sym_str, sym_addr)) { if (PC != sym_addr) sym_str += csprintf("+%d", PC - sym_addr); -- cgit v1.2.3 From 7400769768d847b4d7b8f2c27eb78f463c3887a2 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:22:43 -0800 Subject: X86: Implement IST stack switching. --- src/arch/x86/isa/insts/romutil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/romutil.py b/src/arch/x86/isa/insts/romutil.py index beeda3d12..e47259eb3 100644 --- a/src/arch/x86/isa/insts/romutil.py +++ b/src/arch/x86/isa/insts/romutil.py @@ -99,7 +99,7 @@ def rom br rom_local_label("%(startLabel)s_stackSwitched") %(startLabel)s_istStackSwitch: - panic "IST based stack switching isn't implemented" + ld t6, tr, [8, t12, t0], 0x1c, dataSize=8, addressSize=8, atCPL0=True br rom_local_label("%(startLabel)s_stackSwitched") %(startLabel)s_cplStackSwitch: -- cgit v1.2.3 From 4a644931589499a444cafe8a7c6eeec614b8bdb7 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Feb 2009 10:22:49 -0800 Subject: Devices: Make the RTC device reflect the use of BCD in its status registers. --- src/dev/mc146818.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/dev/mc146818.cc b/src/dev/mc146818.cc index 7b219e30c..c01d945b3 100644 --- a/src/dev/mc146818.cc +++ b/src/dev/mc146818.cc @@ -49,7 +49,9 @@ MC146818::MC146818(EventManager *em, const string &n, const struct tm time, { memset(clock_data, 0, sizeof(clock_data)); stat_regA = RTCA_32768HZ | RTCA_1024HZ; - stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR; + stat_regB = RTCB_PRDC_IE | RTCB_24HR; + if (!bcd) + stat_regB |= RTCB_BIN; year = time.tm_year; -- cgit v1.2.3 From 894925f1350409c40106aa6a0cc4d5cc31fa2b84 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Thu, 26 Feb 2009 19:29:16 -0500 Subject: Trace: fix the --trace-start option --- src/python/m5/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/python/m5/main.py b/src/python/m5/main.py index f562835da..98019b197 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -312,7 +312,7 @@ def main(): if options.trace_start: check_tracing() - e = event.create(trace.enable, Event.Trace_Enable_Pri) + e = event.create(trace.enable, event.Event.Trace_Enable_Pri) event.mainq.schedule(e, options.trace_start) else: trace.enable() -- cgit v1.2.3 From 6fd4bc34a154601ba0a74e41875094c20076e091 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Thu, 26 Feb 2009 19:29:17 -0500 Subject: CPA: Add new object for gathering critical path annotations. --- src/arch/alpha/isa/decoder.isa | 59 +- src/arch/alpha/isa/main.isa | 1 + src/base/CPA.py | 8 + src/base/SConscript | 9 +- src/base/annotate.cc | 122 ---- src/base/annotate.hh | 73 --- src/base/cp_annotate.cc | 1404 ++++++++++++++++++++++++++++++++++++++++ src/base/cp_annotate.hh | 522 +++++++++++++++ src/base/hashmap.hh | 10 + src/base/loader/symtab.hh | 1 + src/python/m5/SimObject.py | 3 +- src/sim/pseudo_inst.cc | 2 +- 12 files changed, 2013 insertions(+), 201 deletions(-) create mode 100644 src/base/CPA.py delete mode 100644 src/base/annotate.cc delete mode 100644 src/base/annotate.hh create mode 100644 src/base/cp_annotate.cc create mode 100644 src/base/cp_annotate.hh (limited to 'src') diff --git a/src/arch/alpha/isa/decoder.isa b/src/arch/alpha/isa/decoder.isa index 67bc5c7a2..0b2a31410 100644 --- a/src/arch/alpha/isa/decoder.isa +++ b/src/arch/alpha/isa/decoder.isa @@ -870,9 +870,62 @@ decode OPCODE default Unknown::unknown() { 0x54: m5panic({{ panic("M5 panic instruction called at pc=%#x.", xc->readPC()); }}, IsNonSpeculative); - 0x55: m5reserved1({{ - warn("M5 reserved opcode ignored"); - }}, IsNonSpeculative); +#define CPANN(lbl) CPA::cpa()->lbl(xc->tcBase()) + 0x55: decode RA { + 0x00: m5a_old({{ + panic("Deprecated M5 annotate instruction executed at pc=%#x\n", + xc->readPC()); + }}, IsNonSpeculative); + 0x01: m5a_bsm({{ + CPANN(swSmBegin); + }}, IsNonSpeculative); + 0x02: m5a_esm({{ + CPANN(swSmEnd); + }}, IsNonSpeculative); + 0x03: m5a_begin({{ + CPANN(swExplictBegin); + }}, IsNonSpeculative); + 0x04: m5a_end({{ + CPANN(swEnd); + }}, IsNonSpeculative); + 0x06: m5a_q({{ + CPANN(swQ); + }}, IsNonSpeculative); + 0x07: m5a_dq({{ + CPANN(swDq); + }}, IsNonSpeculative); + 0x08: m5a_wf({{ + CPANN(swWf); + }}, IsNonSpeculative); + 0x09: m5a_we({{ + CPANN(swWe); + }}, IsNonSpeculative); + 0x0C: m5a_sq({{ + CPANN(swSq); + }}, IsNonSpeculative); + 0x0D: m5a_aq({{ + CPANN(swAq); + }}, IsNonSpeculative); + 0x0E: m5a_pq({{ + CPANN(swPq); + }}, IsNonSpeculative); + 0x0F: m5a_l({{ + CPANN(swLink); + }}, IsNonSpeculative); + 0x10: m5a_identify({{ + CPANN(swIdentify); + }}, IsNonSpeculative); + 0x11: m5a_getid({{ + R0 = CPANN(swGetId); + }}, IsNonSpeculative); + 0x13: m5a_scl({{ + CPANN(swSyscallLink); + }}, IsNonSpeculative); + 0x14: m5a_rq({{ + CPANN(swRq); + }}, IsNonSpeculative); + } // M5 Annotate Operations +#undef CPANN 0x56: m5reserved2({{ warn("M5 reserved opcode ignored"); }}, IsNonSpeculative); diff --git a/src/arch/alpha/isa/main.isa b/src/arch/alpha/isa/main.isa index f34bd4b33..aea44976c 100644 --- a/src/arch/alpha/isa/main.isa +++ b/src/arch/alpha/isa/main.isa @@ -68,6 +68,7 @@ using namespace AlphaISA; output exec {{ #include +#include "base/cp_annotate.hh" #include "sim/pseudo_inst.hh" #include "arch/alpha/ipr.hh" #include "base/fenv.hh" diff --git a/src/base/CPA.py b/src/base/CPA.py new file mode 100644 index 000000000..c0beaedef --- /dev/null +++ b/src/base/CPA.py @@ -0,0 +1,8 @@ +from m5.SimObject import SimObject +from m5.params import * + +class CPA(SimObject): + type = 'CPA' + + enabled = Param.Bool(False, "Is Annotation enabled?") + user_apps = VectorParam.String([], "List of apps to get symbols for") diff --git a/src/base/SConscript b/src/base/SConscript index ffad1929a..58c453184 100644 --- a/src/base/SConscript +++ b/src/base/SConscript @@ -30,7 +30,9 @@ Import('*') -Source('annotate.cc') +if env['CP_ANNOTATE']: + SimObject('CPA.py') + Source('cp_annotate.cc') Source('atomicio.cc') Source('bigint.cc') Source('circlebuf.cc') @@ -82,6 +84,8 @@ if env['USE_MYSQL']: Source('stats/mysql.cc') TraceFlag('Annotate', "State machine annotation debugging") +TraceFlag('AnnotateQ', "State machine annotation queue debugging") +TraceFlag('AnnotateVerbose', "Dump all state machine annotation details") TraceFlag('GDBAcc', "Remote debugger accesses") TraceFlag('GDBExtra', "Dump extra information on reads and writes") TraceFlag('GDBMisc', "Breakpoints, traps, watchpoints, etc.") @@ -96,3 +100,6 @@ CompoundFlag('GDBAll', [ 'GDBMisc', 'GDBAcc', 'GDBRead', 'GDBWrite', 'GDBSend', 'GDBRecv', 'GDBExtra' ], desc="All Remote debugging flags") +CompoundFlag('AnnotateAll', ['Annotate', 'AnnotateQ', 'AnnotateVerbose'], + desc="All Annotation flags") + diff --git a/src/base/annotate.cc b/src/base/annotate.cc deleted file mode 100644 index de7eeed51..000000000 --- a/src/base/annotate.cc +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Ali Saidi - */ - -#include "base/annotate.hh" -#include "base/callback.hh" -#include "base/output.hh" -#include "base/trace.hh" -#include "sim/core.hh" -#include "sim/sim_exit.hh" -#include "sim/system.hh" - - - -class AnnotateDumpCallback : public Callback -{ - public: - virtual void process(); -}; - -void -AnnotateDumpCallback::process() -{ - Annotate::annotations.dump(); -} - -namespace Annotate { - - -Annotate annotations; - -Annotate::Annotate() -{ - registerExitCallback(new AnnotateDumpCallback); -} - -void -Annotate::add(System *sys, Addr stack, uint32_t sm, uint32_t st, - uint32_t wm, uint32_t ws) -{ - AnnotateData *an; - - an = new AnnotateData; - an->time = curTick; - - std::map::iterator i = nameCache.find(sys); - if (i == nameCache.end()) { - nameCache[sys] = sys->name(); - } - - an->system = nameCache[sys]; - an->stack = stack; - an->stateMachine = sm; - an->curState = st; - an->waitMachine = wm; - an->waitState = ws; - - data.push_back(an); - if (an->waitMachine) - DPRINTF(Annotate, "Annotating: %s(%#llX) %d:%d waiting on %d:%d\n", - an->system, an->stack, an->stateMachine, an->curState, - an->waitMachine, an->waitState); - else - DPRINTF(Annotate, "Annotating: %s(%#llX) %d:%d beginning\n", an->system, - an->stack, an->stateMachine, an->curState); - - DPRINTF(Annotate, "Now %d events on list\n", data.size()); - -} - -void -Annotate::dump() -{ - - std::list::iterator i; - - i = data.begin(); - - if (i == data.end()) - return; - - std::ostream *os = simout.create("annotate.dat"); - - AnnotateData *an; - - while (i != data.end()) { - DPRINTF(Annotate, "Writing\n", data.size()); - an = *i; - ccprintf(*os, "%d %s(%#llX) %d %d %d %d\n", an->time, an->system, - an->stack, an->stateMachine, an->curState, an->waitMachine, - an->waitState); - i++; - } -} - -} //namespace Annotate diff --git a/src/base/annotate.hh b/src/base/annotate.hh deleted file mode 100644 index 36607bf90..000000000 --- a/src/base/annotate.hh +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Ali Saidi - */ - -#ifndef __BASE__ANNOTATE_HH__ -#define __BASE__ANNOTATE_HH__ - -#include "sim/host.hh" - -#include -#include -#include - - -class System; - -namespace Annotate { - - -class Annotate { - - protected: - struct AnnotateData { - Tick time; - std::string system; - Addr stack; - uint32_t stateMachine; - uint32_t curState; - uint32_t waitMachine; - uint32_t waitState; - }; - - std::list data; - std::map nameCache; - - public: - Annotate(); - void add(System *sys, Addr stack, uint32_t sm, uint32_t st, uint32_t - wm, uint32_t ws); - void dump(); -}; - -extern Annotate annotations; -} //namespace Annotate - -#endif //__BASE__ANNOTATE_HH__ - diff --git a/src/base/cp_annotate.cc b/src/base/cp_annotate.cc new file mode 100644 index 000000000..0aba2d999 --- /dev/null +++ b/src/base/cp_annotate.cc @@ -0,0 +1,1404 @@ +/* + * Copyright (c) 2006-2009 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + +#include "arch/utility.hh" +#include "arch/alpha/linux/threadinfo.hh" +#include "base/cp_annotate.hh" +#include "base/callback.hh" +#include "base/loader/object_file.hh" +#include "base/output.hh" +#include "base/trace.hh" +#include "cpu/thread_context.hh" +#include "sim/arguments.hh" +#include "sim/core.hh" +#include "sim/sim_exit.hh" +#include "sim/system.hh" + +struct CPAIgnoreSymbol +{ + const char *symbol; + size_t len; +}; +#define CPA_IGNORE_SYMBOL(sym) { #sym, sizeof(#sym) } + +CPAIgnoreSymbol ignoreSymbols[] = { + CPA_IGNORE_SYMBOL("m5a_"), + CPA_IGNORE_SYMBOL("ret_from_sys_call"), + CPA_IGNORE_SYMBOL("ret_from_reschedule"), + CPA_IGNORE_SYMBOL("_spin_"), + CPA_IGNORE_SYMBOL("local_bh_"), + CPA_IGNORE_SYMBOL("restore_all"), + CPA_IGNORE_SYMBOL("Call_Pal_"), + CPA_IGNORE_SYMBOL("pal_post_interrupt"), + CPA_IGNORE_SYMBOL("rti_to_"), + CPA_IGNORE_SYMBOL("sys_int_2"), + CPA_IGNORE_SYMBOL("sys_interrupt"), + CPA_IGNORE_SYMBOL("normal_int"), + CPA_IGNORE_SYMBOL("TRAP_INTERRUPT_10_"), + CPA_IGNORE_SYMBOL("Trap_Interrupt"), + CPA_IGNORE_SYMBOL("do_entInt"), + CPA_IGNORE_SYMBOL("__do_softirq"), + CPA_IGNORE_SYMBOL("_end"), + CPA_IGNORE_SYMBOL("entInt"), + CPA_IGNORE_SYMBOL("entSys"), + {0,0} +}; +#undef CPA_IGNORE_SYMBOL + +using namespace std; +using namespace TheISA; + +bool CPA::exists; +CPA *CPA::_cpa; + +class AnnotateDumpCallback : public Callback +{ + + private: + CPA *cpa; + public: + virtual void process(); + AnnotateDumpCallback(CPA *_cpa) + : cpa(_cpa) + {} +}; + +void +AnnotateDumpCallback::process() +{ + cpa->dump(true); + cpa->dumpKey(); +} + + +CPA::CPA(Params *p) + : SimObject(p), numSm(0), numSmt(0), numSys(0), numQs(0), conId(0) +{ + if (exists) + fatal("Multiple annotation objects found in system"); + exists = true; + + _enabled = p->enabled; + _cpa = this; + + vector::iterator i; + i = p->user_apps.begin(); + + while (i != p->user_apps.end()) { + ObjectFile *of = createObjectFile(*i); + string sf; + if (!of) + fatal("Couldn't load symbols from file: %s\n", *i); + sf = *i; + sf.erase(0, sf.rfind('/') + 1);; + DPRINTFN("file %s short: %s\n", *i, sf); + userApp[sf] = new SymbolTable; + bool result1 = of->loadGlobalSymbols(userApp[sf]); + bool result2 = of->loadLocalSymbols(userApp[sf]); + if (!result1 || !result2) + panic("blah"); + assert(result1 && result2); + i++; + } +} + +void +CPA::startup() +{ + osbin = simout.create("annotate.bin", true); + // MAGIC version number 'M''5''A'N' + version/capabilities + ah.version = 0x4D35414E00000101ULL; + ah.num_recs = 0; + ah.key_off = 0; + osbin->write((char*)&ah, sizeof(AnnotateHeader)); + + registerExitCallback(new AnnotateDumpCallback(this)); +} +void +CPA::swSmBegin(ThreadContext *tc) +{ + if (!enabled()) + return; + + Arguments args(tc); + std::string st; + Addr junk; + char sm[50]; + if (!TheISA::inUserMode(tc)) + debugSymbolTable->findNearestSymbol( + tc->readIntReg(ReturnAddressReg), st, junk); + + CopyStringOut(tc, sm, args[0], 50); + System *sys = tc->getSystemPtr(); + StringWrap name(sys->name()); + + if (!sm[0]) + warn("Got null SM at tick %d\n", curTick); + + int sysi = getSys(sys); + int smi = getSm(sysi, sm, args[1]); + DPRINTF(Annotate, "Starting machine: %s(%d) sysi: %d id: %#x\n", sm, + smi, sysi, args[1]); + DPRINTF(Annotate, "smMap[%d] = %d, %s, %#x\n", smi, + smMap[smi-1].first, smMap[smi-1].second.first, + smMap[smi-1].second.second); + + uint64_t frame = getFrame(tc); + StackId sid = StackId(sysi, frame); + + // check if we need to link to the previous state machine + int flags = args[2]; + if (flags & FL_LINK) { + if (smStack[sid].size()) { + int prev_smi = smStack[sid].back(); + DPRINTF(Annotate, "Linking from %d to state machine %s(%d) [%#x]\n", + prev_smi, sm, smi, args[1]); + + if (lnMap[smi]) + DPRINTF(Annotate, "LnMap already contains entry for %d of %d\n", + smi, lnMap[smi]); + assert(lnMap[smi] == 0); + lnMap[smi] = prev_smi; + + add(OP_LINK, FL_NONE, tc->contextId(), prev_smi, smi); + } else { + DPRINTF(Annotate, "Not Linking to state machine %s(%d) [%#x]\n", + sm, smi, args[1]); + } + } + + + smStack[sid].push_back(smi); + + DPRINTF(Annotate, "Stack Now (%#X):\n", frame); + for (int x = smStack[sid].size()-1; x >= 0; x--) + DPRINTF(Annotate, "-- %d\n", smStack[sid][x]); + + // reset the sw state exculsion to false + if (swExpl[sid]) + swExpl[sid] = false; + + + Id id = Id(sm, frame); + if (scLinks[sysi-1][id]) { + AnnDataPtr an = scLinks[sysi-1][id]; + scLinks[sysi-1].erase(id); + an->stq = smi; + an->dump = true; + DPRINTF(Annotate, + "Found prev unknown linking from %d to state machine %s(%d)\n", + an->sm, sm, smi); + + if (lnMap[smi]) + DPRINTF(Annotate, "LnMap already contains entry for %d of %d\n", + smi, lnMap[smi]); + assert(lnMap[smi] == 0); + lnMap[smi] = an->sm; + } + + // add a new begin ifwe have that info + if (st != "") { + DPRINTF(Annotate, "st: %s smi: %d stCache.size %d\n", st, + smi, stCache.size()); + int sti = getSt(sm, st); + lastState[smi] = sti; + add(OP_BEGIN, FL_NONE, tc->contextId(), smi, sti); + } +} + +void +CPA::swSmEnd(ThreadContext *tc) +{ + if (!enabled()) + return; + + Arguments args(tc); + char sm[50]; + CopyStringOut(tc, sm, args[0], 50); + System *sys = tc->getSystemPtr(); + doSwSmEnd(sys, tc->contextId(), sm, getFrame(tc)); +} + +void +CPA::doSwSmEnd(System *sys, int cpuid, string sm, uint64_t frame) +{ + int sysi = getSys(sys); + StackId sid = StackId(sysi, frame); + + + // reset the sw state exculsion to false + if (swExpl[sid]) + swExpl[sid] = false; + + + int smib = smStack[sid].back(); + StringWrap name(sys->name()); + DPRINTF(Annotate, "Ending machine: %s[%d, %#x] (%d?)\n", sm, sysi, + frame, smib); + + if (!smStack[sid].size() || smMap[smib-1].second.first != sm) { + DPRINTF(Annotate, "State Machine not unwinding correctly. sid: %d, %#x" + " top of stack: %s Current Stack:\n", + sysi, frame, smMap[smib-1].second.first); + for (int x = smStack[sid].size()-1; x >= 0; x--) + DPRINTF(Annotate, "-- %d\n", smStack[sid][x]); + DPRINTF(Annotate, "Ending machine: %s; end stack: %s\n", sm, + smMap[smib-1].second.first); + + warn("State machine stack not unwinding correctly at %d\n", curTick); + } else { + DPRINTF(Annotate, + "State machine ending:%s sysi:%d id:%#x back:%d getSm:%d\n", + sm, sysi, smMap[smib-1].second.second, smStack[sid].back(), + getSm(sysi, sm, smMap[smib-1].second.second)); + assert(getSm(sysi, sm, smMap[smib-1].second.second) == + smStack[sid].back()); + + int smi = smStack[sid].back(); + smStack[sid].pop_back(); + + if (lnMap[smi]) { + DPRINTF(Annotate, "Linking %d back to %d\n", smi, lnMap[smi]); + add(OP_LINK, FL_NONE, cpuid, smi, lnMap[smi]); + lnMap.erase(smi); + } + + if (smStack[sid].size()) { + add(OP_BEGIN, FL_NONE, cpuid, smi, lastState[smi]); + } + + DPRINTF(Annotate, "Stack Now:\n"); + for (int x = smStack[sid].size()-1; x >= 0; x--) + DPRINTF(Annotate, "-- %d\n", smStack[sid][x]); + } +} + + +void +CPA::swExplictBegin(ThreadContext *tc) +{ + if (!enabled()) + return; + + Arguments args(tc); + char st[50]; + CopyStringOut(tc, st, args[1], 50); + + StringWrap name(tc->getSystemPtr()->name()); + DPRINTF(Annotate, "Explict begin of state %s\n", st); + uint32_t flags = args[0]; + if (flags & FL_BAD) + warn("BAD state encountered: at cycle %d: %s\n", curTick, st); + swBegin(tc->getSystemPtr(), tc->contextId(), st, getFrame(tc), true, args[0]); +} + +void +CPA::swAutoBegin(ThreadContext *tc, Addr next_pc) +{ + if (!enabled()) + return; + + string sym; + Addr sym_addr = 0; + SymbolTable *symtab = NULL; + + + if (!TheISA::inUserMode(tc)) { + debugSymbolTable->findNearestSymbol(next_pc, sym, sym_addr); + symtab = debugSymbolTable; + } else { + Linux::ThreadInfo ti(tc); + string app = ti.curTaskName(); + if (userApp.count(app)) + userApp[app]->findNearestSymbol(next_pc, sym, sym_addr); + } + + if (sym_addr) + swBegin(tc->getSystemPtr(), tc->contextId(), sym, getFrame(tc)); +} + +void +CPA::swBegin(System *sys, int cpuid, std::string st, uint64_t frame, bool expl, + int flags) +{ + int x = 0; + int len; + while (ignoreSymbols[x].len) + { + len = ignoreSymbols[x].len; + if (!st.compare(0,len, ignoreSymbols[x].symbol, len)) + return; + x++; + } + + int sysi = getSys(sys); + StackId sid = StackId(sysi, frame); + // if expl is true suspend symbol table based states + if (!smStack[sid].size()) + return; + if (!expl && swExpl[sid]) + return; + if (expl) + swExpl[sid] = true; + DPRINTFS(AnnotateVerbose, sys, "SwBegin: %s sysi: %d\n", st, sysi); + int smi = smStack[sid].back(); + int sti = getSt(smMap[smi-1].second.first, st); + if (lastState[smi] != sti) { + lastState[smi] = sti; + add(OP_BEGIN, flags, cpuid, smi, sti); + } +} + +void +CPA::swEnd(ThreadContext *tc) +{ + if (!enabled()) + return; + + std::string st; + Addr junk; + if (!TheISA::inUserMode(tc)) + debugSymbolTable->findNearestSymbol( + tc->readIntReg(ReturnAddressReg), st, junk); + System *sys = tc->getSystemPtr(); + StringWrap name(sys->name()); + + int sysi = getSys(sys); + StackId sid = StackId(sysi, getFrame(tc)); + if (!smStack[sid].size()) { + DPRINTF(Annotate, "Explict end of State: %s IGNORED\n", st); + return; + } + DPRINTF(Annotate, "Explict end of State: %s\n", st); + // return back to symbol table based states + swExpl[sid] = false; + int smi = smStack[sid].back(); + if (st != "") { + int sti = getSt(smMap[smi-1].second.first, st); + lastState[smi] = sti; + add(OP_BEGIN, FL_NONE, tc->contextId(), smi, sti); + } +} + +void +CPA::swQ(ThreadContext *tc) +{ + if (!enabled()) + return; + + char q[50]; + Arguments args(tc); + uint64_t id = args[0]; + CopyStringOut(tc, q, args[1], 50); + int32_t count = args[2]; + System *sys = tc->getSystemPtr(); + + int sysi = getSys(sys); + StackId sid = StackId(sysi, getFrame(tc)); + if (!smStack[sid].size()) + return; + int smi = smStack[sid].back(); + if (swExpl[sid]) + swExpl[sid] = false; + int qi = getQ(sysi, q, id); + if (count == 0) { + //warn("Tried to queue 0 bytes in %s, ignoring\n", q); + return; + } + DPRINTFS(AnnotateQ, sys, + "swQ: %s[%#x] cur size %d %d bytes: %d adding: %d\n", + q, id, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count); + doQ(sys, FL_NONE, tc->contextId(), smi, q, qi, count); +} + +void +CPA::swDq(ThreadContext *tc) +{ + if (!enabled()) + return; + + char q[50]; + Arguments args(tc); + uint64_t id = args[0]; + CopyStringOut(tc, q, args[1], 50); + int32_t count = args[2]; + System *sys = tc->getSystemPtr(); + + int sysi = getSys(sys); + StackId sid = StackId(sysi, getFrame(tc)); + if (!smStack[sid].size()) + return; + int smi = smStack[sid].back(); + int qi = getQ(sysi, q, id); + if (swExpl[sid]) + swExpl[sid] = false; + DPRINTFS(AnnotateQ, sys, + "swDq: %s[%#x] cur size %d %d bytes: %d removing: %d\n", + q, id, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count); + assert(count != 0); + + doDq(sys, FL_NONE, tc->contextId(), smi, q, qi, count); +} + +void +CPA::swPq(ThreadContext *tc) +{ + if (!enabled()) + return; + + char q[50]; + Arguments args(tc); + uint64_t id = args[0]; + CopyStringOut(tc, q, args[1], 50); + System *sys = tc->getSystemPtr(); + int32_t count = args[2]; + + int sysi = getSys(sys); + StackId sid = StackId(sysi, getFrame(tc)); + if (!smStack[sid].size()) + return; + int smi = smStack[sid].back(); + int qi = getQ(sysi, q, id); + if (swExpl[sid]) + swExpl[sid] = false; + DPRINTFS(AnnotateQ, sys, + "swPq: %s [%#x] cur size %d %d bytes: %d peeking: %d\n", + q, id, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count); + + assert(count != 0); + if (qBytes[qi-1] < count) { + dump(true); + dumpKey(); + fatal("Queue %s peeking with not enough bytes available in queue!\n", q); + } + + add(OP_PEEK, FL_NONE, tc->contextId(), smi, qi, count); +} + +void +CPA::swRq(ThreadContext *tc) +{ + if (!enabled()) + return; + + char q[50]; + Arguments args(tc); + uint64_t id = args[0]; + CopyStringOut(tc, q, args[1], 50); + System *sys = tc->getSystemPtr(); + int32_t count = args[2]; + + int sysi = getSys(sys); + StackId sid = StackId(sysi, getFrame(tc)); + if (!smStack[sid].size()) + return; + int smi = smStack[sid].back(); + int qi = getQ(sysi, q, id); + if (swExpl[sid]) + swExpl[sid] = false; + DPRINTFS(AnnotateQ, sys, + "swRq: %s [%#x] cur size %d %d bytes: %d reserve: %d\n", + q, id, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count); + + assert(count != 0); + + add(OP_RESERVE, FL_NONE, tc->contextId(), smi, qi, count); +} + + +void +CPA::swWf(ThreadContext *tc) +{ + if (!enabled()) + return; + + char q[50]; + Arguments args(tc); + uint64_t id = args[0]; + CopyStringOut(tc, q, args[1], 50); + System *sys = tc->getSystemPtr(); + int32_t count = args[3]; + + int sysi = getSys(sys); + StackId sid = StackId(sysi, getFrame(tc)); + if (!smStack[sid].size()) + return; + int smi = smStack[sid].back(); + int qi = getQ(sysi, q, id); + add(OP_WAIT_FULL, FL_NONE, tc->contextId(), smi, qi, count); + + if (!!args[2]) { + char sm[50]; + CopyStringOut(tc, sm, args[2], 50); + doSwSmEnd(tc->getSystemPtr(), tc->contextId(), sm, getFrame(tc)); + } +} + +void +CPA::swWe(ThreadContext *tc) +{ + if (!enabled()) + return; + + char q[50]; + Arguments args(tc); + uint64_t id = args[0]; + CopyStringOut(tc, q, args[1], 50); + System *sys = tc->getSystemPtr(); + int32_t count = args[3]; + + int sysi = getSys(sys); + StackId sid = StackId(sysi, getFrame(tc)); + if (!smStack[sid].size()) + return; + int smi = smStack[sid].back(); + int qi = getQ(sysi, q, id); + add(OP_WAIT_EMPTY, FL_NONE, tc->contextId(), smi, qi, count); + + if (!!args[2]) { + char sm[50]; + CopyStringOut(tc, sm, args[2], 50); + doSwSmEnd(tc->getSystemPtr(), tc->contextId(), sm, getFrame(tc)); + } +} + +void +CPA::swSq(ThreadContext *tc) +{ + if (!enabled()) + return; + + char q[50]; + Arguments args(tc); + uint64_t id = args[0]; + CopyStringOut(tc, q, args[1], 50); + System *sys = tc->getSystemPtr(); + StringWrap name(sys->name()); + int32_t size = args[2]; + int flags = args[3]; + + int sysi = getSys(sys); + StackId sid = StackId(sysi, getFrame(tc)); + if (!smStack[sid].size()) + return; + int smi = smStack[sid].back(); + int qi = getQ(sysi, q, id); + DPRINTF(AnnotateQ, "swSq: %s [%#x] cur size: %d bytes: %d, new size: %d\n", + q, id, qSize[qi-1], qBytes[qi-1], size); + + if (FL_RESET & flags) { + DPRINTF(AnnotateQ, "Resetting Queue %s\n", q); + add(OP_SIZE_QUEUE, FL_NONE, tc->contextId(), smi, qi, 0); + qData[qi-1].clear(); + qSize[qi-1] = 0; + qBytes[qi-1] = 0; + } + + if (qBytes[qi-1] < size) + doQ(sys, FL_NONE, tc->contextId(), smi, q, qi, size - qBytes[qi-1]); + else if (qBytes[qi-1] > size) { + DPRINTF(AnnotateQ, "removing for resize of queue %s\n", q); + add(OP_SIZE_QUEUE, FL_NONE, tc->contextId(), smi, qi, size); + if (size <= 0) { + qData[qi-1].clear(); + qSize[qi-1] = 0; + qBytes[qi-1] = 0; + return; + } + int need = qBytes[qi-1] - size; + qBytes[qi-1] = size; + while (need > 0) { + int32_t tail_bytes = qData[qi-1].back()->data; + if (qSize[qi-1] <= 0 || qBytes[qi-1] < 0) { + dump(true); + dumpKey(); + fatal("Queue %s had inconsistancy when doing size queue!\n", q); + } + if (tail_bytes > need) { + qData[qi-1].back()->data -= need; + need = 0; + } else if (tail_bytes == need) { + qData[qi-1].pop_back(); + qSize[qi-1]--; + need = 0; + } else { + qData[qi-1].pop_back(); + qSize[qi-1]--; + need -= tail_bytes; + } + } + } +} + +void +CPA::swAq(ThreadContext *tc) +{ + if (!enabled()) + return; + + char q[50]; + Arguments args(tc); + uint64_t id = args[0]; + CopyStringOut(tc, q, args[1], 50); + System *sys = tc->getSystemPtr(); + StringWrap name(sys->name()); + int32_t size = args[2]; + + int sysi = getSys(sys); + int qi = getQ(sysi, q, id); + if (qBytes[qi-1] != size) { + DPRINTF(AnnotateQ, "Queue %s [%#x] has inconsintant size\n", q, id); + //dump(true); + //dumpKey(); + std::list::iterator ai = qData[qi-1].begin(); + int x = 0; + while (ai != qData[qi-1].end()) { + DPRINTF(AnnotateQ, "--Element %d size %d\n", x, (*ai)->data); + ai++; + x++; + } + + warn("%d: Queue Assert: SW said there should be %d byte(s) in %s," + "however there are %d byte(s)\n", + curTick, size, q, qBytes[qi-1]); + DPRINTF(AnnotateQ, "%d: Queue Assert: SW said there should be %d" + " byte(s) in %s, however there are %d byte(s)\n", + curTick, size, q, qBytes[qi-1]); + } +} + +void +CPA::swLink(ThreadContext *tc) +{ + if (!enabled()) + return; + + char lsm[50]; + Arguments args(tc); + CopyStringOut(tc, lsm, args[0], 50); + System *sys = tc->getSystemPtr(); + StringWrap name(sys->name()); + + int sysi = getSys(sys); + StackId sid = StackId(sysi, getFrame(tc)); + if (!smStack[sid].size()) + return; + int smi = smStack[sid].back(); + int lsmi = getSm(sysi, lsm, args[1]); + + DPRINTF(Annotate, "Linking from %d to state machine %s(%d) [%#x]\n", + smi, lsm, lsmi, args[1]); + + if (lnMap[lsmi]) + DPRINTF(Annotate, "LnMap already contains entry for %d of %d\n", + lsmi, lnMap[lsmi]); + assert(lnMap[lsmi] == 0); + lnMap[lsmi] = smi; + + add(OP_LINK, FL_NONE, tc->contextId(), smi, lsmi); + + if (!!args[2]) { + char sm[50]; + CopyStringOut(tc, sm, args[2], 50); + doSwSmEnd(tc->getSystemPtr(), tc->contextId(), sm, getFrame(tc)); + } +} + +void +CPA::swIdentify(ThreadContext *tc) +{ + if (!enabled()) + return; + + Arguments args(tc); + int sysi = getSys(tc->getSystemPtr()); + StackId sid = StackId(sysi, getFrame(tc)); + if (!smStack[sid].size()) + return; + int smi = smStack[sid].back(); + + DPRINTFS(Annotate, tc->getSystemPtr(), "swIdentify: id %#X\n", args[0]); + + add(OP_IDENT, FL_NONE, tc->contextId(), smi, 0, args[0]); +} + +uint64_t +CPA::swGetId(ThreadContext *tc) +{ + if (!enabled()) + return 0; + + uint64_t id = ++conId; + int sysi = getSys(tc->getSystemPtr()); + StackId sid = StackId(sysi, getFrame(tc)); + if (!smStack[sid].size()) + panic("swGetId called without a state machine stack!"); + int smi = smStack[sid].back(); + + DPRINTFS(Annotate, tc->getSystemPtr(), "swGetId: id %#X\n", id); + + add(OP_IDENT, FL_NONE, tc->contextId(), smi, 0, id); + return id; +} + + +void +CPA::swSyscallLink(ThreadContext *tc) +{ + if (!enabled()) + return; + + char lsm[50]; + Arguments args(tc); + CopyStringOut(tc, lsm, args[0], 50); + System *sys = tc->getSystemPtr(); + StringWrap name(sys->name()); + int sysi = getSys(sys); + + Id id = Id(lsm, getFrame(tc)); + StackId sid = StackId(sysi, getFrame(tc)); + + if (!smStack[sid].size()) + return; + + int smi = smStack[sid].back(); + + DPRINTF(Annotate, "Linking from %d to state machine %s(UNKNOWN)\n", + smi, lsm); + + if (scLinks[sysi-1][id]) + DPRINTF(Annotate, + "scLinks already contains entry for system %d %s[%x] of %d\n", + sysi, lsm, getFrame(tc), scLinks[sysi-1][id]); + assert(scLinks[sysi-1][id] == 0); + scLinks[sysi-1][id] = add(OP_LINK, FL_NONE, tc->contextId(), smi, 0xFFFF); + scLinks[sysi-1][id]->dump = false; + + if (!!args[1]) { + char sm[50]; + CopyStringOut(tc, sm, args[1], 50); + doSwSmEnd(tc->getSystemPtr(), tc->contextId(), sm, getFrame(tc)); + } +} + +CPA::AnnDataPtr +CPA::add(int t, int f, int c, int sm, int stq, int32_t d) +{ + AnnDataPtr an = new AnnotateData; + an->time = curTick; + an->data = d; + an->orig_data = d; + an->op = t; + an->flag = f; + an->sm = sm; + an->stq = stq; + an->cpu = c; + an->dump = true; + + data.push_back(an); + + DPRINTF(AnnotateVerbose, "Annotate: op: %d flags: 0x%x sm: %d state: %d time: %d, data: %d\n", + an->op, an->flag, an->sm, an->stq, an->time, an->data); + + // Don't dump Links because we might be setting no-dump on it + if (an->op != OP_LINK) + dump(false); + + return an; +} + +void +CPA::dumpKey() +{ + std::streampos curpos = osbin->tellp(); + ah.key_off = curpos; + + // Output the various state machines and their corresponding states + *osbin << "# Automatically generated state machine descriptor file" << endl; + + *osbin << "sms = {}" << endl << endl; + vector state_machines; + state_machines.resize(numSmt+1); + + // State machines, id -> states + SCache::iterator i = smtCache.begin(); + while (i != smtCache.end()) { + state_machines[i->second] = i->first; + i++; + } + + for (int x = 1; x < state_machines.size(); x++) { + vector states; + states.resize(numSt[x-1]+1); + assert(x-1 < stCache.size()); + SCache::iterator i = stCache[x-1].begin(); + while (i != stCache[x-1].end()) { + states[i->second] = i->first; + i++; + } + *osbin << "sms[\"" << state_machines[x] << "\"] = [\"NULL\""; + for (int y = 1; y < states.size(); y++) + *osbin << ", \"" << states[y] << "\""; + *osbin << "]" << endl; + } + + *osbin << endl << endl << endl; + + // state machine number -> system, name, id + *osbin << "smNum = [\"NULL\""; + for (int x = 0; x < smMap.size(); x++) + *osbin << ", (" << smMap[x].first << ", \"" << smMap[x].second.first << + "\", " << smMap[x].second.second << ")"; + *osbin << "]" << endl; + + *osbin << endl << endl << endl; + + // Output the systems + vector systems; + systems.resize(numSys+1); + NameCache::iterator i2 = nameCache.begin(); + while (i2 != nameCache.end()) { + systems[i2->second.second] = i2->second.first; + i2++; + } + + *osbin << "sysNum = [\"NULL\""; + for (int x = 1; x < systems.size(); x++) { + *osbin << ", \"" << systems[x] << "\""; + } + *osbin << "]" << endl; + + // queue number -> system, qname, qid + *osbin << "queues = [\"NULL\""; + for (int x = 0; x < qMap.size(); x++) + *osbin << ", (" << qMap[x].first << ", \"" << qMap[x].second.first << + "\", " << qMap[x].second.second << ")"; + *osbin << "]" << endl; + + *osbin << "smComb = [s for s in [(i,r) for i in xrange(1,len(sysNum)) " + << "for r in xrange (1,len(smNum))]]" << endl; + ah.key_len = osbin->tellp() - curpos; + + // output index + curpos = osbin->tellp(); + ah.idx_off = curpos; + + for (int x = 0; x < annotateIdx.size(); x++) + osbin->write((char*)&annotateIdx[x], sizeof(uint64_t)); + ah.idx_len = osbin->tellp() - curpos; + + osbin->seekp(0); + osbin->write((char*)&ah, sizeof(AnnotateHeader)); + osbin->flush(); + +} + +void +CPA::dump(bool all) +{ + + list::iterator i; + + i = data.begin(); + + if (i == data.end()) + return; + + // Dump the data every + if (!all && data.size() < 10000) + return; + + DPRINTF(Annotate, "Writing %d\n", data.size()); + while (i != data.end()) { + AnnDataPtr an = *i; + + // If we can't dump this record, hold here + if (!an->dump && !all) + break; + + ah.num_recs++; + if (ah.num_recs % 100000 == 0) + annotateIdx.push_back(osbin->tellp()); + + + osbin->write((char*)&(an->time), sizeof(an->time)); + osbin->write((char*)&(an->orig_data), sizeof(an->orig_data)); + osbin->write((char*)&(an->sm), sizeof(an->sm)); + osbin->write((char*)&(an->stq), sizeof(an->stq)); + osbin->write((char*)&(an->op), sizeof(an->op)); + osbin->write((char*)&(an->flag), sizeof(an->flag)); + osbin->write((char*)&(an->cpu), sizeof(an->cpu)); + i++; + } + if (data.begin() != i) + data.erase(data.begin(), i); + + if (all) + osbin->flush(); +} + +void +CPA::doQ(System *sys, int flags, int cpuid, int sm, + string q, int qi, int count) +{ + qSize[qi-1]++; + qBytes[qi-1] += count; + if (qSize[qi-1] > 2501 || qBytes[qi-1] > 2000000000) + warn("Queue %s is %d elements/%d bytes, " + "maybe things aren't being removed?\n", + q, qSize[qi-1], qBytes[qi-1]); + if (flags & FL_QOPP) + qData[qi-1].push_front(add(OP_QUEUE, flags, cpuid, sm, qi, count)); + else + qData[qi-1].push_back(add(OP_QUEUE, flags, cpuid, sm, qi, count)); + DPRINTFS(AnnotateQ, sys, "Queing in queue %s size now %d/%d\n", + q, qSize[qi-1], qBytes[qi-1]); + assert(qSize[qi-1] >= 0); + assert(qBytes[qi-1] >= 0); +} + + +void +CPA::doDq(System *sys, int flags, int cpuid, int sm, + string q, int qi, int count) +{ + + StringWrap name(sys->name()); + if (count == -1) { + add(OP_DEQUEUE, flags, cpuid, sm, qi, count); + qData[qi-1].clear(); + qSize[qi-1] = 0; + qBytes[qi-1] = 0; + DPRINTF(AnnotateQ, "Dequeing all data in queue %s size now %d/%d\n", + q, qSize[qi-1], qBytes[qi-1]); + return; + } + + assert(count > 0); + if (qSize[qi-1] <= 0 || qBytes[qi-1] <= 0 || !qData[qi-1].size()) { + dump(true); + dumpKey(); + fatal("Queue %s dequing with no data available in queue!\n", + q); + } + assert(qSize[qi-1] >= 0); + assert(qBytes[qi-1] >= 0); + assert(qData[qi-1].size()); + + int32_t need = count; + qBytes[qi-1] -= count; + if (qBytes[qi-1] < 0) { + dump(true); + dumpKey(); + fatal("Queue %s dequing with no bytes available in queue!\n", + q); + } + + while (need > 0) { + int32_t head_bytes = qData[qi-1].front()->data; + if (qSize[qi-1] <= 0 || qBytes[qi-1] < 0) { + dump(true); + dumpKey(); + fatal("Queue %s dequing with nothing in queue!\n", + q); + } + + if (head_bytes > need) { + qData[qi-1].front()->data -= need; + need = 0; + } else if (head_bytes == need) { + qData[qi-1].pop_front(); + qSize[qi-1]--; + need = 0; + } else { + qData[qi-1].pop_front(); + qSize[qi-1]--; + need -= head_bytes; + } + } + + add(OP_DEQUEUE, flags, cpuid, sm, qi, count); + DPRINTF(AnnotateQ, "Dequeing in queue %s size now %d/%d\n", + q, qSize[qi-1], qBytes[qi-1]); +} + + + +void +CPA::serialize(std::ostream &os) +{ + + SERIALIZE_SCALAR(numSm); + SERIALIZE_SCALAR(numSmt); + arrayParamOut(os, "numSt", numSt); + arrayParamOut(os, "numQ", numQ); + SERIALIZE_SCALAR(numSys); + SERIALIZE_SCALAR(numQs); + SERIALIZE_SCALAR(conId); + arrayParamOut(os, "qSize", qSize); + arrayParamOut(os, "qSize", qSize); + arrayParamOut(os, "qBytes", qBytes); + + std::list::iterator ai; + + SCache::iterator i; + int x = 0, y = 0; + + // smtCache (SCache) + x = 0; + y = 0; + i = smtCache.begin(); + while (i != smtCache.end()) { + paramOut(os, csprintf("smtCache%d.str", x), i->first); + paramOut(os, csprintf("smtCache%d.int", x), i->second); + x++; i++; + } + + // stCache (StCache) + for (x = 0; x < stCache.size(); x++) { + i = stCache[x].begin(); + y = 0; + while (i != stCache[x].end()) { + paramOut(os, csprintf("stCache%d_%d.str", x, y), i->first); + paramOut(os, csprintf("stCache%d_%d.int", x, y), i->second); + y++; i++; + } + } + + // qCache (IdCache) + IdHCache::iterator idi; + for (x = 0; x < qCache.size(); x++) { + idi = qCache[x].begin(); + y = 0; + while (idi != qCache[x].end()) { + paramOut(os, csprintf("qCache%d_%d.str", x, y), idi->first.first); + paramOut(os, csprintf("qCache%d_%d.id", x, y), idi->first.second); + paramOut(os, csprintf("qCache%d_%d.int", x, y), idi->second); + y++; idi++; + } + } + + // smCache (IdCache) + for (x = 0; x < smCache.size(); x++) { + idi = smCache[x].begin(); + y = 0; + paramOut(os, csprintf("smCache%d", x), smCache[x].size()); + while (idi != smCache[x].end()) { + paramOut(os, csprintf("smCache%d_%d.str", x, y), idi->first.first); + paramOut(os, csprintf("smCache%d_%d.id", x, y), idi->first.second); + paramOut(os, csprintf("smCache%d_%d.int", x, y), idi->second); + y++; idi++; + } + } + + // scLinks (ScCache) -- data not serialize + + + // namecache (NameCache) + NameCache::iterator ni; + + ni = nameCache.begin(); + x = 0; + while (ni != nameCache.end()) { + paramOut(os, csprintf("nameCache%d.name", x), ni->first->name()); + paramOut(os, csprintf("nameCache%d.str", x), ni->second.first); + paramOut(os, csprintf("nameCache%d.int", x), ni->second.second); + x++; ni++; + } + + // smStack (SmStack) + SmStack::iterator si; + si = smStack.begin(); + x = 0; + paramOut(os, "smStackIdCount", smStack.size()); + while (si != smStack.end()) { + paramOut(os, csprintf("smStackId%d.sys", x), si->first.first); + paramOut(os, csprintf("smStackId%d.frame", x), si->first.second); + paramOut(os, csprintf("smStackId%d.count", x), si->second.size()); + for (y = 0; y < si->second.size(); y++) + paramOut(os, csprintf("smStackId%d_%d", x, y), si->second[y]); + x++; si++; + } + + // lnMap (LinkMap) + x = 0; + LinkMap::iterator li; + li = lnMap.begin(); + paramOut(os, "lnMapSize", lnMap.size()); + while (li != lnMap.end()) { + paramOut(os, csprintf("lnMap%d.smi", x), li->first); + paramOut(os, csprintf("lnMap%d.lsmi", x), li->second); + x++; li++; + } + + // swExpl (vector) + SwExpl::iterator swexpli; + swexpli = swExpl.begin(); + x = 0; + paramOut(os, "swExplCount", swExpl.size()); + while (swexpli != swExpl.end()) { + paramOut(os, csprintf("swExpl%d.sys", x), swexpli->first.first); + paramOut(os, csprintf("swExpl%d.frame", x), swexpli->first.second); + paramOut(os, csprintf("swExpl%d.swexpl", x), swexpli->second); + x++; swexpli++; + } + + // lastState (IMap) + x = 0; + IMap::iterator ii; + ii = lastState.begin(); + paramOut(os, "lastStateSize", lastState.size()); + while (ii != lastState.end()) { + paramOut(os, csprintf("lastState%d.smi", x), ii->first); + paramOut(os, csprintf("lastState%d.sti", x), ii->second); + x++; ii++; + } + + // smMap (IdMap) + for (x = 0; x < smMap.size(); x++) { + paramOut(os, csprintf("smMap%d.sys", x), smMap[x].first); + paramOut(os, csprintf("smMap%d.smname", x), smMap[x].second.first); + paramOut(os, csprintf("smMap%d.id", x), smMap[x].second.second); + } + + // qMap (IdMap) + for (x = 0; x < qMap.size(); x++) { + paramOut(os, csprintf("qMap%d.sys", x), qMap[x].first); + paramOut(os, csprintf("qMap%d.qname", x), qMap[x].second.first); + paramOut(os, csprintf("qMap%d.id", x), qMap[x].second.second); + } + + // qData (vector) + for(x = 0; x < qData.size(); x++) { + if (!qData[x].size()) + continue; + y = 0; + ai = qData[x].begin(); + while (ai != qData[x].end()) { + nameOut(os, csprintf("%s.Q%d_%d", name(), x, y)); + (*ai)->serialize(os); + ai++; + y++; + } + } +} + +void +CPA::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_SCALAR(numSm); + UNSERIALIZE_SCALAR(numSmt); + arrayParamIn(cp, section, "numSt", numSt); + arrayParamIn(cp, section, "numQ", numQ); + UNSERIALIZE_SCALAR(numSys); + UNSERIALIZE_SCALAR(numQs); + UNSERIALIZE_SCALAR(conId); + arrayParamIn(cp, section, "qSize", qSize); + arrayParamIn(cp, section, "qBytes", qBytes); + + + // smtCache (SCache + string str; + int smi; + for (int x = 0; x < numSmt; x++) { + paramIn(cp, section, csprintf("smtCache%d.str", x), str); + paramIn(cp, section, csprintf("smtCache%d.int", x), smi); + smtCache[str] = smi; + } + + // stCache (StCache) + stCache.resize(numSmt); + for (int x = 0; x < numSmt; x++) { + for (int y = 0; y < numSt[x]; y++) { + paramIn(cp, section, csprintf("stCache%d_%d.str", x,y), str); + paramIn(cp, section, csprintf("stCache%d_%d.int", x,y), smi); + stCache[x][str] = smi; + } + } + + // qCache (IdCache) + uint64_t id; + qCache.resize(numSys); + for (int x = 0; x < numSys; x++) { + for (int y = 0; y < numQ[x]; y++) { + paramIn(cp, section, csprintf("qCache%d_%d.str", x,y), str); + paramIn(cp, section, csprintf("qCache%d_%d.id", x,y), id); + paramIn(cp, section, csprintf("qCache%d_%d.int", x,y), smi); + qCache[x][Id(str,id)] = smi; + } + } + + // smCache (IdCache) + smCache.resize(numSys); + for (int x = 0; x < numSys; x++) { + int size; + paramIn(cp, section, csprintf("smCache%d", x), size); + for (int y = 0; y < size; y++) { + paramIn(cp, section, csprintf("smCache%d_%d.str", x,y), str); + paramIn(cp, section, csprintf("smCache%d_%d.id", x,y), id); + paramIn(cp, section, csprintf("smCache%d_%d.int", x,y), smi); + smCache[x][Id(str,id)] = smi; + } + } + + // scLinks (ScCache) -- data not serialized, just creating one per sys + for (int x = 0; x < numSys; x++) + scLinks.push_back(ScHCache()); + + // nameCache (NameCache) + for (int x = 0; x < numSys; x++) { + System *sys; + SimObject *sptr; + string str; + int sysi; + + objParamIn(cp, section, csprintf("nameCache%d.name", x), sptr); + sys = dynamic_cast(sptr); + + paramIn(cp, section, csprintf("nameCache%d.str", x), str); + paramIn(cp, section, csprintf("nameCache%d.int", x), sysi); + nameCache[sys] = std::make_pair(str, sysi); + } + + //smStack (SmStack) + int smStack_size; + paramIn(cp, section, "smStackIdCount", smStack_size); + for (int x = 0; x < smStack_size; x++) { + int sysi; + uint64_t frame; + int count; + paramIn(cp, section, csprintf("smStackId%d.sys", x), sysi); + paramIn(cp, section, csprintf("smStackId%d.frame", x), frame); + paramIn(cp, section, csprintf("smStackId%d.count", x), count); + StackId sid = StackId(sysi, frame); + for (int y = 0; y < count; y++) { + paramIn(cp, section, csprintf("smStackId%d_%d", x, y), smi); + smStack[sid].push_back(smi); + } + } + + // lnMap (LinkMap) + int lsmi; + int lnMap_size; + paramIn(cp, section, "lnMapSize", lnMap_size); + for (int x = 0; x < lnMap_size; x++) { + paramIn(cp, section, csprintf("lnMap%d.smi", x), smi); + paramIn(cp, section, csprintf("lnMap%d.lsmi", x), lsmi); + lnMap[smi] = lsmi; + } + + // swExpl (vector) + int swExpl_size; + paramIn(cp, section, "swExplCount", swExpl_size); + for (int x = 0; x < swExpl_size; x++) { + int sysi; + uint64_t frame; + bool b; + paramIn(cp, section, csprintf("swExpl%d.sys", x), sysi); + paramIn(cp, section, csprintf("swExpl%d.frame", x), frame); + paramIn(cp, section, csprintf("swExpl%d.swexpl", x), b); + StackId sid = StackId(sysi, frame); + swExpl[sid] = b; + } + + // lastState (IMap) + int sti; + int lastState_size; + paramIn(cp, section, "lastStateSize", lastState_size); + for (int x = 0; x < lastState_size; x++) { + paramIn(cp, section, csprintf("lastState%d.smi", x), smi); + paramIn(cp, section, csprintf("lastState%d.sti", x), sti); + lastState[smi] = sti; + } + + + //smMap (IdMap) + smMap.resize(numSm); + for (int x = 0; x < smMap.size(); x++) { + paramIn(cp, section, csprintf("smMap%d.sys", x), smMap[x].first); + paramIn(cp, section, csprintf("smMap%d.smname", x), smMap[x].second.first); + paramIn(cp, section, csprintf("smMap%d.id", x), smMap[x].second.second); + } + + //qMap (IdMap) + qMap.resize(numQs); + for (int x = 0; x < qMap.size(); x++) { + paramIn(cp, section, csprintf("qMap%d.sys", x), qMap[x].first); + paramIn(cp, section, csprintf("qMap%d.qname", x), qMap[x].second.first); + paramIn(cp, section, csprintf("qMap%d.id", x), qMap[x].second.second); + } + + + // qData (vector) + qData.resize(qSize.size()); + for (int x = 0; x < qSize.size(); x++) { + if (!qSize[x]) + continue; + for (int y = 0; y < qSize[x]; y++) { + AnnDataPtr a = new AnnotateData; + a->unserialize(cp, csprintf("%s.Q%d_%d", section, x, y)); + data.push_back(a); + qData[x].push_back(a); + } + } +} + +void +CPA::AnnotateData::serialize(std::ostream &os) +{ + SERIALIZE_SCALAR(time); + SERIALIZE_SCALAR(data); + SERIALIZE_SCALAR(sm); + SERIALIZE_SCALAR(stq); + SERIALIZE_SCALAR(op); + SERIALIZE_SCALAR(flag); + SERIALIZE_SCALAR(cpu); +} + +void +CPA::AnnotateData::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_SCALAR(time); + UNSERIALIZE_SCALAR(data); + orig_data = data; + UNSERIALIZE_SCALAR(sm); + UNSERIALIZE_SCALAR(stq); + UNSERIALIZE_SCALAR(op); + UNSERIALIZE_SCALAR(flag); + UNSERIALIZE_SCALAR(cpu); + dump = true; +} + +CPA* +CPAParams::create() +{ + return new CPA(this); +} + diff --git a/src/base/cp_annotate.hh b/src/base/cp_annotate.hh new file mode 100644 index 000000000..9ec39b6cb --- /dev/null +++ b/src/base/cp_annotate.hh @@ -0,0 +1,522 @@ +/* + * Copyright (c) 2006-2009 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ali Saidi + */ + +#ifndef __BASE__CP_ANNOTATE_HH__ +#define __BASE__CP_ANNOTATE_HH__ + +#include "base/loader/symtab.hh" +#include "config/cp_annotate.hh" +#include "sim/host.hh" +#include "sim/serialize.hh" +#include "sim/startup.hh" +#include "sim/system.hh" + +#include +#include +#include +#include +#include "base/hashmap.hh" +#include "base/trace.hh" +#if CP_ANNOTATE +#include "params/CPA.hh" +#endif + +class System; +class ThreadContext; + + +#if !CP_ANNOTATE +class CPA : SimObject +{ + public: + enum flags { + FL_NONE = 0x00, + FL_HW = 0x01, + FL_BAD = 0x02, + FL_QOPP = 0x04, + FL_WAIT = 0x08, + FL_LINK = 0x10, + FL_RESET = 0x20 + }; + + static CPA *cpa() { return NULL; } + static bool available() { return false; } + bool enabled() { return false; } + void swSmBegin(ThreadContext *tc) { return; } + void swSmEnd(ThreadContext *tc) { return; } + void swExplictBegin(ThreadContext *tc) { return; } + void swAutoBegin(ThreadContext *tc, Addr next_pc) { return; } + void swEnd(ThreadContext *tc) { return; } + void swQ(ThreadContext *tc) { return; } + void swDq(ThreadContext *tc) { return; } + void swPq(ThreadContext *tc) { return; } + void swRq(ThreadContext *tc) { return; } + void swWf(ThreadContext *tc) { return; } + void swWe(ThreadContext *tc) { return; } + void swSq(ThreadContext *tc) { return; } + void swAq(ThreadContext *tc) { return; } + void swLink(ThreadContext *tc) { return; } + void swIdentify(ThreadContext *tc) { return; } + uint64_t swGetId(ThreadContext *tc) { return 0; } + void swSyscallLink(ThreadContext *tc) { return; } + void hwBegin(flags f, System *sys, uint64_t frame, std::string sm, + std::string st) { return; } + void hwQ(flags f, System *sys, uint64_t frame, std::string sm, + std::string q, uint64_t qid, System *q_sys = NULL, + int32_t count = 1) { return; } + void hwDq(flags f, System *sys, uint64_t frame, std::string sm, + std::string q, uint64_t qid, System *q_sys = NULL, + int32_t count = 1) { return; } + void hwPq(flags f, System *sys, uint64_t frame, std::string sm, + std::string q, uint64_t qid, System *q_sys = NULL, + int32_t count = 1) { return; } + void hwRq(flags f, System *sys, uint64_t frame, std::string sm, + std::string q, uint64_t qid, System *q_sys = NULL, + int32_t count = 1) { return; } + void hwWf(flags f, System *sys, uint64_t frame, std::string sm, + std::string q, uint64_t qid, System *q_sys = NULL, + int32_t count = 1) { return; } + void hwWe(flags f, System *sys, uint64_t frame, std::string sm, + std::string q, uint64_t qid, System *q_sys = NULL, + int32_t count = 1) { return; } +}; +#else +class CPA : SimObject +{ + public: + typedef CPAParams Params; + + /** The known operations that are written to the annotation output file. */ + enum ops { + OP_BEGIN = 0x01, + OP_WAIT_EMPTY = 0x02, + OP_WAIT_FULL = 0x03, + OP_QUEUE = 0x04, + OP_DEQUEUE = 0x05, + OP_SIZE_QUEUE = 0x08, + OP_PEEK = 0x09, + OP_LINK = 0x0A, + OP_IDENT = 0x0B, + OP_RESERVE = 0x0C + }; + + /** Flags for the various options.*/ + enum flags { + /* no flags */ + FL_NONE = 0x00, + /* operation was done on hardware */ + FL_HW = 0x01, + /* operation should cause a warning when encountered */ + FL_BAD = 0x02, + /* Queue like a stack, not a queue */ + FL_QOPP = 0x04, + /* Mark HW state as waiting for some non-resource constraint + * (e.g. wait because SM only starts after 10 items are queued) */ + FL_WAIT = 0x08, + /* operation is linking to another state machine */ + FL_LINK = 0x10, + /* queue should be completely cleared/reset before executing this + * operation */ + FL_RESET = 0x20 + }; + + + + protected: + const Params * + params() const + { + return dynamic_cast(_params); + } + + /* struct that is written to the annotation output file */ + struct AnnotateData : public RefCounted { + + Tick time; + uint32_t data; + uint32_t orig_data; + uint16_t sm; + uint16_t stq; + uint8_t op; + uint8_t flag; + uint8_t cpu; + bool dump; + + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); + + }; + + typedef RefCountingPtr AnnDataPtr; + + /* header for the annotation file */ + struct AnnotateHeader { + uint64_t version; + uint64_t num_recs; + uint64_t key_off; + uint64_t idx_off; + uint32_t key_len; + uint32_t idx_len; + }; + + AnnotateHeader ah; + + std::vector annotateIdx; + + // number of state machines encountered in the simulation + int numSm; + // number of states encountered in the simulation + int numSmt; + // number of states/queues for a given state machine/system respectively + std::vector numSt, numQ; + // number of systems in the simulation + int numSys; + // number of queues in the state machine + int numQs; + // maximum connection id assigned so far + uint64_t conId; + + // Convert state strings into state ids + typedef m5::hash_map SCache; + typedef std::vector StCache; + + // Convert sm and queue name,id into queue id + typedef std::pair Id; + typedef m5::hash_map IdHCache; + typedef std::vector IdCache; + + // Hold mapping of sm and queues to output python + typedef std::vector > IdMap; + + // System pointer to name,id + typedef std::map > NameCache; + + // array of systems each of which is a stack of running sm + typedef std::pair StackId; + typedef std::map > SmStack; + + // map of each context and if it's currently in explict state mode + // states are not automatically updated until it leaves + typedef std::map SwExpl; + + typedef std::map IMap; + // List of annotate records have not been written/completed yet + typedef std::list AnnotateList; + + // Maintain link state information + typedef std::map LinkMap; + + // SC Links + typedef m5::hash_map ScHCache; + typedef std::vector ScCache; + + + AnnotateList data; + + // vector indexed by queueid to find current number of elements and bytes + std::vector qSize; + std::vector qBytes; + + + // Turn state machine string into state machine id (small int) + // Used for outputting key to convert id back into string + SCache smtCache; + // Turn state machine id, state name into state id (small int) + StCache stCache; + // turn system, queue, and queue identify into qid (small int) + // turn system, state, and context into state machine id (small int) + IdCache qCache, smCache; + //Link state machines accross system calls + ScCache scLinks; + // System pointer to name,id + NameCache nameCache; + // Stack of state machines currently nested (should unwind correctly) + SmStack smStack; + // Map of currently outstanding links + LinkMap lnMap; + // If the state machine is currently exculding automatic changes + SwExpl swExpl; + // Last state that a given state machine was in + IMap lastState; + // Hold mapping of sm and queues to output python + IdMap smMap, qMap; + // Items still in queue, used for sanity checking + std::vector qData; + + void doDq(System *sys, int flags, int cpu, int sm, std::string q, int qi, + int count); + void doQ(System *sys, int flags, int cpu, int sm, std::string q, int qi, + int count); + + void doSwSmEnd(System *sys, int cpuid, std::string sm, uint64_t frame); + + // Turn a system id, state machine string, state machine id into a small int + // for annotation output + int + getSm(int sysi, std::string si, uint64_t id) + { + int smi; + Id smid = Id(si, id); + + smi = smCache[sysi-1][smid]; + if (smi == 0) { + smCache[sysi-1][smid] = smi = ++numSm; + assert(smi < 65535); + smMap.push_back(std::make_pair(sysi, smid)); + } + return smi; + } + + // Turn a state machine string, state string into a small int + // for annotation output + int + getSt(std::string sm, std::string s) + { + int sti, smi; + + smi = smtCache[sm]; + if (smi == 0) + smi = smtCache[sm] = ++numSmt; + + while (stCache.size() < smi) { + //stCache.resize(sm); + stCache.push_back(SCache()); + numSt.push_back(0); + } + //assert(stCache.size() == sm); + //assert(numSt.size() == sm); + sti = stCache[smi-1][s]; + if (sti == 0) + stCache[smi-1][s] = sti = ++numSt[smi-1]; + return sti; + } + + // Turn state machine pointer into a smal int for annotation output + int + getSys(System *s) + { + NameCache::iterator i = nameCache.find(s); + if (i == nameCache.end()) { + nameCache[s] = std::make_pair(s->name(), ++numSys); + i = nameCache.find(s); + // might need to put smstackid into map here, but perhaps not + //smStack.push_back(std::vector()); + //swExpl.push_back(false); + numQ.push_back(0); + qCache.push_back(IdHCache()); + smCache.push_back(IdHCache()); + scLinks.push_back(ScHCache()); + } + return i->second.second; + } + + // Turn queue name, and queue context into small int for + // annotation output + int + getQ(int sys, std::string q, uint64_t id) + { + int qi; + Id qid = Id(q, id); + + qi = qCache[sys-1][qid]; + if (qi == 0) { + qi = qCache[sys-1][qid] = ++numQs; + assert(qi < 65535); + qSize.push_back(0); + qBytes.push_back(0); + qData.push_back(AnnotateList()); + numQ[sys-1]++; + qMap.push_back(std::make_pair(sys, qid)); + } + return qi; + } + + void swBegin(System *sys, int cpuid, std::string st, uint64_t frame, + bool expl = false, int flags = FL_NONE); + + AnnDataPtr add(int t, int f, int c, int sm, int stq, int32_t data=0); + + std::ostream *osbin; + + bool _enabled; + + /** Only allow one CPA object in a system. It doesn't make sense to have + * more that one per simulation because if a part of the system was + * important it would have annotations and queues, and with more than one + * object none of the sanity checking for queues will work. */ + static bool exists; + static CPA *_cpa; + + + std::map userApp; + + public: + static CPA *cpa() { return _cpa; } + void swSmBegin(ThreadContext *tc); + void swSmEnd(ThreadContext *tc); + void swExplictBegin(ThreadContext *tc); + void swAutoBegin(ThreadContext *tc, Addr next_pc); + void swEnd(ThreadContext *tc); + void swQ(ThreadContext *tc); + void swDq(ThreadContext *tc); + void swPq(ThreadContext *tc); + void swRq(ThreadContext *tc); + void swWf(ThreadContext *tc); + void swWe(ThreadContext *tc); + void swSq(ThreadContext *tc); + void swAq(ThreadContext *tc); + void swLink(ThreadContext *tc); + void swIdentify(ThreadContext *tc); + uint64_t swGetId(ThreadContext *tc); + void swSyscallLink(ThreadContext *tc); + + inline void hwBegin(flags f, System *sys, uint64_t frame, std::string sm, + std::string st) + { + if (!enabled()) + return; + + int sysi = getSys(sys); + int smi = getSm(sysi, sm, frame); + add(OP_BEGIN, FL_HW | f, 0, smi, getSt(sm, st)); + if (f & FL_BAD) + warn("BAD state encountered: at cycle %d: %s\n", curTick, st); + } + + inline void hwQ(flags f, System *sys, uint64_t frame, std::string sm, + std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1) + { + if (!enabled()) + return; + + int sysi = getSys(sys); + int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid); + DPRINTFS(AnnotateQ, sys, + "hwQ: %s[%#x] cur size %d %d bytes: %d adding: %d\n", + q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count); + doQ(sys, FL_HW | f, 0, getSm(sysi, sm, frame), q, qi, count); + + } + + inline void hwDq(flags f, System *sys, uint64_t frame, std::string sm, + std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1) + { + if (!enabled()) + return; + + int sysi = getSys(sys); + int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid); + DPRINTFS(AnnotateQ, sys, + "hwDQ: %s[%#x] cur size %d %d bytes: %d removing: %d\n", + q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count); + doDq(sys, FL_HW | f, 0, getSm(sysi,sm, frame), q, qi, count); + } + + inline void hwPq(flags f, System *sys, uint64_t frame, std::string sm, + std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1) + { + if (!enabled()) + return; + + int sysi = getSys(sys); + int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid); + DPRINTFS(AnnotateQ, sys, + "hwPQ: %s[%#x] cur size %d %d bytes: %d peeking: %d\n", + q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count); + add(OP_PEEK, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count); + } + + inline void hwRq(flags f, System *sys, uint64_t frame, std::string sm, + std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1) + { + if (!enabled()) + return; + + int sysi = getSys(sys); + int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid); + DPRINTFS(AnnotateQ, sys, + "hwRQ: %s[%#x] cur size %d %d bytes: %d reserving: %d\n", + q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count); + add(OP_RESERVE, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count); + } + + inline void hwWf(flags f, System *sys, uint64_t frame, std::string sm, + std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1) + { + if (!enabled()) + return; + + int sysi = getSys(sys); + int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid); + add(OP_WAIT_FULL, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count); + } + + inline void hwWe(flags f, System *sys, uint64_t frame, std::string sm, + std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1) + { + if (!enabled()) + return; + + int sysi = getSys(sys); + int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid); + add(OP_WAIT_EMPTY, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count); + } + + public: + CPA(Params *p); + void startup(); + + // This code is ISA specific and will need to be changed + // if the annotation code is used for something other than Alpha + inline uint64_t getFrame(ThreadContext *tc) + { return (tc->readMiscRegNoEffect(TheISA::IPR_PALtemp23) & + ~ULL(0x3FFF)); } + + static bool available() { return true; } + + bool + enabled() + { + if (!this) + return false; + return _enabled; + } + + void dump(bool all); + void dumpKey(); + + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); + +}; +#endif // !CP_ANNOTATE + +#endif //__BASE__CP_ANNOTATE_HH__ + diff --git a/src/base/hashmap.hh b/src/base/hashmap.hh index f8d799780..ff2aa151f 100644 --- a/src/base/hashmap.hh +++ b/src/base/hashmap.hh @@ -81,6 +81,16 @@ namespace __hash_namespace { return(__stl_hash_string(s.c_str())); } }; + + template <> + struct hash > { + size_t operator() (std::pair r) const { + return (__stl_hash_string(r.first.c_str())) ^ r.second; + } + }; + + + } diff --git a/src/base/loader/symtab.hh b/src/base/loader/symtab.hh index 97a675140..cc1dc368f 100644 --- a/src/base/loader/symtab.hh +++ b/src/base/loader/symtab.hh @@ -34,6 +34,7 @@ #include #include +#include #include "sim/host.hh" // for Addr diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index 1db9c7495..8ef22be4e 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -65,6 +65,7 @@ from params import * # There are a few things we need that aren't in params.__all__ since # normal users don't need them from params import ParamDesc, VectorParamDesc, isNullPointer, SimObjVector +from proxy import * noDot = False try: @@ -667,7 +668,7 @@ class SimObject(object): match_obj = self._values[pname] if found_obj != None and found_obj != match_obj: raise AttributeError, \ - 'parent.any matched more than one: %s' % obj.path + 'parent.any matched more than one: %s and %s' % (found_obj.path, match_obj.path) found_obj = match_obj return found_obj, found_obj != None diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index 00d0dbe7a..3c2a27f54 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -37,7 +37,6 @@ #include "arch/kernel_stats.hh" #include "arch/vtophys.hh" -#include "base/annotate.hh" #include "base/debug.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" @@ -214,6 +213,7 @@ addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr) DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr); tc->getSystemPtr()->kernelSymtab->insert(addr,symbol); + debugSymbolTable->insert(addr,symbol); } #endif -- cgit v1.2.3 From d447ccb2c61a9225e5663ac29c999ac0a52a412f Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Thu, 26 Feb 2009 19:29:17 -0500 Subject: CPA: Add code to automatically record function symbols as CPU executes. --- src/arch/alpha/ev5.cc | 3 +++ src/cpu/o3/commit_impl.hh | 7 +++++++ src/cpu/o3/dyn_inst_impl.hh | 5 +++++ src/cpu/simple/base.cc | 5 +++++ 4 files changed, 20 insertions(+) (limited to 'src') diff --git a/src/arch/alpha/ev5.cc b/src/arch/alpha/ev5.cc index b3ef8f5d8..02497e282 100644 --- a/src/arch/alpha/ev5.cc +++ b/src/arch/alpha/ev5.cc @@ -35,6 +35,7 @@ #include "arch/alpha/osfpal.hh" #include "arch/alpha/tlb.hh" #include "arch/alpha/kgdb.h" +#include "base/cp_annotate.hh" #include "base/debug.hh" #include "base/remote_gdb.hh" #include "base/stats/events.hh" @@ -560,6 +561,8 @@ SimpleThread::hwrei() setNextPC(readMiscRegNoEffect(IPR_EXC_ADDR)); + CPA::cpa()->swAutoBegin(tc, readNextPC()); + if (!misspeculating()) { if (kernelStats) kernelStats->hwrei(); diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index e215fe49e..7cd88b49b 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -36,6 +36,7 @@ #include #include "arch/utility.hh" +#include "base/cp_annotate.hh" #include "base/loader/symtab.hh" #include "base/timebuf.hh" #include "cpu/exetrace.hh" @@ -1097,6 +1098,12 @@ DefaultCommit::commitHead(DynInstPtr &head_inst, unsigned inst_num) if (node) thread[tid]->profileNode = node; } + if (CPA::available()) { + if (head_inst->isControl()) { + ThreadContext *tc = thread[tid]->getTC(); + CPA::cpa()->swAutoBegin(tc, head_inst->readNextPC()); + } + } #endif if (head_inst->traceData) { diff --git a/src/cpu/o3/dyn_inst_impl.hh b/src/cpu/o3/dyn_inst_impl.hh index 6398a3afe..8d391ceaf 100644 --- a/src/cpu/o3/dyn_inst_impl.hh +++ b/src/cpu/o3/dyn_inst_impl.hh @@ -28,6 +28,7 @@ * Authors: Kevin Lim */ +#include "base/cp_annotate.hh" #include "cpu/o3/dyn_inst.hh" template @@ -136,6 +137,10 @@ BaseO3DynInst::hwrei() // Set the next PC based on the value of the EXC_ADDR IPR. this->setNextPC(this->cpu->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR, this->threadNumber)); + if (CPA::available()) { + ThreadContext *tc = this->cpu->tcBase(this->threadNumber); + CPA::cpa()->swAutoBegin(tc, this->readNextPC()); + } // Tell CPU to clear any state it needs to if a hwrei is taken. this->cpu->hwrei(this->threadNumber); diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index 9372ff43d..348d2392f 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -31,6 +31,7 @@ #include "arch/utility.hh" #include "arch/faults.hh" #include "base/cprintf.hh" +#include "base/cp_annotate.hh" #include "base/inifile.hh" #include "base/loader/symtab.hh" #include "base/misc.hh" @@ -450,6 +451,10 @@ BaseSimpleCPU::postExecute() comLoadEventQueue[0]->serviceEvents(numLoad); } + if (CPA::available()) { + CPA::cpa()->swAutoBegin(tc, thread->readNextPC()); + } + traceFunctions(thread->readPC()); if (traceData) { -- cgit v1.2.3 From bebbc9dc8901d82954988d019d54bf5dee2d1a90 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Thu, 26 Feb 2009 19:29:17 -0500 Subject: CPA: Add annotations to IGbE and CopyEngine device models. --- src/dev/copy_engine.cc | 17 +++++++++ src/dev/copy_engine.hh | 30 ++++++++++++++++ src/dev/i8254xGBe.cc | 92 +++++++++++++++++++++++++++++++++++++++++++++++++ src/dev/i8254xGBe.hh | 93 +++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 227 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/dev/copy_engine.cc b/src/dev/copy_engine.cc index 46d3127e7..3c759ac1d 100644 --- a/src/dev/copy_engine.cc +++ b/src/dev/copy_engine.cc @@ -34,6 +34,7 @@ #include +#include "base/cp_annotate.hh" #include "base/trace.hh" #include "dev/copy_engine.hh" #include "mem/packet.hh" @@ -427,6 +428,8 @@ CopyEngine::regStats() void CopyEngine::CopyEngineChannel::fetchDescriptor(Addr address) { + anDq(); + anBegin("FetchDescriptor"); DPRINTF(DMACopyEngine, "Reading descriptor from at memory location %#x(%#x)\n", address, ce->platform->pciToDma(address)); assert(address); @@ -455,6 +458,8 @@ CopyEngine::CopyEngineChannel::fetchDescComplete() if (inDrain()) return; writeCompletionStatus(); } else { + anBegin("Idle"); + anWait(); busy = false; nextState = Idle; inDrain(); @@ -473,6 +478,7 @@ CopyEngine::CopyEngineChannel::fetchDescComplete() void CopyEngine::CopyEngineChannel::readCopyBytes() { + anBegin("ReadCopyBytes"); DPRINTF(DMACopyEngine, "Reading %d bytes from buffer to memory location %#x(%#x)\n", curDmaDesc->len, curDmaDesc->dest, ce->platform->pciToDma(curDmaDesc->src)); @@ -493,6 +499,7 @@ CopyEngine::CopyEngineChannel::readCopyBytesComplete() void CopyEngine::CopyEngineChannel::writeCopyBytes() { + anBegin("WriteCopyBytes"); DPRINTF(DMACopyEngine, "Writing %d bytes from buffer to memory location %#x(%#x)\n", curDmaDesc->len, curDmaDesc->dest, ce->platform->pciToDma(curDmaDesc->dest)); @@ -513,6 +520,8 @@ CopyEngine::CopyEngineChannel::writeCopyBytesComplete() cr.status.compl_desc_addr(lastDescriptorAddr >> 6); completionDataReg = cr.status() | 1; + anQ("DMAUsedDescQ", channelId, 1); + anQ("AppRecvQ", curDmaDesc->user1, curDmaDesc->len); if (curDmaDesc->command & DESC_CTRL_CP_STS) { nextState = CompletionWrite; if (inDrain()) return; @@ -529,6 +538,8 @@ CopyEngine::CopyEngineChannel::continueProcessing() busy = false; if (underReset) { + anBegin("Reset"); + anWait(); underReset = false; refreshNext = false; busy = false; @@ -549,12 +560,15 @@ CopyEngine::CopyEngineChannel::continueProcessing() } else { inDrain(); nextState = Idle; + anWait(); + anBegin("Idle"); } } void CopyEngine::CopyEngineChannel::writeCompletionStatus() { + anBegin("WriteCompletionStatus"); DPRINTF(DMACopyEngine, "Writing completion status %#x to address %#x(%#x)\n", completionDataReg, cr.completionAddr, ce->platform->pciToDma(cr.completionAddr)); @@ -574,6 +588,7 @@ CopyEngine::CopyEngineChannel::writeStatusComplete() void CopyEngine::CopyEngineChannel::fetchNextAddr(Addr address) { + anBegin("FetchNextAddr"); DPRINTF(DMACopyEngine, "Fetching next address...\n"); busy = true; cePort->dmaAction(MemCmd::ReadReq, ce->platform->pciToDma(address + @@ -590,6 +605,8 @@ CopyEngine::CopyEngineChannel::fetchAddrComplete() DPRINTF(DMACopyEngine, "Got NULL descriptor, nothing more to do\n"); busy = false; nextState = Idle; + anWait(); + anBegin("Idle"); inDrain(); return; } diff --git a/src/dev/copy_engine.hh b/src/dev/copy_engine.hh index 475c0a5bf..12531f68c 100644 --- a/src/dev/copy_engine.hh +++ b/src/dev/copy_engine.hh @@ -130,6 +130,36 @@ class CopyEngine : public PciDev void recvCommand(); bool inDrain(); void restartStateMachine(); + inline void anBegin(const char *s) + { + CPA::cpa()->hwBegin(CPA::FL_NONE, ce->sys, + channelId, "CopyEngine", s); + } + + inline void anWait() + { + CPA::cpa()->hwWe(CPA::FL_NONE, ce->sys, + channelId, "CopyEngine", "DMAUnusedDescQ", channelId); + } + + inline void anDq() + { + CPA::cpa()->hwDq(CPA::FL_NONE, ce->sys, + channelId, "CopyEngine", "DMAUnusedDescQ", channelId); + } + + inline void anPq() + { + CPA::cpa()->hwDq(CPA::FL_NONE, ce->sys, + channelId, "CopyEngine", "DMAUnusedDescQ", channelId); + } + + inline void anQ(const char * s, uint64_t id, int size = 1) + { + CPA::cpa()->hwQ(CPA::FL_NONE, ce->sys, channelId, + "CopyEngine", s, id, NULL, size); + } + }; private: diff --git a/src/dev/i8254xGBe.cc b/src/dev/i8254xGBe.cc index d6a888b21..274f60e39 100644 --- a/src/dev/i8254xGBe.cc +++ b/src/dev/i8254xGBe.cc @@ -113,10 +113,20 @@ IGbE::IGbE(const Params *p) // Magic happy checksum value flash[EEPROM_SIZE-1] = htobe((uint16_t)(EEPROM_CSUM - csum)); + // Store the MAC address as queue ID + macAddr = p->hardware_address; + rxFifo.clear(); txFifo.clear(); } +void +IGbE::init() +{ + cpa = CPA::cpa(); + PciDev::init(); +} + EtherInt* IGbE::getEthPort(const std::string &if_name, int idx) { @@ -793,6 +803,13 @@ IGbE::RxDescCache::RxDescCache(IGbE *i, const std::string n, int s) pktEvent(this), pktHdrEvent(this), pktDataEvent(this) { + annSmFetch = "RX Desc Fetch"; + annSmWb = "RX Desc Writeback"; + annUnusedDescQ = "RX Unused Descriptors"; + annUnusedCacheQ = "RX Unused Descriptor Cache"; + annUsedCacheQ = "RX Used Descriptor Cache"; + annUsedDescQ = "RX Used Descriptors"; + annDescQ = "RX Descriptors"; } void @@ -910,6 +927,8 @@ IGbE::RxDescCache::pktComplete() RxDesc *desc; desc = unusedCache.front(); + igbe->anBegin("RXS", "Update Desc"); + uint16_t crcfixup = igbe->regs.rctl.secrc() ? 0 : 4 ; DPRINTF(EthernetDesc, "pktPtr->length: %d bytesCopied: %d stripcrc offset: %d value written: %d %d\n", pktPtr->length, bytesCopied, crcfixup, @@ -1052,8 +1071,11 @@ IGbE::RxDescCache::pktComplete() enableSm(); pktDone = true; + igbe->anBegin("RXS", "Done Updating Desc"); DPRINTF(EthernetDesc, "Processing of this descriptor complete\n"); + igbe->anDq("RXS", annUnusedCacheQ); unusedCache.pop_front(); + igbe->anQ("RXS", annUsedCacheQ); usedCache.push_back(desc); } @@ -1112,6 +1134,13 @@ IGbE::TxDescCache::TxDescCache(IGbE *i, const std::string n, int s) useTso(false), pktEvent(this), headerEvent(this), nullEvent(this) { + annSmFetch = "TX Desc Fetch"; + annSmWb = "TX Desc Writeback"; + annUnusedDescQ = "TX Unused Descriptors"; + annUnusedCacheQ = "TX Unused Descriptor Cache"; + annUsedCacheQ = "TX Used Descriptor Cache"; + annUsedDescQ = "TX Used Descriptors"; + annDescQ = "TX Descriptors"; } void @@ -1154,7 +1183,9 @@ IGbE::TxDescCache::processContextDesc() TxdOp::setDd(desc); unusedCache.pop_front(); + igbe->anDq("TXS", annUnusedCacheQ); usedCache.push_back(desc); + igbe->anQ("TXS", annUsedCacheQ); } if (!unusedCache.size()) @@ -1298,6 +1329,8 @@ IGbE::TxDescCache::pktComplete() assert(unusedCache.size()); assert(pktPtr); + igbe->anBegin("TXS", "Update Desc"); + DPRINTF(EthernetDesc, "DMA of packet complete\n"); @@ -1323,7 +1356,9 @@ IGbE::TxDescCache::pktComplete() (pktPtr->length < ( tsoMss + tsoHeaderLen) && tsoTotalLen != tsoUsedLen && useTso)) { assert(!useTso || (tsoDescBytesUsed == TxdOp::getLen(desc))); + igbe->anDq("TXS", annUnusedCacheQ); unusedCache.pop_front(); + igbe->anQ("TXS", annUsedCacheQ); usedCache.push_back(desc); tsoDescBytesUsed = 0; @@ -1441,7 +1476,9 @@ IGbE::TxDescCache::pktComplete() if (!useTso || TxdOp::getLen(desc) == tsoDescBytesUsed) { DPRINTF(EthernetDesc, "Descriptor Done\n"); + igbe->anDq("TXS", annUnusedCacheQ); unusedCache.pop_front(); + igbe->anQ("TXS", annUsedCacheQ); usedCache.push_back(desc); tsoDescBytesUsed = 0; } @@ -1458,14 +1495,17 @@ IGbE::TxDescCache::pktComplete() tsoPktHasHeader = false; if (igbe->regs.txdctl.wthresh() == 0) { + igbe->anBegin("TXS", "Desc Writeback"); DPRINTF(EthernetDesc, "WTHRESH == 0, writing back descriptor\n"); writeback(0); } else if (igbe->regs.txdctl.gran() && igbe->regs.txdctl.wthresh() >= descInBlock(usedCache.size())) { DPRINTF(EthernetDesc, "used > WTHRESH, writing back descriptor\n"); + igbe->anBegin("TXS", "Desc Writeback"); writeback((igbe->cacheBlockSize()-1)>>4); } else if (igbe->regs.txdctl.wthresh() >= usedCache.size()) { DPRINTF(EthernetDesc, "used > WTHRESH, writing back descriptor\n"); + igbe->anBegin("TXS", "Desc Writeback"); writeback((igbe->cacheBlockSize()-1)>>4); } @@ -1604,6 +1644,7 @@ IGbE::drain(Event *de) else changeState(Drained); + DPRINTF(EthernetSM, "got drain() returning %d", count); return count; } @@ -1617,6 +1658,7 @@ IGbE::resume() rxTick = true; restartClock(); + DPRINTF(EthernetSM, "resuming from drain"); } void @@ -1625,6 +1667,7 @@ IGbE::checkDrain() if (!drainEvent) return; + DPRINTF(EthernetSM, "checkDrain() in drain\n"); txFifoTick = false; txTick = false; rxTick = false; @@ -1651,11 +1694,13 @@ IGbE::txStateMachine() && !txDescCache.packetMultiDesc() && txPacket->length) { bool success; + anQ("TXS", "TX FIFO Q"); DPRINTF(EthernetSM, "TXS: packet placed in TX FIFO\n"); success = txFifo.push(txPacket); txFifoTick = true && !drainEvent; assert(success); txPacket = NULL; + anBegin("TXS", "Desc Writeback"); txDescCache.writeback((cacheBlockSize()-1)>>4); return; } @@ -1673,7 +1718,10 @@ IGbE::txStateMachine() if (!txDescCache.packetWaiting()) { if (txDescCache.descLeft() == 0) { postInterrupt(IT_TXQE); + anBegin("TXS", "Desc Writeback"); txDescCache.writeback(0); + anBegin("TXS", "Desc Fetch"); + anWe("TXS", txDescCache.annUnusedCacheQ); txDescCache.fetchDescriptors(); DPRINTF(EthernetSM, "TXS: No descriptors left in ring, forcing " "writeback stopping ticking and posting TXQE\n"); @@ -1683,11 +1731,14 @@ IGbE::txStateMachine() if (!(txDescCache.descUnused())) { + anBegin("TXS", "Desc Fetch"); txDescCache.fetchDescriptors(); + anWe("TXS", txDescCache.annUnusedCacheQ); DPRINTF(EthernetSM, "TXS: No descriptors available in cache, fetching and stopping ticking\n"); txTick = false; return; } + anPq("TXS", txDescCache.annUnusedCacheQ); txDescCache.processContextDesc(); @@ -1700,6 +1751,8 @@ IGbE::txStateMachine() int size; size = txDescCache.getPacketSize(txPacket); if (size > 0 && txFifo.avail() > size) { + anRq("TXS", "TX FIFO Q"); + anBegin("TXS", "DMA Packet"); DPRINTF(EthernetSM, "TXS: Reserving %d bytes in FIFO and begining " "DMA of next packet\n", size); txFifo.reserve(size); @@ -1707,8 +1760,10 @@ IGbE::txStateMachine() } else if (size <= 0) { DPRINTF(EthernetSM, "TXS: getPacketSize returned: %d\n", size); DPRINTF(EthernetSM, "TXS: No packets to get, writing back used descriptors\n"); + anBegin("TXS", "Desc Writeback"); txDescCache.writeback(0); } else { + anWf("TXS", "TX FIFO Q"); DPRINTF(EthernetSM, "TXS: FIFO full, stopping ticking until space " "available in FIFO\n"); txTick = false; @@ -1728,9 +1783,12 @@ IGbE::ethRxPkt(EthPacketPtr pkt) rxPackets++; DPRINTF(Ethernet, "RxFIFO: Receiving pcakte from wire\n"); + anBegin("RXQ", "Wire Recv"); + if (!regs.rctl.en()) { DPRINTF(Ethernet, "RxFIFO: RX not enabled, dropping\n"); + anBegin("RXQ", "FIFO Drop", CPA::FL_BAD); return true; } @@ -1744,9 +1802,23 @@ IGbE::ethRxPkt(EthPacketPtr pkt) if (!rxFifo.push(pkt)) { DPRINTF(Ethernet, "RxFIFO: Packet won't fit in fifo... dropped\n"); postInterrupt(IT_RXO, true); + anBegin("RXQ", "FIFO Drop", CPA::FL_BAD); return false; } + if (CPA::available() && cpa->enabled()) { + assert(sys->numSystemsRunning <= 2); + System *other_sys; + if (sys->systemList[0] == sys) + other_sys = sys->systemList[1]; + else + other_sys = sys->systemList[0]; + + cpa->hwDq(CPA::FL_NONE, sys, macAddr, "RXQ", "WireQ", 0, other_sys); + anQ("RXQ", "RX FIFO Q"); + cpa->hwWe(CPA::FL_NONE, sys, macAddr, "RXQ", "WireQ", 0, other_sys); + } + return true; } @@ -1780,6 +1852,7 @@ IGbE::rxStateMachine() rxDescCache.writeback(0); if (descLeft == 0) { + anBegin("RXS", "Writeback Descriptors"); rxDescCache.writeback(0); DPRINTF(EthernetSM, "RXS: No descriptors left in ring, forcing" " writeback and stopping ticking\n"); @@ -1791,6 +1864,7 @@ IGbE::rxStateMachine() if (regs.rxdctl.wthresh() >= rxDescCache.descUsed()) { DPRINTF(EthernetSM, "RXS: Writing back because WTHRESH >= descUsed\n"); + anBegin("RXS", "Writeback Descriptors"); if (regs.rxdctl.wthresh() < (cacheBlockSize()>>4)) rxDescCache.writeback(regs.rxdctl.wthresh()-1); else @@ -1800,11 +1874,14 @@ IGbE::rxStateMachine() if ((rxDescCache.descUnused() < regs.rxdctl.pthresh()) && ((rxDescCache.descLeft() - rxDescCache.descUnused()) > regs.rxdctl.hthresh())) { DPRINTF(EthernetSM, "RXS: Fetching descriptors because descUnused < PTHRESH\n"); + anBegin("RXS", "Fetch Descriptors"); rxDescCache.fetchDescriptors(); } if (rxDescCache.descUnused() == 0) { + anBegin("RXS", "Fetch Descriptors"); rxDescCache.fetchDescriptors(); + anWe("RXS", rxDescCache.annUnusedCacheQ); DPRINTF(EthernetSM, "RXS: No descriptors available in cache, " "fetching descriptors and stopping ticking\n"); rxTick = false; @@ -1819,18 +1896,24 @@ IGbE::rxStateMachine() } if (!rxDescCache.descUnused()) { + anBegin("RXS", "Fetch Descriptors"); rxDescCache.fetchDescriptors(); + anWe("RXS", rxDescCache.annUnusedCacheQ); DPRINTF(EthernetSM, "RXS: No descriptors available in cache, stopping ticking\n"); rxTick = false; DPRINTF(EthernetSM, "RXS: No descriptors available, fetching\n"); return; } + anPq("RXS", rxDescCache.annUnusedCacheQ); if (rxFifo.empty()) { + anWe("RXS", "RX FIFO Q"); DPRINTF(EthernetSM, "RXS: RxFIFO empty, stopping ticking\n"); rxTick = false; return; } + anPq("RXS", "RX FIFO Q"); + anBegin("RXS", "Get Desc"); EthPacketPtr pkt; pkt = rxFifo.front(); @@ -1839,26 +1922,32 @@ IGbE::rxStateMachine() pktOffset = rxDescCache.writePacket(pkt, pktOffset); DPRINTF(EthernetSM, "RXS: Writing packet into memory\n"); if (pktOffset == pkt->length) { + anBegin( "RXS", "FIFO Dequeue"); DPRINTF(EthernetSM, "RXS: Removing packet from FIFO\n"); pktOffset = 0; + anDq("RXS", "RX FIFO Q"); rxFifo.pop(); } DPRINTF(EthernetSM, "RXS: stopping ticking until packet DMA completes\n"); rxTick = false; rxDmaPacket = true; + anBegin("RXS", "DMA Packet"); } void IGbE::txWire() { if (txFifo.empty()) { + anWe("TXQ", "TX FIFO Q"); txFifoTick = false; return; } + anPq("TXQ", "TX FIFO Q"); if (etherInt->sendPacket(txFifo.front())) { + cpa->hwQ(CPA::FL_NONE, sys, macAddr, "TXQ", "WireQ", 0); if (DTRACE(EthernetSM)) { IpPtr ip(txFifo.front()); if (ip) @@ -1867,6 +1956,8 @@ IGbE::txWire() else DPRINTF(EthernetSM, "Transmitting Non-Ip packet\n"); } + anDq("TXQ", "TX FIFO Q"); + anBegin("TXQ", "Wire Send"); DPRINTF(EthernetSM, "TxFIFO: Successful transmit, bytes available in fifo: %d\n", txFifo.avail()); @@ -1903,6 +1994,7 @@ IGbE::tick() void IGbE::ethTxDone() { + anBegin("TXQ", "Send Done"); // restart the tx state machines if they are stopped // fifo to send another packet // tx sm to put more data into the fifo diff --git a/src/dev/i8254xGBe.hh b/src/dev/i8254xGBe.hh index 6dd2141b0..0422abc33 100644 --- a/src/dev/i8254xGBe.hh +++ b/src/dev/i8254xGBe.hh @@ -38,6 +38,7 @@ #include #include +#include "base/cp_annotate.hh" #include "base/inet.hh" #include "dev/etherdevice.hh" #include "dev/etherint.hh" @@ -54,6 +55,7 @@ class IGbE : public EtherDevice { private: IGbEInt *etherInt; + CPA *cpa; // device registers iGbReg::Regs regs; @@ -176,6 +178,35 @@ class IGbE : public EtherDevice */ void checkDrain(); + void anBegin(std::string sm, std::string st, int flags = CPA::FL_NONE) { + cpa->hwBegin((CPA::flags)flags, sys, macAddr, sm, st); + } + + void anQ(std::string sm, std::string q) { + cpa->hwQ(CPA::FL_NONE, sys, macAddr, sm, q, macAddr); + } + + void anDq(std::string sm, std::string q) { + cpa->hwDq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr); + } + + void anPq(std::string sm, std::string q, int num = 1) { + cpa->hwPq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr, NULL, num); + } + + void anRq(std::string sm, std::string q, int num = 1) { + cpa->hwPq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr, NULL, num); + } + + void anWe(std::string sm, std::string q) { + cpa->hwWe(CPA::FL_NONE, sys, macAddr, sm, q, macAddr); + } + + void anWf(std::string sm, std::string q) { + cpa->hwWf(CPA::FL_NONE, sys, macAddr, sm, q, macAddr); + } + + template class DescCache { @@ -225,6 +256,10 @@ class IGbE : public EtherDevice EthPacketPtr pktPtr; public: + /** Annotate sm*/ + std::string annSmFetch, annSmWb, annUnusedDescQ, annUsedCacheQ, + annUsedDescQ, annUnusedCacheQ, annDescQ; + DescCache(IGbE *i, const std::string n, int s) : igbe(i), _name(n), cachePnt(0), size(s), curFetching(0), wbOut(0), pktPtr(NULL), wbDelayEvent(this), fetchDelayEvent(this), @@ -290,6 +325,10 @@ class IGbE : public EtherDevice DPRINTF(EthernetDesc, "Writing back %d descriptors\n", max_to_wb); if (max_to_wb <= 0) { + if (usedCache.size()) + igbe->anBegin(annSmWb, "Wait Alignment", CPA::FL_WAIT); + else + igbe->anWe(annSmWb, annUsedCacheQ); return; } @@ -297,25 +336,30 @@ class IGbE : public EtherDevice assert(!wbDelayEvent.scheduled()); igbe->schedule(wbDelayEvent, curTick + igbe->wbDelay); + igbe->anBegin(annSmWb, "Prepare Writeback Desc"); } void writeback1() { // If we're draining delay issuing this DMA - if (igbe->drainEvent) { + if (igbe->getState() != SimObject::Running) { igbe->schedule(wbDelayEvent, curTick + igbe->wbDelay); return; } - DPRINTF(EthernetDesc, "Beining DMA of %d descriptors\n", wbOut); + DPRINTF(EthernetDesc, "Begining DMA of %d descriptors\n", wbOut); for (int x = 0; x < wbOut; x++) { assert(usedCache.size()); memcpy(&wbBuf[x], usedCache[x], sizeof(T)); - //delete usedCache[0]; - //usedCache.pop_front(); + igbe->anPq(annSmWb, annUsedCacheQ); + igbe->anPq(annSmWb, annDescQ); + igbe->anQ(annSmWb, annUsedDescQ); } + + igbe->anBegin(annSmWb, "Writeback Desc DMA"); + assert(wbOut); igbe->dmaWrite(igbe->platform->pciToDma(descBase() + descHead() * sizeof(T)), wbOut * sizeof(T), &wbEvent, (uint8_t*)wbBuf, @@ -343,6 +387,18 @@ class IGbE : public EtherDevice size_t free_cache = size - usedCache.size() - unusedCache.size(); + if (!max_to_fetch) + igbe->anWe(annSmFetch, annUnusedDescQ); + else + igbe->anPq(annSmFetch, annUnusedDescQ, max_to_fetch); + + if (max_to_fetch) { + if (!free_cache) + igbe->anWf(annSmFetch, annDescQ); + else + igbe->anRq(annSmFetch, annDescQ, free_cache); + } + max_to_fetch = std::min(max_to_fetch, free_cache); @@ -360,16 +416,19 @@ class IGbE : public EtherDevice assert(!fetchDelayEvent.scheduled()); igbe->schedule(fetchDelayEvent, curTick + igbe->fetchDelay); + igbe->anBegin(annSmFetch, "Prepare Fetch Desc"); } void fetchDescriptors1() { // If we're draining delay issuing this DMA - if (igbe->drainEvent) { + if (igbe->getState() != SimObject::Running) { igbe->schedule(fetchDelayEvent, curTick + igbe->fetchDelay); return; } + igbe->anBegin(annSmFetch, "Fetch Desc"); + DPRINTF(EthernetDesc, "Fetching descriptors at %#x (%#x), size: %#x\n", descBase() + cachePnt * sizeof(T), igbe->platform->pciToDma(descBase() + cachePnt * sizeof(T)), @@ -387,10 +446,14 @@ class IGbE : public EtherDevice void fetchComplete() { T *newDesc; + igbe->anBegin(annSmFetch, "Fetch Complete"); for (int x = 0; x < curFetching; x++) { newDesc = new T; memcpy(newDesc, &fetchBuf[x], sizeof(T)); unusedCache.push_back(newDesc); + igbe->anDq(annSmFetch, annUnusedDescQ); + igbe->anQ(annSmFetch, annUnusedCacheQ); + igbe->anQ(annSmFetch, annDescQ); } @@ -408,6 +471,16 @@ class IGbE : public EtherDevice DPRINTF(EthernetDesc, "Fetching complete cachePnt %d -> %d\n", oldCp, cachePnt); + if ((descTail() >= cachePnt ? (descTail() - cachePnt) : (descLen() - + cachePnt)) == 0) + { + igbe->anWe(annSmFetch, annUnusedDescQ); + } else if (!(size - usedCache.size() - unusedCache.size())) { + igbe->anWf(annSmFetch, annDescQ); + } else { + igbe->anBegin(annSmFetch, "Wait", CPA::FL_WAIT); + } + enableSm(); igbe->checkDrain(); } @@ -419,6 +492,8 @@ class IGbE : public EtherDevice void wbComplete() { + igbe->anBegin(annSmWb, "Finish Writeback"); + long curHead = descHead(); #ifndef NDEBUG long oldHead = curHead; @@ -428,6 +503,9 @@ class IGbE : public EtherDevice assert(usedCache.size()); delete usedCache[0]; usedCache.pop_front(); + + igbe->anDq(annSmWb, annUsedCacheQ); + igbe->anDq(annSmWb, annDescQ); } curHead += wbOut; @@ -452,6 +530,10 @@ class IGbE : public EtherDevice if (!wbOut) { igbe->checkDrain(); + if (usedCache.size()) + igbe->anBegin(annSmWb, "Wait", CPA::FL_WAIT); + else + igbe->anWe(annSmWb, annUsedCacheQ); } fetchAfterWb(); } @@ -747,6 +829,7 @@ class IGbE : public EtherDevice } IGbE(const Params *params); ~IGbE() {} + virtual void init(); virtual EtherInt *getEthPort(const std::string &if_name, int idx); -- cgit v1.2.3 From 932f6440a1269c6ceaf2dc07a9ced8ac4b7b1652 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:21:14 -0800 Subject: X86: Add a class to support 32 bit x86 linux process. --- src/arch/x86/linux/process.cc | 23 +-- src/arch/x86/linux/process.hh | 32 +++- src/arch/x86/linux/syscalls.cc | 329 ++++++++++++++++++++++++++++++++++++++++- src/sim/process.cc | 4 +- 4 files changed, 364 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/arch/x86/linux/process.cc b/src/arch/x86/linux/process.cc index 8beaf150b..8a3fc67ee 100644 --- a/src/arch/x86/linux/process.cc +++ b/src/arch/x86/linux/process.cc @@ -72,26 +72,17 @@ using namespace X86ISA; SyscallDesc* X86LinuxProcess::getDesc(int callnum) { - if (callnum < 0 || callnum > Num_Syscall_Descs) + if (callnum < 0 || callnum >= Num_Syscall_Descs) return NULL; return &syscallDescs[callnum]; } -X86LinuxProcess::X86LinuxProcess(LiveProcessParams * params, +X86_64LinuxProcess::X86_64LinuxProcess(LiveProcessParams * params, ObjectFile *objFile) - : X86LiveProcess(params, objFile), - Num_Syscall_Descs(273) + : X86LinuxProcess(params, objFile, syscallDescs, 273) {} -void X86LinuxProcess::handleTrap(int trapNum, ThreadContext *tc) -{ - switch(trapNum) - { - //This implementation is from SPARC - case 0x10: //Linux 32 bit syscall trap - tc->syscall(tc->readIntReg(1)); - break; - default: - X86LiveProcess::handleTrap(trapNum, tc); - } -} +I386LinuxProcess::I386LinuxProcess(LiveProcessParams * params, + ObjectFile *objFile) + : X86LinuxProcess(params, objFile, syscallDescs, 324) +{} diff --git a/src/arch/x86/linux/process.hh b/src/arch/x86/linux/process.hh index e224374d4..e80b86537 100644 --- a/src/arch/x86/linux/process.hh +++ b/src/arch/x86/linux/process.hh @@ -67,19 +67,41 @@ namespace X86ISA { /// A process with emulated x86/Linux syscalls. class X86LinuxProcess : public X86LiveProcess +{ + protected: + SyscallDesc *syscallDescs; + + const int Num_Syscall_Descs; + + /// Constructor. + X86LinuxProcess(LiveProcessParams * params, ObjectFile *objFile, + SyscallDesc *_syscallDescs, int numSyscallDescs) : + X86LiveProcess(params, objFile), syscallDescs(_syscallDescs), + Num_Syscall_Descs(numSyscallDescs) + {} + + public: + SyscallDesc* getDesc(int callnum); +}; + +class X86_64LinuxProcess : public X86LinuxProcess { public: /// Constructor. - X86LinuxProcess(LiveProcessParams * params, ObjectFile *objFile); + X86_64LinuxProcess(LiveProcessParams * params, ObjectFile *objFile); /// Array of syscall descriptors, indexed by call number. static SyscallDesc syscallDescs[]; +}; - SyscallDesc* getDesc(int callnum); - - const int Num_Syscall_Descs; +class I386LinuxProcess : public X86LinuxProcess +{ + public: + /// Constructor. + I386LinuxProcess(LiveProcessParams * params, ObjectFile *objFile); - void handleTrap(int trapNum, ThreadContext *tc); + /// Array of syscall descriptors, indexed by call number. + static SyscallDesc syscallDescs[]; }; } // namespace X86ISA diff --git a/src/arch/x86/linux/syscalls.cc b/src/arch/x86/linux/syscalls.cc index ca35a5dd6..324749366 100644 --- a/src/arch/x86/linux/syscalls.cc +++ b/src/arch/x86/linux/syscalls.cc @@ -122,7 +122,7 @@ archPrctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, } } -SyscallDesc X86LinuxProcess::syscallDescs[] = { +SyscallDesc X86_64LinuxProcess::syscallDescs[] = { /* 0 */ SyscallDesc("read", readFunc), /* 1 */ SyscallDesc("write", writeFunc), /* 2 */ SyscallDesc("open", openFunc), @@ -397,3 +397,330 @@ SyscallDesc X86LinuxProcess::syscallDescs[] = { /* 271 */ SyscallDesc("ppoll", unimplementedFunc), /* 272 */ SyscallDesc("unshare", unimplementedFunc) }; + +SyscallDesc I386LinuxProcess::syscallDescs[] = { + /* 0 */ SyscallDesc("restart_syscall", unimplementedFunc), + /* 1 */ SyscallDesc("exit", unimplementedFunc), + /* 2 */ SyscallDesc("fork", unimplementedFunc), + /* 3 */ SyscallDesc("read", unimplementedFunc), + /* 4 */ SyscallDesc("write", unimplementedFunc), + /* 5 */ SyscallDesc("open", unimplementedFunc), + /* 6 */ SyscallDesc("close", unimplementedFunc), + /* 7 */ SyscallDesc("waitpid", unimplementedFunc), + /* 8 */ SyscallDesc("creat", unimplementedFunc), + /* 9 */ SyscallDesc("link", unimplementedFunc), + /* 10 */ SyscallDesc("unlink", unimplementedFunc), + /* 11 */ SyscallDesc("execve", unimplementedFunc), + /* 12 */ SyscallDesc("chdir", unimplementedFunc), + /* 13 */ SyscallDesc("time", unimplementedFunc), + /* 14 */ SyscallDesc("mknod", unimplementedFunc), + /* 15 */ SyscallDesc("chmod", unimplementedFunc), + /* 16 */ SyscallDesc("lchown", unimplementedFunc), + /* 17 */ SyscallDesc("break", unimplementedFunc), + /* 18 */ SyscallDesc("oldstat", unimplementedFunc), + /* 19 */ SyscallDesc("lseek", unimplementedFunc), + /* 20 */ SyscallDesc("getpid", unimplementedFunc), + /* 21 */ SyscallDesc("mount", unimplementedFunc), + /* 22 */ SyscallDesc("umount", unimplementedFunc), + /* 23 */ SyscallDesc("setuid", unimplementedFunc), + /* 24 */ SyscallDesc("getuid", unimplementedFunc), + /* 25 */ SyscallDesc("stime", unimplementedFunc), + /* 26 */ SyscallDesc("ptrace", unimplementedFunc), + /* 27 */ SyscallDesc("alarm", unimplementedFunc), + /* 28 */ SyscallDesc("oldfstat", unimplementedFunc), + /* 29 */ SyscallDesc("pause", unimplementedFunc), + /* 30 */ SyscallDesc("utime", unimplementedFunc), + /* 31 */ SyscallDesc("stty", unimplementedFunc), + /* 32 */ SyscallDesc("gtty", unimplementedFunc), + /* 33 */ SyscallDesc("access", unimplementedFunc), + /* 34 */ SyscallDesc("nice", unimplementedFunc), + /* 35 */ SyscallDesc("ftime", unimplementedFunc), + /* 36 */ SyscallDesc("sync", unimplementedFunc), + /* 37 */ SyscallDesc("kill", unimplementedFunc), + /* 38 */ SyscallDesc("rename", unimplementedFunc), + /* 39 */ SyscallDesc("mkdir", unimplementedFunc), + /* 40 */ SyscallDesc("rmdir", unimplementedFunc), + /* 41 */ SyscallDesc("dup", unimplementedFunc), + /* 42 */ SyscallDesc("pipe", unimplementedFunc), + /* 43 */ SyscallDesc("times", unimplementedFunc), + /* 44 */ SyscallDesc("prof", unimplementedFunc), + /* 45 */ SyscallDesc("brk", unimplementedFunc), + /* 46 */ SyscallDesc("setgid", unimplementedFunc), + /* 47 */ SyscallDesc("getgid", unimplementedFunc), + /* 48 */ SyscallDesc("signal", unimplementedFunc), + /* 49 */ SyscallDesc("geteuid", unimplementedFunc), + /* 50 */ SyscallDesc("getegid", unimplementedFunc), + /* 51 */ SyscallDesc("acct", unimplementedFunc), + /* 52 */ SyscallDesc("umount2", unimplementedFunc), + /* 53 */ SyscallDesc("lock", unimplementedFunc), + /* 54 */ SyscallDesc("ioctl", unimplementedFunc), + /* 55 */ SyscallDesc("fcntl", unimplementedFunc), + /* 56 */ SyscallDesc("mpx", unimplementedFunc), + /* 57 */ SyscallDesc("setpgid", unimplementedFunc), + /* 58 */ SyscallDesc("ulimit", unimplementedFunc), + /* 59 */ SyscallDesc("oldolduname", unimplementedFunc), + /* 60 */ SyscallDesc("umask", unimplementedFunc), + /* 61 */ SyscallDesc("chroot", unimplementedFunc), + /* 62 */ SyscallDesc("ustat", unimplementedFunc), + /* 63 */ SyscallDesc("dup2", unimplementedFunc), + /* 64 */ SyscallDesc("getppid", unimplementedFunc), + /* 65 */ SyscallDesc("getpgrp", unimplementedFunc), + /* 66 */ SyscallDesc("setsid", unimplementedFunc), + /* 67 */ SyscallDesc("sigaction", unimplementedFunc), + /* 68 */ SyscallDesc("sgetmask", unimplementedFunc), + /* 69 */ SyscallDesc("ssetmask", unimplementedFunc), + /* 70 */ SyscallDesc("setreuid", unimplementedFunc), + /* 71 */ SyscallDesc("setregid", unimplementedFunc), + /* 72 */ SyscallDesc("sigsuspend", unimplementedFunc), + /* 73 */ SyscallDesc("sigpending", unimplementedFunc), + /* 74 */ SyscallDesc("sethostname", unimplementedFunc), + /* 75 */ SyscallDesc("setrlimit", unimplementedFunc), + /* 76 */ SyscallDesc("getrlimit", unimplementedFunc), + /* 77 */ SyscallDesc("getrusage", unimplementedFunc), + /* 78 */ SyscallDesc("gettimeofday", unimplementedFunc), + /* 79 */ SyscallDesc("settimeofday", unimplementedFunc), + /* 80 */ SyscallDesc("getgroups", unimplementedFunc), + /* 81 */ SyscallDesc("setgroups", unimplementedFunc), + /* 82 */ SyscallDesc("select", unimplementedFunc), + /* 83 */ SyscallDesc("symlink", unimplementedFunc), + /* 84 */ SyscallDesc("oldlstat", unimplementedFunc), + /* 85 */ SyscallDesc("readlink", unimplementedFunc), + /* 86 */ SyscallDesc("uselib", unimplementedFunc), + /* 87 */ SyscallDesc("swapon", unimplementedFunc), + /* 88 */ SyscallDesc("reboot", unimplementedFunc), + /* 89 */ SyscallDesc("readdir", unimplementedFunc), + /* 90 */ SyscallDesc("mmap", unimplementedFunc), + /* 91 */ SyscallDesc("munmap", unimplementedFunc), + /* 92 */ SyscallDesc("truncate", unimplementedFunc), + /* 93 */ SyscallDesc("ftruncate", unimplementedFunc), + /* 94 */ SyscallDesc("fchmod", unimplementedFunc), + /* 95 */ SyscallDesc("fchown", unimplementedFunc), + /* 96 */ SyscallDesc("getpriority", unimplementedFunc), + /* 97 */ SyscallDesc("setpriority", unimplementedFunc), + /* 98 */ SyscallDesc("profil", unimplementedFunc), + /* 99 */ SyscallDesc("statfs", unimplementedFunc), + /* 100 */ SyscallDesc("fstatfs", unimplementedFunc), + /* 101 */ SyscallDesc("ioperm", unimplementedFunc), + /* 102 */ SyscallDesc("socketcall", unimplementedFunc), + /* 103 */ SyscallDesc("syslog", unimplementedFunc), + /* 104 */ SyscallDesc("setitimer", unimplementedFunc), + /* 105 */ SyscallDesc("getitimer", unimplementedFunc), + /* 106 */ SyscallDesc("stat", unimplementedFunc), + /* 107 */ SyscallDesc("lstat", unimplementedFunc), + /* 108 */ SyscallDesc("fstat", unimplementedFunc), + /* 109 */ SyscallDesc("olduname", unimplementedFunc), + /* 110 */ SyscallDesc("iopl", unimplementedFunc), + /* 111 */ SyscallDesc("vhangup", unimplementedFunc), + /* 112 */ SyscallDesc("idle", unimplementedFunc), + /* 113 */ SyscallDesc("vm86old", unimplementedFunc), + /* 114 */ SyscallDesc("wait4", unimplementedFunc), + /* 115 */ SyscallDesc("swapoff", unimplementedFunc), + /* 116 */ SyscallDesc("sysinfo", unimplementedFunc), + /* 117 */ SyscallDesc("ipc", unimplementedFunc), + /* 118 */ SyscallDesc("fsync", unimplementedFunc), + /* 119 */ SyscallDesc("sigreturn", unimplementedFunc), + /* 120 */ SyscallDesc("clone", unimplementedFunc), + /* 121 */ SyscallDesc("setdomainname", unimplementedFunc), + /* 122 */ SyscallDesc("uname", unimplementedFunc), + /* 123 */ SyscallDesc("modify_ldt", unimplementedFunc), + /* 124 */ SyscallDesc("adjtimex", unimplementedFunc), + /* 125 */ SyscallDesc("mprotect", unimplementedFunc), + /* 126 */ SyscallDesc("sigprocmask", unimplementedFunc), + /* 127 */ SyscallDesc("create_module", unimplementedFunc), + /* 128 */ SyscallDesc("init_module", unimplementedFunc), + /* 129 */ SyscallDesc("delete_module", unimplementedFunc), + /* 130 */ SyscallDesc("get_kernel_syms", unimplementedFunc), + /* 131 */ SyscallDesc("quotactl", unimplementedFunc), + /* 132 */ SyscallDesc("getpgid", unimplementedFunc), + /* 133 */ SyscallDesc("fchdir", unimplementedFunc), + /* 134 */ SyscallDesc("bdflush", unimplementedFunc), + /* 135 */ SyscallDesc("sysfs", unimplementedFunc), + /* 136 */ SyscallDesc("personality", unimplementedFunc), + /* 137 */ SyscallDesc("afs_syscall", unimplementedFunc), + /* 138 */ SyscallDesc("setfsuid", unimplementedFunc), + /* 139 */ SyscallDesc("setfsgid", unimplementedFunc), + /* 140 */ SyscallDesc("_llseek", unimplementedFunc), + /* 141 */ SyscallDesc("getdents", unimplementedFunc), + /* 142 */ SyscallDesc("_newselect", unimplementedFunc), + /* 143 */ SyscallDesc("flock", unimplementedFunc), + /* 144 */ SyscallDesc("msync", unimplementedFunc), + /* 145 */ SyscallDesc("readv", unimplementedFunc), + /* 146 */ SyscallDesc("writev", unimplementedFunc), + /* 147 */ SyscallDesc("getsid", unimplementedFunc), + /* 148 */ SyscallDesc("fdatasync", unimplementedFunc), + /* 149 */ SyscallDesc("_sysctl", unimplementedFunc), + /* 150 */ SyscallDesc("mlock", unimplementedFunc), + /* 151 */ SyscallDesc("munlock", unimplementedFunc), + /* 152 */ SyscallDesc("mlockall", unimplementedFunc), + /* 153 */ SyscallDesc("munlockall", unimplementedFunc), + /* 154 */ SyscallDesc("sched_setparam", unimplementedFunc), + /* 155 */ SyscallDesc("sched_getparam", unimplementedFunc), + /* 156 */ SyscallDesc("sched_setscheduler", unimplementedFunc), + /* 157 */ SyscallDesc("sched_getscheduler", unimplementedFunc), + /* 158 */ SyscallDesc("sched_yield", unimplementedFunc), + /* 159 */ SyscallDesc("sched_get_priority_max", unimplementedFunc), + /* 160 */ SyscallDesc("sched_get_priority_min", unimplementedFunc), + /* 161 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc), + /* 162 */ SyscallDesc("nanosleep", unimplementedFunc), + /* 163 */ SyscallDesc("mremap", unimplementedFunc), + /* 164 */ SyscallDesc("setresuid", unimplementedFunc), + /* 165 */ SyscallDesc("getresuid", unimplementedFunc), + /* 166 */ SyscallDesc("vm86", unimplementedFunc), + /* 167 */ SyscallDesc("query_module", unimplementedFunc), + /* 168 */ SyscallDesc("poll", unimplementedFunc), + /* 169 */ SyscallDesc("nfsservctl", unimplementedFunc), + /* 170 */ SyscallDesc("setresgid", unimplementedFunc), + /* 171 */ SyscallDesc("getresgid", unimplementedFunc), + /* 172 */ SyscallDesc("prctl", unimplementedFunc), + /* 173 */ SyscallDesc("rt_sigreturn", unimplementedFunc), + /* 174 */ SyscallDesc("rt_sigaction", unimplementedFunc), + /* 175 */ SyscallDesc("rt_sigprocmask", unimplementedFunc), + /* 176 */ SyscallDesc("rt_sigpending", unimplementedFunc), + /* 177 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc), + /* 178 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc), + /* 179 */ SyscallDesc("rt_sigsuspend", unimplementedFunc), + /* 180 */ SyscallDesc("pread64", unimplementedFunc), + /* 181 */ SyscallDesc("pwrite64", unimplementedFunc), + /* 182 */ SyscallDesc("chown", unimplementedFunc), + /* 183 */ SyscallDesc("getcwd", unimplementedFunc), + /* 184 */ SyscallDesc("capget", unimplementedFunc), + /* 185 */ SyscallDesc("capset", unimplementedFunc), + /* 186 */ SyscallDesc("sigaltstack", unimplementedFunc), + /* 187 */ SyscallDesc("sendfile", unimplementedFunc), + /* 188 */ SyscallDesc("getpmsg", unimplementedFunc), + /* 189 */ SyscallDesc("putpmsg", unimplementedFunc), + /* 190 */ SyscallDesc("vfork", unimplementedFunc), + /* 191 */ SyscallDesc("ugetrlimit", unimplementedFunc), + /* 192 */ SyscallDesc("mmap2", unimplementedFunc), + /* 193 */ SyscallDesc("truncate64", unimplementedFunc), + /* 194 */ SyscallDesc("ftruncate64", unimplementedFunc), + /* 195 */ SyscallDesc("stat64", unimplementedFunc), + /* 196 */ SyscallDesc("lstat64", unimplementedFunc), + /* 197 */ SyscallDesc("fstat64", unimplementedFunc), + /* 198 */ SyscallDesc("lchown32", unimplementedFunc), + /* 199 */ SyscallDesc("getuid32", unimplementedFunc), + /* 200 */ SyscallDesc("getgid32", unimplementedFunc), + /* 201 */ SyscallDesc("geteuid32", unimplementedFunc), + /* 202 */ SyscallDesc("getegid32", unimplementedFunc), + /* 203 */ SyscallDesc("setreuid32", unimplementedFunc), + /* 204 */ SyscallDesc("setregid32", unimplementedFunc), + /* 205 */ SyscallDesc("getgroups32", unimplementedFunc), + /* 206 */ SyscallDesc("setgroups32", unimplementedFunc), + /* 207 */ SyscallDesc("fchown32", unimplementedFunc), + /* 208 */ SyscallDesc("setresuid32", unimplementedFunc), + /* 209 */ SyscallDesc("getresuid32", unimplementedFunc), + /* 210 */ SyscallDesc("setresgid32", unimplementedFunc), + /* 211 */ SyscallDesc("getresgid32", unimplementedFunc), + /* 212 */ SyscallDesc("chown32", unimplementedFunc), + /* 213 */ SyscallDesc("setuid32", unimplementedFunc), + /* 214 */ SyscallDesc("setgid32", unimplementedFunc), + /* 215 */ SyscallDesc("setfsuid32", unimplementedFunc), + /* 216 */ SyscallDesc("setfsgid32", unimplementedFunc), + /* 217 */ SyscallDesc("pivot_root", unimplementedFunc), + /* 218 */ SyscallDesc("mincore", unimplementedFunc), + /* 219 */ SyscallDesc("madvise", unimplementedFunc), + /* 220 */ SyscallDesc("madvise1", unimplementedFunc), + /* 221 */ SyscallDesc("getdents64", unimplementedFunc), + /* 222 */ SyscallDesc("fcntl64", unimplementedFunc), + /* 223 */ SyscallDesc("unused", unimplementedFunc), + /* 224 */ SyscallDesc("gettid", unimplementedFunc), + /* 225 */ SyscallDesc("readahead", unimplementedFunc), + /* 226 */ SyscallDesc("setxattr", unimplementedFunc), + /* 227 */ SyscallDesc("lsetxattr", unimplementedFunc), + /* 228 */ SyscallDesc("fsetxattr", unimplementedFunc), + /* 229 */ SyscallDesc("getxattr", unimplementedFunc), + /* 230 */ SyscallDesc("lgetxattr", unimplementedFunc), + /* 231 */ SyscallDesc("fgetxattr", unimplementedFunc), + /* 232 */ SyscallDesc("listxattr", unimplementedFunc), + /* 233 */ SyscallDesc("llistxattr", unimplementedFunc), + /* 234 */ SyscallDesc("flistxattr", unimplementedFunc), + /* 235 */ SyscallDesc("removexattr", unimplementedFunc), + /* 236 */ SyscallDesc("lremovexattr", unimplementedFunc), + /* 237 */ SyscallDesc("fremovexattr", unimplementedFunc), + /* 238 */ SyscallDesc("tkill", unimplementedFunc), + /* 239 */ SyscallDesc("sendfile64", unimplementedFunc), + /* 240 */ SyscallDesc("futex", unimplementedFunc), + /* 241 */ SyscallDesc("sched_setaffinity", unimplementedFunc), + /* 242 */ SyscallDesc("sched_getaffinity", unimplementedFunc), + /* 243 */ SyscallDesc("set_thread_area", unimplementedFunc), + /* 244 */ SyscallDesc("get_thread_area", unimplementedFunc), + /* 245 */ SyscallDesc("io_setup", unimplementedFunc), + /* 246 */ SyscallDesc("io_destroy", unimplementedFunc), + /* 247 */ SyscallDesc("io_getevents", unimplementedFunc), + /* 248 */ SyscallDesc("io_submit", unimplementedFunc), + /* 249 */ SyscallDesc("io_cancel", unimplementedFunc), + /* 250 */ SyscallDesc("fadvise64", unimplementedFunc), + /* 251 */ SyscallDesc("unused", unimplementedFunc), + /* 252 */ SyscallDesc("exit_group", unimplementedFunc), + /* 253 */ SyscallDesc("lookup_dcookie", unimplementedFunc), + /* 254 */ SyscallDesc("epoll_create", unimplementedFunc), + /* 255 */ SyscallDesc("epoll_ctl", unimplementedFunc), + /* 256 */ SyscallDesc("epoll_wait", unimplementedFunc), + /* 257 */ SyscallDesc("remap_file_pages", unimplementedFunc), + /* 258 */ SyscallDesc("set_tid_address", unimplementedFunc), + /* 259 */ SyscallDesc("timer_create", unimplementedFunc), + /* 260 */ SyscallDesc("timer_settime", unimplementedFunc), + /* 261 */ SyscallDesc("timer_gettime", unimplementedFunc), + /* 262 */ SyscallDesc("timer_getoverrun", unimplementedFunc), + /* 263 */ SyscallDesc("timer_delete", unimplementedFunc), + /* 264 */ SyscallDesc("clock_settime", unimplementedFunc), + /* 265 */ SyscallDesc("clock_gettime", unimplementedFunc), + /* 266 */ SyscallDesc("clock_getres", unimplementedFunc), + /* 267 */ SyscallDesc("clock_nanosleep", unimplementedFunc), + /* 268 */ SyscallDesc("statfs64", unimplementedFunc), + /* 269 */ SyscallDesc("fstatfs64", unimplementedFunc), + /* 270 */ SyscallDesc("tgkill", unimplementedFunc), + /* 271 */ SyscallDesc("utimes", unimplementedFunc), + /* 272 */ SyscallDesc("fadvise64_64", unimplementedFunc), + /* 273 */ SyscallDesc("vserver", unimplementedFunc), + /* 274 */ SyscallDesc("mbind", unimplementedFunc), + /* 275 */ SyscallDesc("get_mempolicy", unimplementedFunc), + /* 276 */ SyscallDesc("set_mempolicy", unimplementedFunc), + /* 277 */ SyscallDesc("mq_open", unimplementedFunc), + /* 278 */ SyscallDesc("mq_unlink", unimplementedFunc), + /* 279 */ SyscallDesc("mq_timedsend", unimplementedFunc), + /* 280 */ SyscallDesc("mq_timedreceive", unimplementedFunc), + /* 281 */ SyscallDesc("mq_notify", unimplementedFunc), + /* 282 */ SyscallDesc("mq_getsetattr", unimplementedFunc), + /* 283 */ SyscallDesc("kexec_load", unimplementedFunc), + /* 284 */ SyscallDesc("waitid", unimplementedFunc), + /* 285 */ SyscallDesc("sys_setaltroot", unimplementedFunc), + /* 286 */ SyscallDesc("add_key", unimplementedFunc), + /* 287 */ SyscallDesc("request_key", unimplementedFunc), + /* 288 */ SyscallDesc("keyctl", unimplementedFunc), + /* 289 */ SyscallDesc("ioprio_set", unimplementedFunc), + /* 290 */ SyscallDesc("ioprio_get", unimplementedFunc), + /* 291 */ SyscallDesc("inotify_init", unimplementedFunc), + /* 292 */ SyscallDesc("inotify_add_watch", unimplementedFunc), + /* 293 */ SyscallDesc("inotify_rm_watch", unimplementedFunc), + /* 294 */ SyscallDesc("migrate_pages", unimplementedFunc), + /* 295 */ SyscallDesc("openat", unimplementedFunc), + /* 296 */ SyscallDesc("mkdirat", unimplementedFunc), + /* 297 */ SyscallDesc("mknodat", unimplementedFunc), + /* 298 */ SyscallDesc("fchownat", unimplementedFunc), + /* 299 */ SyscallDesc("futimesat", unimplementedFunc), + /* 300 */ SyscallDesc("fstatat64", unimplementedFunc), + /* 301 */ SyscallDesc("unlinkat", unimplementedFunc), + /* 302 */ SyscallDesc("renameat", unimplementedFunc), + /* 303 */ SyscallDesc("linkat", unimplementedFunc), + /* 304 */ SyscallDesc("symlinkat", unimplementedFunc), + /* 305 */ SyscallDesc("readlinkat", unimplementedFunc), + /* 306 */ SyscallDesc("fchmodat", unimplementedFunc), + /* 307 */ SyscallDesc("faccessat", unimplementedFunc), + /* 308 */ SyscallDesc("pselect6", unimplementedFunc), + /* 309 */ SyscallDesc("ppoll", unimplementedFunc), + /* 310 */ SyscallDesc("unshare", unimplementedFunc), + /* 311 */ SyscallDesc("set_robust_list", unimplementedFunc), + /* 312 */ SyscallDesc("get_robust_list", unimplementedFunc), + /* 313 */ SyscallDesc("splice", unimplementedFunc), + /* 314 */ SyscallDesc("sync_file_range", unimplementedFunc), + /* 315 */ SyscallDesc("tee", unimplementedFunc), + /* 316 */ SyscallDesc("vmsplice", unimplementedFunc), + /* 317 */ SyscallDesc("move_pages", unimplementedFunc), + /* 318 */ SyscallDesc("getcpu", unimplementedFunc), + /* 319 */ SyscallDesc("epoll_pwait", unimplementedFunc), + /* 320 */ SyscallDesc("utimensat", unimplementedFunc), + /* 321 */ SyscallDesc("signalfd", unimplementedFunc), + /* 322 */ SyscallDesc("timerfd", unimplementedFunc), + /* 323 */ SyscallDesc("eventfd", unimplementedFunc) +}; diff --git a/src/sim/process.cc b/src/sim/process.cc index 7383611c0..51c0573ba 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -717,9 +717,9 @@ LiveProcess::create(LiveProcessParams * params) // fall through case ObjectFile::Linux: if (objFile->getArch() == ObjectFile::X86_64) { - process = new X86LinuxProcess(params, objFile); + process = new X86_64LinuxProcess(params, objFile); } else { - panic("32 bit x86 Linux process aren't implemented.\n"); + process = new I386LinuxProcess(params, objFile); } break; -- cgit v1.2.3 From 05de9f4e2cb0771a8f83dc1888c877852e19f1ad Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:21:36 -0800 Subject: X86: Distinguish the width of values on the stack between 32 and 64 bit processes. --- src/arch/x86/linux/process.cc | 13 +--- src/arch/x86/linux/process.hh | 31 ++------ src/arch/x86/process.cc | 164 ++++++++++++++++++++++++++++++++++-------- src/arch/x86/process.hh | 33 +++++++-- 4 files changed, 172 insertions(+), 69 deletions(-) (limited to 'src') diff --git a/src/arch/x86/linux/process.cc b/src/arch/x86/linux/process.cc index 8a3fc67ee..da22d9851 100644 --- a/src/arch/x86/linux/process.cc +++ b/src/arch/x86/linux/process.cc @@ -64,25 +64,16 @@ #include "kern/linux/linux.hh" #include "sim/process.hh" -#include "sim/syscall_emul.hh" using namespace std; using namespace X86ISA; -SyscallDesc* -X86LinuxProcess::getDesc(int callnum) -{ - if (callnum < 0 || callnum >= Num_Syscall_Descs) - return NULL; - return &syscallDescs[callnum]; -} - X86_64LinuxProcess::X86_64LinuxProcess(LiveProcessParams * params, ObjectFile *objFile) - : X86LinuxProcess(params, objFile, syscallDescs, 273) + : X86_64LiveProcess(params, objFile, syscallDescs, 273) {} I386LinuxProcess::I386LinuxProcess(LiveProcessParams * params, ObjectFile *objFile) - : X86LinuxProcess(params, objFile, syscallDescs, 324) + : I386LiveProcess(params, objFile, syscallDescs, 324) {} diff --git a/src/arch/x86/linux/process.hh b/src/arch/x86/linux/process.hh index e80b86537..2f37692e3 100644 --- a/src/arch/x86/linux/process.hh +++ b/src/arch/x86/linux/process.hh @@ -65,43 +65,26 @@ namespace X86ISA { -/// A process with emulated x86/Linux syscalls. -class X86LinuxProcess : public X86LiveProcess +class X86_64LinuxProcess : public X86_64LiveProcess { protected: - SyscallDesc *syscallDescs; - - const int Num_Syscall_Descs; - - /// Constructor. - X86LinuxProcess(LiveProcessParams * params, ObjectFile *objFile, - SyscallDesc *_syscallDescs, int numSyscallDescs) : - X86LiveProcess(params, objFile), syscallDescs(_syscallDescs), - Num_Syscall_Descs(numSyscallDescs) - {} - - public: - SyscallDesc* getDesc(int callnum); -}; + /// Array of syscall descriptors, indexed by call number. + static SyscallDesc syscallDescs[]; -class X86_64LinuxProcess : public X86LinuxProcess -{ public: /// Constructor. X86_64LinuxProcess(LiveProcessParams * params, ObjectFile *objFile); +}; +class I386LinuxProcess : public I386LiveProcess +{ + protected: /// Array of syscall descriptors, indexed by call number. static SyscallDesc syscallDescs[]; -}; -class I386LinuxProcess : public X86LinuxProcess -{ public: /// Constructor. I386LinuxProcess(LiveProcessParams * params, ObjectFile *objFile); - - /// Array of syscall descriptors, indexed by call number. - static SyscallDesc syscallDescs[]; }; } // namespace X86ISA diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index d6f3b2371..800dd44ef 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -98,48 +98,72 @@ #include "mem/page_table.hh" #include "mem/translating_port.hh" #include "sim/process_impl.hh" +#include "sim/syscall_emul.hh" #include "sim/system.hh" using namespace std; using namespace X86ISA; -X86LiveProcess::X86LiveProcess(LiveProcessParams * params, - ObjectFile *objFile) - : LiveProcess(params, objFile) +X86LiveProcess::X86LiveProcess(LiveProcessParams * params, ObjectFile *objFile, + SyscallDesc *_syscallDescs, int _numSyscallDescs) : + LiveProcess(params, objFile), syscallDescs(_syscallDescs), + numSyscallDescs(_numSyscallDescs) { brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize(); brk_point = roundUp(brk_point, VMPageSize); +} - // Set pointer for next thread stack. Reserve 8M for main stack. - next_thread_stack_base = stack_base - (8 * 1024 * 1024); - +X86_64LiveProcess::X86_64LiveProcess(LiveProcessParams *params, + ObjectFile *objFile, SyscallDesc *_syscallDescs, + int _numSyscallDescs) : + X86LiveProcess(params, objFile, _syscallDescs, _numSyscallDescs) +{ // Set up stack. On X86_64 Linux, stack goes from the top of memory // downward, less the hole for the kernel address space plus one page // for undertermined purposes. stack_base = (Addr)0x7FFFFFFFF000ULL; + // Set pointer for next thread stack. Reserve 8M for main stack. + next_thread_stack_base = stack_base - (8 * 1024 * 1024); + // Set up region for mmaps. This was determined empirically and may not // always be correct. mmap_start = mmap_end = (Addr)0x2aaaaaaab000ULL; } -void X86LiveProcess::handleTrap(int trapNum, ThreadContext *tc) +I386LiveProcess::I386LiveProcess(LiveProcessParams *params, + ObjectFile *objFile, SyscallDesc *_syscallDescs, + int _numSyscallDescs) : + X86LiveProcess(params, objFile, _syscallDescs, _numSyscallDescs) { - switch(trapNum) - { - default: - panic("Unimplemented trap to operating system: trap number %#x.\n", trapNum); - } + stack_base = (Addr)0xffffe000ULL; + + // Set pointer for next thread stack. Reserve 8M for main stack. + next_thread_stack_base = stack_base - (8 * 1024 * 1024); + + // Set up region for mmaps. This was determined empirically and may not + // always be correct. + mmap_start = mmap_end = (Addr)0xf7ffd000ULL; +} + +SyscallDesc* +X86LiveProcess::getDesc(int callnum) +{ + if (callnum < 0 || callnum >= numSyscallDescs) + return NULL; + return &syscallDescs[callnum]; } void -X86LiveProcess::startup() +X86_64LiveProcess::startup() { + LiveProcess::startup(); + if (checkpointRestored) return; - argsInit(sizeof(IntReg), VMPageSize); + argsInit(sizeof(uint64_t), VMPageSize); for (int i = 0; i < contextIds.size(); i++) { ThreadContext * tc = system->getThreadContext(contextIds[i]); @@ -198,12 +222,80 @@ X86LiveProcess::startup() } void -X86LiveProcess::argsInit(int intSize, int pageSize) +I386LiveProcess::startup() { - typedef AuxVector auxv_t; - std::vector auxv; + LiveProcess::startup(); + + if (checkpointRestored) + return; + + argsInit(sizeof(uint32_t), VMPageSize); + + for (int i = 0; i < contextIds.size(); i++) { + ThreadContext * tc = system->getThreadContext(contextIds[i]); + + SegAttr dataAttr = 0; + dataAttr.writable = 1; + dataAttr.readable = 1; + dataAttr.expandDown = 0; + dataAttr.dpl = 3; + dataAttr.defaultSize = 1; + dataAttr.longMode = 0; + + //Initialize the segment registers. + for(int seg = 0; seg < NUM_SEGMENTREGS; seg++) { + tc->setMiscRegNoEffect(MISCREG_SEG_BASE(seg), 0); + tc->setMiscRegNoEffect(MISCREG_SEG_EFF_BASE(seg), 0); + tc->setMiscRegNoEffect(MISCREG_SEG_ATTR(seg), dataAttr); + tc->setMiscRegNoEffect(MISCREG_SEG_SEL(seg), 0xB); + } + + SegAttr csAttr = 0; + csAttr.writable = 0; + csAttr.readable = 1; + csAttr.expandDown = 0; + csAttr.dpl = 3; + csAttr.defaultSize = 1; + csAttr.longMode = 0; + + tc->setMiscRegNoEffect(MISCREG_CS_ATTR, csAttr); + + //Set up the registers that describe the operating mode. + CR0 cr0 = 0; + cr0.pg = 1; // Turn on paging. + cr0.cd = 0; // Don't disable caching. + cr0.nw = 0; // This is bit is defined to be ignored. + cr0.am = 0; // No alignment checking + cr0.wp = 0; // Supervisor mode can write read only pages + cr0.ne = 1; + cr0.et = 1; // This should always be 1 + cr0.ts = 0; // We don't do task switching, so causing fp exceptions + // would be pointless. + cr0.em = 0; // Allow x87 instructions to execute natively. + cr0.mp = 1; // This doesn't really matter, but the manual suggests + // setting it to one. + cr0.pe = 1; // We're definitely in protected mode. + tc->setMiscReg(MISCREG_CR0, cr0); - Process::startup(); + Efer efer = 0; + efer.sce = 1; // Enable system call extensions. + efer.lme = 1; // Enable long mode. + efer.lma = 0; // Deactivate long mode. + efer.nxe = 1; // Enable nx support. + efer.svme = 0; // Disable svm support for now. It isn't implemented. + efer.ffxsr = 1; // Turn on fast fxsave and fxrstor. + tc->setMiscReg(MISCREG_EFER, efer); + } +} + +template +void +X86LiveProcess::argsInit(int pageSize) +{ + int intSize = sizeof(IntType); + + typedef AuxVector auxv_t; + std::vector auxv; string filename; if(argv.size() < 1) @@ -396,15 +488,15 @@ X86LiveProcess::argsInit(int intSize, int pageSize) roundUp(stack_size, pageSize)); // map out initial stack contents - Addr sentry_base = stack_base - sentry_size; - Addr file_name_base = sentry_base - file_name_size; - Addr env_data_base = file_name_base - env_data_size; - Addr arg_data_base = env_data_base - arg_data_size; - Addr aux_data_base = arg_data_base - info_block_padding - aux_data_size; - Addr auxv_array_base = aux_data_base - aux_array_size - aux_padding; - Addr envp_array_base = auxv_array_base - envp_array_size; - Addr argv_array_base = envp_array_base - argv_array_size; - Addr argc_base = argv_array_base - argc_size; + IntType sentry_base = stack_base - sentry_size; + IntType file_name_base = sentry_base - file_name_size; + IntType env_data_base = file_name_base - env_data_size; + IntType arg_data_base = env_data_base - arg_data_size; + IntType aux_data_base = arg_data_base - info_block_padding - aux_data_size; + IntType auxv_array_base = aux_data_base - aux_array_size - aux_padding; + IntType envp_array_base = auxv_array_base - envp_array_size; + IntType argv_array_base = envp_array_base - argv_array_size; + IntType argc_base = argv_array_base - argc_size; DPRINTF(Stack, "The addresses of items on the initial stack:\n"); DPRINTF(Stack, "0x%x - file name\n", file_name_base); @@ -420,11 +512,11 @@ X86LiveProcess::argsInit(int intSize, int pageSize) // write contents to stack // figure out argc - uint64_t argc = argv.size(); - uint64_t guestArgc = X86ISA::htog(argc); + IntType argc = argv.size(); + IntType guestArgc = X86ISA::htog(argc); //Write out the sentry void * - uint64_t sentry_NULL = 0; + IntType sentry_NULL = 0; initVirtMem->writeBlob(sentry_base, (uint8_t*)&sentry_NULL, sentry_size); @@ -470,3 +562,15 @@ X86LiveProcess::argsInit(int intSize, int pageSize) // num_processes++; } + +void +X86_64LiveProcess::argsInit(int intSize, int pageSize) +{ + X86LiveProcess::argsInit(pageSize); +} + +void +I386LiveProcess::argsInit(int intSize, int pageSize) +{ + X86LiveProcess::argsInit(pageSize); +} diff --git a/src/arch/x86/process.hh b/src/arch/x86/process.hh index d034d990e..8d77bd79d 100644 --- a/src/arch/x86/process.hh +++ b/src/arch/x86/process.hh @@ -62,22 +62,47 @@ #include #include "sim/process.hh" +class SyscallDesc; + namespace X86ISA { class X86LiveProcess : public LiveProcess { protected: - X86LiveProcess(LiveProcessParams * params, ObjectFile *objFile); + SyscallDesc *syscallDescs; + const int numSyscallDescs; - void startup(); + X86LiveProcess(LiveProcessParams * params, ObjectFile *objFile, + SyscallDesc *_syscallDescs, int _numSyscallDescs); + + template + void argsInit(int pageSize); + + public: + SyscallDesc* getDesc(int callnum); + }; + + class X86_64LiveProcess : public X86LiveProcess + { + protected: + X86_64LiveProcess(LiveProcessParams *params, ObjectFile *objFile, + SyscallDesc *_syscallDescs, int _numSyscallDescs); public: + void argsInit(int intSize, int pageSize); + void startup(); + }; - //Handles traps which request services from the operating system - virtual void handleTrap(int trapNum, ThreadContext *tc); + class I386LiveProcess : public X86LiveProcess + { + protected: + I386LiveProcess(LiveProcessParams *params, ObjectFile *objFile, + SyscallDesc *_syscallDescs, int _numSyscallDescs); + public: void argsInit(int intSize, int pageSize); + void startup(); }; } -- cgit v1.2.3 From 60aab03e854c0d955127d12c63f4c99a36d19d80 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:21:58 -0800 Subject: X86: Implement the int system call interface in the decoder. --- src/arch/x86/isa/decoder/one_byte_opcodes.isa | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src') diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa index 005864f02..817986232 100644 --- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa @@ -418,7 +418,18 @@ default: Inst::RET_FAR(); } 0x4: int3(); +#if FULL_SYSTEM 0x5: int_Ib(); +#else + // Really only the LSB matters, but the predecoder will sign + // extend it, and there's no easy way to specify only checking + // the first byte. + 0x5: decode IMMEDIATE { + 0xffffffffffffff80: + SyscallInst::int80('xc->syscall(Rax)', IsSyscall); + default: int_Ib(); + } +#endif 0x6: decode MODE_SUBMODE { 0x0: Inst::UD2(); default: into(); -- cgit v1.2.3 From 9a000c51736d97c1109be296ea7d1fd41d84debb Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:22:14 -0800 Subject: Processes: Make getting and setting system call arguments part of a process object. --- src/arch/SConscript | 1 - src/arch/alpha/freebsd/system.cc | 5 +- src/arch/alpha/isa_traits.hh | 9 ++-- src/arch/alpha/linux/process.cc | 14 +++--- src/arch/alpha/process.cc | 40 +++++++++++++-- src/arch/alpha/process.hh | 5 ++ src/arch/alpha/syscallreturn.hh | 59 ---------------------- src/arch/alpha/tru64/process.cc | 35 ++++++------- src/arch/alpha/utility.cc | 5 +- src/arch/mips/isa_traits.hh | 14 +----- src/arch/mips/linux/process.cc | 14 +++--- src/arch/mips/process.cc | 34 +++++++++++++ src/arch/mips/process.hh | 4 ++ src/arch/mips/syscallreturn.hh | 55 --------------------- src/arch/sparc/isa_traits.hh | 8 +-- src/arch/sparc/linux/process.hh | 1 - src/arch/sparc/linux/syscalls.cc | 9 ++-- src/arch/sparc/process.cc | 63 ++++++++++++++++++++++++ src/arch/sparc/process.hh | 7 +++ src/arch/sparc/solaris/process.cc | 2 +- src/arch/sparc/syscallreturn.hh | 74 ---------------------------- src/arch/sparc/utility.cc | 3 +- src/arch/x86/isa_traits.hh | 12 ----- src/arch/x86/linux/process.hh | 1 - src/arch/x86/linux/syscalls.cc | 6 +-- src/arch/x86/process.cc | 44 +++++++++++++++++ src/arch/x86/process.hh | 8 +++ src/arch/x86/syscallreturn.hh | 74 ---------------------------- src/cpu/checker/thread_context.hh | 15 ------ src/cpu/inorder/cpu.cc | 26 ---------- src/cpu/inorder/cpu.hh | 9 ---- src/cpu/inorder/thread_context.cc | 18 ------- src/cpu/inorder/thread_context.hh | 9 ---- src/cpu/o3/cpu.cc | 35 ------------- src/cpu/o3/cpu.hh | 11 ----- src/cpu/o3/thread_context.hh | 9 ---- src/cpu/o3/thread_context_impl.hh | 25 ---------- src/cpu/ozone/cpu.hh | 17 ------- src/cpu/ozone/cpu_impl.hh | 20 -------- src/cpu/simple_thread.hh | 28 ----------- src/cpu/thread_context.hh | 17 ------- src/kern/tru64/tru64.hh | 70 +++++++++++++------------- src/kern/tru64/tru64_events.cc | 2 +- src/sim/process.cc | 6 +-- src/sim/process.hh | 7 +++ src/sim/syscall_emul.cc | 101 +++++++++++++++++++------------------- src/sim/syscall_emul.hh | 96 +++++++++++++++++++----------------- 47 files changed, 401 insertions(+), 726 deletions(-) delete mode 100644 src/arch/alpha/syscallreturn.hh delete mode 100644 src/arch/mips/syscallreturn.hh delete mode 100644 src/arch/sparc/syscallreturn.hh delete mode 100644 src/arch/x86/syscallreturn.hh (limited to 'src') diff --git a/src/arch/SConscript b/src/arch/SConscript index 2b0af2816..b85ffbd89 100644 --- a/src/arch/SConscript +++ b/src/arch/SConscript @@ -56,7 +56,6 @@ isa_switch_hdrs = Split(''' regfile.hh remote_gdb.hh stacktrace.hh - syscallreturn.hh tlb.hh types.hh utility.hh diff --git a/src/arch/alpha/freebsd/system.cc b/src/arch/alpha/freebsd/system.cc index f2ea1b587..e541b260c 100644 --- a/src/arch/alpha/freebsd/system.cc +++ b/src/arch/alpha/freebsd/system.cc @@ -74,9 +74,8 @@ FreebsdAlphaSystem::doCalibrateClocks(ThreadContext *tc) Addr ppc_vaddr = 0; Addr timer_vaddr = 0; - assert(NumArgumentRegs >= 3); - ppc_vaddr = (Addr)tc->readIntReg(ArgumentReg[1]); - timer_vaddr = (Addr)tc->readIntReg(ArgumentReg[2]); + ppc_vaddr = (Addr)tc->readIntReg(17); + timer_vaddr = (Addr)tc->readIntReg(18); virtPort.write(ppc_vaddr, (uint32_t)Clock::Frequency); virtPort.write(timer_vaddr, (uint32_t)TIMER_FREQUENCY); diff --git a/src/arch/alpha/isa_traits.hh b/src/arch/alpha/isa_traits.hh index e5e4542a7..d37a769ea 100644 --- a/src/arch/alpha/isa_traits.hh +++ b/src/arch/alpha/isa_traits.hh @@ -152,12 +152,9 @@ const int ReturnAddressReg = 26; const int ReturnValueReg = 0; const int FramePointerReg = 15; -const int ArgumentReg[] = {16, 17, 18, 19, 20, 21}; -const int NumArgumentRegs = sizeof(ArgumentReg) / sizeof(const int); - -const int SyscallNumReg = ReturnValueReg; -const int SyscallPseudoReturnReg = ArgumentReg[4]; -const int SyscallSuccessReg = 19; +const int SyscallNumReg = 0; +const int FirstArgumentReg = 16; +const int SyscallPseudoReturnReg = 20; const int LogVMPageSize = 13; // 8K bytes const int VMPageSize = (1 << LogVMPageSize); diff --git a/src/arch/alpha/linux/process.cc b/src/arch/alpha/linux/process.cc index 605e40627..1e4f75790 100644 --- a/src/arch/alpha/linux/process.cc +++ b/src/arch/alpha/linux/process.cc @@ -48,7 +48,7 @@ static SyscallReturn unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - TypedBufferArg name(tc->getSyscallArg(0)); + TypedBufferArg name(process->getSyscallArg(tc, 0)); strcpy(name->sysname, "Linux"); strcpy(name->nodename, "m5.eecs.umich.edu"); @@ -67,13 +67,13 @@ static SyscallReturn osf_getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - unsigned op = tc->getSyscallArg(0); - // unsigned nbytes = tc->getSyscallArg(2); + unsigned op = process->getSyscallArg(tc, 0); + // unsigned nbytes = process->getSyscallArg(tc, 2); switch (op) { case 45: { // GSI_IEEE_FP_CONTROL - TypedBufferArg fpcr(tc->getSyscallArg(1)); + TypedBufferArg fpcr(process->getSyscallArg(tc, 1)); // I don't think this exactly matches the HW FPCR *fpcr = 0; fpcr.copyOut(tc->getMemPort()); @@ -94,13 +94,13 @@ static SyscallReturn osf_setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - unsigned op = tc->getSyscallArg(0); - // unsigned nbytes = tc->getSyscallArg(2); + unsigned op = process->getSyscallArg(tc, 0); + // unsigned nbytes = process->getSyscallArg(tc, 2); switch (op) { case 14: { // SSI_IEEE_FP_CONTROL - TypedBufferArg fpcr(tc->getSyscallArg(1)); + TypedBufferArg fpcr(process->getSyscallArg(tc, 1)); // I don't think this exactly matches the HW FPCR fpcr.copyIn(tc->getMemPort()); DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): " diff --git a/src/arch/alpha/process.cc b/src/arch/alpha/process.cc index 004be1ec0..9c6e62815 100644 --- a/src/arch/alpha/process.cc +++ b/src/arch/alpha/process.cc @@ -42,6 +42,8 @@ using namespace AlphaISA; using namespace std; +static const int SyscallSuccessReg = 19; + AlphaLiveProcess::AlphaLiveProcess(LiveProcessParams *params, ObjectFile *objFile) : LiveProcess(params, objFile) @@ -156,12 +158,10 @@ AlphaLiveProcess::argsInit(int intSize, int pageSize) (uint8_t*)&(auxv[x].a_val), intSize); } - assert(NumArgumentRegs >= 2); - ThreadContext *tc = system->getThreadContext(contextIds[0]); - tc->setIntReg(ArgumentReg[0], argc); - tc->setIntReg(ArgumentReg[1], argv_array_base); + setSyscallArg(tc, 0, argc); + setSyscallArg(tc, 1, argv_array_base); tc->setIntReg(StackPointerReg, stack_min); Addr prog_entry = objFile->entryPoint(); @@ -195,3 +195,35 @@ AlphaLiveProcess::startup() tc->setMiscRegNoEffect(IPR_DTB_ASN, M5_pid << 57); } +AlphaISA::IntReg +AlphaLiveProcess::getSyscallArg(ThreadContext *tc, int i) +{ + assert(i < 6); + return tc->readIntReg(FirstArgumentReg + i); +} + +void +AlphaLiveProcess::setSyscallArg(ThreadContext *tc, + int i, AlphaISA::IntReg val) +{ + assert(i < 6); + tc->setIntReg(FirstArgumentReg + i, val); +} + +void +AlphaLiveProcess::setSyscallReturn(ThreadContext *tc, + SyscallReturn return_value) +{ + // check for error condition. Alpha syscall convention is to + // indicate success/failure in reg a3 (r19) and put the + // return value itself in the standard return value reg (v0). + if (return_value.successful()) { + // no error + tc->setIntReg(SyscallSuccessReg, 0); + tc->setIntReg(ReturnValueReg, return_value.value()); + } else { + // got an error, return details + tc->setIntReg(SyscallSuccessReg, (IntReg)-1); + tc->setIntReg(ReturnValueReg, -return_value.value()); + } +} diff --git a/src/arch/alpha/process.hh b/src/arch/alpha/process.hh index 65c4624ae..6d083c5ac 100644 --- a/src/arch/alpha/process.hh +++ b/src/arch/alpha/process.hh @@ -42,6 +42,11 @@ class AlphaLiveProcess : public LiveProcess void startup(); void argsInit(int intSize, int pageSize); + + public: + AlphaISA::IntReg getSyscallArg(ThreadContext *tc, int i); + void setSyscallArg(ThreadContext *tc, int i, AlphaISA::IntReg val); + void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value); }; #endif // __ARCH_ALPHA_PROCESS_HH__ diff --git a/src/arch/alpha/syscallreturn.hh b/src/arch/alpha/syscallreturn.hh deleted file mode 100644 index 776f34fbf..000000000 --- a/src/arch/alpha/syscallreturn.hh +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2003-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Steve Reinhardt - * Gabe Black - */ - -#ifndef __ARCH_ALPHA_SYSCALLRETURN_HH__ -#define __ARCH_ALPHA_SYSCALLRETURN_HH__ - -#include "cpu/thread_context.hh" -#include "sim/syscallreturn.hh" - -namespace AlphaISA { - -static inline void -setSyscallReturn(SyscallReturn return_value, ThreadContext *tc) -{ - // check for error condition. Alpha syscall convention is to - // indicate success/failure in reg a3 (r19) and put the - // return value itself in the standard return value reg (v0). - if (return_value.successful()) { - // no error - tc->setIntReg(SyscallSuccessReg, 0); - tc->setIntReg(ReturnValueReg, return_value.value()); - } else { - // got an error, return details - tc->setIntReg(SyscallSuccessReg, (IntReg)-1); - tc->setIntReg(ReturnValueReg, -return_value.value()); - } -} - -} // namespace AlphaISA - -#endif // __ARCH_ALPHA_SYSCALLRETURN_HH__ diff --git a/src/arch/alpha/tru64/process.cc b/src/arch/alpha/tru64/process.cc index b84dfb286..8fa3cdeda 100644 --- a/src/arch/alpha/tru64/process.cc +++ b/src/arch/alpha/tru64/process.cc @@ -45,7 +45,7 @@ static SyscallReturn unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - TypedBufferArg name(tc->getSyscallArg(0)); + TypedBufferArg name(process->getSyscallArg(tc, 0)); strcpy(name->sysname, "OSF1"); strcpy(name->nodename, "m5.eecs.umich.edu"); @@ -62,34 +62,35 @@ static SyscallReturn getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - unsigned op = tc->getSyscallArg(0); - unsigned nbytes = tc->getSyscallArg(2); + unsigned op = process->getSyscallArg(tc, 0); + unsigned nbytes = process->getSyscallArg(tc, 2); switch (op) { case AlphaTru64::GSI_MAX_CPU: { - TypedBufferArg max_cpu(tc->getSyscallArg(1)); + TypedBufferArg max_cpu(process->getSyscallArg(tc, 1)); *max_cpu = htog((uint32_t)process->numCpus()); max_cpu.copyOut(tc->getMemPort()); return 1; } case AlphaTru64::GSI_CPUS_IN_BOX: { - TypedBufferArg cpus_in_box(tc->getSyscallArg(1)); + TypedBufferArg cpus_in_box(process->getSyscallArg(tc, 1)); *cpus_in_box = htog((uint32_t)process->numCpus()); cpus_in_box.copyOut(tc->getMemPort()); return 1; } case AlphaTru64::GSI_PHYSMEM: { - TypedBufferArg physmem(tc->getSyscallArg(1)); + TypedBufferArg physmem(process->getSyscallArg(tc, 1)); *physmem = htog((uint64_t)1024 * 1024); // physical memory in KB physmem.copyOut(tc->getMemPort()); return 1; } case AlphaTru64::GSI_CPU_INFO: { - TypedBufferArg infop(tc->getSyscallArg(1)); + TypedBufferArg + infop(process->getSyscallArg(tc, 1)); infop->current_cpu = htog(0); infop->cpus_in_box = htog(process->numCpus()); @@ -106,14 +107,14 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, } case AlphaTru64::GSI_PROC_TYPE: { - TypedBufferArg proc_type(tc->getSyscallArg(1)); + TypedBufferArg proc_type(process->getSyscallArg(tc, 1)); *proc_type = htog((uint64_t)11); proc_type.copyOut(tc->getMemPort()); return 1; } case AlphaTru64::GSI_PLATFORM_NAME: { - BufferArg bufArg(tc->getSyscallArg(1), nbytes); + BufferArg bufArg(process->getSyscallArg(tc, 1), nbytes); strncpy((char *)bufArg.bufferPtr(), "COMPAQ Professional Workstation XP1000", nbytes); @@ -122,7 +123,7 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, } case AlphaTru64::GSI_CLK_TCK: { - TypedBufferArg clk_hz(tc->getSyscallArg(1)); + TypedBufferArg clk_hz(process->getSyscallArg(tc, 1)); *clk_hz = htog((uint64_t)1024); clk_hz.copyOut(tc->getMemPort()); return 1; @@ -141,12 +142,12 @@ static SyscallReturn setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - unsigned op = tc->getSyscallArg(0); + unsigned op = process->getSyscallArg(tc, 0); switch (op) { case AlphaTru64::SSI_IEEE_FP_CONTROL: warn("setsysinfo: ignoring ieee_set_fp_control() arg 0x%x\n", - tc->getSyscallArg(1)); + process->getSyscallArg(tc, 1)); break; default: @@ -164,17 +165,17 @@ tableFunc(SyscallDesc *desc, int callnum, LiveProcess *process, { using namespace std; - int id = tc->getSyscallArg(0); // table ID - int index = tc->getSyscallArg(1); // index into table + int id = process->getSyscallArg(tc, 0); // table ID + int index = process->getSyscallArg(tc, 1); // index into table // arg 2 is buffer pointer; type depends on table ID - int nel = tc->getSyscallArg(3); // number of elements - int lel = tc->getSyscallArg(4); // expected element size + int nel = process->getSyscallArg(tc, 3); // number of elements + int lel = process->getSyscallArg(tc, 4); // expected element size switch (id) { case AlphaTru64::TBL_SYSINFO: { if (index != 0 || nel != 1 || lel != sizeof(Tru64::tbl_sysinfo)) return -EINVAL; - TypedBufferArg elp(tc->getSyscallArg(2)); + TypedBufferArg elp(process->getSyscallArg(tc, 2)); const int clk_hz = one_million; elp->si_user = htog(curTick / (Clock::Frequency / clk_hz)); diff --git a/src/arch/alpha/utility.cc b/src/arch/alpha/utility.cc index 2cf64b799..763da0d4f 100644 --- a/src/arch/alpha/utility.cc +++ b/src/arch/alpha/utility.cc @@ -42,11 +42,12 @@ uint64_t getArgument(ThreadContext *tc, int number, bool fp) { #if FULL_SYSTEM + const int NumArgumentRegs = 6; if (number < NumArgumentRegs) { if (fp) - return tc->readFloatRegBits(ArgumentReg[number]); + return tc->readFloatRegBits(16 + number); else - return tc->readIntReg(ArgumentReg[number]); + return tc->readIntReg(16 + number); } else { Addr sp = tc->readIntReg(StackPointerReg); VirtualPort *vp = tc->getVirtPort(); diff --git a/src/arch/mips/isa_traits.hh b/src/arch/mips/isa_traits.hh index 3450c273e..ed4ed9877 100644 --- a/src/arch/mips/isa_traits.hh +++ b/src/arch/mips/isa_traits.hh @@ -190,13 +190,6 @@ namespace MipsISA // semantically meaningful register indices const int ZeroReg = 0; const int AssemblerReg = 1; - const int ReturnValueReg = 2; - const int ReturnValueReg1 = 2; - const int ReturnValueReg2 = 3; - const int ArgumentReg0 = 4; - const int ArgumentReg1 = 5; - const int ArgumentReg2 = 6; - const int ArgumentReg3 = 7; const int KernelReg0 = 26; const int KernelReg1 = 27; const int GlobalPointerReg = 28; @@ -204,12 +197,7 @@ namespace MipsISA const int FramePointerReg = 30; const int ReturnAddressReg = 31; - const int ArgumentReg[] = {4, 5, 6, 7}; - const int NumArgumentRegs = sizeof(ArgumentReg) / sizeof(const int); - - const int SyscallNumReg = ReturnValueReg1; - const int SyscallPseudoReturnReg = ReturnValueReg2; - const int SyscallSuccessReg = ArgumentReg3; + const int SyscallPseudoReturnReg = 3; const int LogVMPageSize = 13; // 8K bytes const int VMPageSize = (1 << LogVMPageSize); diff --git a/src/arch/mips/linux/process.cc b/src/arch/mips/linux/process.cc index 9d9d33325..dc3b84ced 100644 --- a/src/arch/mips/linux/process.cc +++ b/src/arch/mips/linux/process.cc @@ -51,7 +51,7 @@ static SyscallReturn unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - TypedBufferArg name(tc->getSyscallArg(0)); + TypedBufferArg name(process->getSyscallArg(tc, 0)); strcpy(name->sysname, "Linux"); strcpy(name->nodename,"m5.eecs.umich.edu"); @@ -70,13 +70,13 @@ static SyscallReturn sys_getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - unsigned op = tc->getSyscallArg(0); - // unsigned nbytes = tc->getSyscallArg(2); + unsigned op = process->getSyscallArg(tc, 0); + // unsigned nbytes = process->getSyscallArg(tc, 2); switch (op) { case 45: { // GSI_IEEE_FP_CONTROL - TypedBufferArg fpcr(tc->getSyscallArg(1)); + TypedBufferArg fpcr(process->getSyscallArg(tc, 1)); // I don't think this exactly matches the HW FPCR *fpcr = 0; fpcr.copyOut(tc->getMemPort()); @@ -97,13 +97,13 @@ static SyscallReturn sys_setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - unsigned op = tc->getSyscallArg(0); - // unsigned nbytes = tc->getSyscallArg(2); + unsigned op = process->getSyscallArg(tc, 0); + // unsigned nbytes = process->getSyscallArg(tc, 2); switch (op) { case 14: { // SSI_IEEE_FP_CONTROL - TypedBufferArg fpcr(tc->getSyscallArg(1)); + TypedBufferArg fpcr(process->getSyscallArg(tc, 1)); // I don't think this exactly matches the HW FPCR fpcr.copyIn(tc->getMemPort()); DPRINTFR(SyscallVerbose, "sys_setsysinfo(SSI_IEEE_FP_CONTROL): " diff --git a/src/arch/mips/process.cc b/src/arch/mips/process.cc index b7bd22d78..784ddfe33 100644 --- a/src/arch/mips/process.cc +++ b/src/arch/mips/process.cc @@ -40,6 +40,10 @@ using namespace std; using namespace MipsISA; +static const int SyscallSuccessReg = 7; +static const int FirstArgumentReg = 4; +static const int ReturnValueReg = 2; + MipsLiveProcess::MipsLiveProcess(LiveProcessParams * params, ObjectFile *objFile) : LiveProcess(params, objFile) @@ -64,3 +68,33 @@ MipsLiveProcess::startup() { argsInit(MachineBytes, VMPageSize); } + +MipsISA::IntReg +MipsLiveProcess::getSyscallArg(ThreadContext *tc, int i) +{ + assert(i < 6); + return tc->readIntReg(FirstArgumentReg + i); +} + +void +MipsLiveProcess::setSyscallArg(ThreadContext *tc, + int i, MipsISA::IntReg val) +{ + assert(i < 6); + tc->setIntReg(FirstArgumentReg + i, val); +} + +void +MipsLiveProcess::setSyscallReturn(ThreadContext *tc, + SyscallReturn return_value) +{ + if (return_value.successful()) { + // no error + tc->setIntReg(SyscallSuccessReg, 0); + tc->setIntReg(ReturnValueReg, return_value.value()); + } else { + // got an error, return details + tc->setIntReg(SyscallSuccessReg, (IntReg) -1); + tc->setIntReg(ReturnValueReg, -return_value.value()); + } +} diff --git a/src/arch/mips/process.hh b/src/arch/mips/process.hh index 18bf289b8..87c62330f 100644 --- a/src/arch/mips/process.hh +++ b/src/arch/mips/process.hh @@ -47,6 +47,10 @@ class MipsLiveProcess : public LiveProcess virtual void startup(); + public: + MipsISA::IntReg getSyscallArg(ThreadContext *tc, int i); + void setSyscallArg(ThreadContext *tc, int i, MipsISA::IntReg val); + void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value); }; diff --git a/src/arch/mips/syscallreturn.hh b/src/arch/mips/syscallreturn.hh deleted file mode 100644 index 24a40ddcc..000000000 --- a/src/arch/mips/syscallreturn.hh +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2007 MIPS Technologies, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - * Korey Sewell - */ - -#ifndef __ARCH_MIPS_SYSCALLRETURN_HH__ -#define __ARCH_MIPS_SYSCALLRETURN_HH__ - -#include "sim/syscallreturn.hh" -#include "cpu/thread_context.hh" - -namespace MipsISA -{ - static inline void setSyscallReturn(SyscallReturn return_value, - ThreadContext *tc) - { - if (return_value.successful()) { - // no error - tc->setIntReg(SyscallSuccessReg, 0); - tc->setIntReg(ReturnValueReg1, return_value.value()); - } else { - // got an error, return details - tc->setIntReg(SyscallSuccessReg, (IntReg) -1); - tc->setIntReg(ReturnValueReg1, -return_value.value()); - } - } -} - -#endif diff --git a/src/arch/sparc/isa_traits.hh b/src/arch/sparc/isa_traits.hh index 30455792f..501f2f990 100644 --- a/src/arch/sparc/isa_traits.hh +++ b/src/arch/sparc/isa_traits.hh @@ -68,16 +68,12 @@ namespace SparcISA // semantically meaningful register indices const int ZeroReg = 0; // architecturally meaningful // the rest of these depend on the ABI - const int StackPointerReg = 14; const int ReturnAddressReg = 31; // post call, precall is 15 - const int ReturnValueReg = 8; // Post return, 24 is pre-return. + const int StackPointerReg = 14; const int FramePointerReg = 30; - const int ArgumentReg[] = {8, 9, 10, 11, 12, 13}; - const int NumArgumentRegs = sizeof(ArgumentReg) / sizeof(const int); - // Some OS syscall use a second register (o1) to return a second value - const int SyscallPseudoReturnReg = ArgumentReg[1]; + const int SyscallPseudoReturnReg = 9; //8K. This value is implmentation specific; and should probably //be somewhere else. diff --git a/src/arch/sparc/linux/process.hh b/src/arch/sparc/linux/process.hh index 06eee9235..a76b4b3b2 100644 --- a/src/arch/sparc/linux/process.hh +++ b/src/arch/sparc/linux/process.hh @@ -32,7 +32,6 @@ #define __SPARC_LINUX_PROCESS_HH__ #include "arch/sparc/linux/linux.hh" -#include "arch/sparc/syscallreturn.hh" #include "arch/sparc/process.hh" #include "sim/process.hh" diff --git a/src/arch/sparc/linux/syscalls.cc b/src/arch/sparc/linux/syscalls.cc index 3e8c603cd..8496fca13 100644 --- a/src/arch/sparc/linux/syscalls.cc +++ b/src/arch/sparc/linux/syscalls.cc @@ -29,7 +29,6 @@ */ #include "arch/sparc/linux/process.hh" -#include "arch/sparc/syscallreturn.hh" #include "sim/syscall_emul.hh" class LiveProcess; @@ -42,7 +41,7 @@ static SyscallReturn unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - TypedBufferArg name(tc->getSyscallArg(0)); + TypedBufferArg name(process->getSyscallArg(tc, 0)); strcpy(name->sysname, "Linux"); strcpy(name->nodename, "m5.eecs.umich.edu"); @@ -60,9 +59,9 @@ SyscallReturn getresuidFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { const IntReg id = htog(100); - Addr ruid = tc->getSyscallArg(0); - Addr euid = tc->getSyscallArg(1); - Addr suid = tc->getSyscallArg(2); + Addr ruid = p->getSyscallArg(tc, 0); + Addr euid = p->getSyscallArg(tc, 1); + Addr suid = p->getSyscallArg(tc, 2); //Handle the EFAULT case //Set the ruid if(ruid) diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index 515389687..b2b539816 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -46,6 +46,9 @@ using namespace std; using namespace SparcISA; +static const int FirstArgumentReg = 8; +static const int ReturnValueReg = 8; + SparcLiveProcess::SparcLiveProcess(LiveProcessParams * params, ObjectFile *objFile, Addr _StackBias) @@ -509,3 +512,63 @@ void Sparc64LiveProcess::flushWindows(ThreadContext *tc) tc->setIntReg(NumIntArchRegs + 4, Canrestore); tc->setMiscReg(MISCREG_CWP, origCWP); } + +IntReg +Sparc32LiveProcess::getSyscallArg(ThreadContext *tc, int i) +{ + assert(i < 6); + return bits(tc->readIntReg(FirstArgumentReg + i), 31, 0); +} + +void +Sparc32LiveProcess::setSyscallArg(ThreadContext *tc, int i, IntReg val) +{ + assert(i < 6); + tc->setIntReg(FirstArgumentReg + i, bits(val, 31, 0)); +} + +IntReg +Sparc64LiveProcess::getSyscallArg(ThreadContext *tc, int i) +{ + assert(i < 6); + return tc->readIntReg(FirstArgumentReg + i); +} + +void +Sparc64LiveProcess::setSyscallArg(ThreadContext *tc, int i, IntReg val) +{ + assert(i < 6); + tc->setIntReg(FirstArgumentReg + i, val); +} + +void +SparcLiveProcess::setSyscallReturn(ThreadContext *tc, + SyscallReturn return_value) +{ + // check for error condition. SPARC syscall convention is to + // indicate success/failure in reg the carry bit of the ccr + // and put the return value itself in the standard return value reg (). + if (return_value.successful()) { + // no error, clear XCC.C + tc->setIntReg(NumIntArchRegs + 2, + tc->readIntReg(NumIntArchRegs + 2) & 0xEE); + //tc->setMiscRegNoEffect(MISCREG_CCR, tc->readMiscRegNoEffect(MISCREG_CCR) & 0xEE); + IntReg val = return_value.value(); + if (bits(tc->readMiscRegNoEffect( + SparcISA::MISCREG_PSTATE), 3, 3)) { + val = bits(val, 31, 0); + } + tc->setIntReg(ReturnValueReg, val); + } else { + // got an error, set XCC.C + tc->setIntReg(NumIntArchRegs + 2, + tc->readIntReg(NumIntArchRegs + 2) | 0x11); + //tc->setMiscRegNoEffect(MISCREG_CCR, tc->readMiscRegNoEffect(MISCREG_CCR) | 0x11); + IntReg val = -return_value.value(); + if (bits(tc->readMiscRegNoEffect( + SparcISA::MISCREG_PSTATE), 3, 3)) { + val = bits(val, 31, 0); + } + tc->setIntReg(ReturnValueReg, val); + } +} diff --git a/src/arch/sparc/process.hh b/src/arch/sparc/process.hh index 95abb93d3..fdb9734ba 100644 --- a/src/arch/sparc/process.hh +++ b/src/arch/sparc/process.hh @@ -69,6 +69,7 @@ class SparcLiveProcess : public LiveProcess { return spillStart; } virtual void flushWindows(ThreadContext *tc) = 0; + void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value); }; class Sparc32LiveProcess : public SparcLiveProcess @@ -93,6 +94,9 @@ class Sparc32LiveProcess : public SparcLiveProcess void argsInit(int intSize, int pageSize); void flushWindows(ThreadContext *tc); + + SparcISA::IntReg getSyscallArg(ThreadContext *tc, int i); + void setSyscallArg(ThreadContext *tc, int i, SparcISA::IntReg val); }; class Sparc64LiveProcess : public SparcLiveProcess @@ -118,6 +122,9 @@ class Sparc64LiveProcess : public SparcLiveProcess void argsInit(int intSize, int pageSize); void flushWindows(ThreadContext *tc); + + SparcISA::IntReg getSyscallArg(ThreadContext *tc, int i); + void setSyscallArg(ThreadContext *tc, int i, SparcISA::IntReg val); }; #endif // __SPARC_PROCESS_HH__ diff --git a/src/arch/sparc/solaris/process.cc b/src/arch/sparc/solaris/process.cc index e4f6b23c8..1a4940b59 100644 --- a/src/arch/sparc/solaris/process.cc +++ b/src/arch/sparc/solaris/process.cc @@ -48,7 +48,7 @@ static SyscallReturn unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - TypedBufferArg name(tc->getSyscallArg(0)); + TypedBufferArg name(process->getSyscallArg(tc, 0)); strcpy(name->sysname, "SunOS"); strcpy(name->nodename, "m5.eecs.umich.edu"); diff --git a/src/arch/sparc/syscallreturn.hh b/src/arch/sparc/syscallreturn.hh deleted file mode 100644 index d4e6c7c50..000000000 --- a/src/arch/sparc/syscallreturn.hh +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2003-2005 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Gabe Black - */ - -#ifndef __ARCH_SPARC_SYSCALLRETURN_HH__ -#define __ARCH_SPARC_SYSCALLRETURN_HH__ - -#include - -#include "sim/syscallreturn.hh" -#include "arch/sparc/regfile.hh" -#include "cpu/thread_context.hh" - -namespace SparcISA -{ - static inline void setSyscallReturn(SyscallReturn return_value, - ThreadContext * tc) - { - // check for error condition. SPARC syscall convention is to - // indicate success/failure in reg the carry bit of the ccr - // and put the return value itself in the standard return value reg (). - if (return_value.successful()) { - // no error, clear XCC.C - tc->setIntReg(NumIntArchRegs + 2, - tc->readIntReg(NumIntArchRegs + 2) & 0xEE); - //tc->setMiscRegNoEffect(MISCREG_CCR, tc->readMiscRegNoEffect(MISCREG_CCR) & 0xEE); - IntReg val = return_value.value(); - if (bits(tc->readMiscRegNoEffect( - SparcISA::MISCREG_PSTATE), 3, 3)) { - val = bits(val, 31, 0); - } - tc->setIntReg(ReturnValueReg, val); - } else { - // got an error, set XCC.C - tc->setIntReg(NumIntArchRegs + 2, - tc->readIntReg(NumIntArchRegs + 2) | 0x11); - //tc->setMiscRegNoEffect(MISCREG_CCR, tc->readMiscRegNoEffect(MISCREG_CCR) | 0x11); - IntReg val = -return_value.value(); - if (bits(tc->readMiscRegNoEffect( - SparcISA::MISCREG_PSTATE), 3, 3)) { - val = bits(val, 31, 0); - } - tc->setIntReg(ReturnValueReg, val); - } - } -}; - -#endif diff --git a/src/arch/sparc/utility.cc b/src/arch/sparc/utility.cc index 8f5c3e036..d4cc286e6 100644 --- a/src/arch/sparc/utility.cc +++ b/src/arch/sparc/utility.cc @@ -46,8 +46,9 @@ namespace SparcISA { //first 6 arguments which the caller may use but doesn't have to. uint64_t getArgument(ThreadContext *tc, int number, bool fp) { #if FULL_SYSTEM + const int NumArgumentRegs = 6; if (number < NumArgumentRegs) { - return tc->readIntReg(ArgumentReg[number]); + return tc->readIntReg(8 + number); } else { Addr sp = tc->readIntReg(StackPointerReg); VirtualPort *vp = tc->getVirtPort(); diff --git a/src/arch/x86/isa_traits.hh b/src/arch/x86/isa_traits.hh index abb7694ed..d25e0eb70 100644 --- a/src/arch/x86/isa_traits.hh +++ b/src/arch/x86/isa_traits.hh @@ -106,19 +106,7 @@ namespace X86ISA const int StackPointerReg = INTREG_RSP; //X86 doesn't seem to have a link register const int ReturnAddressReg = 0; - const int ReturnValueReg = INTREG_RAX; const int FramePointerReg = INTREG_RBP; - const int ArgumentReg[] = { - INTREG_RDI, - INTREG_RSI, - INTREG_RDX, - //This argument register is r10 for syscalls and rcx for C. - INTREG_R10W, - //INTREG_RCX, - INTREG_R8W, - INTREG_R9W - }; - const int NumArgumentRegs = sizeof(ArgumentReg) / sizeof(const int); // Some OS syscalls use a second register (rdx) to return a second // value diff --git a/src/arch/x86/linux/process.hh b/src/arch/x86/linux/process.hh index 2f37692e3..ca3606ef0 100644 --- a/src/arch/x86/linux/process.hh +++ b/src/arch/x86/linux/process.hh @@ -60,7 +60,6 @@ #include "sim/process.hh" #include "arch/x86/linux/linux.hh" -#include "arch/x86/syscallreturn.hh" #include "arch/x86/process.hh" namespace X86ISA { diff --git a/src/arch/x86/linux/syscalls.cc b/src/arch/x86/linux/syscalls.cc index 324749366..e4e0fa234 100644 --- a/src/arch/x86/linux/syscalls.cc +++ b/src/arch/x86/linux/syscalls.cc @@ -68,7 +68,7 @@ static SyscallReturn unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - TypedBufferArg name(tc->getSyscallArg(0)); + TypedBufferArg name(process->getSyscallArg(tc, 0)); strcpy(name->sysname, "Linux"); strcpy(name->nodename, "m5.eecs.umich.edu"); @@ -94,8 +94,8 @@ archPrctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, }; //First argument is the code, second is the address - int code = tc->getSyscallArg(0); - uint64_t addr = tc->getSyscallArg(1); + int code = process->getSyscallArg(tc, 0); + uint64_t addr = process->getSyscallArg(tc, 1); uint64_t fsBase, gsBase; TranslatingPort *p = tc->getMemPort(); switch(code) diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index 800dd44ef..7d7978a35 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -104,6 +104,18 @@ using namespace std; using namespace X86ISA; +static const int ReturnValueReg = INTREG_RAX; +static const int ArgumentReg[] = { + INTREG_RDI, + INTREG_RSI, + INTREG_RDX, + //This argument register is r10 for syscalls and rcx for C. + INTREG_R10W, + //INTREG_RCX, + INTREG_R8W, + INTREG_R9W +}; +static const int NumArgumentRegs = sizeof(ArgumentReg) / sizeof(const int); X86LiveProcess::X86LiveProcess(LiveProcessParams * params, ObjectFile *objFile, SyscallDesc *_syscallDescs, int _numSyscallDescs) : @@ -574,3 +586,35 @@ I386LiveProcess::argsInit(int intSize, int pageSize) { X86LiveProcess::argsInit(pageSize); } + +void +X86LiveProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn return_value) +{ + tc->setIntReg(INTREG_RAX, return_value.value()); +} + +X86ISA::IntReg +X86_64LiveProcess::getSyscallArg(ThreadContext *tc, int i) +{ + assert(i < NumArgumentRegs); + return tc->readIntReg(ArgumentReg[i]); +} + +void +X86_64LiveProcess::setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val) +{ + assert(i < NumArgumentRegs); + return tc->setIntReg(ArgumentReg[i], val); +} + +X86ISA::IntReg +I386LiveProcess::getSyscallArg(ThreadContext *tc, int i) +{ + panic("32 bit getSyscallArg not implemented.\n"); +} + +void +I386LiveProcess::setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val) +{ + panic("32 bit setSyscallArg not implemented.\n"); +} diff --git a/src/arch/x86/process.hh b/src/arch/x86/process.hh index 8d77bd79d..e337e589e 100644 --- a/src/arch/x86/process.hh +++ b/src/arch/x86/process.hh @@ -81,6 +81,8 @@ namespace X86ISA public: SyscallDesc* getDesc(int callnum); + + void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value); }; class X86_64LiveProcess : public X86LiveProcess @@ -92,6 +94,9 @@ namespace X86ISA public: void argsInit(int intSize, int pageSize); void startup(); + + X86ISA::IntReg getSyscallArg(ThreadContext *tc, int i); + void setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val); }; class I386LiveProcess : public X86LiveProcess @@ -103,6 +108,9 @@ namespace X86ISA public: void argsInit(int intSize, int pageSize); void startup(); + + X86ISA::IntReg getSyscallArg(ThreadContext *tc, int i); + void setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val); }; } diff --git a/src/arch/x86/syscallreturn.hh b/src/arch/x86/syscallreturn.hh deleted file mode 100644 index 6a7fdba58..000000000 --- a/src/arch/x86/syscallreturn.hh +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2007 The Hewlett-Packard Development Company - * All rights reserved. - * - * Redistribution and use of this software in source and binary forms, - * with or without modification, are permitted provided that the - * following conditions are met: - * - * The software must be used only for Non-Commercial Use which means any - * use which is NOT directed to receiving any direct monetary - * compensation for, or commercial advantage from such use. Illustrative - * examples of non-commercial use are academic research, personal study, - * teaching, education and corporate research & development. - * Illustrative examples of commercial use are distributing products for - * commercial advantage and providing services using the software for - * commercial advantage. - * - * If you wish to use this software or functionality therein that may be - * covered by patents for commercial use, please contact: - * Director of Intellectual Property Licensing - * Office of Strategy and Technology - * Hewlett-Packard Company - * 1501 Page Mill Road - * Palo Alto, California 94304 - * - * 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. No right of - * sublicense is granted herewith. Derivatives of the software and - * output created using the software may be prepared, but only for - * Non-Commercial Uses. Derivatives of the software may be shared with - * others provided: (i) the others agree to abide by the list of - * conditions herein which includes the Non-Commercial Use restrictions; - * and (ii) such Derivatives of the software include the above copyright - * notice to acknowledge the contribution from this software where - * applicable, this list of conditions and the disclaimer below. - * - * 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: Gabe Black - */ - -#ifndef __ARCH_X86_SYSCALLRETURN_HH__ -#define __ARCH_X86_SYSCALLRETURN_HH__ - -#include "base/misc.hh" -#include "cpu/thread_context.hh" -#include "sim/syscallreturn.hh" - -namespace X86ISA -{ - static inline void setSyscallReturn(SyscallReturn return_value, - ThreadContext * tc) - { - tc->setIntReg(INTREG_RAX, return_value.value()); - } -}; - -#endif // __ARCH_X86_SYSCALLRETURN_HH__ diff --git a/src/cpu/checker/thread_context.hh b/src/cpu/checker/thread_context.hh index 524e87cd4..3c87f841f 100644 --- a/src/cpu/checker/thread_context.hh +++ b/src/cpu/checker/thread_context.hh @@ -277,21 +277,6 @@ class CheckerThreadContext : public ThreadContext bool misspeculating() { return actualTC->misspeculating(); } #if !FULL_SYSTEM - IntReg getSyscallArg(int i) { return actualTC->getSyscallArg(i); } - - // used to shift args for indirect syscall - void setSyscallArg(int i, IntReg val) - { - checkerTC->setSyscallArg(i, val); - actualTC->setSyscallArg(i, val); - } - - void setSyscallReturn(SyscallReturn return_value) - { - checkerTC->setSyscallReturn(return_value); - actualTC->setSyscallReturn(return_value); - } - Counter readFuncExeInst() { return actualTC->readFuncExeInst(); } #endif }; diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc index adbf645f4..c22dd1154 100644 --- a/src/cpu/inorder/cpu.cc +++ b/src/cpu/inorder/cpu.cc @@ -1281,32 +1281,6 @@ InOrderCPU::syscall(int64_t callnum, int tid) nonSpecInstActive[tid] = false; } -IntReg -InOrderCPU::getSyscallArg(int idx, int tid) -{ - return readIntReg(ArgumentReg0 + idx, tid); -} - -void -InOrderCPU::setSyscallArg(int idx, IntReg val, int tid) -{ - setIntReg(ArgumentReg0 + idx, val, tid); -} - -void -InOrderCPU::setSyscallReturn(SyscallReturn return_value, int tid) -{ - if (return_value.successful()) { - // no error - setIntReg(SyscallSuccessReg, 0, tid); - setIntReg(ReturnValueReg, return_value.value(), tid); - } else { - // got an error, return details - setIntReg(SyscallSuccessReg, (IntReg) -1, tid); - setIntReg(ReturnValueReg, -return_value.value(), tid); - } -} - Fault InOrderCPU::read(DynInstPtr inst) { diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh index 4a7dfb404..e27687a72 100644 --- a/src/cpu/inorder/cpu.hh +++ b/src/cpu/inorder/cpu.hh @@ -511,15 +511,6 @@ class InOrderCPU : public BaseCPU /** Executes a syscall.*/ void syscall(int64_t callnum, int tid); - /** Gets a syscall argument. */ - IntReg getSyscallArg(int i, int tid); - - /** Used to shift args for indirect syscall. */ - void setSyscallArg(int i, IntReg val, int tid); - - /** Sets the return value of a syscall. */ - void setSyscallReturn(SyscallReturn return_value, int tid); - public: /** Per-Thread List of all the instructions in flight. */ std::list instList[ThePipeline::MaxThreads]; diff --git a/src/cpu/inorder/thread_context.cc b/src/cpu/inorder/thread_context.cc index 2470ee676..13f8ecdad 100644 --- a/src/cpu/inorder/thread_context.cc +++ b/src/cpu/inorder/thread_context.cc @@ -262,21 +262,3 @@ InOrderThreadContext::setMiscReg(int misc_reg, const MiscReg &val) { cpu->setMiscReg(misc_reg, val, thread->readTid()); } - -TheISA::IntReg -InOrderThreadContext::getSyscallArg(int i) -{ - return cpu->getSyscallArg(i, thread->readTid()); -} - -void -InOrderThreadContext::setSyscallArg(int i, IntReg val) -{ - cpu->setSyscallArg(i, val, thread->readTid()); -} - -void -InOrderThreadContext::setSyscallReturn(SyscallReturn return_value) -{ - cpu->setSyscallReturn(return_value, thread->readTid()); -} diff --git a/src/cpu/inorder/thread_context.hh b/src/cpu/inorder/thread_context.hh index 708dcf6b3..dce150b47 100644 --- a/src/cpu/inorder/thread_context.hh +++ b/src/cpu/inorder/thread_context.hh @@ -236,15 +236,6 @@ class InOrderThreadContext : public ThreadContext * misspeculating, this is set as false. */ virtual bool misspeculating() { return false; } - /** Gets a syscall argument by index. */ - virtual IntReg getSyscallArg(int i); - - /** Sets a syscall argument. */ - virtual void setSyscallArg(int i, IntReg val); - - /** Sets the syscall return value. */ - virtual void setSyscallReturn(SyscallReturn return_value); - /** Executes a syscall in SE mode. */ virtual void syscall(int64_t callnum) { return cpu->syscall(callnum, thread->readTid()); } diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 4f6d5d41c..1d7fb97c0 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -420,34 +420,6 @@ FullO3CPU::FullO3CPU(DerivO3CPUParams *params) lockFlag = false; } -#if !FULL_SYSTEM - -template -TheISA::IntReg -FullO3CPU::getSyscallArg(int i, int tid) -{ - assert(i < TheISA::NumArgumentRegs); - TheISA::IntReg idx = TheISA::flattenIntIndex(this->tcBase(tid), - TheISA::ArgumentReg[i]); - TheISA::IntReg val = this->readArchIntReg(idx, tid); -#if THE_ISA == SPARC_ISA - if (bits(this->readMiscRegNoEffect(SparcISA::MISCREG_PSTATE, tid), 3, 3)) - val = bits(val, 31, 0); -#endif - return val; -} - -template -void -FullO3CPU::setSyscallArg(int i, TheISA::IntReg val, int tid) -{ - assert(i < TheISA::NumArgumentRegs); - TheISA::IntReg idx = TheISA::flattenIntIndex(this->tcBase(tid), - TheISA::ArgumentReg[i]); - this->setArchIntReg(idx, val, tid); -} -#endif - template FullO3CPU::~FullO3CPU() { @@ -1000,13 +972,6 @@ FullO3CPU::syscall(int64_t callnum, int tid) --(this->thread[tid]->funcExeInst); } -template -void -FullO3CPU::setSyscallReturn(SyscallReturn return_value, int tid) -{ - TheISA::setSyscallReturn(return_value, this->tcBase(tid)); -} - #endif template diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 683e4284f..f4ed28e8e 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -193,13 +193,6 @@ class FullO3CPU : public BaseO3CPU activateThreadEvent[tid].squash(); } -#if !FULL_SYSTEM - TheISA::IntReg getSyscallArg(int i, int tid); - - /** Used to shift args for indirect syscall. */ - void setSyscallArg(int i, TheISA::IntReg val, int tid); -#endif - /** The tick event used for scheduling CPU ticks. */ ActivateThreadEvent activateThreadEvent[Impl::MaxThreads]; @@ -354,10 +347,6 @@ class FullO3CPU : public BaseO3CPU * @todo: Determine if this needs to be virtual. */ void syscall(int64_t callnum, int tid); - - /** Sets the return value of a syscall. */ - void setSyscallReturn(SyscallReturn return_value, int tid); - #endif /** Starts draining the CPU's pipeline of all instructions in diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index 6de773ff1..f3058925d 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -247,15 +247,6 @@ class O3ThreadContext : public ThreadContext virtual bool misspeculating() { return false; } #if !FULL_SYSTEM - /** Gets a syscall argument by index. */ - virtual IntReg getSyscallArg(int i); - - /** Sets a syscall argument. */ - virtual void setSyscallArg(int i, IntReg val); - - /** Sets the syscall return value. */ - virtual void setSyscallReturn(SyscallReturn return_value); - /** Executes a syscall in SE mode. */ virtual void syscall(int64_t callnum) { return cpu->syscall(callnum, thread->threadId()); } diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index 12b2d1b31..fc8b66b83 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -482,28 +482,3 @@ O3ThreadContext::setMiscReg(int misc_reg, } } -#if !FULL_SYSTEM - -template -TheISA::IntReg -O3ThreadContext::getSyscallArg(int i) -{ - return cpu->getSyscallArg(i, thread->threadId()); -} - -template -void -O3ThreadContext::setSyscallArg(int i, IntReg val) -{ - cpu->setSyscallArg(i, val, thread->threadId()); -} - -template -void -O3ThreadContext::setSyscallReturn(SyscallReturn return_value) -{ - cpu->setSyscallReturn(return_value, thread->threadId()); -} - -#endif // FULL_SYSTEM - diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index 0eb4b31f7..054fc1aa1 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -246,22 +246,6 @@ class OzoneCPU : public BaseCPU bool misspeculating() { return false; } #if !FULL_SYSTEM - TheISA::IntReg getSyscallArg(int i) - { - assert(i < TheISA::NumArgumentRegs); - return thread->renameTable[TheISA::ArgumentReg[i]]->readIntResult(); - } - - // used to shift args for indirect syscall - void setSyscallArg(int i, TheISA::IntReg val) - { - assert(i < TheISA::NumArgumentRegs); - thread->renameTable[TheISA::ArgumentReg[i]]->setIntResult(i); - } - - void setSyscallReturn(SyscallReturn return_value) - { cpu->setSyscallReturn(return_value, thread->threadId()); } - Counter readFuncExeInst() { return thread->funcExeInst; } void setFuncExeInst(Counter new_val) @@ -468,7 +452,6 @@ class OzoneCPU : public BaseCPU void processInterrupts(); #else void syscall(uint64_t &callnum); - void setSyscallReturn(SyscallReturn return_value, int tid); #endif ThreadContext *tcBase() { return tc; } diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index 84ee69464..aa76c8aa6 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -648,26 +648,6 @@ OzoneCPU::syscall(uint64_t &callnum) frontEnd->renameTable.copyFrom(thread.renameTable); backEnd->renameTable.copyFrom(thread.renameTable); } - -template -void -OzoneCPU::setSyscallReturn(SyscallReturn return_value, int tid) -{ - // check for error condition. Alpha syscall convention is to - // indicate success/failure in reg a3 (r19) and put the - // return value itself in the standard return value reg (v0). - if (return_value.successful()) { - // no error - thread.renameTable[SyscallSuccessReg]->setIntResult(0); - thread.renameTable[ReturnValueReg]->setIntResult( - return_value.value()); - } else { - // got an error, return details - thread.renameTable[SyscallSuccessReg]->setIntResult((IntReg) -1); - thread.renameTable[ReturnValueReg]->setIntResult( - -return_value.value()); - } -} #else template Fault diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index 4eba493c3..73929d362 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -34,7 +34,6 @@ #include "arch/isa_traits.hh" #include "arch/regfile.hh" -#include "arch/syscallreturn.hh" #include "arch/tlb.hh" #include "config/full_system.hh" #include "cpu/thread_context.hh" @@ -367,33 +366,6 @@ class SimpleThread : public ThreadState { storeCondFailures = sc_failures; } #if !FULL_SYSTEM - TheISA::IntReg getSyscallArg(int i) - { - assert(i < TheISA::NumArgumentRegs); - TheISA::IntReg val = regs.readIntReg( - TheISA::flattenIntIndex(getTC(), TheISA::ArgumentReg[i])); -#if THE_ISA == SPARC_ISA - if (bits(this->readMiscRegNoEffect( - SparcISA::MISCREG_PSTATE), 3, 3)) { - val = bits(val, 31, 0); - } -#endif - return val; - } - - // used to shift args for indirect syscall - void setSyscallArg(int i, TheISA::IntReg val) - { - assert(i < TheISA::NumArgumentRegs); - regs.setIntReg(TheISA::flattenIntIndex(getTC(), - TheISA::ArgumentReg[i]), val); - } - - void setSyscallReturn(SyscallReturn return_value) - { - TheISA::setSyscallReturn(return_value, getTC()); - } - void syscall(int64_t callnum) { process->syscall(callnum, tc); diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index 7c3f11c12..700f1571e 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -38,7 +38,6 @@ #include "sim/faults.hh" #include "sim/host.hh" #include "sim/serialize.hh" -#include "sim/syscallreturn.hh" #include "sim/byteswap.hh" // @todo: Figure out a more architecture independent way to obtain the ITB and @@ -258,13 +257,6 @@ class ThreadContext virtual bool misspeculating() = 0; #if !FULL_SYSTEM - virtual IntReg getSyscallArg(int i) = 0; - - // used to shift args for indirect syscall - virtual void setSyscallArg(int i, IntReg val) = 0; - - virtual void setSyscallReturn(SyscallReturn return_value) = 0; - // Same with st cond failures. virtual Counter readFuncExeInst() = 0; @@ -457,15 +449,6 @@ class ProxyThreadContext : public ThreadContext bool misspeculating() { return actualTC->misspeculating(); } #if !FULL_SYSTEM - IntReg getSyscallArg(int i) { return actualTC->getSyscallArg(i); } - - // used to shift args for indirect syscall - void setSyscallArg(int i, IntReg val) - { actualTC->setSyscallArg(i, val); } - - void setSyscallReturn(SyscallReturn return_value) - { actualTC->setSyscallReturn(return_value); } - void syscall(int64_t callnum) { actualTC->syscall(callnum); } diff --git a/src/kern/tru64/tru64.hh b/src/kern/tru64/tru64.hh index 5f8307cd2..b1af4ec0e 100644 --- a/src/kern/tru64/tru64.hh +++ b/src/kern/tru64/tru64.hh @@ -437,10 +437,10 @@ class Tru64 : public OperatingSystem #ifdef __CYGWIN__ panic("getdirent not implemented on cygwin!"); #else - int fd = process->sim_fd(tc->getSyscallArg(0)); - Addr tgt_buf = tc->getSyscallArg(1); - int tgt_nbytes = tc->getSyscallArg(2); - Addr tgt_basep = tc->getSyscallArg(3); + int fd = process->sim_fd(process->getSyscallArg(tc, 0)); + Addr tgt_buf = process->getSyscallArg(tc, 1); + int tgt_nbytes = process->getSyscallArg(tc, 2); + Addr tgt_basep = process->getSyscallArg(tc, 3); char * const host_buf = new char[tgt_nbytes]; @@ -496,7 +496,7 @@ class Tru64 : public OperatingSystem using namespace TheISA; using TheISA::RegFile; - TypedBufferArg sc(tc->getSyscallArg(0)); + TypedBufferArg sc(process->getSyscallArg(tc, 0)); sc.copyIn(tc->getMemPort()); @@ -528,7 +528,7 @@ class Tru64 : public OperatingSystem { using namespace TheISA; - TypedBufferArg argp(tc->getSyscallArg(0)); + TypedBufferArg argp(process->getSyscallArg(tc, 0)); argp.copyIn(tc->getMemPort()); @@ -576,8 +576,9 @@ class Tru64 : public OperatingSystem using namespace std; using namespace TheISA; - TypedBufferArg attrp(tc->getSyscallArg(0)); - TypedBufferArg configptr_ptr(tc->getSyscallArg(1)); + TypedBufferArg + attrp(process->getSyscallArg(tc, 0)); + TypedBufferArg configptr_ptr(process->getSyscallArg(tc, 1)); attrp.copyIn(tc->getMemPort()); @@ -683,14 +684,14 @@ class Tru64 : public OperatingSystem /// Initialize thread context. static void - init_thread_context(ThreadContext *tc, + init_thread_context(LiveProcess *process, ThreadContext *tc, Tru64::nxm_thread_attr *attrp, uint64_t uniq_val) { using namespace TheISA; tc->clearArchRegs(); - tc->setIntReg(TheISA::ArgumentReg[0], gtoh(attrp->registers.a0)); + process->setSyscallArg(tc, 0, gtoh(attrp->registers.a0)); tc->setIntReg(27/*t12*/, gtoh(attrp->registers.pc)); tc->setIntReg(TheISA::StackPointerReg, gtoh(attrp->registers.sp)); tc->setMiscRegNoEffect(AlphaISA::MISCREG_UNIQ, uniq_val); @@ -709,9 +710,10 @@ class Tru64 : public OperatingSystem using namespace std; using namespace TheISA; - TypedBufferArg attrp(tc->getSyscallArg(0)); - TypedBufferArg kidp(tc->getSyscallArg(1)); - int thread_index = tc->getSyscallArg(2); + TypedBufferArg + attrp(process->getSyscallArg(tc, 0)); + TypedBufferArg kidp(process->getSyscallArg(tc, 1)); + int thread_index = process->getSyscallArg(tc, 2); // get attribute args attrp.copyIn(tc->getMemPort()); @@ -792,7 +794,7 @@ class Tru64 : public OperatingSystem ThreadContext *tc = process->findFreeContext(); if (tc) { // inactive context... grab it - init_thread_context(tc, attrp, uniq_val); + init_thread_context(process, tc, attrp, uniq_val); // This is supposed to be a port number, but we'll try // and get away with just sticking the thread index @@ -830,11 +832,11 @@ class Tru64 : public OperatingSystem { using namespace std; - uint64_t tid = tc->getSyscallArg(0); - uint64_t secs = tc->getSyscallArg(1); - uint64_t flags = tc->getSyscallArg(2); - uint64_t action = tc->getSyscallArg(3); - uint64_t usecs = tc->getSyscallArg(4); + uint64_t tid = process->getSyscallArg(tc, 0); + uint64_t secs = process->getSyscallArg(tc, 1); + uint64_t flags = process->getSyscallArg(tc, 2); + uint64_t action = process->getSyscallArg(tc, 3); + uint64_t usecs = process->getSyscallArg(tc, 4); cout << tc->getCpuPtr()->name() << ": nxm_thread_block " << tid << " " << secs << " " << flags << " " << action << " " << usecs << endl; @@ -849,11 +851,11 @@ class Tru64 : public OperatingSystem { using namespace std; - Addr uaddr = tc->getSyscallArg(0); - uint64_t val = tc->getSyscallArg(1); - uint64_t secs = tc->getSyscallArg(2); - uint64_t usecs = tc->getSyscallArg(3); - uint64_t flags = tc->getSyscallArg(4); + Addr uaddr = process->getSyscallArg(tc, 0); + uint64_t val = process->getSyscallArg(tc, 1); + uint64_t secs = process->getSyscallArg(tc, 2); + uint64_t usecs = process->getSyscallArg(tc, 3); + uint64_t flags = process->getSyscallArg(tc, 4); BaseCPU *cpu = tc->getCpuPtr(); @@ -872,7 +874,7 @@ class Tru64 : public OperatingSystem { using namespace std; - Addr uaddr = tc->getSyscallArg(0); + Addr uaddr = process->getSyscallArg(tc, 0); cout << tc->getCpuPtr()->name() << ": nxm_unblock " << hex << uaddr << dec << endl; @@ -973,7 +975,7 @@ class Tru64 : public OperatingSystem m5_mutex_lockFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - Addr uaddr = tc->getSyscallArg(0); + Addr uaddr = process->getSyscallArg(tc, 0); m5_lock_mutex(uaddr, process, tc); @@ -990,7 +992,7 @@ class Tru64 : public OperatingSystem { using namespace TheISA; - Addr uaddr = tc->getSyscallArg(0); + Addr uaddr = process->getSyscallArg(tc, 0); TypedBufferArg lockp(uaddr); lockp.copyIn(tc->getMemPort()); @@ -1010,7 +1012,7 @@ class Tru64 : public OperatingSystem m5_mutex_unlockFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - Addr uaddr = tc->getSyscallArg(0); + Addr uaddr = process->getSyscallArg(tc, 0); m5_unlock_mutex(uaddr, process, tc); @@ -1022,7 +1024,7 @@ class Tru64 : public OperatingSystem m5_cond_signalFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - Addr cond_addr = tc->getSyscallArg(0); + Addr cond_addr = process->getSyscallArg(tc, 0); // Wake up one process waiting on the condition variable. activate_waiting_context(cond_addr, process); @@ -1035,7 +1037,7 @@ class Tru64 : public OperatingSystem m5_cond_broadcastFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - Addr cond_addr = tc->getSyscallArg(0); + Addr cond_addr = process->getSyscallArg(tc, 0); activate_waiting_context(cond_addr, process, true); @@ -1049,8 +1051,8 @@ class Tru64 : public OperatingSystem { using namespace TheISA; - Addr cond_addr = tc->getSyscallArg(0); - Addr lock_addr = tc->getSyscallArg(1); + Addr cond_addr = process->getSyscallArg(tc, 0); + Addr lock_addr = process->getSyscallArg(tc, 1); TypedBufferArg condp(cond_addr); TypedBufferArg lockp(lock_addr); @@ -1082,10 +1084,10 @@ class Tru64 : public OperatingSystem indirectSyscallFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - int new_callnum = tc->getSyscallArg(0); + int new_callnum = process->getSyscallArg(tc, 0); for (int i = 0; i < 5; ++i) - tc->setSyscallArg(i, tc->getSyscallArg(i+1)); + process->setSyscallArg(tc, i, process->getSyscallArg(tc, i+1)); SyscallDesc *new_desc = process->getDesc(new_callnum); diff --git a/src/kern/tru64/tru64_events.cc b/src/kern/tru64/tru64_events.cc index 9534c31de..4867df559 100644 --- a/src/kern/tru64/tru64_events.cc +++ b/src/kern/tru64/tru64_events.cc @@ -51,7 +51,7 @@ BadAddrEvent::process(ThreadContext *tc) // annotation for vmunix::badaddr in: // simos/simulation/apps/tcl/osf/tlaser.tcl - uint64_t a0 = tc->readIntReg(ArgumentReg[0]); + uint64_t a0 = tc->readIntReg(16); AddrRangeList resp; bool snoop; diff --git a/src/sim/process.cc b/src/sim/process.cc index 51c0573ba..4be97f2f6 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -616,12 +616,10 @@ LiveProcess::argsInit(int intSize, int pageSize) copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem); copyStringArray(envp, envp_array_base, env_data_base, initVirtMem); - assert(NumArgumentRegs >= 2); - ThreadContext *tc = system->getThreadContext(contextIds[0]); - tc->setIntReg(ArgumentReg[0], argc); - tc->setIntReg(ArgumentReg[1], argv_array_base); + setSyscallArg(tc, 0, argc); + setSyscallArg(tc, 1, argv_array_base); tc->setIntReg(StackPointerReg, stack_min); Addr prog_entry = objFile->entryPoint(); diff --git a/src/sim/process.hh b/src/sim/process.hh index e6b7c80b7..790adcb87 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -44,9 +44,11 @@ #include #include +#include "arch/types.hh" #include "base/statistics.hh" #include "sim/host.hh" #include "sim/sim_object.hh" +#include "sim/syscallreturn.hh" class GDBListener; class PageTable; @@ -321,6 +323,11 @@ class LiveProcess : public Process std::string getcwd() const { return cwd; } virtual void syscall(int64_t callnum, ThreadContext *tc); + virtual TheISA::IntReg getSyscallArg(ThreadContext *tc, int i) = 0; + virtual void setSyscallArg(ThreadContext *tc, + int i, TheISA::IntReg val) = 0; + virtual void setSyscallReturn(ThreadContext *tc, + SyscallReturn return_value) = 0; virtual SyscallDesc* getDesc(int callnum) = 0; diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index fb6af0b0c..5fe30c269 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -53,8 +53,8 @@ SyscallDesc::doSyscall(int callnum, LiveProcess *process, ThreadContext *tc) { DPRINTFR(SyscallVerbose, "%d: %s: syscall %s called w/arguments %d,%d,%d,%d\n", curTick,tc->getCpuPtr()->name(), name, - tc->getSyscallArg(0),tc->getSyscallArg(1), - tc->getSyscallArg(2),tc->getSyscallArg(3)); + process->getSyscallArg(tc, 0), process->getSyscallArg(tc, 1), + process->getSyscallArg(tc, 2), process->getSyscallArg(tc, 3)); SyscallReturn retval = (*funcPtr)(this, callnum, process, tc); @@ -62,7 +62,7 @@ SyscallDesc::doSyscall(int callnum, LiveProcess *process, ThreadContext *tc) curTick,tc->getCpuPtr()->name(), name, retval.value()); if (!(flags & SyscallDesc::SuppressReturnValue)) - tc->setSyscallReturn(retval); + process->setSyscallReturn(tc, retval); } @@ -81,7 +81,7 @@ ignoreFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { warn("ignoring syscall %s(%d, %d, ...)", desc->name, - tc->getSyscallArg(0), tc->getSyscallArg(1)); + process->getSyscallArg(tc, 0), process->getSyscallArg(tc, 1)); return 0; } @@ -92,7 +92,8 @@ exitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { if (tc->exit()) { - exitSimLoop("target called exit()", tc->getSyscallArg(0) & 0xff); + exitSimLoop("target called exit()", + process->getSyscallArg(tc, 0) & 0xff); } return 1; @@ -110,7 +111,7 @@ SyscallReturn brkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { // change brk addr to first arg - Addr new_brk = tc->getSyscallArg(0); + Addr new_brk = p->getSyscallArg(tc, 0); // in Linux at least, brk(0) returns the current break value // (note that the syscall and the glibc function have different behavior) @@ -136,7 +137,7 @@ brkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) SyscallReturn closeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { - int target_fd = tc->getSyscallArg(0); + int target_fd = p->getSyscallArg(tc, 0); int status = close(p->sim_fd(target_fd)); if (status >= 0) p->free_fd(target_fd); @@ -147,9 +148,9 @@ closeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) SyscallReturn readFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { - int fd = p->sim_fd(tc->getSyscallArg(0)); - int nbytes = tc->getSyscallArg(2); - BufferArg bufArg(tc->getSyscallArg(1), nbytes); + int fd = p->sim_fd(p->getSyscallArg(tc, 0)); + int nbytes = p->getSyscallArg(tc, 2); + BufferArg bufArg(p->getSyscallArg(tc, 1), nbytes); int bytes_read = read(fd, bufArg.bufferPtr(), nbytes); @@ -162,9 +163,9 @@ readFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) SyscallReturn writeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { - int fd = p->sim_fd(tc->getSyscallArg(0)); - int nbytes = tc->getSyscallArg(2); - BufferArg bufArg(tc->getSyscallArg(1), nbytes); + int fd = p->sim_fd(p->getSyscallArg(tc, 0)); + int nbytes = p->getSyscallArg(tc, 2); + BufferArg bufArg(p->getSyscallArg(tc, 1), nbytes); bufArg.copyIn(tc->getMemPort()); @@ -179,9 +180,9 @@ writeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) SyscallReturn lseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { - int fd = p->sim_fd(tc->getSyscallArg(0)); - uint64_t offs = tc->getSyscallArg(1); - int whence = tc->getSyscallArg(2); + int fd = p->sim_fd(p->getSyscallArg(tc, 0)); + uint64_t offs = p->getSyscallArg(tc, 1); + int whence = p->getSyscallArg(tc, 2); off_t result = lseek(fd, offs, whence); @@ -192,11 +193,11 @@ lseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) SyscallReturn _llseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { - int fd = p->sim_fd(tc->getSyscallArg(0)); - uint64_t offset_high = tc->getSyscallArg(1); - uint32_t offset_low = tc->getSyscallArg(2); - Addr result_ptr = tc->getSyscallArg(3); - int whence = tc->getSyscallArg(4); + int fd = p->sim_fd(p->getSyscallArg(tc, 0)); + uint64_t offset_high = p->getSyscallArg(tc, 1); + uint32_t offset_low = p->getSyscallArg(tc, 2); + Addr result_ptr = p->getSyscallArg(tc, 3); + int whence = p->getSyscallArg(tc, 4); uint64_t offset = (offset_high << 32) | offset_low; @@ -235,8 +236,8 @@ const char *hostname = "m5.eecs.umich.edu"; SyscallReturn gethostnameFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { - int name_len = tc->getSyscallArg(1); - BufferArg name(tc->getSyscallArg(0), name_len); + int name_len = p->getSyscallArg(tc, 1); + BufferArg name(p->getSyscallArg(tc, 0), name_len); strncpy((char *)name.bufferPtr(), hostname, name_len); @@ -249,8 +250,8 @@ SyscallReturn getcwdFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { int result = 0; - unsigned long size = tc->getSyscallArg(1); - BufferArg buf(tc->getSyscallArg(0), size); + unsigned long size = p->getSyscallArg(tc, 1); + BufferArg buf(p->getSyscallArg(tc, 0), size); // Is current working directory defined? string cwd = p->getcwd(); @@ -282,14 +283,14 @@ readlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { string path; - if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) + if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, 0))) return (TheISA::IntReg)-EFAULT; // Adjust path for current working directory path = p->fullPath(path); - size_t bufsiz = tc->getSyscallArg(2); - BufferArg buf(tc->getSyscallArg(1), bufsiz); + size_t bufsiz = p->getSyscallArg(tc, 2); + BufferArg buf(p->getSyscallArg(tc, 1), bufsiz); int result = readlink(path.c_str(), (char *)buf.bufferPtr(), bufsiz); @@ -303,7 +304,7 @@ unlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { string path; - if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) + if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, 0))) return (TheISA::IntReg)-EFAULT; // Adjust path for current working directory @@ -319,13 +320,13 @@ mkdirFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { string path; - if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) + if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, 0))) return (TheISA::IntReg)-EFAULT; // Adjust path for current working directory path = p->fullPath(path); - mode_t mode = tc->getSyscallArg(1); + mode_t mode = p->getSyscallArg(tc, 1); int result = mkdir(path.c_str(), mode); return (result == -1) ? -errno : result; @@ -336,12 +337,12 @@ renameFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { string old_name; - if (!tc->getMemPort()->tryReadString(old_name, tc->getSyscallArg(0))) + if (!tc->getMemPort()->tryReadString(old_name, p->getSyscallArg(tc, 0))) return -EFAULT; string new_name; - if (!tc->getMemPort()->tryReadString(new_name, tc->getSyscallArg(1))) + if (!tc->getMemPort()->tryReadString(new_name, p->getSyscallArg(tc, 1))) return -EFAULT; // Adjust path for current working directory @@ -357,10 +358,10 @@ truncateFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { string path; - if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) + if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, 0))) return -EFAULT; - off_t length = tc->getSyscallArg(1); + off_t length = p->getSyscallArg(tc, 1); // Adjust path for current working directory path = p->fullPath(path); @@ -372,12 +373,12 @@ truncateFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) SyscallReturn ftruncateFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) { - int fd = process->sim_fd(tc->getSyscallArg(0)); + int fd = process->sim_fd(process->getSyscallArg(tc, 0)); if (fd < 0) return -EBADF; - off_t length = tc->getSyscallArg(1); + off_t length = process->getSyscallArg(tc, 1); int result = ftruncate(fd, length); return (result == -1) ? -errno : result; @@ -399,13 +400,13 @@ chownFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { string path; - if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) + if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, 0))) return -EFAULT; /* XXX endianess */ - uint32_t owner = tc->getSyscallArg(1); + uint32_t owner = p->getSyscallArg(tc, 1); uid_t hostOwner = owner; - uint32_t group = tc->getSyscallArg(2); + uint32_t group = p->getSyscallArg(tc, 2); gid_t hostGroup = group; // Adjust path for current working directory @@ -418,15 +419,15 @@ chownFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) SyscallReturn fchownFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) { - int fd = process->sim_fd(tc->getSyscallArg(0)); + int fd = process->sim_fd(process->getSyscallArg(tc, 0)); if (fd < 0) return -EBADF; /* XXX endianess */ - uint32_t owner = tc->getSyscallArg(1); + uint32_t owner = process->getSyscallArg(tc, 1); uid_t hostOwner = owner; - uint32_t group = tc->getSyscallArg(2); + uint32_t group = process->getSyscallArg(tc, 2); gid_t hostGroup = group; int result = fchown(fd, hostOwner, hostGroup); @@ -437,11 +438,11 @@ fchownFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) SyscallReturn dupFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) { - int fd = process->sim_fd(tc->getSyscallArg(0)); + int fd = process->sim_fd(process->getSyscallArg(tc, 0)); if (fd < 0) return -EBADF; - Process::FdMap *fdo = process->sim_fd_obj(tc->getSyscallArg(0)); + Process::FdMap *fdo = process->sim_fd_obj(process->getSyscallArg(tc, 0)); int result = dup(fd); return (result == -1) ? -errno : process->alloc_fd(result, fdo->filename, fdo->flags, fdo->mode, false); @@ -452,12 +453,12 @@ SyscallReturn fcntlFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) { - int fd = tc->getSyscallArg(0); + int fd = process->getSyscallArg(tc, 0); if (fd < 0 || process->sim_fd(fd) < 0) return -EBADF; - int cmd = tc->getSyscallArg(1); + int cmd = process->getSyscallArg(tc, 1); switch (cmd) { case 0: // F_DUPFD // if we really wanted to support this, we'd need to do it @@ -494,12 +495,12 @@ SyscallReturn fcntl64Func(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) { - int fd = tc->getSyscallArg(0); + int fd = process->getSyscallArg(tc, 0); if (fd < 0 || process->sim_fd(fd) < 0) return -EBADF; - int cmd = tc->getSyscallArg(1); + int cmd = process->getSyscallArg(tc, 1); switch (cmd) { case 33: //F_GETLK64 warn("fcntl64(%d, F_GETLK64) not supported, error returned\n", fd); @@ -583,7 +584,7 @@ setuidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { // can't fathom why a benchmark would call this. - warn("Ignoring call to setuid(%d)\n", tc->getSyscallArg(0)); + warn("Ignoring call to setuid(%d)\n", process->getSyscallArg(tc, 0)); return 0; } diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index 0e34a835e..0b0e73692 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -467,8 +467,8 @@ SyscallReturn ioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - int fd = tc->getSyscallArg(0); - unsigned req = tc->getSyscallArg(1); + int fd = process->getSyscallArg(tc, 0); + unsigned req = process->getSyscallArg(tc, 1); DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req); @@ -502,7 +502,7 @@ openFunc(SyscallDesc *desc, int callnum, LiveProcess *process, { std::string path; - if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) + if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0))) return -EFAULT; if (path == "/dev/sysdev0") { @@ -512,8 +512,8 @@ openFunc(SyscallDesc *desc, int callnum, LiveProcess *process, return -ENOENT; } - int tgtFlags = tc->getSyscallArg(1); - int mode = tc->getSyscallArg(2); + int tgtFlags = process->getSyscallArg(tc, 1); + int mode = process->getSyscallArg(tc, 2); int hostFlags = 0; // translate open flags @@ -560,10 +560,10 @@ chmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, { std::string path; - if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) + if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0))) return -EFAULT; - uint32_t mode = tc->getSyscallArg(1); + uint32_t mode = process->getSyscallArg(tc, 1); mode_t hostMode = 0; // XXX translate mode flags via OS::something??? @@ -587,13 +587,13 @@ SyscallReturn fchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - int fd = tc->getSyscallArg(0); + int fd = process->getSyscallArg(tc, 0); if (fd < 0 || process->sim_fd(fd) < 0) { // doesn't map to any simulator fd: not a valid target fd return -EBADF; } - uint32_t mode = tc->getSyscallArg(1); + uint32_t mode = process->getSyscallArg(tc, 1); mode_t hostMode = 0; // XXX translate mode flags via OS::someting??? @@ -612,10 +612,10 @@ template SyscallReturn mremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - Addr start = tc->getSyscallArg(0); - uint64_t old_length = tc->getSyscallArg(1); - uint64_t new_length = tc->getSyscallArg(2); - uint64_t flags = tc->getSyscallArg(3); + Addr start = process->getSyscallArg(tc, 0); + uint64_t old_length = process->getSyscallArg(tc, 1); + uint64_t new_length = process->getSyscallArg(tc, 2); + uint64_t flags = process->getSyscallArg(tc, 3); if ((start % TheISA::VMPageSize != 0) || (new_length % TheISA::VMPageSize != 0)) { @@ -661,7 +661,7 @@ statFunc(SyscallDesc *desc, int callnum, LiveProcess *process, { std::string path; - if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) + if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0))) return -EFAULT; // Adjust path for current working directory @@ -673,7 +673,8 @@ statFunc(SyscallDesc *desc, int callnum, LiveProcess *process, if (result < 0) return -errno; - copyOutStatBuf(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf); + copyOutStatBuf(tc->getMemPort(), process->getSyscallArg(tc, 1), + &hostBuf); return 0; } @@ -687,7 +688,7 @@ stat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, { std::string path; - if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) + if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0))) return -EFAULT; // Adjust path for current working directory @@ -704,7 +705,8 @@ stat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, if (result < 0) return -errno; - copyOutStat64Buf(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf); + copyOutStat64Buf(tc->getMemPort(), process->getSyscallArg(tc, 1), + &hostBuf); return 0; } @@ -716,7 +718,7 @@ SyscallReturn fstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - int fd = tc->getSyscallArg(0); + int fd = process->getSyscallArg(tc, 0); if (fd < 0 || process->sim_fd(fd) < 0) { // doesn't map to any simulator fd: not a valid target fd return -EBADF; @@ -733,7 +735,7 @@ fstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, if (result < 0) return -errno; - copyOutStat64Buf(tc->getMemPort(), tc->getSyscallArg(1), + copyOutStat64Buf(tc->getMemPort(), process->getSyscallArg(tc, 1), &hostBuf, (fd == 1)); return 0; @@ -748,7 +750,7 @@ lstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, { std::string path; - if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) + if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0))) return -EFAULT; // Adjust path for current working directory @@ -760,7 +762,8 @@ lstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, if (result < 0) return -errno; - copyOutStatBuf(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf); + copyOutStatBuf(tc->getMemPort(), process->getSyscallArg(tc, 1), + &hostBuf); return 0; } @@ -773,7 +776,7 @@ lstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, { std::string path; - if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) + if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0))) return -EFAULT; // Adjust path for current working directory @@ -790,7 +793,8 @@ lstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, if (result < 0) return -errno; - copyOutStat64Buf(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf); + copyOutStat64Buf(tc->getMemPort(), process->getSyscallArg(tc, 1), + &hostBuf); return 0; } @@ -801,7 +805,7 @@ SyscallReturn fstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - int fd = process->sim_fd(tc->getSyscallArg(0)); + int fd = process->sim_fd(process->getSyscallArg(tc, 0)); DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd); @@ -814,7 +818,7 @@ fstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, if (result < 0) return -errno; - copyOutStatBuf(tc->getMemPort(), tc->getSyscallArg(1), + copyOutStatBuf(tc->getMemPort(), process->getSyscallArg(tc, 1), &hostBuf, (fd == 1)); return 0; @@ -829,7 +833,7 @@ statfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, { std::string path; - if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) + if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0))) return -EFAULT; // Adjust path for current working directory @@ -842,7 +846,7 @@ statfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, return -errno; OS::copyOutStatfsBuf(tc->getMemPort(), - (Addr)(tc->getSyscallArg(1)), &hostBuf); + (Addr)(process->getSyscallArg(tc, 1)), &hostBuf); return 0; } @@ -854,7 +858,7 @@ SyscallReturn fstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - int fd = process->sim_fd(tc->getSyscallArg(0)); + int fd = process->sim_fd(process->getSyscallArg(tc, 0)); if (fd < 0) return -EBADF; @@ -865,7 +869,7 @@ fstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, if (result < 0) return -errno; - OS::copyOutStatfsBuf(tc->getMemPort(), tc->getSyscallArg(1), + OS::copyOutStatfsBuf(tc->getMemPort(), process->getSyscallArg(tc, 1), &hostBuf); return 0; @@ -878,15 +882,15 @@ SyscallReturn writevFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - int fd = tc->getSyscallArg(0); + int fd = process->getSyscallArg(tc, 0); if (fd < 0 || process->sim_fd(fd) < 0) { // doesn't map to any simulator fd: not a valid target fd return -EBADF; } TranslatingPort *p = tc->getMemPort(); - uint64_t tiov_base = tc->getSyscallArg(1); - size_t count = tc->getSyscallArg(2); + uint64_t tiov_base = process->getSyscallArg(tc, 1); + size_t count = process->getSyscallArg(tc, 2); struct iovec hiov[count]; for (int i = 0; i < count; ++i) { @@ -930,12 +934,12 @@ template SyscallReturn mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { - Addr start = tc->getSyscallArg(0); - uint64_t length = tc->getSyscallArg(1); - // int prot = tc->getSyscallArg(2); - int flags = tc->getSyscallArg(3); - // int fd = p->sim_fd(tc->getSyscallArg(4)); - // int offset = tc->getSyscallArg(5); + Addr start = p->getSyscallArg(tc, 0); + uint64_t length = p->getSyscallArg(tc, 1); + // int prot = p->getSyscallArg(tc, 2); + int flags = p->getSyscallArg(tc, 3); + // int fd = p->sim_fd(p->getSyscallArg(tc, 4)); + // int offset = p->getSyscallArg(tc, 5); if ((start % TheISA::VMPageSize) != 0 || @@ -958,7 +962,7 @@ mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) if (!(flags & OS::TGT_MAP_ANONYMOUS)) { warn("allowing mmap of file @ fd %d. " - "This will break if not /dev/zero.", tc->getSyscallArg(4)); + "This will break if not /dev/zero.", p->getSyscallArg(tc, 4)); } return start; @@ -970,8 +974,8 @@ SyscallReturn getrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - unsigned resource = tc->getSyscallArg(0); - TypedBufferArg rlp(tc->getSyscallArg(1)); + unsigned resource = process->getSyscallArg(tc, 0); + TypedBufferArg rlp(process->getSyscallArg(tc, 1)); switch (resource) { case OS::TGT_RLIMIT_STACK: @@ -1005,7 +1009,7 @@ SyscallReturn gettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - TypedBufferArg tp(tc->getSyscallArg(0)); + TypedBufferArg tp(process->getSyscallArg(tc, 0)); getElapsedTime(tp->tv_sec, tp->tv_usec); tp->tv_sec += seconds_since_epoch; @@ -1026,10 +1030,10 @@ utimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, { std::string path; - if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) + if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0))) return -EFAULT; - TypedBufferArg tp(tc->getSyscallArg(1)); + TypedBufferArg tp(process->getSyscallArg(tc, 1)); tp.copyIn(tc->getMemPort()); struct timeval hostTimeval[2]; @@ -1055,8 +1059,8 @@ SyscallReturn getrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { - int who = tc->getSyscallArg(0); // THREAD, SELF, or CHILDREN - TypedBufferArg rup(tc->getSyscallArg(1)); + int who = process->getSyscallArg(tc, 0); // THREAD, SELF, or CHILDREN + TypedBufferArg rup(process->getSyscallArg(tc, 1)); rup->ru_utime.tv_sec = 0; rup->ru_utime.tv_usec = 0; -- cgit v1.2.3 From 6ca53f8675ec0cc31de09d0878b4c29d4048a1fa Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:22:30 -0800 Subject: X86: Handle 32 bit system call arguments. --- src/arch/x86/process.cc | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index 7d7978a35..232f07934 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -116,6 +116,14 @@ static const int ArgumentReg[] = { INTREG_R9W }; static const int NumArgumentRegs = sizeof(ArgumentReg) / sizeof(const int); +static const int ArgumentReg32[] = { + INTREG_EBX, + INTREG_ECX, + INTREG_EDX, + INTREG_ESI, + INTREG_EDI, +}; +static const int NumArgumentRegs32 = sizeof(ArgumentReg) / sizeof(const int); X86LiveProcess::X86LiveProcess(LiveProcessParams * params, ObjectFile *objFile, SyscallDesc *_syscallDescs, int _numSyscallDescs) : @@ -260,6 +268,7 @@ I386LiveProcess::startup() tc->setMiscRegNoEffect(MISCREG_SEG_EFF_BASE(seg), 0); tc->setMiscRegNoEffect(MISCREG_SEG_ATTR(seg), dataAttr); tc->setMiscRegNoEffect(MISCREG_SEG_SEL(seg), 0xB); + tc->setMiscRegNoEffect(MISCREG_SEG_LIMIT(seg), (uint32_t)(-1)); } SegAttr csAttr = 0; @@ -610,11 +619,13 @@ X86_64LiveProcess::setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val) X86ISA::IntReg I386LiveProcess::getSyscallArg(ThreadContext *tc, int i) { - panic("32 bit getSyscallArg not implemented.\n"); + assert(i < NumArgumentRegs32); + return tc->readIntReg(ArgumentReg32[i]); } void I386LiveProcess::setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val) { - panic("32 bit setSyscallArg not implemented.\n"); + assert(i < NumArgumentRegs); + return tc->setIntReg(ArgumentReg[i], val); } -- cgit v1.2.3 From 14fc06640e82b0a90b737faa18d7232f8fe4c82e Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:22:50 -0800 Subject: X86: Install some 32 bit system calls. --- src/arch/x86/linux/linux.cc | 39 +++++++++++++++++++++++++++++++++++++++ src/arch/x86/linux/linux.hh | 25 +++++++++++++++++++++++++ src/arch/x86/linux/syscalls.cc | 8 ++++---- 3 files changed, 68 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/arch/x86/linux/linux.cc b/src/arch/x86/linux/linux.cc index 5e8d2de16..41855da59 100644 --- a/src/arch/x86/linux/linux.cc +++ b/src/arch/x86/linux/linux.cc @@ -97,3 +97,42 @@ const int X86Linux64::NUM_OPEN_FLAGS = sizeof(X86Linux64::openFlagTable) / sizeof(X86Linux64::openFlagTable[0]); +// open(2) flags translation table +OpenFlagTransTable X86Linux32::openFlagTable[] = { +#ifdef _MSC_VER + { TGT_O_RDONLY, _O_RDONLY }, + { TGT_O_WRONLY, _O_WRONLY }, + { TGT_O_RDWR, _O_RDWR }, + { TGT_O_APPEND, _O_APPEND }, + { TGT_O_CREAT, _O_CREAT }, + { TGT_O_TRUNC, _O_TRUNC }, + { TGT_O_EXCL, _O_EXCL }, +#ifdef _O_NONBLOCK + { TGT_O_NONBLOCK, _O_NONBLOCK }, +#endif +#ifdef _O_NOCTTY + { TGT_O_NOCTTY, _O_NOCTTY }, +#endif +#ifdef _O_SYNC + { TGT_O_SYNC, _O_SYNC }, +#endif +#else /* !_MSC_VER */ + { TGT_O_RDONLY, O_RDONLY }, + { TGT_O_WRONLY, O_WRONLY }, + { TGT_O_RDWR, O_RDWR }, + { TGT_O_APPEND, O_APPEND }, + { TGT_O_CREAT, O_CREAT }, + { TGT_O_TRUNC, O_TRUNC }, + { TGT_O_EXCL, O_EXCL }, + { TGT_O_NONBLOCK, O_NONBLOCK }, + { TGT_O_NOCTTY, O_NOCTTY }, +#ifdef O_SYNC + { TGT_O_SYNC, O_SYNC }, +#endif +#endif /* _MSC_VER */ +}; + +const int X86Linux32::NUM_OPEN_FLAGS = + sizeof(X86Linux32::openFlagTable) / + sizeof(X86Linux32::openFlagTable[0]); + diff --git a/src/arch/x86/linux/linux.hh b/src/arch/x86/linux/linux.hh index dbc336da1..c45caa19f 100644 --- a/src/arch/x86/linux/linux.hh +++ b/src/arch/x86/linux/linux.hh @@ -113,4 +113,29 @@ class X86Linux64 : public Linux } tgt_iovec; }; +class X86Linux32 : public Linux +{ + public: + + static OpenFlagTransTable openFlagTable[]; + + static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY + static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY + static const int TGT_O_RDWR = 00000002; //!< O_RDWR + static const int TGT_O_NONBLOCK = 00004000; //!< O_NONBLOCK + static const int TGT_O_APPEND = 00002000; //!< O_APPEND + static const int TGT_O_CREAT = 00000100; //!< O_CREAT + static const int TGT_O_TRUNC = 00001000; //!< O_TRUNC + static const int TGT_O_EXCL = 00000200; //!< O_EXCL + static const int TGT_O_NOCTTY = 00000400; //!< O_NOCTTY + static const int TGT_O_SYNC = 00010000; //!< O_SYNC +// static const int TGT_O_DRD = 0x00010000; //!< O_DRD +// static const int TGT_O_DIRECTIO = 0x00020000; //!< O_DIRECTIO +// static const int TGT_O_CACHE = 0x00002000; //!< O_CACHE +// static const int TGT_O_DSYNC = 0x00008000; //!< O_DSYNC +// static const int TGT_O_RSYNC = 0x00040000; //!< O_RSYNC + + static const int NUM_OPEN_FLAGS; +}; + #endif diff --git a/src/arch/x86/linux/syscalls.cc b/src/arch/x86/linux/syscalls.cc index e4e0fa234..6c44785d2 100644 --- a/src/arch/x86/linux/syscalls.cc +++ b/src/arch/x86/linux/syscalls.cc @@ -404,7 +404,7 @@ SyscallDesc I386LinuxProcess::syscallDescs[] = { /* 2 */ SyscallDesc("fork", unimplementedFunc), /* 3 */ SyscallDesc("read", unimplementedFunc), /* 4 */ SyscallDesc("write", unimplementedFunc), - /* 5 */ SyscallDesc("open", unimplementedFunc), + /* 5 */ SyscallDesc("open", openFunc), /* 6 */ SyscallDesc("close", unimplementedFunc), /* 7 */ SyscallDesc("waitpid", unimplementedFunc), /* 8 */ SyscallDesc("creat", unimplementedFunc), @@ -444,7 +444,7 @@ SyscallDesc I386LinuxProcess::syscallDescs[] = { /* 42 */ SyscallDesc("pipe", unimplementedFunc), /* 43 */ SyscallDesc("times", unimplementedFunc), /* 44 */ SyscallDesc("prof", unimplementedFunc), - /* 45 */ SyscallDesc("brk", unimplementedFunc), + /* 45 */ SyscallDesc("brk", brkFunc), /* 46 */ SyscallDesc("setgid", unimplementedFunc), /* 47 */ SyscallDesc("getgid", unimplementedFunc), /* 48 */ SyscallDesc("signal", unimplementedFunc), @@ -521,7 +521,7 @@ SyscallDesc I386LinuxProcess::syscallDescs[] = { /* 119 */ SyscallDesc("sigreturn", unimplementedFunc), /* 120 */ SyscallDesc("clone", unimplementedFunc), /* 121 */ SyscallDesc("setdomainname", unimplementedFunc), - /* 122 */ SyscallDesc("uname", unimplementedFunc), + /* 122 */ SyscallDesc("uname", unameFunc), /* 123 */ SyscallDesc("modify_ldt", unimplementedFunc), /* 124 */ SyscallDesc("adjtimex", unimplementedFunc), /* 125 */ SyscallDesc("mprotect", unimplementedFunc), @@ -545,7 +545,7 @@ SyscallDesc I386LinuxProcess::syscallDescs[] = { /* 143 */ SyscallDesc("flock", unimplementedFunc), /* 144 */ SyscallDesc("msync", unimplementedFunc), /* 145 */ SyscallDesc("readv", unimplementedFunc), - /* 146 */ SyscallDesc("writev", unimplementedFunc), + /* 146 */ SyscallDesc("writev", writevFunc), /* 147 */ SyscallDesc("getsid", unimplementedFunc), /* 148 */ SyscallDesc("fdatasync", unimplementedFunc), /* 149 */ SyscallDesc("_sysctl", unimplementedFunc), -- cgit v1.2.3 From 281ef8111a15e8501cee03fdf35e0c41437518e2 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:23:00 -0800 Subject: X86: Compute shift instruction flags correctly. --- .../general_purpose/rotate_and_shift/shift.py | 54 +++++++++++----------- 1 file changed, 27 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/rotate_and_shift/shift.py b/src/arch/x86/isa/insts/general_purpose/rotate_and_shift/shift.py index ed7d761b8..138082eb2 100644 --- a/src/arch/x86/isa/insts/general_purpose/rotate_and_shift/shift.py +++ b/src/arch/x86/isa/insts/general_purpose/rotate_and_shift/shift.py @@ -56,13 +56,13 @@ microcode = ''' def macroop SAL_R_I { - slli reg, reg, imm, flags=(SF,ZF,PF) + slli reg, reg, imm, flags=(CF,OF,SF,ZF,PF) }; def macroop SAL_M_I { ldst t1, seg, sib, disp - slli t1, t1, imm, flags=(SF,ZF,PF) + slli t1, t1, imm, flags=(CF,OF,SF,ZF,PF) st t1, seg, sib, disp }; @@ -70,19 +70,19 @@ def macroop SAL_P_I { rdip t7 ldst t1, seg, riprel, disp - slli t1, t1, imm, flags=(SF,ZF,PF) + slli t1, t1, imm, flags=(CF,OF,SF,ZF,PF) st t1, seg, riprel, disp }; def macroop SAL_1_R { - slli reg, reg, 1, flags=(SF,ZF,PF) + slli reg, reg, 1, flags=(CF,OF,SF,ZF,PF) }; def macroop SAL_1_M { ldst t1, seg, sib, disp - slli t1, t1, 1, flags=(SF,ZF,PF) + slli t1, t1, 1, flags=(CF,OF,SF,ZF,PF) st t1, seg, sib, disp }; @@ -90,19 +90,19 @@ def macroop SAL_1_P { rdip t7 ldst t1, seg, riprel, disp - slli t1, t1, 1, flags=(SF,ZF,PF) + slli t1, t1, 1, flags=(CF,OF,SF,ZF,PF) st t1, seg, riprel, disp }; def macroop SAL_R_R { - sll reg, reg, regm, flags=(SF,ZF,PF) + sll reg, reg, regm, flags=(CF,OF,SF,ZF,PF) }; def macroop SAL_M_R { ldst t1, seg, sib, disp - sll t1, t1, reg, flags=(SF,ZF,PF) + sll t1, t1, reg, flags=(CF,OF,SF,ZF,PF) st t1, seg, sib, disp }; @@ -110,19 +110,19 @@ def macroop SAL_P_R { rdip t7 ldst t1, seg, riprel, disp - sll t1, t1, reg, flags=(SF,ZF,PF) + sll t1, t1, reg, flags=(CF,OF,SF,ZF,PF) st t1, seg, riprel, disp }; def macroop SHR_R_I { - srli reg, reg, imm, flags=(SF,ZF,PF) + srli reg, reg, imm, flags=(CF,OF,SF,ZF,PF) }; def macroop SHR_M_I { ldst t1, seg, sib, disp - srli t1, t1, imm, flags=(SF,ZF,PF) + srli t1, t1, imm, flags=(CF,OF,SF,ZF,PF) st t1, seg, sib, disp }; @@ -130,19 +130,19 @@ def macroop SHR_P_I { rdip t7 ldst t1, seg, riprel, disp - srli t1, t1, imm, flags=(SF,ZF,PF) + srli t1, t1, imm, flags=(CF,OF,SF,ZF,PF) st t1, seg, riprel, disp }; def macroop SHR_1_R { - srli reg, reg, 1, flags=(SF,ZF,PF) + srli reg, reg, 1, flags=(CF,OF,SF,ZF,PF) }; def macroop SHR_1_M { ldst t1, seg, sib, disp - srli t1, t1, 1, flags=(SF,ZF,PF) + srli t1, t1, 1, flags=(CF,OF,SF,ZF,PF) st t1, seg, sib, disp }; @@ -150,19 +150,19 @@ def macroop SHR_1_P { rdip t7 ldst t1, seg, riprel, disp - srli t1, t1, 1, flags=(SF,ZF,PF) + srli t1, t1, 1, flags=(CF,OF,SF,ZF,PF) st t1, seg, riprel, disp }; def macroop SHR_R_R { - srl reg, reg, regm, flags=(SF,ZF,PF) + srl reg, reg, regm, flags=(CF,OF,SF,ZF,PF) }; def macroop SHR_M_R { ldst t1, seg, sib, disp - srl t1, t1, reg, flags=(SF,ZF,PF) + srl t1, t1, reg, flags=(CF,OF,SF,ZF,PF) st t1, seg, sib, disp }; @@ -170,19 +170,19 @@ def macroop SHR_P_R { rdip t7 ldst t1, seg, riprel, disp - srl t1, t1, reg, flags=(SF,ZF,PF) + srl t1, t1, reg, flags=(CF,OF,SF,ZF,PF) st t1, seg, riprel, disp }; def macroop SAR_R_I { - srai reg, reg, imm, flags=(SF,ZF,PF) + srai reg, reg, imm, flags=(CF,OF,SF,ZF,PF) }; def macroop SAR_M_I { ldst t1, seg, sib, disp - srai t1, t1, imm, flags=(SF,ZF,PF) + srai t1, t1, imm, flags=(CF,OF,SF,ZF,PF) st t1, seg, sib, disp }; @@ -190,19 +190,19 @@ def macroop SAR_P_I { rdip t7 ldst t1, seg, riprel, disp - srai t1, t1, imm, flags=(SF,ZF,PF) + srai t1, t1, imm, flags=(CF,OF,SF,ZF,PF) st t1, seg, riprel, disp }; def macroop SAR_1_R { - srai reg, reg, 1, flags=(SF,ZF,PF) + srai reg, reg, 1, flags=(CF,OF,SF,ZF,PF) }; def macroop SAR_1_M { ldst t1, seg, sib, disp - srai t1, t1, 1, flags=(SF,ZF,PF) + srai t1, t1, 1, flags=(CF,OF,SF,ZF,PF) st t1, seg, sib, disp }; @@ -210,19 +210,19 @@ def macroop SAR_1_P { rdip t7 ldst t1, seg, riprel, disp - srai t1, t1, 1, flags=(SF,ZF,PF) + srai t1, t1, 1, flags=(CF,OF,SF,ZF,PF) st t1, seg, riprel, disp }; def macroop SAR_R_R { - sra reg, reg, regm, flags=(SF,ZF,PF) + sra reg, reg, regm, flags=(CF,OF,SF,ZF,PF) }; def macroop SAR_M_R { ldst t1, seg, sib, disp - sra t1, t1, reg, flags=(SF,ZF,PF) + sra t1, t1, reg, flags=(CF,OF,SF,ZF,PF) st t1, seg, sib, disp }; @@ -230,7 +230,7 @@ def macroop SAR_P_R { rdip t7 ldst t1, seg, riprel, disp - sra t1, t1, reg, flags=(SF,ZF,PF) + sra t1, t1, reg, flags=(CF,OF,SF,ZF,PF) st t1, seg, riprel, disp }; ''' -- cgit v1.2.3 From e23d688d8f7e728e694f15752cd70df84bc4ae67 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:23:17 -0800 Subject: X86: Set up a space for a GDT in SE so we can set up TLS or LDT segments. --- src/arch/x86/process.cc | 18 ++++++++++++++++++ src/arch/x86/process.hh | 9 +++++++++ 2 files changed, 27 insertions(+) (limited to 'src') diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index 232f07934..22030cbfa 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -251,6 +251,20 @@ I386LiveProcess::startup() argsInit(sizeof(uint32_t), VMPageSize); + /* + * Set up a GDT for this process. The whole GDT wouldn't really be for + * this process, but the only parts we care about are. + */ + _gdtStart = stack_base; + _gdtSize = VMPageSize; + pTable->allocate(_gdtStart, _gdtSize); + uint64_t zero = 0; + assert(_gdtSize % sizeof(zero) == 0); + for (Addr gdtCurrent = _gdtStart; + gdtCurrent < _gdtStart + _gdtSize; gdtCurrent += sizeof(zero)) { + initVirtMem->write(gdtCurrent, zero); + } + for (int i = 0; i < contextIds.size(); i++) { ThreadContext * tc = system->getThreadContext(contextIds[i]); @@ -281,6 +295,10 @@ I386LiveProcess::startup() tc->setMiscRegNoEffect(MISCREG_CS_ATTR, csAttr); + tc->setMiscRegNoEffect(MISCREG_TSG_BASE, _gdtStart); + tc->setMiscRegNoEffect(MISCREG_TSG_EFF_BASE, _gdtStart); + tc->setMiscRegNoEffect(MISCREG_TSG_LIMIT, _gdtStart + _gdtSize - 1); + //Set up the registers that describe the operating mode. CR0 cr0 = 0; cr0.pg = 1; // Turn on paging. diff --git a/src/arch/x86/process.hh b/src/arch/x86/process.hh index e337e589e..2d72d3fd0 100644 --- a/src/arch/x86/process.hh +++ b/src/arch/x86/process.hh @@ -70,6 +70,9 @@ namespace X86ISA class X86LiveProcess : public LiveProcess { protected: + Addr _gdtStart; + Addr _gdtSize; + SyscallDesc *syscallDescs; const int numSyscallDescs; @@ -80,6 +83,12 @@ namespace X86ISA void argsInit(int pageSize); public: + Addr gdtStart() + { return _gdtStart; } + + Addr gdtSize() + { return _gdtSize; } + SyscallDesc* getDesc(int callnum); void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value); -- cgit v1.2.3 From 1786f200587384d595851972b2f4b9bdd70175ac Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:23:27 -0800 Subject: X86: Set an initial value for the LDT selector. --- src/arch/x86/process.cc | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index 22030cbfa..54d5d07ab 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -299,6 +299,9 @@ I386LiveProcess::startup() tc->setMiscRegNoEffect(MISCREG_TSG_EFF_BASE, _gdtStart); tc->setMiscRegNoEffect(MISCREG_TSG_LIMIT, _gdtStart + _gdtSize - 1); + // Set the LDT selector to 0 to deactivate it. + tc->setMiscRegNoEffect(MISCREG_TSL, 0); + //Set up the registers that describe the operating mode. CR0 cr0 = 0; cr0.pg = 1; // Turn on paging. -- cgit v1.2.3 From 9491debaa623aa0ed148ca4bc810f099058b67a1 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:23:42 -0800 Subject: X86: Implement the 32 bit set_thread_area system call. --- src/arch/x86/linux/syscalls.cc | 107 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 106 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/linux/syscalls.cc b/src/arch/x86/linux/syscalls.cc index 6c44785d2..eacbf5e7b 100644 --- a/src/arch/x86/linux/syscalls.cc +++ b/src/arch/x86/linux/syscalls.cc @@ -122,6 +122,111 @@ archPrctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, } } +BitUnion32(UserDescFlags) + Bitfield<0> seg_32bit; + Bitfield<2, 1> contents; + Bitfield<3> read_exec_only; + Bitfield<4> limit_in_pages; + Bitfield<5> seg_not_present; + Bitfield<6> useable; +EndBitUnion(UserDescFlags) + +struct UserDesc32 { + uint32_t entry_number; + uint32_t base_addr; + uint32_t limit; + uint32_t flags; +}; + +struct UserDesc64 { + uint32_t entry_number; + uint32_t __padding1; + uint64_t base_addr; + uint32_t limit; + uint32_t flags; +}; + +static SyscallReturn +setThreadArea32Func(SyscallDesc *desc, int callnum, + LiveProcess *process, ThreadContext *tc) +{ + const int minTLSEntry = 6; + const int numTLSEntries = 3; + const int maxTLSEntry = minTLSEntry + numTLSEntries - 1; + + X86LiveProcess *x86lp = dynamic_cast(process); + assert(x86lp); + + assert((maxTLSEntry + 1) * sizeof(uint64_t) <= x86lp->gdtSize()); + + TypedBufferArg userDesc(process->getSyscallArg(tc, 0)); + TypedBufferArg + gdt(x86lp->gdtStart() + minTLSEntry * sizeof(uint64_t), + numTLSEntries * sizeof(uint64_t)); + + if (!userDesc.copyIn(tc->getMemPort())) + return -EFAULT; + + if (!gdt.copyIn(tc->getMemPort())) + panic("Failed to copy in GDT for %s.\n", desc->name); + + if (userDesc->entry_number == (uint32_t)(-1)) { + // Find a free TLS entry. + for (int i = 0; i < numTLSEntries; i++) { + if (gdt[i] == 0) { + userDesc->entry_number = i + minTLSEntry; + break; + } + } + // We failed to find one. + if (userDesc->entry_number == (uint32_t)(-1)) + return -ESRCH; + } + + int index = userDesc->entry_number; + + if (index < minTLSEntry || index > maxTLSEntry) + return -EINVAL; + + index -= minTLSEntry; + + // Build the entry we're going to add. + SegDescriptor segDesc = 0; + UserDescFlags flags = userDesc->flags; + + segDesc.limitLow = bits(userDesc->limit, 15, 0); + segDesc.baseLow = bits(userDesc->base_addr, 23, 0); + segDesc.type.a = 1; + if (!flags.read_exec_only) + segDesc.type.w = 1; + if (bits((uint8_t)flags.contents, 0)) + segDesc.type.e = 1; + if (bits((uint8_t)flags.contents, 1)) + segDesc.type.codeOrData = 1; + segDesc.s = 1; + segDesc.dpl = 3; + if (!flags.seg_not_present) + segDesc.p = 1; + segDesc.limitHigh = bits(userDesc->limit, 19, 16); + if (flags.useable) + segDesc.avl = 1; + segDesc.l = 0; + if (flags.seg_32bit) + segDesc.d = 1; + if (flags.limit_in_pages) + segDesc.g = 1; + segDesc.baseHigh = bits(userDesc->base_addr, 31, 24); + + gdt[index] = (uint64_t)segDesc; + + if (!userDesc.copyOut(tc->getMemPort())) + return -EFAULT; + if (!gdt.copyOut(tc->getMemPort())) + panic("Failed to copy out GDT for %s.\n", desc->name); + + return 0; +} + SyscallDesc X86_64LinuxProcess::syscallDescs[] = { /* 0 */ SyscallDesc("read", readFunc), /* 1 */ SyscallDesc("write", writeFunc), @@ -642,7 +747,7 @@ SyscallDesc I386LinuxProcess::syscallDescs[] = { /* 240 */ SyscallDesc("futex", unimplementedFunc), /* 241 */ SyscallDesc("sched_setaffinity", unimplementedFunc), /* 242 */ SyscallDesc("sched_getaffinity", unimplementedFunc), - /* 243 */ SyscallDesc("set_thread_area", unimplementedFunc), + /* 243 */ SyscallDesc("set_thread_area", setThreadArea32Func), /* 244 */ SyscallDesc("get_thread_area", unimplementedFunc), /* 245 */ SyscallDesc("io_setup", unimplementedFunc), /* 246 */ SyscallDesc("io_destroy", unimplementedFunc), -- cgit v1.2.3 From 9dfa3f7f735ead0ada9eb79227f217d0d76e0f49 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:23:50 -0800 Subject: X86: Fix segment limit checks. --- src/arch/x86/insts/microldstop.hh | 3 ++- src/arch/x86/isa/microops/ldstop.isa | 4 +++- src/arch/x86/tlb.cc | 36 ++++++++++++++++-------------------- 3 files changed, 21 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/arch/x86/insts/microldstop.hh b/src/arch/x86/insts/microldstop.hh index f0051e2cf..1774454c3 100644 --- a/src/arch/x86/insts/microldstop.hh +++ b/src/arch/x86/insts/microldstop.hh @@ -67,7 +67,8 @@ namespace X86ISA static const Request::FlagsType SegmentFlagMask = mask(4); static const int FlagShift = 4; enum FlagBit { - CPL0FlagBit = 1 + CPL0FlagBit = 1, + AddrSizeFlagBit = 2 }; /** diff --git a/src/arch/x86/isa/microops/ldstop.isa b/src/arch/x86/isa/microops/ldstop.isa index 3bc238174..834b3947f 100644 --- a/src/arch/x86/isa/microops/ldstop.isa +++ b/src/arch/x86/isa/microops/ldstop.isa @@ -375,6 +375,8 @@ let {{ self.memFlags += " | (CPL0FlagBit << FlagShift)" if prefetch: self.memFlags += " | Request::PF_EXCLUSIVE" + self.memFlags += " | (machInst.legacy.addr ? " + \ + "(AddrSizeFlagBit << FlagShift) : 0)" def getAllocator(self, *microFlags): allocator = '''new %(class_name)s(machInst, macrocodeBlock @@ -439,7 +441,7 @@ let {{ defineMicroLoadOp('Ldfp', 'FpData.uqw = Mem;') def defineMicroStoreOp(mnemonic, code, \ - postCode="", completeCode="", mem_flags=0): + postCode="", completeCode="", mem_flags="0"): global header_output global decoder_output global exec_output diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index 603d4e45f..47a2eb37e 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -575,38 +575,34 @@ TLB::translate(RequestPtr req, ThreadContext *tc, if (!tc->readMiscRegNoEffect(MISCREG_SEG_SEL(seg))) return new GeneralProtection(0); bool expandDown = false; + SegAttr attr = tc->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg)); if (seg >= SEGMENT_REG_ES && seg <= SEGMENT_REG_HS) { - SegAttr attr = tc->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg)); if (!attr.writable && write) return new GeneralProtection(0); if (!attr.readable && !write && !execute) return new GeneralProtection(0); expandDown = attr.expandDown; + } Addr base = tc->readMiscRegNoEffect(MISCREG_SEG_BASE(seg)); Addr limit = tc->readMiscRegNoEffect(MISCREG_SEG_LIMIT(seg)); + // This assumes we're not in 64 bit mode. If we were, the default + // address size is 64 bits, overridable to 32. + int size = 32; + bool sizeOverride = (flags & (AddrSizeFlagBit << FlagShift)); + if (csAttr.defaultSize && sizeOverride || + !csAttr.defaultSize && !sizeOverride) + size = 16; + Addr offset = bits(vaddr - base, size-1, 0); + Addr endOffset = offset + req->getSize() - 1; if (expandDown) { DPRINTF(TLB, "Checking an expand down segment.\n"); - // We don't have to worry about the access going around the - // end of memory because accesses will be broken up into - // pieces at boundaries aligned on sizes smaller than an - // entire address space. We do have to worry about the limit - // being less than the base. - if (limit < base) { - if (limit < vaddr + req->getSize() && vaddr < base) - return new GeneralProtection(0); - } else { - if (limit < vaddr + req->getSize()) - return new GeneralProtection(0); - } + warn_once("Expand down segments are untested.\n"); + if (offset <= limit || endOffset <= limit) + return new GeneralProtection(0); } else { - if (limit < base) { - if (vaddr <= limit || vaddr + req->getSize() >= base) - return new GeneralProtection(0); - } else { - if (vaddr <= limit && vaddr + req->getSize() >= base) - return new GeneralProtection(0); - } + if (offset > limit || endOffset > limit) + return new GeneralProtection(0); } } // If paging is enabled, do the translation. -- cgit v1.2.3 From 3dfa564e70e4804ef118ba94c81233fb85f56ba2 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:23:58 -0800 Subject: X86: Respect segment override prefixes even when there's no ModRM byte. --- src/arch/x86/emulenv.cc | 8 ++++++++ src/arch/x86/emulenv.hh | 1 + src/arch/x86/isa/macroop.isa | 11 +++++++---- 3 files changed, 16 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/arch/x86/emulenv.cc b/src/arch/x86/emulenv.cc index 30ed80942..0d7b32130 100644 --- a/src/arch/x86/emulenv.cc +++ b/src/arch/x86/emulenv.cc @@ -105,3 +105,11 @@ void EmulEnv::doModRM(const ExtMachInst & machInst) } } +void EmulEnv::setSeg(const ExtMachInst & machInst) +{ + seg = SEGMENT_REG_DS; + //Handle any segment override that might have been in the instruction + int segFromInst = machInst.legacy.seg; + if (segFromInst) + seg = (SegmentRegIndex)(segFromInst - 1); +} diff --git a/src/arch/x86/emulenv.hh b/src/arch/x86/emulenv.hh index 1044dbdf9..cdb1bf863 100644 --- a/src/arch/x86/emulenv.hh +++ b/src/arch/x86/emulenv.hh @@ -86,6 +86,7 @@ namespace X86ISA {;} void doModRM(const ExtMachInst & machInst); + void setSeg(const ExtMachInst & machInst); }; }; diff --git a/src/arch/x86/isa/macroop.isa b/src/arch/x86/isa/macroop.isa index 8eaf5f786..3a836ff68 100644 --- a/src/arch/x86/isa/macroop.isa +++ b/src/arch/x86/isa/macroop.isa @@ -135,7 +135,7 @@ def template MacroConstructor {{ %(adjust_env)s; %(adjust_imm)s; %(adjust_disp)s; - %(do_modrm)s; + %(init_env)s; %(constructor)s; const char *macrocodeBlock = "%(class_name)s"; //alloc_microops is the code that sets up the microops @@ -166,7 +166,7 @@ let {{ } self.declared = False self.adjust_env = "" - self.doModRM = "" + self.init_env = "" self.adjust_imm = ''' uint64_t adjustedImm = IMMEDIATE; //This is to pacify gcc in case the immediate isn't used. @@ -228,7 +228,7 @@ let {{ "adjust_disp" : self.adjust_disp, "disassembly" : env.disassembly, "regSize" : regSize, - "do_modrm" : self.doModRM}) + "init_env" : self.initEnv}) return MacroConstructor.subst(iop) + \ MacroDisassembly.subst(iop); }}; @@ -304,6 +304,7 @@ let {{ let {{ doModRMString = "env.doModRM(machInst);\n" + noModRMString = "env.setSeg(machInst);\n" def genMacroop(Name, env): blocks = OutputBlocks() if not macroopDict.has_key(Name): @@ -311,7 +312,9 @@ let {{ macroop = macroopDict[Name] if not macroop.declared: if env.doModRM: - macroop.doModRM = doModRMString + macroop.initEnv = doModRMString + else: + macroop.initEnv = noModRMString blocks.header_output = macroop.getDeclaration() blocks.decoder_output = macroop.getDefinition(env) macroop.declared = True -- cgit v1.2.3 From 79bc1b37400ffc4aacfbf19b64aed4c7d568c941 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:24:10 -0800 Subject: X86: Fix a decoder bug and add in some missing instructions. --- src/arch/x86/isa/decoder/two_byte_opcodes.isa | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index 9c376e2c4..64920bcbd 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -829,20 +829,25 @@ 0x4: shrd_Ev_Gv_Ib(); 0x5: shrd_Ev_Gv_rCl(); //0x6: group16(); - 0x6: decode MODRM_MOD { - 0x3: decode MODRM_REG { - 0x5: BasicOperate::LFENCE( + 0x6: decode MODRM_REG { + 0x0: fxsave(); + 0x1: fxrstor(); + 0x2: ldmxcsr(); + 0x3: stmxcsr(); + 0x4: Inst::UD2(); + 0x5: decode MODRM_MOD { + 0x3: BasicOperate::LFENCE( {{/*Nothing*/}}, IsReadBarrier); - 0x6: BasicOperate::MFENCE( + default: Inst::UD2(); + } + 0x6: decode MODRM_MOD { + 0x3: BasicOperate::MFENCE( {{/*Nothing*/}}, IsMemBarrier); - 0x7: BasicOperate::SFENCE( - {{/*Nothing*/}}, IsWriteBarrier); default: Inst::UD2(); } - default: decode MODRM_REG { - 0x0: fxsave(); - 0x1: fxrstor(); - 0x7: clflush(); + 0x7: decode MODRM_MOD { + 0x3: BasicOperate::SFENCE( + {{/*Nothing*/}}, IsWriteBarrier); default: Inst::UD2(); } } -- cgit v1.2.3 From 1d18eb9043d5d2e69d3885be8dd59695ad80a92d Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:25:02 -0800 Subject: X86: Make instructions that use intseg preserve all 8 bytes of their addresses. --- src/arch/x86/isa/insts/general_purpose/input_output/general_io.py | 8 ++++---- src/arch/x86/isa/insts/system/msrs.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/input_output/general_io.py b/src/arch/x86/isa/insts/general_purpose/input_output/general_io.py index 924bfcb6e..4e3c9b316 100644 --- a/src/arch/x86/isa/insts/general_purpose/input_output/general_io.py +++ b/src/arch/x86/isa/insts/general_purpose/input_output/general_io.py @@ -85,22 +85,22 @@ microcode = ''' def macroop IN_R_I { .adjust_imm trimImm(8) limm t1, imm, dataSize=asz - ld reg, intseg, [1, t1, t0], "IntAddrPrefixIO << 3", addressSize=4 + ld reg, intseg, [1, t1, t0], "IntAddrPrefixIO << 3", addressSize=8 }; def macroop IN_R_R { zexti t2, regm, 15, dataSize=8 - ld reg, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=4 + ld reg, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8 }; def macroop OUT_I_R { .adjust_imm trimImm(8) limm t1, imm, dataSize=8 - st reg, intseg, [1, t1, t0], "IntAddrPrefixIO << 3", addressSize=4 + st reg, intseg, [1, t1, t0], "IntAddrPrefixIO << 3", addressSize=8 }; def macroop OUT_R_R { zexti t2, reg, 15, dataSize=8 - st regm, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=4 + st regm, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8 }; ''' diff --git a/src/arch/x86/isa/insts/system/msrs.py b/src/arch/x86/isa/insts/system/msrs.py index f3c867398..7f283c8c1 100644 --- a/src/arch/x86/isa/insts/system/msrs.py +++ b/src/arch/x86/isa/insts/system/msrs.py @@ -85,7 +85,7 @@ microcode = ''' def macroop RDMSR { ld t2, intseg, [8, rcx, t0], "IntAddrPrefixMSR << 3", \ - dataSize=8, addressSize=4 + dataSize=8, addressSize=8 mov rax, rax, t2, dataSize=4 srli t2, t2, 32, dataSize=8 mov rdx, rdx, t2, dataSize=4 @@ -97,7 +97,7 @@ def macroop WRMSR slli t3, rdx, 32, dataSize=8 or t2, t2, t3, dataSize=8 st t2, intseg, [8, rcx, t0], "IntAddrPrefixMSR << 3", \ - dataSize=8, addressSize=4 + dataSize=8, addressSize=8 }; def macroop RDTSC -- cgit v1.2.3 From 8a1eb7e8bec41d41daf3e35b30a11e04f6285f66 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:25:16 -0800 Subject: X86: Take address size into account when computing an effective address. --- src/arch/x86/isa/microops/ldstop.isa | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/isa/microops/ldstop.isa b/src/arch/x86/isa/microops/ldstop.isa index 834b3947f..af94cf31e 100644 --- a/src/arch/x86/isa/microops/ldstop.isa +++ b/src/arch/x86/isa/microops/ldstop.isa @@ -402,7 +402,9 @@ let {{ decoder_output = "" exec_output = "" - calculateEA = "EA = SegBase + scale * Index + Base + disp;" + calculateEA = ''' + EA = bits(SegBase + scale * Index + Base + disp, addressSize * 8 - 1, 0); + ''' def defineMicroLoadOp(mnemonic, code, mem_flags="0"): global header_output -- cgit v1.2.3 From 04dbed79f8c9b3069644f60b7b1087df392edd59 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:25:26 -0800 Subject: X86: Install a 32 bit fstat64 system call. --- src/arch/x86/linux/syscalls.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/linux/syscalls.cc b/src/arch/x86/linux/syscalls.cc index eacbf5e7b..1d2d8d691 100644 --- a/src/arch/x86/linux/syscalls.cc +++ b/src/arch/x86/linux/syscalls.cc @@ -701,7 +701,7 @@ SyscallDesc I386LinuxProcess::syscallDescs[] = { /* 194 */ SyscallDesc("ftruncate64", unimplementedFunc), /* 195 */ SyscallDesc("stat64", unimplementedFunc), /* 196 */ SyscallDesc("lstat64", unimplementedFunc), - /* 197 */ SyscallDesc("fstat64", unimplementedFunc), + /* 197 */ SyscallDesc("fstat64", fstat64Func), /* 198 */ SyscallDesc("lchown32", unimplementedFunc), /* 199 */ SyscallDesc("getuid32", unimplementedFunc), /* 200 */ SyscallDesc("getgid32", unimplementedFunc), -- cgit v1.2.3 From 5c1cc99d486870bb6942980474b535ec0917f85c Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:25:33 -0800 Subject: X86: Add a 32 bit mmap2 system call. --- src/arch/x86/linux/linux.hh | 2 ++ src/arch/x86/linux/syscalls.cc | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/linux/linux.hh b/src/arch/x86/linux/linux.hh index c45caa19f..c6fe28318 100644 --- a/src/arch/x86/linux/linux.hh +++ b/src/arch/x86/linux/linux.hh @@ -136,6 +136,8 @@ class X86Linux32 : public Linux // static const int TGT_O_RSYNC = 0x00040000; //!< O_RSYNC static const int NUM_OPEN_FLAGS; + + static const unsigned TGT_MAP_ANONYMOUS = 0x20; }; #endif diff --git a/src/arch/x86/linux/syscalls.cc b/src/arch/x86/linux/syscalls.cc index 1d2d8d691..7969f2e41 100644 --- a/src/arch/x86/linux/syscalls.cc +++ b/src/arch/x86/linux/syscalls.cc @@ -696,7 +696,7 @@ SyscallDesc I386LinuxProcess::syscallDescs[] = { /* 189 */ SyscallDesc("putpmsg", unimplementedFunc), /* 190 */ SyscallDesc("vfork", unimplementedFunc), /* 191 */ SyscallDesc("ugetrlimit", unimplementedFunc), - /* 192 */ SyscallDesc("mmap2", unimplementedFunc), + /* 192 */ SyscallDesc("mmap2", mmapFunc), /* 193 */ SyscallDesc("truncate64", unimplementedFunc), /* 194 */ SyscallDesc("ftruncate64", unimplementedFunc), /* 195 */ SyscallDesc("stat64", unimplementedFunc), -- cgit v1.2.3 From c3d7d7ed0e3931d549a14ef8b32a1619861f3ef0 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:25:43 -0800 Subject: X86: Implement sysenter as a system call interface. --- src/arch/x86/isa/decoder/two_byte_opcodes.isa | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index 64920bcbd..c3fb5c19d 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -420,7 +420,11 @@ 0x1: Inst::RDTSC(); 0x2: Inst::RDMSR(); 0x3: rdpmc(); +#if FULL_SYSTEM 0x4: sysenter(); +#else + 0x4: SyscallInst::sysenter('xc->syscall(Rax)', IsSyscall); +#endif 0x5: sysexit(); 0x6: Inst::UD2(); 0x7: getsec(); -- cgit v1.2.3 From db3c51d3a02864594c23f25b9e18825327703643 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:25:51 -0800 Subject: X86: Add a vsyscall page for 32 bit processes to use. --- src/arch/x86/process.cc | 60 +++++++++++++++++++++++++++++++++++++++++++------ src/arch/x86/process.hh | 14 +++++++++++- 2 files changed, 66 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index 54d5d07ab..4a61ed168 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -152,12 +152,32 @@ X86_64LiveProcess::X86_64LiveProcess(LiveProcessParams *params, mmap_start = mmap_end = (Addr)0x2aaaaaaab000ULL; } +void +I386LiveProcess::syscall(int64_t callnum, ThreadContext *tc) +{ + Addr eip = tc->readPC(); + if (eip >= vsyscallPage.base && + eip < vsyscallPage.base + vsyscallPage.size) { + tc->setNextPC(vsyscallPage.base + vsyscallPage.vsysexitOffset); + } + X86LiveProcess::syscall(callnum, tc); +} + + I386LiveProcess::I386LiveProcess(LiveProcessParams *params, ObjectFile *objFile, SyscallDesc *_syscallDescs, int _numSyscallDescs) : X86LiveProcess(params, objFile, _syscallDescs, _numSyscallDescs) { - stack_base = (Addr)0xffffe000ULL; + _gdtStart = 0x100000000; + _gdtSize = VMPageSize; + + vsyscallPage.base = 0xffffe000ULL; + vsyscallPage.size = VMPageSize; + vsyscallPage.vsyscallOffset = 0x400; + vsyscallPage.vsysexitOffset = 0x410; + + stack_base = vsyscallPage.base; // Set pointer for next thread stack. Reserve 8M for main stack. next_thread_stack_base = stack_base - (8 * 1024 * 1024); @@ -255,8 +275,6 @@ I386LiveProcess::startup() * Set up a GDT for this process. The whole GDT wouldn't really be for * this process, but the only parts we care about are. */ - _gdtStart = stack_base; - _gdtSize = VMPageSize; pTable->allocate(_gdtStart, _gdtSize); uint64_t zero = 0; assert(_gdtSize % sizeof(zero) == 0); @@ -265,6 +283,27 @@ I386LiveProcess::startup() initVirtMem->write(gdtCurrent, zero); } + // Set up the vsyscall page for this process. + pTable->allocate(vsyscallPage.base, vsyscallPage.size); + uint8_t vsyscallBlob[] = { + 0x51, // push %ecx + 0x52, // push %edp + 0x55, // push %ebp + 0x89, 0xe5, // mov %esp, %ebp + 0x0f, 0x34 // sysenter + }; + initVirtMem->writeBlob(vsyscallPage.base + vsyscallPage.vsyscallOffset, + vsyscallBlob, sizeof(vsyscallBlob)); + + uint8_t vsysexitBlob[] = { + 0x5d, // pop %ebp + 0x5a, // pop %edx + 0x59, // pop %ecx + 0xc3 // ret + }; + initVirtMem->writeBlob(vsyscallPage.base + vsyscallPage.vsysexitOffset, + vsysexitBlob, sizeof(vsysexitBlob)); + for (int i = 0; i < contextIds.size(); i++) { ThreadContext * tc = system->getThreadContext(contextIds[i]); @@ -332,12 +371,13 @@ I386LiveProcess::startup() template void -X86LiveProcess::argsInit(int pageSize) +X86LiveProcess::argsInit(int pageSize, + std::vector > extraAuxvs) { int intSize = sizeof(IntType); typedef AuxVector auxv_t; - std::vector auxv; + std::vector auxv = extraAuxvs; string filename; if(argv.size() < 1) @@ -608,13 +648,19 @@ X86LiveProcess::argsInit(int pageSize) void X86_64LiveProcess::argsInit(int intSize, int pageSize) { - X86LiveProcess::argsInit(pageSize); + std::vector > extraAuxvs; + X86LiveProcess::argsInit(pageSize, extraAuxvs); } void I386LiveProcess::argsInit(int intSize, int pageSize) { - X86LiveProcess::argsInit(pageSize); + std::vector > extraAuxvs; + //Tell the binary where the vsyscall part of the vsyscall page is. + extraAuxvs.push_back(AuxVector(0x20, + vsyscallPage.base + vsyscallPage.vsyscallOffset)); + extraAuxvs.push_back(AuxVector(0x21, vsyscallPage.base)); + X86LiveProcess::argsInit(pageSize, extraAuxvs); } void diff --git a/src/arch/x86/process.hh b/src/arch/x86/process.hh index 2d72d3fd0..cd6d99e66 100644 --- a/src/arch/x86/process.hh +++ b/src/arch/x86/process.hh @@ -80,7 +80,8 @@ namespace X86ISA SyscallDesc *_syscallDescs, int _numSyscallDescs); template - void argsInit(int pageSize); + void argsInit(int pageSize, + std::vector > extraAuxvs); public: Addr gdtStart() @@ -114,10 +115,21 @@ namespace X86ISA I386LiveProcess(LiveProcessParams *params, ObjectFile *objFile, SyscallDesc *_syscallDescs, int _numSyscallDescs); + class VSyscallPage + { + public: + Addr base; + Addr size; + Addr vsyscallOffset; + Addr vsysexitOffset; + }; + VSyscallPage vsyscallPage; + public: void argsInit(int intSize, int pageSize); void startup(); + void syscall(int64_t callnum, ThreadContext *tc); X86ISA::IntReg getSyscallArg(ThreadContext *tc, int i); void setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val); }; -- cgit v1.2.3 From aa51c01d697124fac654b3e87a99bb2d613cae72 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:26:01 -0800 Subject: X86: Set address size to 64 bits when generating addresses internally. --- .../insts/general_purpose/data_transfer/move.py | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py index dded94968..60c046d04 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py +++ b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py @@ -251,10 +251,10 @@ def macroop MOV_S_R { andi t2, regm, 0xF8, dataSize=8 andi t0, regm, 0x4, flags=(EZF,), dataSize=2 br label("globalDescriptor"), flags=(CEZF,) - ld t3, tsl, [1, t0, t2], dataSize=8 + ld t3, tsl, [1, t0, t2], dataSize=8, addressSize=8 br label("processDescriptor") globalDescriptor: - ld t3, tsg, [1, t0, t2], dataSize=8 + ld t3, tsg, [1, t0, t2], dataSize=8, addressSize=8 processDescriptor: chks regm, t3, dataSize=8 wrdl reg, t3, regm @@ -268,10 +268,10 @@ def macroop MOV_S_M { andi t2, t1, 0xF8, dataSize=8 andi t0, t1, 0x4, flags=(EZF,), dataSize=2 br label("globalDescriptor"), flags=(CEZF,) - ld t3, tsl, [1, t0, t2], dataSize=8 + ld t3, tsl, [1, t0, t2], dataSize=8, addressSize=8 br label("processDescriptor") globalDescriptor: - ld t3, tsg, [1, t0, t2], dataSize=8 + ld t3, tsg, [1, t0, t2], dataSize=8, addressSize=8 processDescriptor: chks t1, t3, dataSize=8 wrdl reg, t3, t1 @@ -286,10 +286,10 @@ def macroop MOV_S_P { andi t2, t1, 0xF8, dataSize=8 andi t0, t1, 0x4, flags=(EZF,), dataSize=2 br label("globalDescriptor"), flags=(CEZF,) - ld t3, tsl, [1, t0, t2], dataSize=8 + ld t3, tsl, [1, t0, t2], dataSize=8, addressSize=8 br label("processDescriptor") globalDescriptor: - ld t3, tsg, [1, t0, t2], dataSize=8 + ld t3, tsg, [1, t0, t2], dataSize=8, addressSize=8 processDescriptor: chks t1, t3, dataSize=8 wrdl reg, t3, t1 @@ -302,10 +302,10 @@ def macroop MOVSS_S_R { andi t2, regm, 0xF8, dataSize=8 andi t0, regm, 0x4, flags=(EZF,), dataSize=2 br label("globalDescriptor"), flags=(CEZF,) - ld t3, tsl, [1, t0, t2], dataSize=8 + ld t3, tsl, [1, t0, t2], dataSize=8, addressSize=8 br label("processDescriptor") globalDescriptor: - ld t3, tsg, [1, t0, t2], dataSize=8 + ld t3, tsg, [1, t0, t2], dataSize=8, addressSize=8 processDescriptor: chks regm, t3, SSCheck, dataSize=8 wrdl reg, t3, regm @@ -319,10 +319,10 @@ def macroop MOVSS_S_M { andi t2, t1, 0xF8, dataSize=8 andi t0, t1, 0x4, flags=(EZF,), dataSize=2 br label("globalDescriptor"), flags=(CEZF,) - ld t3, tsl, [1, t0, t2], dataSize=8 + ld t3, tsl, [1, t0, t2], dataSize=8, addressSize=8 br label("processDescriptor") globalDescriptor: - ld t3, tsg, [1, t0, t2], dataSize=8 + ld t3, tsg, [1, t0, t2], dataSize=8, addressSize=8 processDescriptor: chks t1, t3, SSCheck, dataSize=8 wrdl reg, t3, t1 @@ -337,10 +337,10 @@ def macroop MOVSS_S_P { andi t2, t1, 0xF8, dataSize=8 andi t0, t1, 0x4, flags=(EZF,), dataSize=2 br label("globalDescriptor"), flags=(CEZF,) - ld t3, tsl, [1, t0, t2], dataSize=8 + ld t3, tsl, [1, t0, t2], dataSize=8, addressSize=8 br label("processDescriptor") globalDescriptor: - ld t3, tsg, [1, t0, t2], dataSize=8 + ld t3, tsg, [1, t0, t2], dataSize=8, addressSize=8 processDescriptor: chks t1, t3, SSCheck, dataSize=8 wrdl reg, t3, t1 -- cgit v1.2.3 From 27b751ec46e59166867cedbf6da3ee19453671bd Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:26:09 -0800 Subject: X86: Don't treat the REX prefixes as prefixes in 32 bit modes. These are inc/dec instructions. --- src/arch/x86/predecoder.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/predecoder.cc b/src/arch/x86/predecoder.cc index 9d60089e3..620ab89ea 100644 --- a/src/arch/x86/predecoder.cc +++ b/src/arch/x86/predecoder.cc @@ -136,7 +136,10 @@ namespace X86ISA { uint8_t prefix = Prefixes[nextByte]; State nextState = PrefixState; - if(prefix) + // REX prefixes are only recognized in 64 bit mode. + if (prefix == RexPrefix && emi.mode.submode != SixtyFourBitMode) + prefix = 0; + if (prefix) consumeByte(); switch(prefix) { -- cgit v1.2.3 From 2fe87e62ba2bf51dfc773dd6fdb2bd1fdb09e20b Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:26:17 -0800 Subject: X86: Add a structure to allow mapping between the host and guest fstat formats. --- src/arch/x86/linux/linux.hh | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'src') diff --git a/src/arch/x86/linux/linux.hh b/src/arch/x86/linux/linux.hh index c6fe28318..c2941c769 100644 --- a/src/arch/x86/linux/linux.hh +++ b/src/arch/x86/linux/linux.hh @@ -117,6 +117,28 @@ class X86Linux32 : public Linux { public: + typedef struct { + uint64_t st_dev; + uint8_t __pad0[4]; + uint32_t __st_ino; + uint32_t st_mode; + uint32_t st_nlink; + uint32_t st_uid; + uint32_t st_gid; + uint64_t st_rdev; + int64_t st_size; + uint8_t __pad3[4]; + uint32_t st_blksize; + uint64_t st_blocks; + uint32_t st_atimeX; + uint32_t st_atime_nsec; + uint32_t st_mtimeX; + uint32_t st_mtime_nsec; + uint32_t st_ctimeX; + uint32_t st_ctime_nsec; + uint64_t st_ino; + } tgt_stat64; + static OpenFlagTransTable openFlagTable[]; static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY -- cgit v1.2.3 From b36f28472d4e28263f4d2e3f6b3e88c9fa350ca1 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:26:26 -0800 Subject: X86: Implement shrd. --- src/arch/x86/isa/decoder/two_byte_opcodes.isa | 2 +- .../general_purpose/rotate_and_shift/shift.py | 35 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index c3fb5c19d..1ee62142a 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -830,7 +830,7 @@ 0x1: pop_gs(); 0x2: rsm_smm(); 0x3: Inst::BTS(Ev,Gv); - 0x4: shrd_Ev_Gv_Ib(); + 0x4: Inst::SHRD(Ev,Gv,Ib); 0x5: shrd_Ev_Gv_rCl(); //0x6: group16(); 0x6: decode MODRM_REG { diff --git a/src/arch/x86/isa/insts/general_purpose/rotate_and_shift/shift.py b/src/arch/x86/isa/insts/general_purpose/rotate_and_shift/shift.py index 138082eb2..caaeca974 100644 --- a/src/arch/x86/isa/insts/general_purpose/rotate_and_shift/shift.py +++ b/src/arch/x86/isa/insts/general_purpose/rotate_and_shift/shift.py @@ -174,6 +174,41 @@ def macroop SHR_P_R st t1, seg, riprel, disp }; +# SHRD will not set OF correctly when the shift count is 1. +def macroop SHRD_R_R_I +{ + srli t1, reg, imm, flags=(CF,) + rori t2, regm, imm + srli t3, regm, imm + xor t2, t2, t3 + or reg, t1, t2 +}; + +# SHRD will not set OF correctly when the shift count is 1. +def macroop SHRD_M_R_I +{ + ldst t1, seg, sib, disp + srli t1, t1, imm, flags=(CF,) + rori t2, reg, imm + srli t3, reg, imm + xor t2, t2, t3 + or t1, t1, t2 + st t1, seg, sib, disp +}; + +# SHRD will not set OF correctly when the shift count is 1. +def macroop SHRD_P_R_I +{ + rdip t7 + ldst t1, seg, riprel, disp + srli t1, t1, imm, flags=(CF,) + rori t2, reg, imm + srli t3, reg, imm + xor t2, t2, t3 + or t1, t1, t2 + st t1, seg, riprel, disp +}; + def macroop SAR_R_I { srai reg, reg, imm, flags=(CF,OF,SF,ZF,PF) -- cgit v1.2.3 From 9265b3d598b5c394ed3f0f79affba7e64b171dc6 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:26:32 -0800 Subject: X86: Install the 32 bit write system call. --- src/arch/x86/linux/syscalls.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/linux/syscalls.cc b/src/arch/x86/linux/syscalls.cc index 7969f2e41..ce4726634 100644 --- a/src/arch/x86/linux/syscalls.cc +++ b/src/arch/x86/linux/syscalls.cc @@ -508,7 +508,7 @@ SyscallDesc I386LinuxProcess::syscallDescs[] = { /* 1 */ SyscallDesc("exit", unimplementedFunc), /* 2 */ SyscallDesc("fork", unimplementedFunc), /* 3 */ SyscallDesc("read", unimplementedFunc), - /* 4 */ SyscallDesc("write", unimplementedFunc), + /* 4 */ SyscallDesc("write", writeFunc), /* 5 */ SyscallDesc("open", openFunc), /* 6 */ SyscallDesc("close", unimplementedFunc), /* 7 */ SyscallDesc("waitpid", unimplementedFunc), -- cgit v1.2.3 From b69a9ad45a15e84a6422f308df5b6806da80e93a Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Feb 2009 09:26:41 -0800 Subject: X86: Install the exit system call. --- src/arch/x86/linux/syscalls.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/arch/x86/linux/syscalls.cc b/src/arch/x86/linux/syscalls.cc index ce4726634..09235ec94 100644 --- a/src/arch/x86/linux/syscalls.cc +++ b/src/arch/x86/linux/syscalls.cc @@ -756,7 +756,7 @@ SyscallDesc I386LinuxProcess::syscallDescs[] = { /* 249 */ SyscallDesc("io_cancel", unimplementedFunc), /* 250 */ SyscallDesc("fadvise64", unimplementedFunc), /* 251 */ SyscallDesc("unused", unimplementedFunc), - /* 252 */ SyscallDesc("exit_group", unimplementedFunc), + /* 252 */ SyscallDesc("exit_group", exitFunc), /* 253 */ SyscallDesc("lookup_dcookie", unimplementedFunc), /* 254 */ SyscallDesc("epoll_create", unimplementedFunc), /* 255 */ SyscallDesc("epoll_ctl", unimplementedFunc), -- cgit v1.2.3 From 4523741c1c72ef954410ccb0aa7782b28be3441b Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 27 Feb 2009 17:29:58 -0800 Subject: quell gcc 4.3 warning --- src/arch/x86/tlb.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index 47a2eb37e..3fec4c7da 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -590,8 +590,8 @@ TLB::translate(RequestPtr req, ThreadContext *tc, // address size is 64 bits, overridable to 32. int size = 32; bool sizeOverride = (flags & (AddrSizeFlagBit << FlagShift)); - if (csAttr.defaultSize && sizeOverride || - !csAttr.defaultSize && !sizeOverride) + if ((csAttr.defaultSize && sizeOverride) || + (!csAttr.defaultSize && !sizeOverride)) size = 16; Addr offset = bits(vaddr - base, size-1, 0); Addr endOffset = offset + req->getSize() - 1; @@ -647,8 +647,8 @@ TLB::translate(RequestPtr req, ThreadContext *tc, // Do paging protection checks. bool inUser = (csAttr.dpl == 3 && !(flags & (CPL0FlagBit << FlagShift))); - if (inUser && !entry->user || - write && !entry->writable) { + if ((inUser && !entry->user) || + (write && !entry->writable)) { // The page must have been present to get into the TLB in // the first place. We'll assume the reserved bits are // fine even though we're not checking them. -- cgit v1.2.3 From 307905095caaa277e8ccbd58f095381d79b0c402 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Sat, 28 Feb 2009 20:14:22 -0500 Subject: Fix Num_Syscall_Descs check bug in non-x86 ISAs. (See cset d35d2b28df38 for x86 fix.) --- src/arch/alpha/linux/process.cc | 2 +- src/arch/mips/linux/process.cc | 2 +- src/arch/sparc/linux/process.cc | 4 ++-- src/arch/sparc/solaris/process.cc | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/linux/process.cc b/src/arch/alpha/linux/process.cc index 1e4f75790..aeff9fbed 100644 --- a/src/arch/alpha/linux/process.cc +++ b/src/arch/alpha/linux/process.cc @@ -579,7 +579,7 @@ AlphaLinuxProcess::AlphaLinuxProcess(LiveProcessParams * params, SyscallDesc* AlphaLinuxProcess::getDesc(int callnum) { - if (callnum < 0 || callnum > Num_Syscall_Descs) + if (callnum < 0 || callnum >= Num_Syscall_Descs) return NULL; return &syscallDescs[callnum]; } diff --git a/src/arch/mips/linux/process.cc b/src/arch/mips/linux/process.cc index dc3b84ced..24e71305a 100644 --- a/src/arch/mips/linux/process.cc +++ b/src/arch/mips/linux/process.cc @@ -425,7 +425,7 @@ MipsLinuxProcess::getDesc(int callnum) //MIPS32 syscalls are in the range of 4000 - 4999 int m5_sys_idx = callnum - 4000; - if (m5_sys_idx < 0 || m5_sys_idx > Num_Syscall_Descs) + if (m5_sys_idx < 0 || m5_sys_idx >= Num_Syscall_Descs) return NULL; return &syscallDescs[m5_sys_idx]; diff --git a/src/arch/sparc/linux/process.cc b/src/arch/sparc/linux/process.cc index f4ec28c00..2078c1dce 100644 --- a/src/arch/sparc/linux/process.cc +++ b/src/arch/sparc/linux/process.cc @@ -47,7 +47,7 @@ using namespace SparcISA; SyscallDesc* SparcLinuxProcess::getDesc(int callnum) { - if (callnum < 0 || callnum > Num_Syscall_Descs) + if (callnum < 0 || callnum >= Num_Syscall_Descs) return NULL; return &syscallDescs[callnum]; } @@ -55,7 +55,7 @@ SparcLinuxProcess::getDesc(int callnum) SyscallDesc* SparcLinuxProcess::getDesc32(int callnum) { - if (callnum < 0 || callnum > Num_Syscall32_Descs) + if (callnum < 0 || callnum >= Num_Syscall32_Descs) return NULL; return &syscall32Descs[callnum]; } diff --git a/src/arch/sparc/solaris/process.cc b/src/arch/sparc/solaris/process.cc index 1a4940b59..22924736b 100644 --- a/src/arch/sparc/solaris/process.cc +++ b/src/arch/sparc/solaris/process.cc @@ -336,7 +336,7 @@ SparcSolarisProcess::SparcSolarisProcess(LiveProcessParams * params, SyscallDesc* SparcSolarisProcess::getDesc(int callnum) { - if (callnum < 0 || callnum > Num_Syscall_Descs) + if (callnum < 0 || callnum >= Num_Syscall_Descs) return NULL; return &syscallDescs[callnum]; } -- cgit v1.2.3 From 9ee8e685a46ccd5314b93fec178cd73957c5b406 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Wed, 4 Mar 2009 09:25:53 -0500 Subject: O3: Make numThreads error message more helpful. --- src/cpu/o3/fetch_impl.hh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 06df46c2b..79a4f2b7a 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -132,7 +132,9 @@ DefaultFetch::DefaultFetch(O3CPU *_cpu, DerivO3CPUParams *params) switchedOut(false) { if (numThreads > Impl::MaxThreads) - fatal("numThreads is not a valid value\n"); + fatal("numThreads (%d) is larger than compiled limit (%d),\n" + "\tincrease MaxThreads in src/cpu/o3/impl.hh\n", + numThreads, static_cast(Impl::MaxThreads)); // Set fetch stage's status to inactive. _status = Inactive; -- cgit v1.2.3 From e4aa4ca40c0a5ab5946914cc997e0a9bd288c861 Mon Sep 17 00:00:00 2001 From: Korey Sewell Date: Wed, 4 Mar 2009 13:16:48 -0500 Subject: use numCycles instead of simTicks to determine CPI stat in InOrder --- src/cpu/inorder/cpu.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc index c22dd1154..94a6efce9 100644 --- a/src/cpu/inorder/cpu.cc +++ b/src/cpu/inorder/cpu.cc @@ -355,7 +355,7 @@ InOrderCPU::regStats() .name(name() + ".cpi_total") .desc("CPI: Total CPI of All Threads") .precision(6); - totalCpi = simTicks / totalCommittedInsts; + totalCpi = numCycles / totalCommittedInsts; ipc .name(name() + ".ipc") @@ -373,7 +373,7 @@ InOrderCPU::regStats() .name(name() + ".ipc_total") .desc("IPC: Total IPC of All Threads") .precision(6); - totalIpc = totalCommittedInsts / simTicks; + totalIpc = totalCommittedInsts / numCycles; BaseCPU::regStats(); } -- cgit v1.2.3 From 846f953c2bc8f9922afe62c30e60f9b5b531d09e Mon Sep 17 00:00:00 2001 From: Korey Sewell Date: Wed, 4 Mar 2009 13:16:49 -0500 Subject: Give TimeBuffer an ID that can be set. Necessary because InOrder uses generic stages so w/o an ID there is no way to differentiate buffers when debugging --- src/base/timebuf.hh | 13 +++++++++++++ src/cpu/inorder/cpu.cc | 4 +--- src/cpu/inorder/pipeline_stage.cc | 9 +++++---- 3 files changed, 19 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/base/timebuf.hh b/src/base/timebuf.hh index 348f7a673..9f9fc32b5 100644 --- a/src/base/timebuf.hh +++ b/src/base/timebuf.hh @@ -43,6 +43,7 @@ class TimeBuffer int past; int future; int size; + int _id; char *data; std::vector index; @@ -148,6 +149,8 @@ class TimeBuffer new (ptr) T; ptr += sizeof(T); } + + _id = -1; } TimeBuffer() @@ -162,6 +165,16 @@ class TimeBuffer delete [] data; } + void id(int id) + { + _id = id; + } + + int id() + { + return _id; + } + void advance() { diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc index 94a6efce9..1836989af 100644 --- a/src/cpu/inorder/cpu.cc +++ b/src/cpu/inorder/cpu.cc @@ -230,11 +230,9 @@ InOrderCPU::InOrderCPU(Params *params) } // Initialize TimeBuffer Stage Queues - // For now just have these time buffers be pretty big. - // @note: This could be statically allocated but changes - // would have to be made to the standard time buffer class. for (int stNum=0; stNum < NumStages - 1; stNum++) { stageQueue[stNum] = new StageQueue(NumStages, NumStages); + stageQueue[stNum]->id(stNum); } diff --git a/src/cpu/inorder/pipeline_stage.cc b/src/cpu/inorder/pipeline_stage.cc index 547b42537..f356c0e1a 100644 --- a/src/cpu/inorder/pipeline_stage.cc +++ b/src/cpu/inorder/pipeline_stage.cc @@ -556,8 +556,8 @@ PipelineStage::sortInsts() if (prevStageValid) { int insts_from_prev_stage = prevStage->size; - DPRINTF(InOrderStage, "%i insts available from previous stage.\n", - insts_from_prev_stage); + DPRINTF(InOrderStage, "%i insts available from stage buffer %i.\n", + insts_from_prev_stage, prevStageQueue->id()); for (int i = 0; i < insts_from_prev_stage; ++i) { @@ -985,8 +985,9 @@ PipelineStage::sendInstToNextStage(DynInstPtr inst) tid, cpu->pipelineStage[next_stage]->stageBufferAvail()); DPRINTF(InOrderStage, "[tid:%u]: [sn:%i]: being placed into " - "index %i stage %i queue.\n", - tid, inst->seqNum, toNextStageIndex, inst->nextStage); + "index %i of stage buffer %i queue.\n", + tid, inst->seqNum, toNextStageIndex, + cpu->pipelineStage[prev_stage]->nextStageQueue->id()); int next_stage_idx = cpu->pipelineStage[prev_stage]->nextStage->size; -- cgit v1.2.3 From f98e9161a83cd9bafbe7e5612db344a8b5cb2ae1 Mon Sep 17 00:00:00 2001 From: Korey Sewell Date: Wed, 4 Mar 2009 13:17:05 -0500 Subject: InOrder didnt have all it's params set to a default value, which is now required for M5 objects; Also, a # of values need to be reset to 0 (or the appropriate value) before we assume they are OK for use. --- src/cpu/inorder/InOrderCPU.py | 5 ++--- src/cpu/inorder/comm.hh | 8 ++++++++ src/cpu/inorder/inorder_dyn_inst.cc | 5 ++++- src/cpu/inorder/pipeline_stage.cc | 32 +++++------------------------- src/cpu/inorder/resources/mult_div_unit.cc | 5 +++++ 5 files changed, 24 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/cpu/inorder/InOrderCPU.py b/src/cpu/inorder/InOrderCPU.py index a5e81a090..9faadc68c 100644 --- a/src/cpu/inorder/InOrderCPU.py +++ b/src/cpu/inorder/InOrderCPU.py @@ -34,9 +34,8 @@ from BaseCPU import BaseCPU class InOrderCPU(BaseCPU): type = 'InOrderCPU' activity = Param.Unsigned(0, "Initial count") - numThreads = Param.Unsigned(1, "number of HW thread contexts") - cachePorts = Param.Unsigned("Cache Ports") + cachePorts = Param.Unsigned(2, "Cache Ports") stageWidth = Param.Unsigned(1, "Stage width") fetchMemPort = Param.String("icache_port" , "Name of Memory Port to get instructions from") @@ -66,7 +65,7 @@ class InOrderCPU(BaseCPU): functionTraceStart = Param.Tick(0, "Cycle to start function trace") stageTracing = Param.Bool(False, "Enable tracing of each stage in CPU") - memBlockSize = Param.Unsigned("Memory Block Size") + memBlockSize = Param.Unsigned(64, "Memory Block Size") multLatency = Param.Unsigned(1, "Latency for Multiply Operations") multRepeatRate = Param.Unsigned(1, "Repeat Rate for Multiply Operations") diff --git a/src/cpu/inorder/comm.hh b/src/cpu/inorder/comm.hh index c687a9ab4..18bb24169 100644 --- a/src/cpu/inorder/comm.hh +++ b/src/cpu/inorder/comm.hh @@ -53,6 +53,14 @@ struct InterStageStruct { uint64_t nextPC; InstSeqNum squashedSeqNum; bool includeSquashInst; + + InterStageStruct() + :size(0), squash(false), + branchMispredict(false), branchTaken(false), + mispredPC(0), nextPC(0), + squashedSeqNum(0), includeSquashInst(false) + { } + }; /** Turn This into a Class */ diff --git a/src/cpu/inorder/inorder_dyn_inst.cc b/src/cpu/inorder/inorder_dyn_inst.cc index 3a45bd01e..e5fac7141 100644 --- a/src/cpu/inorder/inorder_dyn_inst.cc +++ b/src/cpu/inorder/inorder_dyn_inst.cc @@ -84,7 +84,10 @@ InOrderDynInst::InOrderDynInst(StaticInstPtr &_staticInst) InOrderDynInst::InOrderDynInst() : traceData(NULL), cpu(cpu) -{ initVars(); } +{ + seqNum = 0; + initVars(); +} int InOrderDynInst::instcount = 0; diff --git a/src/cpu/inorder/pipeline_stage.cc b/src/cpu/inorder/pipeline_stage.cc index f356c0e1a..4ded50bf0 100644 --- a/src/cpu/inorder/pipeline_stage.cc +++ b/src/cpu/inorder/pipeline_stage.cc @@ -38,35 +38,10 @@ using namespace std; using namespace ThePipeline; PipelineStage::PipelineStage(Params *params, unsigned stage_num) - : numThreads(ThePipeline::MaxThreads) { - stageNum = stage_num; - stageWidth = ThePipeline::StageWidth; - - _status = Inactive; - - prevStageValid = false; - nextStageValid = false; - - // Init. structures - for(int tid=0; tid < numThreads; tid++) { - stageStatus[tid] = Idle; - - for (int stNum = 0; stNum < NumStages; stNum++) { - stalls[tid].stage[stNum] = false; - } - stalls[tid].resources.clear(); - - if (stageNum < BackEndStartStage) - lastStallingStage[tid] = BackEndStartStage - 1; - else - lastStallingStage[tid] = NumStages - 1; - } - - stageBufferMax = ThePipeline::interStageBuffSize[stage_num]; + init(params, stage_num); } - void PipelineStage::init(Params *params, unsigned stage_num) { @@ -189,7 +164,7 @@ PipelineStage::setNextStageQueue(TimeBuffer *next_stage_ptr) // Setup wire to write information to proper place in stage queue. nextStage = nextStageQueue->getWire(0); - + nextStage->size = 0; nextStageValid = true; } @@ -682,6 +657,9 @@ PipelineStage::tick() bool status_change = false; + if (nextStageValid) + nextStage->size = 0; + toNextStageIndex = 0; sortInsts(); diff --git a/src/cpu/inorder/resources/mult_div_unit.cc b/src/cpu/inorder/resources/mult_div_unit.cc index abef11247..e98e97be7 100644 --- a/src/cpu/inorder/resources/mult_div_unit.cc +++ b/src/cpu/inorder/resources/mult_div_unit.cc @@ -57,6 +57,8 @@ MultDivUnit::MultDivUnit(string res_name, int res_id, int res_width, div32RepeatRate = params->div32RepeatRate; div32Latency = params->div32Latency; + + lastMDUCycle = 0; } void @@ -150,6 +152,9 @@ MultDivUnit::getSlot(DynInstPtr inst) rval); if (rval != -1) { + lastMDUCycle = curTick; + lastOpType = inst->opClass(); + lastInstName = inst->staticInst->getName(); } return rval; -- cgit v1.2.3 From f69b018571a6396d0e679d4d0eceb47ef4496530 Mon Sep 17 00:00:00 2001 From: Korey Sewell Date: Wed, 4 Mar 2009 13:17:07 -0500 Subject: make handling of interstage buffers (i.e. StageQueues) more consistent: (1)number from 0-n, not 1-n+1, (2) always check nextStageValid before a stageNum+1 and prevStageValid for a stageNum-1 reference (3) add skidSize() to get StageQueue size for all threads --- src/cpu/inorder/cpu.cc | 4 +- src/cpu/inorder/first_stage.cc | 2 +- src/cpu/inorder/pipeline_stage.cc | 85 +++++++++++++++++++++++++-------------- src/cpu/inorder/pipeline_stage.hh | 5 ++- 4 files changed, 62 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc index 1836989af..9c957487d 100644 --- a/src/cpu/inorder/cpu.cc +++ b/src/cpu/inorder/cpu.cc @@ -250,8 +250,8 @@ InOrderCPU::InOrderCPU(Params *params) // Take Care of 1st/Nth stages if (stNum > 0) pipelineStage[stNum]->setPrevStageQueue(stageQueue[stNum - 1]); - if (stNum < NumStages - 2) - pipelineStage[stNum]->setNextStageQueue(stageQueue[stNum + 1]); + if (stNum < NumStages - 1) + pipelineStage[stNum]->setNextStageQueue(stageQueue[stNum]); } // Initialize thread specific variables diff --git a/src/cpu/inorder/first_stage.cc b/src/cpu/inorder/first_stage.cc index ce30f8466..be4431a03 100644 --- a/src/cpu/inorder/first_stage.cc +++ b/src/cpu/inorder/first_stage.cc @@ -127,7 +127,7 @@ FirstStage::processInsts(unsigned tid) { bool all_reqs_completed = true; - for (int insts_fetched = 0; insts_fetched < stageWidth && canSendInstToNextStage(); insts_fetched++) { + for (int insts_fetched = 0; insts_fetched < stageWidth && canSendInstToStage(1); insts_fetched++) { DynInstPtr inst; bool new_inst = false; diff --git a/src/cpu/inorder/pipeline_stage.cc b/src/cpu/inorder/pipeline_stage.cc index 4ded50bf0..1c8da2b13 100644 --- a/src/cpu/inorder/pipeline_stage.cc +++ b/src/cpu/inorder/pipeline_stage.cc @@ -229,7 +229,7 @@ PipelineStage::checkStall(unsigned tid) const bool ret_val = false; // Only check pipeline stall from stage directly following this stage - if (stalls[tid].stage[stageNum + 1]) { + if (nextStageValid && stalls[tid].stage[stageNum + 1]) { DPRINTF(InOrderStage,"[tid:%i]: Stall fom Stage %i detected.\n", tid, stageNum + 1); ret_val = true; @@ -422,26 +422,28 @@ PipelineStage::stageBufferAvail() } int incoming_insts = (prevStageValid) ? - cpu->pipelineStage[stageNum-1]->nextStage->size : + cpu->pipelineStage[stageNum]->prevStage->size : 0; - int avail = stageBufferMax - total - incoming_insts; + int avail = stageBufferMax - total -0;// incoming_insts; - assert(avail >= 0); + if (avail < 0) + fatal("stageNum %i:stageBufferAvail() < 0...stBMax=%i,total=%i,incoming=%i=>%i", + stageNum, stageBufferMax, total, incoming_insts, avail); return avail; } bool -PipelineStage::canSendInstToNextStage() +PipelineStage::canSendInstToStage(unsigned stage_num) { bool buffer_avail = false; - if (nextStageValid) { - buffer_avail = (cpu->pipelineStage[stageNum+1]->stageBufferAvail() >= 1); + if (cpu->pipelineStage[stage_num]->prevStageValid) { + buffer_avail = cpu->pipelineStage[stage_num]->stageBufferAvail() >= 1; } - if (!buffer_avail && nextStageValid) { + if (!buffer_avail && nextStageQueueValid(stage_num)) { DPRINTF(InOrderStall, "STALL: No room in stage %i buffer.\n", stageNum + 1); } @@ -468,6 +470,17 @@ PipelineStage::skidInsert(unsigned tid) } +int +PipelineStage::skidSize() +{ + int total = 0; + + for (int i=0; i < ThePipeline::MaxThreads; i++) { + total += skidBuffer[i].size(); + } + + return total; +} bool PipelineStage::skidsEmpty() @@ -743,8 +756,11 @@ PipelineStage::processStage(bool &status_change) nextStage->size, stageNum + 1); } - DPRINTF(InOrderStage, "%i insts left in stage buffer.\n", stageBufferMax - stageBufferAvail()); + DPRINTF(InOrderStage, "%i left in stage %i incoming buffer.\n", skidSize(), + stageNum); + DPRINTF(InOrderStage, "%i available in stage %i incoming buffer.\n", stageBufferAvail(), + stageNum); } void @@ -814,14 +830,10 @@ PipelineStage::processInsts(unsigned tid) int insts_processed = 0; - DPRINTF(InOrderStage, "[tid:%u]: Sending instructions to stage %u.\n", tid, - stageNum+1); - - //Keep processing instructions while ... these ?s are true: - while (insts_available > 0 && //1. are there instructions to process - insts_processed < stageWidth && //2. can the stage still process this - (canSendInstToNextStage() || !nextStageValid) && //3. is there room in next stage - last_req_completed) { //4. was the last instruction completed + while (insts_available > 0 && + insts_processed < stageWidth && + (!nextStageValid || canSendInstToStage(stageNum+1)) && + last_req_completed) { assert(!insts_to_stage.empty()); inst = insts_to_stage.front(); @@ -847,23 +859,21 @@ PipelineStage::processInsts(unsigned tid) last_req_completed = processInstSchedule(inst); - - insts_processed++; - // Don't let instruction pass to next stage if it hasnt completed // all of it's requests for this stage. if (!last_req_completed && !outOfOrderValid()) continue; - insts_to_stage.pop(); - - DPRINTF(InOrderStage, "Marking [tid:%i] [sn:%i] for insertion into next stage buffer.\n", - tid, inst->seqNum); - // Send to Next Stage or Break Loop - if (!sendInstToNextStage(inst)) - break;; + if (nextStageValid && !sendInstToNextStage(inst)) { + DPRINTF(InOrderStage, "[tid:%i] [sn:%i] unable to proceed to stage %i.\n", + tid, inst->seqNum,inst->nextStage); + break; + } + insts_processed++; + + insts_to_stage.pop(); //++stageProcessedInsts; --insts_available; @@ -871,8 +881,6 @@ PipelineStage::processInsts(unsigned tid) // If we didn't process all instructions, then we will need to block // and put all those instructions into the skid buffer. - // @TODO:-IN-PROGRESS-:Evaluating when stages should block/unblock - // for stage stalls... if (!insts_to_stage.empty()) { blockDueToBuffer(tid); } @@ -945,6 +953,8 @@ bool PipelineStage::sendInstToNextStage(DynInstPtr inst) { // Update Next Stage Variable in Instruction + // NOTE: Some Resources will update this nextStage var. to + // for bypassing, so can't always assume nextStage=stageNum+1 if (inst->nextStage == stageNum) inst->nextStage++; @@ -953,14 +963,29 @@ PipelineStage::sendInstToNextStage(DynInstPtr inst) int next_stage = inst->nextStage; int prev_stage = next_stage - 1; + assert(next_stage >= 1); + assert(prev_stage >= 0); + + DPRINTF(InOrderStage, "[tid:%u]: Attempting to send instructions to stage %u.\n", tid, + stageNum+1); + + if (!canSendInstToStage(inst->nextStage)) { + DPRINTF(InOrderStage, "[tid:%u]: Could not send instruction to stage %u.\n", tid, + stageNum+1); + return false; + } + + if (nextStageQueueValid(inst->nextStage - 1)) { if (inst->seqNum > cpu->squashSeqNum[tid] && curTick == cpu->lastSquashCycle[tid]) { DPRINTF(InOrderStage, "[tid:%u]: [sn:%i]: squashed, skipping insertion " "into stage %i queue.\n", tid, inst->seqNum, inst->nextStage); } else { - DPRINTF(InOrderStage, "[tid:%u] %i slots available in next stage buffer.\n", + if (nextStageValid) { + DPRINTF(InOrderStage, "[tid:%u] %i slots available in next stage buffer.\n", tid, cpu->pipelineStage[next_stage]->stageBufferAvail()); + } DPRINTF(InOrderStage, "[tid:%u]: [sn:%i]: being placed into " "index %i of stage buffer %i queue.\n", diff --git a/src/cpu/inorder/pipeline_stage.hh b/src/cpu/inorder/pipeline_stage.hh index 833547704..17ca32595 100644 --- a/src/cpu/inorder/pipeline_stage.hh +++ b/src/cpu/inorder/pipeline_stage.hh @@ -184,7 +184,7 @@ class PipelineStage virtual bool processInstSchedule(DynInstPtr inst); /** Is there room in the next stage buffer for this instruction? */ - virtual bool canSendInstToNextStage(); + virtual bool canSendInstToStage(unsigned stage_num); /** Send an instruction to the next stage buffer */ virtual bool sendInstToNextStage(DynInstPtr inst); @@ -194,6 +194,9 @@ class PipelineStage */ virtual void skidInsert(unsigned tid); + /** Total size of all skid buffers */ + int skidSize(); + /** Returns if all of the skid buffers are empty. */ bool skidsEmpty(); -- cgit v1.2.3 From 30cd2d21fad6c12e2540672f315f561c9a1643ec Mon Sep 17 00:00:00 2001 From: Korey Sewell Date: Wed, 4 Mar 2009 13:17:08 -0500 Subject: Remove unused functions/comments cluttering up the code. --- src/cpu/inorder/SConscript | 2 +- src/cpu/inorder/cpu.cc | 45 ++----------------------- src/cpu/inorder/cpu.hh | 25 ++------------ src/cpu/inorder/inorder_cpu_builder.cc | 1 - src/cpu/inorder/inorder_dyn_inst.cc | 59 ++------------------------------- src/cpu/inorder/inorder_dyn_inst.hh | 4 --- src/cpu/inorder/params.hh | 2 +- src/cpu/inorder/pipeline_stage.cc | 13 ++------ src/cpu/inorder/pipeline_stage.hh | 3 -- src/cpu/inorder/pipeline_traits.hh | 7 ---- src/cpu/inorder/resource.hh | 3 -- src/cpu/inorder/resources/cache_unit.cc | 6 ++-- src/cpu/inorder/thread_context.hh | 3 -- 13 files changed, 14 insertions(+), 159 deletions(-) (limited to 'src') diff --git a/src/cpu/inorder/SConscript b/src/cpu/inorder/SConscript index dc5ff6f46..a987c4e05 100644 --- a/src/cpu/inorder/SConscript +++ b/src/cpu/inorder/SConscript @@ -47,7 +47,7 @@ if 'InOrderCPU' in env['CPU_MODELS']: TraceFlag('RefCount') CompoundFlag('InOrderCPUAll', [ 'InOrderStage', 'InOrderStall', 'InOrderCPU', - 'InOrderMDU', 'RegDepMap', 'Resource']) + 'InOrderMDU', 'InOrderCachePort', 'RegDepMap', 'Resource']) Source('pipeline_traits.cc') Source('inorder_dyn_inst.cc') diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc index 9c957487d..7dafd826f 100644 --- a/src/cpu/inorder/cpu.cc +++ b/src/cpu/inorder/cpu.cc @@ -46,7 +46,6 @@ #include "cpu/inorder/resource_pool.hh" #include "mem/translating_port.hh" #include "sim/process.hh" -//#include "sim/root.hh" #include "sim/stat_control.hh" #include @@ -162,7 +161,6 @@ InOrderCPU::InOrderCPU(Params *params) cpu_params = params; resPool = new ResourcePool(this, params); -// resPool->init(); coreType = "default"; // eventually get this from params @@ -191,13 +189,9 @@ InOrderCPU::InOrderCPU(Params *params) } - /* Use this port to for syscall emulation writes to memory. */ - //Port *mem_port = NULL; - //TranslatingPort *trans_port = NULL; - for (int i = 0; i < numThreads; ++i) { if (i < params->workload.size()) { - DPRINTF(InOrderCPU, "Workload[%i] process is %#x", + DPRINTF(InOrderCPU, "Workload[%i] process is %#x\n", i, this->thread[i]); this->thread[i] = new Thread(this, i, params->workload[i], i); @@ -208,11 +202,8 @@ InOrderCPU::InOrderCPU(Params *params) } else { //Allocate Empty thread so M5 can use later //when scheduling threads to CPU - Process* dummy_proc = params->workload[0]; //LiveProcess::createDummy(); + Process* dummy_proc = params->workload[0]; this->thread[i] = new Thread(this, i, dummy_proc, i); - - // Set Up Syscall Emulation Port - //this->thread[i]->setMemPort(trans_port); } // Setup the TC that will serve as the interface to the threads/CPU. @@ -790,8 +781,6 @@ InOrderCPU::deallocateThread(unsigned tid) { DPRINTF(InOrderCPU,"[tid:%i]: Deallocating ...", tid); - //removeThread(tid); - removeFromCurrentThreads(tid); deactivateThread(tid); @@ -840,19 +829,6 @@ InOrderCPU::activateWhenReady(int tid) } -void -InOrderCPU::signalSwitched() -{ - panic("Unimplemented Function\n."); -} - - -void -InOrderCPU::takeOverFrom(BaseCPU *oldCPU) -{ - panic("Take Over From Another CPU\n."); -} - uint64_t InOrderCPU::readPC(unsigned tid) { @@ -1205,14 +1181,6 @@ InOrderCPU::cleanUpRemovedEvents() } } -/* - -void -InOrderCPU::removeAllInsts() -{ - instList.clear(); -} -*/ void InOrderCPU::dumpInsts() @@ -1233,14 +1201,6 @@ InOrderCPU::dumpInsts() ++num; } } -/* - -void -InOrderCPU::wakeDependents(DynInstPtr &inst) -{ - iew.wakeDependents(inst); -} -*/ void InOrderCPU::wakeCPU() @@ -1252,6 +1212,7 @@ InOrderCPU::wakeCPU() DPRINTF(Activity, "Waking up CPU\n"); + //@todo: figure out how to count idleCycles correctly //idleCycles += (curTick - 1) - lastRunningCycle; mainEventQueue.schedule(&tickEvent, curTick); diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh index e27687a72..36c90a0e9 100644 --- a/src/cpu/inorder/cpu.hh +++ b/src/cpu/inorder/cpu.hh @@ -249,9 +249,6 @@ class InOrderCPU : public BaseCPU TheISA::IntReg nextNPC[ThePipeline::MaxThreads]; /** The Register File for the CPU */ - /** @TODO: This regFile wont be a sufficient solution for out-of-order, add register - * files as a resource in order to handle ths problem - */ TheISA::IntRegFile intRegFile[ThePipeline::MaxThreads];; TheISA::FloatRegFile floatRegFile[ThePipeline::MaxThreads];; TheISA::MiscRegFile miscRegFile; @@ -362,15 +359,6 @@ class InOrderCPU : public BaseCPU void switchToActive(int stage_idx) { /*pipelineStage[stage_idx]->switchToActive();*/ } - /** Switches out this CPU. (Unused currently) */ - //void switchOut(Sampler *sampler); - - /** Signals to this CPU that a stage has completed switching out. (Unused currently)*/ - void signalSwitched(); - - /** Takes over from another CPU. (Unused currently)*/ - void takeOverFrom(BaseCPU *oldCPU); - /** Get the current instruction sequence number, and increment it. */ InstSeqNum getAndIncrementInstSeq(unsigned tid) { return globalSeqNum[tid]++; } @@ -389,6 +377,7 @@ class InOrderCPU : public BaseCPU globalSeqNum[tid] = seq_num; } + /** Get & Update Next Event Number */ InstSeqNum getNextEventNum() { return cpuEventNum++; @@ -463,9 +452,6 @@ class InOrderCPU : public BaseCPU /** Sets the next NPC of a specific thread. */ void setNextNPC(uint64_t val, unsigned tid); - /** Add Destination Register To Dependency Maps */ - //void addToRegDepMap(DynInstPtr &inst); - /** Function to add instruction onto the head of the list of the * instructions. Used when new instructions are fetched. */ @@ -530,13 +516,6 @@ class InOrderCPU : public BaseCPU */ std::queue cpuEventRemoveList; -#ifdef DEBUG - /** Debug structure to keep track of the sequence numbers still in - * flight. - */ - std::set snList; -#endif - /** Records if instructions need to be removed this cycle due to * being retired or squashed. */ @@ -610,7 +589,6 @@ class InOrderCPU : public BaseCPU unsigned readStCondFailures() { return stCondFails; } unsigned setStCondFailures(unsigned st_fails) { return stCondFails = st_fails; } - public: /** Returns a pointer to a thread context. */ ThreadContext *tcBase(unsigned tid = 0) { @@ -631,6 +609,7 @@ class InOrderCPU : public BaseCPU /** Pointer to the icache interface. */ MemInterface *icacheInterface; + /** Pointer to the dcache interface. */ MemInterface *dcacheInterface; diff --git a/src/cpu/inorder/inorder_cpu_builder.cc b/src/cpu/inorder/inorder_cpu_builder.cc index b1b4bea80..0088a3bd9 100644 --- a/src/cpu/inorder/inorder_cpu_builder.cc +++ b/src/cpu/inorder/inorder_cpu_builder.cc @@ -35,7 +35,6 @@ #include "cpu/inst_seq.hh" #include "cpu/static_inst.hh" #include "cpu/inorder/cpu.hh" -//#include "cpu/inorder/params.hh" #include "cpu/inorder/inorder_dyn_inst.hh" #include "cpu/inorder/pipeline_traits.hh" #include "params/InOrderCPU.hh" diff --git a/src/cpu/inorder/inorder_dyn_inst.cc b/src/cpu/inorder/inorder_dyn_inst.cc index e5fac7141..d292d72f0 100644 --- a/src/cpu/inorder/inorder_dyn_inst.cc +++ b/src/cpu/inorder/inorder_dyn_inst.cc @@ -167,10 +167,6 @@ InOrderDynInst::initVars() DPRINTF(InOrderDynInst, "DynInst: [tid:%i] [sn:%lli] Instruction created. (active insts: %i)\n", threadNumber, seqNum, instcount); - -#ifdef DEBUG - cpu->snList.insert(seqNum); -#endif } @@ -192,9 +188,6 @@ InOrderDynInst::~InOrderDynInst() DPRINTF(InOrderDynInst, "DynInst: [tid:%i] [sn:%lli] Instruction destroyed. (active insts: %i)\n", threadNumber, seqNum, instcount); -#ifdef DEBUG - cpu->snList.erase(seqNum); -#endif } void @@ -305,44 +298,13 @@ InOrderDynInst::syscall(int64_t callnum) void InOrderDynInst::prefetch(Addr addr, unsigned flags) { - // This is the "functional" implementation of prefetch. Not much - // happens here since prefetches don't affect the architectural - // state. -/* - // Generate a MemReq so we can translate the effective address. - MemReqPtr req = new MemReq(addr, thread->getXCProxy(), 1, flags); - req->asid = asid; - - // Prefetches never cause faults. - fault = NoFault; - - // note this is a local, not InOrderDynInst::fault - Fault trans_fault = cpu->translateDataReadReq(req); - - if (trans_fault == NoFault && !(req->flags & UNCACHEABLE)) { - // It's a valid address to cacheable space. Record key MemReq - // parameters so we can generate another one just like it for - // the timing access without calling translate() again (which - // might mess up the TLB). - effAddr = req->vaddr; - physEffAddr = req->paddr; - memReqFlags = req->flags; - } else { - // Bogus address (invalid or uncacheable space). Mark it by - // setting the eff_addr to InvalidAddr. - effAddr = physEffAddr = MemReq::inval_addr; - } - - if (traceData) { - traceData->setAddr(addr); - } -*/ + panic("Prefetch Unimplemented\n"); } void InOrderDynInst::writeHint(Addr addr, int size, unsigned flags) { - // Not currently supported. + panic("Write-Hint Unimplemented\n"); } /** @@ -762,20 +724,3 @@ my_hash_t; my_hash_t thishash; #endif - -#ifdef DEBUG - -void -InOrderDynInst::dumpSNList() -{ - std::set::iterator sn_it = cpu->snList.begin(); - - int count = 0; - while (sn_it != cpu->snList.end()) { - cprintf("%i: [sn:%lli] not destroyed\n", count, (*sn_it)); - count++; - sn_it++; - } -} -#endif - diff --git a/src/cpu/inorder/inorder_dyn_inst.hh b/src/cpu/inorder/inorder_dyn_inst.hh index 9f52f954f..55c61ffb9 100644 --- a/src/cpu/inorder/inorder_dyn_inst.hh +++ b/src/cpu/inorder/inorder_dyn_inst.hh @@ -957,10 +957,6 @@ class InOrderDynInst : public FastAlloc, public RefCounted /** Count of total number of dynamic instructions. */ static int instcount; -#ifdef DEBUG - void dumpSNList(); -#endif - /** Dumps out contents of this BaseDynInst. */ void dump(); diff --git a/src/cpu/inorder/params.hh b/src/cpu/inorder/params.hh index 67f8f47f0..51b7409ad 100644 --- a/src/cpu/inorder/params.hh +++ b/src/cpu/inorder/params.hh @@ -121,4 +121,4 @@ class InOrderParams : public BaseCPU::Params }; -#endif // __CPU_O3_CPU_INORDER_PARAMS_HH__ +#endif // _CPU_INORDER_PARAMS_HH__ diff --git a/src/cpu/inorder/pipeline_stage.cc b/src/cpu/inorder/pipeline_stage.cc index 1c8da2b13..ab7328f4a 100644 --- a/src/cpu/inorder/pipeline_stage.cc +++ b/src/cpu/inorder/pipeline_stage.cc @@ -193,7 +193,7 @@ void PipelineStage::switchOut() { // Stage can immediately switch out. - cpu->signalSwitched(); + panic("Switching Out of Stages Unimplemented"); } @@ -691,13 +691,6 @@ PipelineStage::tick() DPRINTF(InOrderStage, "\n\n"); } -bool -PipelineStage::outOfOrderValid() -{ - //@TODO: Define this function when OOO is valid - return false; -} - void PipelineStage::setResStall(ResReqPtr res_req, unsigned tid) { @@ -861,7 +854,7 @@ PipelineStage::processInsts(unsigned tid) // Don't let instruction pass to next stage if it hasnt completed // all of it's requests for this stage. - if (!last_req_completed && !outOfOrderValid()) + if (!last_req_completed) continue; // Send to Next Stage or Break Loop @@ -1018,7 +1011,7 @@ PipelineStage::sendInstToNextStage(DynInstPtr inst) void PipelineStage::dumpInsts() { - std::cerr << "Insts in Stage " << stageNum << " skidbuffers:" << endl; + cprintf("Insts in Stage %i skidbuffers\n",stageNum); for (int tid=0; tid < ThePipeline::MaxThreads; tid++) { diff --git a/src/cpu/inorder/pipeline_stage.hh b/src/cpu/inorder/pipeline_stage.hh index 17ca32595..19bf8154f 100644 --- a/src/cpu/inorder/pipeline_stage.hh +++ b/src/cpu/inorder/pipeline_stage.hh @@ -147,9 +147,6 @@ class PipelineStage */ virtual void tick(); - /** Is out of order processing valid? */ - bool outOfOrderValid(); - /** Set a resource stall in the pipeline-stage */ void setResStall(ResReqPtr res_req, unsigned tid); diff --git a/src/cpu/inorder/pipeline_traits.hh b/src/cpu/inorder/pipeline_traits.hh index c5e4bb228..3c49143bc 100644 --- a/src/cpu/inorder/pipeline_traits.hh +++ b/src/cpu/inorder/pipeline_traits.hh @@ -38,7 +38,6 @@ #include "arch/isa_traits.hh" #include "cpu/base.hh" -//#include "cpu/inorder/params.hh" #include "params/InOrderCPU.hh" @@ -122,12 +121,6 @@ namespace ThePipeline { if (lhs->stageNum > rhs->stageNum) { return true; } else if (lhs->stageNum == rhs->stageNum) { - /*if (lhs->resNum > rhs->resNum) { - return true; - } else { - return false; - }*/ - if (lhs->priority > rhs->priority) { return true; } else { diff --git a/src/cpu/inorder/resource.hh b/src/cpu/inorder/resource.hh index e3536258d..9b9e3c3dc 100644 --- a/src/cpu/inorder/resource.hh +++ b/src/cpu/inorder/resource.hh @@ -79,9 +79,6 @@ class Resource { virtual void init(); virtual void initSlots(); - /** Tasks to perform when simulation starts */ - //virtual void startup() { } - /** Register Stats for this resource */ virtual void regStats(); diff --git a/src/cpu/inorder/resources/cache_unit.cc b/src/cpu/inorder/resources/cache_unit.cc index 6b62c864a..6fd7ae36c 100644 --- a/src/cpu/inorder/resources/cache_unit.cc +++ b/src/cpu/inorder/resources/cache_unit.cc @@ -454,12 +454,10 @@ CacheUnit::processCacheCompletion(PacketPtr pkt) findRequest(cache_pkt->cacheReq->getInst())); assert(cache_req); -#if TRACING_ON + // Get resource request info + // @todo: SMT needs to figure out where to get thread # from. unsigned tid = 0; -#endif - - //tid = pkt->req->getThreadNum(); unsigned stage_num = cache_req->getStageNum(); DynInstPtr inst = cache_req->inst; diff --git a/src/cpu/inorder/thread_context.hh b/src/cpu/inorder/thread_context.hh index dce150b47..8b3b47290 100644 --- a/src/cpu/inorder/thread_context.hh +++ b/src/cpu/inorder/thread_context.hh @@ -111,9 +111,6 @@ class InOrderThreadContext : public ThreadContext virtual void setStatus(Status new_status) { thread->setStatus(new_status); } - /** Returns a pointer to the last graduated/committed instruction in the thread */ - //DynInstPtr getLastGradInst() { return thread->getLastGradInst(); } - /** Set the status to Active. Optional delay indicates number of * cycles to wait before beginning execution. */ virtual void activate(int delay = 1); -- cgit v1.2.3 From 7c8d54421665ccbc204487cb6a9faa31c1b3c243 Mon Sep 17 00:00:00 2001 From: Korey Sewell Date: Wed, 4 Mar 2009 13:17:09 -0500 Subject: Give each resource in InOrder it's own TraceFlag instead of just standard 'Resource' flag --- src/cpu/inorder/SConscript | 17 +++++++++-- src/cpu/inorder/resources/agen_unit.cc | 8 ++--- src/cpu/inorder/resources/branch_predictor.cc | 10 +++---- src/cpu/inorder/resources/branch_predictor.hh | 1 - src/cpu/inorder/resources/decode_unit.cc | 4 +-- src/cpu/inorder/resources/execution_unit.cc | 16 +++++----- src/cpu/inorder/resources/fetch_seq_unit.cc | 28 +++++++++--------- src/cpu/inorder/resources/graduation_unit.cc | 6 ++-- src/cpu/inorder/resources/inst_buffer.cc | 20 ++++++------- src/cpu/inorder/resources/tlb_unit.cc | 12 ++++---- src/cpu/inorder/resources/use_def.cc | 42 +++++++++++++-------------- 11 files changed, 87 insertions(+), 77 deletions(-) (limited to 'src') diff --git a/src/cpu/inorder/SConscript b/src/cpu/inorder/SConscript index a987c4e05..af237a777 100644 --- a/src/cpu/inorder/SConscript +++ b/src/cpu/inorder/SConscript @@ -36,18 +36,29 @@ if 'InOrderCPU' in env['CPU_MODELS']: TraceFlag('ResReqCount') TraceFlag('FreeList') - TraceFlag('InOrderCachePort') TraceFlag('InOrderStage') TraceFlag('InOrderStall') TraceFlag('InOrderCPU') - TraceFlag('InOrderMDU') TraceFlag('RegDepMap') TraceFlag('InOrderDynInst') TraceFlag('Resource') + TraceFlag('InOrderAGEN') + TraceFlag('InOrderFetchSeq') + TraceFlag('InOrderTLB') + TraceFlag('InOrderCachePort') + TraceFlag('InOrderBPred') + TraceFlag('InOrderDecode') + TraceFlag('InOrderExecute') + TraceFlag('InOrderInstBuffer') + TraceFlag('InOrderUseDef') + TraceFlag('InOrderMDU') + TraceFlag('InOrderGraduation') TraceFlag('RefCount') CompoundFlag('InOrderCPUAll', [ 'InOrderStage', 'InOrderStall', 'InOrderCPU', - 'InOrderMDU', 'InOrderCachePort', 'RegDepMap', 'Resource']) + 'InOrderMDU', 'InOrderAGEN', 'InOrderFetchSeq', 'InOrderTLB', 'InOrderBPred', + 'InOrderDecode', 'InOrderExecute', 'InOrderInstBuffer', 'InOrderUseDef', + 'InOrderGraduation', 'InOrderCachePort', 'RegDepMap', 'Resource']) Source('pipeline_traits.cc') Source('inorder_dyn_inst.cc') diff --git a/src/cpu/inorder/resources/agen_unit.cc b/src/cpu/inorder/resources/agen_unit.cc index 8e3d25656..f462b12ea 100644 --- a/src/cpu/inorder/resources/agen_unit.cc +++ b/src/cpu/inorder/resources/agen_unit.cc @@ -54,7 +54,7 @@ AGENUnit::execute(int slot_num) { // Load/Store Instruction if (inst->isMemRef()) { - DPRINTF(Resource, "[tid:%i] Generating Address for [sn:%i] (%s).\n", + DPRINTF(InOrderAGEN, "[tid:%i] Generating Address for [sn:%i] (%s).\n", tid, inst->seqNum, inst->staticInst->getName()); @@ -67,13 +67,13 @@ AGENUnit::execute(int slot_num) inst->setMemAddr(inst->getEA()); //inst->setExecuted(); - DPRINTF(Resource, "[tid:%i] [sn:%i] Effective address calculated to be: " + DPRINTF(InOrderAGEN, "[tid:%i] [sn:%i] Effective address calculated to be: " "%#x.\n", tid, inst->seqNum, inst->getEA()); } else if (inst->isStore()) { fault = inst->calcEA(); inst->setMemAddr(inst->getEA()); - DPRINTF(Resource, "[tid:%i] [sn:%i] Effective address calculated to be: " + DPRINTF(InOrderAGEN, "[tid:%i] [sn:%i] Effective address calculated to be: " "%#x.\n", tid, inst->seqNum, inst->getEA()); } else { panic("Unexpected memory type!\n"); @@ -86,7 +86,7 @@ AGENUnit::execute(int slot_num) } } } else { - DPRINTF(Resource, "[tid:] Ignoring non-memory instruction [sn:%i].\n", tid, seq_num); + DPRINTF(InOrderAGEN, "[tid:] Ignoring non-memory instruction [sn:%i].\n", tid, seq_num); agen_req->done(); } } diff --git a/src/cpu/inorder/resources/branch_predictor.cc b/src/cpu/inorder/resources/branch_predictor.cc index b563a3057..511a0ac82 100644 --- a/src/cpu/inorder/resources/branch_predictor.cc +++ b/src/cpu/inorder/resources/branch_predictor.cc @@ -90,7 +90,7 @@ BranchPredictor::execute(int slot_num) predictedTaken++; } else { - DPRINTF(Resource, "[tid:%i]: [sn:%i]: Branch predicted false.\n", + DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Branch predicted false.\n", tid, seq_num); if (inst->isCondDelaySlot()) @@ -105,11 +105,11 @@ BranchPredictor::execute(int slot_num) inst->setBranchPred(predict_taken); - DPRINTF(Resource, "[tid:%i]: [sn:%i]: Predicted PC is %08p.\n", + DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Predicted PC is %08p.\n", tid, seq_num, pred_PC); } else { - DPRINTF(Resource, "[tid:%i]: Ignoring [sn:%i] because this isn't " + DPRINTF(InOrderBPred, "[tid:%i]: Ignoring [sn:%i] because this isn't " "a control instruction.\n", tid, seq_num); } @@ -119,7 +119,7 @@ BranchPredictor::execute(int slot_num) case UpdatePredictor: { - DPRINTF(Resource, "[tid:%i]: [sn:%i]: Updating Branch Predictor.\n", + DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Updating Branch Predictor.\n", tid, seq_num); @@ -138,7 +138,7 @@ void BranchPredictor::squash(DynInstPtr inst, int squash_stage, InstSeqNum squash_seq_num, unsigned tid) { - DPRINTF(Resource, "Squashing...\n"); + DPRINTF(InOrderBPred, "Squashing...\n"); branchPred.squash(squash_seq_num, tid); } diff --git a/src/cpu/inorder/resources/branch_predictor.hh b/src/cpu/inorder/resources/branch_predictor.hh index 66eb1afe8..57745343c 100644 --- a/src/cpu/inorder/resources/branch_predictor.hh +++ b/src/cpu/inorder/resources/branch_predictor.hh @@ -41,7 +41,6 @@ #include "cpu/inorder/pipeline_traits.hh" #include "cpu/inorder/resources/bpred_unit.hh" #include "cpu/inorder/cpu.hh" -//#include "cpu/inorder/params.hh" class BranchPredictor : public Resource { public: diff --git a/src/cpu/inorder/resources/decode_unit.cc b/src/cpu/inorder/resources/decode_unit.cc index 1628c32d0..d95b1d4bb 100644 --- a/src/cpu/inorder/resources/decode_unit.cc +++ b/src/cpu/inorder/resources/decode_unit.cc @@ -63,7 +63,7 @@ DecodeUnit::execute(int slot_num) bool done_sked = ThePipeline::createBackEndSchedule(inst); if (done_sked) { - DPRINTF(Resource, "[tid:%i]: Setting Destination Register(s) for [sn:%i].\n", + DPRINTF(InOrderDecode, "[tid:%i]: Setting Destination Register(s) for [sn:%i].\n", tid, seq_num); regDepMap[tid]->insert(inst); decode_req->done(); @@ -85,7 +85,7 @@ DecodeUnit::execute(int slot_num) void DecodeUnit::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num, unsigned tid) { - DPRINTF(Resource, "[tid:%i]: Updating due to squash from stage %i after [sn:%i].\n", + DPRINTF(InOrderDecode, "[tid:%i]: Updating due to squash from stage %i after [sn:%i].\n", tid, stage_num, squash_seq_num); //cpu->removeInstsUntil(squash_seq_num, tid); diff --git a/src/cpu/inorder/resources/execution_unit.cc b/src/cpu/inorder/resources/execution_unit.cc index e41291103..843adb5b0 100644 --- a/src/cpu/inorder/resources/execution_unit.cc +++ b/src/cpu/inorder/resources/execution_unit.cc @@ -68,7 +68,7 @@ ExecutionUnit::execute(int slot_num) exec_req->fault = NoFault; - DPRINTF(Resource, "[tid:%i] Executing [sn:%i] [PC:%#x] .\n", + DPRINTF(InOrderExecute, "[tid:%i] Executing [sn:%i] [PC:%#x] .\n", tid, seq_num, inst->readPC()); switch (exec_req->cmd) @@ -99,7 +99,7 @@ ExecutionUnit::execute(int slot_num) inst->bdelaySeqNum = seq_num; inst->setPredTarg(inst->nextPC); - DPRINTF(Resource, "[tid:%i]: Conditional branch inst" + DPRINTF(InOrderExecute, "[tid:%i]: Conditional branch inst" "[sn:%i] PC %#x mispredicted as taken.\n", tid, seq_num, inst->PC); } else if (!inst->predTaken() && inst->isCondDelaySlot()) { @@ -107,13 +107,13 @@ ExecutionUnit::execute(int slot_num) inst->setPredTarg(inst->nextPC); inst->procDelaySlotOnMispred = true; - DPRINTF(Resource, "[tid:%i]: Conditional branch inst." + DPRINTF(InOrderExecute, "[tid:%i]: Conditional branch inst." "[sn:%i] PC %#x mispredicted as not taken.\n", tid, seq_num, inst->PC); } else { inst->bdelaySeqNum = seq_num + 1; - DPRINTF(Resource, "[tid:%i]: Misprediction detected at " + DPRINTF(InOrderExecute, "[tid:%i]: Misprediction detected at " "[sn:%i] PC %#x,\n\t squashing after delay slot " "instruction [sn:%i].\n", tid, seq_num, inst->PC, inst->bdelaySeqNum); @@ -122,20 +122,20 @@ ExecutionUnit::execute(int slot_num) inst->setPredTarg(inst->nextNPC); } - DPRINTF(Resource, "[tid:%i] Redirecting fetch to %#x.\n", tid, + DPRINTF(InOrderExecute, "[tid:%i] Redirecting fetch to %#x.\n", tid, inst->readPredTarg()); } else if(inst->isIndirectCtrl()){ inst->setPredTarg(inst->nextNPC); inst->bdelaySeqNum = seq_num + 1; - DPRINTF(Resource, "[tid:%i] Redirecting fetch to %#x.\n", tid, + DPRINTF(InOrderExecute, "[tid:%i] Redirecting fetch to %#x.\n", tid, inst->readPredTarg()); } else { panic("Non-control instruction (%s) mispredicting?!!", inst->staticInst->getName()); } - DPRINTF(Resource, "[tid:%i] Squashing will start from stage %i.\n", + DPRINTF(InOrderExecute, "[tid:%i] Squashing will start from stage %i.\n", tid, stage_num); cpu->pipelineStage[stage_num]->squashDueToBranch(inst, tid); @@ -164,7 +164,7 @@ ExecutionUnit::execute(int slot_num) inst->setExecuted(); exec_req->done(); - DPRINTF(Resource, "[tid:%i]: The result of execution is 0x%x.\n", + DPRINTF(InOrderExecute, "[tid:%i]: The result of execution is 0x%x.\n", inst->readTid(), inst->readIntResult(0)); } else { warn("inst [sn:%i] had a %s fault", seq_num, fault->name()); diff --git a/src/cpu/inorder/resources/fetch_seq_unit.cc b/src/cpu/inorder/resources/fetch_seq_unit.cc index 00f76f74b..36cf714c9 100644 --- a/src/cpu/inorder/resources/fetch_seq_unit.cc +++ b/src/cpu/inorder/resources/fetch_seq_unit.cc @@ -90,7 +90,7 @@ FetchSeqUnit::execute(int slot_num) delaySlotInfo[tid].targetReady = false; - DPRINTF(Resource, "[tid:%i]: Setting PC to delay slot target\n",tid); + DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC to delay slot target\n",tid); } inst->setPC(PC[tid]); @@ -102,7 +102,7 @@ FetchSeqUnit::execute(int slot_num) inst->setMemAddr(PC[tid]); inst->setSeqNum(cpu->getAndIncrementInstSeq(tid)); - DPRINTF(Resource, "[tid:%i]: Assigning [sn:%i] to PC %08p\n", tid, + DPRINTF(InOrderFetchSeq, "[tid:%i]: Assigning [sn:%i] to PC %08p\n", tid, inst->seqNum, inst->readPC()); if (delaySlotInfo[tid].numInsts > 0) { @@ -113,7 +113,7 @@ FetchSeqUnit::execute(int slot_num) delaySlotInfo[tid].targetReady = true; } - DPRINTF(Resource, "[tid:%i]: %i delay slot inst(s) left to" + DPRINTF(InOrderFetchSeq, "[tid:%i]: %i delay slot inst(s) left to" " process.\n", tid, delaySlotInfo[tid].numInsts); } @@ -139,11 +139,11 @@ FetchSeqUnit::execute(int slot_num) pcBlockStage[tid] = stage_num; } else if (inst->isCondDelaySlot() && !inst->predTaken()) { // Not-Taken AND Conditional Control - DPRINTF(Resource, "[tid:%i]: [sn:%i]: [PC:%08p] Predicted Not-Taken Cond. " + DPRINTF(InOrderFetchSeq, "[tid:%i]: [sn:%i]: [PC:%08p] Predicted Not-Taken Cond. " "Delay inst. Skipping delay slot and Updating PC to %08p\n", tid, inst->seqNum, inst->readPC(), inst->readPredTarg()); - DPRINTF(Resource, "[tid:%i] Setting up squash to start from stage %i, after [sn:%i].\n", + DPRINTF(InOrderFetchSeq, "[tid:%i] Setting up squash to start from stage %i, after [sn:%i].\n", tid, stage_num, seq_num); inst->bdelaySeqNum = seq_num; @@ -152,7 +152,7 @@ FetchSeqUnit::execute(int slot_num) squashAfterInst(inst, stage_num, tid); } else if (!inst->isCondDelaySlot() && !inst->predTaken()) { // Not-Taken Control - DPRINTF(Resource, "[tid:%i]: [sn:%i]: Predicted Not-Taken Control " + DPRINTF(InOrderFetchSeq, "[tid:%i]: [sn:%i]: Predicted Not-Taken Control " "inst. updating PC to %08p\n", tid, inst->seqNum, inst->readNextPC()); @@ -166,11 +166,11 @@ FetchSeqUnit::execute(int slot_num) delaySlotInfo[tid].targetReady = false; delaySlotInfo[tid].targetAddr = inst->readPredTarg(); - DPRINTF(Resource, "[tid:%i]: [sn:%i] Updating delay slot target " + DPRINTF(InOrderFetchSeq, "[tid:%i]: [sn:%i] Updating delay slot target " "to PC %08p\n", tid, inst->seqNum, inst->readPredTarg()); // Set-Up Squash Through-Out Pipeline - DPRINTF(Resource, "[tid:%i] Setting up squash to start from stage %i, after [sn:%i].\n", + DPRINTF(InOrderFetchSeq, "[tid:%i] Setting up squash to start from stage %i, after [sn:%i].\n", tid, stage_num, seq_num + 1); inst->bdelaySeqNum = seq_num + 1; inst->squashingStage = stage_num; @@ -179,7 +179,7 @@ FetchSeqUnit::execute(int slot_num) squashAfterInst(inst, stage_num, tid); } } else { - DPRINTF(Resource, "[tid:%i]: [sn:%i]: Ignoring branch target update " + DPRINTF(InOrderFetchSeq, "[tid:%i]: [sn:%i]: Ignoring branch target update " "since then is not a control instruction.\n", tid, inst->seqNum); } @@ -209,7 +209,7 @@ void FetchSeqUnit::squash(DynInstPtr inst, int squash_stage, InstSeqNum squash_seq_num, unsigned tid) { - DPRINTF(Resource, "[tid:%i]: Updating due to squash from stage %i.\n", + DPRINTF(InOrderFetchSeq, "[tid:%i]: Updating due to squash from stage %i.\n", tid, squash_stage); InstSeqNum done_seq_num = inst->bdelaySeqNum; @@ -217,7 +217,7 @@ FetchSeqUnit::squash(DynInstPtr inst, int squash_stage, if (squashSeqNum[tid] <= done_seq_num && lastSquashCycle[tid] == curTick) { - DPRINTF(Resource, "[tid:%i]: Ignoring squash from stage %i, since" + DPRINTF(InOrderFetchSeq, "[tid:%i]: Ignoring squash from stage %i, since" "there is an outstanding squash that is older.\n", tid, squash_stage); } else { @@ -237,7 +237,7 @@ FetchSeqUnit::squash(DynInstPtr inst, int squash_stage, nextPC[tid] = new_PC + instSize; nextNPC[tid] = new_PC + (2 * instSize); - DPRINTF(Resource, "[tid:%i]: Setting PC to %08p.\n", + DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC to %08p.\n", tid, PC[tid]); } else { delaySlotInfo[tid].numInsts = 1; @@ -278,7 +278,7 @@ FetchSeqUnit::FetchSeqEvent::process() fs_res->PC[i] = fs_res->cpu->readPC(i); fs_res->nextPC[i] = fs_res->cpu->readNextPC(i); fs_res->nextNPC[i] = fs_res->cpu->readNextNPC(i); - DPRINTF(Resource, "[tid:%i]: Setting PC:%08p NPC:%08p NNPC:%08p.\n", + DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC:%08p NPC:%08p NNPC:%08p.\n", fs_res->PC[i], fs_res->nextPC[i], fs_res->nextNPC[i]); fs_res->pcValid[i] = true; @@ -299,7 +299,7 @@ FetchSeqUnit::activateThread(unsigned tid) cpu->fetchPriorityList.push_back(tid); - DPRINTF(Resource, "[tid:%i]: Reading PC:%08p NPC:%08p NNPC:%08p.\n", + DPRINTF(InOrderFetchSeq, "[tid:%i]: Reading PC:%08p NPC:%08p NNPC:%08p.\n", tid, PC[tid], nextPC[tid], nextNPC[tid]); } diff --git a/src/cpu/inorder/resources/graduation_unit.cc b/src/cpu/inorder/resources/graduation_unit.cc index f4bbf3f5d..701da5996 100644 --- a/src/cpu/inorder/resources/graduation_unit.cc +++ b/src/cpu/inorder/resources/graduation_unit.cc @@ -71,14 +71,14 @@ GraduationUnit::execute(int slot_num) lastCycleGrad = curTick; numCycleGrad = 0; } else if (numCycleGrad > width) { - DPRINTF(Resource, "Graduation bandwidth reached for this cycle.\n"); + DPRINTF(InOrderGraduation, "Graduation bandwidth reached for this cycle.\n"); return; } // Make sure this is the last thing on the resource schedule assert(inst->resSched.size() == 1); - DPRINTF(Resource, "[tid:%i] Graduating instruction [sn:%i].\n", + DPRINTF(InOrderGraduation, "[tid:%i] Graduating instruction [sn:%i].\n", tid, seq_num); DPRINTF(RefCount, "Refcount = %i.\n", 0/*inst->curCount()*/); @@ -88,7 +88,7 @@ GraduationUnit::execute(int slot_num) // @TODO: Fix this functionality. Probably too conservative. if (inst->isNonSpeculative()) { *nonSpecInstActive[tid] = false; - DPRINTF(Resource, "[tid:%i] Non-speculative instruction [sn:%i] has graduated.\n", + DPRINTF(InOrderGraduation, "[tid:%i] Non-speculative instruction [sn:%i] has graduated.\n", tid, seq_num); } diff --git a/src/cpu/inorder/resources/inst_buffer.cc b/src/cpu/inorder/resources/inst_buffer.cc index 97924d2d3..fafff1fa7 100644 --- a/src/cpu/inorder/resources/inst_buffer.cc +++ b/src/cpu/inorder/resources/inst_buffer.cc @@ -76,21 +76,21 @@ InstBuffer::execute(int slot_idx) bool do_bypass = true; if (!instList.empty()) { - DPRINTF(Resource, "[sn:%i] cannot bypass stage %i because buffer isn't empty.\n", + DPRINTF(InOrderInstBuffer, "[sn:%i] cannot bypass stage %i because buffer isn't empty.\n", inst->seqNum, next_stage); do_bypass = false; } else if(cpu->pipelineStage[bypass_stage]->isBlocked(tid)) { - DPRINTF(Resource, "[sn:%i] cannot bypass stage %i because stage %i is blocking.\n", + DPRINTF(InOrderInstBuffer, "[sn:%i] cannot bypass stage %i because stage %i is blocking.\n", inst->seqNum, next_stage); do_bypass = false; } else if(cpu->pipelineStage[bypass_stage]->stageBufferAvail() <= 0) { - DPRINTF(Resource, "[sn:%i] cannot bypass stage %i because there is no room in " + DPRINTF(InOrderInstBuffer, "[sn:%i] cannot bypass stage %i because there is no room in " "stage %i incoming stage buffer.\n", inst->seqNum, next_stage); do_bypass = false; } if (!do_bypass) { // SCHEDULE USAGE OF BUFFER - DPRINTF(Resource, "Scheduling [sn:%i] for buffer insertion in stage %i\n", + DPRINTF(InOrderInstBuffer, "Scheduling [sn:%i] for buffer insertion in stage %i\n", inst->seqNum, next_stage); // Add to schedule: Insert into buffer in next stage @@ -105,7 +105,7 @@ InstBuffer::execute(int slot_idx) inst->resSched.push(new ScheduleEntry(bypass_stage, stage_pri, id, InstBuffer::RemoveInst)); } else { // BYPASS BUFFER & NEXT STAGE - DPRINTF(Resource, "Setting [sn:%i] to bypass stage %i and enter stage %i.\n", + DPRINTF(InOrderInstBuffer, "Setting [sn:%i] to bypass stage %i and enter stage %i.\n", inst->seqNum, next_stage, bypass_stage); inst->setNextStage(bypass_stage); instsBypassed++; @@ -120,12 +120,12 @@ InstBuffer::execute(int slot_idx) bool inserted = false; if (instList.size() < width) { - DPRINTF(Resource, "[tid:%i]: Inserting [sn:%i] into buffer.\n", + DPRINTF(InOrderInstBuffer, "[tid:%i]: Inserting [sn:%i] into buffer.\n", tid, seq_num); insert(inst); inserted = true; } else { - DPRINTF(Resource, "[tid:%i]: Denying [sn:%i] request because " + DPRINTF(InOrderInstBuffer, "[tid:%i]: Denying [sn:%i] request because " "buffer is full.\n", tid, seq_num); @@ -144,7 +144,7 @@ InstBuffer::execute(int slot_idx) case RemoveInst: { - DPRINTF(Resource, "[tid:%i]: Removing [sn:%i] from buffer.\n", + DPRINTF(InOrderInstBuffer, "[tid:%i]: Removing [sn:%i] from buffer.\n", tid, seq_num); remove(inst); ib_req->done(); @@ -155,7 +155,7 @@ InstBuffer::execute(int slot_idx) fatal("Unrecognized command to %s", resName); } - DPRINTF(Resource, "Buffer now contains %i insts.\n", instList.size()); + DPRINTF(InOrderInstBuffer, "Buffer now contains %i insts.\n", instList.size()); } void @@ -212,7 +212,7 @@ InstBuffer::squash(DynInstPtr inst, int stage_num, // Removed Instructions from InstList & Clear Remove List while (!remove_list.empty()) { - DPRINTF(Resource, "[tid:%i]: Removing squashed [sn:%i] from buffer.\n", + DPRINTF(InOrderInstBuffer, "[tid:%i]: Removing squashed [sn:%i] from buffer.\n", tid, (*remove_list.front())->seqNum); instList.erase(remove_list.front()); remove_list.pop(); diff --git a/src/cpu/inorder/resources/tlb_unit.cc b/src/cpu/inorder/resources/tlb_unit.cc index 321ac90f8..8f8ba144e 100644 --- a/src/cpu/inorder/resources/tlb_unit.cc +++ b/src/cpu/inorder/resources/tlb_unit.cc @@ -102,7 +102,7 @@ TLBUnit::execute(int slot_idx) cpu->thread[tid]->getTC()); if (tlb_req->fault != NoFault) { - DPRINTF(Resource, "[tid:%i]: %s encountered while translating " + DPRINTF(InOrderTLB, "[tid:%i]: %s encountered while translating " "addr:%08p for [sn:%i].\n", tid, tlb_req->fault->name(), tlb_req->memReq->getVaddr(), seq_num); //insert(inst); @@ -114,7 +114,7 @@ TLBUnit::execute(int slot_idx) // Let CPU handle the fault cpu->trap(tlb_req->fault, tid); } else { - DPRINTF(Resource, "[tid:%i]: [sn:%i] virt. addr %08p translated " + DPRINTF(InOrderTLB, "[tid:%i]: [sn:%i] virt. addr %08p translated " "to phys. addr:%08p.\n", tid, seq_num, tlb_req->memReq->getVaddr(), tlb_req->memReq->getPaddr()); @@ -125,7 +125,7 @@ TLBUnit::execute(int slot_idx) case DataLookup: { - DPRINTF(Resource, "[tid:%i]: [sn:%i]: Attempting to translate %08p.\n", + DPRINTF(InOrderTLB, "[tid:%i]: [sn:%i]: Attempting to translate %08p.\n", tid, seq_num, tlb_req->memReq->getVaddr()); tlb_req->fault = @@ -133,7 +133,7 @@ TLBUnit::execute(int slot_idx) cpu->thread[tid]->getTC()); if (tlb_req->fault != NoFault) { - DPRINTF(Resource, "[tid:%i]: %s encountered while translating " + DPRINTF(InOrderTLB, "[tid:%i]: %s encountered while translating " "addr:%08p for [sn:%i].\n", tid, tlb_req->fault->name(), tlb_req->memReq->getVaddr(), seq_num); //insert(inst); @@ -144,7 +144,7 @@ TLBUnit::execute(int slot_idx) // Let CPU handle the fault cpu->trap(tlb_req->fault, tid); } else { - DPRINTF(Resource, "[tid:%i]: [sn:%i] virt. addr %08p translated " + DPRINTF(InOrderTLB, "[tid:%i]: [sn:%i] virt. addr %08p translated " "to phys. addr:%08p.\n", tid, seq_num, tlb_req->memReq->getVaddr(), tlb_req->memReq->getPaddr()); @@ -169,7 +169,7 @@ TLBUnitEvent::process() int stage_num = resource->reqMap[slotIdx]->getStageNum(); int tid = inst->threadNumber; - DPRINTF(Resource, "Waking up from TLB Miss caused by [sn:%i].\n", + DPRINTF(InOrderTLB, "Waking up from TLB Miss caused by [sn:%i].\n", inst->seqNum); TLBUnit* tlb_res = dynamic_cast(resource); diff --git a/src/cpu/inorder/resources/use_def.cc b/src/cpu/inorder/resources/use_def.cc index ed697c4ca..a9281a18c 100644 --- a/src/cpu/inorder/resources/use_def.cc +++ b/src/cpu/inorder/resources/use_def.cc @@ -104,7 +104,7 @@ UseDefUnit::execute(int slot_idx) // in the pipeline then stall instructions here if (*nonSpecInstActive[tid] == true && seq_num > *nonSpecSeqNum[tid]) { - DPRINTF(Resource, "[tid:%i]: [sn:%i] cannot execute because there is " + DPRINTF(InOrderUseDef, "[tid:%i]: [sn:%i] cannot execute because there is " "non-speculative instruction [sn:%i] has not graduated.\n", tid, seq_num, *nonSpecSeqNum[tid]); return; @@ -119,7 +119,7 @@ UseDefUnit::execute(int slot_idx) { int reg_idx = inst->_srcRegIdx[ud_idx]; - DPRINTF(Resource, "[tid:%i]: Attempting to read source register idx %i.\n", + DPRINTF(InOrderUseDef, "[tid:%i]: Attempting to read source register idx %i.\n", tid, ud_idx); // Ask register dependency map if it is OK to read from Arch. Reg. File @@ -127,19 +127,19 @@ UseDefUnit::execute(int slot_idx) // Read From Register File if (inst->seqNum <= outReadSeqNum[tid]) { if (reg_idx <= FP_Base_DepTag) { - DPRINTF(Resource, "[tid:%i]: Reading Int Reg %i from Register File.\n", + DPRINTF(InOrderUseDef, "[tid:%i]: Reading Int Reg %i from Register File.\n", tid, reg_idx); inst->setIntSrc(ud_idx, cpu->readIntReg(reg_idx,inst->readTid())); } else if (reg_idx <= Ctrl_Base_DepTag) { reg_idx -= FP_Base_DepTag; - DPRINTF(Resource, "[tid:%i]: Reading Float Reg %i from Register File.\n", + DPRINTF(InOrderUseDef, "[tid:%i]: Reading Float Reg %i from Register File.\n", tid, reg_idx); inst->setIntSrc(ud_idx, // Always Read FloatRegBits For Now cpu->readFloatRegBits(reg_idx, inst->readTid())); } else { reg_idx -= Ctrl_Base_DepTag; - DPRINTF(Resource, "[tid:%i]: Reading Misc Reg %i from Register File.\n", + DPRINTF(InOrderUseDef, "[tid:%i]: Reading Misc Reg %i from Register File.\n", tid, reg_idx); inst->setIntSrc(ud_idx, cpu->readMiscReg(reg_idx, inst->readTid())); @@ -149,7 +149,7 @@ UseDefUnit::execute(int slot_idx) ud_req->done(); } else { - DPRINTF(Resource, "[tid:%i]: Unable to read because of [sn:%i] hasnt read it's" + DPRINTF(InOrderUseDef, "[tid:%i]: Unable to read because of [sn:%i] hasnt read it's" " registers yet.\n", tid, outReadSeqNum[tid]); DPRINTF(InOrderStall, "STALL: [tid:%i]: waiting for [sn:%i] to write\n", tid, outReadSeqNum[tid]); @@ -164,19 +164,19 @@ UseDefUnit::execute(int slot_idx) int dest_reg_idx = forward_inst->getDestIdxNum(reg_idx); if (reg_idx <= FP_Base_DepTag) { - DPRINTF(Resource, "[tid:%i]: Forwarding dest. reg value 0x%x from " + DPRINTF(InOrderUseDef, "[tid:%i]: Forwarding dest. reg value 0x%x from " "[sn:%i] to [sn:%i] source #%i.\n", tid, forward_inst->readIntResult(dest_reg_idx) , forward_inst->seqNum, inst->seqNum, ud_idx); inst->setIntSrc(ud_idx, forward_inst->readIntResult(dest_reg_idx)); } else if (reg_idx <= Ctrl_Base_DepTag) { - DPRINTF(Resource, "[tid:%i]: Forwarding dest. reg value 0x%x from " + DPRINTF(InOrderUseDef, "[tid:%i]: Forwarding dest. reg value 0x%x from " "[sn:%i] to [sn:%i] source #%i.\n", tid, forward_inst->readFloatResult(dest_reg_idx) , forward_inst->seqNum, inst->seqNum, ud_idx); inst->setFloatSrc(ud_idx, forward_inst->readFloatResult(dest_reg_idx)); } else { - DPRINTF(Resource, "[tid:%i]: Forwarding dest. reg value 0x%x from " + DPRINTF(InOrderUseDef, "[tid:%i]: Forwarding dest. reg value 0x%x from " "[sn:%i] to [sn:%i] source #%i.\n", tid, forward_inst->readIntResult(dest_reg_idx) , forward_inst->seqNum, inst->seqNum, ud_idx); @@ -187,13 +187,13 @@ UseDefUnit::execute(int slot_idx) ud_req->done(); } else { - DPRINTF(Resource, "[tid:%i]: Unable to read because of [sn:%i] hasnt read it's" + DPRINTF(InOrderUseDef, "[tid:%i]: Unable to read because of [sn:%i] hasnt read it's" " registers yet.\n", tid, outReadSeqNum[tid]); DPRINTF(InOrderStall, "STALL: [tid:%i]: waiting for [sn:%i] to forward\n", tid, outReadSeqNum[tid]); } } else { - DPRINTF(Resource, "[tid:%i]: Source register idx: %i is not ready to read.\n", + DPRINTF(InOrderUseDef, "[tid:%i]: Source register idx: %i is not ready to read.\n", tid, reg_idx); DPRINTF(InOrderStall, "STALL: [tid:%i]: waiting to read register (idx=%i)\n", tid, reg_idx); @@ -208,12 +208,12 @@ UseDefUnit::execute(int slot_idx) int reg_idx = inst->_destRegIdx[ud_idx]; if (regDepMap[tid]->canWrite(reg_idx, inst)) { - DPRINTF(Resource, "[tid:%i]: Attempting to write to Register File.\n", + DPRINTF(InOrderUseDef, "[tid:%i]: Attempting to write to Register File.\n", tid); if (inst->seqNum <= outReadSeqNum[tid]) { if (reg_idx <= FP_Base_DepTag) { - DPRINTF(Resource, "[tid:%i]: Writing 0x%x to register idx %i.\n", + DPRINTF(InOrderUseDef, "[tid:%i]: Writing 0x%x to register idx %i.\n", tid, inst->readIntResult(ud_idx), reg_idx); // Remove Dependencies @@ -246,13 +246,13 @@ UseDefUnit::execute(int slot_idx) ud_req->done(); } else { - DPRINTF(Resource, "[tid:%i]: Unable to write because of [sn:%i] hasnt read it's" + DPRINTF(InOrderUseDef, "[tid:%i]: Unable to write because of [sn:%i] hasnt read it's" " registers yet.\n", tid, outReadSeqNum); DPRINTF(InOrderStall, "STALL: [tid:%i]: waiting for [sn:%i] to read\n", tid, outReadSeqNum); } } else { - DPRINTF(Resource, "[tid:%i]: Dest. register idx: %i is not ready to write.\n", + DPRINTF(InOrderUseDef, "[tid:%i]: Dest. register idx: %i is not ready to write.\n", tid, reg_idx); DPRINTF(InOrderStall, "STALL: [tid:%i]: waiting to write register (idx=%i)\n", tid, reg_idx); @@ -270,7 +270,7 @@ UseDefUnit::execute(int slot_idx) void UseDefUnit::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num, unsigned tid) { - DPRINTF(Resource, "[tid:%i]: Updating Due To Squash After [sn:%i].\n", + DPRINTF(InOrderUseDef, "[tid:%i]: Updating Due To Squash After [sn:%i].\n", tid, squash_seq_num); std::vector slot_remove_list; @@ -285,7 +285,7 @@ UseDefUnit::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num, un req_ptr->getInst()->readTid() == tid && req_ptr->getInst()->seqNum > squash_seq_num) { - DPRINTF(Resource, "[tid:%i]: Squashing [sn:%i].\n", + DPRINTF(InOrderUseDef, "[tid:%i]: Squashing [sn:%i].\n", req_ptr->getInst()->readTid(), req_ptr->getInst()->seqNum); @@ -309,18 +309,18 @@ UseDefUnit::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num, un } if (outReadSeqNum[tid] >= squash_seq_num) { - DPRINTF(Resource, "[tid:%i]: Outstanding Read Seq Num Reset.\n", tid); + DPRINTF(InOrderUseDef, "[tid:%i]: Outstanding Read Seq Num Reset.\n", tid); outReadSeqNum[tid] = maxSeqNum; } else if (outReadSeqNum[tid] != maxSeqNum) { - DPRINTF(Resource, "[tid:%i]: No need to reset Outstanding Read Seq Num %i\n", + DPRINTF(InOrderUseDef, "[tid:%i]: No need to reset Outstanding Read Seq Num %i\n", tid, outReadSeqNum[tid]); } if (outWriteSeqNum[tid] >= squash_seq_num) { - DPRINTF(Resource, "[tid:%i]: Outstanding Write Seq Num Reset.\n", tid); + DPRINTF(InOrderUseDef, "[tid:%i]: Outstanding Write Seq Num Reset.\n", tid); outWriteSeqNum[tid] = maxSeqNum; } else if (outWriteSeqNum[tid] != maxSeqNum) { - DPRINTF(Resource, "[tid:%i]: No need to reset Outstanding Write Seq Num %i\n", + DPRINTF(InOrderUseDef, "[tid:%i]: No need to reset Outstanding Write Seq Num %i\n", tid, outWriteSeqNum[tid]); } } -- cgit v1.2.3 From 9e1dc7f20549e9590c5b1450be17ff03057e346f Mon Sep 17 00:00:00 2001 From: Korey Sewell Date: Wed, 4 Mar 2009 22:37:45 -0500 Subject: InOrderCPU: Clean up Constructors to initialize variables correctly (i.e. in a way for the compiler to play *nice*) --- src/cpu/inorder/cpu.cc | 6 ++---- src/cpu/inorder/first_stage.cc | 7 ++----- src/cpu/inorder/inorder_dyn_inst.cc | 6 ++---- src/cpu/inorder/pipeline_stage.cc | 21 ++++++--------------- src/cpu/inorder/pipeline_stage.hh | 2 +- src/cpu/inorder/resources/cache_unit.cc | 7 +------ src/cpu/inorder/resources/fetch_seq_unit.cc | 5 ++--- src/cpu/inorder/resources/graduation_unit.cc | 7 +++---- src/cpu/inorder/resources/mult_div_unit.cc | 27 ++++++++------------------- src/cpu/inorder/resources/mult_div_unit.hh | 10 +++++----- src/cpu/inorder/thread_context.hh | 1 + 11 files changed, 33 insertions(+), 66 deletions(-) (limited to 'src') diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc index 7dafd826f..70877aae4 100644 --- a/src/cpu/inorder/cpu.cc +++ b/src/cpu/inorder/cpu.cc @@ -147,6 +147,8 @@ InOrderCPU::CPUEvent::unscheduleEvent() InOrderCPU::InOrderCPU(Params *params) : BaseCPU(params), cpu_id(params->cpu_id), + coreType("default"), + _status(Idle), tickEvent(this), miscRegFile(this), timeBuffer(2 , 2), @@ -162,10 +164,6 @@ InOrderCPU::InOrderCPU(Params *params) resPool = new ResourcePool(this, params); - coreType = "default"; // eventually get this from params - - _status = Idle; - // Resize for Multithreading CPUs thread.resize(numThreads); diff --git a/src/cpu/inorder/first_stage.cc b/src/cpu/inorder/first_stage.cc index be4431a03..5e389b256 100644 --- a/src/cpu/inorder/first_stage.cc +++ b/src/cpu/inorder/first_stage.cc @@ -40,15 +40,12 @@ using namespace std; using namespace ThePipeline; FirstStage::FirstStage(Params *params, unsigned stage_num) - : PipelineStage(params, stage_num) + : PipelineStage(params, stage_num), numFetchingThreads(1), + fetchPolicy(FirstStage::RoundRobin) { for(int tid=0; tid < this->numThreads; tid++) { stageStatus[tid] = Running; } - - numFetchingThreads = 1; - - fetchPolicy = RoundRobin; } void diff --git a/src/cpu/inorder/inorder_dyn_inst.cc b/src/cpu/inorder/inorder_dyn_inst.cc index d292d72f0..ceb3cbe51 100644 --- a/src/cpu/inorder/inorder_dyn_inst.cc +++ b/src/cpu/inorder/inorder_dyn_inst.cc @@ -76,16 +76,14 @@ InOrderDynInst::InOrderDynInst(InOrderCPU *cpu, } InOrderDynInst::InOrderDynInst(StaticInstPtr &_staticInst) - : staticInst(_staticInst), traceData(NULL) + : seqNum(0), staticInst(_staticInst), traceData(NULL) { - seqNum = 0; initVars(); } InOrderDynInst::InOrderDynInst() - : traceData(NULL), cpu(cpu) + : seqNum(0), traceData(NULL), cpu(cpu) { - seqNum = 0; initVars(); } diff --git a/src/cpu/inorder/pipeline_stage.cc b/src/cpu/inorder/pipeline_stage.cc index ab7328f4a..cb69464b0 100644 --- a/src/cpu/inorder/pipeline_stage.cc +++ b/src/cpu/inorder/pipeline_stage.cc @@ -38,24 +38,17 @@ using namespace std; using namespace ThePipeline; PipelineStage::PipelineStage(Params *params, unsigned stage_num) + : stageNum(stage_num), stageWidth(ThePipeline::StageWidth), + numThreads(ThePipeline::MaxThreads), _status(Inactive), + stageBufferMax(ThePipeline::interStageBuffSize[stage_num]), + prevStageValid(false), nextStageValid(false) { - init(params, stage_num); + init(params); } void -PipelineStage::init(Params *params, unsigned stage_num) +PipelineStage::init(Params *params) { - stageNum = stage_num; - stageWidth = ThePipeline::StageWidth; - - _status = Inactive; - - numThreads = ThePipeline::MaxThreads; - - prevStageValid = false; - nextStageValid = false; - - // Init. structures for(int tid=0; tid < numThreads; tid++) { stageStatus[tid] = Idle; @@ -69,8 +62,6 @@ PipelineStage::init(Params *params, unsigned stage_num) else lastStallingStage[tid] = NumStages - 1; } - - stageBufferMax = ThePipeline::interStageBuffSize[stage_num]; } diff --git a/src/cpu/inorder/pipeline_stage.hh b/src/cpu/inorder/pipeline_stage.hh index 19bf8154f..2fd8f2215 100644 --- a/src/cpu/inorder/pipeline_stage.hh +++ b/src/cpu/inorder/pipeline_stage.hh @@ -97,7 +97,7 @@ class PipelineStage virtual ~PipelineStage() { } /** PipelineStage initialization. */ - void init(Params *params, unsigned stage_num); + void init(Params *params); /** Returns the name of stage. */ std::string name() const; diff --git a/src/cpu/inorder/resources/cache_unit.cc b/src/cpu/inorder/resources/cache_unit.cc index 6fd7ae36c..57bcb10ef 100644 --- a/src/cpu/inorder/resources/cache_unit.cc +++ b/src/cpu/inorder/resources/cache_unit.cc @@ -81,14 +81,9 @@ CacheUnit::CachePort::recvRetry() CacheUnit::CacheUnit(string res_name, int res_id, int res_width, int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params) : Resource(res_name, res_id, res_width, res_latency, _cpu), - retryPkt(NULL), retrySlot(-1) + retryPkt(NULL), retrySlot(-1), cacheBlocked(false) { - //cacheData.resize(res_width); - //slotStatus = new CachePortStatus[width]; - //fetchPC = new Addr[width]; cachePort = new CachePort(this); - - cacheBlocked = false; } Port * diff --git a/src/cpu/inorder/resources/fetch_seq_unit.cc b/src/cpu/inorder/resources/fetch_seq_unit.cc index 36cf714c9..444252e1b 100644 --- a/src/cpu/inorder/resources/fetch_seq_unit.cc +++ b/src/cpu/inorder/resources/fetch_seq_unit.cc @@ -38,10 +38,9 @@ using namespace ThePipeline; FetchSeqUnit::FetchSeqUnit(std::string res_name, int res_id, int res_width, int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params) - : Resource(res_name, res_id, res_width, res_latency, _cpu) + : Resource(res_name, res_id, res_width, res_latency, _cpu), + instSize(sizeof(MachInst)) { - instSize = sizeof(MachInst); - for (int tid = 0; tid < ThePipeline::MaxThreads; tid++) { delaySlotInfo[tid].numInsts = 0; delaySlotInfo[tid].targetReady = false; diff --git a/src/cpu/inorder/resources/graduation_unit.cc b/src/cpu/inorder/resources/graduation_unit.cc index 701da5996..569401e4f 100644 --- a/src/cpu/inorder/resources/graduation_unit.cc +++ b/src/cpu/inorder/resources/graduation_unit.cc @@ -35,11 +35,10 @@ using namespace ThePipeline; GraduationUnit::GraduationUnit(std::string res_name, int res_id, int res_width, int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params) - : Resource(res_name, res_id, res_width, res_latency, _cpu) + : Resource(res_name, res_id, res_width, res_latency, _cpu), + lastCycleGrad(0), numCycleGrad(0) + { - lastCycleGrad = 0; - numCycleGrad = 0; - for (int tid = 0; tid < ThePipeline::MaxThreads; tid++) { nonSpecInstActive[tid] = &cpu->nonSpecInstActive[tid]; nonSpecSeqNum[tid] = &cpu->nonSpecSeqNum[tid]; diff --git a/src/cpu/inorder/resources/mult_div_unit.cc b/src/cpu/inorder/resources/mult_div_unit.cc index e98e97be7..b31d60ad5 100644 --- a/src/cpu/inorder/resources/mult_div_unit.cc +++ b/src/cpu/inorder/resources/mult_div_unit.cc @@ -41,25 +41,14 @@ using namespace ThePipeline; MultDivUnit::MultDivUnit(string res_name, int res_id, int res_width, int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params) - : Resource(res_name, res_id, res_width, res_latency, _cpu) -{ - multRepeatRate = params->multRepeatRate; - multLatency = params->multLatency; - - div8RepeatRate = params->div8RepeatRate; - div8Latency = params->div8Latency; - - div16RepeatRate = params->div16RepeatRate; - div16Latency = params->div16Latency; - - div24RepeatRate = params->div24RepeatRate; - div24Latency = params->div24Latency; - - div32RepeatRate = params->div32RepeatRate; - div32Latency = params->div32Latency; - - lastMDUCycle = 0; -} + : Resource(res_name, res_id, res_width, res_latency, _cpu), + multRepeatRate(params->multRepeatRate), multLatency(params->multLatency), + div8RepeatRate(params->div8RepeatRate), div8Latency(params->div8Latency), + div16RepeatRate(params->div16RepeatRate), div16Latency(params->div16Latency), + div24RepeatRate(params->div24RepeatRate), div24Latency(params->div24Latency), + div32RepeatRate(params->div32RepeatRate), div32Latency(params->div32Latency), + lastMDUCycle(0) +{ } void MultDivUnit::regStats() diff --git a/src/cpu/inorder/resources/mult_div_unit.hh b/src/cpu/inorder/resources/mult_div_unit.hh index 762442c4b..003f6fbb1 100644 --- a/src/cpu/inorder/resources/mult_div_unit.hh +++ b/src/cpu/inorder/resources/mult_div_unit.hh @@ -84,24 +84,24 @@ class MultDivUnit : public Resource { protected: /** Latency & Repeat Rate for Multiply Insts */ - unsigned multLatency; unsigned multRepeatRate; + unsigned multLatency; /** Latency & Repeat Rate for 8-bit Divide Insts */ - unsigned div8Latency; unsigned div8RepeatRate; + unsigned div8Latency; /** Latency & Repeat Rate for 16-bit Divide Insts */ - unsigned div16Latency; unsigned div16RepeatRate; + unsigned div16Latency; /** Latency & Repeat Rate for 24-bit Divide Insts */ - unsigned div24Latency; unsigned div24RepeatRate; + unsigned div24Latency; /** Latency & Repeat Rate for 32-bit Divide Insts */ - unsigned div32Latency; unsigned div32RepeatRate; + unsigned div32Latency; /** Last cycle that MDU was used */ Tick lastMDUCycle; diff --git a/src/cpu/inorder/thread_context.hh b/src/cpu/inorder/thread_context.hh index 8b3b47290..2fb2ed85f 100644 --- a/src/cpu/inorder/thread_context.hh +++ b/src/cpu/inorder/thread_context.hh @@ -132,6 +132,7 @@ class InOrderThreadContext : public ThreadContext /** Serializes state. */ virtual void serialize(std::ostream &os); + /** Unserializes state. */ virtual void unserialize(Checkpoint *cp, const std::string §ion); -- cgit v1.2.3 From e3d6e8882e02d607ed69108d4bc1301de9c2de56 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Thu, 5 Mar 2009 17:15:31 -0800 Subject: Get rid of 'using namespace' declarations in headers. --- src/arch/alpha/linux/system.hh | 5 +---- src/arch/mips/bare_iron/system.hh | 2 -- src/arch/mips/isa_traits.hh | 2 -- src/arch/mips/linux/linux.hh | 3 --- src/arch/mips/linux/system.hh | 5 +---- src/arch/mips/mt.hh | 3 +-- src/arch/mips/regfile/misc_regfile.cc | 1 + src/cpu/inorder/resources/fetch_seq_unit.hh | 2 -- 8 files changed, 4 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/linux/system.hh b/src/arch/alpha/linux/system.hh index fa03736c3..3e4de7b2a 100644 --- a/src/arch/alpha/linux/system.hh +++ b/src/arch/alpha/linux/system.hh @@ -43,9 +43,6 @@ class IdleStartEvent; #include "kern/linux/events.hh" #include "params/LinuxAlphaSystem.hh" -using namespace AlphaISA; -using namespace Linux; - /** * This class contains linux specific system code (Loading, Events). * It points to objects that are the system binaries to load and patches them @@ -109,7 +106,7 @@ class LinuxAlphaSystem : public AlphaSystem * PC based event to skip the dprink() call and emulate its * functionality */ - DebugPrintkEvent *debugPrintkEvent; + Linux::DebugPrintkEvent *debugPrintkEvent; /** * Skip calculate_delay_loop() rather than waiting for this to be diff --git a/src/arch/mips/bare_iron/system.hh b/src/arch/mips/bare_iron/system.hh index ab4e02344..e593f832c 100755 --- a/src/arch/mips/bare_iron/system.hh +++ b/src/arch/mips/bare_iron/system.hh @@ -39,8 +39,6 @@ class IdleStartEvent; #include "arch/mips/system.hh" #include "params/BareIronMipsSystem.hh" -using namespace MipsISA; - /** * This class contains linux specific system code (Loading, Events). * It points to objects that are the system binaries to load and patches them diff --git a/src/arch/mips/isa_traits.hh b/src/arch/mips/isa_traits.hh index ed4ed9877..12c887132 100644 --- a/src/arch/mips/isa_traits.hh +++ b/src/arch/mips/isa_traits.hh @@ -381,6 +381,4 @@ namespace MipsISA }; -using namespace MipsISA; - #endif // __ARCH_MIPS_ISA_TRAITS_HH__ diff --git a/src/arch/mips/linux/linux.hh b/src/arch/mips/linux/linux.hh index 4667748fb..aaeba0a42 100644 --- a/src/arch/mips/linux/linux.hh +++ b/src/arch/mips/linux/linux.hh @@ -32,9 +32,6 @@ #define __ARCH_MIPS_LINUX_LINUX_HH__ #include "kern/linux/linux.hh" -#include - -using std::string; class MipsLinux : public Linux { diff --git a/src/arch/mips/linux/system.hh b/src/arch/mips/linux/system.hh index 24fb604ed..984f74694 100644 --- a/src/arch/mips/linux/system.hh +++ b/src/arch/mips/linux/system.hh @@ -43,9 +43,6 @@ class IdleStartEvent; #include "kern/linux/events.hh" #include "params/LinuxMipsSystem.hh" -using namespace MipsISA; -using namespace Linux; - /** * This class contains linux specific system code (Loading, Events). * It points to objects that are the system binaries to load and patches them @@ -112,7 +109,7 @@ class LinuxMipsSystem : public MipsSystem * PC based event to skip the dprink() call and emulate its * functionality */ - DebugPrintkEvent *debugPrintkEvent; + Linux::DebugPrintkEvent *debugPrintkEvent; /** * Skip calculate_delay_loop() rather than waiting for this to be diff --git a/src/arch/mips/mt.hh b/src/arch/mips/mt.hh index 8828a09a5..d0c333d86 100755 --- a/src/arch/mips/mt.hh +++ b/src/arch/mips/mt.hh @@ -45,7 +45,6 @@ #include "base/misc.hh" #include -using namespace std; namespace MipsISA { @@ -164,7 +163,7 @@ forkThread(TC *tc, Fault &fault, int Rd_bits, int Rs, int Rt) success = 1; } } else { - std::cerr << "Bad VPEs" << endl; + std::cerr << "Bad VPEs" << std::endl; } } diff --git a/src/arch/mips/regfile/misc_regfile.cc b/src/arch/mips/regfile/misc_regfile.cc index ea858abf0..a00bf166e 100644 --- a/src/arch/mips/regfile/misc_regfile.cc +++ b/src/arch/mips/regfile/misc_regfile.cc @@ -43,6 +43,7 @@ //#include "params/DerivO3CPU.hh" using namespace std; +using namespace MipsISA; std::string MiscRegFile::miscRegNames[NumMiscRegs] = { diff --git a/src/cpu/inorder/resources/fetch_seq_unit.hh b/src/cpu/inorder/resources/fetch_seq_unit.hh index 2b074bbaa..1885d1f11 100644 --- a/src/cpu/inorder/resources/fetch_seq_unit.hh +++ b/src/cpu/inorder/resources/fetch_seq_unit.hh @@ -41,8 +41,6 @@ #include "cpu/inorder/pipeline_traits.hh" #include "cpu/inorder/cpu.hh" -using namespace ThePipeline; - class FetchSeqUnit : public Resource { public: typedef ThePipeline::DynInstPtr DynInstPtr; -- cgit v1.2.3 From a767819d56c1a42ed3581bd63df384f8daa342e5 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 5 Mar 2009 19:09:53 -0800 Subject: serialize: Allow floats and doubles to be serialized --- src/sim/serialize.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/sim/serialize.cc b/src/sim/serialize.cc index ee9b04236..481b9af3b 100644 --- a/src/sim/serialize.cc +++ b/src/sim/serialize.cc @@ -351,6 +351,8 @@ INSTANTIATE_PARAM_TEMPLATES(unsigned long) INSTANTIATE_PARAM_TEMPLATES(signed long long) INSTANTIATE_PARAM_TEMPLATES(unsigned long long) INSTANTIATE_PARAM_TEMPLATES(bool) +INSTANTIATE_PARAM_TEMPLATES(float) +INSTANTIATE_PARAM_TEMPLATES(double) INSTANTIATE_PARAM_TEMPLATES(string) -- cgit v1.2.3 From ec209953e7232b9ef41969f468ebe560cd4e0667 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 5 Mar 2009 19:09:53 -0800 Subject: stats: miscellaneous cleanup --- src/base/statistics.hh | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/base/statistics.hh b/src/base/statistics.hh index 15b6c032a..78028cc0c 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -468,7 +468,7 @@ class Wrap : public Child /** * Set the precision and marks this stat to print at the end of simulation. - * @param p The new precision + * @param _precision The new precision * @return A reference to this stat. */ Parent & @@ -728,7 +728,7 @@ class AvgStor void reset(Info *info) { - total = 0; + total = 0.0; last = curTick; } @@ -1253,7 +1253,7 @@ class VectorProxy Result total() const { - Result total = 0; + Result total = 0.0; for (off_type i = 0; i < size(); ++i) total += data(i)->result(); return total; @@ -1471,7 +1471,6 @@ class DistStor * Add a value to the distribution for the given number of times. * @param val The value to add. * @param number The number of times to add the value. - * @param params The paramters of the distribution. */ void sample(Counter val, int number) @@ -1595,7 +1594,6 @@ class FancyStor * values seen by the given number. * @param val The value to add. * @param number The number of times to add the value. - * @param p The parameters of this stat. */ void sample(Counter val, int number) @@ -1973,7 +1971,7 @@ template Result VectorDistBase::total(off_type index) const { - Result total = 0; + Result total = 0.0; for (off_type i = 0; i < x_size(); ++i) total += data(i)->result(); } @@ -2215,7 +2213,7 @@ class UnaryNode : public Node total() const { const VResult &vec = this->result(); - Result total = 0; + Result total = 0.0; for (off_type i = 0; i < size(); i++) total += vec[i]; return total; @@ -2277,7 +2275,7 @@ class BinaryNode : public Node total() const { const VResult &vec = this->result(); - Result total = 0; + Result total = 0.0; for (off_type i = 0; i < size(); i++) total += vec[i]; return total; @@ -2853,7 +2851,7 @@ class Temp * Return the node pointer. * @return the node pointer. */ - operator NodePtr&() { return node;} + operator NodePtr&() { return node; } public: /** -- cgit v1.2.3 From 2dd5a5b3dc1f35fc61ec9cf7760c04cbe586a6b3 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 5 Mar 2009 19:09:53 -0800 Subject: stats: get rid of meaningless uses of virtual --- src/base/statistics.hh | 158 ++++++++++++++++++++++++------------------------- 1 file changed, 79 insertions(+), 79 deletions(-) (limited to 'src') diff --git a/src/base/statistics.hh b/src/base/statistics.hh index 78028cc0c..8a0079b27 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -155,7 +155,7 @@ class ScalarInfoBase : public Info virtual Counter value() const = 0; virtual Result result() const = 0; virtual Result total() const = 0; - virtual void visit(Visit &visitor) { visitor.visit(*this); } + void visit(Visit &visitor) { visitor.visit(*this); } }; template @@ -167,12 +167,12 @@ class ScalarInfo : public ScalarInfoBase public: ScalarInfo(Stat &stat) : s(stat) {} - virtual bool check() const { return s.check(); } - virtual Counter value() const { return s.value(); } - virtual Result result() const { return s.result(); } - virtual Result total() const { return s.total(); } - virtual void reset() { s.reset(); } - virtual bool zero() const { return s.zero(); } + bool check() const { return s.check(); } + Counter value() const { return s.value(); } + Result result() const { return s.result(); } + Result total() const { return s.total(); } + void reset() { s.reset(); } + bool zero() const { return s.zero(); } }; class VectorInfoBase : public Info @@ -183,10 +183,10 @@ class VectorInfoBase : public Info mutable std::vector subdescs; public: - virtual size_type size() const = 0; + virtual size_type size() const = 0; virtual const VCounter &value() const = 0; virtual const VResult &result() const = 0; - virtual Result total() const = 0; + virtual Result total() const = 0; void update() @@ -213,29 +213,29 @@ class VectorInfo : public VectorInfoBase public: VectorInfo(Stat &stat) : s(stat) {} - virtual bool check() const { return s.check(); } - virtual bool zero() const { return s.zero(); } - virtual void reset() { s.reset(); } + bool check() const { return s.check(); } + bool zero() const { return s.zero(); } + void reset() { s.reset(); } - virtual size_type size() const { return s.size(); } + size_type size() const { return s.size(); } - virtual VCounter & + VCounter & value() const { s.value(cvec); return cvec; } - virtual const VResult & + const VResult & result() const { s.result(rvec); return rvec; } - virtual Result total() const { return s.total(); } + Result total() const { return s.total(); } - virtual void + void visit(Visit &visitor) { update(); @@ -274,11 +274,11 @@ class DistInfo : public DistInfoBase public: DistInfo(Stat &stat) : s(stat) {} - virtual bool check() const { return s.check(); } - virtual void reset() { s.reset(); } - virtual bool zero() const { return s.zero(); } + bool check() const { return s.check(); } + void reset() { s.reset(); } + bool zero() const { return s.zero(); } - virtual void + void visit(Visit &visitor) { s.update(this); @@ -323,12 +323,12 @@ class VectorDistInfo : public VectorDistInfoBase public: VectorDistInfo(Stat &stat) : s(stat) {} - virtual bool check() const { return s.check(); } - virtual void reset() { s.reset(); } - virtual size_type size() const { return s.size(); } - virtual bool zero() const { return s.zero(); } + bool check() const { return s.check(); } + void reset() { s.reset(); } + size_type size() const { return s.size(); } + bool zero() const { return s.zero(); } - virtual void + void visit(Visit &visitor) { update(); @@ -368,11 +368,11 @@ class Vector2dInfo : public Vector2dInfoBase public: Vector2dInfo(Stat &stat) : s(stat) {} - virtual bool check() const { return s.check(); } - virtual void reset() { s.reset(); } - virtual bool zero() const { return s.zero(); } + bool check() const { return s.check(); } + void reset() { s.reset(); } + bool zero() const { return s.zero(); } - virtual void + void visit(Visit &visitor) { update(); @@ -862,12 +862,12 @@ class ScalarBase : public InfoAccess class ProxyInfo : public ScalarInfoBase { public: - virtual void visit(Visit &visitor) { visitor.visit(*this); } - virtual std::string str() const { return to_string(value()); } - virtual size_type size() const { return 1; } - virtual bool zero() const { return value() == 0; } - virtual bool check() const { return true; } - virtual void reset() { } + void visit(Visit &visitor) { visitor.visit(*this); } + std::string str() const { return to_string(value()); } + size_type size() const { return 1; } + bool zero() const { return value() == 0; } + bool check() const { return true; } + void reset() { } }; template @@ -878,9 +878,9 @@ class ValueProxy : public ProxyInfo public: ValueProxy(T &val) : scalar(&val) {} - virtual Counter value() const { return *scalar; } - virtual Result result() const { return *scalar; } - virtual Result total() const { return *scalar; } + Counter value() const { return *scalar; } + Result result() const { return *scalar; } + Result total() const { return *scalar; } }; template @@ -891,9 +891,9 @@ class FunctorProxy : public ProxyInfo public: FunctorProxy(T &func) : functor(&func) {} - virtual Counter value() const { return (*functor)(); } - virtual Result result() const { return (*functor)(); } - virtual Result total() const { return (*functor)(); } + Counter value() const { return (*functor)(); } + Result result() const { return (*functor)(); } + Result total() const { return (*functor)(); } }; class ValueBase : public InfoAccess @@ -2024,21 +2024,21 @@ class ScalarStatNode : public Node public: ScalarStatNode(const ScalarInfoBase *d) : data(d), vresult(1) {} - virtual const VResult & + const VResult & result() const { vresult[0] = data->result(); return vresult; } - virtual Result total() const { return data->result(); }; + Result total() const { return data->result(); }; - virtual size_type size() const { return 1; } + size_type size() const { return 1; } /** * */ - virtual std::string str() const { return data->name; } + std::string str() const { return data->name; } }; template @@ -2053,20 +2053,20 @@ class ScalarProxyNode : public Node : proxy(p), vresult(1) { } - virtual const VResult & + const VResult & result() const { vresult[0] = proxy.result(); return vresult; } - virtual Result + Result total() const { return proxy.result(); } - virtual size_type + size_type size() const { return 1; @@ -2075,7 +2075,7 @@ class ScalarProxyNode : public Node /** * */ - virtual std::string + std::string str() const { return proxy.str(); @@ -2089,12 +2089,12 @@ class VectorStatNode : public Node public: VectorStatNode(const VectorInfoBase *d) : data(d) { } - virtual const VResult &result() const { return data->result(); } - virtual Result total() const { return data->total(); }; + const VResult &result() const { return data->result(); } + Result total() const { return data->total(); }; - virtual size_type size() const { return data->size(); } + size_type size() const { return data->size(); } - virtual std::string str() const { return data->name; } + std::string str() const { return data->name; } }; template @@ -2106,9 +2106,9 @@ class ConstNode : public Node public: ConstNode(T s) : vresult(1, (Result)s) {} const VResult &result() const { return vresult; } - virtual Result total() const { return vresult[0]; }; - virtual size_type size() const { return 1; } - virtual std::string str() const { return to_string(vresult[0]); } + Result total() const { return vresult[0]; }; + size_type size() const { return 1; } + std::string str() const { return to_string(vresult[0]); } }; template @@ -2121,7 +2121,7 @@ class ConstVectorNode : public Node ConstVectorNode(const T &s) : vresult(s.begin(), s.end()) {} const VResult &result() const { return vresult; } - virtual Result + Result total() const { size_type size = this->size(); @@ -2131,8 +2131,8 @@ class ConstVectorNode : public Node return tmp; } - virtual size_type size() const { return vresult.size(); } - virtual std::string + size_type size() const { return vresult.size(); } + std::string str() const { size_type size = this->size(); @@ -2219,9 +2219,9 @@ class UnaryNode : public Node return total; } - virtual size_type size() const { return l->size(); } + size_type size() const { return l->size(); } - virtual std::string + std::string str() const { return OpString::str() + l->str(); @@ -2281,7 +2281,7 @@ class BinaryNode : public Node return total; } - virtual size_type + size_type size() const { size_type ls = l->size(); @@ -2296,7 +2296,7 @@ class BinaryNode : public Node } } - virtual std::string + std::string str() const { return csprintf("(%s %s %s)", l->str(), OpString::str(), r->str()); @@ -2345,9 +2345,9 @@ class SumNode : public Node return vresult; } - virtual size_type size() const { return 1; } + size_type size() const { return 1; } - virtual std::string + std::string str() const { return csprintf("total(%s)", l->str()); @@ -2740,7 +2740,7 @@ class FormulaInfoBase : public VectorInfoBase { public: virtual std::string str() const = 0; - virtual bool check() const { return true; } + bool check() const { return true; } }; template @@ -2754,21 +2754,21 @@ class FormulaInfo : public FormulaInfoBase public: FormulaInfo(Stat &stat) : s(stat) {} - virtual bool zero() const { return s.zero(); } - virtual void reset() { s.reset(); } + bool zero() const { return s.zero(); } + void reset() { s.reset(); } - virtual size_type size() const { return s.size(); } + size_type size() const { return s.size(); } - virtual const VResult & + const VResult & result() const { s.result(vec); return vec; } - virtual Result total() const { return s.total(); } - virtual VCounter &value() const { return cvec; } + Result total() const { return s.total(); } + VCounter &value() const { return cvec; } - virtual void + void visit(Visit &visitor) { update(); @@ -2776,7 +2776,7 @@ class FormulaInfo : public FormulaInfoBase visitor.visit(*this); } - virtual std::string str() const { return s.str(); } + std::string str() const { return s.str(); } }; class Temp; @@ -2822,11 +2822,11 @@ class FormulaNode : public Node public: FormulaNode(const Formula &f) : formula(f) {} - virtual size_type size() const { return formula.size(); } - virtual const VResult &result() const { formula.result(vec); return vec; } - virtual Result total() const { return formula.total(); } + size_type size() const { return formula.size(); } + const VResult &result() const { formula.result(vec); return vec; } + Result total() const { return formula.total(); } - virtual std::string str() const { return formula.str(); } + std::string str() const { return formula.str(); } }; /** -- cgit v1.2.3 From c7bd1ec261d24a5301b5349508f67e636f893ea0 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 5 Mar 2009 19:09:53 -0800 Subject: stats: better naming of template parameters for the wrapper stuff Parent and Child are bad names. Derived and Base are better. --- src/base/statistics.hh | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/base/statistics.hh b/src/base/statistics.hh index 8a0079b27..30715daa3 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -397,16 +397,16 @@ class InfoAccess const Info *info() const; }; -template class Info> -class Wrap : public Child +template class Info> +class Wrap : public Base { public: - typedef Parent ParentType; - typedef Child ChildType; - typedef Info InfoType; + typedef Derived DerivedType; + typedef Base BaseType; + typedef Info InfoType; protected: - Parent &self() { return *reinterpret_cast(this); } + Derived &self() { return *reinterpret_cast(this); } protected: InfoType * @@ -444,7 +444,7 @@ class Wrap : public Child * @param name The new name. * @return A reference to this stat. */ - Parent & + Derived & name(const std::string &_name) { InfoType *info = this->info(); @@ -459,7 +459,7 @@ class Wrap : public Child * @param desc The new description. * @return A reference to this stat. */ - Parent & + Derived & desc(const std::string &_desc) { this->info()->desc = _desc; @@ -471,7 +471,7 @@ class Wrap : public Child * @param _precision The new precision * @return A reference to this stat. */ - Parent & + Derived & precision(int _precision) { this->info()->precision = _precision; @@ -483,7 +483,7 @@ class Wrap : public Child * @param f The new flags. * @return A reference to this stat. */ - Parent & + Derived & flags(StatFlags _flags) { this->info()->flags |= _flags; @@ -497,7 +497,7 @@ class Wrap : public Child * @return A reference to this stat. */ template - Parent & + Derived & prereq(const Stat &prereq) { this->info()->prereq = prereq.info(); @@ -505,13 +505,13 @@ class Wrap : public Child } }; -template class Info> -class WrapVec : public Wrap +template class Info> +class WrapVec : public Wrap { public: - typedef Parent ParentType; - typedef Child ChildType; - typedef Info InfoType; + typedef Derived DerivedType; + typedef Base BaseType; + typedef Info InfoType; public: // The following functions are specific to vectors. If you use them @@ -524,7 +524,7 @@ class WrapVec : public Wrap * @param name The new name of the subfield. * @return A reference to this stat. */ - Parent & + Derived & subname(off_type index, const std::string &name) { std::vector &subn = this->info()->subnames; @@ -541,7 +541,7 @@ class WrapVec : public Wrap * @param desc The new description of the subfield * @return A reference to this stat. */ - Parent & + Derived & subdesc(off_type index, const std::string &desc) { std::vector &subd = this->info()->subdescs; @@ -554,20 +554,20 @@ class WrapVec : public Wrap }; -template class Info> -class WrapVec2d : public WrapVec +template class Info> +class WrapVec2d : public WrapVec { public: - typedef Parent ParentType; - typedef Child ChildType; - typedef Info InfoType; + typedef Derived DerivedType; + typedef Base BaseType; + typedef Info InfoType; public: /** * @warning This makes the assumption that if you're gonna subnames a 2d * vector, you're subnaming across all y */ - Parent & + Derived & ysubnames(const char **names) { InfoType *info = this->info(); @@ -577,7 +577,7 @@ class WrapVec2d : public WrapVec return this->self(); } - Parent & + Derived & ysubname(off_type index, const std::string subname) { InfoType *info = this->info(); -- cgit v1.2.3 From e19fd1d521cd8444a52374392643ebf8be0b6c09 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 5 Mar 2009 19:09:53 -0800 Subject: stats: Add a wrapper class for the information side of things. This provides an easy way to provide the callbacks into the data side of things from the info side of things. Rename Wrap to DataWrap so it is more easily distinguishable from InfoWrap --- src/base/statistics.hh | 219 ++++++++++++++++++++++--------------------------- 1 file changed, 96 insertions(+), 123 deletions(-) (limited to 'src') diff --git a/src/base/statistics.hh b/src/base/statistics.hh index 30715daa3..9e641548c 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -115,7 +115,7 @@ class Info virtual ~Info(); /** - * Reset the corresponding stat to the default state. + * Reset the stat to the default state. */ virtual void reset() = 0; @@ -149,6 +149,20 @@ class Info static bool less(Info *stat1, Info *stat2); }; +template +class InfoWrap : public Base +{ + protected: + Stat &s; + + public: + InfoWrap(Stat &stat) : s(stat) {} + + bool check() const { return s.check(); } + void reset() { s.reset(); } + bool zero() const { return s.zero(); } +}; + class ScalarInfoBase : public Info { public: @@ -159,20 +173,14 @@ class ScalarInfoBase : public Info }; template -class ScalarInfo : public ScalarInfoBase +class ScalarInfo : public InfoWrap { - protected: - Stat &s; - public: - ScalarInfo(Stat &stat) : s(stat) {} + ScalarInfo(Stat &stat) : InfoWrap(stat) {} - bool check() const { return s.check(); } - Counter value() const { return s.value(); } - Result result() const { return s.result(); } - Result total() const { return s.total(); } - void reset() { s.reset(); } - bool zero() const { return s.zero(); } + Counter value() const { return this->s.value(); } + Result result() const { return this->s.result(); } + Result total() const { return this->s.total(); } }; class VectorInfoBase : public Info @@ -203,43 +211,38 @@ class VectorInfoBase : public Info }; template -class VectorInfo : public VectorInfoBase +class VectorInfo : public InfoWrap { protected: - Stat &s; mutable VCounter cvec; mutable VResult rvec; public: - VectorInfo(Stat &stat) : s(stat) {} - - bool check() const { return s.check(); } - bool zero() const { return s.zero(); } - void reset() { s.reset(); } + VectorInfo(Stat &stat) : InfoWrap(stat) {} - size_type size() const { return s.size(); } + size_type size() const { return this->s.size(); } VCounter & value() const { - s.value(cvec); + this->s.value(cvec); return cvec; } const VResult & result() const { - s.result(rvec); + this->s.result(rvec); return rvec; } - Result total() const { return s.total(); } + Result total() const { return this->s.total(); } void visit(Visit &visitor) { - update(); - s.update(this); + this->update(); + this->s.update(this); visitor.visit(*this); } }; @@ -266,22 +269,15 @@ class DistInfoBase : public Info }; template -class DistInfo : public DistInfoBase +class DistInfo : public InfoWrap { - protected: - Stat &s; - public: - DistInfo(Stat &stat) : s(stat) {} - - bool check() const { return s.check(); } - void reset() { s.reset(); } - bool zero() const { return s.zero(); } + DistInfo(Stat &stat) : InfoWrap(stat) {} void visit(Visit &visitor) { - s.update(this); + this->s.update(this); visitor.visit(*this); } }; @@ -315,24 +311,18 @@ class VectorDistInfoBase : public Info }; template -class VectorDistInfo : public VectorDistInfoBase +class VectorDistInfo : public InfoWrap { - protected: - Stat &s; - public: - VectorDistInfo(Stat &stat) : s(stat) {} + VectorDistInfo(Stat &stat) : InfoWrap(stat) {} - bool check() const { return s.check(); } - void reset() { s.reset(); } - size_type size() const { return s.size(); } - bool zero() const { return s.zero(); } + size_type size() const { return this->s.size(); } void visit(Visit &visitor) { - update(); - s.update(this); + this->update(); + this->s.update(this); visitor.visit(*this); } }; @@ -360,23 +350,16 @@ class Vector2dInfoBase : public Info }; template -class Vector2dInfo : public Vector2dInfoBase +class Vector2dInfo : public InfoWrap { - protected: - Stat &s; - public: - Vector2dInfo(Stat &stat) : s(stat) {} - - bool check() const { return s.check(); } - void reset() { s.reset(); } - bool zero() const { return s.zero(); } + Vector2dInfo(Stat &stat) : InfoWrap(stat) {} void visit(Visit &visitor) { - update(); - s.update(this); + this->update(); + this->s.update(this); visitor.visit(*this); } }; @@ -395,10 +378,29 @@ class InfoAccess Info *info(); /** Grab the information class for this statistic */ const Info *info() const; + + public: + /** + * Reset the stat to the default state. + */ + void reset() {} + + /** + * @return true if this stat has a value and satisfies its + * requirement as a prereq + */ + bool zero() const { return true; } + + /** + * Check that this stat has been set up properly and is ready for + * use + * @return true for success + */ + bool check() const { return true; } }; template class Info> -class Wrap : public Base +class DataWrap : public Base { public: typedef Derived DerivedType; @@ -426,15 +428,15 @@ class Wrap : public Base /** * Copy constructor, copies are not allowed. */ - Wrap(const Wrap &stat); + DataWrap(const DataWrap &stat); /** * Can't copy stats. */ - void operator=(const Wrap &); + void operator=(const DataWrap &); public: - Wrap() + DataWrap() { this->setInfo(new InfoType(*this)); } @@ -506,7 +508,7 @@ class Wrap : public Base }; template class Info> -class WrapVec : public Wrap +class DataWrapVec : public DataWrap { public: typedef Derived DerivedType; @@ -555,7 +557,7 @@ class WrapVec : public Wrap }; template class Info> -class WrapVec2d : public WrapVec +class DataWrapVec2d : public DataWrapVec { public: typedef Derived DerivedType; @@ -842,8 +844,6 @@ class ScalarBase : public InfoAccess */ size_type size() const { return 1; } - bool check() const { return true; } - /** * Reset stat value to default */ @@ -856,7 +856,6 @@ class ScalarBase : public InfoAccess Result total() { return result(); } bool zero() { return result() == 0.0; } - }; class ProxyInfo : public ScalarInfoBase @@ -865,9 +864,9 @@ class ProxyInfo : public ScalarInfoBase void visit(Visit &visitor) { visitor.visit(*this); } std::string str() const { return to_string(value()); } size_type size() const { return 1; } - bool zero() const { return value() == 0; } bool check() const { return true; } - void reset() { } + void reset() {} + bool zero() const { return value() == 0; } }; template @@ -1057,11 +1056,6 @@ class ScalarProxy */ size_type size() const { return 1; } - /** - * This stat has no state. Nothing to reset - */ - void reset() { } - public: std::string str() const @@ -1287,11 +1281,6 @@ class VectorProxy } size_type size() const { return len; } - - /** - * This stat has no state. Nothing to reset. - */ - void reset() { } }; template @@ -1401,7 +1390,7 @@ class Vector2dBase : public InfoAccess } bool - check() + check() const { return storage != NULL; } @@ -1788,12 +1777,6 @@ class DistBase : public InfoAccess { data()->reset(info()); } - - bool - check() - { - return true; - } }; template @@ -1887,7 +1870,7 @@ class VectorDistBase : public InfoAccess } bool - check() + check() const { return storage != NULL; } @@ -2371,7 +2354,7 @@ class SumNode : public Node * @sa Stat, ScalarBase, StatStor */ template -class Scalar : public Wrap, ScalarBase, ScalarInfo> +class Scalar : public DataWrap, ScalarBase, ScalarInfo> { public: /** The base implementation. */ @@ -2391,7 +2374,7 @@ class Scalar : public Wrap, ScalarBase, ScalarInfo> void operator=(const U &v) { Base::operator=(v); } }; -class Value : public Wrap +class Value : public DataWrap { public: /** The base implementation. */ @@ -2419,7 +2402,7 @@ class Value : public Wrap * @sa Stat, ScalarBase, AvgStor */ template -class Average : public Wrap, ScalarBase, ScalarInfo> +class Average : public DataWrap, ScalarBase, ScalarInfo> { public: /** The base implementation. */ @@ -2448,7 +2431,7 @@ class Average : public Wrap, ScalarBase, ScalarInfo> * @sa Stat, VectorBase, StatStor */ template -class Vector : public WrapVec, VectorBase, VectorInfo> +class Vector : public DataWrapVec, VectorBase, VectorInfo> { public: /** The base implementation. */ @@ -2473,7 +2456,7 @@ class Vector : public WrapVec, VectorBase, VectorInfo> */ template class AverageVector - : public WrapVec, VectorBase, VectorInfo> + : public DataWrapVec, VectorBase, VectorInfo> { public: /** @@ -2495,7 +2478,7 @@ class AverageVector */ template class Vector2d - : public WrapVec2d, Vector2dBase, Vector2dInfo> + : public DataWrapVec2d, Vector2dBase, Vector2dInfo> { public: Vector2d & @@ -2512,7 +2495,7 @@ class Vector2d */ template class Distribution - : public Wrap, DistBase, DistInfo> + : public DataWrap, DistBase, DistInfo> { public: /** Base implementation. */ @@ -2546,7 +2529,7 @@ class Distribution */ template class StandardDeviation - : public Wrap, DistBase, DistInfo> + : public DataWrap, DistBase, DistInfo> { public: /** The base implementation */ @@ -2568,7 +2551,7 @@ class StandardDeviation */ template class AverageDeviation - : public Wrap, DistBase, DistInfo> + : public DataWrap, DistBase, DistInfo> { public: /** The base implementation */ @@ -2590,9 +2573,9 @@ class AverageDeviation */ template class VectorDistribution - : public WrapVec, - VectorDistBase, - VectorDistInfo> + : public DataWrapVec, + VectorDistBase, + VectorDistInfo> { public: /** The base implementation */ @@ -2627,9 +2610,9 @@ class VectorDistribution */ template class VectorStandardDeviation - : public WrapVec, - VectorDistBase, - VectorDistInfo> + : public DataWrapVec, + VectorDistBase, + VectorDistInfo> { public: /** The base implementation */ @@ -2655,9 +2638,9 @@ class VectorStandardDeviation */ template class VectorAverageDeviation - : public WrapVec, - VectorDistBase, - VectorDistInfo> + : public DataWrapVec, + VectorDistBase, + VectorDistInfo> { public: /** The base implementation */ @@ -2716,8 +2699,6 @@ class FormulaBase : public InfoAccess */ size_type size() const; - bool check() const { return true; } - /** * Formulas don't need to be reset */ @@ -2740,50 +2721,42 @@ class FormulaInfoBase : public VectorInfoBase { public: virtual std::string str() const = 0; - bool check() const { return true; } }; template -class FormulaInfo : public FormulaInfoBase +class FormulaInfo : public InfoWrap { protected: - Stat &s; mutable VResult vec; mutable VCounter cvec; public: - FormulaInfo(Stat &stat) : s(stat) {} - - bool zero() const { return s.zero(); } - void reset() { s.reset(); } + FormulaInfo(Stat &stat) : InfoWrap(stat) {} - size_type size() const { return s.size(); } + size_type size() const { return this->s.size(); } const VResult & result() const { - s.result(vec); + this->s.result(vec); return vec; } - Result total() const { return s.total(); } + Result total() const { return this->s.total(); } VCounter &value() const { return cvec; } void visit(Visit &visitor) { - update(); - s.update(this); + this->update(); + this->s.update(this); visitor.visit(*this); } - std::string str() const { return s.str(); } + std::string str() const { return this->s.str(); } }; class Temp; -class Formula - : public WrapVec +class Formula : public DataWrapVec { public: /** -- cgit v1.2.3 From 244c2a517a48a0985091397bed6a754cb2e2e1a5 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 5 Mar 2009 19:09:53 -0800 Subject: stats: stick the distribution's fancy parameter into the parameters structure. --- src/base/statistics.hh | 23 ++++++++++------------- src/base/stats/mysql.cc | 8 ++++---- src/base/stats/text.cc | 17 ++++++++--------- 3 files changed, 22 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/base/statistics.hh b/src/base/statistics.hh index 9e641548c..6f2da2f3e 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -257,8 +257,6 @@ struct DistData Counter sum; Counter squares; Counter samples; - - bool fancy; }; class DistInfoBase : public Info @@ -1419,8 +1417,9 @@ class DistStor Counter bucket_size; /** The number of buckets. Equal to (max-min)/bucket_size. */ size_type buckets; + + enum { fancy = false }; }; - enum { fancy = false }; private: /** The minimum value to track. */ @@ -1556,10 +1555,10 @@ class DistStor class FancyStor { public: - struct Params : public StorageParams {}; - - public: - enum { fancy = true }; + struct Params : public StorageParams + { + enum { fancy = true }; + }; private: /** The current sum. */ @@ -1632,10 +1631,10 @@ class FancyStor class AvgFancy { public: - struct Params : public StorageParams {}; - - public: - enum { fancy = true }; + struct Params : public StorageParams + { + enum { fancy = true }; + }; private: /** Current total. */ @@ -1765,7 +1764,6 @@ class DistBase : public InfoAccess void update(DistInfoBase *base) { - base->data.fancy = Storage::fancy; data()->update(info(), base->data); } @@ -1881,7 +1879,6 @@ class VectorDistBase : public InfoAccess size_type size = this->size(); base->data.resize(size); for (off_type i = 0; i < size; ++i) { - base->data[i].fancy = Storage::fancy; data(i)->update(info(), base->data[i]); } } diff --git a/src/base/stats/mysql.cc b/src/base/stats/mysql.cc index 72f31240d..58c620ed1 100644 --- a/src/base/stats/mysql.cc +++ b/src/base/stats/mysql.cc @@ -583,8 +583,8 @@ MySql::configure(const DistInfoBase &info) if (!configure(info, "DIST")) return; - if (!info.data.fancy) { - const Params *params = safe_cast(info.storageParams); + const Params *params = safe_cast(info.storageParams); + if (!params->fancy) { stat.size = params->buckets; stat.min = params->min; stat.max = params->max; @@ -599,8 +599,8 @@ MySql::configure(const VectorDistInfoBase &info) if (!configure(info, "VECTORDIST")) return; - if (!info.data[0].fancy) { - const Params *params = safe_cast(info.storageParams); + const Params *params = safe_cast(info.storageParams); + if (!params->fancy) { stat.size = params->buckets; stat.min = params->min; stat.max = params->max; diff --git a/src/base/stats/text.cc b/src/base/stats/text.cc index 3a00620c7..6c2078bd0 100644 --- a/src/base/stats/text.cc +++ b/src/base/stats/text.cc @@ -673,12 +673,11 @@ Text::visit(const DistInfoBase &info) print.squares = data.squares; print.samples = data.samples; - print.fancy = data.fancy; - - if (!data.fancy) { - const DistStor::Params *params = - safe_cast(info.storageParams); + const DistStor::Params *params = + safe_cast(info.storageParams); + print.fancy = params->fancy; + if (!params->fancy) { print.min = params->min; print.max = params->max; print.bucket_size = params->bucket_size; @@ -716,11 +715,11 @@ Text::visit(const VectorDistInfoBase &info) print.squares = info.data[i].squares; print.samples = info.data[i].samples; - print.fancy = info.data[i].fancy; - if (!print.fancy) { - const DistStor::Params *params = - safe_cast(info.storageParams); + const DistStor::Params *params = + safe_cast(info.storageParams); + print.fancy = params->fancy; + if (!params->fancy) { print.min = params->min; print.max = params->max; print.bucket_size = params->bucket_size; -- cgit v1.2.3 From c7e82f965fa40b4a377a6ddedcdeb542a43ae7c5 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 5 Mar 2009 19:09:53 -0800 Subject: stats: remove the template wart left over from the ancient binning stuff --- src/base/statistics.hh | 42 ++++++++++++++---------------------------- 1 file changed, 14 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/base/statistics.hh b/src/base/statistics.hh index 6f2da2f3e..7b69184e9 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -2350,8 +2350,7 @@ class SumNode : public Node * This is a simple scalar statistic, like a counter. * @sa Stat, ScalarBase, StatStor */ -template -class Scalar : public DataWrap, ScalarBase, ScalarInfo> +class Scalar : public DataWrap, ScalarInfo> { public: /** The base implementation. */ @@ -2398,8 +2397,7 @@ class Value : public DataWrap * A stat that calculates the per tick average of a value. * @sa Stat, ScalarBase, AvgStor */ -template -class Average : public DataWrap, ScalarBase, ScalarInfo> +class Average : public DataWrap, ScalarInfo> { public: /** The base implementation. */ @@ -2427,8 +2425,7 @@ class Average : public DataWrap, ScalarBase, ScalarInfo> * A vector of scalar stats. * @sa Stat, VectorBase, StatStor */ -template -class Vector : public DataWrapVec, VectorBase, VectorInfo> +class Vector : public DataWrapVec, VectorInfo> { public: /** The base implementation. */ @@ -2451,9 +2448,8 @@ class Vector : public DataWrapVec, VectorBase, VectorInfo> * A vector of Average stats. * @sa Stat, VectorBase, AvgStor */ -template class AverageVector - : public DataWrapVec, VectorBase, VectorInfo> + : public DataWrapVec, VectorInfo> { public: /** @@ -2473,9 +2469,8 @@ class AverageVector * A 2-Dimensional vecto of scalar stats. * @sa Stat, Vector2dBase, StatStor */ -template class Vector2d - : public DataWrapVec2d, Vector2dBase, Vector2dInfo> + : public DataWrapVec2d, Vector2dInfo> { public: Vector2d & @@ -2490,9 +2485,8 @@ class Vector2d * A simple distribution stat. * @sa Stat, DistBase, DistStor */ -template class Distribution - : public DataWrap, DistBase, DistInfo> + : public DataWrap, DistInfo> { public: /** Base implementation. */ @@ -2524,9 +2518,8 @@ class Distribution * Calculates the mean and variance of all the samples. * @sa Stat, DistBase, FancyStor */ -template class StandardDeviation - : public DataWrap, DistBase, DistInfo> + : public DataWrap, DistInfo> { public: /** The base implementation */ @@ -2546,9 +2539,8 @@ class StandardDeviation * Calculates the per tick mean and variance of the samples. * @sa Stat, DistBase, AvgFancy */ -template class AverageDeviation - : public DataWrap, DistBase, DistInfo> + : public DataWrap, DistInfo> { public: /** The base implementation */ @@ -2568,9 +2560,8 @@ class AverageDeviation * A vector of distributions. * @sa Stat, VectorDistBase, DistStor */ -template class VectorDistribution - : public DataWrapVec, + : public DataWrapVec, VectorDistInfo> { @@ -2605,9 +2596,8 @@ class VectorDistribution * This is a vector of StandardDeviation stats. * @sa Stat, VectorDistBase, FancyStor */ -template class VectorStandardDeviation - : public DataWrapVec, + : public DataWrapVec, VectorDistInfo> { @@ -2633,9 +2623,8 @@ class VectorStandardDeviation * This is a vector of AverageDeviation stats. * @sa Stat, VectorDistBase, AvgFancy */ -template class VectorAverageDeviation - : public DataWrapVec, + : public DataWrapVec, VectorDistInfo> { @@ -2828,8 +2817,7 @@ class Temp * Create a new ScalarStatNode. * @param s The ScalarStat to place in a node. */ - template - Temp(const Scalar &s) + Temp(const Scalar &s) : node(new ScalarStatNode(s.info())) { } @@ -2845,8 +2833,7 @@ class Temp * Create a new ScalarStatNode. * @param s The ScalarStat to place in a node. */ - template - Temp(const Average &s) + Temp(const Average &s) : node(new ScalarStatNode(s.info())) { } @@ -2854,8 +2841,7 @@ class Temp * Create a new VectorStatNode. * @param s The VectorStat to place in a node. */ - template - Temp(const Vector &s) + Temp(const Vector &s) : node(new VectorStatNode(s.info())) { } -- cgit v1.2.3 From cc95b5739097e31fdaa36a3ff443861969e338b1 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 5 Mar 2009 19:09:53 -0800 Subject: stats: Fix all stats usages to deal with template fixes --- src/arch/alpha/kernel_stats.hh | 12 ++-- src/arch/alpha/tlb.hh | 22 +++---- src/arch/mips/tlb.hh | 16 ++--- src/base/hybrid_pred.hh | 12 ++-- src/base/sat_counter.hh | 12 ++-- src/cpu/base.hh | 2 +- src/cpu/inorder/cpu.hh | 14 ++-- src/cpu/inorder/pipeline_stage.hh | 14 ++-- src/cpu/inorder/resource.hh | 2 +- src/cpu/inorder/resources/bpred_unit.hh | 16 ++--- src/cpu/inorder/resources/branch_predictor.hh | 4 +- src/cpu/inorder/resources/execution_unit.hh | 4 +- src/cpu/inorder/resources/inst_buffer.hh | 2 +- src/cpu/inorder/resources/mult_div_unit.hh | 4 +- src/cpu/memtest/memtest.hh | 6 +- src/cpu/o3/bpred_unit.hh | 16 ++--- src/cpu/o3/commit.hh | 28 ++++---- src/cpu/o3/cpu.hh | 8 +-- src/cpu/o3/decode.hh | 20 +++--- src/cpu/o3/fetch.hh | 24 +++---- src/cpu/o3/iew.hh | 54 ++++++++-------- src/cpu/o3/inst_queue.hh | 38 +++++------ src/cpu/o3/lsq_unit.hh | 20 +++--- src/cpu/o3/mem_dep_unit.hh | 8 +-- src/cpu/o3/rename.hh | 38 +++++------ src/cpu/ozone/back_end.hh | 92 +++++++++++++-------------- src/cpu/ozone/cpu.hh | 4 +- src/cpu/ozone/front_end.hh | 40 ++++++------ src/cpu/ozone/inorder_back_end.hh | 2 +- src/cpu/ozone/inst_queue.hh | 32 +++++----- src/cpu/ozone/lsq_unit.hh | 2 +- src/cpu/ozone/lw_back_end.hh | 84 ++++++++++++------------ src/cpu/ozone/lw_lsq.hh | 4 +- src/cpu/simple/base.hh | 14 ++-- src/cpu/thread_state.hh | 4 +- src/dev/copy_engine.hh | 4 +- src/dev/etherdevice.hh | 64 +++++++++---------- src/dev/ide_disk.hh | 12 ++-- src/dev/sinic.hh | 42 ++++++------ src/kern/kernel_stats.hh | 16 ++--- src/mem/cache/base.hh | 32 +++++----- src/mem/cache/prefetch/base.hh | 18 +++--- src/mem/cache/tags/base.hh | 10 +-- src/mem/cache/tags/fa_lru.hh | 6 +- src/mem/cache/tags/iic.hh | 14 ++-- src/mem/cache/tags/iic_repl/gen.hh | 6 +- src/mem/dram.hh | 38 +++++------ src/sim/faults.hh | 2 +- src/sim/process.hh | 2 +- src/unittest/stattest.cc | 38 +++++------ 50 files changed, 489 insertions(+), 489 deletions(-) (limited to 'src') diff --git a/src/arch/alpha/kernel_stats.hh b/src/arch/alpha/kernel_stats.hh index aab96b150..837269309 100644 --- a/src/arch/alpha/kernel_stats.hh +++ b/src/arch/alpha/kernel_stats.hh @@ -62,15 +62,15 @@ class Statistics : public ::Kernel::Statistics void changeMode(cpu_mode newmode, ThreadContext *tc); private: - Stats::Vector<> _callpal; -// Stats::Vector<> _faults; + Stats::Vector _callpal; +// Stats::Vector _faults; - Stats::Vector<> _mode; - Stats::Vector<> _modeGood; + Stats::Vector _mode; + Stats::Vector _modeGood; Stats::Formula _modeFraction; - Stats::Vector<> _modeTicks; + Stats::Vector _modeTicks; - Stats::Scalar<> _swap_context; + Stats::Scalar _swap_context; public: Statistics(System *system); diff --git a/src/arch/alpha/tlb.hh b/src/arch/alpha/tlb.hh index 877533797..643889534 100644 --- a/src/arch/alpha/tlb.hh +++ b/src/arch/alpha/tlb.hh @@ -121,9 +121,9 @@ class TLB : public BaseTLB class ITB : public TLB { protected: - mutable Stats::Scalar<> hits; - mutable Stats::Scalar<> misses; - mutable Stats::Scalar<> acv; + mutable Stats::Scalar hits; + mutable Stats::Scalar misses; + mutable Stats::Scalar acv; mutable Stats::Formula accesses; public: @@ -139,14 +139,14 @@ class ITB : public TLB class DTB : public TLB { protected: - mutable Stats::Scalar<> read_hits; - mutable Stats::Scalar<> read_misses; - mutable Stats::Scalar<> read_acv; - mutable Stats::Scalar<> read_accesses; - mutable Stats::Scalar<> write_hits; - mutable Stats::Scalar<> write_misses; - mutable Stats::Scalar<> write_acv; - mutable Stats::Scalar<> write_accesses; + mutable Stats::Scalar read_hits; + mutable Stats::Scalar read_misses; + mutable Stats::Scalar read_acv; + mutable Stats::Scalar read_accesses; + mutable Stats::Scalar write_hits; + mutable Stats::Scalar write_misses; + mutable Stats::Scalar write_acv; + mutable Stats::Scalar write_accesses; Stats::Formula hits; Stats::Formula misses; Stats::Formula acv; diff --git a/src/arch/mips/tlb.hh b/src/arch/mips/tlb.hh index 1ab9d77e5..dc0babf9a 100644 --- a/src/arch/mips/tlb.hh +++ b/src/arch/mips/tlb.hh @@ -96,14 +96,14 @@ class TLB : public BaseTLB void nextnlu() { if (++nlu >= size) nlu = 0; } MipsISA::PTE *lookup(Addr vpn, uint8_t asn) const; - mutable Stats::Scalar<> read_hits; - mutable Stats::Scalar<> read_misses; - mutable Stats::Scalar<> read_acv; - mutable Stats::Scalar<> read_accesses; - mutable Stats::Scalar<> write_hits; - mutable Stats::Scalar<> write_misses; - mutable Stats::Scalar<> write_acv; - mutable Stats::Scalar<> write_accesses; + mutable Stats::Scalar read_hits; + mutable Stats::Scalar read_misses; + mutable Stats::Scalar read_acv; + mutable Stats::Scalar read_accesses; + mutable Stats::Scalar write_hits; + mutable Stats::Scalar write_misses; + mutable Stats::Scalar write_acv; + mutable Stats::Scalar write_accesses; Stats::Formula hits; Stats::Formula misses; Stats::Formula invalids; diff --git a/src/base/hybrid_pred.hh b/src/base/hybrid_pred.hh index cb1d6003b..5e478553b 100644 --- a/src/base/hybrid_pred.hh +++ b/src/base/hybrid_pred.hh @@ -62,12 +62,12 @@ class HybridPredictor : public GenericPredictor // // Stats // - Stats::Scalar<> pred_one; //num_one_preds - Stats::Scalar<> pred_zero; //num_zero_preds - Stats::Scalar<> correct_pred_one; //num_one_correct - Stats::Scalar<> correct_pred_zero; //num_zero_correct - Stats::Scalar<> record_one; //num_one_updates - Stats::Scalar<> record_zero; //num_zero_updates + Stats::Scalar pred_one; //num_one_preds + Stats::Scalar pred_zero; //num_zero_preds + Stats::Scalar correct_pred_one; //num_one_correct + Stats::Scalar correct_pred_zero; //num_zero_correct + Stats::Scalar record_one; //num_one_updates + Stats::Scalar record_zero; //num_zero_updates Stats::Formula total_preds; Stats::Formula frac_preds_zero; diff --git a/src/base/sat_counter.hh b/src/base/sat_counter.hh index 79de11156..38c4ec74f 100644 --- a/src/base/sat_counter.hh +++ b/src/base/sat_counter.hh @@ -64,13 +64,13 @@ class SaturatingCounterPred : public GenericPredictor unsigned *table; // Statistics - Stats::Scalar<> predicted_one; // Total predictions of one, preds_one - Stats::Scalar<> predicted_zero; // Total predictions of zero, preds_zero - Stats::Scalar<> correct_pred_one; // Total correct predictions of one, correct_one - Stats::Scalar<> correct_pred_zero; // Total correct predictions of zero, correct_zero + Stats::Scalar predicted_one; // Total predictions of one, preds_one + Stats::Scalar predicted_zero; // Total predictions of zero, preds_zero + Stats::Scalar correct_pred_one; // Total correct predictions of one, correct_one + Stats::Scalar correct_pred_zero; // Total correct predictions of zero, correct_zero - Stats::Scalar<> record_zero; //updates_zero - Stats::Scalar<> record_one; //updates_one + Stats::Scalar record_zero; //updates_zero + Stats::Scalar record_one; //updates_one Stats::Formula preds_total; Stats::Formula pred_frac_zero; diff --git a/src/cpu/base.hh b/src/cpu/base.hh index c8215e047..8af3295eb 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -304,7 +304,7 @@ class BaseCPU : public MemObject public: // Number of CPU cycles simulated - Stats::Scalar<> numCycles; + Stats::Scalar numCycles; }; #endif // __CPU_BASE_HH__ diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh index 36c90a0e9..adcd28019 100644 --- a/src/cpu/inorder/cpu.hh +++ b/src/cpu/inorder/cpu.hh @@ -638,25 +638,25 @@ class InOrderCPU : public BaseCPU inline void tickThreadStats(); /** Per-Thread Tick */ - Stats::Vector<> threadCycles; + Stats::Vector threadCycles; /** Tick for SMT */ - Stats::Scalar<> smtCycles; + Stats::Scalar smtCycles; /** Stat for total number of times the CPU is descheduled. */ - Stats::Scalar<> timesIdled; + Stats::Scalar timesIdled; /** Stat for total number of cycles the CPU spends descheduled. */ - Stats::Scalar<> idleCycles; + Stats::Scalar idleCycles; /** Stat for the number of committed instructions per thread. */ - Stats::Vector<> committedInsts; + Stats::Vector committedInsts; /** Stat for the number of committed instructions per thread. */ - Stats::Vector<> smtCommittedInsts; + Stats::Vector smtCommittedInsts; /** Stat for the total number of committed instructions. */ - Stats::Scalar<> totalCommittedInsts; + Stats::Scalar totalCommittedInsts; /** Stat for the CPI per thread. */ Stats::Formula cpi; diff --git a/src/cpu/inorder/pipeline_stage.hh b/src/cpu/inorder/pipeline_stage.hh index 2fd8f2215..b074639fb 100644 --- a/src/cpu/inorder/pipeline_stage.hh +++ b/src/cpu/inorder/pipeline_stage.hh @@ -340,19 +340,19 @@ class PipelineStage //@TODO: Use Stats for the pipeline stages /** Stat for total number of idle cycles. */ - //Stats::Scalar<> stageIdleCycles; + //Stats::Scalar stageIdleCycles; /** Stat for total number of blocked cycles. */ - //Stats::Scalar<> stageBlockedCycles; + //Stats::Scalar stageBlockedCycles; /** Stat for total number of normal running cycles. */ - //Stats::Scalar<> stageRunCycles; + //Stats::Scalar stageRunCycles; /** Stat for total number of unblocking cycles. */ - //Stats::Scalar<> stageUnblockCycles; + //Stats::Scalar stageUnblockCycles; /** Stat for total number of squashing cycles. */ - //Stats::Scalar<> stageSquashCycles; + //Stats::Scalar stageSquashCycles; /** Stat for total number of staged instructions. */ - //Stats::Scalar<> stageProcessedInsts; + //Stats::Scalar stageProcessedInsts; /** Stat for total number of squashed instructions. */ - //Stats::Scalar<> stageSquashedInsts; + //Stats::Scalar stageSquashedInsts; }; #endif diff --git a/src/cpu/inorder/resource.hh b/src/cpu/inorder/resource.hh index 9b9e3c3dc..b857e59ed 100644 --- a/src/cpu/inorder/resource.hh +++ b/src/cpu/inorder/resource.hh @@ -232,7 +232,7 @@ class Resource { // ///////////////////////////////////////////////////////////////// /** Number of Instruction Requests the Resource Processes */ - Stats::Scalar<> instReqsProcessed; + Stats::Scalar instReqsProcessed; }; class ResourceEvent : public Event diff --git a/src/cpu/inorder/resources/bpred_unit.hh b/src/cpu/inorder/resources/bpred_unit.hh index b945922a7..bd68459d1 100644 --- a/src/cpu/inorder/resources/bpred_unit.hh +++ b/src/cpu/inorder/resources/bpred_unit.hh @@ -238,21 +238,21 @@ class BPredUnit ReturnAddrStack RAS[ThePipeline::MaxThreads]; /** Stat for number of BP lookups. */ - Stats::Scalar<> lookups; + Stats::Scalar lookups; /** Stat for number of conditional branches predicted. */ - Stats::Scalar<> condPredicted; + Stats::Scalar condPredicted; /** Stat for number of conditional branches predicted incorrectly. */ - Stats::Scalar<> condIncorrect; + Stats::Scalar condIncorrect; /** Stat for number of BTB lookups. */ - Stats::Scalar<> BTBLookups; + Stats::Scalar BTBLookups; /** Stat for number of BTB hits. */ - Stats::Scalar<> BTBHits; + Stats::Scalar BTBHits; /** Stat for number of times the BTB is correct. */ - Stats::Scalar<> BTBCorrect; + Stats::Scalar BTBCorrect; /** Stat for number of times the RAS is used to get a target. */ - Stats::Scalar<> usedRAS; + Stats::Scalar usedRAS; /** Stat for number of times the RAS is incorrect. */ - Stats::Scalar<> RASIncorrect; + Stats::Scalar RASIncorrect; }; #endif // __CPU_INORDER_BPRED_UNIT_HH__ diff --git a/src/cpu/inorder/resources/branch_predictor.hh b/src/cpu/inorder/resources/branch_predictor.hh index 57745343c..47053910d 100644 --- a/src/cpu/inorder/resources/branch_predictor.hh +++ b/src/cpu/inorder/resources/branch_predictor.hh @@ -78,8 +78,8 @@ class BranchPredictor : public Resource { // RESOURCE STATISTICS // ///////////////////////////////////////////////////////////////// - Stats::Scalar<> predictedTaken; - Stats::Scalar<> predictedNotTaken; + Stats::Scalar predictedTaken; + Stats::Scalar predictedNotTaken; }; diff --git a/src/cpu/inorder/resources/execution_unit.hh b/src/cpu/inorder/resources/execution_unit.hh index e969497a2..46691bbf2 100644 --- a/src/cpu/inorder/resources/execution_unit.hh +++ b/src/cpu/inorder/resources/execution_unit.hh @@ -69,8 +69,8 @@ class ExecutionUnit : public Resource { // RESOURCE STATISTICS // ///////////////////////////////////////////////////////////////// - Stats::Scalar<> predictedTakenIncorrect; - Stats::Scalar<> predictedNotTakenIncorrect; + Stats::Scalar predictedTakenIncorrect; + Stats::Scalar predictedNotTakenIncorrect; }; diff --git a/src/cpu/inorder/resources/inst_buffer.hh b/src/cpu/inorder/resources/inst_buffer.hh index f4851e868..baadd42ff 100644 --- a/src/cpu/inorder/resources/inst_buffer.hh +++ b/src/cpu/inorder/resources/inst_buffer.hh @@ -86,7 +86,7 @@ class InstBuffer : public Resource { // ///////////////////////////////////////////////////////////////// /** Number of Instruction Requests the Resource Processes */ - Stats::Scalar<> instsBypassed; + Stats::Scalar instsBypassed; }; diff --git a/src/cpu/inorder/resources/mult_div_unit.hh b/src/cpu/inorder/resources/mult_div_unit.hh index 003f6fbb1..76180714c 100644 --- a/src/cpu/inorder/resources/mult_div_unit.hh +++ b/src/cpu/inorder/resources/mult_div_unit.hh @@ -116,10 +116,10 @@ class MultDivUnit : public Resource { std::string lastInstName; /** Number of Instruction Requests the Resource Processes */ - Stats::Scalar<> multInstReqsProcessed; + Stats::Scalar multInstReqsProcessed; /** Number of Instruction Requests the Resource Processes */ - Stats::Scalar<> divInstReqsProcessed; + Stats::Scalar divInstReqsProcessed; MDUEvent *mduEvent; }; diff --git a/src/cpu/memtest/memtest.hh b/src/cpu/memtest/memtest.hh index 82438b41f..907659f69 100644 --- a/src/cpu/memtest/memtest.hh +++ b/src/cpu/memtest/memtest.hh @@ -171,9 +171,9 @@ class MemTest : public MemObject bool atomic; - Stats::Scalar<> numReadsStat; - Stats::Scalar<> numWritesStat; - Stats::Scalar<> numCopiesStat; + Stats::Scalar numReadsStat; + Stats::Scalar numWritesStat; + Stats::Scalar numCopiesStat; // called by MemCompleteEvent::process() void completeRequest(PacketPtr pkt); diff --git a/src/cpu/o3/bpred_unit.hh b/src/cpu/o3/bpred_unit.hh index 34fe74178..44f9bea79 100644 --- a/src/cpu/o3/bpred_unit.hh +++ b/src/cpu/o3/bpred_unit.hh @@ -237,21 +237,21 @@ class BPredUnit ReturnAddrStack RAS[Impl::MaxThreads]; /** Stat for number of BP lookups. */ - Stats::Scalar<> lookups; + Stats::Scalar lookups; /** Stat for number of conditional branches predicted. */ - Stats::Scalar<> condPredicted; + Stats::Scalar condPredicted; /** Stat for number of conditional branches predicted incorrectly. */ - Stats::Scalar<> condIncorrect; + Stats::Scalar condIncorrect; /** Stat for number of BTB lookups. */ - Stats::Scalar<> BTBLookups; + Stats::Scalar BTBLookups; /** Stat for number of BTB hits. */ - Stats::Scalar<> BTBHits; + Stats::Scalar BTBHits; /** Stat for number of times the BTB is correct. */ - Stats::Scalar<> BTBCorrect; + Stats::Scalar BTBCorrect; /** Stat for number of times the RAS is used to get a target. */ - Stats::Scalar<> usedRAS; + Stats::Scalar usedRAS; /** Stat for number of times the RAS is incorrect. */ - Stats::Scalar<> RASIncorrect; + Stats::Scalar RASIncorrect; }; #endif // __CPU_O3_BPRED_UNIT_HH__ diff --git a/src/cpu/o3/commit.hh b/src/cpu/o3/commit.hh index ff1e517f2..f21c14569 100644 --- a/src/cpu/o3/commit.hh +++ b/src/cpu/o3/commit.hh @@ -452,40 +452,40 @@ class DefaultCommit void updateComInstStats(DynInstPtr &inst); /** Stat for the total number of committed instructions. */ - Stats::Scalar<> commitCommittedInsts; + Stats::Scalar commitCommittedInsts; /** Stat for the total number of squashed instructions discarded by commit. */ - Stats::Scalar<> commitSquashedInsts; + Stats::Scalar commitSquashedInsts; /** Stat for the total number of times commit is told to squash. * @todo: Actually increment this stat. */ - Stats::Scalar<> commitSquashEvents; + Stats::Scalar commitSquashEvents; /** Stat for the total number of times commit has had to stall due to a non- * speculative instruction reaching the head of the ROB. */ - Stats::Scalar<> commitNonSpecStalls; + Stats::Scalar commitNonSpecStalls; /** Stat for the total number of branch mispredicts that caused a squash. */ - Stats::Scalar<> branchMispredicts; + Stats::Scalar branchMispredicts; /** Distribution of the number of committed instructions each cycle. */ - Stats::Distribution<> numCommittedDist; + Stats::Distribution numCommittedDist; /** Total number of instructions committed. */ - Stats::Vector<> statComInst; + Stats::Vector statComInst; /** Total number of software prefetches committed. */ - Stats::Vector<> statComSwp; + Stats::Vector statComSwp; /** Stat for the total number of committed memory references. */ - Stats::Vector<> statComRefs; + Stats::Vector statComRefs; /** Stat for the total number of committed loads. */ - Stats::Vector<> statComLoads; + Stats::Vector statComLoads; /** Total number of committed memory barriers. */ - Stats::Vector<> statComMembars; + Stats::Vector statComMembars; /** Total number of committed branches. */ - Stats::Vector<> statComBranches; + Stats::Vector statComBranches; /** Number of cycles where the commit bandwidth limit is reached. */ - Stats::Scalar<> commitEligibleSamples; + Stats::Scalar commitEligibleSamples; /** Number of instructions not committed due to bandwidth limits. */ - Stats::Vector<> commitEligible; + Stats::Vector commitEligible; }; #endif // __CPU_O3_COMMIT_HH__ diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index f4ed28e8e..942970f5f 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -755,13 +755,13 @@ class FullO3CPU : public BaseO3CPU bool lockFlag; /** Stat for total number of times the CPU is descheduled. */ - Stats::Scalar<> timesIdled; + Stats::Scalar timesIdled; /** Stat for total number of cycles the CPU spends descheduled. */ - Stats::Scalar<> idleCycles; + Stats::Scalar idleCycles; /** Stat for the number of committed instructions per thread. */ - Stats::Vector<> committedInsts; + Stats::Vector committedInsts; /** Stat for the total number of committed instructions. */ - Stats::Scalar<> totalCommittedInsts; + Stats::Scalar totalCommittedInsts; /** Stat for the CPI per thread. */ Stats::Formula cpi; /** Stat for the total CPI. */ diff --git a/src/cpu/o3/decode.hh b/src/cpu/o3/decode.hh index dc8063f29..294b5b623 100644 --- a/src/cpu/o3/decode.hh +++ b/src/cpu/o3/decode.hh @@ -288,27 +288,27 @@ class DefaultDecode /** Stat for total number of idle cycles. */ - Stats::Scalar<> decodeIdleCycles; + Stats::Scalar decodeIdleCycles; /** Stat for total number of blocked cycles. */ - Stats::Scalar<> decodeBlockedCycles; + Stats::Scalar decodeBlockedCycles; /** Stat for total number of normal running cycles. */ - Stats::Scalar<> decodeRunCycles; + Stats::Scalar decodeRunCycles; /** Stat for total number of unblocking cycles. */ - Stats::Scalar<> decodeUnblockCycles; + Stats::Scalar decodeUnblockCycles; /** Stat for total number of squashing cycles. */ - Stats::Scalar<> decodeSquashCycles; + Stats::Scalar decodeSquashCycles; /** Stat for number of times a branch is resolved at decode. */ - Stats::Scalar<> decodeBranchResolved; + Stats::Scalar decodeBranchResolved; /** Stat for number of times a branch mispredict is detected. */ - Stats::Scalar<> decodeBranchMispred; + Stats::Scalar decodeBranchMispred; /** Stat for number of times decode detected a non-control instruction * incorrectly predicted as a branch. */ - Stats::Scalar<> decodeControlMispred; + Stats::Scalar decodeControlMispred; /** Stat for total number of decoded instructions. */ - Stats::Scalar<> decodeDecodedInsts; + Stats::Scalar decodeDecodedInsts; /** Stat for total number of squashed instructions. */ - Stats::Scalar<> decodeSquashedInsts; + Stats::Scalar decodeSquashedInsts; }; #endif // __CPU_O3_DECODE_HH__ diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index 9886b6675..08ccb094b 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -448,33 +448,33 @@ class DefaultFetch // @todo: Consider making these vectors and tracking on a per thread basis. /** Stat for total number of cycles stalled due to an icache miss. */ - Stats::Scalar<> icacheStallCycles; + Stats::Scalar icacheStallCycles; /** Stat for total number of fetched instructions. */ - Stats::Scalar<> fetchedInsts; + Stats::Scalar fetchedInsts; /** Total number of fetched branches. */ - Stats::Scalar<> fetchedBranches; + Stats::Scalar fetchedBranches; /** Stat for total number of predicted branches. */ - Stats::Scalar<> predictedBranches; + Stats::Scalar predictedBranches; /** Stat for total number of cycles spent fetching. */ - Stats::Scalar<> fetchCycles; + Stats::Scalar fetchCycles; /** Stat for total number of cycles spent squashing. */ - Stats::Scalar<> fetchSquashCycles; + Stats::Scalar fetchSquashCycles; /** Stat for total number of cycles spent blocked due to other stages in * the pipeline. */ - Stats::Scalar<> fetchIdleCycles; + Stats::Scalar fetchIdleCycles; /** Total number of cycles spent blocked. */ - Stats::Scalar<> fetchBlockedCycles; + Stats::Scalar fetchBlockedCycles; /** Total number of cycles spent in any other state. */ - Stats::Scalar<> fetchMiscStallCycles; + Stats::Scalar fetchMiscStallCycles; /** Stat for total number of fetched cache lines. */ - Stats::Scalar<> fetchedCacheLines; + Stats::Scalar fetchedCacheLines; /** Total number of outstanding icache accesses that were dropped * due to a squash. */ - Stats::Scalar<> fetchIcacheSquashes; + Stats::Scalar fetchIcacheSquashes; /** Distribution of number of instructions fetched each cycle. */ - Stats::Distribution<> fetchNisnDist; + Stats::Distribution fetchNisnDist; /** Rate of how often fetch was idle. */ Stats::Formula idleRate; /** Number of branch fetches per cycle. */ diff --git a/src/cpu/o3/iew.hh b/src/cpu/o3/iew.hh index bc60f401b..3458f09d6 100644 --- a/src/cpu/o3/iew.hh +++ b/src/cpu/o3/iew.hh @@ -465,69 +465,69 @@ class DefaultIEW bool switchedOut; /** Stat for total number of idle cycles. */ - Stats::Scalar<> iewIdleCycles; + Stats::Scalar iewIdleCycles; /** Stat for total number of squashing cycles. */ - Stats::Scalar<> iewSquashCycles; + Stats::Scalar iewSquashCycles; /** Stat for total number of blocking cycles. */ - Stats::Scalar<> iewBlockCycles; + Stats::Scalar iewBlockCycles; /** Stat for total number of unblocking cycles. */ - Stats::Scalar<> iewUnblockCycles; + Stats::Scalar iewUnblockCycles; /** Stat for total number of instructions dispatched. */ - Stats::Scalar<> iewDispatchedInsts; + Stats::Scalar iewDispatchedInsts; /** Stat for total number of squashed instructions dispatch skips. */ - Stats::Scalar<> iewDispSquashedInsts; + Stats::Scalar iewDispSquashedInsts; /** Stat for total number of dispatched load instructions. */ - Stats::Scalar<> iewDispLoadInsts; + Stats::Scalar iewDispLoadInsts; /** Stat for total number of dispatched store instructions. */ - Stats::Scalar<> iewDispStoreInsts; + Stats::Scalar iewDispStoreInsts; /** Stat for total number of dispatched non speculative instructions. */ - Stats::Scalar<> iewDispNonSpecInsts; + Stats::Scalar iewDispNonSpecInsts; /** Stat for number of times the IQ becomes full. */ - Stats::Scalar<> iewIQFullEvents; + Stats::Scalar iewIQFullEvents; /** Stat for number of times the LSQ becomes full. */ - Stats::Scalar<> iewLSQFullEvents; + Stats::Scalar iewLSQFullEvents; /** Stat for total number of memory ordering violation events. */ - Stats::Scalar<> memOrderViolationEvents; + Stats::Scalar memOrderViolationEvents; /** Stat for total number of incorrect predicted taken branches. */ - Stats::Scalar<> predictedTakenIncorrect; + Stats::Scalar predictedTakenIncorrect; /** Stat for total number of incorrect predicted not taken branches. */ - Stats::Scalar<> predictedNotTakenIncorrect; + Stats::Scalar predictedNotTakenIncorrect; /** Stat for total number of mispredicted branches detected at execute. */ Stats::Formula branchMispredicts; /** Stat for total number of executed instructions. */ - Stats::Scalar<> iewExecutedInsts; + Stats::Scalar iewExecutedInsts; /** Stat for total number of executed load instructions. */ - Stats::Vector<> iewExecLoadInsts; + Stats::Vector iewExecLoadInsts; /** Stat for total number of executed store instructions. */ -// Stats::Scalar<> iewExecStoreInsts; +// Stats::Scalar iewExecStoreInsts; /** Stat for total number of squashed instructions skipped at execute. */ - Stats::Scalar<> iewExecSquashedInsts; + Stats::Scalar iewExecSquashedInsts; /** Number of executed software prefetches. */ - Stats::Vector<> iewExecutedSwp; + Stats::Vector iewExecutedSwp; /** Number of executed nops. */ - Stats::Vector<> iewExecutedNop; + Stats::Vector iewExecutedNop; /** Number of executed meomory references. */ - Stats::Vector<> iewExecutedRefs; + Stats::Vector iewExecutedRefs; /** Number of executed branches. */ - Stats::Vector<> iewExecutedBranches; + Stats::Vector iewExecutedBranches; /** Number of executed store instructions. */ Stats::Formula iewExecStoreInsts; /** Number of instructions executed per cycle. */ Stats::Formula iewExecRate; /** Number of instructions sent to commit. */ - Stats::Vector<> iewInstsToCommit; + Stats::Vector iewInstsToCommit; /** Number of instructions that writeback. */ - Stats::Vector<> writebackCount; + Stats::Vector writebackCount; /** Number of instructions that wake consumers. */ - Stats::Vector<> producerInst; + Stats::Vector producerInst; /** Number of instructions that wake up from producers. */ - Stats::Vector<> consumerInst; + Stats::Vector consumerInst; /** Number of instructions that were delayed in writing back due * to resource contention. */ - Stats::Vector<> wbPenalized; + Stats::Vector wbPenalized; /** Number of instructions per cycle written back. */ Stats::Formula wbRate; /** Average number of woken instructions per writeback. */ diff --git a/src/cpu/o3/inst_queue.hh b/src/cpu/o3/inst_queue.hh index 43da1565d..0c3f44436 100644 --- a/src/cpu/o3/inst_queue.hh +++ b/src/cpu/o3/inst_queue.hh @@ -443,58 +443,58 @@ class InstructionQueue void dumpInsts(); /** Stat for number of instructions added. */ - Stats::Scalar<> iqInstsAdded; + Stats::Scalar iqInstsAdded; /** Stat for number of non-speculative instructions added. */ - Stats::Scalar<> iqNonSpecInstsAdded; + Stats::Scalar iqNonSpecInstsAdded; - Stats::Scalar<> iqInstsIssued; + Stats::Scalar iqInstsIssued; /** Stat for number of integer instructions issued. */ - Stats::Scalar<> iqIntInstsIssued; + Stats::Scalar iqIntInstsIssued; /** Stat for number of floating point instructions issued. */ - Stats::Scalar<> iqFloatInstsIssued; + Stats::Scalar iqFloatInstsIssued; /** Stat for number of branch instructions issued. */ - Stats::Scalar<> iqBranchInstsIssued; + Stats::Scalar iqBranchInstsIssued; /** Stat for number of memory instructions issued. */ - Stats::Scalar<> iqMemInstsIssued; + Stats::Scalar iqMemInstsIssued; /** Stat for number of miscellaneous instructions issued. */ - Stats::Scalar<> iqMiscInstsIssued; + Stats::Scalar iqMiscInstsIssued; /** Stat for number of squashed instructions that were ready to issue. */ - Stats::Scalar<> iqSquashedInstsIssued; + Stats::Scalar iqSquashedInstsIssued; /** Stat for number of squashed instructions examined when squashing. */ - Stats::Scalar<> iqSquashedInstsExamined; + Stats::Scalar iqSquashedInstsExamined; /** Stat for number of squashed instruction operands examined when * squashing. */ - Stats::Scalar<> iqSquashedOperandsExamined; + Stats::Scalar iqSquashedOperandsExamined; /** Stat for number of non-speculative instructions removed due to a squash. */ - Stats::Scalar<> iqSquashedNonSpecRemoved; + Stats::Scalar iqSquashedNonSpecRemoved; // Also include number of instructions rescheduled and replayed. /** Distribution of number of instructions in the queue. * @todo: Need to create struct to track the entry time for each * instruction. */ -// Stats::VectorDistribution<> queueResDist; +// Stats::VectorDistribution queueResDist; /** Distribution of the number of instructions issued. */ - Stats::Distribution<> numIssuedDist; + Stats::Distribution numIssuedDist; /** Distribution of the cycles it takes to issue an instruction. * @todo: Need to create struct to track the ready time for each * instruction. */ -// Stats::VectorDistribution<> issueDelayDist; +// Stats::VectorDistribution issueDelayDist; /** Number of times an instruction could not be issued because a * FU was busy. */ - Stats::Vector<> statFuBusy; -// Stats::Vector<> dist_unissued; + Stats::Vector statFuBusy; +// Stats::Vector dist_unissued; /** Stat for total number issued for each instruction type. */ - Stats::Vector2d<> statIssuedInstType; + Stats::Vector2d statIssuedInstType; /** Number of instructions issued per cycle. */ Stats::Formula issueRate; /** Number of times the FU was busy. */ - Stats::Vector<> fuBusy; + Stats::Vector fuBusy; /** Number of times the FU was busy per instruction issued. */ Stats::Formula fuBusyRate; }; diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh index 8af8f18e6..5323e3a47 100644 --- a/src/cpu/o3/lsq_unit.hh +++ b/src/cpu/o3/lsq_unit.hh @@ -409,35 +409,35 @@ class LSQUnit { // of that in stage that is one level up, and only call executeLoad/Store // the appropriate number of times. /** Total number of loads forwaded from LSQ stores. */ - Stats::Scalar<> lsqForwLoads; + Stats::Scalar lsqForwLoads; /** Total number of loads ignored due to invalid addresses. */ - Stats::Scalar<> invAddrLoads; + Stats::Scalar invAddrLoads; /** Total number of squashed loads. */ - Stats::Scalar<> lsqSquashedLoads; + Stats::Scalar lsqSquashedLoads; /** Total number of responses from the memory system that are * ignored due to the instruction already being squashed. */ - Stats::Scalar<> lsqIgnoredResponses; + Stats::Scalar lsqIgnoredResponses; /** Tota number of memory ordering violations. */ - Stats::Scalar<> lsqMemOrderViolation; + Stats::Scalar lsqMemOrderViolation; /** Total number of squashed stores. */ - Stats::Scalar<> lsqSquashedStores; + Stats::Scalar lsqSquashedStores; /** Total number of software prefetches ignored due to invalid addresses. */ - Stats::Scalar<> invAddrSwpfs; + Stats::Scalar invAddrSwpfs; /** Ready loads blocked due to partial store-forwarding. */ - Stats::Scalar<> lsqBlockedLoads; + Stats::Scalar lsqBlockedLoads; /** Number of loads that were rescheduled. */ - Stats::Scalar<> lsqRescheduledLoads; + Stats::Scalar lsqRescheduledLoads; /** Number of times the LSQ is blocked due to the cache. */ - Stats::Scalar<> lsqCacheBlocked; + Stats::Scalar lsqCacheBlocked; public: /** Executes the load at the given index. */ diff --git a/src/cpu/o3/mem_dep_unit.hh b/src/cpu/o3/mem_dep_unit.hh index 4f66b4599..fa1c33320 100644 --- a/src/cpu/o3/mem_dep_unit.hh +++ b/src/cpu/o3/mem_dep_unit.hh @@ -253,13 +253,13 @@ class MemDepUnit { int id; /** Stat for number of inserted loads. */ - Stats::Scalar<> insertedLoads; + Stats::Scalar insertedLoads; /** Stat for number of inserted stores. */ - Stats::Scalar<> insertedStores; + Stats::Scalar insertedStores; /** Stat for number of conflicting loads that had to wait for a store. */ - Stats::Scalar<> conflictingLoads; + Stats::Scalar conflictingLoads; /** Stat for number of conflicting stores that had to wait for a store. */ - Stats::Scalar<> conflictingStores; + Stats::Scalar conflictingStores; }; #endif // __CPU_O3_MEM_DEP_UNIT_HH__ diff --git a/src/cpu/o3/rename.hh b/src/cpu/o3/rename.hh index c9e0d418d..0fdf28b19 100644 --- a/src/cpu/o3/rename.hh +++ b/src/cpu/o3/rename.hh @@ -441,44 +441,44 @@ class DefaultRename inline void incrFullStat(const FullSource &source); /** Stat for total number of cycles spent squashing. */ - Stats::Scalar<> renameSquashCycles; + Stats::Scalar renameSquashCycles; /** Stat for total number of cycles spent idle. */ - Stats::Scalar<> renameIdleCycles; + Stats::Scalar renameIdleCycles; /** Stat for total number of cycles spent blocking. */ - Stats::Scalar<> renameBlockCycles; + Stats::Scalar renameBlockCycles; /** Stat for total number of cycles spent stalling for a serializing inst. */ - Stats::Scalar<> renameSerializeStallCycles; + Stats::Scalar renameSerializeStallCycles; /** Stat for total number of cycles spent running normally. */ - Stats::Scalar<> renameRunCycles; + Stats::Scalar renameRunCycles; /** Stat for total number of cycles spent unblocking. */ - Stats::Scalar<> renameUnblockCycles; + Stats::Scalar renameUnblockCycles; /** Stat for total number of renamed instructions. */ - Stats::Scalar<> renameRenamedInsts; + Stats::Scalar renameRenamedInsts; /** Stat for total number of squashed instructions that rename discards. */ - Stats::Scalar<> renameSquashedInsts; + Stats::Scalar renameSquashedInsts; /** Stat for total number of times that the ROB starts a stall in rename. */ - Stats::Scalar<> renameROBFullEvents; + Stats::Scalar renameROBFullEvents; /** Stat for total number of times that the IQ starts a stall in rename. */ - Stats::Scalar<> renameIQFullEvents; + Stats::Scalar renameIQFullEvents; /** Stat for total number of times that the LSQ starts a stall in rename. */ - Stats::Scalar<> renameLSQFullEvents; + Stats::Scalar renameLSQFullEvents; /** Stat for total number of times that rename runs out of free registers * to use to rename. */ - Stats::Scalar<> renameFullRegistersEvents; + Stats::Scalar renameFullRegistersEvents; /** Stat for total number of renamed destination registers. */ - Stats::Scalar<> renameRenamedOperands; + Stats::Scalar renameRenamedOperands; /** Stat for total number of source register rename lookups. */ - Stats::Scalar<> renameRenameLookups; + Stats::Scalar renameRenameLookups; /** Stat for total number of committed renaming mappings. */ - Stats::Scalar<> renameCommittedMaps; + Stats::Scalar renameCommittedMaps; /** Stat for total number of mappings that were undone due to a squash. */ - Stats::Scalar<> renameUndoneMaps; + Stats::Scalar renameUndoneMaps; /** Number of serialize instructions handled. */ - Stats::Scalar<> renamedSerializing; + Stats::Scalar renamedSerializing; /** Number of instructions marked as temporarily serializing. */ - Stats::Scalar<> renamedTempSerializing; + Stats::Scalar renamedTempSerializing; /** Number of instructions inserted into skid buffers. */ - Stats::Scalar<> renameSkidInsts; + Stats::Scalar renameSkidInsts; }; #endif // __CPU_O3_RENAME_HH__ diff --git a/src/cpu/ozone/back_end.hh b/src/cpu/ozone/back_end.hh index 84429f3c1..ca858ce2e 100644 --- a/src/cpu/ozone/back_end.hh +++ b/src/cpu/ozone/back_end.hh @@ -157,13 +157,13 @@ class BackEnd int numInsts; int width; - Stats::VectorDistribution<> occ_dist; + Stats::VectorDistribution occ_dist; - Stats::Vector<> inst_count; - Stats::Vector<> peak_inst_count; - Stats::Scalar<> empty_count; - Stats::Scalar<> current_count; - Stats::Scalar<> fullCount; + Stats::Vector inst_count; + Stats::Vector peak_inst_count; + Stats::Scalar empty_count; + Stats::Scalar current_count; + Stats::Scalar fullCount; Stats::Formula occ_rate; Stats::Formula avg_residency; @@ -371,45 +371,45 @@ class BackEnd bool fetchRedirect[Impl::MaxThreads]; // number of cycles stalled for D-cache misses -/* Stats::Scalar<> dcacheStallCycles; +/* Stats::Scalar dcacheStallCycles; Counter lastDcacheStall; */ - Stats::Vector<> rob_cap_events; - Stats::Vector<> rob_cap_inst_count; - Stats::Vector<> iq_cap_events; - Stats::Vector<> iq_cap_inst_count; + Stats::Vector rob_cap_events; + Stats::Vector rob_cap_inst_count; + Stats::Vector iq_cap_events; + Stats::Vector iq_cap_inst_count; // total number of instructions executed - Stats::Vector<> exe_inst; - Stats::Vector<> exe_swp; - Stats::Vector<> exe_nop; - Stats::Vector<> exe_refs; - Stats::Vector<> exe_loads; - Stats::Vector<> exe_branches; + Stats::Vector exe_inst; + Stats::Vector exe_swp; + Stats::Vector exe_nop; + Stats::Vector exe_refs; + Stats::Vector exe_loads; + Stats::Vector exe_branches; - Stats::Vector<> issued_ops; + Stats::Vector issued_ops; // total number of loads forwaded from LSQ stores - Stats::Vector<> lsq_forw_loads; + Stats::Vector lsq_forw_loads; // total number of loads ignored due to invalid addresses - Stats::Vector<> inv_addr_loads; + Stats::Vector inv_addr_loads; // total number of software prefetches ignored due to invalid addresses - Stats::Vector<> inv_addr_swpfs; + Stats::Vector inv_addr_swpfs; // ready loads blocked due to memory disambiguation - Stats::Vector<> lsq_blocked_loads; + Stats::Vector lsq_blocked_loads; - Stats::Scalar<> lsqInversion; + Stats::Scalar lsqInversion; - Stats::Vector<> n_issued_dist; - Stats::VectorDistribution<> issue_delay_dist; + Stats::Vector n_issued_dist; + Stats::VectorDistribution issue_delay_dist; - Stats::VectorDistribution<> queue_res_dist; + Stats::VectorDistribution queue_res_dist; /* - Stats::Vector<> stat_fu_busy; - Stats::Vector2d<> stat_fuBusy; - Stats::Vector<> dist_unissued; - Stats::Vector2d<> stat_issued_inst_type; + Stats::Vector stat_fu_busy; + Stats::Vector2d stat_fuBusy; + Stats::Vector dist_unissued; + Stats::Vector2d stat_issued_inst_type; Stats::Formula misspec_cnt; Stats::Formula misspec_ipc; @@ -422,34 +422,34 @@ class BackEnd Stats::Formula commit_ipb; Stats::Formula lsq_inv_rate; */ - Stats::Vector<> writeback_count; - Stats::Vector<> producer_inst; - Stats::Vector<> consumer_inst; - Stats::Vector<> wb_penalized; + Stats::Vector writeback_count; + Stats::Vector producer_inst; + Stats::Vector consumer_inst; + Stats::Vector wb_penalized; Stats::Formula wb_rate; Stats::Formula wb_fanout; Stats::Formula wb_penalized_rate; // total number of instructions committed - Stats::Vector<> stat_com_inst; - Stats::Vector<> stat_com_swp; - Stats::Vector<> stat_com_refs; - Stats::Vector<> stat_com_loads; - Stats::Vector<> stat_com_membars; - Stats::Vector<> stat_com_branches; + Stats::Vector stat_com_inst; + Stats::Vector stat_com_swp; + Stats::Vector stat_com_refs; + Stats::Vector stat_com_loads; + Stats::Vector stat_com_membars; + Stats::Vector stat_com_branches; - Stats::Distribution<> n_committed_dist; + Stats::Distribution n_committed_dist; - Stats::Scalar<> commit_eligible_samples; - Stats::Vector<> commit_eligible; + Stats::Scalar commit_eligible_samples; + Stats::Vector commit_eligible; - Stats::Scalar<> ROB_fcount; + Stats::Scalar ROB_fcount; Stats::Formula ROB_full_rate; - Stats::Vector<> ROB_count; // cumulative ROB occupancy + Stats::Vector ROB_count; // cumulative ROB occupancy Stats::Formula ROB_occ_rate; - Stats::VectorDistribution<> ROB_occ_dist; + Stats::VectorDistribution ROB_occ_dist; public: void dumpInsts(); }; diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index 054fc1aa1..0bfb4bfa9 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -390,7 +390,7 @@ class OzoneCPU : public BaseCPU Counter startNumLoad; // number of idle cycles - Stats::Average<> notIdleFraction; + Stats::Average notIdleFraction; Stats::Formula idleFraction; public: @@ -473,7 +473,7 @@ class OzoneCPU : public BaseCPU bool lockFlag; - Stats::Scalar<> quiesceCycles; + Stats::Scalar quiesceCycles; Checker *checker; }; diff --git a/src/cpu/ozone/front_end.hh b/src/cpu/ozone/front_end.hh index fac243449..38fc89e3f 100644 --- a/src/cpu/ozone/front_end.hh +++ b/src/cpu/ozone/front_end.hh @@ -275,48 +275,48 @@ class FrontEnd private: // number of idle cycles /* - Stats::Average<> notIdleFraction; + Stats::Average notIdleFraction; Stats::Formula idleFraction; */ // @todo: Consider making these vectors and tracking on a per thread basis. /** Stat for total number of cycles stalled due to an icache miss. */ - Stats::Scalar<> icacheStallCycles; + Stats::Scalar icacheStallCycles; /** Stat for total number of fetched instructions. */ - Stats::Scalar<> fetchedInsts; - Stats::Scalar<> fetchedBranches; + Stats::Scalar fetchedInsts; + Stats::Scalar fetchedBranches; /** Stat for total number of predicted branches. */ - Stats::Scalar<> predictedBranches; + Stats::Scalar predictedBranches; /** Stat for total number of cycles spent fetching. */ - Stats::Scalar<> fetchCycles; + Stats::Scalar fetchCycles; - Stats::Scalar<> fetchIdleCycles; + Stats::Scalar fetchIdleCycles; /** Stat for total number of cycles spent squashing. */ - Stats::Scalar<> fetchSquashCycles; + Stats::Scalar fetchSquashCycles; /** Stat for total number of cycles spent blocked due to other stages in * the pipeline. */ - Stats::Scalar<> fetchBlockedCycles; + Stats::Scalar fetchBlockedCycles; /** Stat for total number of fetched cache lines. */ - Stats::Scalar<> fetchedCacheLines; + Stats::Scalar fetchedCacheLines; - Stats::Scalar<> fetchIcacheSquashes; + Stats::Scalar fetchIcacheSquashes; /** Distribution of number of instructions fetched each cycle. */ - Stats::Distribution<> fetchNisnDist; -// Stats::Vector<> qfull_iq_occupancy; -// Stats::VectorDistribution<> qfull_iq_occ_dist_; + Stats::Distribution fetchNisnDist; +// Stats::Vector qfull_iq_occupancy; +// Stats::VectorDistribution qfull_iq_occ_dist_; Stats::Formula idleRate; Stats::Formula branchRate; Stats::Formula fetchRate; - Stats::Scalar<> IFQCount; // cumulative IFQ occupancy + Stats::Scalar IFQCount; // cumulative IFQ occupancy Stats::Formula IFQOccupancy; Stats::Formula IFQLatency; - Stats::Scalar<> IFQFcount; // cumulative IFQ full count + Stats::Scalar IFQFcount; // cumulative IFQ full count Stats::Formula IFQFullRate; - Stats::Scalar<> dispatchCountStat; - Stats::Scalar<> dispatchedSerializing; - Stats::Scalar<> dispatchedTempSerializing; - Stats::Scalar<> dispatchSerializeStallCycles; + Stats::Scalar dispatchCountStat; + Stats::Scalar dispatchedSerializing; + Stats::Scalar dispatchedTempSerializing; + Stats::Scalar dispatchSerializeStallCycles; Stats::Formula dispatchRate; Stats::Formula regIntFull; Stats::Formula regFpFull; diff --git a/src/cpu/ozone/inorder_back_end.hh b/src/cpu/ozone/inorder_back_end.hh index 0840591e0..e930144be 100644 --- a/src/cpu/ozone/inorder_back_end.hh +++ b/src/cpu/ozone/inorder_back_end.hh @@ -192,7 +192,7 @@ class InorderBackEnd TimeBuffer *comm; // number of cycles stalled for D-cache misses - Stats::Scalar<> dcacheStallCycles; + Stats::Scalar dcacheStallCycles; Counter lastDcacheStall; }; diff --git a/src/cpu/ozone/inst_queue.hh b/src/cpu/ozone/inst_queue.hh index a11d5204b..e840d5c21 100644 --- a/src/cpu/ozone/inst_queue.hh +++ b/src/cpu/ozone/inst_queue.hh @@ -473,35 +473,35 @@ class InstQueue void dumpInsts(); /** Stat for number of instructions added. */ - Stats::Scalar<> iqInstsAdded; + Stats::Scalar iqInstsAdded; /** Stat for number of non-speculative instructions added. */ - Stats::Scalar<> iqNonSpecInstsAdded; -// Stats::Scalar<> iqIntInstsAdded; + Stats::Scalar iqNonSpecInstsAdded; +// Stats::Scalar iqIntInstsAdded; /** Stat for number of integer instructions issued. */ - Stats::Scalar<> iqIntInstsIssued; -// Stats::Scalar<> iqFloatInstsAdded; + Stats::Scalar iqIntInstsIssued; +// Stats::Scalar iqFloatInstsAdded; /** Stat for number of floating point instructions issued. */ - Stats::Scalar<> iqFloatInstsIssued; -// Stats::Scalar<> iqBranchInstsAdded; + Stats::Scalar iqFloatInstsIssued; +// Stats::Scalar iqBranchInstsAdded; /** Stat for number of branch instructions issued. */ - Stats::Scalar<> iqBranchInstsIssued; -// Stats::Scalar<> iqMemInstsAdded; + Stats::Scalar iqBranchInstsIssued; +// Stats::Scalar iqMemInstsAdded; /** Stat for number of memory instructions issued. */ - Stats::Scalar<> iqMemInstsIssued; -// Stats::Scalar<> iqMiscInstsAdded; + Stats::Scalar iqMemInstsIssued; +// Stats::Scalar iqMiscInstsAdded; /** Stat for number of miscellaneous instructions issued. */ - Stats::Scalar<> iqMiscInstsIssued; + Stats::Scalar iqMiscInstsIssued; /** Stat for number of squashed instructions that were ready to issue. */ - Stats::Scalar<> iqSquashedInstsIssued; + Stats::Scalar iqSquashedInstsIssued; /** Stat for number of squashed instructions examined when squashing. */ - Stats::Scalar<> iqSquashedInstsExamined; + Stats::Scalar iqSquashedInstsExamined; /** Stat for number of squashed instruction operands examined when * squashing. */ - Stats::Scalar<> iqSquashedOperandsExamined; + Stats::Scalar iqSquashedOperandsExamined; /** Stat for number of non-speculative instructions removed due to a squash. */ - Stats::Scalar<> iqSquashedNonSpecRemoved; + Stats::Scalar iqSquashedNonSpecRemoved; }; diff --git a/src/cpu/ozone/lsq_unit.hh b/src/cpu/ozone/lsq_unit.hh index 981682c26..47be245e5 100644 --- a/src/cpu/ozone/lsq_unit.hh +++ b/src/cpu/ozone/lsq_unit.hh @@ -331,7 +331,7 @@ class OzoneLSQ { //list mshrSeqNums; - //Stats::Scalar<> dcacheStallCycles; + //Stats::Scalar dcacheStallCycles; Counter lastDcacheStall; /** Wire to read information from the issue stage time queue. */ diff --git a/src/cpu/ozone/lw_back_end.hh b/src/cpu/ozone/lw_back_end.hh index 8ab50d5c9..4a1657c9b 100644 --- a/src/cpu/ozone/lw_back_end.hh +++ b/src/cpu/ozone/lw_back_end.hh @@ -326,47 +326,47 @@ class LWBackEnd bool exactFullStall; // number of cycles stalled for D-cache misses -/* Stats::Scalar<> dcacheStallCycles; +/* Stats::Scalar dcacheStallCycles; Counter lastDcacheStall; */ - Stats::Vector<> robCapEvents; - Stats::Vector<> robCapInstCount; - Stats::Vector<> iqCapEvents; - Stats::Vector<> iqCapInstCount; + Stats::Vector robCapEvents; + Stats::Vector robCapInstCount; + Stats::Vector iqCapEvents; + Stats::Vector iqCapInstCount; // total number of instructions executed - Stats::Vector<> exeInst; - Stats::Vector<> exeSwp; - Stats::Vector<> exeNop; - Stats::Vector<> exeRefs; - Stats::Vector<> exeLoads; - Stats::Vector<> exeBranches; + Stats::Vector exeInst; + Stats::Vector exeSwp; + Stats::Vector exeNop; + Stats::Vector exeRefs; + Stats::Vector exeLoads; + Stats::Vector exeBranches; - Stats::Vector<> issuedOps; + Stats::Vector issuedOps; // total number of loads forwaded from LSQ stores - Stats::Vector<> lsqForwLoads; + Stats::Vector lsqForwLoads; // total number of loads ignored due to invalid addresses - Stats::Vector<> invAddrLoads; + Stats::Vector invAddrLoads; // total number of software prefetches ignored due to invalid addresses - Stats::Vector<> invAddrSwpfs; + Stats::Vector invAddrSwpfs; // ready loads blocked due to memory disambiguation - Stats::Vector<> lsqBlockedLoads; + Stats::Vector lsqBlockedLoads; - Stats::Scalar<> lsqInversion; + Stats::Scalar lsqInversion; - Stats::Vector<> nIssuedDist; + Stats::Vector nIssuedDist; /* - Stats::VectorDistribution<> issueDelayDist; + Stats::VectorDistribution issueDelayDist; - Stats::VectorDistribution<> queueResDist; + Stats::VectorDistribution queueResDist; */ /* - Stats::Vector<> stat_fu_busy; - Stats::Vector2d<> stat_fuBusy; - Stats::Vector<> dist_unissued; - Stats::Vector2d<> stat_issued_inst_type; + Stats::Vector stat_fu_busy; + Stats::Vector2d stat_fuBusy; + Stats::Vector dist_unissued; + Stats::Vector2d stat_issued_inst_type; Stats::Formula misspec_cnt; Stats::Formula misspec_ipc; @@ -379,37 +379,37 @@ class LWBackEnd Stats::Formula commit_ipb; Stats::Formula lsq_inv_rate; */ - Stats::Vector<> writebackCount; - Stats::Vector<> producerInst; - Stats::Vector<> consumerInst; - Stats::Vector<> wbPenalized; + Stats::Vector writebackCount; + Stats::Vector producerInst; + Stats::Vector consumerInst; + Stats::Vector wbPenalized; Stats::Formula wbRate; Stats::Formula wbFanout; Stats::Formula wbPenalizedRate; // total number of instructions committed - Stats::Vector<> statComInst; - Stats::Vector<> statComSwp; - Stats::Vector<> statComRefs; - Stats::Vector<> statComLoads; - Stats::Vector<> statComMembars; - Stats::Vector<> statComBranches; + Stats::Vector statComInst; + Stats::Vector statComSwp; + Stats::Vector statComRefs; + Stats::Vector statComLoads; + Stats::Vector statComMembars; + Stats::Vector statComBranches; - Stats::Distribution<> nCommittedDist; + Stats::Distribution nCommittedDist; - Stats::Scalar<> commitEligibleSamples; - Stats::Vector<> commitEligible; + Stats::Scalar commitEligibleSamples; + Stats::Vector commitEligible; - Stats::Vector<> squashedInsts; - Stats::Vector<> ROBSquashedInsts; + Stats::Vector squashedInsts; + Stats::Vector ROBSquashedInsts; - Stats::Scalar<> ROBFcount; + Stats::Scalar ROBFcount; Stats::Formula ROBFullRate; - Stats::Vector<> ROBCount; // cumulative ROB occupancy + Stats::Vector ROBCount; // cumulative ROB occupancy Stats::Formula ROBOccRate; -// Stats::VectorDistribution<> ROBOccDist; +// Stats::VectorDistribution ROBOccDist; public: void dumpInsts(); diff --git a/src/cpu/ozone/lw_lsq.hh b/src/cpu/ozone/lw_lsq.hh index 2525da76e..4f8101bc0 100644 --- a/src/cpu/ozone/lw_lsq.hh +++ b/src/cpu/ozone/lw_lsq.hh @@ -411,9 +411,9 @@ class OzoneLWLSQ { //list mshrSeqNums; /** Tota number of memory ordering violations. */ - Stats::Scalar<> lsqMemOrderViolation; + Stats::Scalar lsqMemOrderViolation; - //Stats::Scalar<> dcacheStallCycles; + //Stats::Scalar dcacheStallCycles; Counter lastDcacheStall; // Make these per thread? diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index d2ccc0ff1..e80606388 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -177,7 +177,7 @@ class BaseSimpleCPU : public BaseCPU // number of simulated instructions Counter numInst; Counter startNumInst; - Stats::Scalar<> numInsts; + Stats::Scalar numInsts; void countInst() { @@ -196,30 +196,30 @@ class BaseSimpleCPU : public BaseCPU static const Addr PCMask = ~((Addr)sizeof(TheISA::MachInst) - 1); // number of simulated memory references - Stats::Scalar<> numMemRefs; + Stats::Scalar numMemRefs; // number of simulated loads Counter numLoad; Counter startNumLoad; // number of idle cycles - Stats::Average<> notIdleFraction; + Stats::Average notIdleFraction; Stats::Formula idleFraction; // number of cycles stalled for I-cache responses - Stats::Scalar<> icacheStallCycles; + Stats::Scalar icacheStallCycles; Counter lastIcacheStall; // number of cycles stalled for I-cache retries - Stats::Scalar<> icacheRetryCycles; + Stats::Scalar icacheRetryCycles; Counter lastIcacheRetry; // number of cycles stalled for D-cache responses - Stats::Scalar<> dcacheStallCycles; + Stats::Scalar dcacheStallCycles; Counter lastDcacheStall; // number of cycles stalled for D-cache retries - Stats::Scalar<> dcacheRetryCycles; + Stats::Scalar dcacheRetryCycles; Counter lastDcacheRetry; virtual void serialize(std::ostream &os); diff --git a/src/cpu/thread_state.hh b/src/cpu/thread_state.hh index 4465ce635..99f0c2a87 100644 --- a/src/cpu/thread_state.hh +++ b/src/cpu/thread_state.hh @@ -155,9 +155,9 @@ struct ThreadState { /** Number of instructions committed. */ Counter numInst; /** Stat for number instructions committed. */ - Stats::Scalar<> numInsts; + Stats::Scalar numInsts; /** Stat for number of memory references. */ - Stats::Scalar<> numMemRefs; + Stats::Scalar numMemRefs; /** Number of simulated loads, used for tracking events based on * the number of loads committed. diff --git a/src/dev/copy_engine.hh b/src/dev/copy_engine.hh index 12531f68c..dfe469588 100644 --- a/src/dev/copy_engine.hh +++ b/src/dev/copy_engine.hh @@ -164,8 +164,8 @@ class CopyEngine : public PciDev private: - Stats::Vector<> bytesCopied; - Stats::Vector<> copiesProcessed; + Stats::Vector bytesCopied; + Stats::Vector copiesProcessed; // device registers CopyEngineReg::Regs regs; diff --git a/src/dev/etherdevice.hh b/src/dev/etherdevice.hh index e43f3b686..5d86275b4 100644 --- a/src/dev/etherdevice.hh +++ b/src/dev/etherdevice.hh @@ -69,20 +69,20 @@ class EtherDevice : public PciDev void regStats(); protected: - Stats::Scalar<> txBytes; - Stats::Scalar<> rxBytes; - Stats::Scalar<> txPackets; - Stats::Scalar<> rxPackets; - Stats::Scalar<> txIpChecksums; - Stats::Scalar<> rxIpChecksums; - Stats::Scalar<> txTcpChecksums; - Stats::Scalar<> rxTcpChecksums; - Stats::Scalar<> txUdpChecksums; - Stats::Scalar<> rxUdpChecksums; - Stats::Scalar<> descDmaReads; - Stats::Scalar<> descDmaWrites; - Stats::Scalar<> descDmaRdBytes; - Stats::Scalar<> descDmaWrBytes; + Stats::Scalar txBytes; + Stats::Scalar rxBytes; + Stats::Scalar txPackets; + Stats::Scalar rxPackets; + Stats::Scalar txIpChecksums; + Stats::Scalar rxIpChecksums; + Stats::Scalar txTcpChecksums; + Stats::Scalar rxTcpChecksums; + Stats::Scalar txUdpChecksums; + Stats::Scalar rxUdpChecksums; + Stats::Scalar descDmaReads; + Stats::Scalar descDmaWrites; + Stats::Scalar descDmaRdBytes; + Stats::Scalar descDmaWrBytes; Stats::Formula totBandwidth; Stats::Formula totPackets; Stats::Formula totBytes; @@ -91,33 +91,33 @@ class EtherDevice : public PciDev Stats::Formula rxBandwidth; Stats::Formula txPacketRate; Stats::Formula rxPacketRate; - Stats::Scalar<> postedSwi; + Stats::Scalar postedSwi; Stats::Formula coalescedSwi; - Stats::Scalar<> totalSwi; - Stats::Scalar<> postedRxIdle; + Stats::Scalar totalSwi; + Stats::Scalar postedRxIdle; Stats::Formula coalescedRxIdle; - Stats::Scalar<> totalRxIdle; - Stats::Scalar<> postedRxOk; + Stats::Scalar totalRxIdle; + Stats::Scalar postedRxOk; Stats::Formula coalescedRxOk; - Stats::Scalar<> totalRxOk; - Stats::Scalar<> postedRxDesc; + Stats::Scalar totalRxOk; + Stats::Scalar postedRxDesc; Stats::Formula coalescedRxDesc; - Stats::Scalar<> totalRxDesc; - Stats::Scalar<> postedTxOk; + Stats::Scalar totalRxDesc; + Stats::Scalar postedTxOk; Stats::Formula coalescedTxOk; - Stats::Scalar<> totalTxOk; - Stats::Scalar<> postedTxIdle; + Stats::Scalar totalTxOk; + Stats::Scalar postedTxIdle; Stats::Formula coalescedTxIdle; - Stats::Scalar<> totalTxIdle; - Stats::Scalar<> postedTxDesc; + Stats::Scalar totalTxIdle; + Stats::Scalar postedTxDesc; Stats::Formula coalescedTxDesc; - Stats::Scalar<> totalTxDesc; - Stats::Scalar<> postedRxOrn; + Stats::Scalar totalTxDesc; + Stats::Scalar postedRxOrn; Stats::Formula coalescedRxOrn; - Stats::Scalar<> totalRxOrn; + Stats::Scalar totalRxOrn; Stats::Formula coalescedTotal; - Stats::Scalar<> postedInterrupts; - Stats::Scalar<> droppedPackets; + Stats::Scalar postedInterrupts; + Stats::Scalar droppedPackets; }; #endif //__DEV_ETHERDEVICE_HH__ diff --git a/src/dev/ide_disk.hh b/src/dev/ide_disk.hh index 68ae5c3c0..1b455e8ad 100644 --- a/src/dev/ide_disk.hh +++ b/src/dev/ide_disk.hh @@ -238,12 +238,12 @@ class IdeDisk : public SimObject /** Interrupt pending */ bool intrPending; - Stats::Scalar<> dmaReadFullPages; - Stats::Scalar<> dmaReadBytes; - Stats::Scalar<> dmaReadTxs; - Stats::Scalar<> dmaWriteFullPages; - Stats::Scalar<> dmaWriteBytes; - Stats::Scalar<> dmaWriteTxs; + Stats::Scalar dmaReadFullPages; + Stats::Scalar dmaReadBytes; + Stats::Scalar dmaReadTxs; + Stats::Scalar dmaWriteFullPages; + Stats::Scalar dmaWriteBytes; + Stats::Scalar dmaWriteTxs; Stats::Formula rdBandwidth; Stats::Formula wrBandwidth; Stats::Formula totBandwidth; diff --git a/src/dev/sinic.hh b/src/dev/sinic.hh index 3185e8696..cd8412ef4 100644 --- a/src/dev/sinic.hh +++ b/src/dev/sinic.hh @@ -283,35 +283,35 @@ class Device : public Base * Statistics */ private: - Stats::Scalar<> rxBytes; + Stats::Scalar rxBytes; Stats::Formula rxBandwidth; - Stats::Scalar<> rxPackets; + Stats::Scalar rxPackets; Stats::Formula rxPacketRate; - Stats::Scalar<> rxIpPackets; - Stats::Scalar<> rxTcpPackets; - Stats::Scalar<> rxUdpPackets; - Stats::Scalar<> rxIpChecksums; - Stats::Scalar<> rxTcpChecksums; - Stats::Scalar<> rxUdpChecksums; - - Stats::Scalar<> txBytes; + Stats::Scalar rxIpPackets; + Stats::Scalar rxTcpPackets; + Stats::Scalar rxUdpPackets; + Stats::Scalar rxIpChecksums; + Stats::Scalar rxTcpChecksums; + Stats::Scalar rxUdpChecksums; + + Stats::Scalar txBytes; Stats::Formula txBandwidth; Stats::Formula totBandwidth; Stats::Formula totPackets; Stats::Formula totBytes; Stats::Formula totPacketRate; - Stats::Scalar<> txPackets; + Stats::Scalar txPackets; Stats::Formula txPacketRate; - Stats::Scalar<> txIpPackets; - Stats::Scalar<> txTcpPackets; - Stats::Scalar<> txUdpPackets; - Stats::Scalar<> txIpChecksums; - Stats::Scalar<> txTcpChecksums; - Stats::Scalar<> txUdpChecksums; - - Stats::Scalar<> totalVnicDistance; - Stats::Scalar<> numVnicDistance; - Stats::Scalar<> maxVnicDistance; + Stats::Scalar txIpPackets; + Stats::Scalar txTcpPackets; + Stats::Scalar txUdpPackets; + Stats::Scalar txIpChecksums; + Stats::Scalar txTcpChecksums; + Stats::Scalar txUdpChecksums; + + Stats::Scalar totalVnicDistance; + Stats::Scalar numVnicDistance; + Stats::Scalar maxVnicDistance; Stats::Formula avgVnicDistance; int _maxVnicDistance; diff --git a/src/kern/kernel_stats.hh b/src/kern/kernel_stats.hh index 66248c9c8..85a47ec00 100644 --- a/src/kern/kernel_stats.hh +++ b/src/kern/kernel_stats.hh @@ -51,17 +51,17 @@ class Statistics : public Serializable std::string myname; protected: - Stats::Scalar<> _arm; - Stats::Scalar<> _quiesce; - Stats::Scalar<> _hwrei; + Stats::Scalar _arm; + Stats::Scalar _quiesce; + Stats::Scalar _hwrei; - Stats::Vector<> _iplCount; - Stats::Vector<> _iplGood; - Stats::Vector<> _iplTicks; + Stats::Vector _iplCount; + Stats::Vector _iplGood; + Stats::Vector _iplTicks; Stats::Formula _iplUsed; - Stats::Vector<> _syscall; -// Stats::Vector<> _faults; + Stats::Vector _syscall; +// Stats::Vector _faults; private: int iplLast; diff --git a/src/mem/cache/base.hh b/src/mem/cache/base.hh index fe191fb1c..4319717e5 100644 --- a/src/mem/cache/base.hh +++ b/src/mem/cache/base.hh @@ -223,14 +223,14 @@ class BaseCache : public MemObject */ /** Number of hits per thread for each type of command. @sa Packet::Command */ - Stats::Vector<> hits[MemCmd::NUM_MEM_CMDS]; + Stats::Vector hits[MemCmd::NUM_MEM_CMDS]; /** Number of hits for demand accesses. */ Stats::Formula demandHits; /** Number of hit for all accesses. */ Stats::Formula overallHits; /** Number of misses per thread for each type of command. @sa Packet::Command */ - Stats::Vector<> misses[MemCmd::NUM_MEM_CMDS]; + Stats::Vector misses[MemCmd::NUM_MEM_CMDS]; /** Number of misses for demand accesses. */ Stats::Formula demandMisses; /** Number of misses for all accesses. */ @@ -240,7 +240,7 @@ class BaseCache : public MemObject * Total number of cycles per thread/command spent waiting for a miss. * Used to calculate the average miss latency. */ - Stats::Vector<> missLatency[MemCmd::NUM_MEM_CMDS]; + Stats::Vector missLatency[MemCmd::NUM_MEM_CMDS]; /** Total number of cycles spent waiting for demand misses. */ Stats::Formula demandMissLatency; /** Total number of cycles spent waiting for all misses. */ @@ -268,50 +268,50 @@ class BaseCache : public MemObject Stats::Formula overallAvgMissLatency; /** The total number of cycles blocked for each blocked cause. */ - Stats::Vector<> blocked_cycles; + Stats::Vector blocked_cycles; /** The number of times this cache blocked for each blocked cause. */ - Stats::Vector<> blocked_causes; + Stats::Vector blocked_causes; /** The average number of cycles blocked for each blocked cause. */ Stats::Formula avg_blocked; /** The number of fast writes (WH64) performed. */ - Stats::Scalar<> fastWrites; + Stats::Scalar fastWrites; /** The number of cache copies performed. */ - Stats::Scalar<> cacheCopies; + Stats::Scalar cacheCopies; /** Number of blocks written back per thread. */ - Stats::Vector<> writebacks; + Stats::Vector writebacks; /** Number of misses that hit in the MSHRs per command and thread. */ - Stats::Vector<> mshr_hits[MemCmd::NUM_MEM_CMDS]; + Stats::Vector mshr_hits[MemCmd::NUM_MEM_CMDS]; /** Demand misses that hit in the MSHRs. */ Stats::Formula demandMshrHits; /** Total number of misses that hit in the MSHRs. */ Stats::Formula overallMshrHits; /** Number of misses that miss in the MSHRs, per command and thread. */ - Stats::Vector<> mshr_misses[MemCmd::NUM_MEM_CMDS]; + Stats::Vector mshr_misses[MemCmd::NUM_MEM_CMDS]; /** Demand misses that miss in the MSHRs. */ Stats::Formula demandMshrMisses; /** Total number of misses that miss in the MSHRs. */ Stats::Formula overallMshrMisses; /** Number of misses that miss in the MSHRs, per command and thread. */ - Stats::Vector<> mshr_uncacheable[MemCmd::NUM_MEM_CMDS]; + Stats::Vector mshr_uncacheable[MemCmd::NUM_MEM_CMDS]; /** Total number of misses that miss in the MSHRs. */ Stats::Formula overallMshrUncacheable; /** Total cycle latency of each MSHR miss, per command and thread. */ - Stats::Vector<> mshr_miss_latency[MemCmd::NUM_MEM_CMDS]; + Stats::Vector mshr_miss_latency[MemCmd::NUM_MEM_CMDS]; /** Total cycle latency of demand MSHR misses. */ Stats::Formula demandMshrMissLatency; /** Total cycle latency of overall MSHR misses. */ Stats::Formula overallMshrMissLatency; /** Total cycle latency of each MSHR miss, per command and thread. */ - Stats::Vector<> mshr_uncacheable_lat[MemCmd::NUM_MEM_CMDS]; + Stats::Vector mshr_uncacheable_lat[MemCmd::NUM_MEM_CMDS]; /** Total cycle latency of overall MSHR misses. */ Stats::Formula overallMshrUncacheableLatency; @@ -342,11 +342,11 @@ class BaseCache : public MemObject Stats::Formula overallAvgMshrUncacheableLatency; /** The number of times a thread hit its MSHR cap. */ - Stats::Vector<> mshr_cap_events; + Stats::Vector mshr_cap_events; /** The number of times software prefetches caused the MSHR to block. */ - Stats::Vector<> soft_prefetch_mshr_full; + Stats::Vector soft_prefetch_mshr_full; - Stats::Scalar<> mshr_no_allocate_misses; + Stats::Scalar mshr_no_allocate_misses; /** * @} diff --git a/src/mem/cache/prefetch/base.hh b/src/mem/cache/prefetch/base.hh index 92040e899..fc027cb3b 100644 --- a/src/mem/cache/prefetch/base.hh +++ b/src/mem/cache/prefetch/base.hh @@ -79,15 +79,15 @@ class BasePrefetcher public: - Stats::Scalar<> pfIdentified; - Stats::Scalar<> pfMSHRHit; - Stats::Scalar<> pfCacheHit; - Stats::Scalar<> pfBufferHit; - Stats::Scalar<> pfRemovedFull; - Stats::Scalar<> pfRemovedMSHR; - Stats::Scalar<> pfIssued; - Stats::Scalar<> pfSpanPage; - Stats::Scalar<> pfSquashed; + Stats::Scalar pfIdentified; + Stats::Scalar pfMSHRHit; + Stats::Scalar pfCacheHit; + Stats::Scalar pfBufferHit; + Stats::Scalar pfRemovedFull; + Stats::Scalar pfRemovedMSHR; + Stats::Scalar pfIssued; + Stats::Scalar pfSpanPage; + Stats::Scalar pfSquashed; void regStats(const std::string &name); diff --git a/src/mem/cache/tags/base.hh b/src/mem/cache/tags/base.hh index b7b0c7ef0..46c7186b1 100644 --- a/src/mem/cache/tags/base.hh +++ b/src/mem/cache/tags/base.hh @@ -70,19 +70,19 @@ class BaseTags */ /** Number of replacements of valid blocks per thread. */ - Stats::Vector<> replacements; + Stats::Vector replacements; /** Per cycle average of the number of tags that hold valid data. */ - Stats::Average<> tagsInUse; + Stats::Average tagsInUse; /** The total number of references to a block before it is replaced. */ - Stats::Scalar<> totalRefs; + Stats::Scalar totalRefs; /** * The number of reference counts sampled. This is different from * replacements because we sample all the valid blocks when the simulator * exits. */ - Stats::Scalar<> sampledRefs; + Stats::Scalar sampledRefs; /** * Average number of references to a block before is was replaced. @@ -91,7 +91,7 @@ class BaseTags Stats::Formula avgRefs; /** The cycle that the warmup percentage was hit. */ - Stats::Scalar<> warmupCycle; + Stats::Scalar warmupCycle; /** * @} */ diff --git a/src/mem/cache/tags/fa_lru.hh b/src/mem/cache/tags/fa_lru.hh index 7925e1870..4eab10c49 100644 --- a/src/mem/cache/tags/fa_lru.hh +++ b/src/mem/cache/tags/fa_lru.hh @@ -139,11 +139,11 @@ class FALRU : public BaseTags */ /** Hits in each cache size >= 128K. */ - Stats::Vector<> hits; + Stats::Vector hits; /** Misses in each cache size >= 128K. */ - Stats::Vector<> misses; + Stats::Vector misses; /** Total number of accesses. */ - Stats::Scalar<> accesses; + Stats::Scalar accesses; /** * @} diff --git a/src/mem/cache/tags/iic.hh b/src/mem/cache/tags/iic.hh index 9e14dc119..45c8ee801 100644 --- a/src/mem/cache/tags/iic.hh +++ b/src/mem/cache/tags/iic.hh @@ -248,20 +248,20 @@ class IIC : public BaseTags */ /** Hash hit depth of cache hits. */ - Stats::Distribution<> hitHashDepth; + Stats::Distribution hitHashDepth; /** Hash depth for cache misses. */ - Stats::Distribution<> missHashDepth; + Stats::Distribution missHashDepth; /** Count of accesses to each hash set. */ - Stats::Distribution<> setAccess; + Stats::Distribution setAccess; /** The total hash depth for every miss. */ - Stats::Scalar<> missDepthTotal; + Stats::Scalar missDepthTotal; /** The total hash depth for all hits. */ - Stats::Scalar<> hitDepthTotal; + Stats::Scalar hitDepthTotal; /** The number of hash misses. */ - Stats::Scalar<> hashMiss; + Stats::Scalar hashMiss; /** The number of hash hits. */ - Stats::Scalar<> hashHit; + Stats::Scalar hashHit; /** @} */ public: diff --git a/src/mem/cache/tags/iic_repl/gen.hh b/src/mem/cache/tags/iic_repl/gen.hh index 22436b384..fe105d95a 100644 --- a/src/mem/cache/tags/iic_repl/gen.hh +++ b/src/mem/cache/tags/iic_repl/gen.hh @@ -162,11 +162,11 @@ class GenRepl : public Repl * @{ */ /** The number of replacements from each pool. */ - Stats::Distribution<> repl_pool; + Stats::Distribution repl_pool; /** The number of advances out of each pool. */ - Stats::Distribution<> advance_pool; + Stats::Distribution advance_pool; /** The number of demotions from each pool. */ - Stats::Distribution<> demote_pool; + Stats::Distribution demote_pool; /** * @} */ diff --git a/src/mem/dram.hh b/src/mem/dram.hh index 352ca96ae..1745fa52b 100644 --- a/src/mem/dram.hh +++ b/src/mem/dram.hh @@ -117,27 +117,27 @@ class DRAMMemory : public PhysicalMemory Tick time_last_access; - Stats::Vector<> accesses; - Stats::Vector<> bytesRequested; - Stats::Vector<> bytesSent; - Stats::Vector<> compressedAccesses; - - Stats::Vector<> cycles_nCKE; - Stats::Vector<> cycles_all_precharge_CKE; - Stats::Vector<> cycles_all_precharge_nCKE; - Stats::Vector<> cycles_bank_active_nCKE; - Stats::Vector<> cycles_avg_ACT; - Stats::Vector<> cycles_read_out; - Stats::Vector<> cycles_write_in; - Stats::Vector<> cycles_between_misses; - Stats::Vector<> other_bank_read_access_miss; - Stats::Vector<> other_bank_write_access_miss; - Stats::Scalar<> total_latency; - Stats::Scalar<> total_icache_req; - Stats::Scalar<> total_arb_latency; + Stats::Vector accesses; + Stats::Vector bytesRequested; + Stats::Vector bytesSent; + Stats::Vector compressedAccesses; + + Stats::Vector cycles_nCKE; + Stats::Vector cycles_all_precharge_CKE; + Stats::Vector cycles_all_precharge_nCKE; + Stats::Vector cycles_bank_active_nCKE; + Stats::Vector cycles_avg_ACT; + Stats::Vector cycles_read_out; + Stats::Vector cycles_write_in; + Stats::Vector cycles_between_misses; + Stats::Vector other_bank_read_access_miss; + Stats::Vector other_bank_write_access_miss; + Stats::Scalar total_latency; + Stats::Scalar total_icache_req; + Stats::Scalar total_arb_latency; Stats::Formula avg_latency; Stats::Formula avg_arb_latency; - Stats::Vector2d<> bank_access_profile; + Stats::Vector2d bank_access_profile; protected: diff --git a/src/sim/faults.hh b/src/sim/faults.hh index cfc6ad105..75696641b 100644 --- a/src/sim/faults.hh +++ b/src/sim/faults.hh @@ -41,7 +41,7 @@ class FaultBase; typedef RefCountingPtr Fault; typedef const char * FaultName; -typedef Stats::Scalar<> FaultStat; +typedef Stats::Scalar FaultStat; // Each class has it's name statically define in _name, // and has a virtual function to access it's name. diff --git a/src/sim/process.hh b/src/sim/process.hh index 790adcb87..527209467 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -137,7 +137,7 @@ class Process : public SimObject std::string prog_fname; // file name - Stats::Scalar<> num_syscalls; // number of syscalls executed + Stats::Scalar num_syscalls; // number of syscalls executed protected: diff --git a/src/unittest/stattest.cc b/src/unittest/stattest.cc index 30b7f8a6c..3934786ec 100644 --- a/src/unittest/stattest.cc +++ b/src/unittest/stattest.cc @@ -116,22 +116,22 @@ main(int argc, char *argv[]) if (!text && (compat || descriptions)) usage(); - Scalar<> s1; - Scalar<> s2; - Average<> s3; - Scalar<> s4; - Vector<> s5; - Distribution<> s6; - Vector<> s7; - AverageVector<> s8; - StandardDeviation<> s9; - AverageDeviation<> s10; - Scalar<> s11; - Distribution<> s12; - VectorDistribution<> s13; - VectorStandardDeviation<> s14; - VectorAverageDeviation<> s15; - Vector2d<> s16; + Scalar s1; + Scalar s2; + Average s3; + Scalar s4; + Vector s5; + Distribution s6; + Vector s7; + AverageVector s8; + StandardDeviation s9; + AverageDeviation s10; + Scalar s11; + Distribution s12; + VectorDistribution s13; + VectorStandardDeviation s14; + VectorAverageDeviation s15; + Vector2d s16; Value s17; Value s18; @@ -141,9 +141,9 @@ main(int argc, char *argv[]) Formula f4; Formula f5; - cprintf("sizeof(Scalar<>) = %d\n", sizeof(Scalar<>)); - cprintf("sizeof(Vector<>) = %d\n", sizeof(Vector<>)); - cprintf("sizeof(Distribution<>) = %d\n", sizeof(Distribution<>)); + cprintf("sizeof(Scalar) = %d\n", sizeof(Scalar)); + cprintf("sizeof(Vector) = %d\n", sizeof(Vector)); + cprintf("sizeof(Distribution) = %d\n", sizeof(Distribution)); s1 .name("Stat01") -- cgit v1.2.3 From 9f45fbaaa6e5f0fc63c63162b756c44b33e367f5 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 5 Mar 2009 19:09:53 -0800 Subject: stats: clean up how templates are used on the data side. This basically works by taking advantage of the curiously recurring template pattern in an intelligent way so as to reduce the number of lines of code and hopefully make things a little bit clearer. --- src/base/statistics.cc | 78 +++--- src/base/statistics.hh | 639 +++++++++++++++++++++---------------------------- 2 files changed, 315 insertions(+), 402 deletions(-) (limited to 'src') diff --git a/src/base/statistics.cc b/src/base/statistics.cc index 032cbf689..c77816f23 100644 --- a/src/base/statistics.cc +++ b/src/base/statistics.cc @@ -158,7 +158,7 @@ Info::less(Info *stat1, Info *stat2) bool Info::baseCheck() const { - if (!(flags & init)) { + if (!(flags & Stats::init)) { #ifdef DEBUG cprintf("this is stat number %d\n", id); #endif @@ -175,21 +175,52 @@ Info::baseCheck() const } +Formula::Formula() +{ + setInit(); +} + +Formula::Formula(Temp r) +{ + root = r; + assert(size()); +} + +const Formula & +Formula::operator=(Temp r) +{ + assert(!root && "Can't change formulas"); + root = r; + assert(size()); + return *this; +} + +const Formula & +Formula::operator+=(Temp r) +{ + if (root) + root = NodePtr(new BinaryNode >(root, r)); + else + root = r; + assert(size()); + return *this; +} + void -FormulaBase::result(VResult &vec) const +Formula::result(VResult &vec) const { if (root) vec = root->result(); } Result -FormulaBase::total() const +Formula::total() const { return root ? root->total() : 0.0; } size_type -FormulaBase::size() const +Formula::size() const { if (!root) return 0; @@ -198,12 +229,12 @@ FormulaBase::size() const } void -FormulaBase::reset() +Formula::reset() { } bool -FormulaBase::zero() const +Formula::zero() const { VResult vec; result(vec); @@ -214,47 +245,16 @@ FormulaBase::zero() const } void -FormulaBase::update(Info *) +Formula::update() { } string -FormulaBase::str() const +Formula::str() const { return root ? root->str() : ""; } -Formula::Formula() -{ - setInit(); -} - -Formula::Formula(Temp r) -{ - root = r; - assert(size()); -} - -const Formula & -Formula::operator=(Temp r) -{ - assert(!root && "Can't change formulas"); - root = r; - assert(size()); - return *this; -} - -const Formula & -Formula::operator+=(Temp r) -{ - if (root) - root = NodePtr(new BinaryNode >(root, r)); - else - root = r; - assert(size()); - return *this; -} - void check() { diff --git a/src/base/statistics.hh b/src/base/statistics.hh index 7b69184e9..ef22ebe24 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -114,6 +114,14 @@ class Info Info(); virtual ~Info(); + /** + * Check that this stat has been set up properly and is ready for + * use + * @return true for success + */ + virtual bool check() const = 0; + bool baseCheck() const; + /** * Reset the stat to the default state. */ @@ -125,14 +133,6 @@ class Info */ virtual bool zero() const = 0; - /** - * Check that this stat has been set up properly and is ready for - * use - * @return true for success - */ - virtual bool check() const = 0; - bool baseCheck() const; - /** * Visitor entry for outputing statistics data */ @@ -187,8 +187,8 @@ class VectorInfoBase : public Info { public: /** Names and descriptions of subfields. */ - mutable std::vector subnames; - mutable std::vector subdescs; + std::vector subnames; + std::vector subdescs; public: virtual size_type size() const = 0; @@ -242,7 +242,7 @@ class VectorInfo : public InfoWrap visit(Visit &visitor) { this->update(); - this->s.update(this); + this->s.update(); visitor.visit(*this); } }; @@ -275,7 +275,7 @@ class DistInfo : public InfoWrap void visit(Visit &visitor) { - this->s.update(this); + this->s.update(); visitor.visit(*this); } }; @@ -285,9 +285,9 @@ class VectorDistInfoBase : public Info public: std::vector data; - /** Names and descriptions of subfields. */ - mutable std::vector subnames; - mutable std::vector subdescs; + /** Names and descriptions of subfields. */ + std::vector subnames; + std::vector subdescs; protected: /** Local storage for the entry values, used for printing. */ @@ -320,7 +320,7 @@ class VectorDistInfo : public InfoWrap visit(Visit &visitor) { this->update(); - this->s.update(this); + this->s.update(); visitor.visit(*this); } }; @@ -333,10 +333,11 @@ class Vector2dInfoBase : public Info std::vector subdescs; std::vector y_subnames; + size_type x; + size_type y; + /** Local storage for the entry values, used for printing. */ mutable VCounter cvec; - mutable size_type x; - mutable size_type y; public: void @@ -357,7 +358,7 @@ class Vector2dInfo : public InfoWrap visit(Visit &visitor) { this->update(); - this->s.update(this); + this->s.update(); visitor.visit(*this); } }; @@ -397,29 +398,27 @@ class InfoAccess bool check() const { return true; } }; -template class Info> -class DataWrap : public Base +template class InfoType> +class DataWrap : public InfoAccess { public: - typedef Derived DerivedType; - typedef Base BaseType; - typedef Info InfoType; + typedef InfoType Info; protected: - Derived &self() { return *reinterpret_cast(this); } + Derived &self() { return *static_cast(this); } protected: - InfoType * + Info * info() { - return safe_cast(InfoAccess::info()); + return safe_cast(InfoAccess::info()); } public: - const InfoType * + const Info * info() const { - return safe_cast(InfoAccess::info()); + return safe_cast(InfoAccess::info()); } protected: @@ -436,7 +435,7 @@ class DataWrap : public Base public: DataWrap() { - this->setInfo(new InfoType(*this)); + this->setInfo(new Info(self())); } /** @@ -447,11 +446,12 @@ class DataWrap : public Base Derived & name(const std::string &_name) { - InfoType *info = this->info(); + Info *info = this->info(); info->name = _name; info->flags |= print; return this->self(); } + const std::string &name() const { return this->info()->name; } /** * Set the description and marks this stat to print at the end of @@ -505,15 +505,12 @@ class DataWrap : public Base } }; -template class Info> -class DataWrapVec : public DataWrap +template class InfoType> +class DataWrapVec : public DataWrap { public: - typedef Derived DerivedType; - typedef Base BaseType; - typedef Info InfoType; + typedef InfoType Info; - public: // The following functions are specific to vectors. If you use them // in a non vector context, you will get a nice compiler error! @@ -527,13 +524,20 @@ class DataWrapVec : public DataWrap Derived & subname(off_type index, const std::string &name) { - std::vector &subn = this->info()->subnames; + Derived &self = this->self(); + Info *info = this->info(); + + std::vector &subn = info->subnames; if (subn.size() <= index) subn.resize(index + 1); subn[index] = name; - return this->self(); + return self; } + // The following functions are specific to 2d vectors. If you use + // them in a non vector context, you will get a nice compiler + // error because info doesn't have the right variables. + /** * Set the subfield description for the given index and marks this stat to * print at the end of simulation. @@ -544,7 +548,9 @@ class DataWrapVec : public DataWrap Derived & subdesc(off_type index, const std::string &desc) { - std::vector &subd = this->info()->subdescs; + Info *info = this->info(); + + std::vector &subd = info->subdescs; if (subd.size() <= index) subd.resize(index + 1); subd[index] = desc; @@ -552,17 +558,24 @@ class DataWrapVec : public DataWrap return this->self(); } + void + reset() + { + Derived &self = this->self(); + Info *info = this->info(); + + size_t size = self.size(); + for (off_type i = 0; i < size; ++i) + self.data(i)->reset(info); + } }; -template class Info> -class DataWrapVec2d : public DataWrapVec +template class InfoType> +class DataWrapVec2d : public DataWrapVec { public: - typedef Derived DerivedType; - typedef Base BaseType; - typedef Info InfoType; + typedef InfoType Info; - public: /** * @warning This makes the assumption that if you're gonna subnames a 2d * vector, you're subnaming across all y @@ -570,21 +583,25 @@ class DataWrapVec2d : public DataWrapVec Derived & ysubnames(const char **names) { - InfoType *info = this->info(); - info->y_subnames.resize(this->y); - for (off_type i = 0; i < this->y; ++i) + Derived &self = this->self(); + Info *info = this->info(); + + info->y_subnames.resize(self.y); + for (off_type i = 0; i < self.y; ++i) info->y_subnames[i] = names[i]; - return this->self(); + return self; } Derived & ysubname(off_type index, const std::string subname) { - InfoType *info = this->info(); - assert(index < this->y); - info->y_subnames.resize(this->y); + Derived &self = this->self(); + Info *info = this->info(); + + assert(index < self.y); + info->y_subnames.resize(self.y); info->y_subnames[index] = subname.c_str(); - return this->self(); + return self; } }; @@ -722,6 +739,11 @@ class AvgStor return (Result)(total + current) / (Result)(curTick + 1); } + /** + * @return true if zero value + */ + bool zero() const { return total == 0.0; } + /** * Reset stat value to default */ @@ -732,18 +754,14 @@ class AvgStor last = curTick; } - /** - * @return true if zero value - */ - bool zero() const { return total == 0.0; } }; /** * Implementation of a scalar stat. The type of stat is determined by the * Storage template. */ -template -class ScalarBase : public InfoAccess +template +class ScalarBase : public DataWrap { public: typedef Stor Storage; @@ -780,8 +798,8 @@ class ScalarBase : public InfoAccess void doInit() { - new (storage) Storage(info()); - setInit(); + new (storage) Storage(this->info()); + this->setInit(); } public: @@ -792,7 +810,10 @@ class ScalarBase : public InfoAccess Counter value() const { return data()->value(); } public: - ScalarBase() { } + ScalarBase() + { + this->doInit(); + } public: // Common operators for stats @@ -845,7 +866,7 @@ class ScalarBase : public InfoAccess /** * Reset stat value to default */ - void reset() { data()->reset(info()); } + void reset() { data()->reset(this->info()); } Counter value() { return data()->value(); } @@ -893,7 +914,8 @@ class FunctorProxy : public ProxyInfo Result total() const { return (*functor)(); } }; -class ValueBase : public InfoAccess +template +class ValueBase : public DataWrap { private: ProxyInfo *proxy; @@ -903,19 +925,21 @@ class ValueBase : public InfoAccess ~ValueBase() { if (proxy) delete proxy; } template - void + Derived & scalar(T &value) { proxy = new ValueProxy(value); - setInit(); + this->setInit(); + return this->self(); } template - void + Derived & functor(T &func) { proxy = new FunctorProxy(func); - setInit(); + this->setInit(); + return this->self(); } Counter value() { return proxy->value(); } @@ -944,7 +968,7 @@ class ScalarProxy { private: /** Pointer to the parent Vector. */ - Stat *stat; + Stat &stat; /** The index to access in the parent VectorBase. */ off_type index; @@ -967,10 +991,9 @@ class ScalarProxy * Create and initialize this proxy, do not register it with the database. * @param i The index to access. */ - ScalarProxy(Stat *s, off_type i) + ScalarProxy(Stat &s, off_type i) : stat(s), index(i) { - assert(stat); } /** @@ -1000,12 +1023,12 @@ class ScalarProxy * Increment the stat by 1. This calls the associated storage object inc * function. */ - void operator++() { stat->data(index)->inc(1); } + void operator++() { stat.data(index)->inc(1); } /** * Decrement the stat by 1. This calls the associated storage object dec * function. */ - void operator--() { stat->data(index)->dec(1); } + void operator--() { stat.data(index)->dec(1); } /** Increment the stat by 1. */ void operator++(int) { ++*this; } @@ -1021,7 +1044,7 @@ class ScalarProxy void operator=(const U &v) { - stat->data(index)->set(v); + stat.data(index)->set(v); } /** @@ -1033,7 +1056,7 @@ class ScalarProxy void operator+=(const U &v) { - stat->data(index)->inc(v); + stat.data(index)->inc(v); } /** @@ -1045,7 +1068,7 @@ class ScalarProxy void operator-=(const U &v) { - stat->data(index)->dec(v); + stat.data(index)->dec(v); } /** @@ -1058,7 +1081,7 @@ class ScalarProxy std::string str() const { - return csprintf("%s[%d]", stat->info()->name, index); + return csprintf("%s[%d]", stat.info()->name, index); } }; @@ -1066,17 +1089,17 @@ class ScalarProxy * Implementation of a vector of stats. The type of stat is determined by the * Storage class. @sa ScalarBase */ -template -class VectorBase : public InfoAccess +template +class VectorBase : public DataWrapVec { public: typedef Stor Storage; typedef typename Stor::Params Params; /** Proxy type */ - typedef ScalarProxy > Proxy; - - friend class ScalarProxy >; + typedef ScalarProxy Proxy; + friend class ScalarProxy; + friend class DataWrapVec; protected: /** The storage of this stat. */ @@ -1109,9 +1132,9 @@ class VectorBase : public InfoAccess storage = reinterpret_cast(ptr); for (off_type i = 0; i < _size; ++i) - new (&storage[i]) Storage(info()); + new (&storage[i]) Storage(this->info()); - setInit(); + this->setInit(); } public: @@ -1168,13 +1191,6 @@ class VectorBase : public InfoAccess return storage != NULL; } - void - reset() - { - for (off_type i = 0; i < size(); ++i) - data(i)->reset(info()); - } - public: VectorBase() : storage(NULL) @@ -1190,6 +1206,19 @@ class VectorBase : public InfoAccess delete [] reinterpret_cast(storage); } + /** + * Set this vector to have the given size. + * @param size The new size. + * @return A reference to this stat. + */ + Derived & + init(size_type size) + { + Derived &self = this->self(); + self.doInit(size); + return self; + } + /** * Return a reference (ScalarProxy) to the stat at the given index. * @param index The vector index to access. @@ -1199,17 +1228,17 @@ class VectorBase : public InfoAccess operator[](off_type index) { assert (index >= 0 && index < size()); - return Proxy(this, index); + return Proxy(this->self(), index); } - void update(Info *data) {} + void update() {} }; template class VectorProxy { private: - Stat *stat; + Stat &stat; off_type offset; size_type len; @@ -1220,14 +1249,14 @@ class VectorProxy data(off_type index) { assert(index < len); - return stat->data(offset + index); + return stat.data(offset + index); } const typename Stat::Storage * data(off_type index) const { assert(index < len); - return const_cast(stat)->data(offset + index); + return stat.data(offset + index); } public: @@ -1252,7 +1281,7 @@ class VectorProxy } public: - VectorProxy(Stat *s, off_type o, size_type l) + VectorProxy(Stat &s, off_type o, size_type l) : stat(s), offset(o), len(l) { } @@ -1281,15 +1310,18 @@ class VectorProxy size_type size() const { return len; } }; -template -class Vector2dBase : public InfoAccess +template +class Vector2dBase : public DataWrapVec2d { public: + typedef Vector2dInfo Info; typedef Stor Storage; typedef typename Stor::Params Params; - typedef VectorProxy > Proxy; - friend class ScalarProxy >; - friend class VectorProxy >; + typedef VectorProxy Proxy; + friend class ScalarProxy; + friend class VectorProxy; + friend class DataWrapVec; + friend class DataWrapVec2d; protected: size_type x; @@ -1301,29 +1333,6 @@ class Vector2dBase : public InfoAccess Storage *data(off_type index) { return &storage[index]; } const Storage *data(off_type index) const { return &storage[index]; } - void - doInit(size_type _x, size_type _y) - { - assert(_x > 0 && _y > 0 && "sizes must be positive!"); - assert(!storage && "already initialized"); - - Vector2dInfoBase *info = safe_cast(this->info()); - - x = _x; - y = _y; - info->x = _x; - info->y = _y; - _size = x * y; - - char *ptr = new char[_size * sizeof(Storage)]; - storage = reinterpret_cast(ptr); - - for (off_type i = 0; i < _size; ++i) - new (&storage[i]) Storage(info); - - setInit(); - } - public: Vector2dBase() : storage(NULL) @@ -1340,12 +1349,39 @@ class Vector2dBase : public InfoAccess } void - update(Vector2dInfoBase *newinfo) + update() { + Info *info = this->info(); size_type size = this->size(); - newinfo->cvec.resize(size); + info->cvec.resize(size); for (off_type i = 0; i < size; ++i) - newinfo->cvec[i] = data(i)->value(); + info->cvec[i] = data(i)->value(); + } + + Derived & + init(size_type _x, size_type _y) + { + assert(_x > 0 && _y > 0 && "sizes must be positive!"); + assert(!storage && "already initialized"); + + Derived &self = this->self(); + Info *info = this->info(); + + x = _x; + y = _y; + info->x = _x; + info->y = _y; + _size = x * y; + + char *ptr = new char[_size * sizeof(Storage)]; + storage = reinterpret_cast(ptr); + + for (off_type i = 0; i < _size; ++i) + new (&storage[i]) Storage(info); + + this->setInit(); + + return self; } std::string ysubname(off_type i) const { return (*this->y_subnames)[i]; } @@ -1355,7 +1391,7 @@ class Vector2dBase : public InfoAccess { off_type offset = index * y; assert (index >= 0 && offset + index < size()); - return Proxy(this, offset, y); + return Proxy(this->self(), offset, y); } @@ -1383,8 +1419,10 @@ class Vector2dBase : public InfoAccess void reset() { - for (off_type i = 0; i < size(); ++i) - data(i)->reset(info()); + Info *info = this->info(); + size_type size = this->size(); + for (off_type i = 0; i < size; ++i) + data(i)->reset(info); } bool @@ -1699,10 +1737,11 @@ class AvgFancy * Implementation of a distribution stat. The type of distribution is * determined by the Storage template. @sa ScalarBase */ -template -class DistBase : public InfoAccess +template +class DistBase : public DataWrap { public: + typedef DistInfo Info; typedef Stor Storage; typedef typename Stor::Params Params; @@ -1734,8 +1773,8 @@ class DistBase : public InfoAccess void doInit() { - new (storage) Storage(info()); - setInit(); + new (storage) Storage(this->info()); + this->setInit(); } public: @@ -1762,9 +1801,10 @@ class DistBase : public InfoAccess bool zero() const { return data()->zero(); } void - update(DistInfoBase *base) + update() { - data()->update(info(), base->data); + Info *info = this->info(); + data()->update(info, info->data); } /** @@ -1773,21 +1813,23 @@ class DistBase : public InfoAccess void reset() { - data()->reset(info()); + data()->reset(this->info()); } }; template class DistProxy; -template -class VectorDistBase : public InfoAccess +template +class VectorDistBase : public DataWrapVec { public: + typedef VectorDistInfo Info; typedef Stor Storage; typedef typename Stor::Params Params; - typedef DistProxy > Proxy; - friend class DistProxy >; + typedef DistProxy Proxy; + friend class DistProxy; + friend class DataWrapVec; protected: Storage *storage; @@ -1816,10 +1858,11 @@ class VectorDistBase : public InfoAccess char *ptr = new char[_size * sizeof(Storage)]; storage = reinterpret_cast(ptr); + Info *info = this->info(); for (off_type i = 0; i < _size; ++i) - new (&storage[i]) Storage(info()); + new (&storage[i]) Storage(info); - setInit(); + this->setInit(); } public: @@ -1857,16 +1900,6 @@ class VectorDistBase : public InfoAccess #endif } - /** - * Reset stat value to default - */ - void - reset() - { - for (off_type i = 0; i < size(); ++i) - data(i)->reset(info()); - } - bool check() const { @@ -1874,12 +1907,15 @@ class VectorDistBase : public InfoAccess } void - update(VectorDistInfoBase *base) + update() { - size_type size = this->size(); - base->data.resize(size); + Derived &self = this->self(); + Info *info = this->info(); + + size_type size = self.size(); + info.data.resize(size); for (off_type i = 0; i < size; ++i) { - data(i)->update(info(), base->data[i]); + data(i)->update(info, info.data[i]); } } }; @@ -1938,12 +1974,13 @@ class DistProxy void reset() { } }; -template -inline typename VectorDistBase::Proxy -VectorDistBase::operator[](off_type index) +template +inline typename VectorDistBase::Proxy +VectorDistBase::operator[](off_type index) { assert (index >= 0 && index < size()); - return typename VectorDistBase::Proxy(this, index); + typedef typename VectorDistBase::Proxy Proxy; + return Proxy(this, index); } #if 0 @@ -2350,148 +2387,56 @@ class SumNode : public Node * This is a simple scalar statistic, like a counter. * @sa Stat, ScalarBase, StatStor */ -class Scalar : public DataWrap, ScalarInfo> +class Scalar : public ScalarBase { public: - /** The base implementation. */ - typedef ScalarBase Base; - - Scalar() - { - this->doInit(); - } - - /** - * Sets the stat equal to the given value. Calls the base implementation - * of operator= - * @param v The new value. - */ - template - void operator=(const U &v) { Base::operator=(v); } -}; - -class Value : public DataWrap -{ - public: - /** The base implementation. */ - typedef ValueBase Base; - - template - Value & - scalar(T &value) - { - Base::scalar(value); - return *this; - } - - template - Value & - functor(T &func) - { - Base::functor(func); - return *this; - } + using ScalarBase::operator=; }; /** * A stat that calculates the per tick average of a value. * @sa Stat, ScalarBase, AvgStor */ -class Average : public DataWrap, ScalarInfo> +class Average : public ScalarBase { public: - /** The base implementation. */ - typedef ScalarBase Base; - - Average() - { - this->doInit(); - } + using ScalarBase::operator=; +}; - /** - * Sets the stat equal to the given value. Calls the base implementation - * of operator= - * @param v The new value. - */ - template - void - operator=(const U &v) - { - Base::operator=(v); - } +class Value : public ValueBase +{ }; /** * A vector of scalar stats. * @sa Stat, VectorBase, StatStor */ -class Vector : public DataWrapVec, VectorInfo> +class Vector : public VectorBase { - public: - /** The base implementation. */ - typedef ScalarBase Base; - - /** - * Set this vector to have the given size. - * @param size The new size. - * @return A reference to this stat. - */ - Vector & - init(size_type size) - { - this->doInit(size); - return *this; - } }; /** * A vector of Average stats. * @sa Stat, VectorBase, AvgStor */ -class AverageVector - : public DataWrapVec, VectorInfo> +class AverageVector : public VectorBase { - public: - /** - * Set this vector to have the given size. - * @param size The new size. - * @return A reference to this stat. - */ - AverageVector & - init(size_type size) - { - this->doInit(size); - return *this; - } }; /** * A 2-Dimensional vecto of scalar stats. * @sa Stat, Vector2dBase, StatStor */ -class Vector2d - : public DataWrapVec2d, Vector2dInfo> +class Vector2d : public Vector2dBase { - public: - Vector2d & - init(size_type x, size_type y) - { - this->doInit(x, y); - return *this; - } }; /** * A simple distribution stat. * @sa Stat, DistBase, DistStor */ -class Distribution - : public DataWrap, DistInfo> +class Distribution : public DistBase { - public: - /** Base implementation. */ - typedef DistBase Base; - public: /** * Set the parameters of this distribution. @sa DistStor::Params @@ -2510,7 +2455,7 @@ class Distribution params->buckets = (size_type)rint((max - min) / bkt + 1.0); this->setParams(params); this->doInit(); - return *this; + return this->self(); } }; @@ -2518,13 +2463,8 @@ class Distribution * Calculates the mean and variance of all the samples. * @sa Stat, DistBase, FancyStor */ -class StandardDeviation - : public DataWrap, DistInfo> +class StandardDeviation : public DistBase { - public: - /** The base implementation */ - typedef DistBase Base; - public: /** * Construct and initialize this distribution. @@ -2539,13 +2479,8 @@ class StandardDeviation * Calculates the per tick mean and variance of the samples. * @sa Stat, DistBase, AvgFancy */ -class AverageDeviation - : public DataWrap, DistInfo> +class AverageDeviation : public DistBase { - public: - /** The base implementation */ - typedef DistBase Base; - public: /** * Construct and initialize this distribution. @@ -2560,15 +2495,8 @@ class AverageDeviation * A vector of distributions. * @sa Stat, VectorDistBase, DistStor */ -class VectorDistribution - : public DataWrapVec, - VectorDistInfo> +class VectorDistribution : public VectorDistBase { - public: - /** The base implementation */ - typedef VectorDistBase Base; - public: /** * Initialize storage and parameters for this distribution. @@ -2588,7 +2516,7 @@ class VectorDistribution params->buckets = rint((max - min) / bkt + 1.0); this->setParams(params); this->doInit(size); - return *this; + return this->self(); } }; @@ -2597,14 +2525,8 @@ class VectorDistribution * @sa Stat, VectorDistBase, FancyStor */ class VectorStandardDeviation - : public DataWrapVec, - VectorDistInfo> + : public VectorDistBase { - public: - /** The base implementation */ - typedef VectorDistBase Base; - public: /** * Initialize storage for this distribution. @@ -2615,7 +2537,7 @@ class VectorStandardDeviation init(size_type size) { this->doInit(size); - return *this; + return this->self(); } }; @@ -2624,14 +2546,8 @@ class VectorStandardDeviation * @sa Stat, VectorDistBase, AvgFancy */ class VectorAverageDeviation - : public DataWrapVec, - VectorDistInfo> + : public VectorDistBase { - public: - /** The base implementation */ - typedef VectorDistBase Base; - public: /** * Initialize storage for this distribution. @@ -2642,67 +2558,10 @@ class VectorAverageDeviation init(size_type size) { this->doInit(size); - return *this; + return this->self(); } }; -/** - * A formula for statistics that is calculated when printed. A formula is - * stored as a tree of Nodes that represent the equation to calculate. - * @sa Stat, ScalarStat, VectorStat, Node, Temp - */ -class FormulaBase : public InfoAccess -{ - protected: - /** The root of the tree which represents the Formula */ - NodePtr root; - friend class Temp; - - public: - /** - * Return the result of the Fomula in a vector. If there were no Vector - * components to the Formula, then the vector is size 1. If there were, - * like x/y with x being a vector of size 3, then the result returned will - * be x[0]/y, x[1]/y, x[2]/y, respectively. - * @return The result vector. - */ - void result(VResult &vec) const; - - /** - * Return the total Formula result. If there is a Vector - * component to this Formula, then this is the result of the - * Formula if the formula is applied after summing all the - * components of the Vector. For example, if Formula is x/y where - * x is size 3, then total() will return (x[1]+x[2]+x[3])/y. If - * there is no Vector component, total() returns the same value as - * the first entry in the VResult val() returns. - * @return The total of the result vector. - */ - Result total() const; - - /** - * Return the number of elements in the tree. - */ - size_type size() const; - - /** - * Formulas don't need to be reset - */ - void reset(); - - /** - * - */ - bool zero() const; - - /** - * - */ - void update(Info *); - - std::string str() const; -}; - class FormulaInfoBase : public VectorInfoBase { public: @@ -2734,7 +2593,7 @@ class FormulaInfo : public InfoWrap visit(Visit &visitor) { this->update(); - this->s.update(this); + this->s.update(); visitor.visit(*this); } @@ -2742,8 +2601,18 @@ class FormulaInfo : public InfoWrap }; class Temp; -class Formula : public DataWrapVec +/** + * A formula for statistics that is calculated when printed. A formula is + * stored as a tree of Nodes that represent the equation to calculate. + * @sa Stat, ScalarStat, VectorStat, Node, Temp + */ +class Formula : public DataWrapVec { + protected: + /** The root of the tree which represents the Formula */ + NodePtr root; + friend class Temp; + public: /** * Create and initialize thie formula, and register it with the database. @@ -2770,6 +2639,50 @@ class Formula : public DataWrapVec * @return a reference to this formula. */ const Formula &operator+=(Temp r); + /** + * Return the result of the Fomula in a vector. If there were no Vector + * components to the Formula, then the vector is size 1. If there were, + * like x/y with x being a vector of size 3, then the result returned will + * be x[0]/y, x[1]/y, x[2]/y, respectively. + * @return The result vector. + */ + void result(VResult &vec) const; + + /** + * Return the total Formula result. If there is a Vector + * component to this Formula, then this is the result of the + * Formula if the formula is applied after summing all the + * components of the Vector. For example, if Formula is x/y where + * x is size 3, then total() will return (x[1]+x[2]+x[3])/y. If + * there is no Vector component, total() returns the same value as + * the first entry in the VResult val() returns. + * @return The total of the result vector. + */ + Result total() const; + + /** + * Return the number of elements in the tree. + */ + size_type size() const; + + void prepare() { } + + /** + * Formulas don't need to be reset + */ + void reset(); + + /** + * + */ + bool zero() const; + + /** + * + */ + void update(); + + std::string str() const; }; class FormulaNode : public Node -- cgit v1.2.3 From 6f787e3d368eb248aee0854d99ed55e332d80170 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 5 Mar 2009 19:09:53 -0800 Subject: stats: create an enable phase, and a prepare phase. Enable more or less takes the place of check, but also allows stats to do some other configuration. Prepare moves all of the code that readies a stat for dumping into a separate function in preparation for supporting serialization of certain pieces of statistics data. While we're at it, clean up the visitor code and some of the python code. --- src/base/statistics.cc | 65 +++++++++--- src/base/statistics.hh | 264 ++++++++++++++++++++++------------------------ src/base/stats/output.cc | 3 + src/python/m5/core.py | 7 ++ src/python/m5/simulate.py | 14 +-- src/python/m5/stats.py | 19 +++- src/python/swig/stats.i | 3 +- 7 files changed, 214 insertions(+), 161 deletions(-) (limited to 'src') diff --git a/src/base/statistics.cc b/src/base/statistics.cc index c77816f23..0a59248e7 100644 --- a/src/base/statistics.cc +++ b/src/base/statistics.cc @@ -32,6 +32,7 @@ #include #include #include +#include #include #include "base/callback.hh" @@ -174,6 +175,41 @@ Info::baseCheck() const return true; } +void +Info::enable() +{ +} + +void +VectorInfoBase::enable() +{ + size_type s = size(); + if (subnames.size() < s) + subnames.resize(s); + if (subdescs.size() < s) + subdescs.resize(s); +} + +void +VectorDistInfoBase::enable() +{ + size_type s = size(); + if (subnames.size() < s) + subnames.resize(s); + if (subdescs.size() < s) + subdescs.resize(s); +} + +void +Vector2dInfoBase::enable() +{ + if (subnames.size() < x) + subnames.resize(x); + if (subdescs.size() < x) + subdescs.resize(x); + if (y_subnames.size() < y) + y_subnames.resize(y); +} Formula::Formula() { @@ -244,11 +280,6 @@ Formula::zero() const return true; } -void -Formula::update() -{ -} - string Formula::str() const { @@ -256,7 +287,7 @@ Formula::str() const } void -check() +enable() { typedef list::iterator iter_t; @@ -277,17 +308,21 @@ check() statsList().sort(Info::less); - if (i == end) - return; - - iter_t last = i; - ++i; - for (i = statsList().begin(); i != end; ++i) { - if ((*i)->name == (*last)->name) - panic("same name used twice! name=%s\n", (*i)->name); + Info *info = *i; + info->enable(); + } +} - last = i; +void +prepare() +{ + list::iterator i = statsList().begin(); + list::iterator end = statsList().end(); + while (i != end) { + Info *info = *i; + info->prepare(); + ++i; } } diff --git a/src/base/statistics.hh b/src/base/statistics.hh index ef22ebe24..6240be7a2 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -122,6 +122,16 @@ class Info virtual bool check() const = 0; bool baseCheck() const; + /** + * Enable the stat for use + */ + virtual void enable(); + + /** + * Prepare the stat for dumping. + */ + virtual void prepare() = 0; + /** * Reset the stat to the default state. */ @@ -159,7 +169,13 @@ class InfoWrap : public Base InfoWrap(Stat &stat) : s(stat) {} bool check() const { return s.check(); } + void prepare() { s.prepare(); } void reset() { s.reset(); } + void + visit(Visit &visitor) + { + visitor.visit(*static_cast(this)); + } bool zero() const { return s.zero(); } }; @@ -169,7 +185,6 @@ class ScalarInfoBase : public Info virtual Counter value() const = 0; virtual Result result() const = 0; virtual Result total() const = 0; - void visit(Visit &visitor) { visitor.visit(*this); } }; template @@ -190,24 +205,14 @@ class VectorInfoBase : public Info std::vector subnames; std::vector subdescs; + public: + void enable(); + public: virtual size_type size() const = 0; virtual const VCounter &value() const = 0; virtual const VResult &result() const = 0; virtual Result total() const = 0; - - void - update() - { - if (!subnames.empty()) { - size_type s = size(); - if (subnames.size() < s) - subnames.resize(s); - - if (subdescs.size() < s) - subdescs.resize(s); - } - } }; template @@ -237,14 +242,6 @@ class VectorInfo : public InfoWrap } Result total() const { return this->s.total(); } - - void - visit(Visit &visitor) - { - this->update(); - this->s.update(); - visitor.visit(*this); - } }; struct DistData @@ -271,13 +268,6 @@ class DistInfo : public InfoWrap { public: DistInfo(Stat &stat) : InfoWrap(stat) {} - - void - visit(Visit &visitor) - { - this->s.update(); - visitor.visit(*this); - } }; class VectorDistInfoBase : public Info @@ -288,6 +278,7 @@ class VectorDistInfoBase : public Info /** Names and descriptions of subfields. */ std::vector subnames; std::vector subdescs; + void enable(); protected: /** Local storage for the entry values, used for printing. */ @@ -295,17 +286,6 @@ class VectorDistInfoBase : public Info public: virtual size_type size() const = 0; - - void - update() - { - size_type s = size(); - if (subnames.size() < s) - subnames.resize(s); - - if (subdescs.size() < s) - subdescs.resize(s); - } }; template @@ -315,14 +295,6 @@ class VectorDistInfo : public InfoWrap VectorDistInfo(Stat &stat) : InfoWrap(stat) {} size_type size() const { return this->s.size(); } - - void - visit(Visit &visitor) - { - this->update(); - this->s.update(); - visitor.visit(*this); - } }; class Vector2dInfoBase : public Info @@ -339,13 +311,7 @@ class Vector2dInfoBase : public Info /** Local storage for the entry values, used for printing. */ mutable VCounter cvec; - public: - void - update() - { - if (subnames.size() < x) - subnames.resize(x); - } + void enable(); }; template @@ -353,14 +319,6 @@ class Vector2dInfo : public InfoWrap { public: Vector2dInfo(Stat &stat) : InfoWrap(stat) {} - - void - visit(Visit &visitor) - { - this->update(); - this->s.update(); - visitor.visit(*this); - } }; class InfoAccess @@ -382,7 +340,7 @@ class InfoAccess /** * Reset the stat to the default state. */ - void reset() {} + void reset() { } /** * @return true if this stat has a value and satisfies its @@ -525,7 +483,7 @@ class DataWrapVec : public DataWrap subname(off_type index, const std::string &name) { Derived &self = this->self(); - Info *info = this->info(); + Info *info = self.info(); std::vector &subn = info->subnames; if (subn.size() <= index) @@ -558,6 +516,17 @@ class DataWrapVec : public DataWrap return this->self(); } + void + prepare() + { + Derived &self = this->self(); + Info *info = this->info(); + + size_t size = self.size(); + for (off_type i = 0; i < size; ++i) + self.data(i)->prepare(info); + } + void reset() { @@ -657,6 +626,10 @@ class StatStor * @return The value of this stat. */ Result result() const { return (Result)data; } + /** + * Prepare stat data for dumping or serialization + */ + void prepare(Info *info) { } /** * Reset stat value to default */ @@ -734,8 +707,7 @@ class AvgStor Result result() const { - total += current * (curTick - last); - last = curTick; + assert(last == curTick); return (Result)(total + current) / (Result)(curTick + 1); } @@ -744,6 +716,16 @@ class AvgStor */ bool zero() const { return total == 0.0; } + /** + * Prepare stat data for dumping or serialization + */ + void + prepare(Info *info) + { + total += current * (curTick - last); + last = curTick; + } + /** * Reset stat value to default */ @@ -863,11 +845,6 @@ class ScalarBase : public DataWrap */ size_type size() const { return 1; } - /** - * Reset stat value to default - */ - void reset() { data()->reset(this->info()); } - Counter value() { return data()->value(); } Result result() { return data()->result(); } @@ -875,17 +852,22 @@ class ScalarBase : public DataWrap Result total() { return result(); } bool zero() { return result() == 0.0; } + + void reset() { data()->reset(this->info()); } + void prepare() { data()->prepare(this->info()); } }; class ProxyInfo : public ScalarInfoBase { public: - void visit(Visit &visitor) { visitor.visit(*this); } std::string str() const { return to_string(value()); } size_type size() const { return 1; } bool check() const { return true; } - void reset() {} + void prepare() { } + void reset() { } bool zero() const { return value() == 0; } + + void visit(Visit &visitor) { visitor.visit(*this); } }; template @@ -950,6 +932,7 @@ class ValueBase : public DataWrap std::string str() const { return proxy->str(); } bool zero() const { return proxy->zero(); } bool check() const { return proxy != NULL; } + void prepare() { } void reset() { } }; @@ -1230,8 +1213,6 @@ class VectorBase : public DataWrapVec assert (index >= 0 && index < size()); return Proxy(this->self(), index); } - - void update() {} }; template @@ -1348,16 +1329,6 @@ class Vector2dBase : public DataWrapVec2d delete [] reinterpret_cast(storage); } - void - update() - { - Info *info = this->info(); - size_type size = this->size(); - info->cvec.resize(size); - for (off_type i = 0; i < size; ++i) - info->cvec[i] = data(i)->value(); - } - Derived & init(size_type _x, size_type _y) { @@ -1413,6 +1384,20 @@ class Vector2dBase : public DataWrapVec2d #endif } + void + prepare() + { + Info *info = this->info(); + size_type size = this->size(); + + for (off_type i = 0; i < size; ++i) + data(i)->prepare(info); + + info->cvec.resize(size); + for (off_type i = 0; i < size; ++i) + info->cvec[i] = data(i)->value(); + } + /** * Reset stat value to default */ @@ -1541,7 +1526,7 @@ class DistStor } void - update(Info *info, DistData &data) + prepare(Info *info, DistData &data) { const Params *params = safe_cast(info->storageParams); @@ -1630,14 +1615,6 @@ class FancyStor samples += number; } - void - update(Info *info, DistData &data) - { - data.sum = sum; - data.squares = squares; - data.samples = samples; - } - /** * Return the number of entries in this stat, 1 * @return 1. @@ -1650,6 +1627,14 @@ class FancyStor */ bool zero() const { return samples == Counter(); } + void + prepare(Info *info, DistData &data) + { + data.sum = sum; + data.squares = squares; + data.samples = samples; + } + /** * Reset stat value to default */ @@ -1702,14 +1687,6 @@ class AvgFancy squares += value * value; } - void - update(Info *info, DistData &data) - { - data.sum = sum; - data.squares = squares; - data.samples = curTick; - } - /** * Return the number of entries, in this case 1. * @return 1. @@ -1722,6 +1699,14 @@ class AvgFancy */ bool zero() const { return sum == Counter(); } + void + prepare(Info *info, DistData &data) + { + data.sum = sum; + data.squares = squares; + data.samples = curTick; + } + /** * Reset stat value to default */ @@ -1801,10 +1786,10 @@ class DistBase : public DataWrap bool zero() const { return data()->zero(); } void - update() + prepare() { Info *info = this->info(); - data()->update(info, info->data); + data()->prepare(info, info->data); } /** @@ -1900,23 +1885,20 @@ class VectorDistBase : public DataWrapVec #endif } - bool - check() const - { - return storage != NULL; - } - void - update() + prepare() { - Derived &self = this->self(); Info *info = this->info(); + size_type size = this->size(); + info->data.resize(size); + for (off_type i = 0; i < size; ++i) + data(i)->prepare(info, info->data[i]); + } - size_type size = self.size(); - info.data.resize(size); - for (off_type i = 0; i < size; ++i) { - data(i)->update(info, info.data[i]); - } + bool + check() const + { + return storage != NULL; } }; @@ -2589,14 +2571,6 @@ class FormulaInfo : public InfoWrap Result total() const { return this->s.total(); } VCounter &value() const { return cvec; } - void - visit(Visit &visitor) - { - this->update(); - this->s.update(); - visitor.visit(*this); - } - std::string str() const { return this->s.str(); } }; @@ -2677,11 +2651,6 @@ class Formula : public DataWrapVec */ bool zero() const; - /** - * - */ - void update(); - std::string str() const; }; @@ -2876,11 +2845,6 @@ class Temp * @} */ -void check(); -void dump(); -void reset(); -void registerResetCallback(Callback *cb); - inline Temp operator+(Temp l, Temp r) { @@ -2931,6 +2895,34 @@ sum(Temp val) return NodePtr(new SumNode >(val)); } +/** + * Enable the statistics package. Before the statistics package is + * enabled, all statistics must be created and initialized and once + * the package is enabled, no more statistics can be created. + */ +void enable(); + +/** + * Prepare all stats for data access. This must be done before + * dumping and serialization. + */ +void prepare(); + +/** + * Dump all statistics data to the registered outputs + */ +void dump(); + +/** + * Reset all statistics to the base state + */ +void reset(); +/** + * Register a callback that should be called whenever statistics are + * reset + */ +void registerResetCallback(Callback *cb); + std::list &statsList(); /* namespace Stats */ } diff --git a/src/base/stats/output.cc b/src/base/stats/output.cc index 9f2b91c77..31aa21c45 100644 --- a/src/base/stats/output.cc +++ b/src/base/stats/output.cc @@ -30,6 +30,7 @@ #include +#include "base/statistics.hh" #include "base/stats/output.hh" #include "sim/eventq.hh" #include "sim/host.hh" @@ -49,6 +50,8 @@ dump() return; lastDump = curTick; + prepare(); + list::iterator i = OutputList.begin(); list::iterator end = OutputList.end(); for (; i != end; ++i) { diff --git a/src/python/m5/core.py b/src/python/m5/core.py index 232fe2ceb..1d7985be6 100644 --- a/src/python/m5/core.py +++ b/src/python/m5/core.py @@ -27,7 +27,14 @@ # Authors: Nathan Binkert import internal +from internal.core import initAll, regAllStats def setOutputDir(dir): internal.core.setOutputDir(dir) +def initAll(): + internal.core.initAll() + +def regAllStats(): + internal.core.regAllStats() + diff --git a/src/python/m5/simulate.py b/src/python/m5/simulate.py index 617ac3be2..45992fe85 100644 --- a/src/python/m5/simulate.py +++ b/src/python/m5/simulate.py @@ -33,6 +33,8 @@ import sys # import the SWIG-wrapped main C++ functions import internal +import core +import stats from main import options import SimObject import ticks @@ -52,23 +54,23 @@ def instantiate(root): ini_file.close() # Initialize the global statistics - internal.stats.initSimStats() + stats.initSimStats() # Create the C++ sim objects and connect ports root.createCCObject() root.connectPorts() # Do a second pass to finish initializing the sim objects - internal.core.initAll() + core.initAll() # Do a third pass to initialize statistics - internal.core.regAllStats() + core.regAllStats() - # Check to make sure that the stats package is properly initialized - internal.stats.check() + # We're done registering statistics. Enable the stats package now. + stats.enable() # Reset to put the stats in a consistent state. - internal.stats.reset() + stats.reset() def doDot(root): dot = pydot.Dot() diff --git a/src/python/m5/stats.py b/src/python/m5/stats.py index 041a3f58d..5bd9d5f6a 100644 --- a/src/python/m5/stats.py +++ b/src/python/m5/stats.py @@ -28,9 +28,6 @@ import internal -from internal.stats import dump -from internal.stats import initSimStats -from internal.stats import reset from internal.stats import StatEvent as event def initText(filename, desc=True, compat=True): @@ -44,3 +41,19 @@ def initMySQL(host, database, user='', passwd='', project='test', name='test', internal.stats.initMySQL(host, database, user, passwd, project, name, sample) + +def initSimStats(): + internal.stats.initSimStats() + +def enable(): + internal.stats.enable() + +def dump(): + # Currently prepare happens in the dump, but we should maybe move + # that out. + + #internal.stats.prepare() + internal.stats.dump() + +def reset(): + internal.stats.reset() diff --git a/src/python/swig/stats.i b/src/python/swig/stats.i index d36f82dbc..284df8ff8 100644 --- a/src/python/swig/stats.i +++ b/src/python/swig/stats.i @@ -48,7 +48,8 @@ void initMySQL(std::string host, std::string database, std::string user, void StatEvent(bool dump, bool reset, Tick when = curTick, Tick repeat = 0); -void check(); +void enable(); +void prepare(); void dump(); void reset(); -- cgit v1.2.3 From 66a85b54e2f59e13b726f05a30bb115f2fb10dbc Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 7 Mar 2009 14:30:52 -0800 Subject: build: fix errors for compilers other than g++ 4.3 --- src/base/cp_annotate.hh | 2 +- src/base/statistics.hh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/base/cp_annotate.hh b/src/base/cp_annotate.hh index 9ec39b6cb..13ced82de 100644 --- a/src/base/cp_annotate.hh +++ b/src/base/cp_annotate.hh @@ -53,7 +53,7 @@ class ThreadContext; #if !CP_ANNOTATE -class CPA : SimObject +class CPA { public: enum flags { diff --git a/src/base/statistics.hh b/src/base/statistics.hh index 6240be7a2..827c1d311 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -2495,7 +2495,7 @@ class VectorDistribution : public VectorDistBase params->min = min; params->max = max; params->bucket_size = bkt; - params->buckets = rint((max - min) / bkt + 1.0); + params->buckets = (size_type)rint((max - min) / bkt + 1.0); this->setParams(params); this->doInit(size); return this->self(); -- cgit v1.2.3 From fcaf1b74b0b4b40891a71b3b8bccd3f173aeff56 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 7 Mar 2009 14:30:53 -0800 Subject: stats: cleanup text output stuff and fix mysql output --- src/base/statistics.hh | 39 ++++++----- src/base/stats/mysql.cc | 15 +++-- src/base/stats/mysql.hh | 3 +- src/base/stats/text.cc | 173 ++++++++++++++++++++---------------------------- 4 files changed, 106 insertions(+), 124 deletions(-) (limited to 'src') diff --git a/src/base/statistics.hh b/src/base/statistics.hh index 827c1d311..06c15a77d 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -1423,6 +1423,22 @@ class Vector2dBase : public DataWrapVec2d // ////////////////////////////////////////////////////////////////////// +struct DistParams : public StorageParams +{ + const bool fancy; + + /** The minimum value to track. */ + Counter min; + /** The maximum value to track. */ + Counter max; + /** The number of entries in each bucket. */ + Counter bucket_size; + /** The number of buckets. Equal to (max-min)/bucket_size. */ + size_type buckets; + + explicit DistParams(bool f) : fancy(f) {} +}; + /** * Templatized storage and interface for a distrbution stat. */ @@ -1430,18 +1446,9 @@ class DistStor { public: /** The parameters for a distribution stat. */ - struct Params : public StorageParams - { - /** The minimum value to track. */ - Counter min; - /** The maximum value to track. */ - Counter max; - /** The number of entries in each bucket. */ - Counter bucket_size; - /** The number of buckets. Equal to (max-min)/bucket_size. */ - size_type buckets; - - enum { fancy = false }; + struct Params : public DistParams + { + Params() : DistParams(false) {} }; private: @@ -1578,9 +1585,9 @@ class DistStor class FancyStor { public: - struct Params : public StorageParams + struct Params : public DistParams { - enum { fancy = true }; + Params() : DistParams(true) {} }; private: @@ -1654,9 +1661,9 @@ class FancyStor class AvgFancy { public: - struct Params : public StorageParams + struct Params : public DistParams { - enum { fancy = true }; + Params() : DistParams(true) {} }; private: diff --git a/src/base/stats/mysql.cc b/src/base/stats/mysql.cc index 58c620ed1..1e0c923f1 100644 --- a/src/base/stats/mysql.cc +++ b/src/base/stats/mysql.cc @@ -583,7 +583,8 @@ MySql::configure(const DistInfoBase &info) if (!configure(info, "DIST")) return; - const Params *params = safe_cast(info.storageParams); + const DistParams *params = + safe_cast(info.storageParams); if (!params->fancy) { stat.size = params->buckets; stat.min = params->min; @@ -599,7 +600,8 @@ MySql::configure(const VectorDistInfoBase &info) if (!configure(info, "VECTORDIST")) return; - const Params *params = safe_cast(info.storageParams); + const DistParams *params = + safe_cast(info.storageParams); if (!params->fancy) { stat.size = params->buckets; stat.min = params->min; @@ -765,7 +767,7 @@ MySql::output(const VectorInfoBase &info) } void -MySql::output(const DistData &data) +MySql::output(const DistData &data, const DistParams *params) { const int db_sum = -1; const int db_squares = -2; @@ -787,7 +789,7 @@ MySql::output(const DistData &data) newdata.data = data.samples; newdata.insert(); - if (data.samples && !data.fancy) { + if (data.samples && !params->fancy) { newdata.x = db_min_val; newdata.data = data.min_val; newdata.insert(); @@ -821,7 +823,7 @@ MySql::output(const DistInfoBase &info) newdata.stat = find(info.id); newdata.y = 0; - output(info.data); + output(info.data, safe_cast(info.storageParams)); } void @@ -835,7 +837,8 @@ MySql::output(const VectorDistInfoBase &info) size_type size = info.data.size(); for (off_type y = 0; y < size; ++y) { newdata.y = y; - output(info.data[y]); + output(info.data[y], + safe_cast(info.storageParams)); } } diff --git a/src/base/stats/mysql.hh b/src/base/stats/mysql.hh index f0f79bebd..86a4d6d23 100644 --- a/src/base/stats/mysql.hh +++ b/src/base/stats/mysql.hh @@ -56,6 +56,7 @@ struct SetupStat bool total; bool pdf; bool cdf; + double min; double max; double bktsize; @@ -177,7 +178,7 @@ class MySql : public Output void output(const VectorDistInfoBase &info); void output(const Vector2dInfoBase &info); void output(const FormulaInfoBase &info); - void output(const DistData &data); + void output(const DistData &data, const DistParams *params); void configure(); bool configure(const Info &info, std::string type); diff --git a/src/base/stats/text.cc b/src/base/stats/text.cc index 6c2078bd0..c3e484cf4 100644 --- a/src/base/stats/text.cc +++ b/src/base/stats/text.cc @@ -351,27 +351,63 @@ struct DistPrint bool descriptions; int precision; - Result min_val; - Result max_val; - Result underflow; - Result overflow; - VResult vec; - Result sum; - Result squares; - Result samples; - Counter min; Counter max; Counter bucket_size; size_type size; bool fancy; + const DistData &data; + + DistPrint(const DistInfoBase &info); + DistPrint(const VectorDistInfoBase &info, int i); + void init(const Info &info, const DistParams *params); void operator()(ostream &stream) const; }; +DistPrint::DistPrint(const DistInfoBase &info) + : data(info.data) +{ + init(info, safe_cast(info.storageParams)); +} + +DistPrint::DistPrint(const VectorDistInfoBase &info, int i) + : data(info.data[i]) +{ + init(info, safe_cast(info.storageParams)); + + name = info.name + "_" + + (info.subnames[i].empty() ? (to_string(i)) : info.subnames[i]); + + if (!info.subdescs[i].empty()) + desc = info.subdescs[i]; +} + +void +DistPrint::init(const Info &info, const DistParams *params) +{ + name = info.name; + desc = info.desc; + flags = info.flags; + compat = compat; + descriptions = descriptions; + precision = info.precision; + + fancy = params->fancy; + min = params->min; + max = params->max; + bucket_size = params->bucket_size; + size = params->buckets; +} + void DistPrint::operator()(ostream &stream) const { + Result stdev = NAN; + if (data.samples) + stdev = sqrt((data.samples * data.squares - data.sum * data.sum) / + (data.samples * (data.samples - 1.0))); + if (fancy) { ScalarPrint print; string base = name + (compat ? "_" : "::"); @@ -385,28 +421,27 @@ DistPrint::operator()(ostream &stream) const print.cdf = NAN; print.name = base + "mean"; - print.value = samples ? sum / samples : NAN; + print.value = data.samples ? data.sum / data.samples : NAN; print(stream); print.name = base + "stdev"; - print.value = samples ? sqrt((samples * squares - sum * sum) / - (samples * (samples - 1.0))) : NAN; + print.value = stdev; print(stream); print.name = "**Ignore: " + base + "TOT"; - print.value = samples; + print.value = data.samples; print(stream); return; } - assert(size == vec.size()); + assert(size == data.cvec.size()); Result total = 0.0; - total += underflow; + total += data.underflow; for (off_type i = 0; i < size; ++i) - total += vec[i]; - total += overflow; + total += data.cvec[i]; + total += data.overflow; string base = name + (compat ? "." : "::"); @@ -427,18 +462,18 @@ DistPrint::operator()(ostream &stream) const } print.name = base + "samples"; - print.value = samples; + print.value = data.samples; print(stream); print.name = base + "min_value"; - print.value = min_val; + print.value = data.min_val; print(stream); - if (!compat || underflow > 0.0) { + if (!compat || data.underflow > 0.0) { print.name = base + "underflows"; - print.value = underflow; + print.value = data.underflow; if (!compat && total) { - print.pdf = underflow / total; + print.pdf = data.underflow / total; print.cdf += print.pdf; } print(stream); @@ -456,9 +491,9 @@ DistPrint::operator()(ostream &stream) const namestr << "-" << high; print.name = namestr.str(); - print.value = vec[i]; + print.value = data.cvec[i]; if (total) { - print.pdf = vec[i] / total; + print.pdf = data.cvec[i] / total; print.cdf += print.pdf; } print(stream); @@ -471,17 +506,17 @@ DistPrint::operator()(ostream &stream) const print.flags = flags | __substat; for (off_type i = 0; i < size; ++i) { - if ((flags & nozero && vec[i] == 0.0) || - (flags & nonan && isnan(vec[i]))) + if ((flags & nozero && data.cvec[i] == 0.0) || + (flags & nonan && isnan(data.cvec[i]))) continue; _min = i * bucket_size + min; - _pdf = vec[i] / total * 100.0; + _pdf = data.cvec[i] / total * 100.0; _cdf += _pdf; print.name = ValueToString(_min, 0, compat); - print.value = vec[i]; + print.value = data.cvec[i]; print.pdf = (flags & pdf) ? _pdf : NAN; print.cdf = (flags & cdf) ? _cdf : NAN; print(stream); @@ -490,11 +525,11 @@ DistPrint::operator()(ostream &stream) const print.flags = flags; } - if (!compat || overflow > 0.0) { + if (!compat || data.overflow > 0.0) { print.name = base + "overflows"; - print.value = overflow; + print.value = data.overflow; if (!compat && total) { - print.pdf = overflow / total; + print.pdf = data.overflow / total; print.cdf += print.pdf; } else { print.pdf = NAN; @@ -513,17 +548,16 @@ DistPrint::operator()(ostream &stream) const } print.name = base + "max_value"; - print.value = max_val; + print.value = data.max_val; print(stream); - if (!compat && samples != 0) { + if (!compat && data.samples != 0) { print.name = base + "mean"; - print.value = sum / samples; + print.value = data.sum / data.samples; print(stream); print.name = base + "stdev"; - print.value = sqrt((samples * squares - sum * sum) / - (samples * (samples - 1.0))); + print.value = stdev; print(stream); } @@ -651,39 +685,7 @@ Text::visit(const DistInfoBase &info) if (noOutput(info)) return; - DistPrint print; - - print.name = info.name; - print.desc = info.desc; - print.flags = info.flags; - print.compat = compat; - print.descriptions = descriptions; - print.precision = info.precision; - - const DistData &data = info.data; - - print.min_val = data.min_val; - print.max_val = data.max_val; - print.underflow = data.underflow; - print.overflow = data.overflow; - print.vec.resize(data.cvec.size()); - for (off_type i = 0; i < print.vec.size(); ++i) - print.vec[i] = (Result)data.cvec[i]; - print.sum = data.sum; - print.squares = data.squares; - print.samples = data.samples; - - const DistStor::Params *params = - safe_cast(info.storageParams); - - print.fancy = params->fancy; - if (!params->fancy) { - print.min = params->min; - print.max = params->max; - print.bucket_size = params->bucket_size; - print.size = params->buckets; - } - + DistPrint print(info); print(*stream); } @@ -694,38 +696,7 @@ Text::visit(const VectorDistInfoBase &info) return; for (off_type i = 0; i < info.size(); ++i) { - DistPrint print; - - print.name = info.name + "_" + - (info.subnames[i].empty() ? (to_string(i)) : info.subnames[i]); - print.desc = info.subdescs[i].empty() ? info.desc : info.subdescs[i]; - print.flags = info.flags; - print.compat = compat; - print.descriptions = descriptions; - print.precision = info.precision; - - print.min_val = info.data[i].min_val; - print.max_val = info.data[i].max_val; - print.underflow = info.data[i].underflow; - print.overflow = info.data[i].overflow; - print.vec.resize(info.data[i].cvec.size()); - for (off_type j = 0; j < print.vec.size(); ++j) - print.vec[j] = (Result)info.data[i].cvec[j]; - print.sum = info.data[i].sum; - print.squares = info.data[i].squares; - print.samples = info.data[i].samples; - - const DistStor::Params *params = - safe_cast(info.storageParams); - - print.fancy = params->fancy; - if (!params->fancy) { - print.min = params->min; - print.max = params->max; - print.bucket_size = params->bucket_size; - print.size = params->buckets; - } - + DistPrint print(info, i); print(*stream); } } -- cgit v1.2.3 From ac7bda0212a22d86d9e24665998f294b96869680 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 7 Mar 2009 14:30:54 -0800 Subject: stats: fix duplicate statistics names. This generally requires providing a more meaningful name() function for a class. --- src/cpu/o3/bpred_unit.hh | 4 ++++ src/cpu/o3/bpred_unit_impl.hh | 23 ++++++++++++----------- src/cpu/o3/mem_dep_unit.hh | 8 ++++++-- src/cpu/o3/mem_dep_unit_impl.hh | 19 +++++++------------ 4 files changed, 29 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/cpu/o3/bpred_unit.hh b/src/cpu/o3/bpred_unit.hh index 44f9bea79..b32d2bd23 100644 --- a/src/cpu/o3/bpred_unit.hh +++ b/src/cpu/o3/bpred_unit.hh @@ -62,6 +62,8 @@ class BPredUnit PredType predictor; + const std::string _name; + public: /** @@ -69,6 +71,8 @@ class BPredUnit */ BPredUnit(DerivO3CPUParams *params); + const std::string &name() const { return _name; } + /** * Registers statistics. */ diff --git a/src/cpu/o3/bpred_unit_impl.hh b/src/cpu/o3/bpred_unit_impl.hh index ded72a1b5..2fa59280d 100644 --- a/src/cpu/o3/bpred_unit_impl.hh +++ b/src/cpu/o3/bpred_unit_impl.hh @@ -38,9 +38,10 @@ template BPredUnit::BPredUnit(DerivO3CPUParams *params) - : BTB(params->BTBEntries, - params->BTBTagSize, - params->instShiftAmt) + : _name(params->name + ".BPredUnit"), + BTB(params->BTBEntries, + params->BTBTagSize, + params->instShiftAmt) { // Setup the selected predictor. if (params->predType == "local") { @@ -73,43 +74,43 @@ void BPredUnit::regStats() { lookups - .name(name() + ".BPredUnit.lookups") + .name(name() + ".lookups") .desc("Number of BP lookups") ; condPredicted - .name(name() + ".BPredUnit.condPredicted") + .name(name() + ".condPredicted") .desc("Number of conditional branches predicted") ; condIncorrect - .name(name() + ".BPredUnit.condIncorrect") + .name(name() + ".condIncorrect") .desc("Number of conditional branches incorrect") ; BTBLookups - .name(name() + ".BPredUnit.BTBLookups") + .name(name() + ".BTBLookups") .desc("Number of BTB lookups") ; BTBHits - .name(name() + ".BPredUnit.BTBHits") + .name(name() + ".BTBHits") .desc("Number of BTB hits") ; BTBCorrect - .name(name() + ".BPredUnit.BTBCorrect") + .name(name() + ".BTBCorrect") .desc("Number of correct BTB predictions (this stat may not " "work properly.") ; usedRAS - .name(name() + ".BPredUnit.usedRAS") + .name(name() + ".usedRAS") .desc("Number of times the RAS was used to get a target.") ; RASIncorrect - .name(name() + ".BPredUnit.RASInCorrect") + .name(name() + ".RASInCorrect") .desc("Number of incorrect RAS predictions.") ; } diff --git a/src/cpu/o3/mem_dep_unit.hh b/src/cpu/o3/mem_dep_unit.hh index fa1c33320..4f9e7c9f7 100644 --- a/src/cpu/o3/mem_dep_unit.hh +++ b/src/cpu/o3/mem_dep_unit.hh @@ -65,7 +65,11 @@ class InstructionQueue; * dependence prediction schemes. */ template -class MemDepUnit { +class MemDepUnit +{ + protected: + std::string _name; + public: typedef typename Impl::DynInstPtr DynInstPtr; @@ -79,7 +83,7 @@ class MemDepUnit { ~MemDepUnit(); /** Returns the name of the memory dependence unit. */ - std::string name() const; + std::string name() const { return _name; } /** Initializes the unit with parameters and a thread id. */ void init(DerivO3CPUParams *params, int tid); diff --git a/src/cpu/o3/mem_dep_unit_impl.hh b/src/cpu/o3/mem_dep_unit_impl.hh index 124c087f8..8754539f9 100644 --- a/src/cpu/o3/mem_dep_unit_impl.hh +++ b/src/cpu/o3/mem_dep_unit_impl.hh @@ -44,7 +44,8 @@ MemDepUnit::MemDepUnit() template MemDepUnit::MemDepUnit(DerivO3CPUParams *params) - : depPred(params->SSITSize, params->LFSTSize), loadBarrier(false), + : _name(params->name + ".memdepunit"), + depPred(params->SSITSize, params->LFSTSize), loadBarrier(false), loadBarrierSN(0), storeBarrier(false), storeBarrierSN(0), iqPtr(NULL) { DPRINTF(MemDepUnit, "Creating MemDepUnit object.\n"); @@ -75,19 +76,13 @@ MemDepUnit::~MemDepUnit() #endif } -template -std::string -MemDepUnit::name() const -{ - return "memdepunit"; -} - template void MemDepUnit::init(DerivO3CPUParams *params, int tid) { DPRINTF(MemDepUnit, "Creating MemDepUnit %i object.\n",tid); + _name = csprintf("%s.memDep%d", params->name, tid); id = tid; depPred.init(params->SSITSize, params->LFSTSize); @@ -98,19 +93,19 @@ void MemDepUnit::regStats() { insertedLoads - .name(name() + ".memDep.insertedLoads") + .name(name() + ".insertedLoads") .desc("Number of loads inserted to the mem dependence unit."); insertedStores - .name(name() + ".memDep.insertedStores") + .name(name() + ".insertedStores") .desc("Number of stores inserted to the mem dependence unit."); conflictingLoads - .name(name() + ".memDep.conflictingLoads") + .name(name() + ".conflictingLoads") .desc("Number of conflicting loads."); conflictingStores - .name(name() + ".memDep.conflictingStores") + .name(name() + ".conflictingStores") .desc("Number of conflicting stores."); } -- cgit v1.2.3 From 4f1855484c1fe148d66b2dbc2dc0d7964b578c5c Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Sat, 7 Mar 2009 16:58:51 -0800 Subject: Fix up regression execution to better handle tests that end abnormally. E.g., mark aborts due to assertion failures as failed tests, but those that get killed by the user as needing to be rerun, etc. --- src/python/m5/config.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/python/m5/config.py b/src/python/m5/config.py index 7fb531a18..c28f6675a 100644 --- a/src/python/m5/config.py +++ b/src/python/m5/config.py @@ -29,10 +29,18 @@ import os from os.path import isdir, isfile, join as joinpath -homedir = os.environ['HOME'] -confdir = os.environ.get('M5_CONFIG', joinpath(homedir, '.m5')) + +confdir = os.environ.get('M5_CONFIG') + +if not confdir: + # HOME is not set when running regressions, due to use of scons + # Execute() function. + homedir = os.environ.get('HOME') + if homedir and isdir(joinpath(homedir, '.m5')): + confdir = joinpath(homedir, '.m5') + def get(name): - if not isdir(confdir): + if not confdir: return None conffile = joinpath(confdir, name) if not isfile(conffile): -- cgit v1.2.3 From ac64586a99cad5aa8daf4346e1f6021764dbca1b Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Sat, 7 Mar 2009 21:34:50 -0800 Subject: build: fix compiler warnings in g++ 3.4 --- src/arch/x86/faults.hh | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/arch/x86/faults.hh b/src/arch/x86/faults.hh index cb1a3f18a..fe5132994 100644 --- a/src/arch/x86/faults.hh +++ b/src/arch/x86/faults.hh @@ -76,9 +76,9 @@ namespace X86ISA uint64_t errorCode; X86FaultBase(const char * _faultName, const char * _mnem, - const uint8_t _vector, uint64_t _errorCode = -1) : - faultName(_faultName), mnem(_mnem), - vector(_vector), errorCode(_errorCode) + const uint8_t _vector, uint64_t _errorCode = (uint64_t)-1) + : faultName(_faultName), mnem(_mnem), + vector(_vector), errorCode(_errorCode) { } @@ -115,8 +115,8 @@ namespace X86ISA { protected: X86Fault(const char * name, const char * mnem, - const uint8_t vector, uint64_t _errorCode = -1) : - X86FaultBase(name, mnem, vector, _errorCode) + const uint8_t vector, uint64_t _errorCode = (uint64_t)-1) + : X86FaultBase(name, mnem, vector, _errorCode) {} }; @@ -126,8 +126,8 @@ namespace X86ISA { protected: X86Trap(const char * name, const char * mnem, - const uint8_t vector, uint64_t _errorCode = -1) : - X86FaultBase(name, mnem, vector, _errorCode) + const uint8_t vector, uint64_t _errorCode = (uint64_t)-1) + : X86FaultBase(name, mnem, vector, _errorCode) {} #if FULL_SYSTEM @@ -140,8 +140,8 @@ namespace X86ISA { protected: X86Abort(const char * name, const char * mnem, - const uint8_t vector, uint64_t _errorCode = -1) : - X86FaultBase(name, mnem, vector, _errorCode) + const uint8_t vector, uint64_t _errorCode = (uint64_t)-1) + : X86FaultBase(name, mnem, vector, _errorCode) {} #if FULL_SYSTEM @@ -154,8 +154,8 @@ namespace X86ISA { protected: X86Interrupt(const char * name, const char * mnem, - const uint8_t _vector, uint64_t _errorCode = -1) : - X86FaultBase(name, mnem, _vector, _errorCode) + const uint8_t _vector, uint64_t _errorCode = (uint64_t)-1) + : X86FaultBase(name, mnem, _vector, _errorCode) {} }; -- cgit v1.2.3 From a94c68228a29562c382a4587ce9cf18101f9babc Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Tue, 10 Mar 2009 17:37:15 -0700 Subject: prefetch: don't panic on requests w/o contextID (e.g., writebacks). --- src/mem/cache/prefetch/ghb.cc | 7 ++++++- src/mem/cache/prefetch/stride.cc | 5 +++++ src/mem/request.hh | 8 +++++++- 3 files changed, 18 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/mem/cache/prefetch/ghb.cc b/src/mem/cache/prefetch/ghb.cc index c27165248..f8f7de1db 100644 --- a/src/mem/cache/prefetch/ghb.cc +++ b/src/mem/cache/prefetch/ghb.cc @@ -34,13 +34,18 @@ * GHB Prefetcher implementation. */ +#include "base/trace.hh" #include "mem/cache/prefetch/ghb.hh" -#include "arch/isa_traits.hh" void GHBPrefetcher::calculatePrefetch(PacketPtr &pkt, std::list &addresses, std::list &delays) { + if (useContextId && !pkt->req->hasContextId()) { + DPRINTF(HWPrefetch, "ignoring request with no context ID"); + return; + } + Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1); int ctx_id = useContextId ? pkt->req->contextId() : 0; assert(ctx_id < Max_Contexts); diff --git a/src/mem/cache/prefetch/stride.cc b/src/mem/cache/prefetch/stride.cc index cfd2469fa..8af4e615e 100644 --- a/src/mem/cache/prefetch/stride.cc +++ b/src/mem/cache/prefetch/stride.cc @@ -46,6 +46,11 @@ StridePrefetcher::calculatePrefetch(PacketPtr &pkt, std::list &addresses, return; } + if (useContextId && !pkt->req->hasContextId()) { + DPRINTF(HWPrefetch, "ignoring request with no context ID"); + return; + } + Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1); int ctx_id = useContextId ? pkt->req->contextId() : 0; Addr pc = pkt->req->getPC(); diff --git a/src/mem/request.hh b/src/mem/request.hh index dde68ca37..ee62ce771 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -409,6 +409,12 @@ class Request : public FastAlloc flags.set(VALID_EXTRA_DATA); } + bool + hasContextId() const + { + return flags.isSet(VALID_CONTEXT_ID); + } + /** Accessor function for context ID.*/ int contextId() const @@ -425,13 +431,13 @@ class Request : public FastAlloc return _threadId; } - /** Accessor function for pc.*/ bool hasPC() const { return flags.isSet(VALID_PC); } + /** Accessor function for pc.*/ Addr getPC() const { -- cgit v1.2.3 From 61ff48a1f834b7335c2ae615a1f855995cfab335 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Wed, 11 Mar 2009 23:05:24 -0700 Subject: cpu: fix minor endian issue with trace output (no functional change) --- src/cpu/simple/atomic.cc | 2 +- src/cpu/simple/timing.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index acda552d9..17f93c882 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -513,7 +513,7 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) // calling changeStatus() and changing it to "bad addr write" // or something. if (traceData) { - traceData->setData(data); + traceData->setData(gtoh(data)); } return fault; } diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index f398365d3..a8f86f8d2 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -564,7 +564,7 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) assert(split_addr <= addr || split_addr - addr < block_size); T *dataP = new T; - *dataP = TheISA::gtoh(data); + *dataP = TheISA::htog(data); _status = DTBWaitResponse; if (split_addr > addr) { RequestPtr req1, req2; -- cgit v1.2.3 From 758bfe4eb57e5b7aada4c974830532ec067a5bda Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Wed, 11 Mar 2009 23:05:26 -0700 Subject: cache: set dirty bit on swaps (oops!) --- src/mem/cache/cache_impl.hh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 618e00569..a78fd3637 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -149,8 +149,10 @@ Cache::cmpAndSwap(BlkType *blk, PacketPtr pkt) panic("Invalid size for conditional read/write\n"); } - if (overwrite_mem) + if (overwrite_mem) { std::memcpy(blk_data, &overwrite_val, pkt->getSize()); + blk->status |= BlkDirty; + } } -- cgit v1.2.3 From 4eea8acaf2c3a7b2103f827d81c15379efde4a7c Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 16 Mar 2009 15:16:58 -0700 Subject: stats: fix compiler error --- src/base/statistics.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/base/statistics.hh b/src/base/statistics.hh index 06c15a77d..88704207d 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -961,13 +961,13 @@ class ScalarProxy * Return the current value of this stat as its base type. * @return The current value. */ - Counter value() const { return stat->data(index)->value(); } + Counter value() const { return stat.data(index)->value(); } /** * Return the current value of this statas a result type. * @return The current value. */ - Result result() const { return stat->data(index)->result(); } + Result result() const { return stat.data(index)->result(); } public: /** -- cgit v1.2.3 From 639cb0a42d953ee32bc7e96b0cdfa96cd40e9fc1 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Wed, 25 Mar 2009 20:06:54 -0400 Subject: CPA: Fix a typo that managed to sneak in. --- src/dev/i8254xGBe.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/dev/i8254xGBe.hh b/src/dev/i8254xGBe.hh index 0422abc33..308cfabde 100644 --- a/src/dev/i8254xGBe.hh +++ b/src/dev/i8254xGBe.hh @@ -195,7 +195,7 @@ class IGbE : public EtherDevice } void anRq(std::string sm, std::string q, int num = 1) { - cpa->hwPq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr, NULL, num); + cpa->hwRq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr, NULL, num); } void anWe(std::string sm, std::string q) { -- cgit v1.2.3