39a40
> * Jose Marinho
50a52
> #include "dev/arm/generic_timer.hh"
64c66,69
< counters(p->eventCounters),
---
> maximumCounterCount(p->eventCounters),
> cycleCounter(*this, maximumCounterCount),
> cycleCounterEventId(p->cycleEventId),
> swIncrementEvent(nullptr),
71c76
< if (p->eventCounters > 31) {
---
> if (maximumCounterCount > 31) {
73c78
< p->eventCounters);
---
> maximumCounterCount);
90a96,117
> PMU::addSoftwareIncrementEvent(unsigned int id)
> {
> auto old_event = eventMap.find(id);
> DPRINTF(PMUVerbose, "PMU: Adding SW increment event with id '0x%x'\n", id);
>
> if (swIncrementEvent) {
> fatal_if(old_event == eventMap.end() ||
> old_event->second != swIncrementEvent,
> "Trying to add a software increment event with multiple"
> "IDs. This is not supported.\n");
> return;
> }
>
> fatal_if(old_event != eventMap.end(), "An event with id %d has "
> "been previously defined\n", id);
>
> swIncrementEvent = new SWIncrementEvent();
> eventMap[id] = swIncrementEvent;
> registerEvent(id);
> }
>
> void
93,95d119
< DPRINTF(PMUVerbose, "PMU: Adding event type '0x%x' as probe %s:%s\n",
< id, obj->name(), probe_name);
< pmuEventTypes.insert(std::make_pair(id, EventType(obj, probe_name)));
96a121,145
> DPRINTF(PMUVerbose, "PMU: Adding Probe Driven event with id '0x%x'"
> "as probe %s:%s\n",id, obj->name(), probe_name);
>
> RegularEvent *event = nullptr;
> auto event_entry = eventMap.find(id);
> if (event_entry == eventMap.end()) {
>
> event = new RegularEvent();
> eventMap[id] = event;
>
> } else {
> event = dynamic_cast<RegularEvent*>(event_entry->second);
> if (!event) {
> fatal("Event with id %d is not probe driven\n", id);
> }
> }
> event->addMicroarchitectureProbe(obj, probe_name);
>
> registerEvent(id);
>
> }
>
> void
> PMU::registerEvent(uint32_t id)
> {
117a167,182
> PMU::regProbeListeners()
> {
>
> // at this stage all probe configurations are done
> // counters can be configured
> for (uint32_t index = 0; index < maximumCounterCount-1; index++) {
> counters.emplace_back(*this, index);
> }
>
> PMUEvent *event = getEvent(cycleCounterEventId);
> panic_if(!event, "core cycle event is not present\n");
> cycleCounter.enabled = true;
> cycleCounter.attach(event);
> }
>
> void
148,153c213,214
< for (int i = 0; i < counters.size(); ++i) {
< CounterState &ctr(getCounter(i));
< if (ctr.enabled && (val & (1 << i))
< && ctr.eventId == ARCH_EVENT_SW_INCR ) {
< ++ctr.value;
< }
---
> if (swIncrementEvent) {
> swIncrementEvent->write(val);
155c216
< break;
---
> return;
159c220
< cycleCounter.value = val;
---
> cycleCounter.setValue(val);
281c342
< return cycleCounter.value;
---
> return cycleCounter.getValue();
284c345
< return cycleCounter.value & 0xFFFFFFFF;
---
> return cycleCounter.getValue() & 0xFFFFFFFF;
298,299c359,361
< case MISCREG_PMEVCNTR0_EL0...MISCREG_PMEVCNTR5_EL0:
< return getCounterValue(misc_reg - MISCREG_PMEVCNTR0_EL0) & 0xFFFFFFFF;
---
> case MISCREG_PMEVCNTR0_EL0...MISCREG_PMEVCNTR5_EL0: {
> return getCounterValue(misc_reg - MISCREG_PMEVCNTR0_EL0) &
> 0xFFFFFFFF;
300a363,364
> }
>
337c401
< cycleCounter.value = 0;
---
> cycleCounter.setValue(0);
358c422
< updateCounter(i, ctr);
---
> updateCounter(ctr);
365c429
< updateCounter(PMCCNTR, cycleCounter);
---
> updateCounter(cycleCounter);
368a433,481
> void
> PMU::PMUEvent::attachEvent(PMU::CounterState *user)
> {
> if (userCounters.empty()) {
> enable();
> }
> userCounters.insert(user);
> updateAttachedCounters();
> }
>
> void
> PMU::PMUEvent::increment(const uint64_t val)
> {
> for (auto& counter: userCounters) {
> counter->add(val);
> }
> }
>
> void
> PMU::PMUEvent::detachEvent(PMU::CounterState *user)
> {
> userCounters.erase(user);
>
> if (userCounters.empty()) {
> disable();
> }
> }
>
> void
> PMU::RegularEvent::RegularProbe::notify(const uint64_t &val)
> {
> parentEvent->increment(val);
> }
>
> void
> PMU::RegularEvent::enable()
> {
> for (auto& subEvents: microArchitectureEventSet) {
> attachedProbePointList.emplace_back(
> new RegularProbe(this, subEvents.first, subEvents.second));
> }
> }
>
> void
> PMU::RegularEvent::disable()
> {
> attachedProbePointList.clear();
> }
>
370c483
< PMU::isFiltered(const CounterState &ctr) const
---
> PMU::CounterState::isFiltered() const
372c485
< assert(isa);
---
> assert(pmu.isa);
374,376c487,489
< const PMEVTYPER_t filter(ctr.filter);
< const SCR scr(isa->readMiscRegNoEffect(MISCREG_SCR));
< const CPSR cpsr(isa->readMiscRegNoEffect(MISCREG_CPSR));
---
> const PMEVTYPER_t filter(this->filter);
> const SCR scr(pmu.isa->readMiscRegNoEffect(MISCREG_SCR));
> const CPSR cpsr(pmu.isa->readMiscRegNoEffect(MISCREG_CPSR));
399c512
< PMU::handleEvent(CounterId id, uint64_t delta)
---
> PMU::CounterState::detach()
401,402c514,521
< CounterState &ctr(getCounter(id));
< const bool overflowed(reg_pmovsr & (1 << id));
---
> if (sourceEvent) {
> sourceEvent->detachEvent(this);
> sourceEvent = nullptr;
> } else {
> debugCounter("detaching event not currently attached"
> " to any event\n");
> }
> }
404,405c523,529
< if (isFiltered(ctr))
< return;
---
> void
> PMU::CounterState::attach(PMUEvent* event)
> {
> value = 0;
> sourceEvent = event;
> sourceEvent->attachEvent(this);
> }
407,411c531,538
< // Handle the "count every 64 cycles" mode
< if (id == PMCCNTR && reg_pmcr.d) {
< clock_remainder += delta;
< delta = (clock_remainder >> 6);
< clock_remainder &= 63;
---
> uint64_t
> PMU::CounterState::getValue() const
> {
> if (sourceEvent) {
> sourceEvent->updateAttachedCounters();
> } else {
> debugCounter("attempted to get value from a counter without"
> " an associated event\n");
412a540,541
> return value;
> }
414,421c543,553
< // Add delta and handle (new) overflows
< if (ctr.add(delta) && !overflowed) {
< DPRINTF(PMUVerbose, "PMU counter '%i' overflowed.\n", id);
< reg_pmovsr |= (1 << id);
< // Deliver a PMU interrupt if interrupt delivery is enabled
< // for this counter.
< if (reg_pminten & (1 << id))
< raiseInterrupt();
---
> void
> PMU::CounterState::setValue(uint64_t val)
> {
> value = val;
> resetValue = true;
>
> if (sourceEvent) {
> sourceEvent->updateAttachedCounters();
> } else {
> debugCounter("attempted to set value from a counter without"
> " an associated event\n");
426c558
< PMU::updateCounter(CounterId id, CounterState &ctr)
---
> PMU::updateCounter(CounterState &ctr)
429,432c561,564
< if (!ctr.listeners.empty()) {
< DPRINTF(PMUVerbose, "updateCounter(%i): Disabling counter\n", id);
< ctr.listeners.clear();
< }
---
> DPRINTF(PMUVerbose, "updateCounter(%i): Disabling counter\n",
> ctr.getCounterId());
> ctr.detach();
>
435c567
< id, ctr.eventId);
---
> ctr.getCounterId(), ctr.eventId);
437,450c569,570
< // Attach all probes belonging to this event
< auto range(pmuEventTypes.equal_range(ctr.eventId));
< for (auto it = range.first; it != range.second; ++it) {
< const EventType &et(it->second);
<
< DPRINTF(PMUVerbose, "\tProbe: %s:%s\n", et.obj->name(), et.name);
< ctr.listeners.emplace_back(et.create(*this, id));
< }
<
< /* The SW_INCR event type is a special case which doesn't need
< * any probes since it is controlled by software and the PMU
< * itself.
< */
< if (ctr.listeners.empty() && ctr.eventId != ARCH_EVENT_SW_INCR) {
---
> auto sourceEvent = eventMap.find(ctr.eventId);
> if (sourceEvent == eventMap.end()) {
452a573,574
> } else {
> ctr.attach(sourceEvent->second);
462c584
< ctr.value = 0;
---
> ctr.setValue(0);
475c597
< ctr.value = val;
---
> ctr.setValue(val);
512c634
< updateCounter(reg_pmselr.sel, ctr);
---
> updateCounter(ctr);
576a699,711
> PMU::PMUEvent*
> PMU::getEvent(uint64_t eventId)
> {
> auto entry = eventMap.find(eventId);
>
> if (entry == eventMap.end()) {
> warn("event %d does not exist\n", eventId);
> return nullptr;
> } else {
> return entry->second;
> }
> }
>
593c728
< bool
---
> uint64_t
596,597c731,736
< const uint64_t msb(1ULL << (overflow64 ? 63 : 31));
< const uint64_t old_value(value);
---
> uint64_t value_until_overflow;
> if (overflow64) {
> value_until_overflow = UINT64_MAX - value;
> } else {
> value_until_overflow = UINT32_MAX - (uint32_t)value;
> }
599c738,739
< value += delta;
---
> if (isFiltered())
> return value_until_overflow;
601,602c741,761
< // Overflow if the msb goes from 1 to 0
< return (old_value & msb) && !(value & msb);
---
> if (resetValue) {
> delta = 0;
> resetValue = false;
> } else {
> value += delta;
> }
>
> if (delta > value_until_overflow) {
>
> // overflow situation detected
> // flag the overflow occurence
> pmu.reg_pmovsr |= (1 << counterId);
>
> // Deliver a PMU interrupt if interrupt delivery is enabled
> // for this counter.
> if (pmu.reg_pminten & (1 << counterId)) {
> pmu.raiseInterrupt();
> }
> return overflow64 ? UINT64_MAX : UINT32_MAX;
> }
> return value_until_overflow - delta + 1;
604a764,773
> void
> PMU::SWIncrementEvent::write(uint64_t val)
> {
> for (auto& counter: userCounters) {
> if (val & (0x1 << counter->getCounterId())) {
> counter->add(1);
> }
> }
> }
>