From ccaf80cc46fb86639ab5ee166baca08277f5450f Mon Sep 17 00:00:00 2001 From: Kevin Lim Date: Thu, 2 Nov 2006 13:11:38 -0500 Subject: [PATCH 1/6] Use ISA specific makeExtMI. src/arch/alpha/utility.hh: For now makeExtMI will be specific to the ISA. --HG-- extra : convert_revision : 89959c6499efcc3df9301ad8ea039580764a1496 --- src/arch/alpha/utility.hh | 6 +++--- src/cpu/checker/cpu_impl.hh | 5 +++++ src/cpu/o3/fetch_impl.hh | 6 +++++- src/cpu/ozone/front_end_impl.hh | 4 ++++ src/cpu/simple/base.cc | 4 ++++ 5 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh index 0304d1c3a..cb86c7e9e 100644 --- a/src/arch/alpha/utility.hh +++ b/src/arch/alpha/utility.hh @@ -43,11 +43,11 @@ namespace AlphaISA { static inline ExtMachInst - makeExtMI(MachInst inst, ThreadContext * xc) { + makeExtMI(MachInst inst, Addr pc) { #if FULL_SYSTEM ExtMachInst ext_inst = inst; - if (xc->readPC() && 0x1) - return ext_inst|=(static_cast(xc->readPC() & 0x1) << 32); + if (pc && 0x1) + return ext_inst|=(static_cast(pc & 0x1) << 32); else return ext_inst; #else diff --git a/src/cpu/checker/cpu_impl.hh b/src/cpu/checker/cpu_impl.hh index 36c7349e6..56e13dd1e 100644 --- a/src/cpu/checker/cpu_impl.hh +++ b/src/cpu/checker/cpu_impl.hh @@ -199,8 +199,13 @@ Checker::verify(DynInstPtr &completed_inst) // Checks both the machine instruction and the PC. validateInst(inst); +#if THE_ISA == ALPHA_ISA + curStaticInst = StaticInst::decode(makeExtMI(machInst, + thread->readPC())); +#elif THE_ISA == SPARC_ISA curStaticInst = StaticInst::decode(makeExtMI(machInst, thread->getTC())); +#endif #if FULL_SYSTEM thread->setInst(machInst); diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 2b152e376..31f3b96d6 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -1117,7 +1117,11 @@ DefaultFetch::fetch(bool &status_change) inst = TheISA::gtoh(*reinterpret_cast (&cacheData[tid][offset])); - ext_inst = TheISA::makeExtMI(inst, cpu->tcBase(tid)); +#if THE_ISA == ALPHA_ISA + ext_inst = TheISA::makeExtMI(inst, fetch_PC); +#elif THE_ISA == SPARC_ISA + ext_inst = TheISA::makeExtMI(inst, cpu->thread[tid]->getTC()); +#endif // Create a new DynInst from the instruction fetched. DynInstPtr instruction = new DynInst(ext_inst, fetch_PC, diff --git a/src/cpu/ozone/front_end_impl.hh b/src/cpu/ozone/front_end_impl.hh index 63cf0a952..6d02c58cb 100644 --- a/src/cpu/ozone/front_end_impl.hh +++ b/src/cpu/ozone/front_end_impl.hh @@ -882,7 +882,11 @@ FrontEnd::getInstFromCacheline() // Get the instruction from the array of the cache line. inst = htog(*reinterpret_cast(&cacheData[offset])); +#if THE_ISA == ALPHA_ISA + ExtMachInst decode_inst = TheISA::makeExtMI(inst, PC); +#elif THE_ISA == SPARC_ISA ExtMachInst decode_inst = TheISA::makeExtMI(inst, tc); +#endif // Create a new DynInst from the instruction fetched. DynInstPtr instruction = new DynInst(decode_inst, PC, PC+sizeof(MachInst), diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index 47b3b938f..6a2c0bbe9 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -398,7 +398,11 @@ BaseSimpleCPU::preExecute() inst = gtoh(inst); //If we're not in the middle of a macro instruction if (!curMacroStaticInst) { +#if THE_ISA == ALPHA_ISA + StaticInstPtr instPtr = StaticInst::decode(makeExtMI(inst, thread->readPC())); +#elif THE_ISA == SPARC_ISA StaticInstPtr instPtr = StaticInst::decode(makeExtMI(inst, thread->getTC())); +#endif if (instPtr->isMacroOp()) { curMacroStaticInst = instPtr; curStaticInst = curMacroStaticInst-> From 64f8cd12c6a613205196bbe9dbc0fab98c4ca735 Mon Sep 17 00:00:00 2001 From: Kevin Lim Date: Thu, 2 Nov 2006 13:12:36 -0500 Subject: [PATCH 2/6] Remove function that should have been deleted. src/cpu/simple_thread.cc: This function should have been deleted from an earlier push. src/cpu/simple_thread.hh: Delete this function; it's now in thread_state.hh/.cc. --HG-- extra : convert_revision : f78dcf9c2b388418030d48d0ea4911c8b8b1f5ff --- src/cpu/simple_thread.cc | 20 -------------------- src/cpu/simple_thread.hh | 2 -- 2 files changed, 22 deletions(-) diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index c89a13eef..28d8bdf62 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -323,25 +323,5 @@ SimpleThread::delVirtPort(VirtualPort *vp) } } -#else -TranslatingPort * -SimpleThread::getMemPort() -{ - if (port != NULL) - return port; - - /* Use this port to for syscall emulation writes to memory. */ - Port *dcache_port; - port = new TranslatingPort(csprintf("%s-%d-funcport", - cpu->name(), tid), - process->pTable, false); - dcache_port = cpu->getPort("dcache_port"); - assert(dcache_port != NULL); - dcache_port = dcache_port->getPeer(); -// mem_port->setPeer(port); - port->setPeer(dcache_port); - return port; -} - #endif diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index f002cbdce..20001063a 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -173,8 +173,6 @@ class SimpleThread : public ThreadState bool simPalCheck(int palFunc); #else - // Override this function. - TranslatingPort *getMemPort(); Fault translateInstReq(RequestPtr &req) { From dd5e2cd959e61b8af094137f337e999048317ec3 Mon Sep 17 00:00:00 2001 From: Kevin Lim Date: Thu, 2 Nov 2006 14:58:31 -0500 Subject: [PATCH 3/6] More proper handling of the ports. src/cpu/simple_thread.cc: Fix up port handling to share code. src/cpu/thread_state.cc: Separate code off into a function. src/cpu/thread_state.hh: Make a separate function that will get the CPU's memory's functional port. --HG-- extra : convert_revision : 96a9bb3c5e4b9ba5511678c0fd17f0017c8cd312 --- src/cpu/simple_thread.cc | 10 ++++++---- src/cpu/thread_state.cc | 31 +++++++++++++++++++++++++------ src/cpu/thread_state.hh | 9 +++++++++ 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index 28d8bdf62..f5fa68529 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -129,6 +129,10 @@ SimpleThread::SimpleThread() SimpleThread::~SimpleThread() { +#if FULL_SYSTEM + delete physPort; + delete virtPort; +#endif delete tc; } @@ -304,11 +308,9 @@ SimpleThread::getVirtPort(ThreadContext *src_tc) if (!src_tc) return virtPort; - VirtualPort *vp; - Port *mem_port; + VirtualPort *vp = new VirtualPort("tc-vport", src_tc); + Port *mem_port = getMemFuncPort(); - vp = new VirtualPort("tc-vport", src_tc); - mem_port = system->physmem->getPort("functional"); mem_port->setPeer(vp); vp->setPeer(mem_port); return vp; diff --git a/src/cpu/thread_state.cc b/src/cpu/thread_state.cc index f81b78147..a6fff5fc3 100644 --- a/src/cpu/thread_state.cc +++ b/src/cpu/thread_state.cc @@ -59,6 +59,16 @@ ThreadState::ThreadState(BaseCPU *cpu, int _cpuId, int _tid, Process *_process, numLoad = 0; } +ThreadState::~ThreadState() +{ +#if !FULL_SYSTEM + if (port) { + delete port->getPeer(); + delete port; + } +#endif +} + void ThreadState::serialize(std::ostream &os) { @@ -124,11 +134,24 @@ ThreadState::getMemPort() return port; /* Use this port to for syscall emulation writes to memory. */ - Port *dcache_port, *func_mem_port; port = new TranslatingPort(csprintf("%s-%d-funcport", baseCpu->name(), tid), process->pTable, false); + Port *func_port = getMemFuncPort(); + + func_port->setPeer(port); + port->setPeer(func_port); + + return port; +} +#endif + +Port * +ThreadState::getMemFuncPort() +{ + Port *dcache_port, *func_mem_port; + dcache_port = baseCpu->getPort("dcache_port"); assert(dcache_port != NULL); @@ -138,9 +161,5 @@ ThreadState::getMemPort() func_mem_port = mem_object->getPort("functional"); assert(func_mem_port != NULL); - func_mem_port->setPeer(port); - port->setPeer(func_mem_port); - - return port; + return func_mem_port; } -#endif diff --git a/src/cpu/thread_state.hh b/src/cpu/thread_state.hh index 14673aabb..862d671f2 100644 --- a/src/cpu/thread_state.hh +++ b/src/cpu/thread_state.hh @@ -51,6 +51,7 @@ namespace Kernel { class BaseCPU; class Checkpoint; +class Port; class TranslatingPort; /** @@ -69,6 +70,8 @@ struct ThreadState { short _asid); #endif + ~ThreadState(); + void serialize(std::ostream &os); void unserialize(Checkpoint *cp, const std::string §ion); @@ -136,6 +139,12 @@ struct ThreadState { /** Sets the status of this thread. */ void setStatus(Status new_status) { _status = new_status; } + protected: + /** Gets a functional port from the memory object that's connected + * to the CPU. */ + Port *getMemFuncPort(); + + public: /** Number of instructions committed. */ Counter numInst; /** Stat for number instructions committed. */ From 8d53f298a6efd3312cc1096b13b6be9e6a7fe02f Mon Sep 17 00:00:00 2001 From: Kevin Lim Date: Thu, 2 Nov 2006 15:17:45 -0500 Subject: [PATCH 4/6] Caches return a new functional port whenever asked for one. src/mem/cache/base_cache.cc: Have caches return a new functional port whenever asked for them. I'm pretty sure this is desired behavior. Ron can correct me if it's not. --HG-- extra : convert_revision : e1fadf895a7d714968128ff900d10e86fde53387 --- src/mem/cache/base_cache.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/mem/cache/base_cache.cc b/src/mem/cache/base_cache.cc index 47d40a490..1c519fb86 100644 --- a/src/mem/cache/base_cache.cc +++ b/src/mem/cache/base_cache.cc @@ -357,9 +357,7 @@ BaseCache::getPort(const std::string &if_name, int idx) } else if (if_name == "functional") { - if(cpuSidePort == NULL) - cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true); - return cpuSidePort; + return new CachePort(name() + "-cpu_side_port", this, true); } else if (if_name == "cpu_side") { From c3485a654888f641dca23128f8197ef747c706d2 Mon Sep 17 00:00:00 2001 From: Kevin Lim Date: Thu, 2 Nov 2006 15:18:35 -0500 Subject: [PATCH 5/6] Implement device that will return BadAddress. --HG-- extra : convert_revision : d833c20f691e01c84a0678f19f7d83f3ee50c0c1 --- src/dev/isa_fake.cc | 63 +++++++++++++++++++++++++++++++++++++++++++++ src/dev/isa_fake.hh | 17 ++++++++++++ 2 files changed, 80 insertions(+) diff --git a/src/dev/isa_fake.cc b/src/dev/isa_fake.cc index 23761cd10..ccc9a1f7c 100644 --- a/src/dev/isa_fake.cc +++ b/src/dev/isa_fake.cc @@ -88,6 +88,38 @@ IsaFake::write(PacketPtr pkt) return pioDelay; } +BadAddr::BadAddr(Params *p) + : BasicPioDevice(p) +{ +} + +void +BadAddr::init() +{ + // Only init this device if it's connected to anything. + if (pioPort) + PioDevice::init(); +} + +Tick +BadAddr::read(PacketPtr pkt) +{ + assert(pkt->result == Packet::Unknown); + DPRINTF(Tsunami, "read to bad address va=%#x size=%d\n", + pkt->getAddr(), pkt->getSize()); + pkt->result = Packet::BadAddress; + return pioDelay; +} + +Tick +BadAddr::write(PacketPtr pkt) +{ + DPRINTF(Tsunami, "write to bad address va=%#x size=%d \n", + pkt->getAddr(), pkt->getSize()); + pkt->result = Packet::BadAddress; + return pioDelay; +} + BEGIN_DECLARE_SIM_OBJECT_PARAMS(IsaFake) Param pio_addr; @@ -121,3 +153,34 @@ CREATE_SIM_OBJECT(IsaFake) } REGISTER_SIM_OBJECT("IsaFake", IsaFake) + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(BadAddr) + + Param pio_addr; + Param pio_latency; + SimObjectParam platform; + SimObjectParam system; + +END_DECLARE_SIM_OBJECT_PARAMS(BadAddr) + +BEGIN_INIT_SIM_OBJECT_PARAMS(BadAddr) + + INIT_PARAM(pio_addr, "Device Address"), + INIT_PARAM(pio_latency, "Programmed IO latency"), + INIT_PARAM(platform, "platform"), + INIT_PARAM(system, "system object") + +END_INIT_SIM_OBJECT_PARAMS(BadAddr) + +CREATE_SIM_OBJECT(BadAddr) +{ + BadAddr::Params *p = new BadAddr::Params; + p->name = getInstanceName(); + p->pio_addr = pio_addr; + p->pio_delay = pio_latency; + p->platform = platform; + p->system = system; + return new BadAddr(p); +} + +REGISTER_SIM_OBJECT("BadAddr", BadAddr) diff --git a/src/dev/isa_fake.hh b/src/dev/isa_fake.hh index 366061c25..6665f1a78 100644 --- a/src/dev/isa_fake.hh +++ b/src/dev/isa_fake.hh @@ -79,4 +79,21 @@ class IsaFake : public BasicPioDevice virtual Tick write(PacketPtr pkt); }; +/** + * BadAddr is a device that fills the packet's result field with "BadAddress". + * @todo: Consider consolidating with IsaFake and similar classes. + */ +class BadAddr : public BasicPioDevice +{ + public: + struct Params : public BasicPioDevice::Params + { + }; + + BadAddr(Params *p); + virtual void init(); + virtual Tick read(PacketPtr pkt); + virtual Tick write(PacketPtr pkt); +}; + #endif // __TSUNAMI_FAKE_HH__ From 45363ea658251df0c31a75d7bd5d0ac3a3809623 Mon Sep 17 00:00:00 2001 From: Kevin Lim Date: Thu, 2 Nov 2006 15:20:37 -0500 Subject: [PATCH 6/6] Have bus use the BadAddress device to handle bad addresses. The O3 CPU should be able to boot into Linux with caches on after this change. src/mem/bus.cc: src/mem/bus.hh: Bus now will be setup with a default responder, unless the user overrides it. This default responder should return BadAddress if no matching port is found. src/python/m5/objects/Bus.py: Bus now has a default responder for FS mode if the user doesn't override it. It returns BadAddress if no matching port is found. src/python/m5/objects/Tsunami.py: Add bad address device. Also record when the user has specified their own default responder. --HG-- extra : convert_revision : 59070477ae313ee711b2d59baa2369c9a91c5b85 --- src/mem/bus.cc | 37 ++++++++++++++++++++++---------- src/mem/bus.hh | 9 ++++++-- src/python/m5/objects/Bus.py | 10 ++++++++- src/python/m5/objects/Tsunami.py | 4 ++++ 4 files changed, 46 insertions(+), 14 deletions(-) diff --git a/src/mem/bus.cc b/src/mem/bus.cc index 86a148f87..7ae41e11e 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -42,13 +42,14 @@ Port * Bus::getPort(const std::string &if_name, int idx) { - if (if_name == "default") + if (if_name == "default") { if (defaultPort == NULL) { defaultPort = new BusPort(csprintf("%s-default",name()), this, - defaultId); + defaultId); return defaultPort; } else fatal("Default port already set\n"); + } // if_name ignored? forced to be empty? int id = interfaces.size(); @@ -269,7 +270,16 @@ Bus::findPort(Addr addr, int id) return defaultPort; } } - panic("Unable to find destination for addr: %#llx", addr); + + if (responderSet) { + panic("Unable to find destination for addr (user set default " + "responder): %#llx", addr); + } else { + DPRINTF(Bus, "Unable to find destination for addr: %#llx, will use " + "default port", addr); + + return defaultPort; + } } @@ -392,12 +402,15 @@ Bus::recvStatusChange(Port::Status status, int id) if (id == defaultId) { defaultRange.clear(); - defaultPort->getPeerAddressRanges(ranges, snoops); - assert(snoops.size() == 0); - for(iter = ranges.begin(); iter != ranges.end(); iter++) { - defaultRange.push_back(*iter); - DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for default range\n", - iter->start, iter->end); + // Only try to update these ranges if the user set a default responder. + if (responderSet) { + defaultPort->getPeerAddressRanges(ranges, snoops); + assert(snoops.size() == 0); + for(iter = ranges.begin(); iter != ranges.end(); iter++) { + defaultRange.push_back(*iter); + DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for default range\n", + iter->start, iter->end); + } } } else { @@ -503,18 +516,20 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bus) Param bus_id; Param clock; Param width; + Param responder_set; END_DECLARE_SIM_OBJECT_PARAMS(Bus) BEGIN_INIT_SIM_OBJECT_PARAMS(Bus) INIT_PARAM(bus_id, "a globally unique bus id"), INIT_PARAM(clock, "bus clock speed"), - INIT_PARAM(width, "width of the bus (bits)") + INIT_PARAM(width, "width of the bus (bits)"), + INIT_PARAM(responder_set, "Is a default responder set by the user") END_INIT_SIM_OBJECT_PARAMS(Bus) CREATE_SIM_OBJECT(Bus) { - return new Bus(getInstanceName(), bus_id, clock, width); + return new Bus(getInstanceName(), bus_id, clock, width, responder_set); } REGISTER_SIM_OBJECT("Bus", Bus) diff --git a/src/mem/bus.hh b/src/mem/bus.hh index 7ec7e6830..619720a79 100644 --- a/src/mem/bus.hh +++ b/src/mem/bus.hh @@ -240,6 +240,9 @@ class Bus : public MemObject /** Port that handles requests that don't match any of the interfaces.*/ BusPort *defaultPort; + /** Has the user specified their own default responder? */ + bool responderSet; + public: /** A function used to return the port associated with this bus object. */ @@ -247,9 +250,11 @@ class Bus : public MemObject virtual void init(); - Bus(const std::string &n, int bus_id, int _clock, int _width) + Bus(const std::string &n, int bus_id, int _clock, int _width, + bool responder_set) : MemObject(n), busId(bus_id), clock(_clock), width(_width), - tickNextIdle(0), busIdle(this), inRetry(false), defaultPort(NULL) + tickNextIdle(0), busIdle(this), inRetry(false), defaultPort(NULL), + responderSet(responder_set) { //Both the width and clock period must be positive if (width <= 0) diff --git a/src/python/m5/objects/Bus.py b/src/python/m5/objects/Bus.py index 6710111e5..e7019f3ac 100644 --- a/src/python/m5/objects/Bus.py +++ b/src/python/m5/objects/Bus.py @@ -1,10 +1,18 @@ +from m5 import build_env from m5.params import * +from m5.proxy import * from MemObject import MemObject +from Tsunami import BadAddr class Bus(MemObject): type = 'Bus' port = VectorPort("vector port for connecting devices") - default = Port("Default port for requests that aren't handeled by a device.") bus_id = Param.Int(0, "blah") clock = Param.Clock("1GHz", "bus clock speed") width = Param.Int(64, "bus width (bytes)") + responder_set = Param.Bool(False, "Did the user specify a default responder.") + if build_env['FULL_SYSTEM']: + default = Port(Self.responder.pio, "Default port for requests that aren't handled by a device.") + responder = BadAddr(pio_addr=0x0, pio_latency="1ps") + else: + default = Port("Default port for requests that aren't handled by a device.") diff --git a/src/python/m5/objects/Tsunami.py b/src/python/m5/objects/Tsunami.py index 0b53153a0..42bcab089 100644 --- a/src/python/m5/objects/Tsunami.py +++ b/src/python/m5/objects/Tsunami.py @@ -15,6 +15,9 @@ class IsaFake(BasicPioDevice): type = 'IsaFake' pio_size = Param.Addr(0x8, "Size of address range") +class BadAddr(BasicPioDevice): + type = 'BadAddr' + class TsunamiIO(BasicPioDevice): type = 'TsunamiIO' time = Param.UInt64(1136073600, @@ -70,6 +73,7 @@ class Tsunami(Platform): self.cchip.pio = bus.port self.pchip.pio = bus.port self.pciconfig.pio = bus.default + bus.responder_set = True self.fake_sm_chip.pio = bus.port self.fake_uart1.pio = bus.port self.fake_uart2.pio = bus.port