atomic.cc revision 2631
12381SN/A/*
213732Snikos.nikoleris@arm.com * Copyright (c) 2002-2005 The Regents of The University of Michigan
38949Sandreas.hansson@arm.com * All rights reserved.
48949Sandreas.hansson@arm.com *
58949Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
68949Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
78949Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
88949Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
98949Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
108949Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
118949Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
128949Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
138949Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
142592SN/A * this software without specific prior written permission.
1510975Sdavid.hashe@amd.com *
162381SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172381SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182381SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192381SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202381SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212381SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222381SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232381SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242381SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252381SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262381SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272381SN/A */
282381SN/A
292381SN/A#include "arch/utility.hh"
302381SN/A#include "cpu/exetrace.hh"
312381SN/A#include "cpu/simple/atomic.hh"
322381SN/A#include "mem/packet_impl.hh"
332381SN/A#include "sim/builder.hh"
342381SN/A
352381SN/Ausing namespace std;
362381SN/Ausing namespace TheISA;
372381SN/A
382381SN/AAtomicSimpleCPU::TickEvent::TickEvent(AtomicSimpleCPU *c)
392381SN/A    : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c)
402665Ssaidi@eecs.umich.edu{
412665Ssaidi@eecs.umich.edu}
422665Ssaidi@eecs.umich.edu
432665Ssaidi@eecs.umich.edu
449031Sandreas.hansson@arm.comvoid
4512349Snikos.nikoleris@arm.comAtomicSimpleCPU::TickEvent::process()
462381SN/A{
472381SN/A    cpu->tick();
482381SN/A}
492381SN/A
502662Sstever@eecs.umich.educonst char *
512381SN/AAtomicSimpleCPU::TickEvent::description()
522381SN/A{
532381SN/A    return "AtomicSimpleCPU tick event";
542381SN/A}
552381SN/A
568229Snate@binkert.org
573348Sbinkertn@umich.eduvoid
583348Sbinkertn@umich.eduAtomicSimpleCPU::init()
593348Sbinkertn@umich.edu{
6013856Sodanrc@yahoo.com.br    //Create Memory Ports (conect them up)
615735Snate@binkert.org    Port *mem_dport = mem->getPort("");
624024Sbinkertn@umich.edu    dcachePort.setPeer(mem_dport);
635735Snate@binkert.org    mem_dport->setPeer(&dcachePort);
6412334Sgabeblack@google.com
655314Sstever@gmail.com    Port *mem_iport = mem->getPort("");
666216Snate@binkert.org    icachePort.setPeer(mem_iport);
6713347Sgabeblack@google.com    mem_iport->setPeer(&icachePort);
682392SN/A
694167Sbinkertn@umich.edu    BaseCPU::init();
702394SN/A#if FULL_SYSTEM
718737Skoansin.tan@gmail.com    for (int i = 0; i < execContexts.size(); ++i) {
723349Sbinkertn@umich.edu        ExecContext *xc = execContexts[i];
732394SN/A
742812Srdreslin@umich.edu        // initialize CPU, including PC
7512351Snikos.nikoleris@arm.com        TheISA::initCPU(xc, xc->readCpuId());
762812Srdreslin@umich.edu    }
774022Sstever@eecs.umich.edu#endif
784022Sstever@eecs.umich.edu}
795735Snate@binkert.org
805735Snate@binkert.orgbool
814022Sstever@eecs.umich.eduAtomicSimpleCPU::CpuPort::recvTiming(Packet *pkt)
825735Snate@binkert.org{
835735Snate@binkert.org    panic("AtomicSimpleCPU doesn't expect recvAtomic callback!");
845735Snate@binkert.org    return true;
854022Sstever@eecs.umich.edu}
864022Sstever@eecs.umich.edu
874022Sstever@eecs.umich.eduTick
884022Sstever@eecs.umich.eduAtomicSimpleCPU::CpuPort::recvAtomic(Packet *pkt)
894473Sstever@eecs.umich.edu{
905319Sstever@gmail.com    panic("AtomicSimpleCPU doesn't expect recvAtomic callback!");
914022Sstever@eecs.umich.edu    return curTick;
924022Sstever@eecs.umich.edu}
9311199Sandreas.hansson@arm.com
9411199Sandreas.hansson@arm.comvoid
9512344Snikos.nikoleris@arm.comAtomicSimpleCPU::CpuPort::recvFunctional(Packet *pkt)
9610883Sali.jafri@arm.com{
974022Sstever@eecs.umich.edu    panic("AtomicSimpleCPU doesn't expect recvFunctional callback!");
9813367Syuetsu.kodama@riken.jp}
994022Sstever@eecs.umich.edu
1004022Sstever@eecs.umich.eduvoid
1014022Sstever@eecs.umich.eduAtomicSimpleCPU::CpuPort::recvStatusChange(Status status)
10210886Sandreas.hansson@arm.com{
1034022Sstever@eecs.umich.edu    if (status == RangeChange)
1047465Ssteve.reinhardt@amd.com        return;
1054628Sstever@eecs.umich.edu
1067465Ssteve.reinhardt@amd.com    panic("AtomicSimpleCPU doesn't expect recvStatusChange callback!");
1077465Ssteve.reinhardt@amd.com}
1084022Sstever@eecs.umich.edu
1094022Sstever@eecs.umich.eduPacket *
11010885Sandreas.hansson@arm.comAtomicSimpleCPU::CpuPort::recvRetry()
11110885Sandreas.hansson@arm.com{
1124626Sstever@eecs.umich.edu    panic("AtomicSimpleCPU doesn't expect recvRetry callback!");
1134626Sstever@eecs.umich.edu    return NULL;
1147669Ssteve.reinhardt@amd.com}
1154626Sstever@eecs.umich.edu
1164040Ssaidi@eecs.umich.edu
1174040Ssaidi@eecs.umich.eduAtomicSimpleCPU::AtomicSimpleCPU(Params *p)
1185650Sgblack@eecs.umich.edu    : BaseSimpleCPU(p), tickEvent(this),
1195650Sgblack@eecs.umich.edu      width(p->width), simulate_stalls(p->simulate_stalls),
12011256Santhony.gutierrez@amd.com      icachePort(this), dcachePort(this)
12111256Santhony.gutierrez@amd.com{
12212347Snikos.nikoleris@arm.com    _status = Idle;
12312347Snikos.nikoleris@arm.com
12412347Snikos.nikoleris@arm.com    ifetch_req = new Request(true);
12512347Snikos.nikoleris@arm.com    ifetch_req->setAsid(0);
1264870Sstever@eecs.umich.edu    // @todo fix me and get the real cpu iD!!!
1274870Sstever@eecs.umich.edu    ifetch_req->setCpuNum(0);
1284870Sstever@eecs.umich.edu    ifetch_req->setSize(sizeof(MachInst));
1294870Sstever@eecs.umich.edu    ifetch_pkt = new Packet;
1304870Sstever@eecs.umich.edu    ifetch_pkt->cmd = Read;
1314870Sstever@eecs.umich.edu    ifetch_pkt->dataStatic(&inst);
1328436SBrad.Beckmann@amd.com    ifetch_pkt->req = ifetch_req;
1338436SBrad.Beckmann@amd.com    ifetch_pkt->size = sizeof(MachInst);
1345314Sstever@gmail.com    ifetch_pkt->dest = Packet::Broadcast;
1355314Sstever@gmail.com
1368184Ssomayeh@cs.wisc.edu    data_read_req = new Request(true);
13710886Sandreas.hansson@arm.com    // @todo fix me and get the real cpu iD!!!
13810886Sandreas.hansson@arm.com    data_read_req->setCpuNum(0);
1394022Sstever@eecs.umich.edu    data_read_req->setAsid(0);
1404022Sstever@eecs.umich.edu    data_read_pkt = new Packet;
1414022Sstever@eecs.umich.edu    data_read_pkt->cmd = Read;
1424022Sstever@eecs.umich.edu    data_read_pkt->dataStatic(&dataReg);
1435735Snate@binkert.org    data_read_pkt->req = data_read_req;
1445735Snate@binkert.org    data_read_pkt->dest = Packet::Broadcast;
1455735Snate@binkert.org
1464022Sstever@eecs.umich.edu    data_write_req = new Request(true);
1474022Sstever@eecs.umich.edu    // @todo fix me and get the real cpu iD!!!
1484626Sstever@eecs.umich.edu    data_write_req->setCpuNum(0);
1494626Sstever@eecs.umich.edu    data_write_req->setAsid(0);
1507465Ssteve.reinhardt@amd.com    data_write_pkt = new Packet;
1514022Sstever@eecs.umich.edu    data_write_pkt->cmd = Write;
15212347Snikos.nikoleris@arm.com    data_write_pkt->req = data_write_req;
15311284Sandreas.hansson@arm.com    data_write_pkt->dest = Packet::Broadcast;
1544626Sstever@eecs.umich.edu}
1554626Sstever@eecs.umich.edu
1564626Sstever@eecs.umich.edu
15711199Sandreas.hansson@arm.comAtomicSimpleCPU::~AtomicSimpleCPU()
1584022Sstever@eecs.umich.edu{
1594022Sstever@eecs.umich.edu}
1606076Sgblack@eecs.umich.edu
1614626Sstever@eecs.umich.eduvoid
1624870Sstever@eecs.umich.eduAtomicSimpleCPU::serialize(ostream &os)
1635314Sstever@gmail.com{
1648184Ssomayeh@cs.wisc.edu    BaseSimpleCPU::serialize(os);
16511600Sandreas.hansson@arm.com    SERIALIZE_ENUM(_status);
1664022Sstever@eecs.umich.edu    nameOut(os, csprintf("%s.tickEvent", name()));
1674022Sstever@eecs.umich.edu    tickEvent.serialize(os);
1684022Sstever@eecs.umich.edu}
1695735Snate@binkert.org
1705735Snate@binkert.orgvoid
1715735Snate@binkert.orgAtomicSimpleCPU::unserialize(Checkpoint *cp, const string &section)
1725735Snate@binkert.org{
1735735Snate@binkert.org    BaseSimpleCPU::unserialize(cp, section);
1745735Snate@binkert.org    UNSERIALIZE_ENUM(_status);
1755735Snate@binkert.org    tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
1764022Sstever@eecs.umich.edu}
1775735Snate@binkert.org
1785735Snate@binkert.orgvoid
1794022Sstever@eecs.umich.eduAtomicSimpleCPU::switchOut(Sampler *s)
1805735Snate@binkert.org{
1814022Sstever@eecs.umich.edu    sampler = s;
1824022Sstever@eecs.umich.edu    if (status() == Running) {
1834022Sstever@eecs.umich.edu        _status = SwitchedOut;
1845735Snate@binkert.org
1854022Sstever@eecs.umich.edu        tickEvent.squash();
1864022Sstever@eecs.umich.edu    }
1874022Sstever@eecs.umich.edu    sampler->signalSwitched();
1884022Sstever@eecs.umich.edu}
1894022Sstever@eecs.umich.edu
1904022Sstever@eecs.umich.edu
1915735Snate@binkert.orgvoid
1925735Snate@binkert.orgAtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
1935735Snate@binkert.org{
1944022Sstever@eecs.umich.edu    BaseCPU::takeOverFrom(oldCPU);
1954022Sstever@eecs.umich.edu
1964022Sstever@eecs.umich.edu    assert(!tickEvent.scheduled());
1974022Sstever@eecs.umich.edu
1984022Sstever@eecs.umich.edu    // if any of this CPU's ExecContexts are active, mark the CPU as
19910583SCurtis.Dunham@arm.com    // running and schedule its tick event.
20010583SCurtis.Dunham@arm.com    for (int i = 0; i < execContexts.size(); ++i) {
20110583SCurtis.Dunham@arm.com        ExecContext *xc = execContexts[i];
20210583SCurtis.Dunham@arm.com        if (xc->status() == ExecContext::Active && _status != Running) {
20310583SCurtis.Dunham@arm.com            _status = Running;
20411284Sandreas.hansson@arm.com            tickEvent.schedule(curTick);
20510583SCurtis.Dunham@arm.com            break;
20610583SCurtis.Dunham@arm.com        }
20711199Sandreas.hansson@arm.com    }
20812347Snikos.nikoleris@arm.com}
20911600Sandreas.hansson@arm.com
21011199Sandreas.hansson@arm.com
21111199Sandreas.hansson@arm.comvoid
21211199Sandreas.hansson@arm.comAtomicSimpleCPU::activateContext(int thread_num, int delay)
21311199Sandreas.hansson@arm.com{
21411199Sandreas.hansson@arm.com    assert(thread_num == 0);
21511199Sandreas.hansson@arm.com    assert(cpuXC);
21610570Sandreas.hansson@arm.com
21710570Sandreas.hansson@arm.com    assert(_status == Idle);
21810570Sandreas.hansson@arm.com    assert(!tickEvent.scheduled());
21910570Sandreas.hansson@arm.com
22010570Sandreas.hansson@arm.com    notIdleFraction++;
22110570Sandreas.hansson@arm.com    tickEvent.schedule(curTick + cycles(delay));
2224022Sstever@eecs.umich.edu    _status = Running;
2236102Sgblack@eecs.umich.edu}
22410343SCurtis.Dunham@arm.com
22510343SCurtis.Dunham@arm.com
22610343SCurtis.Dunham@arm.comvoid
22710343SCurtis.Dunham@arm.comAtomicSimpleCPU::suspendContext(int thread_num)
2284870Sstever@eecs.umich.edu{
2295314Sstever@gmail.com    assert(thread_num == 0);
2308184Ssomayeh@cs.wisc.edu    assert(cpuXC);
2314022Sstever@eecs.umich.edu
23211294Sandreas.hansson@arm.com    assert(_status == Running);
2335735Snate@binkert.org
2345735Snate@binkert.org    // tick event may not be scheduled if this gets called from inside
2354022Sstever@eecs.umich.edu    // an instruction's execution, e.g. "quiesce"
2364022Sstever@eecs.umich.edu    if (tickEvent.scheduled())
2374022Sstever@eecs.umich.edu        tickEvent.deschedule();
2385735Snate@binkert.org
2395735Snate@binkert.org    notIdleFraction--;
2404022Sstever@eecs.umich.edu    _status = Idle;
2414022Sstever@eecs.umich.edu}
2425735Snate@binkert.org
2435735Snate@binkert.org
2445735Snate@binkert.orgtemplate <class T>
2454022Sstever@eecs.umich.eduFault
2465735Snate@binkert.orgAtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
2475735Snate@binkert.org{
2484022Sstever@eecs.umich.edu    data_read_req->setVaddr(addr);
2494022Sstever@eecs.umich.edu    data_read_req->setSize(sizeof(T));
2502381SN/A    data_read_req->setFlags(flags);
2512662Sstever@eecs.umich.edu    data_read_req->setTime(curTick);
2522662Sstever@eecs.umich.edu
2532662Sstever@eecs.umich.edu    if (traceData) {
2542662Sstever@eecs.umich.edu        traceData->setAddr(addr);
2552662Sstever@eecs.umich.edu    }
2562381SN/A
2579044SAli.Saidi@ARM.com    // translate to physical address
2582381SN/A    Fault fault = cpuXC->translateDataReadReq(data_read_req);
2592813Srdreslin@umich.edu
2605735Snate@binkert.org    // Now do the access.
2615735Snate@binkert.org    if (fault == NoFault) {
2624022Sstever@eecs.umich.edu        data_read_pkt->reset();
2635735Snate@binkert.org        data_read_pkt->addr = data_read_req->getPaddr();
2645735Snate@binkert.org        data_read_pkt->size = sizeof(T);
26510938Sandreas.hansson@arm.com
26610938Sandreas.hansson@arm.com        dcache_complete = dcachePort.sendAtomic(data_read_pkt);
26712349Snikos.nikoleris@arm.com        dcache_access = true;
26810938Sandreas.hansson@arm.com
26913732Snikos.nikoleris@arm.com        assert(data_read_pkt->result == Success);
27013732Snikos.nikoleris@arm.com        data = data_read_pkt->get<T>();
27113732Snikos.nikoleris@arm.com
27211284Sandreas.hansson@arm.com    }
27311284Sandreas.hansson@arm.com
27411284Sandreas.hansson@arm.com    // This will need a new way to tell if it has a dcache attached.
27511284Sandreas.hansson@arm.com    if (data_read_req->getFlags() & UNCACHEABLE)
27610938Sandreas.hansson@arm.com        recordEvent("Uncached Read");
27710938Sandreas.hansson@arm.com
27810938Sandreas.hansson@arm.com    return fault;
27911284Sandreas.hansson@arm.com}
28011284Sandreas.hansson@arm.com
28111284Sandreas.hansson@arm.com#ifndef DOXYGEN_SHOULD_SKIP_THIS
28211284Sandreas.hansson@arm.com
28311284Sandreas.hansson@arm.comtemplate
28411284Sandreas.hansson@arm.comFault
28511284Sandreas.hansson@arm.comAtomicSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags);
28611284Sandreas.hansson@arm.com
28711284Sandreas.hansson@arm.comtemplate
28810938Sandreas.hansson@arm.comFault
28912346Snikos.nikoleris@arm.comAtomicSimpleCPU::read(Addr addr, uint32_t &data, unsigned flags);
29012346Snikos.nikoleris@arm.com
29112346Snikos.nikoleris@arm.comtemplate
29212346Snikos.nikoleris@arm.comFault
29312349Snikos.nikoleris@arm.comAtomicSimpleCPU::read(Addr addr, uint16_t &data, unsigned flags);
29412349Snikos.nikoleris@arm.com
29512349Snikos.nikoleris@arm.comtemplate
29612349Snikos.nikoleris@arm.comFault
29711057Sandreas.hansson@arm.comAtomicSimpleCPU::read(Addr addr, uint8_t &data, unsigned flags);
29811057Sandreas.hansson@arm.com
29911057Sandreas.hansson@arm.com#endif //DOXYGEN_SHOULD_SKIP_THIS
30011057Sandreas.hansson@arm.com
30110938Sandreas.hansson@arm.comtemplate<>
30210938Sandreas.hansson@arm.comFault
30310938Sandreas.hansson@arm.comAtomicSimpleCPU::read(Addr addr, double &data, unsigned flags)
30410938Sandreas.hansson@arm.com{
30510938Sandreas.hansson@arm.com    return read(addr, *(uint64_t*)&data, flags);
30610938Sandreas.hansson@arm.com}
30710938Sandreas.hansson@arm.com
30810938Sandreas.hansson@arm.comtemplate<>
30910938Sandreas.hansson@arm.comFault
31010938Sandreas.hansson@arm.comAtomicSimpleCPU::read(Addr addr, float &data, unsigned flags)
31110938Sandreas.hansson@arm.com{
31210938Sandreas.hansson@arm.com    return read(addr, *(uint32_t*)&data, flags);
31310938Sandreas.hansson@arm.com}
31410938Sandreas.hansson@arm.com
31510938Sandreas.hansson@arm.com
31610938Sandreas.hansson@arm.comtemplate<>
3175735Snate@binkert.orgFault
3185735Snate@binkert.orgAtomicSimpleCPU::read(Addr addr, int32_t &data, unsigned flags)
3195735Snate@binkert.org{
3205735Snate@binkert.org    return read(addr, (uint32_t&)data, flags);
3214022Sstever@eecs.umich.edu}
3224022Sstever@eecs.umich.edu
3235735Snate@binkert.org
3244870Sstever@eecs.umich.edutemplate <class T>
3254870Sstever@eecs.umich.eduFault
32612351Snikos.nikoleris@arm.comAtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
32712351Snikos.nikoleris@arm.com{
3285735Snate@binkert.org    data_write_req->setVaddr(addr);
32912749Sgiacomo.travaglini@arm.com    data_write_req->setTime(curTick);
3304870Sstever@eecs.umich.edu    data_write_req->setSize(sizeof(T));
3312566SN/A    data_write_req->setFlags(flags);
3325735Snate@binkert.org
33312633Sodanrc@yahoo.com.br    if (traceData) {
33412633Sodanrc@yahoo.com.br        traceData->setAddr(addr);
3355735Snate@binkert.org    }
33612633Sodanrc@yahoo.com.br
3375735Snate@binkert.org    // translate to physical address
3382566SN/A    Fault fault = cpuXC->translateDataWriteReq(data_write_req);
3392566SN/A
3402566SN/A    // Now do the access.
3415735Snate@binkert.org    if (fault == NoFault) {
3425735Snate@binkert.org        data_write_pkt->reset();
3432381SN/A        data = htog(data);
3442381SN/A        data_write_pkt->dataStatic(&data);
34510028SGiacomo.Gabrielli@arm.com        data_write_pkt->addr = data_write_req->getPaddr();
34610028SGiacomo.Gabrielli@arm.com        data_write_pkt->size = sizeof(T);
34710028SGiacomo.Gabrielli@arm.com
3485735Snate@binkert.org        dcache_complete = dcachePort.sendAtomic(data_write_pkt);
3496227Snate@binkert.org        dcache_access = true;
3502381SN/A
3515735Snate@binkert.org        assert(data_write_pkt->result == Success);
35210723Sandreas.hansson@arm.com
3538668Sgeoffrey.blake@arm.com        if (res && data_write_req->getFlags() & LOCKED) {
35410723Sandreas.hansson@arm.com            *res = data_write_req->getScResult();
3558668Sgeoffrey.blake@arm.com        }
35612966SMatteo.Andreozzi@arm.com    }
35712966SMatteo.Andreozzi@arm.com
35812966SMatteo.Andreozzi@arm.com    // This will need a new way to tell if it's hooked up to a cache or not.
3592641Sstever@eecs.umich.edu    if (data_write_req->getFlags() & UNCACHEABLE)
3602811Srdreslin@umich.edu        recordEvent("Uncached Write");
3619547Sandreas.hansson@arm.com
36210694SMarco.Balboni@ARM.com    // If the write needs to have a fault on the access, consider calling
36310405Sandreas.hansson@arm.com    // changeStatus() and changing it to "bad addr write" or something.
36410405Sandreas.hansson@arm.com    return fault;
36510405Sandreas.hansson@arm.com}
36610405Sandreas.hansson@arm.com
3679547Sandreas.hansson@arm.com
36810694SMarco.Balboni@ARM.com#ifndef DOXYGEN_SHOULD_SKIP_THIS
3693218Sgblack@eecs.umich.edutemplate
3709547Sandreas.hansson@arm.comFault
37111127Sandreas.hansson@arm.comAtomicSimpleCPU::write(uint64_t data, Addr addr,
37211127Sandreas.hansson@arm.com                       unsigned flags, uint64_t *res);
37311127Sandreas.hansson@arm.com
37411127Sandreas.hansson@arm.comtemplate
37511127Sandreas.hansson@arm.comFault
37611127Sandreas.hansson@arm.comAtomicSimpleCPU::write(uint32_t data, Addr addr,
37711127Sandreas.hansson@arm.com                       unsigned flags, uint64_t *res);
37811127Sandreas.hansson@arm.com
37910694SMarco.Balboni@ARM.comtemplate
38010694SMarco.Balboni@ARM.comFault
38110694SMarco.Balboni@ARM.comAtomicSimpleCPU::write(uint16_t data, Addr addr,
38210694SMarco.Balboni@ARM.com                       unsigned flags, uint64_t *res);
38310405Sandreas.hansson@arm.com
38410405Sandreas.hansson@arm.comtemplate
3859547Sandreas.hansson@arm.comFault
38610694SMarco.Balboni@ARM.comAtomicSimpleCPU::write(uint8_t data, Addr addr,
3873218Sgblack@eecs.umich.edu                       unsigned flags, uint64_t *res);
3885735Snate@binkert.org
3895735Snate@binkert.org#endif //DOXYGEN_SHOULD_SKIP_THIS
39013892Sgabeblack@google.com
3919542Sandreas.hansson@arm.comtemplate<>
39213892Sgabeblack@google.comFault
3939542Sandreas.hansson@arm.comAtomicSimpleCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
3949542Sandreas.hansson@arm.com{
3959542Sandreas.hansson@arm.com    return write(*(uint64_t*)&data, addr, flags, res);
3969542Sandreas.hansson@arm.com}
39713892Sgabeblack@google.com
3989542Sandreas.hansson@arm.comtemplate<>
39913892Sgabeblack@google.comFault
4009542Sandreas.hansson@arm.comAtomicSimpleCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
4019542Sandreas.hansson@arm.com{
4029542Sandreas.hansson@arm.com    return write(*(uint32_t*)&data, addr, flags, res);
4039542Sandreas.hansson@arm.com}
4045735Snate@binkert.org
4055735Snate@binkert.org
4065735Snate@binkert.orgtemplate<>
4079542Sandreas.hansson@arm.comFault
4089542Sandreas.hansson@arm.comAtomicSimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
4092641Sstever@eecs.umich.edu{
4102641Sstever@eecs.umich.edu    return write((uint32_t)data, addr, flags, res);
4112641Sstever@eecs.umich.edu}
4125315Sstever@gmail.com
4135315Sstever@gmail.com
4145315Sstever@gmail.comvoid
4155315Sstever@gmail.comAtomicSimpleCPU::tick()
4169044SAli.Saidi@ARM.com{
4175735Snate@binkert.org    Tick latency = cycles(1); // instruction takes one cycle by default
4185735Snate@binkert.org
4195735Snate@binkert.org    for (int i = 0; i < width; ++i) {
4205735Snate@binkert.org        numCycles++;
4215735Snate@binkert.org
4225735Snate@binkert.org        checkForInterrupts();
4235735Snate@binkert.org
4245314Sstever@gmail.com        ifetch_req->resetMin();
4255314Sstever@gmail.com        ifetch_pkt->reset();
4265314Sstever@gmail.com        Fault fault = setupFetchPacket(ifetch_pkt);
4275735Snate@binkert.org
4285314Sstever@gmail.com        if (fault == NoFault) {
4295314Sstever@gmail.com            Tick icache_complete = icachePort.sendAtomic(ifetch_pkt);
4305314Sstever@gmail.com            // ifetch_req is initialized to read the instruction directly
4315314Sstever@gmail.com            // into the CPU object's inst field.
4325314Sstever@gmail.com
4335314Sstever@gmail.com            dcache_access = false; // assume no dcache access
4345314Sstever@gmail.com            preExecute();
4355314Sstever@gmail.com            fault = curStaticInst->execute(this, traceData);
4365314Sstever@gmail.com            postExecute();
4375314Sstever@gmail.com
4385314Sstever@gmail.com            if (traceData) {
4395314Sstever@gmail.com                traceData->finalize();
4405314Sstever@gmail.com            }
4415314Sstever@gmail.com
4425735Snate@binkert.org            if (simulate_stalls) {
4435735Snate@binkert.org                // This calculation assumes that the icache and dcache
4445735Snate@binkert.org                // access latencies are always a multiple of the CPU's
4455314Sstever@gmail.com                // cycle time.  If not, the next tick event may get
4465315Sstever@gmail.com                // scheduled at a non-integer multiple of the CPU
4475735Snate@binkert.org                // cycle time.
4485735Snate@binkert.org                Tick icache_stall = icache_complete - curTick - cycles(1);
4495315Sstever@gmail.com                Tick dcache_stall =
4505735Snate@binkert.org                    dcache_access ? dcache_complete - curTick - cycles(1) : 0;
4515735Snate@binkert.org                latency += icache_stall + dcache_stall;
4525314Sstever@gmail.com            }
4535314Sstever@gmail.com
4545735Snate@binkert.org        }
4555735Snate@binkert.org
4565735Snate@binkert.org        advancePC(fault);
4575735Snate@binkert.org    }
4585314Sstever@gmail.com
4595735Snate@binkert.org    if (_status != Idle)
4605735Snate@binkert.org        tickEvent.schedule(curTick + latency);
4615735Snate@binkert.org}
4625315Sstever@gmail.com
4635735Snate@binkert.org
4645735Snate@binkert.org////////////////////////////////////////////////////////////////////////
4655314Sstever@gmail.com//
4665735Snate@binkert.org//  AtomicSimpleCPU Simulation Object
4675735Snate@binkert.org//
4685735Snate@binkert.orgBEGIN_DECLARE_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
4695735Snate@binkert.org
4705735Snate@binkert.org    Param<Counter> max_insts_any_thread;
4715314Sstever@gmail.com    Param<Counter> max_insts_all_threads;
4725314Sstever@gmail.com    Param<Counter> max_loads_any_thread;
4735314Sstever@gmail.com    Param<Counter> max_loads_all_threads;
4745735Snate@binkert.org    SimObjectParam<MemObject *> mem;
4755735Snate@binkert.org
4765735Snate@binkert.org#if FULL_SYSTEM
4775735Snate@binkert.org    SimObjectParam<AlphaITB *> itb;
4789542Sandreas.hansson@arm.com    SimObjectParam<AlphaDTB *> dtb;
4795735Snate@binkert.org    SimObjectParam<System *> system;
4805735Snate@binkert.org    Param<int> cpu_id;
4815735Snate@binkert.org    Param<Tick> profile;
4822662Sstever@eecs.umich.edu#else
4832641Sstever@eecs.umich.edu    SimObjectParam<Process *> workload;
4849542Sandreas.hansson@arm.com#endif // FULL_SYSTEM
4859542Sandreas.hansson@arm.com
4869542Sandreas.hansson@arm.com    Param<int> clock;
4879542Sandreas.hansson@arm.com
4889542Sandreas.hansson@arm.com    Param<bool> defer_registration;
4899542Sandreas.hansson@arm.com    Param<int> width;
4909542Sandreas.hansson@arm.com    Param<bool> function_trace;
4919542Sandreas.hansson@arm.com    Param<Tick> function_trace_start;
4929542Sandreas.hansson@arm.com    Param<bool> simulate_stalls;
4939542Sandreas.hansson@arm.com
4949542Sandreas.hansson@arm.comEND_DECLARE_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
4959542Sandreas.hansson@arm.com
4969542Sandreas.hansson@arm.comBEGIN_INIT_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
4979542Sandreas.hansson@arm.com
4989542Sandreas.hansson@arm.com    INIT_PARAM(max_insts_any_thread,
4999542Sandreas.hansson@arm.com               "terminate when any thread reaches this inst count"),
5009542Sandreas.hansson@arm.com    INIT_PARAM(max_insts_all_threads,
5019542Sandreas.hansson@arm.com               "terminate when all threads have reached this inst count"),
5029542Sandreas.hansson@arm.com    INIT_PARAM(max_loads_any_thread,
5039542Sandreas.hansson@arm.com               "terminate when any thread reaches this load count"),
5049543Ssascha.bischoff@arm.com    INIT_PARAM(max_loads_all_threads,
5059543Ssascha.bischoff@arm.com               "terminate when all threads have reached this load count"),
5069543Ssascha.bischoff@arm.com    INIT_PARAM(mem, "memory"),
5079543Ssascha.bischoff@arm.com
5089543Ssascha.bischoff@arm.com#if FULL_SYSTEM
5099543Ssascha.bischoff@arm.com    INIT_PARAM(itb, "Instruction TLB"),
5109543Ssascha.bischoff@arm.com    INIT_PARAM(dtb, "Data TLB"),
5119543Ssascha.bischoff@arm.com    INIT_PARAM(system, "system object"),
5129543Ssascha.bischoff@arm.com    INIT_PARAM(cpu_id, "processor ID"),
5139543Ssascha.bischoff@arm.com    INIT_PARAM(profile, ""),
5149543Ssascha.bischoff@arm.com#else
5159543Ssascha.bischoff@arm.com    INIT_PARAM(workload, "processes to run"),
5169543Ssascha.bischoff@arm.com#endif // FULL_SYSTEM
5179543Ssascha.bischoff@arm.com
5189543Ssascha.bischoff@arm.com    INIT_PARAM(clock, "clock speed"),
5199543Ssascha.bischoff@arm.com    INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
5209543Ssascha.bischoff@arm.com    INIT_PARAM(width, "cpu width"),
5219543Ssascha.bischoff@arm.com    INIT_PARAM(function_trace, "Enable function trace"),
5229543Ssascha.bischoff@arm.com    INIT_PARAM(function_trace_start, "Cycle to start function trace"),
5235735Snate@binkert.org    INIT_PARAM(simulate_stalls, "Simulate cache stall cycles")
5245735Snate@binkert.org
5254022Sstever@eecs.umich.eduEND_INIT_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
5262811Srdreslin@umich.edu
5275735Snate@binkert.org
5284022Sstever@eecs.umich.eduCREATE_SIM_OBJECT(AtomicSimpleCPU)
5292811Srdreslin@umich.edu{
53010583SCurtis.Dunham@arm.com    AtomicSimpleCPU::Params *params = new AtomicSimpleCPU::Params();
53110583SCurtis.Dunham@arm.com    params->name = getInstanceName();
53210583SCurtis.Dunham@arm.com    params->numberOfThreads = 1;
53310583SCurtis.Dunham@arm.com    params->max_insts_any_thread = max_insts_any_thread;
53410583SCurtis.Dunham@arm.com    params->max_insts_all_threads = max_insts_all_threads;
53511287Sandreas.hansson@arm.com    params->max_loads_any_thread = max_loads_any_thread;
53611287Sandreas.hansson@arm.com    params->max_loads_all_threads = max_loads_all_threads;
53711287Sandreas.hansson@arm.com    params->deferRegistration = defer_registration;
53811287Sandreas.hansson@arm.com    params->clock = clock;
53911287Sandreas.hansson@arm.com    params->functionTrace = function_trace;
54011287Sandreas.hansson@arm.com    params->functionTraceStart = function_trace_start;
54111287Sandreas.hansson@arm.com    params->width = width;
54211287Sandreas.hansson@arm.com    params->simulate_stalls = simulate_stalls;
54311287Sandreas.hansson@arm.com    params->mem = mem;
54410583SCurtis.Dunham@arm.com
54510583SCurtis.Dunham@arm.com#if FULL_SYSTEM
54611199Sandreas.hansson@arm.com    params->itb = itb;
54712347Snikos.nikoleris@arm.com    params->dtb = dtb;
54811600Sandreas.hansson@arm.com    params->system = system;
54911199Sandreas.hansson@arm.com    params->cpu_id = cpu_id;
55010583SCurtis.Dunham@arm.com    params->profile = profile;
55111286Sandreas.hansson@arm.com#else
55211286Sandreas.hansson@arm.com    params->process = workload;
55311286Sandreas.hansson@arm.com#endif
55411286Sandreas.hansson@arm.com
55511286Sandreas.hansson@arm.com    AtomicSimpleCPU *cpu = new AtomicSimpleCPU(params);
55610583SCurtis.Dunham@arm.com    return cpu;
55710583SCurtis.Dunham@arm.com}
55810583SCurtis.Dunham@arm.com
55910583SCurtis.Dunham@arm.comREGISTER_SIM_OBJECT("AtomicSimpleCPU", AtomicSimpleCPU)
5602812Srdreslin@umich.edu
56113350Snikos.nikoleris@arm.com