atomic.cc revision 2623
1955SN/A/*
2955SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan
311408Sandreas.sandberg@arm.com * All rights reserved.
49812Sandreas.hansson@arm.com *
59812Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
69812Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
79812Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
89812Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
99812Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
109812Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
119812Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
129812Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
139812Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
149812Sandreas.hansson@arm.com * this software without specific prior written permission.
157816Ssteve.reinhardt@amd.com *
165871Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171762SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26955SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27955SN/A */
28955SN/A
29955SN/A#include "arch/utility.hh"
30955SN/A#include "cpu/exetrace.hh"
31955SN/A#include "cpu/simple/atomic.hh"
32955SN/A#include "mem/packet_impl.hh"
33955SN/A#include "sim/builder.hh"
34955SN/A
35955SN/Ausing namespace std;
36955SN/Ausing namespace TheISA;
37955SN/A
38955SN/AAtomicSimpleCPU::TickEvent::TickEvent(AtomicSimpleCPU *c)
39955SN/A    : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c)
40955SN/A{
41955SN/A}
422665Ssaidi@eecs.umich.edu
432665Ssaidi@eecs.umich.edu
445863Snate@binkert.orgvoid
45955SN/AAtomicSimpleCPU::TickEvent::process()
46955SN/A{
47955SN/A    cpu->tick();
48955SN/A}
49955SN/A
508878Ssteve.reinhardt@amd.comconst char *
512632Sstever@eecs.umich.eduAtomicSimpleCPU::TickEvent::description()
528878Ssteve.reinhardt@amd.com{
532632Sstever@eecs.umich.edu    return "AtomicSimpleCPU tick event";
54955SN/A}
558878Ssteve.reinhardt@amd.com
562632Sstever@eecs.umich.edu
572761Sstever@eecs.umich.eduvoid
582632Sstever@eecs.umich.eduAtomicSimpleCPU::init()
592632Sstever@eecs.umich.edu{
602632Sstever@eecs.umich.edu    //Create Memory Ports (conect them up)
612761Sstever@eecs.umich.edu    Port *mem_dport = mem->getPort("");
622761Sstever@eecs.umich.edu    dcachePort.setPeer(mem_dport);
632761Sstever@eecs.umich.edu    mem_dport->setPeer(&dcachePort);
648878Ssteve.reinhardt@amd.com
658878Ssteve.reinhardt@amd.com    Port *mem_iport = mem->getPort("");
662761Sstever@eecs.umich.edu    icachePort.setPeer(mem_iport);
672761Sstever@eecs.umich.edu    mem_iport->setPeer(&icachePort);
682761Sstever@eecs.umich.edu
692761Sstever@eecs.umich.edu    BaseCPU::init();
702761Sstever@eecs.umich.edu#if FULL_SYSTEM
718878Ssteve.reinhardt@amd.com    for (int i = 0; i < execContexts.size(); ++i) {
728878Ssteve.reinhardt@amd.com        ExecContext *xc = execContexts[i];
732632Sstever@eecs.umich.edu
742632Sstever@eecs.umich.edu        // initialize CPU, including PC
758878Ssteve.reinhardt@amd.com        TheISA::initCPU(xc, xc->readCpuId());
768878Ssteve.reinhardt@amd.com    }
772632Sstever@eecs.umich.edu#endif
78955SN/A}
79955SN/A
80955SN/Abool
815863Snate@binkert.orgAtomicSimpleCPU::CpuPort::recvTiming(Packet &pkt)
825863Snate@binkert.org{
835863Snate@binkert.org    panic("AtomicSimpleCPU doesn't expect recvAtomic callback!");
845863Snate@binkert.org    return true;
855863Snate@binkert.org}
865863Snate@binkert.org
875863Snate@binkert.orgTick
885863Snate@binkert.orgAtomicSimpleCPU::CpuPort::recvAtomic(Packet &pkt)
895863Snate@binkert.org{
905863Snate@binkert.org    panic("AtomicSimpleCPU doesn't expect recvAtomic callback!");
915863Snate@binkert.org    return curTick;
928878Ssteve.reinhardt@amd.com}
935863Snate@binkert.org
945863Snate@binkert.orgvoid
955863Snate@binkert.orgAtomicSimpleCPU::CpuPort::recvFunctional(Packet &pkt)
969812Sandreas.hansson@arm.com{
979812Sandreas.hansson@arm.com    panic("AtomicSimpleCPU doesn't expect recvFunctional callback!");
985863Snate@binkert.org}
999812Sandreas.hansson@arm.com
1005863Snate@binkert.orgvoid
1015863Snate@binkert.orgAtomicSimpleCPU::CpuPort::recvStatusChange(Status status)
1025863Snate@binkert.org{
1039812Sandreas.hansson@arm.com    panic("AtomicSimpleCPU doesn't expect recvStatusChange callback!");
1049812Sandreas.hansson@arm.com}
1055863Snate@binkert.org
1065863Snate@binkert.orgPacket *
1078878Ssteve.reinhardt@amd.comAtomicSimpleCPU::CpuPort::recvRetry()
1085863Snate@binkert.org{
1095863Snate@binkert.org    panic("AtomicSimpleCPU doesn't expect recvRetry callback!");
1105863Snate@binkert.org    return NULL;
1116654Snate@binkert.org}
11210196SCurtis.Dunham@arm.com
113955SN/A
1145396Ssaidi@eecs.umich.eduAtomicSimpleCPU::AtomicSimpleCPU(Params *p)
11511401Sandreas.sandberg@arm.com    : BaseSimpleCPU(p), tickEvent(this),
1165863Snate@binkert.org      width(p->width), simulate_stalls(p->simulate_stalls),
1175863Snate@binkert.org      icachePort(this), dcachePort(this)
1184202Sbinkertn@umich.edu{
1195863Snate@binkert.org    _status = Idle;
1205863Snate@binkert.org
1215863Snate@binkert.org    ifetch_req = new Request(true);
1225863Snate@binkert.org    ifetch_req->setAsid(0);
123955SN/A    // @todo fix me and get the real cpu iD!!!
1246654Snate@binkert.org    ifetch_req->setCpuNum(0);
1255273Sstever@gmail.com    ifetch_req->setSize(sizeof(MachInst));
1265871Snate@binkert.org    ifetch_pkt = new Packet;
1275273Sstever@gmail.com    ifetch_pkt->cmd = Read;
1286655Snate@binkert.org    ifetch_pkt->dataStatic(&inst);
1298878Ssteve.reinhardt@amd.com    ifetch_pkt->req = ifetch_req;
1306655Snate@binkert.org    ifetch_pkt->size = sizeof(MachInst);
1316655Snate@binkert.org    ifetch_pkt->dest = Packet::Broadcast;
1329219Spower.jg@gmail.com
1336655Snate@binkert.org    data_read_req = new Request(true);
1345871Snate@binkert.org    // @todo fix me and get the real cpu iD!!!
1356654Snate@binkert.org    data_read_req->setCpuNum(0);
1368947Sandreas.hansson@arm.com    data_read_req->setAsid(0);
1375396Ssaidi@eecs.umich.edu    data_read_pkt = new Packet;
1388120Sgblack@eecs.umich.edu    data_read_pkt->cmd = Read;
1398120Sgblack@eecs.umich.edu    data_read_pkt->dataStatic(&dataReg);
1408120Sgblack@eecs.umich.edu    data_read_pkt->req = data_read_req;
1418120Sgblack@eecs.umich.edu    data_read_pkt->dest = Packet::Broadcast;
1428120Sgblack@eecs.umich.edu
1438120Sgblack@eecs.umich.edu    data_write_req = new Request(true);
1448120Sgblack@eecs.umich.edu    // @todo fix me and get the real cpu iD!!!
1458120Sgblack@eecs.umich.edu    data_write_req->setCpuNum(0);
1468879Ssteve.reinhardt@amd.com    data_write_req->setAsid(0);
1478879Ssteve.reinhardt@amd.com    data_write_pkt = new Packet;
1488879Ssteve.reinhardt@amd.com    data_write_pkt->cmd = Write;
1498879Ssteve.reinhardt@amd.com    data_write_pkt->req = data_write_req;
1508879Ssteve.reinhardt@amd.com    data_write_pkt->dest = Packet::Broadcast;
1518879Ssteve.reinhardt@amd.com}
1528879Ssteve.reinhardt@amd.com
1538879Ssteve.reinhardt@amd.com
1548879Ssteve.reinhardt@amd.comAtomicSimpleCPU::~AtomicSimpleCPU()
1558879Ssteve.reinhardt@amd.com{
1568879Ssteve.reinhardt@amd.com}
1578879Ssteve.reinhardt@amd.com
1588879Ssteve.reinhardt@amd.comvoid
1598120Sgblack@eecs.umich.eduAtomicSimpleCPU::serialize(ostream &os)
1608120Sgblack@eecs.umich.edu{
1618120Sgblack@eecs.umich.edu    BaseSimpleCPU::serialize(os);
1628120Sgblack@eecs.umich.edu    SERIALIZE_ENUM(_status);
1638120Sgblack@eecs.umich.edu    nameOut(os, csprintf("%s.tickEvent", name()));
1648120Sgblack@eecs.umich.edu    tickEvent.serialize(os);
1658120Sgblack@eecs.umich.edu}
1668120Sgblack@eecs.umich.edu
1678120Sgblack@eecs.umich.eduvoid
1688120Sgblack@eecs.umich.eduAtomicSimpleCPU::unserialize(Checkpoint *cp, const string &section)
1698120Sgblack@eecs.umich.edu{
1708120Sgblack@eecs.umich.edu    BaseSimpleCPU::unserialize(cp, section);
1718120Sgblack@eecs.umich.edu    UNSERIALIZE_ENUM(_status);
1728120Sgblack@eecs.umich.edu    tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
1738879Ssteve.reinhardt@amd.com}
1748879Ssteve.reinhardt@amd.com
1758879Ssteve.reinhardt@amd.comvoid
1768879Ssteve.reinhardt@amd.comAtomicSimpleCPU::switchOut(Sampler *s)
17710458Sandreas.hansson@arm.com{
17810458Sandreas.hansson@arm.com    sampler = s;
17910458Sandreas.hansson@arm.com    if (status() == Running) {
1808879Ssteve.reinhardt@amd.com        _status = SwitchedOut;
1818879Ssteve.reinhardt@amd.com
1828879Ssteve.reinhardt@amd.com        tickEvent.squash();
1838879Ssteve.reinhardt@amd.com    }
1849227Sandreas.hansson@arm.com    sampler->signalSwitched();
1859227Sandreas.hansson@arm.com}
1868879Ssteve.reinhardt@amd.com
1878879Ssteve.reinhardt@amd.com
1888879Ssteve.reinhardt@amd.comvoid
1898879Ssteve.reinhardt@amd.comAtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
19010453SAndrew.Bardsley@arm.com{
19110453SAndrew.Bardsley@arm.com    BaseCPU::takeOverFrom(oldCPU);
19210453SAndrew.Bardsley@arm.com
19310456SCurtis.Dunham@arm.com    assert(!tickEvent.scheduled());
19410456SCurtis.Dunham@arm.com
19510456SCurtis.Dunham@arm.com    // if any of this CPU's ExecContexts are active, mark the CPU as
19610457Sandreas.hansson@arm.com    // running and schedule its tick event.
19710457Sandreas.hansson@arm.com    for (int i = 0; i < execContexts.size(); ++i) {
19811342Sandreas.hansson@arm.com        ExecContext *xc = execContexts[i];
19911342Sandreas.hansson@arm.com        if (xc->status() == ExecContext::Active && _status != Running) {
2008120Sgblack@eecs.umich.edu            _status = Running;
2018947Sandreas.hansson@arm.com            tickEvent.schedule(curTick);
2027816Ssteve.reinhardt@amd.com            break;
2035871Snate@binkert.org        }
2045871Snate@binkert.org    }
2056121Snate@binkert.org}
2065871Snate@binkert.org
2075871Snate@binkert.org
2089926Sstan.czerniawski@arm.comvoid
2099926Sstan.czerniawski@arm.comAtomicSimpleCPU::activateContext(int thread_num, int delay)
2109119Sandreas.hansson@arm.com{
21110068Sandreas.hansson@arm.com    assert(thread_num == 0);
21210068Sandreas.hansson@arm.com    assert(cpuXC);
213955SN/A
2149416SAndreas.Sandberg@ARM.com    assert(_status == Idle);
21511342Sandreas.hansson@arm.com    assert(!tickEvent.scheduled());
21611212Sjoseph.gross@amd.com
21711212Sjoseph.gross@amd.com    notIdleFraction++;
21811212Sjoseph.gross@amd.com    tickEvent.schedule(curTick + cycles(delay));
21911212Sjoseph.gross@amd.com    _status = Running;
22011212Sjoseph.gross@amd.com}
2219416SAndreas.Sandberg@ARM.com
2229416SAndreas.Sandberg@ARM.com
2235871Snate@binkert.orgvoid
22410584Sandreas.hansson@arm.comAtomicSimpleCPU::suspendContext(int thread_num)
2259416SAndreas.Sandberg@ARM.com{
2269416SAndreas.Sandberg@ARM.com    assert(thread_num == 0);
2275871Snate@binkert.org    assert(cpuXC);
228955SN/A
22910671Sandreas.hansson@arm.com    assert(_status == Running);
23010671Sandreas.hansson@arm.com    assert(tickEvent.scheduled());
23110671Sandreas.hansson@arm.com
23210671Sandreas.hansson@arm.com    notIdleFraction--;
2338881Smarc.orr@gmail.com    tickEvent.deschedule();
2346121Snate@binkert.org    _status = Idle;
2356121Snate@binkert.org}
2361533SN/A
2379239Sandreas.hansson@arm.com
2389239Sandreas.hansson@arm.comtemplate <class T>
2399239Sandreas.hansson@arm.comFault
2409239Sandreas.hansson@arm.comAtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
2419239Sandreas.hansson@arm.com{
2429239Sandreas.hansson@arm.com    data_read_req->setVaddr(addr);
2439239Sandreas.hansson@arm.com    data_read_req->setSize(sizeof(T));
2449239Sandreas.hansson@arm.com    data_read_req->setFlags(flags);
2459239Sandreas.hansson@arm.com    data_read_req->setTime(curTick);
2469239Sandreas.hansson@arm.com
2479239Sandreas.hansson@arm.com    if (traceData) {
2489239Sandreas.hansson@arm.com        traceData->setAddr(addr);
2496655Snate@binkert.org    }
2506655Snate@binkert.org
2516655Snate@binkert.org    // translate to physical address
2526655Snate@binkert.org    Fault fault = cpuXC->translateDataReadReq(data_read_req);
2535871Snate@binkert.org
2545871Snate@binkert.org    // Now do the access.
2555863Snate@binkert.org    if (fault == NoFault) {
2565871Snate@binkert.org        data_read_pkt->reset();
2578878Ssteve.reinhardt@amd.com        data_read_pkt->addr = data_read_req->getPaddr();
2585871Snate@binkert.org        data_read_pkt->size = sizeof(T);
2595871Snate@binkert.org
2605871Snate@binkert.org        dcache_complete = dcachePort.sendAtomic(*data_read_pkt);
2615863Snate@binkert.org        dcache_access = true;
2626121Snate@binkert.org
26311408Sandreas.sandberg@arm.com        assert(data_read_pkt->result == Success);
2645863Snate@binkert.org        data = data_read_pkt->get<T>();
26511408Sandreas.sandberg@arm.com
26611408Sandreas.sandberg@arm.com    }
2678336Ssteve.reinhardt@amd.com
2688336Ssteve.reinhardt@amd.com    // This will need a new way to tell if it has a dcache attached.
26911408Sandreas.sandberg@arm.com    if (data_read_req->getFlags() & UNCACHEABLE)
2708336Ssteve.reinhardt@amd.com        recordEvent("Uncached Read");
2714678Snate@binkert.org
27211408Sandreas.sandberg@arm.com    return fault;
27311408Sandreas.sandberg@arm.com}
27411408Sandreas.sandberg@arm.com
27511401Sandreas.sandberg@arm.com#ifndef DOXYGEN_SHOULD_SKIP_THIS
27611401Sandreas.sandberg@arm.com
27711401Sandreas.sandberg@arm.comtemplate
27811401Sandreas.sandberg@arm.comFault
27911401Sandreas.sandberg@arm.comAtomicSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags);
28011401Sandreas.sandberg@arm.com
2818336Ssteve.reinhardt@amd.comtemplate
2828336Ssteve.reinhardt@amd.comFault
2838336Ssteve.reinhardt@amd.comAtomicSimpleCPU::read(Addr addr, uint32_t &data, unsigned flags);
2844678Snate@binkert.org
28511401Sandreas.sandberg@arm.comtemplate
2864678Snate@binkert.orgFault
2874678Snate@binkert.orgAtomicSimpleCPU::read(Addr addr, uint16_t &data, unsigned flags);
28811401Sandreas.sandberg@arm.com
28911401Sandreas.sandberg@arm.comtemplate
2908336Ssteve.reinhardt@amd.comFault
2914678Snate@binkert.orgAtomicSimpleCPU::read(Addr addr, uint8_t &data, unsigned flags);
2928336Ssteve.reinhardt@amd.com
2938336Ssteve.reinhardt@amd.com#endif //DOXYGEN_SHOULD_SKIP_THIS
2948336Ssteve.reinhardt@amd.com
2958336Ssteve.reinhardt@amd.comtemplate<>
2968336Ssteve.reinhardt@amd.comFault
2978336Ssteve.reinhardt@amd.comAtomicSimpleCPU::read(Addr addr, double &data, unsigned flags)
2985871Snate@binkert.org{
2995871Snate@binkert.org    return read(addr, *(uint64_t*)&data, flags);
3008336Ssteve.reinhardt@amd.com}
30111408Sandreas.sandberg@arm.com
30211408Sandreas.sandberg@arm.comtemplate<>
30311408Sandreas.sandberg@arm.comFault
30411408Sandreas.sandberg@arm.comAtomicSimpleCPU::read(Addr addr, float &data, unsigned flags)
30511408Sandreas.sandberg@arm.com{
30611408Sandreas.sandberg@arm.com    return read(addr, *(uint32_t*)&data, flags);
30711408Sandreas.sandberg@arm.com}
3088336Ssteve.reinhardt@amd.com
30911401Sandreas.sandberg@arm.com
31011401Sandreas.sandberg@arm.comtemplate<>
31111401Sandreas.sandberg@arm.comFault
3125871Snate@binkert.orgAtomicSimpleCPU::read(Addr addr, int32_t &data, unsigned flags)
3138336Ssteve.reinhardt@amd.com{
3148336Ssteve.reinhardt@amd.com    return read(addr, (uint32_t&)data, flags);
31511401Sandreas.sandberg@arm.com}
31611401Sandreas.sandberg@arm.com
31711401Sandreas.sandberg@arm.com
31811401Sandreas.sandberg@arm.comtemplate <class T>
31911401Sandreas.sandberg@arm.comFault
3204678Snate@binkert.orgAtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
3215871Snate@binkert.org{
3224678Snate@binkert.org    data_write_req->setVaddr(addr);
32311401Sandreas.sandberg@arm.com    data_write_req->setTime(curTick);
32411401Sandreas.sandberg@arm.com    data_write_req->setSize(sizeof(T));
32511401Sandreas.sandberg@arm.com    data_write_req->setFlags(flags);
32611401Sandreas.sandberg@arm.com
32711401Sandreas.sandberg@arm.com    if (traceData) {
32811401Sandreas.sandberg@arm.com        traceData->setAddr(addr);
32911401Sandreas.sandberg@arm.com    }
33011401Sandreas.sandberg@arm.com
33111401Sandreas.sandberg@arm.com    // translate to physical address
33211401Sandreas.sandberg@arm.com    Fault fault = cpuXC->translateDataWriteReq(data_write_req);
33311401Sandreas.sandberg@arm.com
33411401Sandreas.sandberg@arm.com    // Now do the access.
33511401Sandreas.sandberg@arm.com    if (fault == NoFault) {
33611401Sandreas.sandberg@arm.com        data_write_pkt->reset();
33711401Sandreas.sandberg@arm.com        data = htog(data);
33811401Sandreas.sandberg@arm.com        data_write_pkt->dataStatic(&data);
33911401Sandreas.sandberg@arm.com        data_write_pkt->addr = data_write_req->getPaddr();
34011401Sandreas.sandberg@arm.com        data_write_pkt->size = sizeof(T);
34111401Sandreas.sandberg@arm.com
34211401Sandreas.sandberg@arm.com        dcache_complete = dcachePort.sendAtomic(*data_write_pkt);
34311401Sandreas.sandberg@arm.com        dcache_access = true;
34411401Sandreas.sandberg@arm.com
34511401Sandreas.sandberg@arm.com        assert(data_write_pkt->result == Success);
34611401Sandreas.sandberg@arm.com    }
34711401Sandreas.sandberg@arm.com
34811401Sandreas.sandberg@arm.com    if (res && (fault == NoFault))
34911401Sandreas.sandberg@arm.com        *res = data_write_pkt->result;
35011401Sandreas.sandberg@arm.com
35111401Sandreas.sandberg@arm.com    // This will need a new way to tell if it's hooked up to a cache or not.
35211401Sandreas.sandberg@arm.com    if (data_write_req->getFlags() & UNCACHEABLE)
35311401Sandreas.sandberg@arm.com        recordEvent("Uncached Write");
35411401Sandreas.sandberg@arm.com
3558336Ssteve.reinhardt@amd.com    // @todo this is a hack and only works on uniprocessor systems
3568336Ssteve.reinhardt@amd.com    // some one else can implement LL/SC.
3578336Ssteve.reinhardt@amd.com    if (data_write_req->getFlags() & LOCKED)
3588336Ssteve.reinhardt@amd.com        *res = 1;
3598336Ssteve.reinhardt@amd.com
3608336Ssteve.reinhardt@amd.com    // If the write needs to have a fault on the access, consider calling
3618336Ssteve.reinhardt@amd.com    // changeStatus() and changing it to "bad addr write" or something.
3628336Ssteve.reinhardt@amd.com    return fault;
3638336Ssteve.reinhardt@amd.com}
3648336Ssteve.reinhardt@amd.com
36511401Sandreas.sandberg@arm.com
36611401Sandreas.sandberg@arm.com#ifndef DOXYGEN_SHOULD_SKIP_THIS
3678336Ssteve.reinhardt@amd.comtemplate
3688336Ssteve.reinhardt@amd.comFault
3698336Ssteve.reinhardt@amd.comAtomicSimpleCPU::write(uint64_t data, Addr addr,
3705871Snate@binkert.org                       unsigned flags, uint64_t *res);
37111408Sandreas.sandberg@arm.com
37211408Sandreas.sandberg@arm.comtemplate
37311408Sandreas.sandberg@arm.comFault
37411408Sandreas.sandberg@arm.comAtomicSimpleCPU::write(uint32_t data, Addr addr,
37511408Sandreas.sandberg@arm.com                       unsigned flags, uint64_t *res);
37611408Sandreas.sandberg@arm.com
37711408Sandreas.sandberg@arm.comtemplate
37811408Sandreas.sandberg@arm.comFault
37911408Sandreas.sandberg@arm.comAtomicSimpleCPU::write(uint16_t data, Addr addr,
38011408Sandreas.sandberg@arm.com                       unsigned flags, uint64_t *res);
38111408Sandreas.sandberg@arm.com
38211408Sandreas.sandberg@arm.comtemplate
38311408Sandreas.sandberg@arm.comFault
38411408Sandreas.sandberg@arm.comAtomicSimpleCPU::write(uint8_t data, Addr addr,
38511408Sandreas.sandberg@arm.com                       unsigned flags, uint64_t *res);
38611408Sandreas.sandberg@arm.com
38711408Sandreas.sandberg@arm.com#endif //DOXYGEN_SHOULD_SKIP_THIS
38811408Sandreas.sandberg@arm.com
38911408Sandreas.sandberg@arm.comtemplate<>
39011408Sandreas.sandberg@arm.comFault
39111408Sandreas.sandberg@arm.comAtomicSimpleCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
3926121Snate@binkert.org{
393955SN/A    return write(*(uint64_t*)&data, addr, flags, res);
394955SN/A}
3952632Sstever@eecs.umich.edu
3962632Sstever@eecs.umich.edutemplate<>
397955SN/AFault
398955SN/AAtomicSimpleCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
399955SN/A{
400955SN/A    return write(*(uint32_t*)&data, addr, flags, res);
4018878Ssteve.reinhardt@amd.com}
402955SN/A
4032632Sstever@eecs.umich.edu
4042632Sstever@eecs.umich.edutemplate<>
4052632Sstever@eecs.umich.eduFault
4062632Sstever@eecs.umich.eduAtomicSimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
4072632Sstever@eecs.umich.edu{
4082632Sstever@eecs.umich.edu    return write((uint32_t)data, addr, flags, res);
4092632Sstever@eecs.umich.edu}
4108268Ssteve.reinhardt@amd.com
4118268Ssteve.reinhardt@amd.com
4128268Ssteve.reinhardt@amd.comvoid
4138268Ssteve.reinhardt@amd.comAtomicSimpleCPU::tick()
4148268Ssteve.reinhardt@amd.com{
4158268Ssteve.reinhardt@amd.com    Tick latency = cycles(1); // instruction takes one cycle by default
4168268Ssteve.reinhardt@amd.com
4172632Sstever@eecs.umich.edu    for (int i = 0; i < width; ++i) {
4182632Sstever@eecs.umich.edu        numCycles++;
4192632Sstever@eecs.umich.edu
4202632Sstever@eecs.umich.edu        ifetch_req->resetMin();
4218268Ssteve.reinhardt@amd.com        ifetch_pkt->reset();
4222632Sstever@eecs.umich.edu        Fault fault = setupFetchPacket(ifetch_pkt);
4238268Ssteve.reinhardt@amd.com
4248268Ssteve.reinhardt@amd.com        if (fault == NoFault) {
4258268Ssteve.reinhardt@amd.com            Tick icache_complete = icachePort.sendAtomic(*ifetch_pkt);
4268268Ssteve.reinhardt@amd.com            // ifetch_req is initialized to read the instruction directly
4273718Sstever@eecs.umich.edu            // into the CPU object's inst field.
4282634Sstever@eecs.umich.edu
4292634Sstever@eecs.umich.edu            dcache_access = false; // assume no dcache access
4305863Snate@binkert.org            preExecute();
4312638Sstever@eecs.umich.edu            fault = curStaticInst->execute(this, traceData);
4328268Ssteve.reinhardt@amd.com            postExecute();
4332632Sstever@eecs.umich.edu
4342632Sstever@eecs.umich.edu            if (traceData) {
4352632Sstever@eecs.umich.edu                traceData->finalize();
4362632Sstever@eecs.umich.edu            }
4372632Sstever@eecs.umich.edu
4381858SN/A            if (simulate_stalls) {
4393716Sstever@eecs.umich.edu                // This calculation assumes that the icache and dcache
4402638Sstever@eecs.umich.edu                // access latencies are always a multiple of the CPU's
4412638Sstever@eecs.umich.edu                // cycle time.  If not, the next tick event may get
4422638Sstever@eecs.umich.edu                // scheduled at a non-integer multiple of the CPU
4432638Sstever@eecs.umich.edu                // cycle time.
4442638Sstever@eecs.umich.edu                Tick icache_stall = icache_complete - curTick - cycles(1);
4452638Sstever@eecs.umich.edu                Tick dcache_stall =
4462638Sstever@eecs.umich.edu                    dcache_access ? dcache_complete - curTick - cycles(1) : 0;
4475863Snate@binkert.org                latency += icache_stall + dcache_stall;
4485863Snate@binkert.org            }
4495863Snate@binkert.org
450955SN/A        }
4515341Sstever@gmail.com
4525341Sstever@gmail.com        advancePC(fault);
4535863Snate@binkert.org    }
4547756SAli.Saidi@ARM.com
4555341Sstever@gmail.com    tickEvent.schedule(curTick + latency);
4566121Snate@binkert.org}
4574494Ssaidi@eecs.umich.edu
4586121Snate@binkert.org
4591105SN/A////////////////////////////////////////////////////////////////////////
4602667Sstever@eecs.umich.edu//
4612667Sstever@eecs.umich.edu//  AtomicSimpleCPU Simulation Object
4622667Sstever@eecs.umich.edu//
4632667Sstever@eecs.umich.eduBEGIN_DECLARE_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
4646121Snate@binkert.org
4652667Sstever@eecs.umich.edu    Param<Counter> max_insts_any_thread;
4665341Sstever@gmail.com    Param<Counter> max_insts_all_threads;
4675863Snate@binkert.org    Param<Counter> max_loads_any_thread;
4685341Sstever@gmail.com    Param<Counter> max_loads_all_threads;
4695341Sstever@gmail.com    SimObjectParam<MemObject *> mem;
4705341Sstever@gmail.com
4718120Sgblack@eecs.umich.edu#if FULL_SYSTEM
4725341Sstever@gmail.com    SimObjectParam<AlphaITB *> itb;
4738120Sgblack@eecs.umich.edu    SimObjectParam<AlphaDTB *> dtb;
4745341Sstever@gmail.com    SimObjectParam<System *> system;
4758120Sgblack@eecs.umich.edu    Param<int> cpu_id;
4766121Snate@binkert.org    Param<Tick> profile;
4776121Snate@binkert.org#else
4788980Ssteve.reinhardt@amd.com    SimObjectParam<Process *> workload;
4799396Sandreas.hansson@arm.com#endif // FULL_SYSTEM
4805397Ssaidi@eecs.umich.edu
4815397Ssaidi@eecs.umich.edu    Param<int> clock;
4827727SAli.Saidi@ARM.com
4838268Ssteve.reinhardt@amd.com    Param<bool> defer_registration;
4846168Snate@binkert.org    Param<int> width;
4855341Sstever@gmail.com    Param<bool> function_trace;
4868120Sgblack@eecs.umich.edu    Param<Tick> function_trace_start;
4878120Sgblack@eecs.umich.edu    Param<bool> simulate_stalls;
4888120Sgblack@eecs.umich.edu
4896814Sgblack@eecs.umich.eduEND_DECLARE_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
4905863Snate@binkert.org
4918120Sgblack@eecs.umich.eduBEGIN_INIT_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
4925341Sstever@gmail.com
4935863Snate@binkert.org    INIT_PARAM(max_insts_any_thread,
4948268Ssteve.reinhardt@amd.com               "terminate when any thread reaches this inst count"),
4956121Snate@binkert.org    INIT_PARAM(max_insts_all_threads,
4966121Snate@binkert.org               "terminate when all threads have reached this inst count"),
4978268Ssteve.reinhardt@amd.com    INIT_PARAM(max_loads_any_thread,
4985742Snate@binkert.org               "terminate when any thread reaches this load count"),
4995742Snate@binkert.org    INIT_PARAM(max_loads_all_threads,
5005341Sstever@gmail.com               "terminate when all threads have reached this load count"),
5015742Snate@binkert.org    INIT_PARAM(mem, "memory"),
5025742Snate@binkert.org
5035341Sstever@gmail.com#if FULL_SYSTEM
5046017Snate@binkert.org    INIT_PARAM(itb, "Instruction TLB"),
5056121Snate@binkert.org    INIT_PARAM(dtb, "Data TLB"),
5066017Snate@binkert.org    INIT_PARAM(system, "system object"),
5077816Ssteve.reinhardt@amd.com    INIT_PARAM(cpu_id, "processor ID"),
5087756SAli.Saidi@ARM.com    INIT_PARAM(profile, ""),
5097756SAli.Saidi@ARM.com#else
5107756SAli.Saidi@ARM.com    INIT_PARAM(workload, "processes to run"),
5117756SAli.Saidi@ARM.com#endif // FULL_SYSTEM
5127756SAli.Saidi@ARM.com
5137756SAli.Saidi@ARM.com    INIT_PARAM(clock, "clock speed"),
5147756SAli.Saidi@ARM.com    INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
5157756SAli.Saidi@ARM.com    INIT_PARAM(width, "cpu width"),
5167816Ssteve.reinhardt@amd.com    INIT_PARAM(function_trace, "Enable function trace"),
5177816Ssteve.reinhardt@amd.com    INIT_PARAM(function_trace_start, "Cycle to start function trace"),
5187816Ssteve.reinhardt@amd.com    INIT_PARAM(simulate_stalls, "Simulate cache stall cycles")
5197816Ssteve.reinhardt@amd.com
5207816Ssteve.reinhardt@amd.comEND_INIT_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
5217816Ssteve.reinhardt@amd.com
5227816Ssteve.reinhardt@amd.com
5237816Ssteve.reinhardt@amd.comCREATE_SIM_OBJECT(AtomicSimpleCPU)
5247816Ssteve.reinhardt@amd.com{
5257816Ssteve.reinhardt@amd.com    AtomicSimpleCPU::Params *params = new AtomicSimpleCPU::Params();
5267756SAli.Saidi@ARM.com    params->name = getInstanceName();
5277816Ssteve.reinhardt@amd.com    params->numberOfThreads = 1;
5287816Ssteve.reinhardt@amd.com    params->max_insts_any_thread = max_insts_any_thread;
5297816Ssteve.reinhardt@amd.com    params->max_insts_all_threads = max_insts_all_threads;
5307816Ssteve.reinhardt@amd.com    params->max_loads_any_thread = max_loads_any_thread;
5317816Ssteve.reinhardt@amd.com    params->max_loads_all_threads = max_loads_all_threads;
5327816Ssteve.reinhardt@amd.com    params->deferRegistration = defer_registration;
5337816Ssteve.reinhardt@amd.com    params->clock = clock;
5347816Ssteve.reinhardt@amd.com    params->functionTrace = function_trace;
5357816Ssteve.reinhardt@amd.com    params->functionTraceStart = function_trace_start;
5367816Ssteve.reinhardt@amd.com    params->width = width;
5377816Ssteve.reinhardt@amd.com    params->simulate_stalls = simulate_stalls;
5387816Ssteve.reinhardt@amd.com    params->mem = mem;
5397816Ssteve.reinhardt@amd.com
5407816Ssteve.reinhardt@amd.com#if FULL_SYSTEM
5417816Ssteve.reinhardt@amd.com    params->itb = itb;
5427816Ssteve.reinhardt@amd.com    params->dtb = dtb;
5437816Ssteve.reinhardt@amd.com    params->system = system;
5447816Ssteve.reinhardt@amd.com    params->cpu_id = cpu_id;
5457816Ssteve.reinhardt@amd.com    params->profile = profile;
5467816Ssteve.reinhardt@amd.com#else
5477816Ssteve.reinhardt@amd.com    params->process = workload;
5487816Ssteve.reinhardt@amd.com#endif
5497816Ssteve.reinhardt@amd.com
5507816Ssteve.reinhardt@amd.com    AtomicSimpleCPU *cpu = new AtomicSimpleCPU(params);
5517816Ssteve.reinhardt@amd.com    return cpu;
5527816Ssteve.reinhardt@amd.com}
5537816Ssteve.reinhardt@amd.com
5547816Ssteve.reinhardt@amd.comREGISTER_SIM_OBJECT("AtomicSimpleCPU", AtomicSimpleCPU)
5557816Ssteve.reinhardt@amd.com
5567816Ssteve.reinhardt@amd.com