vcpumntirqWrapper(vcpumntirq, params.name + ".vcpumntirq", -1),
cntpnsirqWrapper(cntpnsirq, params.name + ".cntpnsirq", -1),
clockChanged(Iris::ClockEventName.c_str()),
- clockPeriod(Iris::PeriodAttributeName.c_str())
+ clockPeriod(Iris::PeriodAttributeName.c_str()),
+ gem5Cpu(Iris::Gem5CpuAttributeName.c_str())
{
clockRateControl.bind(clock_rate_s);
set_parameter("core.cpu0.vfp-enable_at_reset",
params.cpu0_vfp_enable_at_reset);
+ add_attribute(gem5Cpu);
add_attribute(clockPeriod);
SC_METHOD(clockChangeHandler);
dont_initialize();
#include "systemc/ext/core/sc_module.hh"
#include "systemc/sc_port_wrapper.hh"
+class BaseCPU;
+
// This macro is to get the type IF of a sc_export<IF> variable x. It relies on
// the fact that the "operator->()" function returns the "IF*" type and
// std::decay to remove cv-qualifiers and reference.
sc_core::sc_event clockChanged;
sc_core::sc_attribute<Tick> clockPeriod;
+ sc_core::sc_attribute<::BaseCPU *> gem5Cpu;
void clockChangeHandler();
namespace Iris
{
+BaseCPU::BaseCPU(BaseCPUParams *params, sc_core::sc_module *_evs) :
+ ::BaseCPU::BaseCPU(params), evs(_evs),
+ clockEvent(nullptr), periodAttribute(nullptr)
+{
+ sc_core::sc_attr_base *base;
+
+ base = evs->get_attribute(Gem5CpuAttributeName);
+ auto *gem5_cpu_attr =
+ dynamic_cast<sc_core::sc_attribute<::BaseCPU *> *>(base);
+ panic_if(base && !gem5_cpu_attr,
+ "The EVS gem5 CPU attribute was not of type "
+ "sc_attribute<::BaesCPU *>.");
+ if (gem5_cpu_attr)
+ gem5_cpu_attr->value = this;
+
+ const auto &event_vec = evs->get_child_events();
+ auto event_it = std::find_if(event_vec.begin(), event_vec.end(),
+ [](const sc_core::sc_event *e) -> bool {
+ return e->basename() == ClockEventName; });
+ if (event_it != event_vec.end())
+ clockEvent = *event_it;
+
+ base = evs->get_attribute(PeriodAttributeName);
+ periodAttribute = dynamic_cast<sc_core::sc_attribute<Tick> *>(base);
+ panic_if(base && !periodAttribute,
+ "The EVS clock period attribute is not of type "
+ "sc_attribute<Tick>.");
+}
+
BaseCPU::~BaseCPU()
{
for (auto &tc: threadContexts)
// The name of the attribute the subsystem should create which can be set to
// the desired clock period, in gem5's Ticks.
static const std::string PeriodAttributeName = "gem5_clock_period_attribute";
+// The name of the attribute the subsystem should create which will be set to
+// a pointer to its corresponding gem5 CPU.
+static const std::string Gem5CpuAttributeName = "gem5_cpu";
// This CPU class adds some mechanisms which help attach the gem5 and fast
// model CPUs to each other. It acts as a base class for the gem5 CPU, and
class BaseCPU : public ::BaseCPU
{
public:
- BaseCPU(BaseCPUParams *params, sc_core::sc_module *_evs) :
- ::BaseCPU::BaseCPU(params), evs(_evs),
- clockEvent(nullptr), periodAttribute(nullptr)
- {}
+ BaseCPU(BaseCPUParams *params, sc_core::sc_module *_evs);
virtual ~BaseCPU();
Port &
sc_core::sc_event *clockEvent;
sc_core::sc_attribute<Tick> *periodAttribute;
- bool
- findClockControls()
- {
- if (!clockEvent) {
- const auto &event_vec = evs->get_child_events();
- auto event_it = std::find_if(event_vec.begin(), event_vec.end(),
- [](const sc_core::sc_event *e) -> bool {
- return e->basename() == ClockEventName; });
- if (event_it != event_vec.end())
- clockEvent = *event_it;
- }
- if (!periodAttribute) {
- sc_core::sc_attr_base *base =
- evs->get_attribute(PeriodAttributeName);
- periodAttribute =
- dynamic_cast<sc_core::sc_attribute<Tick> *>(base);
- panic_if(base && !periodAttribute,
- "The EVS clock period attribute is not of type "
- "sc_attribute<Tick>.");
- }
- return clockEvent && periodAttribute;
- }
-
protected:
void
clockPeriodUpdated() override
{
- if (!findClockControls()) {
+ if (!clockEvent || !periodAttribute) {
warn("Unable to notify EVS of clock change, missing:");
warn_if(!clockEvent, " Clock change event");
warn_if(!periodAttribute, " Clock period attribute");