systemc: Implement the sensitivity mechanism.
This change lets processes be sensitive to events, timeouts, etc. Change-Id: If30a256dfa8a2e92192c1f9c96b48e2aa28ec27e Reviewed-on: https://gem5-review.googlesource.com/11713 Reviewed-by: Gabe Black <gabeblack@google.com> Maintainer: Gabe Black <gabeblack@google.com>
This commit is contained in:
46
src/systemc/core/bindinfo.hh
Normal file
46
src/systemc/core/bindinfo.hh
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2018 Google, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Gabe Black
|
||||
*/
|
||||
|
||||
#ifndef __SYSTEMC_CORE_BINDINFO_HH__
|
||||
#define __SYSTEMC_CORE_BINDINFO_HH__
|
||||
|
||||
#include "systemc/ext/core/sc_interface.hh"
|
||||
|
||||
namespace sc_gem5
|
||||
{
|
||||
|
||||
class BindInfo
|
||||
{
|
||||
public:
|
||||
::sc_core::sc_interface *interface;
|
||||
};
|
||||
|
||||
} // namespace sc_gem5
|
||||
|
||||
#endif // __SYSTEMC_CORE_BINDINFO_HH__
|
||||
@@ -32,6 +32,8 @@
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
|
||||
#include "base/logging.hh"
|
||||
#include "sim/core.hh"
|
||||
#include "systemc/core/module.hh"
|
||||
#include "systemc/core/scheduler.hh"
|
||||
|
||||
@@ -41,7 +43,7 @@ namespace sc_gem5
|
||||
Event::Event(sc_core::sc_event *_sc_event) : Event(_sc_event, "") {}
|
||||
|
||||
Event::Event(sc_core::sc_event *_sc_event, const char *_basename) :
|
||||
_sc_event(_sc_event), _basename(_basename)
|
||||
_sc_event(_sc_event), _basename(_basename), delayedNotify(this)
|
||||
{
|
||||
Module *p = currentModule();
|
||||
|
||||
@@ -81,6 +83,9 @@ Event::~Event()
|
||||
EventsIt it = findEvent(_name);
|
||||
std::swap(*it, allEvents.back());
|
||||
allEvents.pop_back();
|
||||
|
||||
if (delayedNotifyEvent.scheduled())
|
||||
scheduler.deschedule(&delayedNotifyEvent);
|
||||
}
|
||||
|
||||
const std::string &
|
||||
@@ -110,16 +115,34 @@ Event::getParentObject() const
|
||||
void
|
||||
Event::notify()
|
||||
{
|
||||
auto local_sensitivities = sensitivities;
|
||||
for (auto s: local_sensitivities)
|
||||
s->notify(this);
|
||||
}
|
||||
|
||||
void
|
||||
Event::notify(const sc_core::sc_time &t)
|
||||
{
|
||||
//XXX We're assuming the systemc time resolution is in ps.
|
||||
Tick new_tick = t.value() * SimClock::Int::ps +
|
||||
scheduler.eventQueue().getCurTick();
|
||||
if (delayedNotify.scheduled()) {
|
||||
Tick old_tick = delayedNotify.when();
|
||||
|
||||
if (new_tick >= old_tick)
|
||||
return;
|
||||
|
||||
scheduler.eventQueue().deschedule(&delayedNotify);
|
||||
}
|
||||
|
||||
scheduler.eventQueue().schedule(&delayedNotify, new_tick);
|
||||
}
|
||||
|
||||
void
|
||||
Event::cancel()
|
||||
{
|
||||
if (delayedNotify.scheduled())
|
||||
scheduler.eventQueue().deschedule(&delayedNotify);
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -30,9 +30,11 @@
|
||||
#ifndef __SYSTEMC_CORE_EVENT_HH__
|
||||
#define __SYSTEMC_CORE_EVENT_HH__
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "sim/eventq.hh"
|
||||
#include "systemc/core/list.hh"
|
||||
#include "systemc/core/object.hh"
|
||||
#include "systemc/ext/core/sc_prim.hh"
|
||||
@@ -50,6 +52,8 @@ namespace sc_gem5
|
||||
|
||||
typedef std::vector<sc_core::sc_event *> Events;
|
||||
|
||||
class Sensitivity;
|
||||
|
||||
class Event
|
||||
{
|
||||
public:
|
||||
@@ -88,6 +92,9 @@ class Event
|
||||
return e->_gem5_event;
|
||||
}
|
||||
|
||||
void addSensitivity(Sensitivity *s) const { sensitivities.insert(s); }
|
||||
void delSensitivity(Sensitivity *s) const { sensitivities.erase(s); }
|
||||
|
||||
private:
|
||||
sc_core::sc_event *_sc_event;
|
||||
|
||||
@@ -97,6 +104,10 @@ class Event
|
||||
|
||||
sc_core::sc_object *parent;
|
||||
EventsIt parentIt;
|
||||
|
||||
EventWrapper<Event, &Event::notify> delayedNotify;
|
||||
|
||||
mutable std::set<Sensitivity *> sensitivities;
|
||||
};
|
||||
|
||||
extern Events topLevelEvents;
|
||||
|
||||
@@ -56,7 +56,7 @@ Kernel::t0Handler()
|
||||
// happen before them, honoring the ordering for the initialization phase
|
||||
// in the spec. The delta phase will happen at normal priority, and then
|
||||
// the event which runs the processes which is at a lower priority.
|
||||
::sc_gem5::scheduler.initToReady();
|
||||
::sc_gem5::scheduler.prepareForInit();
|
||||
}
|
||||
|
||||
} // namespace SystemC
|
||||
|
||||
@@ -28,11 +28,84 @@
|
||||
*/
|
||||
|
||||
#include "systemc/core/process.hh"
|
||||
|
||||
#include "base/logging.hh"
|
||||
#include "systemc/core/event.hh"
|
||||
#include "systemc/core/scheduler.hh"
|
||||
|
||||
namespace sc_gem5
|
||||
{
|
||||
|
||||
void
|
||||
Sensitivity::satisfy()
|
||||
{
|
||||
warn_once("Ignoring suspended status for now.\n");
|
||||
process->setDynamic(nullptr);
|
||||
scheduler.ready(process);
|
||||
}
|
||||
|
||||
SensitivityTimeout::SensitivityTimeout(Process *p, ::sc_core::sc_time t) :
|
||||
Sensitivity(p), timeoutEvent(this), timeout(t)
|
||||
{
|
||||
Tick when = scheduler.eventQueue().getCurTick() + timeout.value();
|
||||
scheduler.eventQueue().schedule(&timeoutEvent, when);
|
||||
}
|
||||
|
||||
SensitivityTimeout::~SensitivityTimeout()
|
||||
{
|
||||
if (timeoutEvent.scheduled())
|
||||
scheduler.eventQueue().deschedule(&timeoutEvent);
|
||||
}
|
||||
|
||||
SensitivityEvent::SensitivityEvent(
|
||||
Process *p, const ::sc_core::sc_event *e) : Sensitivity(p), event(e)
|
||||
{
|
||||
Event::getFromScEvent(event)->addSensitivity(this);
|
||||
}
|
||||
|
||||
SensitivityEvent::~SensitivityEvent()
|
||||
{
|
||||
Event::getFromScEvent(event)->delSensitivity(this);
|
||||
}
|
||||
|
||||
SensitivityEventAndList::SensitivityEventAndList(
|
||||
Process *p, const ::sc_core::sc_event_and_list *list) :
|
||||
Sensitivity(p), list(list), count(0)
|
||||
{
|
||||
for (auto e: list->events)
|
||||
Event::getFromScEvent(e)->addSensitivity(this);
|
||||
}
|
||||
|
||||
SensitivityEventAndList::~SensitivityEventAndList()
|
||||
{
|
||||
for (auto e: list->events)
|
||||
Event::getFromScEvent(e)->delSensitivity(this);
|
||||
}
|
||||
|
||||
void
|
||||
SensitivityEventAndList::notifyWork(Event *e)
|
||||
{
|
||||
e->delSensitivity(this);
|
||||
count++;
|
||||
if (count == list->events.size())
|
||||
satisfy();
|
||||
}
|
||||
|
||||
SensitivityEventOrList::SensitivityEventOrList(
|
||||
Process *p, const ::sc_core::sc_event_or_list *list) :
|
||||
Sensitivity(p), list(list)
|
||||
{
|
||||
for (auto e: list->events)
|
||||
Event::getFromScEvent(e)->addSensitivity(this);
|
||||
}
|
||||
|
||||
SensitivityEventOrList::~SensitivityEventOrList()
|
||||
{
|
||||
for (auto e: list->events)
|
||||
Event::getFromScEvent(e)->delSensitivity(this);
|
||||
}
|
||||
|
||||
|
||||
class UnwindExceptionReset : public ::sc_core::sc_unwind_exception
|
||||
{
|
||||
public:
|
||||
@@ -190,6 +263,23 @@ Process::syncResetOff(bool inc_kids)
|
||||
_syncReset = false;
|
||||
}
|
||||
|
||||
void
|
||||
Process::dontInitialize()
|
||||
{
|
||||
scheduler.dontInitialize(this);
|
||||
}
|
||||
|
||||
void
|
||||
Process::finalize()
|
||||
{
|
||||
for (auto &s: pendingStaticSensitivities) {
|
||||
s->finalize(staticSensitivities);
|
||||
delete s;
|
||||
s = nullptr;
|
||||
}
|
||||
pendingStaticSensitivities.clear();
|
||||
};
|
||||
|
||||
void
|
||||
Process::run()
|
||||
{
|
||||
@@ -206,15 +296,31 @@ Process::run()
|
||||
_running = false;
|
||||
}
|
||||
|
||||
void
|
||||
Process::addStatic(PendingSensitivity *s)
|
||||
{
|
||||
pendingStaticSensitivities.push_back(s);
|
||||
}
|
||||
|
||||
void
|
||||
Process::setDynamic(Sensitivity *s)
|
||||
{
|
||||
delete dynamicSensitivity;
|
||||
dynamicSensitivity = s;
|
||||
}
|
||||
|
||||
Process::Process(const char *name, ProcessFuncWrapper *func, bool _dynamic) :
|
||||
::sc_core::sc_object(name), excWrapper(nullptr), func(func),
|
||||
_running(false), _dynamic(_dynamic), _isUnwinding(false),
|
||||
_terminated(false), _suspended(false), _disabled(false),
|
||||
_syncReset(false), refCount(0), stackSize(::Fiber::DefaultStackSize)
|
||||
_syncReset(false), refCount(0), stackSize(::Fiber::DefaultStackSize),
|
||||
dynamicSensitivity(nullptr)
|
||||
{
|
||||
_newest = this;
|
||||
if (!_dynamic)
|
||||
scheduler.init(this);
|
||||
if (_dynamic)
|
||||
finalize();
|
||||
else
|
||||
scheduler.reg(this);
|
||||
}
|
||||
|
||||
Process *Process::_newest;
|
||||
|
||||
@@ -31,17 +31,218 @@
|
||||
#define __SYSTEMC_CORE_PROCESS_HH__
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
#include "base/fiber.hh"
|
||||
#include "sim/eventq.hh"
|
||||
#include "systemc/core/bindinfo.hh"
|
||||
#include "systemc/core/list.hh"
|
||||
#include "systemc/core/object.hh"
|
||||
#include "systemc/ext/core/sc_event.hh"
|
||||
#include "systemc/ext/core/sc_interface.hh"
|
||||
#include "systemc/ext/core/sc_module.hh"
|
||||
#include "systemc/ext/core/sc_port.hh"
|
||||
#include "systemc/ext/core/sc_process_handle.hh"
|
||||
|
||||
namespace sc_gem5
|
||||
{
|
||||
|
||||
class Sensitivity
|
||||
{
|
||||
protected:
|
||||
Process *process;
|
||||
void satisfy();
|
||||
|
||||
public:
|
||||
Sensitivity(Process *p) : process(p) {}
|
||||
virtual ~Sensitivity() {}
|
||||
|
||||
virtual void notifyWork(Event *e) { satisfy(); }
|
||||
void notify(Event *e);
|
||||
void notify() { notify(nullptr); }
|
||||
|
||||
const std::string name();
|
||||
};
|
||||
|
||||
class SensitivityTimeout : virtual public Sensitivity
|
||||
{
|
||||
private:
|
||||
EventWrapper<Sensitivity, &Sensitivity::notify> timeoutEvent;
|
||||
::sc_core::sc_time timeout;
|
||||
|
||||
public:
|
||||
SensitivityTimeout(Process *p, ::sc_core::sc_time t);
|
||||
~SensitivityTimeout();
|
||||
};
|
||||
|
||||
class SensitivityEvent : virtual public Sensitivity
|
||||
{
|
||||
private:
|
||||
const ::sc_core::sc_event *event;
|
||||
|
||||
public:
|
||||
SensitivityEvent(Process *p, const ::sc_core::sc_event *e);
|
||||
~SensitivityEvent();
|
||||
};
|
||||
|
||||
//XXX This sensitivity can't be reused. To reset it, it has to be deleted and
|
||||
//recreated. That works for dynamic sensitivities, but not for static.
|
||||
//Fortunately processes can't be statically sensitive to sc_event_and_lists.
|
||||
class SensitivityEventAndList : virtual public Sensitivity
|
||||
{
|
||||
private:
|
||||
const ::sc_core::sc_event_and_list *list;
|
||||
int count;
|
||||
|
||||
public:
|
||||
SensitivityEventAndList(
|
||||
Process *p, const ::sc_core::sc_event_and_list *list);
|
||||
~SensitivityEventAndList();
|
||||
|
||||
virtual void notifyWork(Event *e) override;
|
||||
};
|
||||
|
||||
class SensitivityEventOrList : virtual public Sensitivity
|
||||
{
|
||||
private:
|
||||
const ::sc_core::sc_event_or_list *list;
|
||||
|
||||
public:
|
||||
SensitivityEventOrList(
|
||||
Process *p, const ::sc_core::sc_event_or_list *list);
|
||||
~SensitivityEventOrList();
|
||||
};
|
||||
|
||||
// Combined sensitivities. These trigger when any of their parts do.
|
||||
|
||||
class SensitivityTimeoutAndEvent :
|
||||
public SensitivityTimeout, public SensitivityEvent
|
||||
{
|
||||
public:
|
||||
SensitivityTimeoutAndEvent(
|
||||
Process *p, ::sc_core::sc_time t, const ::sc_core::sc_event *e) :
|
||||
Sensitivity(p), SensitivityTimeout(p, t), SensitivityEvent(p, e)
|
||||
{}
|
||||
};
|
||||
|
||||
class SensitivityTimeoutAndEventAndList :
|
||||
public SensitivityTimeout, public SensitivityEventAndList
|
||||
{
|
||||
public:
|
||||
SensitivityTimeoutAndEventAndList(
|
||||
Process *p, ::sc_core::sc_time t,
|
||||
const ::sc_core::sc_event_and_list *eal) :
|
||||
Sensitivity(p), SensitivityTimeout(p, t),
|
||||
SensitivityEventAndList(p, eal)
|
||||
{}
|
||||
};
|
||||
|
||||
class SensitivityTimeoutAndEventOrList :
|
||||
public SensitivityTimeout, public SensitivityEventOrList
|
||||
{
|
||||
public:
|
||||
SensitivityTimeoutAndEventOrList(
|
||||
Process *p, ::sc_core::sc_time t,
|
||||
const ::sc_core::sc_event_or_list *eol) :
|
||||
Sensitivity(p), SensitivityTimeout(p, t),
|
||||
SensitivityEventOrList(p, eol)
|
||||
{}
|
||||
};
|
||||
|
||||
typedef std::vector<Sensitivity *> Sensitivities;
|
||||
|
||||
|
||||
/*
|
||||
* Pending sensitivities. These are records of sensitivities to install later,
|
||||
* once all the information to configure them is available.
|
||||
*/
|
||||
|
||||
class PendingSensitivity
|
||||
{
|
||||
protected:
|
||||
Process *process;
|
||||
|
||||
public:
|
||||
virtual void finalize(Sensitivities &s) = 0;
|
||||
PendingSensitivity(Process *p) : process(p) {}
|
||||
virtual ~PendingSensitivity() {}
|
||||
};
|
||||
|
||||
class PendingSensitivityEvent : public PendingSensitivity
|
||||
{
|
||||
private:
|
||||
const sc_core::sc_event *event;
|
||||
|
||||
public:
|
||||
PendingSensitivityEvent(Process *p, const sc_core::sc_event *e) :
|
||||
PendingSensitivity(p), event(e) {}
|
||||
|
||||
void
|
||||
finalize(Sensitivities &s) override
|
||||
{
|
||||
s.push_back(new SensitivityEvent(process, event));
|
||||
}
|
||||
};
|
||||
|
||||
class PendingSensitivityInterface : public PendingSensitivity
|
||||
{
|
||||
private:
|
||||
const sc_core::sc_interface *interface;
|
||||
|
||||
public:
|
||||
PendingSensitivityInterface(Process *p, const sc_core::sc_interface *i) :
|
||||
PendingSensitivity(p), interface(i)
|
||||
{}
|
||||
|
||||
void
|
||||
finalize(Sensitivities &s) override
|
||||
{
|
||||
s.push_back(new SensitivityEvent(process,
|
||||
&interface->default_event()));
|
||||
}
|
||||
};
|
||||
|
||||
class PendingSensitivityPort : public PendingSensitivity
|
||||
{
|
||||
private:
|
||||
const sc_core::sc_port_base *port;
|
||||
|
||||
public:
|
||||
PendingSensitivityPort(Process *p, const sc_core::sc_port_base *pb) :
|
||||
PendingSensitivity(p), port(pb)
|
||||
{}
|
||||
|
||||
void
|
||||
finalize(Sensitivities &s) override
|
||||
{
|
||||
for (int i = 0; i < port->size(); i++) {
|
||||
const ::sc_core::sc_event *e =
|
||||
&port->_gem5BindInfo[i]->interface->default_event();
|
||||
s.push_back(new SensitivityEvent(process, e));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class PendingSensitivityFinder : public PendingSensitivity
|
||||
{
|
||||
private:
|
||||
const sc_core::sc_event_finder *finder;
|
||||
|
||||
public:
|
||||
PendingSensitivityFinder(Process *p, const sc_core::sc_event_finder *f) :
|
||||
PendingSensitivity(p), finder(f)
|
||||
{}
|
||||
|
||||
void
|
||||
finalize(Sensitivities &s) override
|
||||
{
|
||||
s.push_back(new SensitivityEvent(process, &finder->find_event()));
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::vector<PendingSensitivity *> PendingSensitivities;
|
||||
|
||||
|
||||
class Process : public ::sc_core::sc_object, public ListNode
|
||||
{
|
||||
public:
|
||||
@@ -78,12 +279,17 @@ class Process : public ::sc_core::sc_object, public ListNode
|
||||
const ::sc_core::sc_event &terminatedEvent() { return _terminatedEvent; }
|
||||
|
||||
// This should only be called before initialization.
|
||||
void dontInitialize() { popListNode(); }
|
||||
void dontInitialize();
|
||||
|
||||
void setStackSize(size_t size) { stackSize = size; }
|
||||
|
||||
void finalize();
|
||||
|
||||
void run();
|
||||
|
||||
void addStatic(PendingSensitivity *);
|
||||
void setDynamic(Sensitivity *);
|
||||
|
||||
virtual Fiber *fiber() { return Fiber::primaryFiber(); }
|
||||
|
||||
static Process *newest() { return _newest; }
|
||||
@@ -93,7 +299,12 @@ class Process : public ::sc_core::sc_object, public ListNode
|
||||
|
||||
static Process *_newest;
|
||||
|
||||
virtual ~Process() { delete func; }
|
||||
virtual ~Process()
|
||||
{
|
||||
delete func;
|
||||
for (auto s: staticSensitivities)
|
||||
delete s;
|
||||
}
|
||||
|
||||
::sc_core::sc_event _resetEvent;
|
||||
::sc_core::sc_event _terminatedEvent;
|
||||
@@ -113,8 +324,26 @@ class Process : public ::sc_core::sc_object, public ListNode
|
||||
int refCount;
|
||||
|
||||
size_t stackSize;
|
||||
|
||||
Sensitivities staticSensitivities;
|
||||
PendingSensitivities pendingStaticSensitivities;
|
||||
|
||||
Sensitivity *dynamicSensitivity;
|
||||
};
|
||||
|
||||
inline void
|
||||
Sensitivity::notify(Event *e)
|
||||
{
|
||||
if (!process->disabled())
|
||||
notifyWork(e);
|
||||
}
|
||||
|
||||
inline const std::string
|
||||
Sensitivity::name()
|
||||
{
|
||||
return std::string(process->name()) + ".timeout";
|
||||
}
|
||||
|
||||
} // namespace sc_gem5
|
||||
|
||||
#endif //__SYSTEMC_CORE_PROCESS_HH__
|
||||
|
||||
@@ -28,17 +28,25 @@
|
||||
*/
|
||||
|
||||
#include "base/logging.hh"
|
||||
#include "systemc/core/bindinfo.hh"
|
||||
#include "systemc/ext/core/sc_port.hh"
|
||||
|
||||
namespace sc_core
|
||||
{
|
||||
|
||||
sc_port_base::sc_port_base(const char *name, int n, sc_port_policy p) :
|
||||
sc_object(name)
|
||||
{}
|
||||
|
||||
void
|
||||
sc_port_base::warn_unimpl(const char *func) const
|
||||
{
|
||||
warn("%s not implemented.\n", func);
|
||||
}
|
||||
|
||||
int sc_port_base::maxSize() const { return _maxSize; }
|
||||
int sc_port_base::size() const { return _gem5BindInfo.size(); }
|
||||
|
||||
void
|
||||
sc_port_base::bind(sc_interface &)
|
||||
{
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
*/
|
||||
|
||||
#include "base/logging.hh"
|
||||
#include "systemc/core/process.hh"
|
||||
#include "systemc/ext/core/sc_interface.hh"
|
||||
#include "systemc/ext/core/sc_sensitive.hh"
|
||||
|
||||
namespace sc_core
|
||||
@@ -36,30 +38,34 @@ namespace sc_core
|
||||
sc_sensitive::sc_sensitive() : currentProcess(nullptr) {}
|
||||
|
||||
sc_sensitive &
|
||||
sc_sensitive::operator << (const sc_event &)
|
||||
sc_sensitive::operator << (const sc_event &e)
|
||||
{
|
||||
warn("%s not implemented.\n", __PRETTY_FUNCTION__);
|
||||
currentProcess->addStatic(
|
||||
new sc_gem5::PendingSensitivityEvent(currentProcess, &e));
|
||||
return *this;
|
||||
}
|
||||
|
||||
sc_sensitive &
|
||||
sc_sensitive::operator << (const sc_interface &)
|
||||
sc_sensitive::operator << (const sc_interface &i)
|
||||
{
|
||||
warn("%s not implemented.\n", __PRETTY_FUNCTION__);
|
||||
currentProcess->addStatic(
|
||||
new sc_gem5::PendingSensitivityInterface(currentProcess, &i));
|
||||
return *this;
|
||||
}
|
||||
|
||||
sc_sensitive &
|
||||
sc_sensitive::operator << (const sc_port_base &)
|
||||
sc_sensitive::operator << (const sc_port_base &b)
|
||||
{
|
||||
warn("%s not implemented.\n", __PRETTY_FUNCTION__);
|
||||
currentProcess->addStatic(
|
||||
new sc_gem5::PendingSensitivityPort(currentProcess, &b));
|
||||
return *this;
|
||||
}
|
||||
|
||||
sc_sensitive &
|
||||
sc_sensitive::operator << (sc_event_finder &)
|
||||
sc_sensitive::operator << (sc_event_finder &f)
|
||||
{
|
||||
warn("%s not implemented.\n", __PRETTY_FUNCTION__);
|
||||
currentProcess->addStatic(
|
||||
new sc_gem5::PendingSensitivityFinder(currentProcess, &f));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,14 +38,52 @@ namespace sc_gem5
|
||||
|
||||
Scheduler::Scheduler() :
|
||||
eq(nullptr), readyEvent(this, false, EventBase::Default_Pri + 1),
|
||||
_numCycles(0), _current(nullptr)
|
||||
_numCycles(0), _current(nullptr), initReady(false)
|
||||
{}
|
||||
|
||||
void
|
||||
Scheduler::initToReady()
|
||||
Scheduler::prepareForInit()
|
||||
{
|
||||
while (!initList.empty())
|
||||
ready(initList.getNext());
|
||||
for (Process *p = toFinalize.getNext(); p; p = toFinalize.getNext()) {
|
||||
p->finalize();
|
||||
p->popListNode();
|
||||
}
|
||||
|
||||
for (Process *p = initList.getNext(); p; p = initList.getNext()) {
|
||||
p->finalize();
|
||||
ready(p);
|
||||
}
|
||||
|
||||
initReady = true;
|
||||
}
|
||||
|
||||
void
|
||||
Scheduler::reg(Process *p)
|
||||
{
|
||||
if (initReady) {
|
||||
// If we're past initialization, finalize static sensitivity.
|
||||
p->finalize();
|
||||
// Mark the process as ready.
|
||||
ready(p);
|
||||
} else {
|
||||
// Otherwise, record that this process should be initialized once we
|
||||
// get there.
|
||||
initList.pushLast(p);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Scheduler::dontInitialize(Process *p)
|
||||
{
|
||||
if (initReady) {
|
||||
// Pop this process off of the ready list.
|
||||
p->popListNode();
|
||||
} else {
|
||||
// Push this process onto the list of processes which still need
|
||||
// their static sensitivity to be finalized. That implicitly pops it
|
||||
// off the list of processes to be initialized/marked ready.
|
||||
toFinalize.pushLast(p);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#ifndef __SYSTEMC_CORE_SCHEDULER_HH__
|
||||
#define __SYSTEMC_CORE_SCHEDULER_HH__
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "sim/eventq.hh"
|
||||
#include "systemc/core/channel.hh"
|
||||
#include "systemc/core/list.hh"
|
||||
@@ -58,7 +60,7 @@ typedef NodeList<Channel> ChannelList;
|
||||
* schedules an event to be run at time 0 with a slightly elevated priority
|
||||
* so that it happens before any "normal" event.
|
||||
*
|
||||
* When that t0 event happens, it calls the schedulers initToReady method
|
||||
* When that t0 event happens, it calls the schedulers prepareForInit method
|
||||
* which performs step 2 above. That indirectly causes the scheduler's
|
||||
* readyEvent to be scheduled with slightly lowered priority, ensuring it
|
||||
* happens after any "normal" event.
|
||||
@@ -115,11 +117,14 @@ class Scheduler
|
||||
uint64_t numCycles() { return _numCycles; }
|
||||
Process *current() { return _current; }
|
||||
|
||||
// Mark processes that need to be initialized as ready.
|
||||
void initToReady();
|
||||
// Prepare for initialization.
|
||||
void prepareForInit();
|
||||
|
||||
// Put a process on the list of processes to be initialized.
|
||||
void init(Process *p) { initList.pushLast(p); }
|
||||
// Register a process with the scheduler.
|
||||
void reg(Process *p);
|
||||
|
||||
// Tell the scheduler not to initialize a process.
|
||||
void dontInitialize(Process *p);
|
||||
|
||||
// Run the next process, if there is one.
|
||||
void yield();
|
||||
@@ -162,7 +167,10 @@ class Scheduler
|
||||
|
||||
Process *_current;
|
||||
|
||||
bool initReady;
|
||||
|
||||
ProcessList initList;
|
||||
ProcessList toFinalize;
|
||||
ProcessList readyList;
|
||||
|
||||
ChannelList updateList;
|
||||
|
||||
@@ -39,6 +39,8 @@ namespace sc_gem5
|
||||
{
|
||||
|
||||
class Event;
|
||||
class SensitivityEventAndList;
|
||||
class SensitivityEventOrList;
|
||||
|
||||
}
|
||||
|
||||
@@ -100,6 +102,7 @@ class sc_event_and_list
|
||||
|
||||
private:
|
||||
friend class sc_event_and_expr;
|
||||
friend class sc_gem5::SensitivityEventAndList;
|
||||
|
||||
explicit sc_event_and_list(bool auto_delete);
|
||||
|
||||
@@ -131,6 +134,7 @@ class sc_event_or_list
|
||||
|
||||
private:
|
||||
friend class sc_event_or_expr;
|
||||
friend class sc_gem5::SensitivityEventOrList;
|
||||
|
||||
explicit sc_event_or_list(bool auto_delete);
|
||||
|
||||
|
||||
@@ -30,9 +30,19 @@
|
||||
#ifndef __SYSTEMC_EXT_CORE_SC_PORT_HH__
|
||||
#define __SYSTEMC_EXT_CORE_SC_PORT_HH__
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "sc_module.hh" // for sc_gen_unique_name
|
||||
#include "sc_object.hh"
|
||||
|
||||
namespace sc_gem5
|
||||
{
|
||||
|
||||
class BindInfo;
|
||||
class PendingSensitivityPort;
|
||||
|
||||
};
|
||||
|
||||
namespace sc_core
|
||||
{
|
||||
|
||||
@@ -48,11 +58,13 @@ enum sc_port_policy
|
||||
class sc_port_base : public sc_object
|
||||
{
|
||||
public:
|
||||
sc_port_base(const char *name, int n, sc_port_policy p) : sc_object(name)
|
||||
{}
|
||||
sc_port_base(const char *name, int n, sc_port_policy p);
|
||||
|
||||
void warn_unimpl(const char *func) const;
|
||||
|
||||
int maxSize() const;
|
||||
int size() const;
|
||||
|
||||
protected:
|
||||
// Implementation defined, but depended on by the tests.
|
||||
void bind(sc_interface &);
|
||||
@@ -61,6 +73,12 @@ class sc_port_base : public sc_object
|
||||
// Implementation defined, but depended on by the tests.
|
||||
virtual int vbind(sc_interface &) = 0;
|
||||
virtual int vbind(sc_port_base &) = 0;
|
||||
|
||||
private:
|
||||
friend class ::sc_gem5::PendingSensitivityPort;
|
||||
|
||||
std::vector<::sc_gem5::BindInfo *> _gem5BindInfo;
|
||||
int _maxSize;
|
||||
};
|
||||
|
||||
template <class IF>
|
||||
|
||||
Reference in New Issue
Block a user