X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fcpu%2Fsimple%2Ftiming.cc;h=45da7c3ebd283fd657f066f162899a6d8cfa79ca;hb=ff90b8c1aa99711eeb55c5eba29519f77cbc041c;hp=33f673cbcf23823c859bf5304445553d2908a84e;hpb=3a9eb598c3e71b543ba9b8fda42b76c89a645634;p=gem5.git diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 33f673cbc..45da7c3eb 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -30,9 +30,11 @@ #include "arch/locked_mem.hh" #include "arch/utility.hh" +#include "base/bigint.hh" #include "cpu/exetrace.hh" #include "cpu/simple/timing.hh" -#include "mem/packet_impl.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" #include "sim/builder.hh" #include "sim/system.hh" @@ -65,14 +67,14 @@ TimingSimpleCPU::init() } Tick -TimingSimpleCPU::CpuPort::recvAtomic(Packet *pkt) +TimingSimpleCPU::CpuPort::recvAtomic(PacketPtr pkt) { panic("TimingSimpleCPU doesn't expect recvAtomic callback!"); return curTick; } void -TimingSimpleCPU::CpuPort::recvFunctional(Packet *pkt) +TimingSimpleCPU::CpuPort::recvFunctional(PacketPtr pkt) { //No internal storage to update, jusst return return; @@ -81,15 +83,20 @@ TimingSimpleCPU::CpuPort::recvFunctional(Packet *pkt) void TimingSimpleCPU::CpuPort::recvStatusChange(Status status) { - if (status == RangeChange) + if (status == RangeChange) { + if (!snoopRangeSent) { + snoopRangeSent = true; + sendStatusChange(Port::RangeChange); + } return; + } panic("TimingSimpleCPU doesn't expect recvStatusChange callback!"); } void -TimingSimpleCPU::CpuPort::TickEvent::schedule(Packet *_pkt, Tick t) +TimingSimpleCPU::CpuPort::TickEvent::schedule(PacketPtr _pkt, Tick t) { pkt = _pkt; Event::schedule(t); @@ -100,6 +107,10 @@ TimingSimpleCPU::TimingSimpleCPU(Params *p) cpu_id(p->cpu_id) { _status = Idle; + + icachePort.snoopRangeSent = false; + dcachePort.snoopRangeSent = false; + ifetch_pkt = dcache_pkt = NULL; drainEvent = NULL; fetchEvent = NULL; @@ -147,6 +158,8 @@ void TimingSimpleCPU::resume() { if (_status != SwitchedOut && _status != Idle) { + assert(system->getMemoryMode() == System::Timing); + // Delete the old event if it existed. if (fetchEvent) { if (fetchEvent->scheduled()) @@ -157,10 +170,9 @@ TimingSimpleCPU::resume() fetchEvent = new EventWrapper(this, false); - fetchEvent->schedule(curTick); + fetchEvent->schedule(nextCycle()); } - assert(system->getMemoryMode() == System::Timing); changeState(SimObject::Running); previousTick = curTick; } @@ -182,7 +194,7 @@ TimingSimpleCPU::switchOut() void TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU) { - BaseCPU::takeOverFrom(oldCPU); + BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort); // if any of this CPU's ThreadContexts are active, mark the CPU as // running and schedule its tick event. @@ -197,23 +209,6 @@ TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU) if (_status != Running) { _status = Idle; } - - Port *peer; - if (icachePort.getPeer() == NULL) { - peer = oldCPU->getPort("icache_port")->getPeer(); - icachePort.setPeer(peer); - } else { - peer = icachePort.getPeer(); - } - peer->setPeer(&icachePort); - - if (dcachePort.getPeer() == NULL) { - peer = oldCPU->getPort("dcache_port")->getPeer(); - dcachePort.setPeer(peer); - } else { - peer = dcachePort.getPeer(); - } - peer->setPeer(&dcachePort); } @@ -227,10 +222,11 @@ TimingSimpleCPU::activateContext(int thread_num, int delay) notIdleFraction++; _status = Running; + // kick things off by initiating the fetch of the next instruction fetchEvent = new EventWrapper(this, false); - fetchEvent->schedule(curTick + cycles(delay)); + fetchEvent->schedule(nextCycle(curTick + cycles(delay))); } @@ -267,8 +263,8 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) // Now do the access. if (fault == NoFault) { - Packet *pkt = - new Packet(req, Packet::ReadReq, Packet::Broadcast); + PacketPtr pkt = + new Packet(req, MemCmd::ReadReq, Packet::Broadcast); pkt->dataDynamic(new T); if (!dcachePort.sendTiming(pkt)) { @@ -279,17 +275,27 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) // memory system takes ownership of packet dcache_pkt = NULL; } - } - // This will need a new way to tell if it has a dcache attached. - if (req->isUncacheable()) - recordEvent("Uncached Read"); + // This will need a new way to tell if it has a dcache attached. + if (req->isUncacheable()) + recordEvent("Uncached Read"); + } else { + delete req; + } return fault; } #ifndef DOXYGEN_SHOULD_SKIP_THIS +template +Fault +TimingSimpleCPU::read(Addr addr, Twin64_t &data, unsigned flags); + +template +Fault +TimingSimpleCPU::read(Addr addr, Twin32_t &data, unsigned flags); + template Fault TimingSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags); @@ -339,13 +345,20 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) new Request(/* asid */ 0, addr, sizeof(T), flags, thread->readPC(), cpu_id, /* thread ID */ 0); + if (traceData) { + traceData->setAddr(req->getVaddr()); + } + // translate to physical address Fault fault = thread->translateDataWriteReq(req); // Now do the access. if (fault == NoFault) { assert(dcache_pkt == NULL); - dcache_pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast); + if (req->isSwap()) + dcache_pkt = new Packet(req, MemCmd::SwapReq, Packet::Broadcast); + else + dcache_pkt = new Packet(req, MemCmd::WriteReq, Packet::Broadcast); dcache_pkt->allocate(); dcache_pkt->set(data); @@ -354,6 +367,10 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) if (req->isLocked()) { do_access = TheISA::handleLockedWrite(thread, req); } + if (req->isCondSwap()) { + assert(res); + req->setExtraData(*res); + } if (do_access) { if (!dcachePort.sendTiming(dcache_pkt)) { @@ -364,11 +381,13 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) 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; } - // 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. @@ -377,6 +396,16 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) #ifndef DOXYGEN_SHOULD_SKIP_THIS +template +Fault +TimingSimpleCPU::write(Twin32_t data, Addr addr, + unsigned flags, uint64_t *res); + +template +Fault +TimingSimpleCPU::write(Twin64_t data, Addr addr, + unsigned flags, uint64_t *res); + template Fault TimingSimpleCPU::write(uint64_t data, Addr addr, @@ -425,13 +454,14 @@ TimingSimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) void TimingSimpleCPU::fetch() { - checkForInterrupts(); + if (!curStaticInst || !curStaticInst->isDelayedCommit()) + checkForInterrupts(); Request *ifetch_req = new Request(); ifetch_req->setThreadContext(cpu_id, /* thread ID */ 0); Fault fault = setupFetchRequest(ifetch_req); - ifetch_pkt = new Packet(ifetch_req, Packet::ReadReq, Packet::Broadcast); + ifetch_pkt = new Packet(ifetch_req, MemCmd::ReadReq, Packet::Broadcast); ifetch_pkt->dataStatic(&inst); if (fault == NoFault) { @@ -445,6 +475,8 @@ TimingSimpleCPU::fetch() ifetch_pkt = NULL; } } else { + delete ifetch_req; + delete ifetch_pkt; // fetch fault: advance directly to next instruction (fault handler) advanceInst(fault); } @@ -469,7 +501,7 @@ TimingSimpleCPU::advanceInst(Fault fault) void -TimingSimpleCPU::completeIfetch(Packet *pkt) +TimingSimpleCPU::completeIfetch(PacketPtr pkt) { // received a response from the icache: execute the received // instruction @@ -478,13 +510,13 @@ TimingSimpleCPU::completeIfetch(Packet *pkt) _status = Running; - delete pkt->req; - delete pkt; - numCycles += curTick - previousTick; previousTick = curTick; if (getState() == SimObject::Draining) { + delete pkt->req; + delete pkt; + completeDrain(); return; } @@ -516,6 +548,9 @@ TimingSimpleCPU::completeIfetch(Packet *pkt) postExecute(); advanceInst(fault); } + + delete pkt->req; + delete pkt; } void @@ -525,19 +560,24 @@ TimingSimpleCPU::IcachePort::ITickEvent::process() } bool -TimingSimpleCPU::IcachePort::recvTiming(Packet *pkt) +TimingSimpleCPU::IcachePort::recvTiming(PacketPtr pkt) { - // delay processing of returned data until next CPU clock edge - Tick time = pkt->req->getTime(); - while (time < curTick) - time += lat; + if (pkt->isResponse()) { + // delay processing of returned data until next CPU clock edge + Tick mem_time = pkt->req->getTime(); + Tick next_tick = cpu->nextCycle(mem_time); - if (time == curTick) - cpu->completeIfetch(pkt); - else - tickEvent.schedule(pkt, time); + if (next_tick == curTick) + cpu->completeIfetch(pkt); + else + tickEvent.schedule(pkt, next_tick); - return true; + return true; + } + else { + //Snooping a Coherence Request, do nothing + return true; + } } void @@ -547,7 +587,7 @@ TimingSimpleCPU::IcachePort::recvRetry() // waiting to transmit assert(cpu->ifetch_pkt != NULL); assert(cpu->_status == IcacheRetry); - Packet *tmp = cpu->ifetch_pkt; + PacketPtr tmp = cpu->ifetch_pkt; if (sendTiming(tmp)) { cpu->_status = IcacheWaitResponse; cpu->ifetch_pkt = NULL; @@ -555,7 +595,7 @@ TimingSimpleCPU::IcachePort::recvRetry() } void -TimingSimpleCPU::completeDataAccess(Packet *pkt) +TimingSimpleCPU::completeDataAccess(PacketPtr pkt) { // received a response from the dcache: complete the load or store // instruction @@ -596,20 +636,37 @@ TimingSimpleCPU::completeDrain() drainEvent->process(); } +void +TimingSimpleCPU::DcachePort::setPeer(Port *port) +{ + Port::setPeer(port); + +#if FULL_SYSTEM + // Update the ThreadContext's memory ports (Functional/Virtual + // Ports) + cpu->tcBase()->connectMemPorts(); +#endif +} + bool -TimingSimpleCPU::DcachePort::recvTiming(Packet *pkt) +TimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt) { - // delay processing of returned data until next CPU clock edge - Tick time = pkt->req->getTime(); - while (time < curTick) - time += lat; + if (pkt->isResponse()) { + // delay processing of returned data until next CPU clock edge + Tick mem_time = pkt->req->getTime(); + Tick next_tick = cpu->nextCycle(mem_time); - if (time == curTick) - cpu->completeDataAccess(pkt); - else - tickEvent.schedule(pkt, time); + if (next_tick == curTick) + cpu->completeDataAccess(pkt); + else + tickEvent.schedule(pkt, next_tick); - return true; + return true; + } + else { + //Snooping a coherence req, do nothing + return true; + } } void @@ -625,7 +682,7 @@ TimingSimpleCPU::DcachePort::recvRetry() // waiting to transmit assert(cpu->dcache_pkt != NULL); assert(cpu->_status == DcacheRetry); - Packet *tmp = cpu->dcache_pkt; + PacketPtr tmp = cpu->dcache_pkt; if (sendTiming(tmp)) { cpu->_status = DcacheWaitResponse; // memory system takes ownership of packet @@ -645,19 +702,23 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(TimingSimpleCPU) Param max_loads_any_thread; Param max_loads_all_threads; Param progress_interval; - SimObjectParam mem; SimObjectParam system; Param cpu_id; #if FULL_SYSTEM - SimObjectParam itb; - SimObjectParam dtb; + SimObjectParam itb; + SimObjectParam dtb; Param profile; + + Param do_quiesce; + Param do_checkpoint_insts; + Param do_statistics_insts; #else SimObjectParam workload; #endif // FULL_SYSTEM Param clock; + Param phase; Param defer_registration; Param width; @@ -678,7 +739,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(TimingSimpleCPU) INIT_PARAM(max_loads_all_threads, "terminate when all threads have reached this load count"), INIT_PARAM(progress_interval, "Progress interval"), - INIT_PARAM(mem, "memory"), INIT_PARAM(system, "system object"), INIT_PARAM(cpu_id, "processor ID"), @@ -686,11 +746,15 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(TimingSimpleCPU) INIT_PARAM(itb, "Instruction TLB"), INIT_PARAM(dtb, "Data TLB"), INIT_PARAM(profile, ""), + INIT_PARAM(do_quiesce, ""), + INIT_PARAM(do_checkpoint_insts, ""), + INIT_PARAM(do_statistics_insts, ""), #else INIT_PARAM(workload, "processes to run"), #endif // FULL_SYSTEM INIT_PARAM(clock, "clock speed"), + INIT_PARAM_DFLT(phase, "clock phase", 0), INIT_PARAM(defer_registration, "defer system registration (for sampling)"), INIT_PARAM(width, "cpu width"), INIT_PARAM(function_trace, "Enable function trace"), @@ -712,9 +776,9 @@ CREATE_SIM_OBJECT(TimingSimpleCPU) 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->mem = mem; params->system = system; params->cpu_id = cpu_id; @@ -722,6 +786,9 @@ CREATE_SIM_OBJECT(TimingSimpleCPU) params->itb = itb; params->dtb = dtb; params->profile = profile; + params->do_quiesce = do_quiesce; + params->do_checkpoint_insts = do_checkpoint_insts; + params->do_statistics_insts = do_statistics_insts; #else params->process = workload; #endif