atomic.cc revision 4762
111784Sarthur.perais@inria.fr/*
211784Sarthur.perais@inria.fr * Copyright (c) 2002-2005 The Regents of The University of Michigan
311784Sarthur.perais@inria.fr * All rights reserved.
411784Sarthur.perais@inria.fr *
511784Sarthur.perais@inria.fr * Redistribution and use in source and binary forms, with or without
611784Sarthur.perais@inria.fr * modification, are permitted provided that the following conditions are
711784Sarthur.perais@inria.fr * met: redistributions of source code must retain the above copyright
811784Sarthur.perais@inria.fr * notice, this list of conditions and the following disclaimer;
911784Sarthur.perais@inria.fr * redistributions in binary form must reproduce the above copyright
1011784Sarthur.perais@inria.fr * notice, this list of conditions and the following disclaimer in the
1111784Sarthur.perais@inria.fr * documentation and/or other materials provided with the distribution;
1211784Sarthur.perais@inria.fr * neither the name of the copyright holders nor the names of its
1311784Sarthur.perais@inria.fr * contributors may be used to endorse or promote products derived from
1411784Sarthur.perais@inria.fr * this software without specific prior written permission.
1511784Sarthur.perais@inria.fr *
1611784Sarthur.perais@inria.fr * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1711784Sarthur.perais@inria.fr * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1811784Sarthur.perais@inria.fr * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1911784Sarthur.perais@inria.fr * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2011784Sarthur.perais@inria.fr * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2111784Sarthur.perais@inria.fr * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2211784Sarthur.perais@inria.fr * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2311784Sarthur.perais@inria.fr * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2411784Sarthur.perais@inria.fr * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2511784Sarthur.perais@inria.fr * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2611784Sarthur.perais@inria.fr * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2711784Sarthur.perais@inria.fr *
2811784Sarthur.perais@inria.fr * Authors: Steve Reinhardt
2911784Sarthur.perais@inria.fr */
3011784Sarthur.perais@inria.fr
3111784Sarthur.perais@inria.fr#include "arch/locked_mem.hh"
3211784Sarthur.perais@inria.fr#include "arch/mmaped_ipr.hh"
3311784Sarthur.perais@inria.fr#include "arch/utility.hh"
3411784Sarthur.perais@inria.fr#include "base/bigint.hh"
3511784Sarthur.perais@inria.fr#include "cpu/exetrace.hh"
3611784Sarthur.perais@inria.fr#include "cpu/simple/atomic.hh"
3711784Sarthur.perais@inria.fr#include "mem/packet.hh"
3811784Sarthur.perais@inria.fr#include "mem/packet_access.hh"
3911784Sarthur.perais@inria.fr#include "params/AtomicSimpleCPU.hh"
4011784Sarthur.perais@inria.fr#include "sim/system.hh"
4111784Sarthur.perais@inria.fr
4211784Sarthur.perais@inria.frusing namespace std;
4311784Sarthur.perais@inria.frusing namespace TheISA;
4411784Sarthur.perais@inria.fr
4511784Sarthur.perais@inria.frAtomicSimpleCPU::TickEvent::TickEvent(AtomicSimpleCPU *c)
4611784Sarthur.perais@inria.fr    : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c)
4711784Sarthur.perais@inria.fr{
4811784Sarthur.perais@inria.fr}
4911784Sarthur.perais@inria.fr
5011784Sarthur.perais@inria.fr
5111784Sarthur.perais@inria.frvoid
5211784Sarthur.perais@inria.frAtomicSimpleCPU::TickEvent::process()
5311784Sarthur.perais@inria.fr{
5411784Sarthur.perais@inria.fr    cpu->tick();
5511784Sarthur.perais@inria.fr}
5611784Sarthur.perais@inria.fr
5711784Sarthur.perais@inria.frconst char *
5811784Sarthur.perais@inria.frAtomicSimpleCPU::TickEvent::description()
5911784Sarthur.perais@inria.fr{
6011784Sarthur.perais@inria.fr    return "AtomicSimpleCPU tick event";
6111784Sarthur.perais@inria.fr}
6211784Sarthur.perais@inria.fr
6311784Sarthur.perais@inria.frPort *
6411784Sarthur.perais@inria.frAtomicSimpleCPU::getPort(const std::string &if_name, int idx)
6511784Sarthur.perais@inria.fr{
6611784Sarthur.perais@inria.fr    if (if_name == "dcache_port")
6711784Sarthur.perais@inria.fr        return &dcachePort;
6811784Sarthur.perais@inria.fr    else if (if_name == "icache_port")
6911784Sarthur.perais@inria.fr        return &icachePort;
7011784Sarthur.perais@inria.fr    else
7111784Sarthur.perais@inria.fr        panic("No Such Port\n");
7211784Sarthur.perais@inria.fr}
7311784Sarthur.perais@inria.fr
7411784Sarthur.perais@inria.frvoid
7511784Sarthur.perais@inria.frAtomicSimpleCPU::init()
7611784Sarthur.perais@inria.fr{
7711784Sarthur.perais@inria.fr    BaseCPU::init();
7811784Sarthur.perais@inria.fr#if FULL_SYSTEM
7911784Sarthur.perais@inria.fr    for (int i = 0; i < threadContexts.size(); ++i) {
8011784Sarthur.perais@inria.fr        ThreadContext *tc = threadContexts[i];
8111784Sarthur.perais@inria.fr
8211784Sarthur.perais@inria.fr        // initialize CPU, including PC
8311784Sarthur.perais@inria.fr        TheISA::initCPU(tc, tc->readCpuId());
8411784Sarthur.perais@inria.fr    }
8511784Sarthur.perais@inria.fr#endif
8611784Sarthur.perais@inria.fr}
8711784Sarthur.perais@inria.fr
8811784Sarthur.perais@inria.frbool
8911784Sarthur.perais@inria.frAtomicSimpleCPU::CpuPort::recvTiming(PacketPtr pkt)
9011784Sarthur.perais@inria.fr{
9111784Sarthur.perais@inria.fr    panic("AtomicSimpleCPU doesn't expect recvTiming callback!");
9211784Sarthur.perais@inria.fr    return true;
9311784Sarthur.perais@inria.fr}
9411784Sarthur.perais@inria.fr
9511784Sarthur.perais@inria.frTick
9611784Sarthur.perais@inria.frAtomicSimpleCPU::CpuPort::recvAtomic(PacketPtr pkt)
9711784Sarthur.perais@inria.fr{
9811784Sarthur.perais@inria.fr    //Snooping a coherence request, just return
9911784Sarthur.perais@inria.fr    return 0;
10011784Sarthur.perais@inria.fr}
10111784Sarthur.perais@inria.fr
10211784Sarthur.perais@inria.frvoid
10311784Sarthur.perais@inria.frAtomicSimpleCPU::CpuPort::recvFunctional(PacketPtr pkt)
10411784Sarthur.perais@inria.fr{
10511784Sarthur.perais@inria.fr    //No internal storage to update, just return
10611784Sarthur.perais@inria.fr    return;
10711784Sarthur.perais@inria.fr}
10811784Sarthur.perais@inria.fr
10911784Sarthur.perais@inria.frvoid
11011784Sarthur.perais@inria.frAtomicSimpleCPU::CpuPort::recvStatusChange(Status status)
11111784Sarthur.perais@inria.fr{
11211784Sarthur.perais@inria.fr    if (status == RangeChange) {
11311784Sarthur.perais@inria.fr        if (!snoopRangeSent) {
11411784Sarthur.perais@inria.fr            snoopRangeSent = true;
11511784Sarthur.perais@inria.fr            sendStatusChange(Port::RangeChange);
11611784Sarthur.perais@inria.fr        }
11711784Sarthur.perais@inria.fr        return;
11811784Sarthur.perais@inria.fr    }
11911784Sarthur.perais@inria.fr
12011784Sarthur.perais@inria.fr    panic("AtomicSimpleCPU doesn't expect recvStatusChange callback!");
12111784Sarthur.perais@inria.fr}
12211784Sarthur.perais@inria.fr
12311784Sarthur.perais@inria.frvoid
12411784Sarthur.perais@inria.frAtomicSimpleCPU::CpuPort::recvRetry()
12511784Sarthur.perais@inria.fr{
12611784Sarthur.perais@inria.fr    panic("AtomicSimpleCPU doesn't expect recvRetry callback!");
12711784Sarthur.perais@inria.fr}
12811784Sarthur.perais@inria.fr
12911784Sarthur.perais@inria.frvoid
13011784Sarthur.perais@inria.frAtomicSimpleCPU::DcachePort::setPeer(Port *port)
13111784Sarthur.perais@inria.fr{
13211784Sarthur.perais@inria.fr    Port::setPeer(port);
13311784Sarthur.perais@inria.fr
13411784Sarthur.perais@inria.fr#if FULL_SYSTEM
13511784Sarthur.perais@inria.fr    // Update the ThreadContext's memory ports (Functional/Virtual
13611784Sarthur.perais@inria.fr    // Ports)
13711784Sarthur.perais@inria.fr    cpu->tcBase()->connectMemPorts();
13811784Sarthur.perais@inria.fr#endif
13911784Sarthur.perais@inria.fr}
14011784Sarthur.perais@inria.fr
14111784Sarthur.perais@inria.frAtomicSimpleCPU::AtomicSimpleCPU(Params *p)
14211784Sarthur.perais@inria.fr    : BaseSimpleCPU(p), tickEvent(this),
14311784Sarthur.perais@inria.fr      width(p->width), simulate_stalls(p->simulate_stalls),
14411784Sarthur.perais@inria.fr      icachePort(name() + "-iport", this), dcachePort(name() + "-iport", this)
14511784Sarthur.perais@inria.fr{
14611784Sarthur.perais@inria.fr    _status = Idle;
14711784Sarthur.perais@inria.fr
14811784Sarthur.perais@inria.fr    icachePort.snoopRangeSent = false;
14911784Sarthur.perais@inria.fr    dcachePort.snoopRangeSent = false;
15011784Sarthur.perais@inria.fr
15111784Sarthur.perais@inria.fr    ifetch_req = new Request();
15211784Sarthur.perais@inria.fr    ifetch_req->setThreadContext(p->cpu_id, 0); // Add thread ID if we add MT
15311784Sarthur.perais@inria.fr    ifetch_pkt = new Packet(ifetch_req, MemCmd::ReadReq, Packet::Broadcast);
15411784Sarthur.perais@inria.fr    ifetch_pkt->dataStatic(&inst);
15511784Sarthur.perais@inria.fr
15611784Sarthur.perais@inria.fr    data_read_req = new Request();
15711784Sarthur.perais@inria.fr    data_read_req->setThreadContext(p->cpu_id, 0); // Add thread ID here too
15811784Sarthur.perais@inria.fr    data_read_pkt = new Packet(data_read_req, MemCmd::ReadReq,
15911784Sarthur.perais@inria.fr                               Packet::Broadcast);
16011784Sarthur.perais@inria.fr    data_read_pkt->dataStatic(&dataReg);
16111784Sarthur.perais@inria.fr
16211784Sarthur.perais@inria.fr    data_write_req = new Request();
16311784Sarthur.perais@inria.fr    data_write_req->setThreadContext(p->cpu_id, 0); // Add thread ID here too
16411784Sarthur.perais@inria.fr    data_write_pkt = new Packet(data_write_req, MemCmd::WriteReq,
16511784Sarthur.perais@inria.fr                                Packet::Broadcast);
16611784Sarthur.perais@inria.fr    data_swap_pkt = new Packet(data_write_req, MemCmd::SwapReq,
16711784Sarthur.perais@inria.fr                                Packet::Broadcast);
16811784Sarthur.perais@inria.fr}
16911784Sarthur.perais@inria.fr
17011784Sarthur.perais@inria.fr
17111784Sarthur.perais@inria.frAtomicSimpleCPU::~AtomicSimpleCPU()
17211784Sarthur.perais@inria.fr{
17311784Sarthur.perais@inria.fr}
17411784Sarthur.perais@inria.fr
17511784Sarthur.perais@inria.frvoid
17611784Sarthur.perais@inria.frAtomicSimpleCPU::serialize(ostream &os)
17711784Sarthur.perais@inria.fr{
17811784Sarthur.perais@inria.fr    SimObject::State so_state = SimObject::getState();
17911784Sarthur.perais@inria.fr    SERIALIZE_ENUM(so_state);
18011784Sarthur.perais@inria.fr    Status _status = status();
18111784Sarthur.perais@inria.fr    SERIALIZE_ENUM(_status);
18211784Sarthur.perais@inria.fr    BaseSimpleCPU::serialize(os);
18311784Sarthur.perais@inria.fr    nameOut(os, csprintf("%s.tickEvent", name()));
18411784Sarthur.perais@inria.fr    tickEvent.serialize(os);
18511784Sarthur.perais@inria.fr}
18611784Sarthur.perais@inria.fr
18711784Sarthur.perais@inria.frvoid
18811784Sarthur.perais@inria.frAtomicSimpleCPU::unserialize(Checkpoint *cp, const string &section)
18911784Sarthur.perais@inria.fr{
19011784Sarthur.perais@inria.fr    SimObject::State so_state;
19111784Sarthur.perais@inria.fr    UNSERIALIZE_ENUM(so_state);
19211784Sarthur.perais@inria.fr    UNSERIALIZE_ENUM(_status);
19311784Sarthur.perais@inria.fr    BaseSimpleCPU::unserialize(cp, section);
19411784Sarthur.perais@inria.fr    tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
19511784Sarthur.perais@inria.fr}
19611784Sarthur.perais@inria.fr
19711784Sarthur.perais@inria.frvoid
19811784Sarthur.perais@inria.frAtomicSimpleCPU::resume()
19911784Sarthur.perais@inria.fr{
20011784Sarthur.perais@inria.fr    if (_status != SwitchedOut && _status != Idle) {
20111784Sarthur.perais@inria.fr        assert(system->getMemoryMode() == Enums::atomic);
20211784Sarthur.perais@inria.fr
20311784Sarthur.perais@inria.fr        changeState(SimObject::Running);
20411784Sarthur.perais@inria.fr        if (thread->status() == ThreadContext::Active) {
20511784Sarthur.perais@inria.fr            if (!tickEvent.scheduled()) {
20611784Sarthur.perais@inria.fr                tickEvent.schedule(nextCycle());
20711784Sarthur.perais@inria.fr            }
20811784Sarthur.perais@inria.fr        }
20911784Sarthur.perais@inria.fr    }
21011784Sarthur.perais@inria.fr}
21111784Sarthur.perais@inria.fr
21211784Sarthur.perais@inria.frvoid
21311784Sarthur.perais@inria.frAtomicSimpleCPU::switchOut()
21411784Sarthur.perais@inria.fr{
21511784Sarthur.perais@inria.fr    assert(status() == Running || status() == Idle);
21611784Sarthur.perais@inria.fr    _status = SwitchedOut;
21711784Sarthur.perais@inria.fr
21811784Sarthur.perais@inria.fr    tickEvent.squash();
21911784Sarthur.perais@inria.fr}
22011784Sarthur.perais@inria.fr
22111784Sarthur.perais@inria.fr
22211784Sarthur.perais@inria.frvoid
22311784Sarthur.perais@inria.frAtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
22411784Sarthur.perais@inria.fr{
22511784Sarthur.perais@inria.fr    BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort);
22611784Sarthur.perais@inria.fr
22711784Sarthur.perais@inria.fr    assert(!tickEvent.scheduled());
22811784Sarthur.perais@inria.fr
22911784Sarthur.perais@inria.fr    // if any of this CPU's ThreadContexts are active, mark the CPU as
23011784Sarthur.perais@inria.fr    // running and schedule its tick event.
23111784Sarthur.perais@inria.fr    for (int i = 0; i < threadContexts.size(); ++i) {
23211784Sarthur.perais@inria.fr        ThreadContext *tc = threadContexts[i];
23311784Sarthur.perais@inria.fr        if (tc->status() == ThreadContext::Active && _status != Running) {
23411784Sarthur.perais@inria.fr            _status = Running;
23511784Sarthur.perais@inria.fr            tickEvent.schedule(nextCycle());
23611784Sarthur.perais@inria.fr            break;
23711784Sarthur.perais@inria.fr        }
23811784Sarthur.perais@inria.fr    }
23911784Sarthur.perais@inria.fr    if (_status != Running) {
24011784Sarthur.perais@inria.fr        _status = Idle;
24111784Sarthur.perais@inria.fr    }
24211784Sarthur.perais@inria.fr}
24311784Sarthur.perais@inria.fr
24411784Sarthur.perais@inria.fr
24511784Sarthur.perais@inria.frvoid
24611784Sarthur.perais@inria.frAtomicSimpleCPU::activateContext(int thread_num, int delay)
24711784Sarthur.perais@inria.fr{
24811784Sarthur.perais@inria.fr    assert(thread_num == 0);
24911784Sarthur.perais@inria.fr    assert(thread);
25011784Sarthur.perais@inria.fr
25111784Sarthur.perais@inria.fr    assert(_status == Idle);
25211784Sarthur.perais@inria.fr    assert(!tickEvent.scheduled());
25311784Sarthur.perais@inria.fr
25411784Sarthur.perais@inria.fr    notIdleFraction++;
25511784Sarthur.perais@inria.fr
25611784Sarthur.perais@inria.fr    //Make sure ticks are still on multiples of cycles
25711784Sarthur.perais@inria.fr    tickEvent.schedule(nextCycle(curTick + cycles(delay)));
25811784Sarthur.perais@inria.fr    _status = Running;
25911784Sarthur.perais@inria.fr}
26011784Sarthur.perais@inria.fr
26111784Sarthur.perais@inria.fr
26211784Sarthur.perais@inria.frvoid
26311784Sarthur.perais@inria.frAtomicSimpleCPU::suspendContext(int thread_num)
26411784Sarthur.perais@inria.fr{
26511784Sarthur.perais@inria.fr    assert(thread_num == 0);
26611784Sarthur.perais@inria.fr    assert(thread);
26711784Sarthur.perais@inria.fr
26811784Sarthur.perais@inria.fr    assert(_status == Running);
26911784Sarthur.perais@inria.fr
27011784Sarthur.perais@inria.fr    // tick event may not be scheduled if this gets called from inside
27111784Sarthur.perais@inria.fr    // an instruction's execution, e.g. "quiesce"
27211784Sarthur.perais@inria.fr    if (tickEvent.scheduled())
27311784Sarthur.perais@inria.fr        tickEvent.deschedule();
27411784Sarthur.perais@inria.fr
27511784Sarthur.perais@inria.fr    notIdleFraction--;
27611784Sarthur.perais@inria.fr    _status = Idle;
27711784Sarthur.perais@inria.fr}
27811784Sarthur.perais@inria.fr
27911784Sarthur.perais@inria.fr
28011784Sarthur.perais@inria.frtemplate <class T>
28111784Sarthur.perais@inria.frFault
28211784Sarthur.perais@inria.frAtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
28311784Sarthur.perais@inria.fr{
28411784Sarthur.perais@inria.fr    // use the CPU's statically allocated read request and packet objects
28511784Sarthur.perais@inria.fr    Request *req = data_read_req;
28611784Sarthur.perais@inria.fr    PacketPtr pkt = data_read_pkt;
28711784Sarthur.perais@inria.fr
28811784Sarthur.perais@inria.fr    req->setVirt(0, addr, sizeof(T), flags, thread->readPC());
28911784Sarthur.perais@inria.fr
29011784Sarthur.perais@inria.fr    if (traceData) {
29111784Sarthur.perais@inria.fr        traceData->setAddr(addr);
29211784Sarthur.perais@inria.fr    }
29311784Sarthur.perais@inria.fr
29411784Sarthur.perais@inria.fr    // translate to physical address
29511784Sarthur.perais@inria.fr    Fault fault = thread->translateDataReadReq(req);
29611784Sarthur.perais@inria.fr
29711784Sarthur.perais@inria.fr    // Now do the access.
29811784Sarthur.perais@inria.fr    if (fault == NoFault) {
29911784Sarthur.perais@inria.fr        pkt->reinitFromRequest();
30011784Sarthur.perais@inria.fr
30111784Sarthur.perais@inria.fr        if (req->isMmapedIpr())
30211784Sarthur.perais@inria.fr            dcache_latency = TheISA::handleIprRead(thread->getTC(),pkt);
30311784Sarthur.perais@inria.fr        else
30411784Sarthur.perais@inria.fr            dcache_latency = dcachePort.sendAtomic(pkt);
30511784Sarthur.perais@inria.fr        dcache_access = true;
30611784Sarthur.perais@inria.fr#if !defined(NDEBUG)
30711784Sarthur.perais@inria.fr        if (pkt->result != Packet::Success)
30811784Sarthur.perais@inria.fr            panic("Unable to find responder for address pa = %#X va = %#X\n",
30911784Sarthur.perais@inria.fr                    pkt->req->getPaddr(), pkt->req->getVaddr());
31011784Sarthur.perais@inria.fr#endif
31111784Sarthur.perais@inria.fr        data = pkt->get<T>();
31211784Sarthur.perais@inria.fr
31311784Sarthur.perais@inria.fr        if (req->isLocked()) {
31411784Sarthur.perais@inria.fr            TheISA::handleLockedRead(thread, req);
31511784Sarthur.perais@inria.fr        }
31611784Sarthur.perais@inria.fr    }
31711784Sarthur.perais@inria.fr
31811784Sarthur.perais@inria.fr    // This will need a new way to tell if it has a dcache attached.
31911784Sarthur.perais@inria.fr    if (req->isUncacheable())
32011784Sarthur.perais@inria.fr        recordEvent("Uncached Read");
32111784Sarthur.perais@inria.fr
32211784Sarthur.perais@inria.fr    return fault;
32311784Sarthur.perais@inria.fr}
32411784Sarthur.perais@inria.fr
32511784Sarthur.perais@inria.fr#ifndef DOXYGEN_SHOULD_SKIP_THIS
32611784Sarthur.perais@inria.fr
32711784Sarthur.perais@inria.frtemplate
32811784Sarthur.perais@inria.frFault
32911784Sarthur.perais@inria.frAtomicSimpleCPU::read(Addr addr, Twin32_t &data, unsigned flags);
33011784Sarthur.perais@inria.fr
33111784Sarthur.perais@inria.frtemplate
33211784Sarthur.perais@inria.frFault
33311784Sarthur.perais@inria.frAtomicSimpleCPU::read(Addr addr, Twin64_t &data, unsigned flags);
33411784Sarthur.perais@inria.fr
33511784Sarthur.perais@inria.frtemplate
33611784Sarthur.perais@inria.frFault
33711784Sarthur.perais@inria.frAtomicSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags);
33811784Sarthur.perais@inria.fr
33911784Sarthur.perais@inria.frtemplate
34011784Sarthur.perais@inria.frFault
34111784Sarthur.perais@inria.frAtomicSimpleCPU::read(Addr addr, uint32_t &data, unsigned flags);
34211784Sarthur.perais@inria.fr
34311784Sarthur.perais@inria.frtemplate
34411784Sarthur.perais@inria.frFault
34511784Sarthur.perais@inria.frAtomicSimpleCPU::read(Addr addr, uint16_t &data, unsigned flags);
34611784Sarthur.perais@inria.fr
34711784Sarthur.perais@inria.frtemplate
34811784Sarthur.perais@inria.frFault
34911784Sarthur.perais@inria.frAtomicSimpleCPU::read(Addr addr, uint8_t &data, unsigned flags);
35011784Sarthur.perais@inria.fr
35111784Sarthur.perais@inria.fr#endif //DOXYGEN_SHOULD_SKIP_THIS
35211784Sarthur.perais@inria.fr
35311784Sarthur.perais@inria.frtemplate<>
35411784Sarthur.perais@inria.frFault
35511784Sarthur.perais@inria.frAtomicSimpleCPU::read(Addr addr, double &data, unsigned flags)
35611784Sarthur.perais@inria.fr{
35711784Sarthur.perais@inria.fr    return read(addr, *(uint64_t*)&data, flags);
35811784Sarthur.perais@inria.fr}
35911784Sarthur.perais@inria.fr
36011784Sarthur.perais@inria.frtemplate<>
36111784Sarthur.perais@inria.frFault
36211784Sarthur.perais@inria.frAtomicSimpleCPU::read(Addr addr, float &data, unsigned flags)
36311784Sarthur.perais@inria.fr{
36411784Sarthur.perais@inria.fr    return read(addr, *(uint32_t*)&data, flags);
36511784Sarthur.perais@inria.fr}
36611784Sarthur.perais@inria.fr
36711784Sarthur.perais@inria.fr
36811784Sarthur.perais@inria.frtemplate<>
36911784Sarthur.perais@inria.frFault
37011784Sarthur.perais@inria.frAtomicSimpleCPU::read(Addr addr, int32_t &data, unsigned flags)
37111784Sarthur.perais@inria.fr{
37211784Sarthur.perais@inria.fr    return read(addr, (uint32_t&)data, flags);
37311784Sarthur.perais@inria.fr}
37411784Sarthur.perais@inria.fr
37511784Sarthur.perais@inria.fr
37611784Sarthur.perais@inria.frtemplate <class T>
37711784Sarthur.perais@inria.frFault
37811784Sarthur.perais@inria.frAtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
37911784Sarthur.perais@inria.fr{
38011784Sarthur.perais@inria.fr    // use the CPU's statically allocated write request and packet objects
38111784Sarthur.perais@inria.fr    Request *req = data_write_req;
38211784Sarthur.perais@inria.fr    PacketPtr pkt;
38311784Sarthur.perais@inria.fr
38411784Sarthur.perais@inria.fr    req->setVirt(0, addr, sizeof(T), flags, thread->readPC());
38511784Sarthur.perais@inria.fr
38611784Sarthur.perais@inria.fr    if (req->isSwap())
38711784Sarthur.perais@inria.fr        pkt = data_swap_pkt;
38811784Sarthur.perais@inria.fr    else
38911784Sarthur.perais@inria.fr        pkt = data_write_pkt;
39011784Sarthur.perais@inria.fr
39111784Sarthur.perais@inria.fr    if (traceData) {
39211784Sarthur.perais@inria.fr        traceData->setAddr(addr);
39311784Sarthur.perais@inria.fr    }
39411784Sarthur.perais@inria.fr
39511784Sarthur.perais@inria.fr    // translate to physical address
39611784Sarthur.perais@inria.fr    Fault fault = thread->translateDataWriteReq(req);
39711784Sarthur.perais@inria.fr
39811784Sarthur.perais@inria.fr    // Now do the access.
39911784Sarthur.perais@inria.fr    if (fault == NoFault) {
40011784Sarthur.perais@inria.fr        bool do_access = true;  // flag to suppress cache access
40111784Sarthur.perais@inria.fr
40211784Sarthur.perais@inria.fr        if (req->isLocked()) {
40311784Sarthur.perais@inria.fr            do_access = TheISA::handleLockedWrite(thread, req);
40411784Sarthur.perais@inria.fr        }
40511784Sarthur.perais@inria.fr        if (req->isCondSwap()) {
40611784Sarthur.perais@inria.fr             assert(res);
40711784Sarthur.perais@inria.fr             req->setExtraData(*res);
40811784Sarthur.perais@inria.fr        }
40911784Sarthur.perais@inria.fr
41011784Sarthur.perais@inria.fr
41111784Sarthur.perais@inria.fr        if (do_access) {
41211784Sarthur.perais@inria.fr            pkt->reinitFromRequest();
41311784Sarthur.perais@inria.fr            pkt->dataStatic(&data);
41411784Sarthur.perais@inria.fr
41511784Sarthur.perais@inria.fr            if (req->isMmapedIpr()) {
41611784Sarthur.perais@inria.fr                dcache_latency = TheISA::handleIprWrite(thread->getTC(), pkt);
41711784Sarthur.perais@inria.fr            } else {
41811784Sarthur.perais@inria.fr                data = htog(data);
41911784Sarthur.perais@inria.fr                dcache_latency = dcachePort.sendAtomic(pkt);
42011784Sarthur.perais@inria.fr            }
42111784Sarthur.perais@inria.fr            dcache_access = true;
42211784Sarthur.perais@inria.fr
42311784Sarthur.perais@inria.fr#if !defined(NDEBUG)
42411784Sarthur.perais@inria.fr            if (pkt->result != Packet::Success)
42511784Sarthur.perais@inria.fr                panic("Unable to find responder for address pa = %#X va = %#X\n",
42611784Sarthur.perais@inria.fr                        pkt->req->getPaddr(), pkt->req->getVaddr());
42711784Sarthur.perais@inria.fr#endif
42811784Sarthur.perais@inria.fr        }
42911784Sarthur.perais@inria.fr
43011784Sarthur.perais@inria.fr        if (req->isSwap()) {
43111784Sarthur.perais@inria.fr            assert(res);
43211784Sarthur.perais@inria.fr            *res = pkt->get<T>();
43311784Sarthur.perais@inria.fr        } else if (res) {
43411784Sarthur.perais@inria.fr            *res = req->getExtraData();
43511784Sarthur.perais@inria.fr        }
43611784Sarthur.perais@inria.fr    }
43711784Sarthur.perais@inria.fr
43811784Sarthur.perais@inria.fr    // This will need a new way to tell if it's hooked up to a cache or not.
43911784Sarthur.perais@inria.fr    if (req->isUncacheable())
44011784Sarthur.perais@inria.fr        recordEvent("Uncached Write");
44111784Sarthur.perais@inria.fr
44211784Sarthur.perais@inria.fr    // If the write needs to have a fault on the access, consider calling
44311784Sarthur.perais@inria.fr    // changeStatus() and changing it to "bad addr write" or something.
44411784Sarthur.perais@inria.fr    return fault;
44511784Sarthur.perais@inria.fr}
44611784Sarthur.perais@inria.fr
44711784Sarthur.perais@inria.fr
44811784Sarthur.perais@inria.fr#ifndef DOXYGEN_SHOULD_SKIP_THIS
44911784Sarthur.perais@inria.fr
45011784Sarthur.perais@inria.frtemplate
45111784Sarthur.perais@inria.frFault
45211784Sarthur.perais@inria.frAtomicSimpleCPU::write(Twin32_t data, Addr addr,
45311784Sarthur.perais@inria.fr                       unsigned flags, uint64_t *res);
45411784Sarthur.perais@inria.fr
45511784Sarthur.perais@inria.frtemplate
45611784Sarthur.perais@inria.frFault
45711784Sarthur.perais@inria.frAtomicSimpleCPU::write(Twin64_t data, Addr addr,
45811784Sarthur.perais@inria.fr                       unsigned flags, uint64_t *res);
45911784Sarthur.perais@inria.fr
46011784Sarthur.perais@inria.frtemplate
46111784Sarthur.perais@inria.frFault
46211784Sarthur.perais@inria.frAtomicSimpleCPU::write(uint64_t data, Addr addr,
46311784Sarthur.perais@inria.fr                       unsigned flags, uint64_t *res);
46411784Sarthur.perais@inria.fr
46511784Sarthur.perais@inria.frtemplate
46611784Sarthur.perais@inria.frFault
46711784Sarthur.perais@inria.frAtomicSimpleCPU::write(uint32_t data, Addr addr,
46811784Sarthur.perais@inria.fr                       unsigned flags, uint64_t *res);
46911784Sarthur.perais@inria.fr
47011784Sarthur.perais@inria.frtemplate
47111784Sarthur.perais@inria.frFault
47211784Sarthur.perais@inria.frAtomicSimpleCPU::write(uint16_t data, Addr addr,
47311784Sarthur.perais@inria.fr                       unsigned flags, uint64_t *res);
47411784Sarthur.perais@inria.fr
47511784Sarthur.perais@inria.frtemplate
47611784Sarthur.perais@inria.frFault
47711784Sarthur.perais@inria.frAtomicSimpleCPU::write(uint8_t data, Addr addr,
47811784Sarthur.perais@inria.fr                       unsigned flags, uint64_t *res);
47911784Sarthur.perais@inria.fr
48011784Sarthur.perais@inria.fr#endif //DOXYGEN_SHOULD_SKIP_THIS
48111784Sarthur.perais@inria.fr
48211784Sarthur.perais@inria.frtemplate<>
48311784Sarthur.perais@inria.frFault
48411784Sarthur.perais@inria.frAtomicSimpleCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
48511784Sarthur.perais@inria.fr{
48611784Sarthur.perais@inria.fr    return write(*(uint64_t*)&data, addr, flags, res);
48711784Sarthur.perais@inria.fr}
48811784Sarthur.perais@inria.fr
48911784Sarthur.perais@inria.frtemplate<>
49011784Sarthur.perais@inria.frFault
49111784Sarthur.perais@inria.frAtomicSimpleCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
49211784Sarthur.perais@inria.fr{
49311784Sarthur.perais@inria.fr    return write(*(uint32_t*)&data, addr, flags, res);
49411784Sarthur.perais@inria.fr}
49511784Sarthur.perais@inria.fr
49611784Sarthur.perais@inria.fr
49711784Sarthur.perais@inria.frtemplate<>
49811784Sarthur.perais@inria.frFault
49911784Sarthur.perais@inria.frAtomicSimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
50011784Sarthur.perais@inria.fr{
50111784Sarthur.perais@inria.fr    return write((uint32_t)data, addr, flags, res);
50211784Sarthur.perais@inria.fr}
50311784Sarthur.perais@inria.fr
50411784Sarthur.perais@inria.fr
50511784Sarthur.perais@inria.frvoid
50611784Sarthur.perais@inria.frAtomicSimpleCPU::tick()
50711784Sarthur.perais@inria.fr{
50811784Sarthur.perais@inria.fr    Tick latency = cycles(1); // instruction takes one cycle by default
50911784Sarthur.perais@inria.fr
51011784Sarthur.perais@inria.fr    for (int i = 0; i < width; ++i) {
51111784Sarthur.perais@inria.fr        numCycles++;
51211784Sarthur.perais@inria.fr
51311784Sarthur.perais@inria.fr        if (!curStaticInst || !curStaticInst->isDelayedCommit())
51411784Sarthur.perais@inria.fr            checkForInterrupts();
51511784Sarthur.perais@inria.fr
51611784Sarthur.perais@inria.fr        Fault fault = setupFetchRequest(ifetch_req);
51711784Sarthur.perais@inria.fr
51811784Sarthur.perais@inria.fr        if (fault == NoFault) {
51911784Sarthur.perais@inria.fr            Tick icache_latency = 0;
52011784Sarthur.perais@inria.fr            bool icache_access = false;
52111784Sarthur.perais@inria.fr            dcache_access = false; // assume no dcache access
52211784Sarthur.perais@inria.fr
52311784Sarthur.perais@inria.fr            //Fetch more instruction memory if necessary
52411784Sarthur.perais@inria.fr            //if(predecoder.needMoreBytes())
52511784Sarthur.perais@inria.fr            //{
52611784Sarthur.perais@inria.fr                icache_access = true;
52711784Sarthur.perais@inria.fr                ifetch_pkt->reinitFromRequest();
52811784Sarthur.perais@inria.fr
52911784Sarthur.perais@inria.fr                icache_latency = icachePort.sendAtomic(ifetch_pkt);
53011784Sarthur.perais@inria.fr                // ifetch_req is initialized to read the instruction directly
53111784Sarthur.perais@inria.fr                // into the CPU object's inst field.
53211784Sarthur.perais@inria.fr            //}
53311784Sarthur.perais@inria.fr
53411784Sarthur.perais@inria.fr            preExecute();
53511784Sarthur.perais@inria.fr
53611784Sarthur.perais@inria.fr            if(curStaticInst)
53711784Sarthur.perais@inria.fr            {
53811784Sarthur.perais@inria.fr                fault = curStaticInst->execute(this, traceData);
53911784Sarthur.perais@inria.fr                postExecute();
54011784Sarthur.perais@inria.fr            }
54111784Sarthur.perais@inria.fr
54211784Sarthur.perais@inria.fr            // @todo remove me after debugging with legion done
54311784Sarthur.perais@inria.fr            if (curStaticInst && (!curStaticInst->isMicroop() ||
54411784Sarthur.perais@inria.fr                        curStaticInst->isFirstMicroop()))
54511784Sarthur.perais@inria.fr                instCnt++;
54611784Sarthur.perais@inria.fr
54711784Sarthur.perais@inria.fr            if (simulate_stalls) {
54811784Sarthur.perais@inria.fr                Tick icache_stall =
54911784Sarthur.perais@inria.fr                    icache_access ? icache_latency - cycles(1) : 0;
55011784Sarthur.perais@inria.fr                Tick dcache_stall =
55111784Sarthur.perais@inria.fr                    dcache_access ? dcache_latency - cycles(1) : 0;
55211784Sarthur.perais@inria.fr                Tick stall_cycles = (icache_stall + dcache_stall) / cycles(1);
55311784Sarthur.perais@inria.fr                if (cycles(stall_cycles) < (icache_stall + dcache_stall))
55411784Sarthur.perais@inria.fr                    latency += cycles(stall_cycles+1);
55511784Sarthur.perais@inria.fr                else
55611784Sarthur.perais@inria.fr                    latency += cycles(stall_cycles);
55711784Sarthur.perais@inria.fr            }
55811784Sarthur.perais@inria.fr
55911784Sarthur.perais@inria.fr        }
56011784Sarthur.perais@inria.fr        if(fault != NoFault || !stayAtPC)
56111784Sarthur.perais@inria.fr            advancePC(fault);
56211784Sarthur.perais@inria.fr    }
56311784Sarthur.perais@inria.fr
56411784Sarthur.perais@inria.fr    if (_status != Idle)
56511784Sarthur.perais@inria.fr        tickEvent.schedule(curTick + latency);
56611784Sarthur.perais@inria.fr}
56711784Sarthur.perais@inria.fr
56811784Sarthur.perais@inria.fr
56911784Sarthur.perais@inria.fr////////////////////////////////////////////////////////////////////////
57011784Sarthur.perais@inria.fr//
57111784Sarthur.perais@inria.fr//  AtomicSimpleCPU Simulation Object
57211784Sarthur.perais@inria.fr//
57311784Sarthur.perais@inria.frAtomicSimpleCPU *
57411784Sarthur.perais@inria.frAtomicSimpleCPUParams::create()
57511784Sarthur.perais@inria.fr{
57611784Sarthur.perais@inria.fr    AtomicSimpleCPU::Params *params = new AtomicSimpleCPU::Params();
57711784Sarthur.perais@inria.fr    params->name = name;
57811784Sarthur.perais@inria.fr    params->numberOfThreads = 1;
57911784Sarthur.perais@inria.fr    params->max_insts_any_thread = max_insts_any_thread;
58011784Sarthur.perais@inria.fr    params->max_insts_all_threads = max_insts_all_threads;
58111784Sarthur.perais@inria.fr    params->max_loads_any_thread = max_loads_any_thread;
58211784Sarthur.perais@inria.fr    params->max_loads_all_threads = max_loads_all_threads;
58311784Sarthur.perais@inria.fr    params->progress_interval = progress_interval;
58411784Sarthur.perais@inria.fr    params->deferRegistration = defer_registration;
58511784Sarthur.perais@inria.fr    params->phase = phase;
58611784Sarthur.perais@inria.fr    params->clock = clock;
58711784Sarthur.perais@inria.fr    params->functionTrace = function_trace;
58811784Sarthur.perais@inria.fr    params->functionTraceStart = function_trace_start;
58911784Sarthur.perais@inria.fr    params->width = width;
59011784Sarthur.perais@inria.fr    params->simulate_stalls = simulate_stalls;
59111784Sarthur.perais@inria.fr    params->system = system;
59211784Sarthur.perais@inria.fr    params->cpu_id = cpu_id;
59311784Sarthur.perais@inria.fr
59411784Sarthur.perais@inria.fr#if FULL_SYSTEM
59511784Sarthur.perais@inria.fr    params->itb = itb;
59611784Sarthur.perais@inria.fr    params->dtb = dtb;
59711784Sarthur.perais@inria.fr    params->profile = profile;
59811784Sarthur.perais@inria.fr    params->do_quiesce = do_quiesce;
59911784Sarthur.perais@inria.fr    params->do_checkpoint_insts = do_checkpoint_insts;
60011784Sarthur.perais@inria.fr    params->do_statistics_insts = do_statistics_insts;
60111784Sarthur.perais@inria.fr#else
60211784Sarthur.perais@inria.fr    if (workload.size() != 1)
60311784Sarthur.perais@inria.fr        panic("only one workload allowed");
60411784Sarthur.perais@inria.fr    params->process = workload[0];
60511784Sarthur.perais@inria.fr#endif
60611784Sarthur.perais@inria.fr
60711784Sarthur.perais@inria.fr    AtomicSimpleCPU *cpu = new AtomicSimpleCPU(params);
60811784Sarthur.perais@inria.fr    return cpu;
60911784Sarthur.perais@inria.fr}
61011784Sarthur.perais@inria.fr