diff --git a/SConstruct b/SConstruct --- a/SConstruct +++ b/SConstruct @@ -180,8 +180,8 @@ # ######################################################################## use_vars = set([ 'AS', 'AR', 'CC', 'CXX', 'HOME', 'LD_LIBRARY_PATH', 'LIBRARY_PATH', 'PATH', 'PKG_CONFIG_PATH', 'PYTHONPATH', - 'RANLIB', 'SWIG' ]) + 'RANLIB', 'SWIG', 'SYSTEMC_HOME' ]) use_prefixes = [ "M5", # M5 configuration (e.g., path to kernels) @@ -213,6 +212,18 @@ print "swig is not installed (package swig on Ubuntu and RedHat)" Exit(1) +needs_systemc=False +for t in BUILD_TARGETS: + if "sysc_build" in t: + needs_systemc=True + +if needs_systemc: +# Check that systemc is present + if not 'SYSTEMC_HOME' in use_env: + print "Please provide the path to systemC in $SYSTEMC_HOME" + Exit(1) + + # add useful python code PYTHONPATH so it can be used by subprocesses # as well main.AppendENVPath('PYTHONPATH', extra_python_paths) @@ -328,7 +339,10 @@ for t in BUILD_TARGETS: path_dirs = t.split('/') try: - build_top = rfind(path_dirs, 'build', -2) + if needs_systemc: + build_top = rfind(path_dirs, 'sysc_build', -2) + else: + build_top = rfind(path_dirs, 'build', -2) except: print "Error: no non-leaf 'build' dir found on target path", t Exit(1) @@ -407,6 +421,8 @@ path = path[len(variant_base):] elif path.startswith('build/'): path = path[6:] + elif path.startswith('sysc_build/'): + path = path[11:] return path # Generate a string of the form: @@ -784,6 +800,19 @@ context.Result(ret) return ret +#because of sc_main specific construct we can't use the regular checking function +def CheckSystemC(context): + context.Message("Checking for systemC...") + context.env.Append(LIBS = 'systemc') + ret = context.TryLink(''' + #include + int sc_main(int argc, char * argv[]) { + sc_core::sc_version(); + return 0; } + ''', extension=".cpp") + context.Result(ret) + return ret + # Platform-specific configuration. Note again that we assume that all # builds under a given build root run on the same host platform. conf = Configure(main, @@ -964,6 +964,21 @@ return host_isa in isa_comp_table.get(isa, []) +# Check if systemC is present if needed +if needs_systemc: + main.MergeFlags({'CPPPATH': + [Dir(main['ENV']['SYSTEMC_HOME']+'/include')]}) + main.MergeFlags({'LIBPATH': + [Dir(main['ENV']['SYSTEMC_HOME']+'/lib-linux')]}) + #64 bits platforms + main.MergeFlags({'LIBPATH': + [Dir(main['ENV']['SYSTEMC_HOME']+'/lib-linux64')]}) + main.MergeFlags({'CPPDEFINES':['_SYSTEMC_']}) + conf.AddTests({ 'CheckSystemC' : CheckSystemC }) + if not conf.CheckSystemC(): + print 'Error: did not find needed systemc library '\ + 'and/or systemc header file.' + Exit(1) ###################################################################### # diff --git a/src/base/pollevent.cc b/src/base/pollevent.cc --- a/src/base/pollevent.cc +++ b/src/base/pollevent.cc @@ -177,11 +177,18 @@ } copy(); +#ifdef _SYSTEMC_ + if (sc_core::sc_time_stamp().value() > 0) + async_event.notify(); +#endif } void PollQueue::service() { +#ifdef _SYSTEMC_ + mainEventQueue.setCurTick(sc_core::sc_time_stamp().value()); +#endif int ret = poll(poll_fds, num_fds, 0); if (ret <= 0) @@ -262,7 +271,12 @@ if (sig != SIGIO) panic("Wrong Handler"); +#ifdef _SYSTEMC_ + if (sc_core::sc_time_stamp().value() > 0) + async_event.notify(); +#else async_event = true; +#endif async_io = true; } @@ -272,7 +288,12 @@ if (sig != SIGALRM) panic("Wrong Handler"); +#ifdef _SYSTEMC_ + if (sc_core::sc_time_stamp().value() > 0) + async_event.notify(); +#else async_event = true; +#endif async_alarm = true; alarm(1); } diff --git a/src/python/swig/event.i b/src/python/swig/event.i --- a/src/python/swig/event.i +++ b/src/python/swig/event.i @@ -43,6 +43,8 @@ #pragma SWIG nowarn=350,351 +%ignore Gem5_event_queue; + %extend EventQueue { void schedule(Event *event, Tick when) diff --git a/src/python/swig/pyevent.cc b/src/python/swig/pyevent.cc --- a/src/python/swig/pyevent.cc +++ b/src/python/swig/pyevent.cc @@ -57,7 +57,11 @@ } else { // Somethign should be done to signal back to the main interpreter // that there's been an exception. +#ifdef _SYSTEMC_ + async_event.notify(); +#else async_event = true; +#endif async_exception = true; } diff --git a/src/sim/async.hh b/src/sim/async.hh --- a/src/sim/async.hh +++ b/src/sim/async.hh @@ -32,17 +32,46 @@ #ifndef __ASYNC_HH__ #define __ASYNC_HH__ +#ifdef _SYSTEMC_ +#include +#endif + /// /// @file sim/async.hh /// This file defines flags used to handle asynchronous simulator events. /// +#ifdef _SYSTEMC_ + +struct AsyncEventIf : sc_core::sc_interface +{ + virtual void notify() = 0; + protected: + virtual void update() = 0; +}; + +struct AsyncEvent : sc_core::sc_prim_channel, AsyncEventIf +{ + AsyncEvent(const char* nm):sc_core::sc_prim_channel(nm) {}; + void notify() { async_request_update(); }; + protected: + virtual void update() { triggerEvent(); }; + private: + void triggerEvent(); +}; + +#endif + /// @name Asynchronous event flags. /// To avoid races, signal handlers simply set these flags, which are /// then checked in the main event loop. Defined in main.cc. /// @note See the PollQueue object (in pollevent.hh) for the use of async_io and async_alarm. //@{ +#ifdef _SYSTEMC_ +extern AsyncEvent async_event; +#else extern volatile bool async_event; ///< Some asynchronous event has happened. +#endif extern volatile bool async_statdump; ///< Async request to dump stats. extern volatile bool async_statreset; ///< Async request to reset stats. extern volatile bool async_exit; ///< Async request to exit simulator. diff --git a/src/sim/async.cc b/src/sim/async.cc --- a/src/sim/async.cc +++ b/src/sim/async.cc @@ -28,7 +28,13 @@ * Authors: Nathan Binkert */ +#include "sim/async.hh" + +#ifdef _SYSTEMC_ +AsyncEvent async_event("async_event"); +#else volatile bool async_event = false; +#endif volatile bool async_statdump = false; volatile bool async_statreset = false; volatile bool async_exit = false; diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -41,6 +41,9 @@ #include #include #include +#ifdef _SYSTEMC_ +#include +#endif #include "base/flags.hh" #include "base/misc.hh" @@ -48,6 +51,22 @@ #include "debug/Event.hh" #include "sim/serialize.hh" +#ifdef _SYSTEMC_ +class Gem5EventQueue : public sc_core::sc_module +{ + public: + + sc_core::sc_event_queue gem5ScEventQueue; + + SC_HAS_PROCESS(Gem5EventQueue); + Gem5EventQueue(sc_core::sc_module_name nm); + ~Gem5EventQueue(); + + void serviceOne(); + uint64_t cp_timestamp; +}; +#endif + class EventQueue; // forward declaration extern EventQueue mainEventQueue; @@ -359,6 +378,9 @@ const EventQueue &operator=(const EventQueue &); public: +#ifdef _SYSTEMC_ + Event *returnEvent; +#endif EventQueue(const std::string &n); virtual const std::string name() const { return objName; } diff --git a/src/sim/eventq.cc b/src/sim/eventq.cc --- a/src/sim/eventq.cc +++ b/src/sim/eventq.cc @@ -29,12 +29,13 @@ * Authors: Steve Reinhardt * Nathan Binkert * Steve Raasch */ #include #include #include #include +#include #include "base/hashmap.hh" #include "base/misc.hh" @@ -43,6 +45,8 @@ #include "debug/Config.hh" #include "sim/core.hh" #include "sim/eventq_impl.hh" +#include "sim/system.hh" + using namespace std; @@ -53,6 +57,10 @@ // cycle, before the pipeline simulation is performed. // EventQueue mainEventQueue("Main Event Queue"); +#ifdef _SYSTEMC_ +Gem5EventQueue gem5EventQueue("Gem5EventQueue"); +std::multiset gem5CancelledEvents; +#endif #ifndef NDEBUG Counter Event::instanceCounter = 0; @@ -93,12 +101,23 @@ event->nextInBin = curr; } +#ifdef _SYSTEMC_ + Tick waitTime=event->when()-curTick(); + gem5EventQueue.gem5ScEventQueue.notify(waitTime,sc_core::SC_PS); +#endif return event; } void EventQueue::insert(Event *event) { +#ifdef _SYSTEMC_ + setCurTick(sc_core::sc_time_stamp().value()); + if (gem5EventQueue.cp_timestamp) + event->setWhen(event->when()-gem5EventQueue.cp_timestamp,&mainEventQueue); + + assert(event->when() >= getCurTick()); +#endif // Deal with the head case if (!head || *event <= *head) { head = Event::insertBefore(event, head); @@ -153,9 +173,17 @@ void EventQueue::remove(Event *event) { +#ifdef _SYSTEMC_ + setCurTick(sc_core::sc_time_stamp().value()); +#endif if (head == NULL) panic("event not found!"); +#ifdef _SYSTEMC_ + //cancel delayed notification + gem5CancelledEvents.insert(sc_core::sc_time(double(event->when()-getCurTick()),sc_core::SC_PS)+sc_core::sc_time_stamp()); +#endif + // deal with an event on the head's 'in bin' list (event has the same // time as the head) if (*head == *event) { @@ -208,6 +236,10 @@ if (event->isExitEvent()) { assert(!event->flags.isSet(Event::AutoDelete) || !event->flags.isSet(Event::IsMainQueue)); // would be silly +#ifdef _SYSTEMC_ + sc_core::sc_stop(); + returnEvent = event; +#endif return event; } } else { @@ -434,3 +466,29 @@ EventQueue::EventQueue(const string &n) : objName(n), head(NULL), _curTick(0) {} + +#ifdef _SYSTEMC_ +Gem5EventQueue::Gem5EventQueue(sc_core::sc_module_name nm): +sc_core::sc_module(nm),gem5ScEventQueue("ScEventsQueue") +{ + SC_METHOD(serviceOne); + dont_initialize(); + sensitive << gem5ScEventQueue; + cp_timestamp=0; +}; + +Gem5EventQueue::~Gem5EventQueue() {}; + +void Gem5EventQueue::serviceOne() +{ + // forward current cycle to the time of the first event on the queue + mainEventQueue.setCurTick(sc_core::sc_time_stamp().value()); + if (gem5CancelledEvents.find(sc_core::sc_time_stamp()) != gem5CancelledEvents.end()) { + gem5CancelledEvents.erase(gem5CancelledEvents.find(sc_core::sc_time_stamp())); + } else if (!mainEventQueue.empty()) { + mainEventQueue.serviceOne(); + } else { + panic("unexpected event trigger"); + } +} +#endif diff --git a/src/sim/init.cc b/src/sim/init.cc --- a/src/sim/init.cc +++ b/src/sim/init.cc @@ -69,14 +69,22 @@ void dumpStatsHandler(int sigtype) { +#ifdef _SYSTEMC_ + async_event.notify(); +#else async_event = true; +#endif async_statdump = true; } void dumprstStatsHandler(int sigtype) { +#ifdef _SYSTEMC_ + async_event.notify(); +#else async_event = true; +#endif async_statdump = true; async_statreset = true; } @@ -85,7 +93,11 @@ void exitNowHandler(int sigtype) { +#ifdef _SYSTEMC_ + async_event.notify(); +#else async_event = true; +#endif async_exit = true; } diff --git a/src/sim/main.cc b/src/sim/main.cc --- a/src/sim/main.cc +++ b/src/sim/main.cc @@ -29,6 +29,9 @@ */ #include +#ifdef _SYSTEMC_ +#include +#endif #include "sim/init.hh" @@ -37,7 +40,11 @@ // into the python environment and then starts things running by // calling m5Main. int +#ifdef _SYSTEMC_ +sc_main(int argc, char **argv) +#else main(int argc, char **argv) +#endif { int ret; diff --git a/src/sim/simulate.hh b/src/sim/simulate.hh --- a/src/sim/simulate.hh +++ b/src/sim/simulate.hh @@ -31,5 +31,8 @@ #include "base/types.hh" #include "sim/sim_events.hh" +#ifdef _SYSTEMC_ +#include "sim/async.hh" +#endif SimLoopExitEvent *simulate(Tick num_cycles = MaxTick); diff --git a/src/sim/simulate.cc b/src/sim/simulate.cc --- a/src/sim/simulate.cc +++ b/src/sim/simulate.cc @@ -62,6 +62,13 @@ new SimLoopExitEvent("simulate() limit reached", 0); mainEventQueue.schedule(limit_event, num_cycles); +#ifdef _SYSTEMC_ + sc_core::sc_start(); + SimLoopExitEvent *se_event; + se_event = dynamic_cast(mainEventQueue.returnEvent); + return se_event; +} +#else while (1) { // there should always be at least one event (the SimLoopExitEvent // we just scheduled) in the queue @@ -98,9 +105,15 @@ return se_event; } +#endif +#ifdef _SYSTEMC_ +void AsyncEvent::triggerEvent() +{ +#else if (async_event) { async_event = false; +#endif if (async_statdump || async_statreset) { Stats::schedStatEvent(async_statdump, async_statreset); async_statdump = false; @@ -120,11 +133,15 @@ if (async_exception) { async_exception = false; +#ifdef _SYSTEMC_ + sc_core::sc_stop(); + mainEventQueue.returnEvent=NULL; +#else return NULL; } } +#endif } - // not reached... only exit is return on SimLoopExitEvent }