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