atomic.cc revision 2631
15729SN/A/*
25729SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan
35729SN/A * All rights reserved.
410036SAli.Saidi@ARM.com *
58835SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without
610036SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are
77873SN/A * met: redistributions of source code must retain the above copyright
87873SN/A * notice, this list of conditions and the following disclaimer;
97873SN/A * redistributions in binary form must reproduce the above copyright
105729SN/A * notice, this list of conditions and the following disclaimer in the
115729SN/A * documentation and/or other materials provided with the distribution;
125729SN/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
148835SAli.Saidi@ARM.com * this software without specific prior written permission.
159885Sstever@gmail.com *
169885Sstever@gmail.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1710036SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
188835SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
198835SAli.Saidi@ARM.com * 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,
218835SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2210315Snilay@cs.wisc.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
239481Snilay@cs.wisc.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249481Snilay@cs.wisc.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
258673SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
268721SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
278835SAli.Saidi@ARM.com */
288835SAli.Saidi@ARM.com
297935SN/A#include "arch/utility.hh"
307935SN/A#include "cpu/exetrace.hh"
317935SN/A#include "cpu/simple/atomic.hh"
327935SN/A#include "mem/packet_impl.hh"
337935SN/A#include "sim/builder.hh"
347935SN/A
357935SN/Ausing namespace std;
368983Snate@binkert.orgusing namespace TheISA;
375729SN/A
389885Sstever@gmail.comAtomicSimpleCPU::TickEvent::TickEvent(AtomicSimpleCPU *c)
399885Sstever@gmail.com    : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c)
409885Sstever@gmail.com{
4110315Snilay@cs.wisc.edu}
4210036SAli.Saidi@ARM.com
4310315Snilay@cs.wisc.edu
449885Sstever@gmail.comvoid
459885Sstever@gmail.comAtomicSimpleCPU::TickEvent::process()
465729SN/A{
475729SN/A    cpu->tick();
489885Sstever@gmail.com}
4910315Snilay@cs.wisc.edu
505876SN/Aconst char *
519885Sstever@gmail.comAtomicSimpleCPU::TickEvent::description()
525729SN/A{
535876SN/A    return "AtomicSimpleCPU tick event";
548835SAli.Saidi@ARM.com}
555876SN/A
565729SN/A
5710036SAli.Saidi@ARM.comvoid
585729SN/AAtomicSimpleCPU::init()
595729SN/A{
608835SAli.Saidi@ARM.com    //Create Memory Ports (conect them up)
619481Snilay@cs.wisc.edu    Port *mem_dport = mem->getPort("");
625729SN/A    dcachePort.setPeer(mem_dport);
635729SN/A    mem_dport->setPeer(&dcachePort);
645729SN/A
655729SN/A    Port *mem_iport = mem->getPort("");
665729SN/A    icachePort.setPeer(mem_iport);
675729SN/A    mem_iport->setPeer(&icachePort);
688835SAli.Saidi@ARM.com
695729SN/A    BaseCPU::init();
709885Sstever@gmail.com#if FULL_SYSTEM
7110315Snilay@cs.wisc.edu    for (int i = 0; i < execContexts.size(); ++i) {
729481Snilay@cs.wisc.edu        ExecContext *xc = execContexts[i];
735729SN/A
745729SN/A        // initialize CPU, including PC
755729SN/A        TheISA::initCPU(xc, xc->readCpuId());
765729SN/A    }
775729SN/A#endif
785729SN/A}
799885Sstever@gmail.com
809885Sstever@gmail.combool
819885Sstever@gmail.comAtomicSimpleCPU::CpuPort::recvTiming(Packet *pkt)
829885Sstever@gmail.com{
8310036SAli.Saidi@ARM.com    panic("AtomicSimpleCPU doesn't expect recvAtomic callback!");
849885Sstever@gmail.com    return true;
855729SN/A}
865729SN/A
879885Sstever@gmail.comTick
888983Snate@binkert.orgAtomicSimpleCPU::CpuPort::recvAtomic(Packet *pkt)
895729SN/A{
909885Sstever@gmail.com    panic("AtomicSimpleCPU doesn't expect recvAtomic callback!");
9110645Snilay@cs.wisc.edu    return curTick;
9210036SAli.Saidi@ARM.com}
936123SN/A
949373Snilay@cs.wisc.eduvoid
958241SN/AAtomicSimpleCPU::CpuPort::recvFunctional(Packet *pkt)
965729SN/A{
979373Snilay@cs.wisc.edu    panic("AtomicSimpleCPU doesn't expect recvFunctional callback!");
985876SN/A}
998835SAli.Saidi@ARM.com
1009373Snilay@cs.wisc.eduvoid
10110036SAli.Saidi@ARM.comAtomicSimpleCPU::CpuPort::recvStatusChange(Status status)
1025729SN/A{
1038835SAli.Saidi@ARM.com    if (status == RangeChange)
1049885Sstever@gmail.com        return;
1059373Snilay@cs.wisc.edu
1065729SN/A    panic("AtomicSimpleCPU doesn't expect recvStatusChange callback!");
1075729SN/A}
1085729SN/A
1098983Snate@binkert.orgPacket *
1105729SN/AAtomicSimpleCPU::CpuPort::recvRetry()
1119885Sstever@gmail.com{
1129885Sstever@gmail.com    panic("AtomicSimpleCPU doesn't expect recvRetry callback!");
1139885Sstever@gmail.com    return NULL;
1149885Sstever@gmail.com}
1159885Sstever@gmail.com
11610036SAli.Saidi@ARM.com
1179885Sstever@gmail.comAtomicSimpleCPU::AtomicSimpleCPU(Params *p)
11810036SAli.Saidi@ARM.com    : BaseSimpleCPU(p), tickEvent(this),
1199885Sstever@gmail.com      width(p->width), simulate_stalls(p->simulate_stalls),
1209885Sstever@gmail.com      icachePort(this), dcachePort(this)
1215729SN/A{
1226024SN/A    _status = Idle;
1238835SAli.Saidi@ARM.com
12410036SAli.Saidi@ARM.com    ifetch_req = new Request(true);
1255729SN/A    ifetch_req->setAsid(0);
1268835SAli.Saidi@ARM.com    // @todo fix me and get the real cpu iD!!!
1278835SAli.Saidi@ARM.com    ifetch_req->setCpuNum(0);
1288835SAli.Saidi@ARM.com    ifetch_req->setSize(sizeof(MachInst));
1298835SAli.Saidi@ARM.com    ifetch_pkt = new Packet;
1309885Sstever@gmail.com    ifetch_pkt->cmd = Read;
13110036SAli.Saidi@ARM.com    ifetch_pkt->dataStatic(&inst);
1329885Sstever@gmail.com    ifetch_pkt->req = ifetch_req;
1338835SAli.Saidi@ARM.com    ifetch_pkt->size = sizeof(MachInst);
1348983Snate@binkert.org    ifetch_pkt->dest = Packet::Broadcast;
1355729SN/A
1365729SN/A    data_read_req = new Request(true);
1375729SN/A    // @todo fix me and get the real cpu iD!!!
1389885Sstever@gmail.com    data_read_req->setCpuNum(0);
1398983Snate@binkert.org    data_read_req->setAsid(0);
1405729SN/A    data_read_pkt = new Packet;
1419885Sstever@gmail.com    data_read_pkt->cmd = Read;
14210645Snilay@cs.wisc.edu    data_read_pkt->dataStatic(&dataReg);
14310036SAli.Saidi@ARM.com    data_read_pkt->req = data_read_req;
1446123SN/A    data_read_pkt->dest = Packet::Broadcast;
1459373Snilay@cs.wisc.edu
1468241SN/A    data_write_req = new Request(true);
1475729SN/A    // @todo fix me and get the real cpu iD!!!
1489373Snilay@cs.wisc.edu    data_write_req->setCpuNum(0);
1495876SN/A    data_write_req->setAsid(0);
1508835SAli.Saidi@ARM.com    data_write_pkt = new Packet;
1519373Snilay@cs.wisc.edu    data_write_pkt->cmd = Write;
15210036SAli.Saidi@ARM.com    data_write_pkt->req = data_write_req;
1535729SN/A    data_write_pkt->dest = Packet::Broadcast;
1548835SAli.Saidi@ARM.com}
1559885Sstever@gmail.com
1569373Snilay@cs.wisc.edu
1575729SN/AAtomicSimpleCPU::~AtomicSimpleCPU()
1585729SN/A{
1595729SN/A}
1608983Snate@binkert.org
1615729SN/Avoid
1629885Sstever@gmail.comAtomicSimpleCPU::serialize(ostream &os)
1639885Sstever@gmail.com{
1649885Sstever@gmail.com    BaseSimpleCPU::serialize(os);
1659885Sstever@gmail.com    SERIALIZE_ENUM(_status);
1669885Sstever@gmail.com    nameOut(os, csprintf("%s.tickEvent", name()));
16710036SAli.Saidi@ARM.com    tickEvent.serialize(os);
1689885Sstever@gmail.com}
16910036SAli.Saidi@ARM.com
1709885Sstever@gmail.comvoid
1719885Sstever@gmail.comAtomicSimpleCPU::unserialize(Checkpoint *cp, const string &section)
1728835SAli.Saidi@ARM.com{
1738835SAli.Saidi@ARM.com    BaseSimpleCPU::unserialize(cp, section);
1749885Sstever@gmail.com    UNSERIALIZE_ENUM(_status);
17510036SAli.Saidi@ARM.com    tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
1768835SAli.Saidi@ARM.com}
1778835SAli.Saidi@ARM.com
1789213Snilay@cs.wisc.eduvoid
1798835SAli.Saidi@ARM.comAtomicSimpleCPU::switchOut(Sampler *s)
1808983Snate@binkert.org{
1818983Snate@binkert.org    sampler = s;
1828983Snate@binkert.org    if (status() == Running) {
1838835SAli.Saidi@ARM.com        _status = SwitchedOut;
1849481Snilay@cs.wisc.edu
1859481Snilay@cs.wisc.edu        tickEvent.squash();
18610036SAli.Saidi@ARM.com    }
1879481Snilay@cs.wisc.edu    sampler->signalSwitched();
1885729SN/A}
1896024SN/A
1908835SAli.Saidi@ARM.com
19110036SAli.Saidi@ARM.comvoid
1925729SN/AAtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
1938835SAli.Saidi@ARM.com{
1948835SAli.Saidi@ARM.com    BaseCPU::takeOverFrom(oldCPU);
1958835SAli.Saidi@ARM.com
1968835SAli.Saidi@ARM.com    assert(!tickEvent.scheduled());
1979885Sstever@gmail.com
19810036SAli.Saidi@ARM.com    // if any of this CPU's ExecContexts are active, mark the CPU as
1999885Sstever@gmail.com    // running and schedule its tick event.
2008835SAli.Saidi@ARM.com    for (int i = 0; i < execContexts.size(); ++i) {
2018983Snate@binkert.org        ExecContext *xc = execContexts[i];
2025729SN/A        if (xc->status() == ExecContext::Active && _status != Running) {
2035729SN/A            _status = Running;
2045729SN/A            tickEvent.schedule(curTick);
2059885Sstever@gmail.com            break;
2068983Snate@binkert.org        }
2079373Snilay@cs.wisc.edu    }
2089885Sstever@gmail.com}
20910645Snilay@cs.wisc.edu
21010036SAli.Saidi@ARM.com
2116123SN/Avoid
2129373Snilay@cs.wisc.eduAtomicSimpleCPU::activateContext(int thread_num, int delay)
2138241SN/A{
2145729SN/A    assert(thread_num == 0);
2159373Snilay@cs.wisc.edu    assert(cpuXC);
2165876SN/A
2178835SAli.Saidi@ARM.com    assert(_status == Idle);
2189373Snilay@cs.wisc.edu    assert(!tickEvent.scheduled());
21910036SAli.Saidi@ARM.com
2205729SN/A    notIdleFraction++;
2218835SAli.Saidi@ARM.com    tickEvent.schedule(curTick + cycles(delay));
2229885Sstever@gmail.com    _status = Running;
2239373Snilay@cs.wisc.edu}
2245729SN/A
2255729SN/A
2268983Snate@binkert.orgvoid
2278983Snate@binkert.orgAtomicSimpleCPU::suspendContext(int thread_num)
2285729SN/A{
2299885Sstever@gmail.com    assert(thread_num == 0);
2309885Sstever@gmail.com    assert(cpuXC);
2319885Sstever@gmail.com
2329885Sstever@gmail.com    assert(_status == Running);
2339885Sstever@gmail.com
23410036SAli.Saidi@ARM.com    // tick event may not be scheduled if this gets called from inside
2359885Sstever@gmail.com    // an instruction's execution, e.g. "quiesce"
23610036SAli.Saidi@ARM.com    if (tickEvent.scheduled())
2379885Sstever@gmail.com        tickEvent.deschedule();
2389885Sstever@gmail.com
2395729SN/A    notIdleFraction--;
24010451Snilay@cs.wisc.edu    _status = Idle;
2419885Sstever@gmail.com}
24210036SAli.Saidi@ARM.com
2435729SN/A
24410451Snilay@cs.wisc.edutemplate <class T>
2459583Snilay@cs.wisc.eduFault
2467524SN/AAtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
2479373Snilay@cs.wisc.edu{
2488983Snate@binkert.org    data_read_req->setVaddr(addr);
2498983Snate@binkert.org    data_read_req->setSize(sizeof(T));
2505729SN/A    data_read_req->setFlags(flags);
2515729SN/A    data_read_req->setTime(curTick);
2525729SN/A
25310036SAli.Saidi@ARM.com    if (traceData) {
2545729SN/A        traceData->setAddr(addr);
2555729SN/A    }
2565729SN/A
2575729SN/A    // translate to physical address
2589373Snilay@cs.wisc.edu    Fault fault = cpuXC->translateDataReadReq(data_read_req);
25910645Snilay@cs.wisc.edu
2605729SN/A    // Now do the access.
2615729SN/A    if (fault == NoFault) {
2625729SN/A        data_read_pkt->reset();
2635729SN/A        data_read_pkt->addr = data_read_req->getPaddr();
26410036SAli.Saidi@ARM.com        data_read_pkt->size = sizeof(T);
26510315Snilay@cs.wisc.edu
2665729SN/A        dcache_complete = dcachePort.sendAtomic(data_read_pkt);
2675729SN/A        dcache_access = true;
26810645Snilay@cs.wisc.edu
2695729SN/A        assert(data_read_pkt->result == Success);
2705729SN/A        data = data_read_pkt->get<T>();
2715729SN/A
2725729SN/A    }
2735729SN/A
2745729SN/A    // This will need a new way to tell if it has a dcache attached.
2755729SN/A    if (data_read_req->getFlags() & UNCACHEABLE)
27610451Snilay@cs.wisc.edu        recordEvent("Uncached Read");
2775729SN/A
2789885Sstever@gmail.com    return fault;
2799885Sstever@gmail.com}
2809885Sstever@gmail.com
28110315Snilay@cs.wisc.edu#ifndef DOXYGEN_SHOULD_SKIP_THIS
28210036SAli.Saidi@ARM.com
28310315Snilay@cs.wisc.edutemplate
2849885Sstever@gmail.comFault
2859885Sstever@gmail.comAtomicSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags);
28610315Snilay@cs.wisc.edu
28710315Snilay@cs.wisc.edutemplate
28810315Snilay@cs.wisc.eduFault
28910315Snilay@cs.wisc.eduAtomicSimpleCPU::read(Addr addr, uint32_t &data, unsigned flags);
29010315Snilay@cs.wisc.edu
29110315Snilay@cs.wisc.edutemplate
29210315Snilay@cs.wisc.eduFault
29310315Snilay@cs.wisc.eduAtomicSimpleCPU::read(Addr addr, uint16_t &data, unsigned flags);
2945729SN/A
29510451Snilay@cs.wisc.edutemplate
2969885Sstever@gmail.comFault
29710036SAli.Saidi@ARM.comAtomicSimpleCPU::read(Addr addr, uint8_t &data, unsigned flags);
2985729SN/A
29910451Snilay@cs.wisc.edu#endif //DOXYGEN_SHOULD_SKIP_THIS
3009583Snilay@cs.wisc.edu
3017524SN/Atemplate<>
3029096Sandreas.hansson@arm.comFault
3039150SAli.Saidi@ARM.comAtomicSimpleCPU::read(Addr addr, double &data, unsigned flags)
3048983Snate@binkert.org{
3055729SN/A    return read(addr, *(uint64_t*)&data, flags);
3065729SN/A}
3078983Snate@binkert.org
3089373Snilay@cs.wisc.edutemplate<>
3099885Sstever@gmail.comFault
3109885Sstever@gmail.comAtomicSimpleCPU::read(Addr addr, float &data, unsigned flags)
31110036SAli.Saidi@ARM.com{
3128983Snate@binkert.org    return read(addr, *(uint32_t*)&data, flags);
3135729SN/A}
3145729SN/A
3155729SN/A
3165729SN/Atemplate<>
3178983Snate@binkert.orgFault
3185729SN/AAtomicSimpleCPU::read(Addr addr, int32_t &data, unsigned flags)
3199885Sstever@gmail.com{
3209885Sstever@gmail.com    return read(addr, (uint32_t&)data, flags);
32110036SAli.Saidi@ARM.com}
3229885Sstever@gmail.com
3239885Sstever@gmail.com
324template <class T>
325Fault
326AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
327{
328    data_write_req->setVaddr(addr);
329    data_write_req->setTime(curTick);
330    data_write_req->setSize(sizeof(T));
331    data_write_req->setFlags(flags);
332
333    if (traceData) {
334        traceData->setAddr(addr);
335    }
336
337    // translate to physical address
338    Fault fault = cpuXC->translateDataWriteReq(data_write_req);
339
340    // Now do the access.
341    if (fault == NoFault) {
342        data_write_pkt->reset();
343        data = htog(data);
344        data_write_pkt->dataStatic(&data);
345        data_write_pkt->addr = data_write_req->getPaddr();
346        data_write_pkt->size = sizeof(T);
347
348        dcache_complete = dcachePort.sendAtomic(data_write_pkt);
349        dcache_access = true;
350
351        assert(data_write_pkt->result == Success);
352
353        if (res && data_write_req->getFlags() & LOCKED) {
354            *res = data_write_req->getScResult();
355        }
356    }
357
358    // This will need a new way to tell if it's hooked up to a cache or not.
359    if (data_write_req->getFlags() & UNCACHEABLE)
360        recordEvent("Uncached Write");
361
362    // If the write needs to have a fault on the access, consider calling
363    // changeStatus() and changing it to "bad addr write" or something.
364    return fault;
365}
366
367
368#ifndef DOXYGEN_SHOULD_SKIP_THIS
369template
370Fault
371AtomicSimpleCPU::write(uint64_t data, Addr addr,
372                       unsigned flags, uint64_t *res);
373
374template
375Fault
376AtomicSimpleCPU::write(uint32_t data, Addr addr,
377                       unsigned flags, uint64_t *res);
378
379template
380Fault
381AtomicSimpleCPU::write(uint16_t data, Addr addr,
382                       unsigned flags, uint64_t *res);
383
384template
385Fault
386AtomicSimpleCPU::write(uint8_t data, Addr addr,
387                       unsigned flags, uint64_t *res);
388
389#endif //DOXYGEN_SHOULD_SKIP_THIS
390
391template<>
392Fault
393AtomicSimpleCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
394{
395    return write(*(uint64_t*)&data, addr, flags, res);
396}
397
398template<>
399Fault
400AtomicSimpleCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
401{
402    return write(*(uint32_t*)&data, addr, flags, res);
403}
404
405
406template<>
407Fault
408AtomicSimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
409{
410    return write((uint32_t)data, addr, flags, res);
411}
412
413
414void
415AtomicSimpleCPU::tick()
416{
417    Tick latency = cycles(1); // instruction takes one cycle by default
418
419    for (int i = 0; i < width; ++i) {
420        numCycles++;
421
422        checkForInterrupts();
423
424        ifetch_req->resetMin();
425        ifetch_pkt->reset();
426        Fault fault = setupFetchPacket(ifetch_pkt);
427
428        if (fault == NoFault) {
429            Tick icache_complete = icachePort.sendAtomic(ifetch_pkt);
430            // ifetch_req is initialized to read the instruction directly
431            // into the CPU object's inst field.
432
433            dcache_access = false; // assume no dcache access
434            preExecute();
435            fault = curStaticInst->execute(this, traceData);
436            postExecute();
437
438            if (traceData) {
439                traceData->finalize();
440            }
441
442            if (simulate_stalls) {
443                // This calculation assumes that the icache and dcache
444                // access latencies are always a multiple of the CPU's
445                // cycle time.  If not, the next tick event may get
446                // scheduled at a non-integer multiple of the CPU
447                // cycle time.
448                Tick icache_stall = icache_complete - curTick - cycles(1);
449                Tick dcache_stall =
450                    dcache_access ? dcache_complete - curTick - cycles(1) : 0;
451                latency += icache_stall + dcache_stall;
452            }
453
454        }
455
456        advancePC(fault);
457    }
458
459    if (_status != Idle)
460        tickEvent.schedule(curTick + latency);
461}
462
463
464////////////////////////////////////////////////////////////////////////
465//
466//  AtomicSimpleCPU Simulation Object
467//
468BEGIN_DECLARE_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
469
470    Param<Counter> max_insts_any_thread;
471    Param<Counter> max_insts_all_threads;
472    Param<Counter> max_loads_any_thread;
473    Param<Counter> max_loads_all_threads;
474    SimObjectParam<MemObject *> mem;
475
476#if FULL_SYSTEM
477    SimObjectParam<AlphaITB *> itb;
478    SimObjectParam<AlphaDTB *> dtb;
479    SimObjectParam<System *> system;
480    Param<int> cpu_id;
481    Param<Tick> profile;
482#else
483    SimObjectParam<Process *> workload;
484#endif // FULL_SYSTEM
485
486    Param<int> clock;
487
488    Param<bool> defer_registration;
489    Param<int> width;
490    Param<bool> function_trace;
491    Param<Tick> function_trace_start;
492    Param<bool> simulate_stalls;
493
494END_DECLARE_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
495
496BEGIN_INIT_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
497
498    INIT_PARAM(max_insts_any_thread,
499               "terminate when any thread reaches this inst count"),
500    INIT_PARAM(max_insts_all_threads,
501               "terminate when all threads have reached this inst count"),
502    INIT_PARAM(max_loads_any_thread,
503               "terminate when any thread reaches this load count"),
504    INIT_PARAM(max_loads_all_threads,
505               "terminate when all threads have reached this load count"),
506    INIT_PARAM(mem, "memory"),
507
508#if FULL_SYSTEM
509    INIT_PARAM(itb, "Instruction TLB"),
510    INIT_PARAM(dtb, "Data TLB"),
511    INIT_PARAM(system, "system object"),
512    INIT_PARAM(cpu_id, "processor ID"),
513    INIT_PARAM(profile, ""),
514#else
515    INIT_PARAM(workload, "processes to run"),
516#endif // FULL_SYSTEM
517
518    INIT_PARAM(clock, "clock speed"),
519    INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
520    INIT_PARAM(width, "cpu width"),
521    INIT_PARAM(function_trace, "Enable function trace"),
522    INIT_PARAM(function_trace_start, "Cycle to start function trace"),
523    INIT_PARAM(simulate_stalls, "Simulate cache stall cycles")
524
525END_INIT_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
526
527
528CREATE_SIM_OBJECT(AtomicSimpleCPU)
529{
530    AtomicSimpleCPU::Params *params = new AtomicSimpleCPU::Params();
531    params->name = getInstanceName();
532    params->numberOfThreads = 1;
533    params->max_insts_any_thread = max_insts_any_thread;
534    params->max_insts_all_threads = max_insts_all_threads;
535    params->max_loads_any_thread = max_loads_any_thread;
536    params->max_loads_all_threads = max_loads_all_threads;
537    params->deferRegistration = defer_registration;
538    params->clock = clock;
539    params->functionTrace = function_trace;
540    params->functionTraceStart = function_trace_start;
541    params->width = width;
542    params->simulate_stalls = simulate_stalls;
543    params->mem = mem;
544
545#if FULL_SYSTEM
546    params->itb = itb;
547    params->dtb = dtb;
548    params->system = system;
549    params->cpu_id = cpu_id;
550    params->profile = profile;
551#else
552    params->process = workload;
553#endif
554
555    AtomicSimpleCPU *cpu = new AtomicSimpleCPU(params);
556    return cpu;
557}
558
559REGISTER_SIM_OBJECT("AtomicSimpleCPU", AtomicSimpleCPU)
560
561