gem5.cc revision 11315
1// Copyright (c) 2015 ARM Limited 2// All rights reserved. 3// 4// The license below extends only to copyright in the software and shall 5// not be construed as granting a license to any other intellectual 6// property including but not limited to intellectual property relating 7// to a hardware implementation of the functionality of the software 8// licensed hereunder. You may use the software subject to the license 9// terms below provided that you ensure that this notice is replicated 10// unmodified and in its entirety in all distributions of the software, 11// modified or unmodified, in source code or in binary form. 12// 13// Redistribution and use in source and binary forms, with or without 14// modification, are permitted provided that the following conditions are 15// met: redistributions of source code must retain the above copyright 16// notice, this list of conditions and the following disclaimer; 17// redistributions in binary form must reproduce the above copyright 18// notice, this list of conditions and the following disclaimer in the 19// documentation and/or other materials provided with the distribution; 20// neither the name of the copyright holders nor the names of its 21// contributors may be used to endorse or promote products derived from 22// this software without specific prior written permission. 23// 24// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 36// Copyright 2009-2014 Sandia Coporation. Under the terms 37// of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. 38// Government retains certain rights in this software. 39// 40// Copyright (c) 2009-2014, Sandia Corporation 41// All rights reserved. 42// 43// For license information, see the LICENSE file in the current directory. 44 45#include <sst_config.h> 46#include <Python.h> // Before serialization to prevent spurious warnings 47#include <sst/core/serialization.h> 48 49#include "gem5.hh" 50 51// System headers 52#include <boost/tokenizer.hpp> 53#include <string> 54 55// gem5 Headers 56#include <sim/core.hh> 57#include <sim/init.hh> 58#include <sim/init_signals.hh> 59#include <sim/system.hh> 60#include <sim/sim_object.hh> 61#include <base/misc.hh> 62#include <base/debug.hh> 63 64#ifdef fatal // gem5 sets this 65#undef fatal 66#endif 67 68// More SST Headers 69#include <sst/core/params.h> 70#include <sst/core/link.h> 71#include <sst/core/timeConverter.h> 72 73using namespace SST; 74using namespace SST::gem5; 75 76gem5Component::gem5Component(ComponentId_t id, Params ¶ms) : 77 SST::Component(id) 78{ 79 dbg.init("@t:gem5:@p():@l " + getName() + ": ", 0, 0, 80 (Output::output_location_t)params.find_integer("comp_debug", 0)); 81 info.init("gem5:" + getName() + ": ", 0, 0, Output::STDOUT); 82 83 TimeConverter *clock = registerClock( 84 params.find_string("frequency", "1GHz"), 85 new Clock::Handler<gem5Component>(this, &gem5Component::clockTick)); 86 87 // This sets how many gem5 cycles we'll need to simulate per clock tick 88 sim_cycles = clock->getFactor(); 89 90 // Disable gem5's inform() messages. 91 want_info = false; 92 93 std::string cmd = params.find_string("cmd", ""); 94 if (cmd.empty()) { 95 dbg.fatal(CALL_INFO, -1, "Component %s must have a 'cmd' parameter.\n", 96 getName().c_str()); 97 } 98 99 std::vector<char*> args; 100 args.push_back(const_cast<char*>("sst.x")); // TODO: Compute this somehow? 101 splitCommandArgs(cmd, args); 102 args.push_back(const_cast<char*>("--initialize-only")); 103 dbg.output(CALL_INFO, "Command string: [sst.x %s --initialize-only]\n", 104 cmd.c_str()); 105 for (size_t i = 0; i < args.size(); ++i) { 106 dbg.output(CALL_INFO, " Arg [%02zu] = %s\n", i, args[i]); 107 } 108 109 std::vector<char*> flags; 110 std::string gem5DbgFlags = params.find_string("gem5DebugFlags", ""); 111 splitCommandArgs(gem5DbgFlags, flags); 112 for (auto flag : flags) { 113 dbg.output(CALL_INFO, " Setting Debug Flag [%s]\n", flag); 114 setDebugFlag(flag); 115 } 116 117 ExternalMaster::registerHandler("sst", this); // these are idempotent 118 ExternalSlave ::registerHandler("sst", this); 119 120 // Initialize m5 special signal handling. 121 initSignals(); 122 123 initPython(args.size(), &args[0]); 124 125 // tell the simulator not to end without us 126 registerAsPrimaryComponent(); 127 primaryComponentDoNotEndSim(); 128 129 clocks_processed = 0; 130} 131 132gem5Component::~gem5Component(void) 133{ 134 Py_Finalize(); 135} 136 137void 138gem5Component::init(unsigned phase) 139{ 140 for (auto m : masters) { 141 m->init(phase); 142 } 143 for (auto s : slaves) { 144 s->init(phase); 145 } 146} 147 148void 149gem5Component::setup(void) 150{ 151 // Switch connectors from initData to regular Sends 152 for (auto m : masters) { 153 m->setup(); 154 } 155 for (auto s : slaves) { 156 s->setup(); 157 } 158} 159 160void 161gem5Component::finish(void) 162{ 163 for (auto m : masters) { 164 m->finish(); 165 } 166 info.output("Complete. Clocks Processed: %"PRIu64"\n", clocks_processed); 167} 168 169bool 170gem5Component::clockTick(Cycle_t cycle) 171{ 172 dbg.output(CALL_INFO, "Cycle %lu\n", cycle); 173 174 for (auto m : masters) { 175 m->clock(); 176 } 177 178 GlobalSimLoopExitEvent *event = simulate(sim_cycles); 179 ++clocks_processed; 180 if (event != simulate_limit_event) { 181 info.output("exiting: curTick()=%lu cause=`%s` code=%d\n", 182 curTick(), event->getCause().c_str(), event->getCode()); 183 primaryComponentOKToEndSim(); 184 return true; 185 } 186 187 return false; 188} 189 190 191void 192gem5Component::splitCommandArgs(std::string &cmd, 193 std::vector<char *> &args) 194{ 195 std::string sep1("\\"); 196 std::string sep2(" "); 197 std::string sep3("\"\'"); 198 199 boost::escaped_list_separator<char> els(sep1, sep2, sep3); 200 boost::tokenizer<boost::escaped_list_separator<char>> tok(cmd, els); 201 202 for (auto beg : tok) { 203 args.push_back(strdup(beg.c_str())); 204 } 205} 206 207 208void 209gem5Component::initPython(int argc, char *argv[]) 210{ 211 const char * m5MainCommands[] = { 212 "import m5", 213 "m5.main()", 214 0 // sentinel is required 215 }; 216 217 PyObject *mainModule,*mainDict; 218 219 Py_SetProgramName(argv[0]); // optional but recommended 220 221 Py_Initialize(); 222 223 int ret = initM5Python(); 224 if (ret != 0) { 225 dbg.fatal(CALL_INFO, -1, "Python failed to initialize. Code: %d\n", 226 ret); 227 } 228 229 PySys_SetArgv(argc, argv); 230 231 mainModule = PyImport_AddModule("__main__"); 232 assert(mainModule); 233 234 mainDict = PyModule_GetDict(mainModule); 235 assert(mainDict); 236 237 PyObject *result; 238 const char **command = m5MainCommands; 239 240 // evaluate each command in the m5MainCommands array (basically a 241 // bunch of python statements. 242 while (*command) { 243 result = PyRun_String(*command, Py_file_input, mainDict, mainDict); 244 if (!result) { 245 PyErr_Print(); 246 break; 247 } 248 Py_DECREF(result); 249 250 command++; 251 } 252} 253 254ExternalMaster::Port* 255gem5Component::getExternalPort(const std::string &name, 256 ExternalMaster &owner, const std::string &port_data) 257{ 258 std::string s(name); // bridges non-& result and &-arg 259 auto master = new ExtMaster(this, info, owner, s); 260 masters.push_back(master); 261 return master; 262} 263 264ExternalSlave::Port* 265gem5Component::getExternalPort(const std::string &name, 266 ExternalSlave &owner, const std::string &port_data) 267{ 268 std::string s(name); // bridges non-& result and &-arg 269 auto slave = new ExtSlave(this, info, owner, s); 270 slaves.push_back(slave); 271 return slave; 272} 273