Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an example of PEvent generation #145

Merged
merged 11 commits into from
Feb 4, 2024
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,39 @@ dyff between baseline.yaml always_hit_DL1.yaml
-l top.*.*.decode info decode_rob.log \
-l top.*.*.rob info decode_rob.log
```
### Generate PEvents (for Correlation)

PEvents or Performance Events are part of the Sparta Modeling
Framework typically used to correlate a performance model with RTL.
Unlike pipeout collection Name/Value Definition Pairs (see an example
in
[Inst.hpp](https://github.com/riscv-software-src/riscv-perf-model/blob/db6c2f1878381389966544d7844c7d10c557083e/core/Inst.hpp#L330)),
PEvent Name/Value Definitions are typically more compact. Below the
surface, Sparta uses the logging infrastructure to collect the data.

Olympia has instrumented a few PEvents as an example. The following
commands are useful in listing/using this functionality.

```
# Dump the list of supported PEvents
./olympia --help-pevents --no-run

# Generate RETIRE only pevents for the first 100 instructions of Dhrystone
./olympia traces/dhry_riscv.zstf --pevents retire.out RETIRE -i100

# Generate COMPLETE only pevents ...
./olympia traces/dhry_riscv.zstf --pevents complete.out COMPLETE -i100

# Generate COMPLETE pevents into complete.out and RETIRE pevents into retire.out ...
./olympia traces/dhry_riscv.zstf --pevents retire.out RETIRE --pevents complete.out COMPLETE -i100

# Generate RETIRE and COMPLETE pevents to the same file
./olympia traces/dhry_riscv.zstf --pevents complete_retire.out RETIRE,COMPLETE -i100

# Generate all pevents
./olympia traces/dhry_riscv.zstf --pevents complete_retire.out ALL -i100
```

### Generate Reports
```
# Run with 1M instructions, generate a report from the top of the tree
Expand Down
4 changes: 4 additions & 0 deletions conda/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ If `conda` is not already set up or the preference is to have a local

## Create a New Environment or Update Existing Conda Environment

