Go to the documentation of this file.
46 #include "config/the_isa.hh"
49 #include "debug/Drain.hh"
50 #include "debug/ExecFaulting.hh"
51 #include "debug/SimpleCPU.hh"
55 #include "params/BaseAtomicSimpleCPU.hh"
68 int cid = threadContexts[0]->contextId();
77 tickEvent([this]{
tick(); },
"AtomicSimpleCPU tick",
79 width(
p.width), locked(
false),
80 simulate_data_stalls(
p.simulate_data_stalls),
81 simulate_inst_stalls(
p.simulate_inst_stalls),
82 icachePort(
name() +
".icache_port",
this),
83 dcachePort(
name() +
".dcache_port",
this),
84 dcache_access(
false), dcache_latency(0),
88 ifetch_req = std::make_shared<Request>();
89 data_read_req = std::make_shared<Request>();
90 data_write_req = std::make_shared<Request>();
91 data_amo_req = std::make_shared<Request>();
106 deschedulePowerGatingEvent();
112 DPRINTF(Drain,
"Requesting drain.\n");
119 DPRINTF(Drain,
"Not executing microcode, no need to drain.\n");
127 DPRINTF(SimpleCPU,
"%s received snoop pkt for addr:%#x %s\n",
130 for (
ThreadID tid = 0; tid < numThreads; tid++) {
132 if (getCpuAddrMonitor(tid)->doMonitor(pkt)) {
136 threadInfo[tid]->thread->getIsaPtr()->handleLockedSnoop(pkt,
149 DPRINTF(SimpleCPU,
"Resume\n");
152 assert(!threadContexts.empty());
156 for (
ThreadID tid = 0; tid < numThreads; tid++) {
158 threadInfo[tid]->execContextStats.notIdleFraction = 1;
167 threadInfo[tid]->execContextStats.notIdleFraction = 0;
172 schedulePowerGatingEvent();
181 DPRINTF(Drain,
"tryCompleteDrain.\n");
185 DPRINTF(Drain,
"CPU done draining, processing drain event\n");
195 BaseSimpleCPU::switchOut();
216 "The atomic CPU requires the memory system to be in "
223 DPRINTF(SimpleCPU,
"ActivateContext %d\n", thread_num);
225 assert(thread_num < numThreads);
227 threadInfo[thread_num]->execContextStats.notIdleFraction = 1;
230 baseStats.numCycles += delta;
242 BaseCPU::activateContext(thread_num);
249 DPRINTF(SimpleCPU,
"SuspendContext %d\n", thread_num);
251 assert(thread_num < numThreads);
259 threadInfo[thread_num]->execContextStats.notIdleFraction = 0;
269 BaseCPU::suspendContext(thread_num);
281 DPRINTF(SimpleCPU,
"%s received atomic snoop pkt for addr:%#x %s\n",
287 for (
ThreadID tid = 0; tid <
cpu->numThreads; tid++) {
288 if (
cpu->getCpuAddrMonitor(tid)->doMonitor(pkt)) {
298 DPRINTF(SimpleCPU,
"received invalidation for addr:%#x\n",
301 t_info->thread->getIsaPtr()->handleLockedSnoop(pkt,
312 DPRINTF(SimpleCPU,
"%s received functional snoop pkt for addr:%#x %s\n",
317 for (
ThreadID tid = 0; tid < cpu->numThreads; tid++) {
318 if (cpu->getCpuAddrMonitor(tid)->doMonitor(pkt)) {
325 DPRINTF(SimpleCPU,
"received invalidation for addr:%#x\n",
328 t_info->thread->getIsaPtr()->handleLockedSnoop(pkt,
338 int &frag_size,
int &size_left)
const
340 bool predicate =
true;
343 frag_size = std::min(
346 size_left -= frag_size;
349 auto it_start = byte_enable.begin() + (size - (frag_size + size_left));
350 auto it_end = byte_enable.begin() + (size - size_left);
352 req->setVirt(frag_addr, frag_size,
flags, dataRequestorId(),
378 req->taskId(taskId());
382 int size_left = size;
388 byte_enable, frag_size, size_left);
397 if (predicate && fault ==
NoFault &&
402 if (req->isLocalAccess()) {
419 return req->isPrefetch() ?
NoFault : fault;
422 if (size_left == 0) {
423 if (req->isLockedRMW() && fault ==
NoFault) {
433 frag_addr += frag_size;
447 static uint8_t zero_array[64] = {};
464 req->taskId(taskId());
468 int size_left = size;
469 int curr_frag_id = 0;
475 byte_enable, frag_size, size_left);
483 if (predicate && fault ==
NoFault) {
484 bool do_access =
true;
487 assert(curr_frag_id == 0);
490 }
else if (req->isSwap()) {
491 assert(curr_frag_id == 0);
492 if (req->isCondSwap()) {
494 req->setExtraData(*res);
502 if (req->isLocalAccess()) {
504 req->localAccessor(thread->
getTC(), &pkt);
515 assert(res && curr_frag_id == 0);
520 if (res && !req->isSwap()) {
521 *res = req->getExtraData();
527 if (fault !=
NoFault || size_left == 0) {
528 if (req->isLockedRMW() && fault ==
NoFault) {
529 assert(!req->isMasked());
534 return req->isPrefetch() ?
NoFault : fault;
540 frag_addr += frag_size;
574 "AMO request should not access across a cache line boundary.");
578 req->taskId(taskId());
579 req->setVirt(
addr, size,
flags, dataRequestorId(),
593 if (req->isLocalAccess()) {
603 assert(!req->isLLSC());
606 if (fault !=
NoFault && req->isPrefetch()) {
623 if (numThreads > 1) {
638 baseStats.numCycles++;
639 updateCycleCounters(BaseCPU::CPU_STATE_ON);
667 Tick icache_latency = 0;
668 bool icache_access =
false;
679 icache_access =
true;
686 Tick stall_ticks = 0;
699 std::dynamic_pointer_cast<SyscallRetryFault>(fault)) {
703 stall_ticks += clockEdge(syscallRetryLatency) -
curTick();
716 stall_ticks += icache_latency;
725 latency +=
divCeil(stall_ticks, clockPeriod()) *
738 if (latency < clockPeriod())
739 latency = clockPeriod();
766 BaseCPU::regProbePoints();
769 (getProbeManager(),
"Commit");
static MemCmd makeWriteCmd(const RequestPtr &req)
Generate the appropriate write MemCmd based on the Request flags.
Tick curTick()
The universal simulation clock.
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
bool tryCompleteDrain()
Try to complete a drain request.
Addr instAddr() const
Returns the memory address of the instruction this PC points to.
std::string to_string() const
Get a string representation of the range.
virtual void handleLockedRead(const RequestPtr &req)
constexpr decltype(nullptr) NoFault
void regProbePoints() override
Fault writeMem(uint8_t *data, unsigned size, Addr addr, Request::Flags flags, uint64_t *res, const std::vector< bool > &byte_enable=std::vector< bool >()) override
std::vector< SimpleExecContext * > threadInfo
void setMem(Addr a, Addr s, unsigned f)
const bool simulate_data_stalls
Trace::InstRecord * traceData
virtual Tick sendPacket(RequestPort &port, const PacketPtr &pkt)
static bool isRomMicroPC(MicroPC upc)
Fault readMem(Addr addr, uint8_t *data, unsigned size, Request::Flags flags, const std::vector< bool > &byte_enable=std::vector< bool >()) override
@ NO_ACCESS
The request should not cause a memory access.
Tick sendAtomic(PacketPtr pkt)
Send an atomic request packet, where the data is moved and the state is updated in zero time,...
virtual bool handleLockedWrite(const RequestPtr &req, Addr cacheBlockMask)
virtual ~AtomicSimpleCPU()
StaticInstPtr curStaticInst
Current instruction.
AtomicCPUDPort dcachePort
Addr addrBlockOffset(Addr addr, Addr block_size)
Calculates the offset of a given address wrt aligned fixed-size blocks.
bool isDelayedCommit() const
bool isFirstMicroop() const
The SimpleThread object provides a combination of the ThreadState object and the ThreadContext interf...
void printAddr(Addr a)
Print state of address in memory system via PrintReq (for debugging).
void checkForInterrupts()
virtual Fault execute(ExecContext *xc, Trace::InstRecord *traceData) const =0
void takeOverFrom(ThreadContext &ntc, ThreadContext &otc)
Copy state between thread contexts in preparation for CPU handover.
const bool simulate_inst_stalls
A RequestPort is a specialisation of a Port, which implements the default protocol for the three diff...
Cycles is a wrapper class for representing cycle counts, i.e.
void dataStatic(T *p)
Set the data pointer to the following value that should not be freed.
DrainState
Object drain/handover states.
std::shared_ptr< FaultBase > Fault
void suspendContext(ThreadID thread_num) override
void print(std::ostream &o, int verbosity=0, const std::string &prefix="") const
void takeOverFrom(BaseCPU *old_cpu) override
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
ProbePointArg< PacketInfo > Packet
Packet probe point.
virtual Tick fetchInstMem()
uint64_t Tick
Tick count type.
EventFunctionWrapper tickEvent
void setupFetchRequest(const RequestPtr &req)
std::shared_ptr< Request > RequestPtr
const T * getConstPtr() const
bool isAnyActiveElement(const std::vector< bool >::const_iterator &it_start, const std::vector< bool >::const_iterator &it_end)
Test if there is any active element in an enablement range.
void verifyMemoryMode() const override
std::list< ThreadID > activeThreads
void drainResume() override
bool genMemFragmentRequest(const RequestPtr &req, Addr frag_addr, int size, Request::Flags flags, const std::vector< bool > &byte_enable, int &frag_size, int &size_left) const
Helper function used to set up the request for a single fragment of a memory access.
static MemCmd makeReadCmd(const RequestPtr &req)
Generate the appropriate read MemCmd based on the Request flags.
static constexpr T roundDown(const T &val, const U &align)
This function is used to align addresses in memory.
void traceFault()
Handler used when encountering a fault; its purpose is to tear down the InstRecord.
@ Drained
Buffers drained, ready for serialization/handover.
void activateContext(ThreadID thread_num) override
bool isCpuDrained() const
Check if a system is in a drained state.
Fault amoMem(Addr addr, uint8_t *data, unsigned size, Request::Flags flags, AtomicOpFunctorPtr amo_op) override
const PCStateBase & pcState() const override
DrainState drain() override
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
const std::string & name()
BaseISA * getIsaPtr() const override
RequestPtr data_write_req
static constexpr T divCeil(const T &a, const U &b)
ProbePointArg generates a point for the class of Arg.
ThreadContext * getTC()
Returns the pointer to this SimpleThread's ThreadContext.
static const FlagsType STORE_NO_DATA
void switchOut() override
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
AtomicSimpleCPU(const BaseAtomicSimpleCPUParams ¶ms)
void threadSnoop(PacketPtr pkt, ThreadID sender)
Perform snoop for other cpu-local thread contexts.
int ContextID
Globally unique thread context ID.
void serviceInstCountEvents()
void wakeup(ThreadID tid) override
void advancePC(const Fault &fault)
ProbePointArg< std::pair< SimpleThread *, const StaticInstPtr > > * ppCommit
Probe Points.
const FlagsType init
This Stat is Initialized.
static const Priority CPU_Tick_Pri
CPU ticks must come after other associated CPU events (such as writebacks).
virtual void recvFunctionalSnoop(PacketPtr pkt)
Receive a functional snoop request packet from the peer.
std::unique_ptr< AtomicOpFunctor > AtomicOpFunctorPtr
virtual Fault translateAtomic(const RequestPtr &req, ThreadContext *tc, Mode mode)
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
virtual Tick recvAtomicSnoop(PacketPtr pkt)
Receive an atomic snoop request packet from our peer.
AddrRange getAddrRange() const
Get address range to which this packet belongs.
void printAddr(Addr a)
Inject a PrintReq for the given address to print the state of that address throughout the memory syst...
StaticInstPtr curMacroStaticInst
@ Draining
Draining buffers pending serialization/handover.
bool scheduled() const
Determine if the current event is scheduled.
int16_t ThreadID
Thread index/ID type.
bool isInvalidate() const
Generated on Wed Jul 13 2022 10:39:17 for gem5 by doxygen 1.8.17