atomic.cc revision 4776
17893SN/A/*
27893SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan
37893SN/A * All rights reserved.
49988Snilay@cs.wisc.edu *
58825Snilay@cs.wisc.edu * Redistribution and use in source and binary forms, with or without
69988Snilay@cs.wisc.edu * modification, are permitted provided that the following conditions are
77893SN/A * met: redistributions of source code must retain the above copyright
87893SN/A * notice, this list of conditions and the following disclaimer;
97893SN/A * redistributions in binary form must reproduce the above copyright
107893SN/A * notice, this list of conditions and the following disclaimer in the
117893SN/A * documentation and/or other materials provided with the distribution;
127893SN/A * neither the name of the copyright holders nor the names of its
1310315Snilay@cs.wisc.edu * contributors may be used to endorse or promote products derived from
148825Snilay@cs.wisc.edu * this software without specific prior written permission.
159885Sstever@gmail.com *
169885Sstever@gmail.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
179988Snilay@cs.wisc.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
188825Snilay@cs.wisc.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
198825Snilay@cs.wisc.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2010315Snilay@cs.wisc.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
218825Snilay@cs.wisc.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2210242Ssteve.reinhardt@amd.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
239449SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249449SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
258464SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2610798Ssteve.reinhardt@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
278721SN/A *
288825Snilay@cs.wisc.edu * Authors: Steve Reinhardt
298825Snilay@cs.wisc.edu */
307935SN/A
317935SN/A#include "arch/locked_mem.hh"
327935SN/A#include "arch/mmaped_ipr.hh"
337935SN/A#include "arch/utility.hh"
347935SN/A#include "base/bigint.hh"
357935SN/A#include "cpu/exetrace.hh"
367935SN/A#include "cpu/simple/atomic.hh"
378983Snate@binkert.org#include "mem/packet.hh"
387893SN/A#include "mem/packet_access.hh"
399885Sstever@gmail.com#include "params/AtomicSimpleCPU.hh"
409885Sstever@gmail.com#include "sim/system.hh"
419885Sstever@gmail.com
4210315Snilay@cs.wisc.eduusing namespace std;
439988Snilay@cs.wisc.eduusing namespace TheISA;
4410315Snilay@cs.wisc.edu
459885Sstever@gmail.comAtomicSimpleCPU::TickEvent::TickEvent(AtomicSimpleCPU *c)
469885Sstever@gmail.com    : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c)
477893SN/A{
487893SN/A}
499885Sstever@gmail.com
507893SN/A
517893SN/Avoid
528241SN/AAtomicSimpleCPU::TickEvent::process()
538241SN/A{
547893SN/A    cpu->tick();
557893SN/A}
567893SN/A
577893SN/Aconst char *
589481Snilay@cs.wisc.eduAtomicSimpleCPU::TickEvent::description()
597893SN/A{
607893SN/A    return "AtomicSimpleCPU tick event";
619885Sstever@gmail.com}
627893SN/A
637893SN/APort *
647893SN/AAtomicSimpleCPU::getPort(const std::string &if_name, int idx)
657893SN/A{
667893SN/A    if (if_name == "dcache_port")
677893SN/A        return &dcachePort;
687893SN/A    else if (if_name == "icache_port")
697893SN/A        return &icachePort;
707893SN/A    else
717893SN/A        panic("No Such Port\n");
727893SN/A}
738825Snilay@cs.wisc.edu
747893SN/Avoid
757893SN/AAtomicSimpleCPU::init()
769988Snilay@cs.wisc.edu{
779988Snilay@cs.wisc.edu    BaseCPU::init();
7810451Snilay@cs.wisc.edu#if FULL_SYSTEM
797893SN/A    for (int i = 0; i < threadContexts.size(); ++i) {
807893SN/A        ThreadContext *tc = threadContexts[i];
817893SN/A
827893SN/A        // initialize CPU, including PC
837893SN/A        TheISA::initCPU(tc, tc->readCpuId());
847893SN/A    }
857893SN/A#endif
867893SN/A}
877893SN/A
887893SN/Abool
897893SN/AAtomicSimpleCPU::CpuPort::recvTiming(PacketPtr pkt)
908825Snilay@cs.wisc.edu{
919449SAli.Saidi@ARM.com    panic("AtomicSimpleCPU doesn't expect recvTiming callback!");
927893SN/A    return true;
937893SN/A}
947893SN/A
957893SN/ATick
967893SN/AAtomicSimpleCPU::CpuPort::recvAtomic(PacketPtr pkt)
977893SN/A{
987893SN/A    //Snooping a coherence request, just return
998728SN/A    return 0;
1007893SN/A}
1019924Ssteve.reinhardt@amd.com
1027893SN/Avoid
1037893SN/AAtomicSimpleCPU::CpuPort::recvFunctional(PacketPtr pkt)
1047893SN/A{
1057893SN/A    //No internal storage to update, just return
1067893SN/A    return;
1078825Snilay@cs.wisc.edu}
1087893SN/A
1097893SN/Avoid
1107893SN/AAtomicSimpleCPU::CpuPort::recvStatusChange(Status status)
1117893SN/A{
1127893SN/A    if (status == RangeChange) {
1137893SN/A        if (!snoopRangeSent) {
1149885Sstever@gmail.com            snoopRangeSent = true;
1157893SN/A            sendStatusChange(Port::RangeChange);
1167893SN/A        }
1177893SN/A        return;
1187893SN/A    }
1197893SN/A
1207893SN/A    panic("AtomicSimpleCPU doesn't expect recvStatusChange callback!");
1217893SN/A}
1227893SN/A
1237893SN/Avoid
12410242Ssteve.reinhardt@amd.comAtomicSimpleCPU::CpuPort::recvRetry()
1257893SN/A{
1268521SN/A    panic("AtomicSimpleCPU doesn't expect recvRetry callback!");
1279449SAli.Saidi@ARM.com}
1287893SN/A
1297893SN/Avoid
1307893SN/AAtomicSimpleCPU::DcachePort::setPeer(Port *port)
1317893SN/A{
1327893SN/A    Port::setPeer(port);
1337893SN/A
1347893SN/A#if FULL_SYSTEM
1357893SN/A    // Update the ThreadContext's memory ports (Functional/Virtual
1369885Sstever@gmail.com    // Ports)
1379885Sstever@gmail.com    cpu->tcBase()->connectMemPorts();
1389885Sstever@gmail.com#endif
1399885Sstever@gmail.com}
1409988Snilay@cs.wisc.edu
1419885Sstever@gmail.comAtomicSimpleCPU::AtomicSimpleCPU(Params *p)
1429481Snilay@cs.wisc.edu    : BaseSimpleCPU(p), tickEvent(this),
14310798Ssteve.reinhardt@amd.com      width(p->width), simulate_stalls(p->simulate_stalls),
1449481Snilay@cs.wisc.edu      icachePort(name() + "-iport", this), dcachePort(name() + "-iport", this)
1459481Snilay@cs.wisc.edu{
1469481Snilay@cs.wisc.edu    _status = Idle;
1479481Snilay@cs.wisc.edu
1489481Snilay@cs.wisc.edu    icachePort.snoopRangeSent = false;
1499988Snilay@cs.wisc.edu    dcachePort.snoopRangeSent = false;
1509481Snilay@cs.wisc.edu
1519481Snilay@cs.wisc.edu    ifetch_req = new Request();
1529481Snilay@cs.wisc.edu    ifetch_req->setThreadContext(p->cpu_id, 0); // Add thread ID if we add MT
1539481Snilay@cs.wisc.edu    ifetch_pkt = new Packet(ifetch_req, MemCmd::ReadReq, Packet::Broadcast);
1549481Snilay@cs.wisc.edu    ifetch_pkt->dataStatic(&inst);
1559481Snilay@cs.wisc.edu
1569481Snilay@cs.wisc.edu    data_read_req = new Request();
1579481Snilay@cs.wisc.edu    data_read_req->setThreadContext(p->cpu_id, 0); // Add thread ID here too
1587893SN/A    data_read_pkt = new Packet(data_read_req, MemCmd::ReadReq,
1597893SN/A                               Packet::Broadcast);
1609885Sstever@gmail.com    data_read_pkt->dataStatic(&dataReg);
1618983Snate@binkert.org
1627893SN/A    data_write_req = new Request();
1639885Sstever@gmail.com    data_write_req->setThreadContext(p->cpu_id, 0); // Add thread ID here too
16410645Snilay@cs.wisc.edu    data_write_pkt = new Packet(data_write_req, MemCmd::WriteReq,
1659988Snilay@cs.wisc.edu                                Packet::Broadcast);
1667893SN/A    data_swap_pkt = new Packet(data_write_req, MemCmd::SwapReq,
1679348SAli.Saidi@ARM.com                                Packet::Broadcast);
16810901Snilay@cs.wisc.edu}
1697893SN/A
1709348SAli.Saidi@ARM.com
1717893SN/AAtomicSimpleCPU::~AtomicSimpleCPU()
1728835SAli.Saidi@ARM.com{
1739348SAli.Saidi@ARM.com}
17410036SAli.Saidi@ARM.com
1757893SN/Avoid
1768835SAli.Saidi@ARM.comAtomicSimpleCPU::serialize(ostream &os)
1779885Sstever@gmail.com{
1787893SN/A    SimObject::State so_state = SimObject::getState();
1797893SN/A    SERIALIZE_ENUM(so_state);
1807893SN/A    Status _status = status();
1818983Snate@binkert.org    SERIALIZE_ENUM(_status);
1827893SN/A    BaseSimpleCPU::serialize(os);
1839885Sstever@gmail.com    nameOut(os, csprintf("%s.tickEvent", name()));
1849885Sstever@gmail.com    tickEvent.serialize(os);
1859885Sstever@gmail.com}
1869885Sstever@gmail.com
1879885Sstever@gmail.comvoid
1889988Snilay@cs.wisc.eduAtomicSimpleCPU::unserialize(Checkpoint *cp, const string &section)
1899885Sstever@gmail.com{
19010036SAli.Saidi@ARM.com    SimObject::State so_state;
1919885Sstever@gmail.com    UNSERIALIZE_ENUM(so_state);
1929885Sstever@gmail.com    UNSERIALIZE_ENUM(_status);
1937893SN/A    BaseSimpleCPU::unserialize(cp, section);
1947893SN/A    tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
1958825Snilay@cs.wisc.edu}
1969988Snilay@cs.wisc.edu
1977893SN/Avoid
1988825Snilay@cs.wisc.eduAtomicSimpleCPU::resume()
1998825Snilay@cs.wisc.edu{
2008825Snilay@cs.wisc.edu    if (_status != SwitchedOut && _status != Idle) {
2018825Snilay@cs.wisc.edu        assert(system->getMemoryMode() == Enums::atomic);
2029885Sstever@gmail.com
2039988Snilay@cs.wisc.edu        changeState(SimObject::Running);
2049885Sstever@gmail.com        if (thread->status() == ThreadContext::Active) {
2058825Snilay@cs.wisc.edu            if (!tickEvent.scheduled()) {
2068983Snate@binkert.org                tickEvent.schedule(nextCycle());
2077893SN/A            }
2087893SN/A        }
2097893SN/A    }
2107893SN/A}
2117893SN/A
2129988Snilay@cs.wisc.eduvoid
2137893SN/AAtomicSimpleCPU::switchOut()
2147893SN/A{
2157893SN/A    assert(status() == Running || status() == Idle);
2167893SN/A    _status = SwitchedOut;
2177893SN/A
2189988Snilay@cs.wisc.edu    tickEvent.squash();
2197893SN/A}
2207893SN/A
2217893SN/A
2227893SN/Avoid
2239988Snilay@cs.wisc.eduAtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
2247893SN/A{
2257893SN/A    BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort);
22610901Snilay@cs.wisc.edu
2277893SN/A    assert(!tickEvent.scheduled());
2287893SN/A
2297893SN/A    // if any of this CPU's ThreadContexts are active, mark the CPU as
2307893SN/A    // running and schedule its tick event.
2317893SN/A    for (int i = 0; i < threadContexts.size(); ++i) {
2329988Snilay@cs.wisc.edu        ThreadContext *tc = threadContexts[i];
2337893SN/A        if (tc->status() == ThreadContext::Active && _status != Running) {
2347893SN/A            _status = Running;
2357893SN/A            tickEvent.schedule(nextCycle());
2367893SN/A            break;
2379988Snilay@cs.wisc.edu        }
2387893SN/A    }
2397893SN/A    if (_status != Running) {
24010901Snilay@cs.wisc.edu        _status = Idle;
2417893SN/A    }
2427893SN/A}
2437893SN/A
2449988Snilay@cs.wisc.edu
2457893SN/Avoid
24610901Snilay@cs.wisc.eduAtomicSimpleCPU::activateContext(int thread_num, int delay)
24710901Snilay@cs.wisc.edu{
2487893SN/A    assert(thread_num == 0);
2497893SN/A    assert(thread);
2507893SN/A
2517893SN/A    assert(_status == Idle);
2527893SN/A    assert(!tickEvent.scheduled());
2539988Snilay@cs.wisc.edu
2547893SN/A    notIdleFraction++;
2557893SN/A
2567893SN/A    //Make sure ticks are still on multiples of cycles
2577893SN/A    tickEvent.schedule(nextCycle(curTick + cycles(delay)));
2589988Snilay@cs.wisc.edu    _status = Running;
2597893SN/A}
2607893SN/A
26110901Snilay@cs.wisc.edu
2627893SN/Avoid
2637893SN/AAtomicSimpleCPU::suspendContext(int thread_num)
2647893SN/A{
2659988Snilay@cs.wisc.edu    assert(thread_num == 0);
2667893SN/A    assert(thread);
2677893SN/A
26810901Snilay@cs.wisc.edu    assert(_status == Running);
2697893SN/A
2707893SN/A    // tick event may not be scheduled if this gets called from inside
2717893SN/A    // an instruction's execution, e.g. "quiesce"
2729988Snilay@cs.wisc.edu    if (tickEvent.scheduled())
2737893SN/A        tickEvent.deschedule();
2747893SN/A
27510901Snilay@cs.wisc.edu    notIdleFraction--;
2767893SN/A    _status = Idle;
2777893SN/A}
2787893SN/A
2797893SN/A
2807893SN/Atemplate <class T>
2819988Snilay@cs.wisc.eduFault
2827893SN/AAtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
2837893SN/A{
2847893SN/A    // use the CPU's statically allocated read request and packet objects
2857893SN/A    Request *req = data_read_req;
2869988Snilay@cs.wisc.edu    PacketPtr pkt = data_read_pkt;
2877893SN/A
2887893SN/A    req->setVirt(0, addr, sizeof(T), flags, thread->readPC());
28910901Snilay@cs.wisc.edu
2907893SN/A    if (traceData) {
2917893SN/A        traceData->setAddr(addr);
2927893SN/A    }
2939988Snilay@cs.wisc.edu
2947893SN/A    // translate to physical address
2957893SN/A    Fault fault = thread->translateDataReadReq(req);
29610901Snilay@cs.wisc.edu
2977893SN/A    // Now do the access.
2987893SN/A    if (fault == NoFault) {
2997893SN/A        pkt->reinitFromRequest();
3009988Snilay@cs.wisc.edu
3017893SN/A        if (req->isMmapedIpr())
3027893SN/A            dcache_latency = TheISA::handleIprRead(thread->getTC(),pkt);
30310901Snilay@cs.wisc.edu        else
3047893SN/A            dcache_latency = dcachePort.sendAtomic(pkt);
3057893SN/A        dcache_access = true;
3067893SN/A#if !defined(NDEBUG)
3077893SN/A        if (pkt->result != Packet::Success)
3087893SN/A            panic("Unable to find responder for address pa = %#X va = %#X\n",
3099988Snilay@cs.wisc.edu                    pkt->req->getPaddr(), pkt->req->getVaddr());
3107893SN/A#endif
3117893SN/A        data = pkt->get<T>();
3127893SN/A
3137893SN/A        if (req->isLocked()) {
3149988Snilay@cs.wisc.edu            TheISA::handleLockedRead(thread, req);
3157893SN/A        }
3167893SN/A    }
31710901Snilay@cs.wisc.edu
3187893SN/A    // This will need a new way to tell if it has a dcache attached.
3197893SN/A    if (req->isUncacheable())
3207893SN/A        recordEvent("Uncached Read");
3217893SN/A
3227893SN/A    return fault;
3239988Snilay@cs.wisc.edu}
3247893SN/A
3257893SN/A#ifndef DOXYGEN_SHOULD_SKIP_THIS
3267893SN/A
3277893SN/Atemplate
3289988Snilay@cs.wisc.eduFault
3297893SN/AAtomicSimpleCPU::read(Addr addr, Twin32_t &data, unsigned flags);
3307893SN/A
33110901Snilay@cs.wisc.edutemplate
3327893SN/AFault
3337893SN/AAtomicSimpleCPU::read(Addr addr, Twin64_t &data, unsigned flags);
3347893SN/A
3359988Snilay@cs.wisc.edutemplate
3367893SN/AFault
3377893SN/AAtomicSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags);
33810901Snilay@cs.wisc.edu
3397893SN/Atemplate
3407893SN/AFault
3417893SN/AAtomicSimpleCPU::read(Addr addr, uint32_t &data, unsigned flags);
3429988Snilay@cs.wisc.edu
3437893SN/Atemplate
3447893SN/AFault
34510901Snilay@cs.wisc.eduAtomicSimpleCPU::read(Addr addr, uint16_t &data, unsigned flags);
3467893SN/A
3477893SN/Atemplate
3487893SN/AFault
3499988Snilay@cs.wisc.eduAtomicSimpleCPU::read(Addr addr, uint8_t &data, unsigned flags);
3507893SN/A
3517893SN/A#endif //DOXYGEN_SHOULD_SKIP_THIS
35210901Snilay@cs.wisc.edu
3537893SN/Atemplate<>
3547893SN/AFault
3557893SN/AAtomicSimpleCPU::read(Addr addr, double &data, unsigned flags)
3569988Snilay@cs.wisc.edu{
3577893SN/A    return read(addr, *(uint64_t*)&data, flags);
3587893SN/A}
35910901Snilay@cs.wisc.edu
3607893SN/Atemplate<>
3617893SN/AFault
3627893SN/AAtomicSimpleCPU::read(Addr addr, float &data, unsigned flags)
3639988Snilay@cs.wisc.edu{
3647893SN/A    return read(addr, *(uint32_t*)&data, flags);
3657893SN/A}
36610901Snilay@cs.wisc.edu
3677893SN/A
3687893SN/Atemplate<>
3697893SN/AFault
3709988Snilay@cs.wisc.eduAtomicSimpleCPU::read(Addr addr, int32_t &data, unsigned flags)
3717893SN/A{
3727893SN/A    return read(addr, (uint32_t&)data, flags);
37310901Snilay@cs.wisc.edu}
3747893SN/A
3757893SN/A
3767893SN/Atemplate <class T>
3779988Snilay@cs.wisc.eduFault
3787893SN/AAtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
3797893SN/A{
38010901Snilay@cs.wisc.edu    // use the CPU's statically allocated write request and packet objects
3817893SN/A    Request *req = data_write_req;
3827893SN/A    PacketPtr pkt;
3837893SN/A
3849988Snilay@cs.wisc.edu    req->setVirt(0, addr, sizeof(T), flags, thread->readPC());
3857893SN/A
3867893SN/A    if (req->isSwap())
38710901Snilay@cs.wisc.edu        pkt = data_swap_pkt;
3887893SN/A    else
3897893SN/A        pkt = data_write_pkt;
3907893SN/A
3919988Snilay@cs.wisc.edu    if (traceData) {
3927893SN/A        traceData->setAddr(addr);
3937893SN/A    }
39410901Snilay@cs.wisc.edu
3957893SN/A    // translate to physical address
3967893SN/A    Fault fault = thread->translateDataWriteReq(req);
3977893SN/A
3989988Snilay@cs.wisc.edu    // Now do the access.
3997893SN/A    if (fault == NoFault) {
4007893SN/A        bool do_access = true;  // flag to suppress cache access
40110901Snilay@cs.wisc.edu
4027893SN/A        if (req->isLocked()) {
4037893SN/A            do_access = TheISA::handleLockedWrite(thread, req);
4047893SN/A        }
4059988Snilay@cs.wisc.edu        if (req->isCondSwap()) {
4067893SN/A             assert(res);
4077893SN/A             req->setExtraData(*res);
40810901Snilay@cs.wisc.edu        }
4097893SN/A
4107893SN/A
4117893SN/A        if (do_access) {
4129988Snilay@cs.wisc.edu            pkt->reinitFromRequest();
4137893SN/A            pkt->dataStatic(&data);
4147893SN/A
41510901Snilay@cs.wisc.edu            if (req->isMmapedIpr()) {
4167893SN/A                dcache_latency = TheISA::handleIprWrite(thread->getTC(), pkt);
4177893SN/A            } else {
4187893SN/A                data = htog(data);
4199988Snilay@cs.wisc.edu                dcache_latency = dcachePort.sendAtomic(pkt);
4207893SN/A            }
4217893SN/A            dcache_access = true;
42210901Snilay@cs.wisc.edu
4237893SN/A#if !defined(NDEBUG)
4247893SN/A            if (pkt->result != Packet::Success)
4257893SN/A                panic("Unable to find responder for address pa = %#X va = %#X\n",
4269988Snilay@cs.wisc.edu                        pkt->req->getPaddr(), pkt->req->getVaddr());
4277893SN/A#endif
4287893SN/A        }
42910901Snilay@cs.wisc.edu
4307893SN/A        if (req->isSwap()) {
4317893SN/A            assert(res);
4327893SN/A            *res = pkt->get<T>();
4339988Snilay@cs.wisc.edu        } else if (res) {
4347893SN/A            *res = req->getExtraData();
4357893SN/A        }
43610901Snilay@cs.wisc.edu    }
4377893SN/A
4387893SN/A    // This will need a new way to tell if it's hooked up to a cache or not.
4397893SN/A    if (req->isUncacheable())
4409988Snilay@cs.wisc.edu        recordEvent("Uncached Write");
4417893SN/A
4427893SN/A    // If the write needs to have a fault on the access, consider calling
44310901Snilay@cs.wisc.edu    // changeStatus() and changing it to "bad addr write" or something.
4447893SN/A    return fault;
4457893SN/A}
4467893SN/A
4479988Snilay@cs.wisc.edu
4487893SN/A#ifndef DOXYGEN_SHOULD_SKIP_THIS
4497893SN/A
45010901Snilay@cs.wisc.edutemplate
4517893SN/AFault
4527893SN/AAtomicSimpleCPU::write(Twin32_t data, Addr addr,
4537893SN/A                       unsigned flags, uint64_t *res);
4549988Snilay@cs.wisc.edu
4557893SN/Atemplate
4567893SN/AFault
45710901Snilay@cs.wisc.eduAtomicSimpleCPU::write(Twin64_t data, Addr addr,
4587893SN/A                       unsigned flags, uint64_t *res);
4597893SN/A
4607893SN/Atemplate
4619988Snilay@cs.wisc.eduFault
4627893SN/AAtomicSimpleCPU::write(uint64_t data, Addr addr,
4637893SN/A                       unsigned flags, uint64_t *res);
46410901Snilay@cs.wisc.edu
4657893SN/Atemplate
4667893SN/AFault
4677893SN/AAtomicSimpleCPU::write(uint32_t data, Addr addr,
4687893SN/A                       unsigned flags, uint64_t *res);
4697893SN/A
4709988Snilay@cs.wisc.edutemplate
4717893SN/AFault
4727893SN/AAtomicSimpleCPU::write(uint16_t data, Addr addr,
4737893SN/A                       unsigned flags, uint64_t *res);
4747893SN/A
4759988Snilay@cs.wisc.edutemplate
4767893SN/AFault
4777893SN/AAtomicSimpleCPU::write(uint8_t data, Addr addr,
47810901Snilay@cs.wisc.edu                       unsigned flags, uint64_t *res);
4797893SN/A
4807893SN/A#endif //DOXYGEN_SHOULD_SKIP_THIS
4817893SN/A
4827893SN/Atemplate<>
4837893SN/AFault
4849988Snilay@cs.wisc.eduAtomicSimpleCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
4857893SN/A{
4867893SN/A    return write(*(uint64_t*)&data, addr, flags, res);
4877893SN/A}
4887893SN/A
4899988Snilay@cs.wisc.edutemplate<>
4907893SN/AFault
4917893SN/AAtomicSimpleCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
49210901Snilay@cs.wisc.edu{
4937893SN/A    return write(*(uint32_t*)&data, addr, flags, res);
4947893SN/A}
4957893SN/A
4969988Snilay@cs.wisc.edu
4977893SN/Atemplate<>
4987893SN/AFault
49910901Snilay@cs.wisc.eduAtomicSimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
5007893SN/A{
5017893SN/A    return write((uint32_t)data, addr, flags, res);
5027893SN/A}
5037893SN/A
5047893SN/A
5059988Snilay@cs.wisc.eduvoid
5067893SN/AAtomicSimpleCPU::tick()
5077893SN/A{
5087893SN/A    Tick latency = cycles(1); // instruction takes one cycle by default
5097893SN/A
5109988Snilay@cs.wisc.edu    for (int i = 0; i < width; ++i) {
5117893SN/A        numCycles++;
5127893SN/A
51310901Snilay@cs.wisc.edu        if (!curStaticInst || !curStaticInst->isDelayedCommit())
5147893SN/A            checkForInterrupts();
5157893SN/A
5167893SN/A        Fault fault = setupFetchRequest(ifetch_req);
5179885Sstever@gmail.com
5188983Snate@binkert.org        if (fault == NoFault) {
5197893SN/A            Tick icache_latency = 0;
5209885Sstever@gmail.com            bool icache_access = false;
52110645Snilay@cs.wisc.edu            dcache_access = false; // assume no dcache access
5229988Snilay@cs.wisc.edu
5237893SN/A            //Fetch more instruction memory if necessary
5249348SAli.Saidi@ARM.com            //if(predecoder.needMoreBytes())
52510901Snilay@cs.wisc.edu            //{
5267893SN/A                icache_access = true;
5279348SAli.Saidi@ARM.com                ifetch_pkt->reinitFromRequest();
5287893SN/A
5298835SAli.Saidi@ARM.com                icache_latency = icachePort.sendAtomic(ifetch_pkt);
5309348SAli.Saidi@ARM.com                // ifetch_req is initialized to read the instruction directly
53110036SAli.Saidi@ARM.com                // into the CPU object's inst field.
5327893SN/A            //}
5338835SAli.Saidi@ARM.com
5349885Sstever@gmail.com            preExecute();
5357893SN/A
5367893SN/A            if(curStaticInst)
5377893SN/A            {
5388983Snate@binkert.org                fault = curStaticInst->execute(this, traceData);
5397893SN/A                postExecute();
5409885Sstever@gmail.com            }
5419885Sstever@gmail.com
5429885Sstever@gmail.com            // @todo remove me after debugging with legion done
5439885Sstever@gmail.com            if (curStaticInst && (!curStaticInst->isMicroop() ||
5449885Sstever@gmail.com                        curStaticInst->isFirstMicroop()))
5459988Snilay@cs.wisc.edu                instCnt++;
5469885Sstever@gmail.com
54710036SAli.Saidi@ARM.com            if (simulate_stalls) {
5489885Sstever@gmail.com                Tick icache_stall =
5499885Sstever@gmail.com                    icache_access ? icache_latency - cycles(1) : 0;
5508825Snilay@cs.wisc.edu                Tick dcache_stall =
5518825Snilay@cs.wisc.edu                    dcache_access ? dcache_latency - cycles(1) : 0;
5529885Sstever@gmail.com                Tick stall_cycles = (icache_stall + dcache_stall) / cycles(1);
5539988Snilay@cs.wisc.edu                if (cycles(stall_cycles) < (icache_stall + dcache_stall))
5548825Snilay@cs.wisc.edu                    latency += cycles(stall_cycles+1);
5558825Snilay@cs.wisc.edu                else
5569213Snilay@cs.wisc.edu                    latency += cycles(stall_cycles);
5578825Snilay@cs.wisc.edu            }
5588983Snate@binkert.org
5598983Snate@binkert.org        }
5608983Snate@binkert.org        if(fault != NoFault || !stayAtPC)
5618825Snilay@cs.wisc.edu            advancePC(fault);
5629449SAli.Saidi@ARM.com    }
5639449SAli.Saidi@ARM.com
5649988Snilay@cs.wisc.edu    if (_status != Idle)
5659449SAli.Saidi@ARM.com        tickEvent.schedule(curTick + latency);
5667893SN/A}
5677893SN/A
5688825Snilay@cs.wisc.edu
5699988Snilay@cs.wisc.edu////////////////////////////////////////////////////////////////////////
5707893SN/A//
5718825Snilay@cs.wisc.edu//  AtomicSimpleCPU Simulation Object
5728825Snilay@cs.wisc.edu//
5738825Snilay@cs.wisc.eduAtomicSimpleCPU *
5748825Snilay@cs.wisc.eduAtomicSimpleCPUParams::create()
5759885Sstever@gmail.com{
5769988Snilay@cs.wisc.edu    AtomicSimpleCPU::Params *params = new AtomicSimpleCPU::Params();
5779885Sstever@gmail.com    params->name = name;
5788825Snilay@cs.wisc.edu    params->numberOfThreads = 1;
5798983Snate@binkert.org    params->max_insts_any_thread = max_insts_any_thread;
5807893SN/A    params->max_insts_all_threads = max_insts_all_threads;
5817893SN/A    params->max_loads_any_thread = max_loads_any_thread;
5827893SN/A    params->max_loads_all_threads = max_loads_all_threads;
5839885Sstever@gmail.com    params->progress_interval = progress_interval;
5848983Snate@binkert.org    params->deferRegistration = defer_registration;
5859348SAli.Saidi@ARM.com    params->phase = phase;
5869885Sstever@gmail.com    params->clock = clock;
58710645Snilay@cs.wisc.edu    params->functionTrace = function_trace;
5889988Snilay@cs.wisc.edu    params->functionTraceStart = function_trace_start;
5897893SN/A    params->width = width;
5909348SAli.Saidi@ARM.com    params->simulate_stalls = simulate_stalls;
59110901Snilay@cs.wisc.edu    params->system = system;
5927893SN/A    params->cpu_id = cpu_id;
5939348SAli.Saidi@ARM.com    params->tracer = tracer;
5947893SN/A
5958835SAli.Saidi@ARM.com#if FULL_SYSTEM
5969348SAli.Saidi@ARM.com    params->itb = itb;
59710036SAli.Saidi@ARM.com    params->dtb = dtb;
5987893SN/A    params->profile = profile;
5998835SAli.Saidi@ARM.com    params->do_quiesce = do_quiesce;
6009885Sstever@gmail.com    params->do_checkpoint_insts = do_checkpoint_insts;
6019348SAli.Saidi@ARM.com    params->do_statistics_insts = do_statistics_insts;
6027893SN/A#else
6038983Snate@binkert.org    if (workload.size() != 1)
6048983Snate@binkert.org        panic("only one workload allowed");
6057893SN/A    params->process = workload[0];
6069885Sstever@gmail.com#endif
6079885Sstever@gmail.com
6089885Sstever@gmail.com    AtomicSimpleCPU *cpu = new AtomicSimpleCPU(params);
6099885Sstever@gmail.com    return cpu;
6109885Sstever@gmail.com}
6119988Snilay@cs.wisc.edu