** If these steps do no work, follow the directions on
[Map/Sparta](https://github.com/sparcians/map/tree/master#building-map)
instead **

A new environment can be created using `environment.yaml` file as follows:

```
Expand Down
1 change: 1 addition & 0 deletions core/ExecutePipe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ namespace olympia
void ExecutePipe::completeInst_(const InstPtr & ex_inst)
{
ex_inst->setStatus(Inst::Status::COMPLETED);
complete_event_.collect(*ex_inst);
ILOG("Completing inst: " << ex_inst);
}

Expand Down
6 changes: 6 additions & 0 deletions core/ExecutePipe.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "sparta/simulation/ResourceFactory.hpp"
#include "sparta/collection/Collectable.hpp"
#include "sparta/resources/Scoreboard.hpp"
#include "sparta/pevents/PeventCollector.hpp"

#include "Inst.hpp"
#include "CoreTypes.hpp"
Expand Down Expand Up @@ -111,6 +112,11 @@ namespace olympia
// A pipeline collector
sparta::collection::Collectable<InstPtr> collected_inst_;

// For correlation activities
sparta::pevents::PeventCollector<InstPEventPairs> complete_event_{"COMPLETE",
getContainer(),
getClock()};

// Counter
sparta::Counter total_insts_issued_{
getStatisticSet(), "total_insts_issued",
Expand Down
34 changes: 27 additions & 7 deletions core/Inst.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,19 +322,23 @@ namespace olympia

/*!
* \class InstPairDef
* \brief Pair Definition class of the Example instruction that flows through the example/CoreModel
* \brief Pair Definition class of the instruction that flows through the Olympia
*
* This is the definition of the PairDefinition class of Inst.
* It's mostly used for pipeline collection (-z option). This
* PairDefinition class could be named anything but it needs to
* inherit publicly from sparta::PairDefinition templatized on the
* actual class Inst.
*/
// This is the definition of the PairDefinition class of Inst.
// This PairDefinition class could be named anything but it needs to
// inherit publicly from sparta::PairDefinition templatized on the actual class Inst.
class InstPairDef : public sparta::PairDefinition<Inst>{
class InstPairDef : public sparta::PairDefinition<Inst>
{
public:

// The SPARTA_ADDPAIRs APIs must be called during the construction of the PairDefinition class
InstPairDef() : PairDefinition<Inst>(){
InstPairDef() : PairDefinition<Inst>() {
SPARTA_INVOKE_PAIRS(Inst);
}
SPARTA_REGISTER_PAIRS(SPARTA_ADDPAIR("DID", &Inst::getUniqueID),
SPARTA_REGISTER_PAIRS(SPARTA_ADDPAIR("DID", &Inst::getUniqueID), // Used by Argos to color code
SPARTA_ADDPAIR("uid", &Inst::getUniqueID),
SPARTA_ADDPAIR("mnemonic", &Inst::getMnemonic),
SPARTA_ADDPAIR("complete", &Inst::getCompletedStatus),
Expand All @@ -344,6 +348,22 @@ namespace olympia
SPARTA_ADDPAIR("tgt_vaddr", &Inst::getTargetVAddr, std::ios::hex))
};

/*!
* \class PEventPairs
* \brief Pair Definitions for pevents
*/
class InstPEventPairs : public sparta::PairDefinition<Inst>
{
public:
using TypeCollected = Inst;

InstPEventPairs() : sparta::PairDefinition<Inst>()
{
addPEventsPair("uid", &Inst::getUniqueID);
addPEventsPair("pc", &Inst::getPC, std::ios::hex);
}
};

// Instruction allocators
using InstAllocator = sparta::SpartaSharedPointerAllocator<Inst>;
using InstArchInfoAllocator = sparta::SpartaSharedPointerAllocator<InstArchInfo>;
Expand Down
51 changes: 50 additions & 1 deletion core/LoadStoreInstInfo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,18 @@

#include "MemoryAccessInfo.hpp"

#include "sparta/simulation/State.hpp"
#include "sparta/pairs/SpartaKeyPairs.hpp"

#include <cinttypes>
#include <string>

namespace olympia
{
// Forward declaration of the Pair Definition class is must as we
// are friending it.
class LoadStoreInstInfoPair;

class LoadStoreInstInfo
{
public:
Expand Down Expand Up @@ -31,6 +41,11 @@ namespace olympia
__LAST = NUM_STATES
};

// The modeler needs to alias a type called
// "SpartaPairDefinitionType" to the Pair Definition class of
// itself
using SpartaPairDefinitionType = LoadStoreInstInfoPair;

LoadStoreInstInfo() = delete;

LoadStoreInstInfo(const MemoryAccessInfoPtr & info_ptr) :
Expand All @@ -56,6 +71,13 @@ namespace olympia
return mem_access_info_ptr == nullptr ? 0 : mem_access_info_ptr->getInstUniqueID();
}

// Get the mnemonic of the instruction this load/store is
// associated. Will return <unassoc> if not associated
std::string getMnemonic() const {
return (mem_access_info_ptr_ != nullptr ?
mem_access_info_ptr_->getMnemonic() : "<unassoc>");
}

void setPriority(const IssuePriority & rank) { rank_.setValue(rank); }

const IssuePriority & getPriority() const { return rank_.getEnumValue(); }
Expand Down Expand Up @@ -184,4 +206,31 @@ namespace olympia
os << *ls_info;
return os;
}
} // namespace olympia

/*!
* \class LoadStoreInstInfoPair
* \brief Pair Definition class of the LoadStoreInstInfo for pipeout collection
*
* This is the definition of the PairDefinition class of LoadStoreInstInfo.
* It's mostly used for pipeline collection (-z option). This
* PairDefinition class could be named anything but it needs to
* inherit publicly from sparta::PairDefinition templatized on the
* actual class LoadStoreInstInfo.
*/
class LoadStoreInstInfoPair : public sparta::PairDefinition<LoadStoreInstInfo>
{
public:

// The SPARTA_ADDPAIRs APIs must be called during the construction of the PairDefinition class
LoadStoreInstInfoPair() : sparta::PairDefinition<LoadStoreInstInfo>() {
SPARTA_INVOKE_PAIRS(LoadStoreInstInfo);
}
SPARTA_REGISTER_PAIRS(SPARTA_ADDPAIR("DID", &LoadStoreInstInfo::getInstUniqueID), // Used by Argos to color code
SPARTA_ADDPAIR("uid", &LoadStoreInstInfo::getInstUniqueID),
SPARTA_ADDPAIR("mnemonic", &LoadStoreInstInfo::getMnemonic),
SPARTA_ADDPAIR("pri:", &LoadStoreInstInfo::getPriority),
SPARTA_ADDPAIR("state", &LoadStoreInstInfo::getState))
};


} // namespace olympia
40 changes: 38 additions & 2 deletions core/MemoryAccessInfo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ namespace olympia
using LoadStoreInstIterator = sparta::Buffer<LoadStoreInstInfoPtr>::const_iterator;

class MemoryAccessInfoPairDef;

class MemoryAccessInfo;

using MemoryAccessInfoPtr = sparta::SpartaSharedPointer<MemoryAccessInfo>;
Expand Down Expand Up @@ -59,6 +58,11 @@ namespace olympia
__LAST = NUM_UNITS
};

// The modeler needs to alias a type called
// "SpartaPairDefinitionType" to the Pair Definition class of
// itself
using SpartaPairDefinitionType = MemoryAccessInfoPairDef;

MemoryAccessInfo() = delete;

MemoryAccessInfo(const MemoryAccessInfo &rhs) = default;
Expand All @@ -82,11 +86,17 @@ namespace olympia
// and we will use this pointer to query values from functions of Inst class
const InstPtr & getInstPtr() const { return ldst_inst_ptr_; }

// Get the mnemonic of the instruction this load/store is
// associated. Will return <unassoc> if not associated
std::string getMnemonic() const {
return (ldst_inst_ptr_ != nullptr ?
ldst_inst_ptr_->getMnemonic() : "<unassoc>");
}

// This is a function which will be added in the SPARTA_ADDPAIRs API.
uint64_t getInstUniqueID() const
{
const InstPtr & inst_ptr = getInstPtr();

return inst_ptr == nullptr ? 0 : inst_ptr->getUniqueID();
}

Expand Down Expand Up @@ -256,4 +266,30 @@ namespace olympia
os << *mem_ptr;
return os;
}

/*!
* \class MemoryAccessInfoPairDef
* \brief Pair Definition class of the MemoryAccessInfo for pipeout collection
*
* This is the definition of the PairDefinition class of MemoryAccessInfo.
* It's mostly used for pipeline collection (-z option). This
* PairDefinition class could be named anything but it needs to
* inherit publicly from sparta::PairDefinition templatized on the
* actual class MemoryAccessInfo.
*/
class MemoryAccessInfoPairDef : public sparta::PairDefinition<MemoryAccessInfo>
{
public:

// The SPARTA_ADDPAIRs APIs must be called during the construction of the PairDefinition class
MemoryAccessInfoPairDef() : sparta::PairDefinition<MemoryAccessInfo>() {
SPARTA_INVOKE_PAIRS(MemoryAccessInfo);
}
SPARTA_REGISTER_PAIRS(SPARTA_ADDPAIR("DID", &MemoryAccessInfo::getInstUniqueID), // Used by Argos to color code
SPARTA_ADDPAIR("uid", &MemoryAccessInfo::getInstUniqueID),
SPARTA_ADDPAIR("mnemonic", &MemoryAccessInfo::getMnemonic),
SPARTA_ADDPAIR("mmu", &MemoryAccessInfo::getMMUState),
SPARTA_ADDPAIR("dcs", &MemoryAccessInfo::getCacheState))
};

}; // namespace olympia
3 changes: 2 additions & 1 deletion core/ROB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ namespace olympia

ILOG("retiring " << ex_inst);

retire_event_.collect(*ex_inst_ptr);

// Use the program ID to verify that the program order has been maintained.
sparta_assert(ex_inst.getProgramID() == expected_program_id_,
"Unexpected program ID when retiring instruction"
Expand Down Expand Up @@ -177,7 +179,6 @@ namespace olympia
FlushManager::FlushingCriteria criteria(FlushManager::FlushCause::POST_SYNC, ex_inst_ptr);
out_retire_flush_.send(criteria);


++num_flushes_;
break;
}
Expand Down
7 changes: 5 additions & 2 deletions core/ROB.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// <ROB.h> -*- C++ -*-

// <ROB.hpp> -*- C++ -*-

#pragma once
#include <string>
Expand All @@ -10,6 +9,7 @@
#include "sparta/simulation/ParameterSet.hpp"
#include "sparta/simulation/TreeNode.hpp"
#include "sparta/log/MessageSource.hpp"
#include "sparta/pevents/PeventCollector.hpp"

#include "sparta/statistics/Counter.hpp"
#include "sparta/statistics/StatisticDef.hpp"
Expand Down Expand Up @@ -112,6 +112,9 @@ namespace olympia
sparta::UniqueEvent<> ev_retire_ {&unit_event_set_, "retire_insts",
CREATE_SPARTA_HANDLER(ROB, retireEvent_)};

// For correlation activities
sparta::pevents::PeventCollector<InstPEventPairs> retire_event_{"RETIRE", getContainer(), getClock()};

// A nice checker to make sure forward progress is being made
// Note that in the ROB constructor, this event is set as non-continuing
sparta::Clock::Cycle last_retirement_ = 0; // Last retirement cycle for checking stalled retire
Expand Down
8 changes: 4 additions & 4 deletions reports/dhry_report.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ content:
top:
"cpu.core0.rob.stats.ipc" : "IPC"

# Assuming 1 iteration is about 265 instructions, calculate the
# Assuming 1 iteration is about 239 instructions, calculate the
# cycles per iteration
"265 / cpu.core0.rob.stats.ipc" : "Cycles Per Iteration"
"239 / cpu.core0.rob.stats.ipc" : "Cycles Per Iteration"

# Assume a 1MHz part, determine the iterations per second
"1e6 / (265 / cpu.core0.rob.stats.ipc)" : "Iterations Per Second"
"1e6 / (239 / cpu.core0.rob.stats.ipc)" : "Iterations Per Second"

# Assume a 1MHz part, determine the DMIPs based on the VAX 1780
# achieving a 1757 Dhrystones per second score
"(1e6 / (265 / cpu.core0.rob.stats.ipc)) / 1757" : "DMIPS Per MHz"
"(1e6 / (239 / cpu.core0.rob.stats.ipc)) / 1757" : "DMIPS Per MHz"
11 changes: 11 additions & 0 deletions test/sim/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,23 @@ sparta_named_test(olympia_coremark_test_report_html olympia -i 1M
--report reports/core_report.def
--workload traces/core_riscv.zstf)

# Test missing opcodes
sparta_named_test(olympia_json_test_missing_opcodes olympia
--workload json_tests/missing_opcodes.json)

# Test FP transfers
sparta_named_test(olympia_json_test_fp_transfers olympia
--workload json_tests/fp_transfers.json)

# Test PEvent generation
sparta_named_test(olympia_json_test_pevents olympia
--workload traces/dhry_riscv.zstf
--pevents test_pevent.out RETIRE
--pevents test_pevent.out COMPLETE)
sparta_named_test(olympia_json_test_pevents_all olympia
--workload traces/dhry_riscv.zstf
--pevents test_pevent.out all)

## Test the arches
file(GLOB TEST_YAML "${SIM_BASE}/arches/*.yaml")
foreach(ARCH_FULL_PATH ${TEST_YAML})
Expand Down
Loading