simulate.cc revision 9983
12207SN/A/* 22207SN/A * Copyright (c) 2006 The Regents of The University of Michigan 32207SN/A * Copyright (c) 2013 Advanced Micro Devices, Inc. 42207SN/A * Copyright (c) 2013 Mark D. Hill and David A. Wood 52207SN/A * All rights reserved. 62207SN/A * 72207SN/A * Redistribution and use in source and binary forms, with or without 82207SN/A * modification, are permitted provided that the following conditions are 92207SN/A * met: redistributions of source code must retain the above copyright 102207SN/A * notice, this list of conditions and the following disclaimer; 112207SN/A * redistributions in binary form must reproduce the above copyright 122207SN/A * notice, this list of conditions and the following disclaimer in the 132207SN/A * documentation and/or other materials provided with the distribution; 142207SN/A * neither the name of the copyright holders nor the names of its 152207SN/A * contributors may be used to endorse or promote products derived from 162207SN/A * this software without specific prior written permission. 172207SN/A * 182207SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 192207SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 202207SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 212207SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 222207SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 232207SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 242207SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 252207SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 262207SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 272665Ssaidi@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 282665Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 292665Ssaidi@eecs.umich.edu * 302207SN/A * Authors: Nathan Binkert 312207SN/A * Steve Reinhardt 3211793Sbrandon.potter@amd.com */ 3311793Sbrandon.potter@amd.com 342972Sgblack@eecs.umich.edu#include <mutex> 358229Snate@binkert.org#include <thread> 362454SN/A 3712334Sgabeblack@google.com#include "base/misc.hh" 382680Sktlim@umich.edu#include "base/pollevent.hh" 398232Snate@binkert.org#include "base/types.hh" 405759Shsul@eecs.umich.edu#include "sim/async.hh" 4112431Sgabeblack@google.com#include "sim/eventq_impl.hh" 4211854Sbrandon.potter@amd.com#include "sim/sim_events.hh" 437678Sgblack@eecs.umich.edu#include "sim/sim_exit.hh" 445759Shsul@eecs.umich.edu#include "sim/simulate.hh" 4511800Sbrandon.potter@amd.com#include "sim/stat_control.hh" 462474SN/A 472207SN/A//! Mutex for handling async events. 482474SN/Astd::mutex asyncEventMutex; 492474SN/A 502474SN/A//! Global barrier for synchronizing threads entering/exiting the 5111851Sbrandon.potter@amd.com//! simulation loop. 5212432Sgabeblack@google.comBarrier *threadBarrier; 5312432Sgabeblack@google.com 542474SN/A//! forward declaration 5512441Sgabeblack@google.comEvent *doSimLoop(EventQueue *); 5611905SBrandon.Potter@amd.com 5711905SBrandon.Potter@amd.com/** 5811905SBrandon.Potter@amd.com * The main function for all subordinate threads (i.e., all threads 592474SN/A * other than the main thread). These threads start by waiting on 602474SN/A * threadBarrier. Once all threads have arrived at threadBarrier, 612474SN/A * they enter the simulation loop concurrently. When they exit the 6211905SBrandon.Potter@amd.com * loop, they return to waiting on threadBarrier. This process is 632474SN/A * repeated until the simulation terminates. 6411905SBrandon.Potter@amd.com */ 6511905SBrandon.Potter@amd.comstatic void 6611905SBrandon.Potter@amd.comthread_loop(EventQueue *queue) 6711905SBrandon.Potter@amd.com{ 682474SN/A while (true) { 692474SN/A threadBarrier->wait(); 7011905SBrandon.Potter@amd.com doSimLoop(queue); 712474SN/A } 7211905SBrandon.Potter@amd.com} 7311905SBrandon.Potter@amd.com 742474SN/A/** Simulate for num_cycles additional cycles. If num_cycles is -1 752474SN/A * (the default), do not limit simulation; some other event must 762474SN/A * terminate the loop. Exported to Python via SWIG. 7711851Sbrandon.potter@amd.com * @return The SimLoopExitEvent that caused the loop to exit. 785759Shsul@eecs.umich.edu */ 7911389Sbrandon.potter@amd.comGlobalSimLoopExitEvent * 8011389Sbrandon.potter@amd.comsimulate(Tick num_cycles) 8111389Sbrandon.potter@amd.com{ 825759Shsul@eecs.umich.edu // The first time simulate() is called from the Python code, we need to 835759Shsul@eecs.umich.edu // create a thread for each of event queues referenced by the 845771Shsul@eecs.umich.edu // instantiated sim objects. 855759Shsul@eecs.umich.edu static bool threads_initialized = false; 865759Shsul@eecs.umich.edu static std::vector<std::thread *> threads; 875759Shsul@eecs.umich.edu 8811321Ssteve.reinhardt@amd.com if (!threads_initialized) { 895759Shsul@eecs.umich.edu threadBarrier = new Barrier(numMainEventQueues); 9011320Ssteve.reinhardt@amd.com 915759Shsul@eecs.umich.edu // the main thread (the one we're currently running on) 925759Shsul@eecs.umich.edu // handles queue 0, so we only need to allocate new threads 935759Shsul@eecs.umich.edu // for queues 1..N-1. We'll call these the "subordinate" threads. 945759Shsul@eecs.umich.edu for (uint32_t i = 1; i < numMainEventQueues; i++) { 955759Shsul@eecs.umich.edu threads.push_back(new std::thread(thread_loop, mainEventQueue[i])); 965759Shsul@eecs.umich.edu } 975759Shsul@eecs.umich.edu 9810318Sandreas.hansson@arm.com threads_initialized = true; 995759Shsul@eecs.umich.edu } 1005759Shsul@eecs.umich.edu 1015759Shsul@eecs.umich.edu inform("Entering event queue @ %d. Starting simulation...\n", curTick()); 1025759Shsul@eecs.umich.edu 10311389Sbrandon.potter@amd.com if (num_cycles < MaxTick - curTick()) 10411389Sbrandon.potter@amd.com num_cycles = curTick() + num_cycles; 10511389Sbrandon.potter@amd.com else // counter would roll over or be set to MaxTick anyhow 10611389Sbrandon.potter@amd.com num_cycles = MaxTick; 1075759Shsul@eecs.umich.edu 1085759Shsul@eecs.umich.edu GlobalEvent *limit_event = new GlobalSimLoopExitEvent(num_cycles, 1095759Shsul@eecs.umich.edu "simulate() limit reached", 0, 0); 1105759Shsul@eecs.umich.edu 1115759Shsul@eecs.umich.edu GlobalSyncEvent *quantum_event = NULL; 1125759Shsul@eecs.umich.edu if (numMainEventQueues > 1) { 1135759Shsul@eecs.umich.edu if (simQuantum == 0) { 1145759Shsul@eecs.umich.edu fatal("Quantum for multi-eventq simulation not specified"); 1155759Shsul@eecs.umich.edu } 1165759Shsul@eecs.umich.edu 1175759Shsul@eecs.umich.edu quantum_event = new GlobalSyncEvent(simQuantum, simQuantum, 1185759Shsul@eecs.umich.edu EventBase::Progress_Event_Pri, 0); 1195759Shsul@eecs.umich.edu 1205759Shsul@eecs.umich.edu inParallelMode = true; 1216227Snate@binkert.org } 1225759Shsul@eecs.umich.edu 1235759Shsul@eecs.umich.edu // all subordinate (created) threads should be waiting on the 1245759Shsul@eecs.umich.edu // barrier; the arrival of the main thread here will satisfy the 1256227Snate@binkert.org // barrier, and all threads will enter doSimLoop in parallel 1265759Shsul@eecs.umich.edu threadBarrier->wait(); 1275759Shsul@eecs.umich.edu Event *local_event = doSimLoop(mainEventQueue[0]); 1285759Shsul@eecs.umich.edu assert(local_event != NULL); 1295759Shsul@eecs.umich.edu 13011320Ssteve.reinhardt@amd.com inParallelMode = false; 13111320Ssteve.reinhardt@amd.com 1325759Shsul@eecs.umich.edu // locate the global exit event and return it to Python 13311320Ssteve.reinhardt@amd.com BaseGlobalEvent *global_event = local_event->globalEvent(); 1345759Shsul@eecs.umich.edu assert(global_event != NULL); 1355759Shsul@eecs.umich.edu 1365759Shsul@eecs.umich.edu GlobalSimLoopExitEvent *global_exit_event = 1375759Shsul@eecs.umich.edu dynamic_cast<GlobalSimLoopExitEvent *>(global_event); 1385759Shsul@eecs.umich.edu assert(global_exit_event != NULL); 1395759Shsul@eecs.umich.edu 14011905SBrandon.Potter@amd.com // if we didn't hit limit_event, delete it. 1415759Shsul@eecs.umich.edu if (global_exit_event != limit_event) { 14211905SBrandon.Potter@amd.com assert(limit_event->scheduled()); 14311905SBrandon.Potter@amd.com limit_event->deschedule(); 1445759Shsul@eecs.umich.edu delete limit_event; 14511905SBrandon.Potter@amd.com } 14611905SBrandon.Potter@amd.com 1475759Shsul@eecs.umich.edu //! Delete the simulation quantum event. 1485759Shsul@eecs.umich.edu if (quantum_event != NULL) { 14911905SBrandon.Potter@amd.com quantum_event->deschedule(); 1505759Shsul@eecs.umich.edu delete quantum_event; 1515759Shsul@eecs.umich.edu } 1525759Shsul@eecs.umich.edu 1535759Shsul@eecs.umich.edu return global_exit_event; 1545759Shsul@eecs.umich.edu} 1555759Shsul@eecs.umich.edu 1565759Shsul@eecs.umich.edu/** 1575759Shsul@eecs.umich.edu * Test and clear the global async_event flag, such that each time the 1585759Shsul@eecs.umich.edu * flag is cleared, only one thread returns true (and thus is assigned 1595759Shsul@eecs.umich.edu * to handle the corresponding async event(s)). 1605759Shsul@eecs.umich.edu */ 1615759Shsul@eecs.umich.edustatic bool 1625759Shsul@eecs.umich.edutestAndClearAsyncEvent() 1635759Shsul@eecs.umich.edu{ 16411905SBrandon.Potter@amd.com bool was_set = false; 1655759Shsul@eecs.umich.edu asyncEventMutex.lock(); 1665759Shsul@eecs.umich.edu 1675759Shsul@eecs.umich.edu if (async_event) { 1685759Shsul@eecs.umich.edu was_set = true; 1695759Shsul@eecs.umich.edu async_event = false; 1706227Snate@binkert.org } 1718852Sandreas.hansson@arm.com 1725759Shsul@eecs.umich.edu asyncEventMutex.unlock(); 1738852Sandreas.hansson@arm.com return was_set; 1745759Shsul@eecs.umich.edu} 1755759Shsul@eecs.umich.edu 1765759Shsul@eecs.umich.edu/** 1775759Shsul@eecs.umich.edu * The main per-thread simulation loop. This loop is executed by all 1785759Shsul@eecs.umich.edu * simulation threads (the main thread and the subordinate threads) in 1795958Sgblack@eecs.umich.edu * parallel. 1805958Sgblack@eecs.umich.edu */ 18111905SBrandon.Potter@amd.comEvent * 1825759Shsul@eecs.umich.edudoSimLoop(EventQueue *eventq) 18311389Sbrandon.potter@amd.com{ 1845759Shsul@eecs.umich.edu // set the per thread current eventq pointer 1855759Shsul@eecs.umich.edu curEventQueue(eventq); 1865759Shsul@eecs.umich.edu eventq->handleAsyncInsertions(); 18711851Sbrandon.potter@amd.com 1882474SN/A while (1) { 1896820SLisa.Hsu@amd.com // there should always be at least one event (the SimLoopExitEvent 19011801Sbrandon.potter@amd.com // we just scheduled) in the queue 1917532Ssteve.reinhardt@amd.com assert(!eventq->empty()); 1926820SLisa.Hsu@amd.com assert(curTick() <= eventq->nextTick() && 1935183Ssaidi@eecs.umich.edu "event scheduled in the past"); 1947532Ssteve.reinhardt@amd.com 19512186Sgabeblack@google.com Event *exit_event = eventq->serviceOne(); 1967532Ssteve.reinhardt@amd.com if (exit_event != NULL) { 19712186Sgabeblack@google.com return exit_event; 19811801Sbrandon.potter@amd.com } 1997532Ssteve.reinhardt@amd.com 2007532Ssteve.reinhardt@amd.com if (async_event && testAndClearAsyncEvent()) { 2017532Ssteve.reinhardt@amd.com async_event = false; 2027532Ssteve.reinhardt@amd.com if (async_statdump || async_statreset) { 2037532Ssteve.reinhardt@amd.com Stats::schedStatEvent(async_statdump, async_statreset); 2047532Ssteve.reinhardt@amd.com async_statdump = false; 20511851Sbrandon.potter@amd.com async_statreset = false; 2067532Ssteve.reinhardt@amd.com } 2077532Ssteve.reinhardt@amd.com 2087532Ssteve.reinhardt@amd.com if (async_exit) { 2097532Ssteve.reinhardt@amd.com async_exit = false; 2107532Ssteve.reinhardt@amd.com exitSimLoop("user interrupt received"); 21111851Sbrandon.potter@amd.com } 2125759Shsul@eecs.umich.edu 21310318Sandreas.hansson@arm.com if (async_io || async_alarm) { 2142474SN/A async_io = false; 2157532Ssteve.reinhardt@amd.com async_alarm = false; 2165713Shsul@eecs.umich.edu pollQueue.service(); 2175713Shsul@eecs.umich.edu } 2187701Sgblack@eecs.umich.edu 2197701Sgblack@eecs.umich.edu if (async_exception) { 2204997Sgblack@eecs.umich.edu async_exception = false; 2215713Shsul@eecs.umich.edu return NULL; 2222474SN/A } 2232474SN/A } 2245958Sgblack@eecs.umich.edu } 22511851Sbrandon.potter@amd.com 2265958Sgblack@eecs.umich.edu // not reached... only exit is return on SimLoopExitEvent 2275958Sgblack@eecs.umich.edu} 2286701Sgblack@eecs.umich.edu