gem5.cc revision 11617
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 <core/sst_config.h> 46#include <Python.h> // Before serialization to prevent spurious warnings 47 48#include "gem5.hh" 49 50// System headers 51#include <boost/tokenizer.hpp> 52#include <string> 53 54// gem5 Headers 55#include <sim/core.hh> 56#include <sim/init.hh> 57#include <sim/init_signals.hh> 58#include <sim/system.hh> 59#include <sim/sim_object.hh> 60#include <base/misc.hh> 61#include <base/debug.hh> 62 63#ifdef fatal // gem5 sets this 64#undef fatal 65#endif 66 67// More SST Headers 68#include <sst/core/params.h> 69#include <sst/core/link.h> 70#include <sst/core/timeConverter.h> 71 72using namespace SST; 73using namespace SST::gem5; 74 75gem5Component::gem5Component(ComponentId_t id, Params ¶ms) : 76 SST::Component(id) 77{ 78 dbg.init("@t:gem5:@p():@l " + getName() + ": ", 0, 0, 79 (Output::output_location_t)params.find_integer("comp_debug", 0)); 80 info.init("gem5:" + getName() + ": ", 0, 0, Output::STDOUT); 81 82 TimeConverter *clock = registerClock( 83 params.find_string("frequency", "1GHz"), 84 new Clock::Handler<gem5Component>(this, &gem5Component::clockTick)); 85 86 // This sets how many gem5 cycles we'll need to simulate per clock tick 87 sim_cycles = clock->getFactor(); 88 89 // Disable gem5's inform() messages. 90 want_info = false; 91 92 std::string cmd = params.find_string("cmd", ""); 93 if (cmd.empty()) { 94 dbg.fatal(CALL_INFO, -1, "Component %s must have a 'cmd' parameter.\n", 95 getName().c_str()); 96 } 97 98 std::vector<char*> args; 99 args.push_back(const_cast<char*>("sst.x")); // TODO: Compute this somehow? 100 splitCommandArgs(cmd, args); 101 args.push_back(const_cast<char*>("--initialize-only")); 102 dbg.output(CALL_INFO, "Command string: [sst.x %s --initialize-only]\n", 103 cmd.c_str()); 104 for (size_t i = 0; i < args.size(); ++i) { 105 dbg.output(CALL_INFO, " Arg [%02zu] = %s\n", i, args[i]); 106 } 107 108 std::vector<char*> flags; 109 std::string gem5DbgFlags = params.find_string("gem5DebugFlags", ""); 110 splitCommandArgs(gem5DbgFlags, flags); 111 for (auto flag : flags) { 112 dbg.output(CALL_INFO, " Setting Debug Flag [%s]\n", flag); 113 setDebugFlag(flag); 114 } 115 116 ExternalMaster::registerHandler("sst", this); // these are idempotent 117 ExternalSlave ::registerHandler("sst", this); 118 119 // Initialize m5 special signal handling. 120 initSignals(); 121 122 initPython(args.size(), &args[0]); 123 124 // tell the simulator not to end without us 125 registerAsPrimaryComponent(); 126 primaryComponentDoNotEndSim(); 127 128 clocks_processed = 0; 129} 130 131gem5Component::~gem5Component(void) 132{ 133 Py_Finalize(); 134} 135 136void 137gem5Component::init(unsigned phase) 138{ 139 for (auto m : masters) { 140 m->init(phase); 141 } 142 for (auto s : slaves) { 143 s->init(phase); 144 } 145} 146 147void 148gem5Component::setup(void) 149{ 150 // Switch connectors from initData to regular Sends 151 for (auto m : masters) { 152 m->setup(); 153 } 154 for (auto s : slaves) { 155 s->setup(); 156 } 157} 158 159void 160gem5Component::finish(void) 161{ 162 for (auto m : masters) { 163 m->finish(); 164 } 165 info.output("Complete. Clocks Processed: %"PRIu64"\n", clocks_processed); 166} 167 168bool 169gem5Component::clockTick(Cycle_t cycle) 170{ 171 dbg.output(CALL_INFO, "Cycle %lu\n", cycle); 172 173 for (auto m : masters) { 174 m->clock(); 175 } 176 177 GlobalSimLoopExitEvent *event = simulate(sim_cycles); 178 ++clocks_processed; 179 if (event != simulate_limit_event) { 180 info.output("exiting: curTick()=%lu cause=`%s` code=%d\n", 181 curTick(), event->getCause().c_str(), event->getCode()); 182 primaryComponentOKToEndSim(); 183 return true; 184 } 185 186 return false; 187} 188 189 190void 191gem5Component::splitCommandArgs(std::string &cmd, 192 std::vector<char *> &args) 193{ 194 std::string sep1("\\"); 195 std::string sep2(" "); 196 std::string sep3("\"\'"); 197 198 boost::escaped_list_separator<char> els(sep1, sep2, sep3); 199 boost::tokenizer<boost::escaped_list_separator<char>> tok(cmd, els); 200 201 for (auto beg : tok) { 202 args.push_back(strdup(beg.c_str())); 203 } 204} 205 206 207void 208gem5Component::initPython(int argc, char *argv[]) 209{ 210 const char * m5MainCommands[] = { 211 "import m5", 212 "m5.main()", 213 0 // sentinel is required 214 }; 215 216 PyObject *mainModule,*mainDict; 217 218 Py_SetProgramName(argv[0]); // optional but recommended 219 220 Py_Initialize(); 221 222 int ret = initM5Python(); 223 if (ret != 0) { 224 dbg.fatal(CALL_INFO, -1, "Python failed to initialize. Code: %d\n", 225 ret); 226 } 227 228 PySys_SetArgv(argc, argv); 229 230 mainModule = PyImport_AddModule("__main__"); 231 assert(mainModule); 232 233 mainDict = PyModule_GetDict(mainModule); 234 assert(mainDict); 235 236 PyObject *result; 237 const char **command = m5MainCommands; 238 239 // evaluate each command in the m5MainCommands array (basically a 240 // bunch of python statements. 241 while (*command) { 242 result = PyRun_String(*command, Py_file_input, mainDict, mainDict); 243 if (!result) { 244 PyErr_Print(); 245 break; 246 } 247 Py_DECREF(result); 248 249 command++; 250 } 251} 252 253ExternalMaster::Port* 254gem5Component::getExternalPort(const std::string &name, 255 ExternalMaster &owner, const std::string &port_data) 256{ 257 std::string s(name); // bridges non-& result and &-arg 258 auto master = new ExtMaster(this, info, owner, s); 259 masters.push_back(master); 260 return master; 261} 262 263ExternalSlave::Port* 264gem5Component::getExternalPort(const std::string &name, 265 ExternalSlave &owner, const std::string &port_data) 266{ 267 std::string s(name); // bridges non-& result and &-arg 268 auto slave = new ExtSlave(this, info, owner, s); 269 slaves.push_back(slave); 270 return slave; 271} 272