cpu.cc revision 14198
12330SN/A/* 22330SN/A * Copyright (c) 2012-2014, 2017 ARM Limited 32330SN/A * All rights reserved 42330SN/A * 52330SN/A * The license below extends only to copyright in the software and shall 62330SN/A * not be construed as granting a license to any other intellectual 72330SN/A * property including but not limited to intellectual property relating 82330SN/A * to a hardware implementation of the functionality of the software 92330SN/A * licensed hereunder. You may use the software subject to the license 102330SN/A * terms below provided that you ensure that this notice is replicated 112330SN/A * unmodified and in its entirety in all distributions of the software, 122330SN/A * modified or unmodified, in source code or in binary form. 132330SN/A * 142330SN/A * Redistribution and use in source and binary forms, with or without 152330SN/A * modification, are permitted provided that the following conditions are 162330SN/A * met: redistributions of source code must retain the above copyright 172330SN/A * notice, this list of conditions and the following disclaimer; 182330SN/A * redistributions in binary form must reproduce the above copyright 192330SN/A * notice, this list of conditions and the following disclaimer in the 202330SN/A * documentation and/or other materials provided with the distribution; 212330SN/A * neither the name of the copyright holders nor the names of its 222330SN/A * contributors may be used to endorse or promote products derived from 232330SN/A * this software without specific prior written permission. 242330SN/A * 252330SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 262330SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 272689Sktlim@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 282689Sktlim@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 292330SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 302292SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 312292SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 322292SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 332292SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 342980Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 356658Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 368229Snate@binkert.org * 372362SN/A * Authors: Andrew Bardsley 382680Sktlim@umich.edu */ 392683Sktlim@umich.edu 402683Sktlim@umich.edu#include "cpu/minor/cpu.hh" 412678Sktlim@umich.edu 422292SN/A#include "arch/utility.hh" 432292SN/A#include "cpu/minor/dyn_inst.hh" 442292SN/A#include "cpu/minor/fetch1.hh" 453548Sgblack@eecs.umich.edu#include "cpu/minor/pipeline.hh" 463548Sgblack@eecs.umich.edu#include "debug/Drain.hh" 473548Sgblack@eecs.umich.edu#include "debug/MinorCPU.hh" 488902Sandreas.hansson@arm.com#include "debug/Quiesce.hh" 498902Sandreas.hansson@arm.com 502292SN/AMinorCPU::MinorCPU(MinorCPUParams *params) : 512862Sktlim@umich.edu BaseCPU(params), 522862Sktlim@umich.edu threadPolicy(params->threadPolicy) 532330SN/A{ 542330SN/A /* This is only written for one thread at the moment */ 552330SN/A Minor::MinorThread *thread; 562330SN/A 572330SN/A for (ThreadID i = 0; i < numThreads; i++) { 582330SN/A if (FullSystem) { 592292SN/A thread = new Minor::MinorThread(this, i, params->system, 602683Sktlim@umich.edu params->itb, params->dtb, params->isa[i]); 612683Sktlim@umich.edu thread->setStatus(ThreadContext::Halted); 626331Sgblack@eecs.umich.edu } else { 632683Sktlim@umich.edu thread = new Minor::MinorThread(this, i, params->system, 648735Sandreas.hanson@arm.com params->workload[i], params->itb, params->dtb, 653486Sktlim@umich.edu params->isa[i]); 662862Sktlim@umich.edu } 672862Sktlim@umich.edu 682862Sktlim@umich.edu threads.push_back(thread); 692862Sktlim@umich.edu ThreadContext *tc = thread->getTC(); 705712Shsul@eecs.umich.edu threadContexts.push_back(tc); 712683Sktlim@umich.edu } 725714Shsul@eecs.umich.edu 735714Shsul@eecs.umich.edu 745714Shsul@eecs.umich.edu if (params->checker) { 755714Shsul@eecs.umich.edu fatal("The Minor model doesn't support checking (yet)\n"); 766221Snate@binkert.org } 772683Sktlim@umich.edu 786221Snate@binkert.org Minor::MinorDynInst::init(); 792683Sktlim@umich.edu 802683Sktlim@umich.edu pipeline = new Minor::Pipeline(*this, *params); 812683Sktlim@umich.edu activityRecorder = pipeline->getActivityRecorder(); 822683Sktlim@umich.edu} 832683Sktlim@umich.edu 848706Sandreas.hansson@arm.comMinorCPU::~MinorCPU() 858706Sandreas.hansson@arm.com{ 868706Sandreas.hansson@arm.com delete pipeline; 878706Sandreas.hansson@arm.com 888921Sandreas.hansson@arm.com for (ThreadID thread_id = 0; thread_id < threads.size(); thread_id++) { 898706Sandreas.hansson@arm.com delete threads[thread_id]; 908706Sandreas.hansson@arm.com } 913675Sktlim@umich.edu} 922683Sktlim@umich.edu 932683Sktlim@umich.eduvoid 942683Sktlim@umich.eduMinorCPU::init() 952683Sktlim@umich.edu{ 962683Sktlim@umich.edu BaseCPU::init(); 972683Sktlim@umich.edu 982683Sktlim@umich.edu if (!params()->switched_out && 992683Sktlim@umich.edu system->getMemoryMode() != Enums::timing) 1003548Sgblack@eecs.umich.edu { 1012683Sktlim@umich.edu fatal("The Minor CPU requires the memory system to be in " 1028852Sandreas.hansson@arm.com "'timing' mode.\n"); 1032690Sktlim@umich.edu } 1048852Sandreas.hansson@arm.com 1058799Sgblack@eecs.umich.edu /* Initialise the ThreadContext's memory proxies */ 1062683Sktlim@umich.edu for (ThreadID thread_id = 0; thread_id < threads.size(); thread_id++) { 1072683Sktlim@umich.edu ThreadContext *tc = getContext(thread_id); 1088921Sandreas.hansson@arm.com 1092292SN/A tc->initMemProxies(tc); 1102683Sktlim@umich.edu } 1112683Sktlim@umich.edu 1122683Sktlim@umich.edu /* Initialise CPUs (== threads in the ISA) */ 1132683Sktlim@umich.edu if (FullSystem && !params()->switched_out) { 1142683Sktlim@umich.edu for (ThreadID thread_id = 0; thread_id < threads.size(); thread_id++) 1152683Sktlim@umich.edu { 1162683Sktlim@umich.edu ThreadContext *tc = getContext(thread_id); 1172683Sktlim@umich.edu 1182683Sktlim@umich.edu /* Initialize CPU, including PC */ 1192683Sktlim@umich.edu TheISA::initCPU(tc, cpuId()); 1202683Sktlim@umich.edu } 1212683Sktlim@umich.edu } 1222683Sktlim@umich.edu} 1232683Sktlim@umich.edu 1242683Sktlim@umich.edu/** Stats interface from SimObject (by way of BaseCPU) */ 1252683Sktlim@umich.eduvoid 1263673Srdreslin@umich.eduMinorCPU::regStats() 1273486Sktlim@umich.edu{ 1282683Sktlim@umich.edu BaseCPU::regStats(); 1292683Sktlim@umich.edu stats.regStats(name(), *this); 1302683Sktlim@umich.edu pipeline->regStats(); 1315999Snate@binkert.org} 1328834Satgutier@umich.edu 1338834Satgutier@umich.eduvoid 1348834Satgutier@umich.eduMinorCPU::serializeThread(CheckpointOut &cp, ThreadID thread_id) const 1358834Satgutier@umich.edu{ 1362683Sktlim@umich.edu threads[thread_id]->serialize(cp); 1375999Snate@binkert.org} 1382683Sktlim@umich.edu 1392683Sktlim@umich.eduvoid 1402683Sktlim@umich.eduMinorCPU::unserializeThread(CheckpointIn &cp, ThreadID thread_id) 1412683Sktlim@umich.edu{ 1422683Sktlim@umich.edu threads[thread_id]->unserialize(cp); 1432683Sktlim@umich.edu} 1442683Sktlim@umich.edu 1452683Sktlim@umich.eduvoid 1462683Sktlim@umich.eduMinorCPU::serialize(CheckpointOut &cp) const 1472683Sktlim@umich.edu{ 1482683Sktlim@umich.edu pipeline->serialize(cp); 1492683Sktlim@umich.edu BaseCPU::serialize(cp); 1503402Sktlim@umich.edu} 1513402Sktlim@umich.edu 1523402Sktlim@umich.eduvoid 1535714Shsul@eecs.umich.eduMinorCPU::unserialize(CheckpointIn &cp) 1545714Shsul@eecs.umich.edu{ 1555714Shsul@eecs.umich.edu pipeline->unserialize(cp); 1562292SN/A BaseCPU::unserialize(cp); 1576221Snate@binkert.org} 1582292SN/A 1592690Sktlim@umich.eduAddr 1602683Sktlim@umich.eduMinorCPU::dbg_vtophys(Addr addr) 1612683Sktlim@umich.edu{ 1622292SN/A /* Note that this gives you the translation for thread 0 */ 1632683Sktlim@umich.edu panic("No implementation for vtophy\n"); 1642683Sktlim@umich.edu 1652292SN/A return 0; 1662683Sktlim@umich.edu} 1672292SN/A 1682292SN/Avoid 1692292SN/AMinorCPU::wakeup(ThreadID tid) 1702292SN/A{ 1712292SN/A DPRINTF(Drain, "[tid:%d] MinorCPU wakeup\n", tid); 1723548Sgblack@eecs.umich.edu assert(tid < numThreads); 1738777Sgblack@eecs.umich.edu 1742683Sktlim@umich.edu if (threads[tid]->status() == ThreadContext::Suspended) { 1758229Snate@binkert.org threads[tid]->activate(); 1768229Snate@binkert.org } 1778706Sandreas.hansson@arm.com} 1782683Sktlim@umich.edu 1798706Sandreas.hansson@arm.comvoid 1802683Sktlim@umich.eduMinorCPU::startup() 1818706Sandreas.hansson@arm.com{ 1828706Sandreas.hansson@arm.com DPRINTF(MinorCPU, "MinorCPU startup\n"); 1838852Sandreas.hansson@arm.com 1848852Sandreas.hansson@arm.com BaseCPU::startup(); 1852678Sktlim@umich.edu 1862690Sktlim@umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) { 1872292SN/A threads[tid]->startup(); 1882292SN/A pipeline->wakeupFetch(tid); 1892292SN/A } 1902292SN/A} 1912292SN/A 1922292SN/ADrainState 1932292SN/AMinorCPU::drain() 1942292SN/A{ 1952292SN/A // Deschedule any power gating event (if any) 1962292SN/A deschedulePowerGatingEvent(); 1972292SN/A 1982292SN/A if (switchedOut()) { 1992292SN/A DPRINTF(Drain, "Minor CPU switched out, draining not needed.\n"); 200 return DrainState::Drained; 201 } 202 203 DPRINTF(Drain, "MinorCPU drain\n"); 204 205 /* Need to suspend all threads and wait for Execute to idle. 206 * Tell Fetch1 not to fetch */ 207 if (pipeline->drain()) { 208 DPRINTF(Drain, "MinorCPU drained\n"); 209 return DrainState::Drained; 210 } else { 211 DPRINTF(Drain, "MinorCPU not finished draining\n"); 212 return DrainState::Draining; 213 } 214} 215 216void 217MinorCPU::signalDrainDone() 218{ 219 DPRINTF(Drain, "MinorCPU drain done\n"); 220 Drainable::signalDrainDone(); 221} 222 223void 224MinorCPU::drainResume() 225{ 226 /* When taking over from another cpu make sure lastStopped 227 * is reset since it might have not been defined previously 228 * and might lead to a stats corruption */ 229 pipeline->resetLastStopped(); 230 231 if (switchedOut()) { 232 DPRINTF(Drain, "drainResume while switched out. Ignoring\n"); 233 return; 234 } 235 236 DPRINTF(Drain, "MinorCPU drainResume\n"); 237 238 if (!system->isTimingMode()) { 239 fatal("The Minor CPU requires the memory system to be in " 240 "'timing' mode.\n"); 241 } 242 243 for (ThreadID tid = 0; tid < numThreads; tid++){ 244 wakeup(tid); 245 } 246 247 pipeline->drainResume(); 248 249 // Reschedule any power gating event (if any) 250 schedulePowerGatingEvent(); 251} 252 253void 254MinorCPU::memWriteback() 255{ 256 DPRINTF(Drain, "MinorCPU memWriteback\n"); 257} 258 259void 260MinorCPU::switchOut() 261{ 262 DPRINTF(MinorCPU, "MinorCPU switchOut\n"); 263 264 assert(!switchedOut()); 265 BaseCPU::switchOut(); 266 267 /* Check that the CPU is drained? */ 268 activityRecorder->reset(); 269} 270 271void 272MinorCPU::takeOverFrom(BaseCPU *old_cpu) 273{ 274 DPRINTF(MinorCPU, "MinorCPU takeOverFrom\n"); 275 276 BaseCPU::takeOverFrom(old_cpu); 277} 278 279void 280MinorCPU::activateContext(ThreadID thread_id) 281{ 282 DPRINTF(MinorCPU, "ActivateContext thread: %d\n", thread_id); 283 284 /* Do some cycle accounting. lastStopped is reset to stop the 285 * wakeup call on the pipeline from adding the quiesce period 286 * to BaseCPU::numCycles */ 287 stats.quiesceCycles += pipeline->cyclesSinceLastStopped(); 288 pipeline->resetLastStopped(); 289 290 /* Wake up the thread, wakeup the pipeline tick */ 291 threads[thread_id]->activate(); 292 wakeupOnEvent(Minor::Pipeline::CPUStageId); 293 pipeline->wakeupFetch(thread_id); 294 295 BaseCPU::activateContext(thread_id); 296} 297 298void 299MinorCPU::suspendContext(ThreadID thread_id) 300{ 301 DPRINTF(MinorCPU, "SuspendContext %d\n", thread_id); 302 303 threads[thread_id]->suspend(); 304 305 BaseCPU::suspendContext(thread_id); 306} 307 308void 309MinorCPU::wakeupOnEvent(unsigned int stage_id) 310{ 311 DPRINTF(Quiesce, "Event wakeup from stage %d\n", stage_id); 312 313 /* Mark that some activity has taken place and start the pipeline */ 314 activityRecorder->activateStage(stage_id); 315 pipeline->start(); 316} 317 318MinorCPU * 319MinorCPUParams::create() 320{ 321 return new MinorCPU(this); 322} 323 324Port & 325MinorCPU::getInstPort() 326{ 327 return pipeline->getInstPort(); 328} 329 330Port & 331MinorCPU::getDataPort() 332{ 333 return pipeline->getDataPort(); 334} 335 336Counter 337MinorCPU::totalInsts() const 338{ 339 Counter ret = 0; 340 341 for (auto i = threads.begin(); i != threads.end(); i ++) 342 ret += (*i)->numInst; 343 344 return ret; 345} 346 347Counter 348MinorCPU::totalOps() const 349{ 350 Counter ret = 0; 351 352 for (auto i = threads.begin(); i != threads.end(); i ++) 353 ret += (*i)->numOp; 354 355 return ret; 356} 357