113372Sgabeblack@google.com/*
213372Sgabeblack@google.com * Copyright (c) 2014 ARM Limited
313372Sgabeblack@google.com * All rights reserved
413372Sgabeblack@google.com *
513372Sgabeblack@google.com * The license below extends only to copyright in the software and shall
613372Sgabeblack@google.com * not be construed as granting a license to any other intellectual
713372Sgabeblack@google.com * property including but not limited to intellectual property relating
813372Sgabeblack@google.com * to a hardware implementation of the functionality of the software
913372Sgabeblack@google.com * licensed hereunder.  You may use the software subject to the license
1013372Sgabeblack@google.com * terms below provided that you ensure that this notice is replicated
1113372Sgabeblack@google.com * unmodified and in its entirety in all distributions of the software,
1213372Sgabeblack@google.com * modified or unmodified, in source code or in binary form.
1313372Sgabeblack@google.com *
1413372Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
1513372Sgabeblack@google.com * modification, are permitted provided that the following conditions are
1613372Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
1713372Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
1813372Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
1913372Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
2013372Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
2113372Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
2213372Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
2313372Sgabeblack@google.com * this software without specific prior written permission.
2413372Sgabeblack@google.com *
2513372Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2613372Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2713372Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2813372Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2913372Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3013372Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3113372Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3213372Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3313372Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3413372Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3513372Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3613372Sgabeblack@google.com *
3713372Sgabeblack@google.com * Authors: Andrew Bardsley
3813372Sgabeblack@google.com */
3913372Sgabeblack@google.com
4013372Sgabeblack@google.com#include <cstdlib>
4113372Sgabeblack@google.com#include <iostream>
4213372Sgabeblack@google.com#include <list>
4313372Sgabeblack@google.com
4413372Sgabeblack@google.com#include "base/statistics.hh"
4513372Sgabeblack@google.com#include "sc_gem5_control.hh"
4613372Sgabeblack@google.com#include "sc_logger.hh"
4713372Sgabeblack@google.com#include "sc_module.hh"
4813372Sgabeblack@google.com#include "sim/cxx_config_ini.hh"
4913372Sgabeblack@google.com#include "sim/cxx_manager.hh"
5013372Sgabeblack@google.com#include "sim/debug.hh"
5113372Sgabeblack@google.com#include "sim/init_signals.hh"
5213372Sgabeblack@google.com#include "sim/stat_control.hh"
5313372Sgabeblack@google.com#include "stats.hh"
5413372Sgabeblack@google.com
5513372Sgabeblack@google.comnamespace Gem5SystemC
5613372Sgabeblack@google.com{
5713372Sgabeblack@google.com
5813372Sgabeblack@google.com/** This is the private side of Gem5Control */
5913372Sgabeblack@google.comclass Gem5TopLevelModule : public Gem5SystemC::Module
6013372Sgabeblack@google.com{
6113372Sgabeblack@google.com    friend class Gem5Control;
6213372Sgabeblack@google.com
6313372Sgabeblack@google.com  protected:
6413372Sgabeblack@google.com    CxxConfigFileBase *config_file;
6513372Sgabeblack@google.com    CxxConfigManager *root_manager;
6613372Sgabeblack@google.com    Gem5SystemC::Logger logger;
6713372Sgabeblack@google.com
6813372Sgabeblack@google.com    /** Things to do at end_of_elaborate */
6913372Sgabeblack@google.com    std::list<void (*)()> endOfElaborationFuncs;
7013372Sgabeblack@google.com
7113372Sgabeblack@google.com  public:
7213372Sgabeblack@google.com    SC_HAS_PROCESS(Gem5TopLevelModule);
7313372Sgabeblack@google.com
7413372Sgabeblack@google.com    Gem5TopLevelModule(sc_core::sc_module_name name,
7513372Sgabeblack@google.com        const std::string &config_filename);
7613372Sgabeblack@google.com    ~Gem5TopLevelModule();
7713372Sgabeblack@google.com
7813372Sgabeblack@google.com    /** gem5 simulate.  @todo for more interesting simulation control,
7913372Sgabeblack@google.com     *  this needs to be more complicated */
8013372Sgabeblack@google.com    void run();
8113372Sgabeblack@google.com
8213372Sgabeblack@google.com    /* Register an action to happen at the end of elaboration */
8313372Sgabeblack@google.com    void registerEndOfElaboration(void (*func)())
8413372Sgabeblack@google.com    {
8513372Sgabeblack@google.com        endOfElaborationFuncs.push_back(func);
8613372Sgabeblack@google.com    }
8713372Sgabeblack@google.com
8813372Sgabeblack@google.com    /** SystemC startup */
8913372Sgabeblack@google.com    void end_of_elaboration();
9013372Sgabeblack@google.com};
9113372Sgabeblack@google.com
9213372Sgabeblack@google.comGem5System::Gem5System(CxxConfigManager *manager_,
9313372Sgabeblack@google.com    const std::string &system_name, const std::string &instance_name) :
9413372Sgabeblack@google.com    manager(manager_),
9513372Sgabeblack@google.com    systemName(system_name),
9613372Sgabeblack@google.com    instanceName(instance_name)
9713372Sgabeblack@google.com{
9813372Sgabeblack@google.com    manager->addRenaming(CxxConfigManager::Renaming(
9913372Sgabeblack@google.com        system_name, instance_name));
10013372Sgabeblack@google.com}
10113372Sgabeblack@google.com
10213372Sgabeblack@google.comGem5System::~Gem5System()
10313372Sgabeblack@google.com{
10413372Sgabeblack@google.com    delete manager;
10513372Sgabeblack@google.com}
10613372Sgabeblack@google.com
10713372Sgabeblack@google.comvoid
10813372Sgabeblack@google.comGem5System::setParam(const std::string &object,
10913372Sgabeblack@google.com    const std::string &param_name, const std::string &param_value)
11013372Sgabeblack@google.com{
11113372Sgabeblack@google.com    manager->setParam(systemName + (object != "" ? "." + object : ""),
11213372Sgabeblack@google.com        param_name, param_value);
11313372Sgabeblack@google.com}
11413372Sgabeblack@google.com
11513372Sgabeblack@google.comvoid
11613372Sgabeblack@google.comGem5System::setParamVector(const std::string &object,
11713372Sgabeblack@google.com    const std::string &param_name,
11813372Sgabeblack@google.com    const std::vector<std::string> &param_values)
11913372Sgabeblack@google.com{
12013372Sgabeblack@google.com    manager->setParamVector(systemName +
12113372Sgabeblack@google.com        (object != "" ? "." + object : ""), param_name, param_values);
12213372Sgabeblack@google.com}
12313372Sgabeblack@google.com
12413372Sgabeblack@google.comvoid
12513372Sgabeblack@google.comGem5System::instantiate()
12613372Sgabeblack@google.com{
12713372Sgabeblack@google.com    try {
12813372Sgabeblack@google.com        /* Make a new System */
12913372Sgabeblack@google.com        SimObject *obj = manager->findObject(systemName, true);
13013372Sgabeblack@google.com
13113372Sgabeblack@google.com        /* Add the System's objects to the list of managed
13213372Sgabeblack@google.com         *  objects for initialisation */
13313372Sgabeblack@google.com        manager->findTraversalOrder(systemName);
13413372Sgabeblack@google.com
13513372Sgabeblack@google.com        /* Bound ports *must* be internal to System */
13613372Sgabeblack@google.com        for (auto i = manager->objectsInOrder.begin();
13713372Sgabeblack@google.com             i != manager->objectsInOrder.end();
13813372Sgabeblack@google.com             ++ i)
13913372Sgabeblack@google.com        {
14013372Sgabeblack@google.com            manager->bindObjectPorts(*i);
14113372Sgabeblack@google.com        }
14213372Sgabeblack@google.com
14313372Sgabeblack@google.com        /* gem5 startup sequence */
14413372Sgabeblack@google.com        manager->instantiate(false);
14513372Sgabeblack@google.com        manager->initState();
14613372Sgabeblack@google.com        manager->startup();
14713372Sgabeblack@google.com    } catch (CxxConfigManager::Exception &e) {
14813372Sgabeblack@google.com        fatal("Config problem in Gem5System: %s: %s",
14913372Sgabeblack@google.com            e.name, e.message);
15013372Sgabeblack@google.com    }
15113372Sgabeblack@google.com}
15213372Sgabeblack@google.com
15313372Sgabeblack@google.comGem5Control::Gem5Control(const std::string &config_filename)
15413372Sgabeblack@google.com{
15513372Sgabeblack@google.com    module = new Gem5TopLevelModule("gem5", config_filename);
15613372Sgabeblack@google.com}
15713372Sgabeblack@google.com
15813372Sgabeblack@google.comGem5Control::~Gem5Control()
15913372Sgabeblack@google.com{ }
16013372Sgabeblack@google.com
16113372Sgabeblack@google.comvoid
16213372Sgabeblack@google.comGem5Control::registerEndOfElaboration(void (*func)())
16313372Sgabeblack@google.com{
16413372Sgabeblack@google.com    module->registerEndOfElaboration(func);
16513372Sgabeblack@google.com}
16613372Sgabeblack@google.com
16713372Sgabeblack@google.comvoid
16813372Sgabeblack@google.comGem5Control::setDebugFlag(const char *flag)
16913372Sgabeblack@google.com{
17013372Sgabeblack@google.com    ::setDebugFlag(flag);
17113372Sgabeblack@google.com}
17213372Sgabeblack@google.com
17313372Sgabeblack@google.comvoid
17413372Sgabeblack@google.comGem5Control::clearDebugFlag(const char *flag)
17513372Sgabeblack@google.com{
17613372Sgabeblack@google.com    ::clearDebugFlag(flag);
17713372Sgabeblack@google.com}
17813372Sgabeblack@google.com
17913372Sgabeblack@google.comvoid
18013372Sgabeblack@google.comGem5Control::setRemoteGDBPort(unsigned int port)
18113372Sgabeblack@google.com{
18213372Sgabeblack@google.com    ::setRemoteGDBPort(port);
18313372Sgabeblack@google.com}
18413372Sgabeblack@google.com
18513372Sgabeblack@google.comGem5System *
18613372Sgabeblack@google.comGem5Control::makeSystem(const std::string &system_name,
18713372Sgabeblack@google.com    const std::string &instance_name)
18813372Sgabeblack@google.com{
18913372Sgabeblack@google.com    Gem5System *ret = new Gem5System(
19013372Sgabeblack@google.com        new CxxConfigManager(*(module->config_file)),
19113372Sgabeblack@google.com        system_name, instance_name);
19213372Sgabeblack@google.com
19313372Sgabeblack@google.com    return ret;
19413372Sgabeblack@google.com}
19513372Sgabeblack@google.com
19613372Sgabeblack@google.comconst std::string &
19713372Sgabeblack@google.comGem5Control::getVersion() const
19813372Sgabeblack@google.com{
19913372Sgabeblack@google.com    return version;
20013372Sgabeblack@google.com}
20113372Sgabeblack@google.com
20213372Sgabeblack@google.comvoid
20313372Sgabeblack@google.comGem5Control::setVersion(const std::string &new_version)
20413372Sgabeblack@google.com{
20513372Sgabeblack@google.com    if (version != "")
20613372Sgabeblack@google.com        fatal("Gem5Control::setVersion called for a second time");
20713372Sgabeblack@google.com
20813372Sgabeblack@google.com    version = new_version;
20913372Sgabeblack@google.com}
21013372Sgabeblack@google.com
21113372Sgabeblack@google.comGem5TopLevelModule::Gem5TopLevelModule(sc_core::sc_module_name name,
21213372Sgabeblack@google.com    const std::string &config_filename) :
21313372Sgabeblack@google.com    Gem5SystemC::Module(name),
21413372Sgabeblack@google.com    config_file(NULL),
21513372Sgabeblack@google.com    root_manager(NULL)
21613372Sgabeblack@google.com{
21713372Sgabeblack@google.com    SC_THREAD(run);
21813372Sgabeblack@google.com
21913372Sgabeblack@google.com    cxxConfigInit();
22013372Sgabeblack@google.com
22113372Sgabeblack@google.com    /* Pass DPRINTF messages to SystemC */
22213372Sgabeblack@google.com    Trace::setDebugLogger(&logger);
22313372Sgabeblack@google.com
22413372Sgabeblack@google.com    /* @todo need this as an option */
22513372Sgabeblack@google.com    Gem5SystemC::setTickFrequency();
22613372Sgabeblack@google.com
22713372Sgabeblack@google.com    /* Make a SystemC-synchronising event queue and install it as the
22813372Sgabeblack@google.com     *  sole top level gem5 EventQueue */
22913372Sgabeblack@google.com    Gem5SystemC::Module::setupEventQueues(*this);
23013372Sgabeblack@google.com
23113372Sgabeblack@google.com    if (sc_core::sc_get_time_resolution() !=
23213372Sgabeblack@google.com        sc_core::sc_time(1, sc_core::SC_PS))
23313372Sgabeblack@google.com    {
23413372Sgabeblack@google.com        fatal("Time resolution must be set to 1 ps for gem5 to work");
23513372Sgabeblack@google.com    }
23613372Sgabeblack@google.com
23713372Sgabeblack@google.com    /* Enable keyboard interrupt, async I/O etc. */
23813372Sgabeblack@google.com    initSignals();
23913372Sgabeblack@google.com
24013372Sgabeblack@google.com    /* Enable stats */
24113372Sgabeblack@google.com    Stats::initSimStats();
24213372Sgabeblack@google.com    Stats::registerHandlers(CxxConfig::statsReset, CxxConfig::statsDump);
24313372Sgabeblack@google.com
24413372Sgabeblack@google.com    Trace::enable();
24513372Sgabeblack@google.com
24613372Sgabeblack@google.com    config_file = new CxxIniFile();
24713372Sgabeblack@google.com
24813372Sgabeblack@google.com    if (!config_file->load(config_filename)) {
24913372Sgabeblack@google.com        fatal("Gem5TopLevelModule: Can't open config file: %s",
25013372Sgabeblack@google.com            config_filename);
25113372Sgabeblack@google.com    }
25213372Sgabeblack@google.com
25313372Sgabeblack@google.com    root_manager = new CxxConfigManager(*config_file);
25413372Sgabeblack@google.com
25513372Sgabeblack@google.com    CxxConfig::statsEnable();
25613372Sgabeblack@google.com
25713372Sgabeblack@google.com    /* Make the root object */
25813372Sgabeblack@google.com    try {
25913372Sgabeblack@google.com        SimObject *root = root_manager->findObject("root", false);
26013372Sgabeblack@google.com
26113372Sgabeblack@google.com        /* Make sure we don't traverse into root's children */
26213372Sgabeblack@google.com        root_manager->objectsInOrder.push_back(root);
26313372Sgabeblack@google.com
26413372Sgabeblack@google.com        root_manager->instantiate(false);
26513372Sgabeblack@google.com        root_manager->initState();
26613372Sgabeblack@google.com        root_manager->startup();
26713372Sgabeblack@google.com    } catch (CxxConfigManager::Exception &e) {
26813372Sgabeblack@google.com        fatal("Config problem in Gem5TopLevelModule: %s: %s",
26913372Sgabeblack@google.com            e.name, e.message);
27013372Sgabeblack@google.com    }
27113372Sgabeblack@google.com}
27213372Sgabeblack@google.com
27313372Sgabeblack@google.comGem5TopLevelModule::~Gem5TopLevelModule()
27413372Sgabeblack@google.com{
27513372Sgabeblack@google.com    delete config_file;
27613372Sgabeblack@google.com    delete root_manager;
27713372Sgabeblack@google.com}
27813372Sgabeblack@google.com
27913372Sgabeblack@google.comvoid
28013372Sgabeblack@google.comGem5TopLevelModule::run()
28113372Sgabeblack@google.com{
28213372Sgabeblack@google.com    GlobalSimLoopExitEvent *exit_event = NULL;
28313372Sgabeblack@google.com
28413372Sgabeblack@google.com    exit_event = simulate();
28513372Sgabeblack@google.com
28613372Sgabeblack@google.com    std::cerr << "Exit at tick " << curTick()
28713372Sgabeblack@google.com        << ", cause: " << exit_event->getCause() << '\n';
28813372Sgabeblack@google.com
28913372Sgabeblack@google.com    getEventQueue(0)->dump();
29013372Sgabeblack@google.com}
29113372Sgabeblack@google.com
29213372Sgabeblack@google.comvoid
29313372Sgabeblack@google.comGem5TopLevelModule::end_of_elaboration()
29413372Sgabeblack@google.com{
29513372Sgabeblack@google.com    for (auto i = endOfElaborationFuncs.begin();
29613372Sgabeblack@google.com         i != endOfElaborationFuncs.end(); ++i)
29713372Sgabeblack@google.com    {
29813372Sgabeblack@google.com        (*i)();
29913372Sgabeblack@google.com    }
30013372Sgabeblack@google.com}
30113372Sgabeblack@google.com
30213372Sgabeblack@google.com}
30313372Sgabeblack@google.com
30413372Sgabeblack@google.comGem5SystemC::Gem5Control *
30513372Sgabeblack@google.commakeGem5Control(const std::string &config_filename)
30613372Sgabeblack@google.com{
30713372Sgabeblack@google.com    return new Gem5SystemC::Gem5Control(config_filename);
30813372Sgabeblack@google.com}
30913372Sgabeblack@google.com
310