Merge branch 'work/demonstrator' into 'develop'
New DRAMSys simulator approach See merge request ems/astdm/modeling.dram/dram.sys.5!5
This commit is contained in:
@@ -77,7 +77,7 @@ endif()
|
||||
set(DRAMSYS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src")
|
||||
set(DRAMSYS_LIBRARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/lib")
|
||||
set(DRAMSYS_TESTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tests")
|
||||
set(DRAMSYS_RESOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/resources")
|
||||
set(DRAMSYS_RESOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/configs")
|
||||
set(DRAMSYS_EXTENSIONS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extensions")
|
||||
|
||||
### Build options ###
|
||||
@@ -137,6 +137,7 @@ FetchContent_Declare(
|
||||
GIT_REPOSITORY https://github.com/accellera-official/systemc.git
|
||||
GIT_TAG 2.3.4)
|
||||
|
||||
set(DISABLE_COPYRIGHT_MESSAGE True)
|
||||
FetchContent_MakeAvailable(systemc)
|
||||
set_target_properties(systemc PROPERTIES FOLDER lib)
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ The JSON code below shows an example configuration:
|
||||
},
|
||||
{
|
||||
"clkMhz": 2000,
|
||||
"type": "generator",
|
||||
"name": "gen0",
|
||||
"numRequests": 2000,
|
||||
"rwRatio": 0.85,
|
||||
@@ -32,7 +31,6 @@ The JSON code below shows an example configuration:
|
||||
},
|
||||
{
|
||||
"clkMhz": 1000,
|
||||
"type": "hammer",
|
||||
"name": "ham0",
|
||||
"numRequests": 4000,
|
||||
"rowIncrement": 2097152
|
||||
@@ -49,11 +47,58 @@ Field Descriptions:
|
||||
- "mcconfig": memory controller configuration file
|
||||
- "tracesetup": The trace setup is only used in standalone mode. In library mode or gem5 mode the trace setup is ignored. Each device should be added as a json object inside the "tracesetup" array.
|
||||
|
||||
Each **trace setup** device configuration can be a **trace player** ("type": "player"), a **traffic generator** ("type": "generator") or a **row hammer generator** ("type": "hammer"). By not specifing the **type** parameter, the device will act as a **trace player**.
|
||||
Each **trace setup** device configuration can be a **trace player**, a **traffic generator** or a **row hammer generator**. The type will be automatically concluded based on the given parameters.
|
||||
All device configurations must define a **clkMhz** (operation frequency of the **traffic initiator**) and a **name** (in case of a trace player this specifies the **trace file** to play; in case of a generator this field is only for identification purposes).
|
||||
The **maxPendingReadRequests** and **maxPendingWriteRequests** parameters define the maximum number of outstanding read/write requests. The current implementation delays all memory accesses if one limit is reached. The default value (0) disables the limit.
|
||||
|
||||
A **traffic generator** can be configured to generate **numRequests** requests in total, of which the **rwRatio** field defines the probability of one request being a read request. The length of a request (in bytes) can be specified with the **dataLength** parameter. The **seed** parameter can be used to produce identical results for all simulations. **minAddress** and **maxAddress** specify the address range, by default the whole address range is used. The parameter **addressDistribution** can either be set to **random** or **sequential**. In case of **sequential** the additional **addressIncrement** field must be specified, defining the address increment after each request.
|
||||
A **traffic generator** can be configured to generate **numRequests** requests in total, of which the **rwRatio** field defines the probability of one request being a read request. The length of a request (in bytes) can be specified with the **dataLength** parameter. The **seed** parameter can be used to produce identical results for all simulations. **minAddress** and **maxAddress** specify the address range, by default the whole address range is used. The parameter **addressDistribution** can either be set to **random** or **sequential**. In case of **sequential** the additional **addressIncrement** field must be specified, defining the address increment after each request. The address alignment of the random generator can be configured using the **dataAlignment** field. By default, the addresses will be naturally aligned at dataLength.
|
||||
|
||||
For more advanced use cases, the traffic generator is capable of acting as a state machine with multiple states that can be configured in the same manner as described earlier. Each state is specified as an element in the **states** array. Each state has to include an unique **id**. The **transitions** field describes all possible transitions from one state to another with their associated **probability**.
|
||||
In the context of a state machine, there exists another type of generator: the idle generator. In an idle state no requests are issued. The parameter **idleClks** specifies the duration of the idle state.
|
||||
|
||||
An example of a state machine configuration with 3 states is shown below.
|
||||
|
||||
```json
|
||||
{
|
||||
"clkMhz": 100,
|
||||
"maxPendingReadRequests": 8,
|
||||
"name": "StateMachine",
|
||||
"states": [
|
||||
{
|
||||
"addressDistribution": "sequential",
|
||||
"addressIncrement": 256,
|
||||
"id": 0,
|
||||
"maxAddress": 1024,
|
||||
"numRequests": 1000,
|
||||
"rwRatio": 0.5
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"idleClks": 1000
|
||||
},
|
||||
{
|
||||
"addressDistribution": "random",
|
||||
"id": 2,
|
||||
"maxAddress": 2048,
|
||||
"minAddress": 1024,
|
||||
"numRequests": 1000,
|
||||
"rwRatio": 0.75
|
||||
}
|
||||
],
|
||||
"transitions": [
|
||||
{
|
||||
"from": 0,
|
||||
"probability": 1.0,
|
||||
"to": 1
|
||||
},
|
||||
{
|
||||
"from": 1,
|
||||
"probability": 1.0,
|
||||
"to": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The **row hammer generator** is a special traffic generator that mimics a row hammer attack. It generates **numRequests** alternating read requests to two different addresses. The first address is 0x0, the second address is specified by the **rowIncrement** parameter and should decode to a different row in the same bank. Since only one outstanding request is allowed, the controller cannot perform any reordering, forcing a row switch (precharge and activate) for each access. That way the number of activations on the target rows are maximized.
|
||||
|
||||
@@ -182,7 +227,7 @@ Used fields:
|
||||
|
||||
```json
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"XOR": [
|
||||
{
|
||||
"FIRST": 13,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
28,
|
||||
29,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
13,
|
||||
14,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
27,
|
||||
28,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
13,
|
||||
14,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
28,
|
||||
29,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
13,
|
||||
14,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
26,
|
||||
27,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
13,
|
||||
14,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANKGROUP_BIT":[
|
||||
28,
|
||||
29
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BYTE_BIT": [
|
||||
0,
|
||||
1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BYTE_BIT": [
|
||||
0,
|
||||
1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BYTE_BIT": [
|
||||
0,
|
||||
1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BYTE_BIT": [
|
||||
0,
|
||||
1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"PSEUDOCHANNEL_BIT":[
|
||||
29
|
||||
],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"PSEUDOCHANNEL_BIT":[
|
||||
28
|
||||
],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
28,
|
||||
29,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
11,
|
||||
12,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
5,
|
||||
6,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
27,
|
||||
28,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
11,
|
||||
12,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
5,
|
||||
6,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
27,
|
||||
28,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BYTE_BIT": [
|
||||
0
|
||||
],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BYTE_BIT": [
|
||||
0
|
||||
],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BYTE_BIT": [
|
||||
0
|
||||
],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BYTE_BIT": [
|
||||
0
|
||||
],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BYTE_BIT": [
|
||||
0
|
||||
],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BYTE_BIT": [
|
||||
0
|
||||
],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BYTE_BIT": [
|
||||
0
|
||||
],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BYTE_BIT": [
|
||||
0
|
||||
],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BYTE_BIT": [
|
||||
0
|
||||
],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BYTE_BIT": [
|
||||
0
|
||||
],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BYTE_BIT": [
|
||||
0
|
||||
],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BYTE_BIT": [
|
||||
0
|
||||
],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"RANK_BIT":[
|
||||
30,
|
||||
31
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
13,
|
||||
14,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
25,
|
||||
26,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
12,
|
||||
13,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
25,
|
||||
26
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
11,
|
||||
12
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
23,
|
||||
24
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
11,
|
||||
12
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
26,
|
||||
27
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
11,
|
||||
12
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
27,
|
||||
28
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
12,
|
||||
13
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
24,
|
||||
25
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
11,
|
||||
12
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"addressmapping": {
|
||||
"BANK_BIT": [
|
||||
4,
|
||||
5
|
||||
|
||||
@@ -217,7 +217,7 @@ void SimulationDialog::saveConfiguration(QFile &file)
|
||||
|
||||
loadConfigurationFromTextFields();
|
||||
|
||||
std::string dump = DRAMSys::Config::dump(configuration, 4);
|
||||
std::string dump = nlohmann::json(configuration).dump(4);
|
||||
out << dump.c_str();
|
||||
}
|
||||
|
||||
@@ -252,13 +252,13 @@ void SimulationDialog::loadConfigurationFromTextFields()
|
||||
|
||||
try
|
||||
{
|
||||
from_dump(ui->addressMappingTextEdit->toPlainText().toStdString(), addressMapping);
|
||||
from_dump(ui->mcConfigTextEdit->toPlainText().toStdString(), mcConfig);
|
||||
from_dump(ui->memSpecTextEdit->toPlainText().toStdString(), memSpec);
|
||||
from_dump(ui->simConfigTextEdit->toPlainText().toStdString(), simConfig);
|
||||
nlohmann::json::parse(ui->addressMappingTextEdit->toPlainText().toStdString()).get_to(addressMapping);
|
||||
nlohmann::json::parse(ui->mcConfigTextEdit->toPlainText().toStdString()).get_to(mcConfig);
|
||||
nlohmann::json::parse(ui->memSpecTextEdit->toPlainText().toStdString()).get_to(memSpec);
|
||||
nlohmann::json::parse(ui->simConfigTextEdit->toPlainText().toStdString()).get_to(simConfig);
|
||||
|
||||
if (!ui->traceSetupTextEdit->toPlainText().toStdString().empty())
|
||||
from_dump(ui->traceSetupTextEdit->toPlainText().toStdString(), traceSetup);
|
||||
nlohmann::json::parse(ui->traceSetupTextEdit->toPlainText().toStdString()).get_to(traceSetup);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
@@ -300,9 +300,9 @@ void SimulationDialog::loadConfiguration()
|
||||
{
|
||||
ui->simulationIdLabel->setEnabled(true);
|
||||
ui->simulationId->setEnabled(true);
|
||||
ui->simulationId->setText(configuration.simulationId.c_str());
|
||||
ui->simulationId->setText(configuration.simulationid.c_str());
|
||||
|
||||
ui->simulationIdLineEdit->setText(configuration.simulationId.c_str());
|
||||
ui->simulationIdLineEdit->setText(configuration.simulationid.c_str());
|
||||
|
||||
loadSimConfig();
|
||||
loadMcConfig();
|
||||
@@ -316,7 +316,7 @@ void SimulationDialog::loadSimConfig()
|
||||
{
|
||||
ui->simConfigTextEdit->clear();
|
||||
|
||||
std::string dump = DRAMSys::Config::dump(configuration.simConfig, 4);
|
||||
std::string dump = nlohmann::json(configuration.simconfig).dump(4);
|
||||
ui->simConfigTextEdit->setText(dump.c_str());
|
||||
}
|
||||
|
||||
@@ -324,7 +324,7 @@ void SimulationDialog::loadMcConfig()
|
||||
{
|
||||
ui->mcConfigTextEdit->clear();
|
||||
|
||||
std::string dump = DRAMSys::Config::dump(configuration.mcConfig, 4);
|
||||
std::string dump = nlohmann::json(configuration.mcconfig).dump(4);
|
||||
ui->mcConfigTextEdit->setText(dump.c_str());
|
||||
}
|
||||
|
||||
@@ -332,7 +332,7 @@ void SimulationDialog::loadMemSpec()
|
||||
{
|
||||
ui->memSpecTextEdit->clear();
|
||||
|
||||
std::string dump = DRAMSys::Config::dump(configuration.memSpec, 4);
|
||||
std::string dump = nlohmann::json(configuration.memspec).dump(4);
|
||||
ui->memSpecTextEdit->setText(dump.c_str());
|
||||
}
|
||||
|
||||
@@ -340,7 +340,7 @@ void SimulationDialog::loadAddressMapping()
|
||||
{
|
||||
ui->addressMappingTextEdit->clear();
|
||||
|
||||
std::string dump = DRAMSys::Config::dump(configuration.addressMapping, 4);
|
||||
std::string dump = nlohmann::json(configuration.addressmapping).dump(4);
|
||||
ui->addressMappingTextEdit->setText(dump.c_str());
|
||||
}
|
||||
|
||||
@@ -348,9 +348,9 @@ void SimulationDialog::loadTraceSetup()
|
||||
{
|
||||
ui->traceSetupTextEdit->clear();
|
||||
|
||||
if (const auto &traceSetup = configuration.traceSetup)
|
||||
if (const auto &traceSetup = configuration.tracesetup)
|
||||
{
|
||||
std::string dump = DRAMSys::Config::dump(*traceSetup, 4);
|
||||
std::string dump = nlohmann::json(*traceSetup).dump(4);
|
||||
ui->traceSetupTextEdit->setText(dump.c_str());
|
||||
}
|
||||
}
|
||||
@@ -359,7 +359,7 @@ void SimulationDialog::loadPreview()
|
||||
{
|
||||
ui->previewTextEdit->clear();
|
||||
|
||||
std::string dump = DRAMSys::Config::dump(configuration, 4);
|
||||
std::string dump = nlohmann::json(configuration).dump(4);
|
||||
ui->previewTextEdit->setText(dump.c_str());
|
||||
}
|
||||
|
||||
@@ -372,7 +372,7 @@ QFileInfoList SimulationDialog::getSimulationResults()
|
||||
|
||||
for (const auto &fileInfo : baseDir.entryInfoList())
|
||||
{
|
||||
if (fileInfo.baseName().startsWith(configuration.simulationId.c_str()))
|
||||
if (fileInfo.baseName().startsWith(configuration.simulationid.c_str()))
|
||||
{
|
||||
// Dont open tracefiles that are older than a few seconds
|
||||
if (fileInfo.metadataChangeTime().secsTo(QDateTime::currentDateTime()) > 30)
|
||||
|
||||
@@ -45,80 +45,80 @@ using namespace tlm;
|
||||
|
||||
MemSpecDDR5::MemSpecDDR5(const DRAMSys::Config::MemSpec &memSpec)
|
||||
: MemSpec(memSpec, MemoryType::DDR5,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfChannels"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfChannels"),
|
||||
1,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks")
|
||||
/ memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks")
|
||||
* memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups")
|
||||
* memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfDevices")),
|
||||
dimmRanksPerChannel(memSpec.memArchitectureSpec.entries.at("nbrOfDIMMRanks")),
|
||||
physicalRanksPerDimmRank(memSpec.memArchitectureSpec.entries.at("nbrOfPhysicalRanks")),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks")
|
||||
/ memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks")
|
||||
* memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBankGroups")
|
||||
* memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfDevices")),
|
||||
dimmRanksPerChannel(memSpec.memarchitecturespec.entries.at("nbrOfDIMMRanks")),
|
||||
physicalRanksPerDimmRank(memSpec.memarchitecturespec.entries.at("nbrOfPhysicalRanks")),
|
||||
physicalRanksPerChannel(physicalRanksPerDimmRank * dimmRanksPerChannel),
|
||||
logicalRanksPerPhysicalRank(memSpec.memArchitectureSpec.entries.at("nbrOfLogicalRanks")),
|
||||
logicalRanksPerPhysicalRank(memSpec.memarchitecturespec.entries.at("nbrOfLogicalRanks")),
|
||||
logicalRanksPerChannel(logicalRanksPerPhysicalRank * physicalRanksPerChannel),
|
||||
cmdMode(memSpec.memArchitectureSpec.entries.at("cmdMode")),
|
||||
refMode(memSpec.memArchitectureSpec.entries.at("refMode")),
|
||||
RAAIMT(memSpec.memArchitectureSpec.entries.at("RAAIMT")),
|
||||
RAAMMT(memSpec.memArchitectureSpec.entries.at("RAAMMT")),
|
||||
RAACDR(memSpec.memArchitectureSpec.entries.at("RAACDR")),
|
||||
tRCD (tCK * memSpec.memTimingSpec.entries.at("RCD")),
|
||||
tPPD (tCK * memSpec.memTimingSpec.entries.at("PPD")),
|
||||
tRP (tCK * memSpec.memTimingSpec.entries.at("RP")),
|
||||
tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")),
|
||||
cmdMode(memSpec.memarchitecturespec.entries.at("cmdMode")),
|
||||
refMode(memSpec.memarchitecturespec.entries.at("refMode")),
|
||||
RAAIMT(memSpec.memarchitecturespec.entries.at("RAAIMT")),
|
||||
RAAMMT(memSpec.memarchitecturespec.entries.at("RAAMMT")),
|
||||
RAACDR(memSpec.memarchitecturespec.entries.at("RAACDR")),
|
||||
tRCD (tCK * memSpec.memtimingspec.entries.at("RCD")),
|
||||
tPPD (tCK * memSpec.memtimingspec.entries.at("PPD")),
|
||||
tRP (tCK * memSpec.memtimingspec.entries.at("RP")),
|
||||
tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")),
|
||||
tRC (tRAS + tRP),
|
||||
tRL (tCK * memSpec.memTimingSpec.entries.at("RL")),
|
||||
tRTP (tCK * memSpec.memTimingSpec.entries.at("RTP")),
|
||||
tRPRE (tCK * memSpec.memTimingSpec.entries.at("RPRE")),
|
||||
tRPST (tCK * memSpec.memTimingSpec.entries.at("RPST")),
|
||||
tRDDQS (tCK * memSpec.memTimingSpec.entries.at("RDDQS")),
|
||||
tWL (tCK * memSpec.memTimingSpec.entries.at("WL")),
|
||||
tWPRE (tCK * memSpec.memTimingSpec.entries.at("WPRE")),
|
||||
tWPST (tCK * memSpec.memTimingSpec.entries.at("WPST")),
|
||||
tWR (tCK * memSpec.memTimingSpec.entries.at("WR")),
|
||||
tCCD_L_slr (tCK * memSpec.memTimingSpec.entries.at("CCD_L_slr")),
|
||||
tCCD_L_WR_slr (tCK * memSpec.memTimingSpec.entries.at("CCD_L_WR_slr")),
|
||||
tCCD_L_WR2_slr (tCK * memSpec.memTimingSpec.entries.at("CCD_L_WR2_slr")),
|
||||
tCCD_M_slr (tCK * memSpec.memTimingSpec.entries.at("CCD_M_slr")),
|
||||
tCCD_M_WR_slr (tCK * memSpec.memTimingSpec.entries.at("CCD_M_WR_slr")),
|
||||
tCCD_S_slr (tCK * memSpec.memTimingSpec.entries.at("CCD_S_slr")),
|
||||
tCCD_S_WR_slr (tCK * memSpec.memTimingSpec.entries.at("CCD_S_WR_slr")),
|
||||
tCCD_dlr (tCK * memSpec.memTimingSpec.entries.at("CCD_dlr")),
|
||||
tCCD_WR_dlr (tCK * memSpec.memTimingSpec.entries.at("CCD_WR_dlr")),
|
||||
tCCD_WR_dpr (tCK * memSpec.memTimingSpec.entries.at("CCD_WR_dpr")),
|
||||
tRRD_L_slr (tCK * memSpec.memTimingSpec.entries.at("RRD_L_slr")),
|
||||
tRRD_S_slr (tCK * memSpec.memTimingSpec.entries.at("RRD_S_slr")),
|
||||
tRRD_dlr (tCK * memSpec.memTimingSpec.entries.at("RRD_dlr")),
|
||||
tFAW_slr (tCK * memSpec.memTimingSpec.entries.at("FAW_slr")),
|
||||
tFAW_dlr (tCK * memSpec.memTimingSpec.entries.at("FAW_dlr")),
|
||||
tWTR_L (tCK * memSpec.memTimingSpec.entries.at("WTR_L")),
|
||||
tWTR_M (tCK * memSpec.memTimingSpec.entries.at("WTR_M")),
|
||||
tWTR_S (tCK * memSpec.memTimingSpec.entries.at("WTR_S")),
|
||||
tRFC_slr ((refMode == 1) ? tCK * memSpec.memTimingSpec.entries.at("RFC1_slr")
|
||||
: tCK * memSpec.memTimingSpec.entries.at("RFC2_slr")),
|
||||
tRFC_dlr ((refMode == 1) ? tCK * memSpec.memTimingSpec.entries.at("RFC1_dlr")
|
||||
: tCK * memSpec.memTimingSpec.entries.at("RFC2_dlr")),
|
||||
tRFC_dpr ((refMode == 1) ? tCK * memSpec.memTimingSpec.entries.at("RFC1_dpr")
|
||||
: tCK * memSpec.memTimingSpec.entries.at("RFC2_dpr")),
|
||||
tRFCsb_slr (tCK * memSpec.memTimingSpec.entries.at("RFCsb_slr")),
|
||||
tRFCsb_dlr (tCK * memSpec.memTimingSpec.entries.at("RFCsb_dlr")),
|
||||
tREFI ((refMode == 1) ? tCK * memSpec.memTimingSpec.entries.at("REFI1")
|
||||
: tCK * memSpec.memTimingSpec.entries.at("REFI2")),
|
||||
tREFIsb (tCK * memSpec.memTimingSpec.entries.at("REFISB")),
|
||||
tREFSBRD_slr (tCK * memSpec.memTimingSpec.entries.at("REFSBRD_slr")),
|
||||
tREFSBRD_dlr (tCK * memSpec.memTimingSpec.entries.at("REFSBRD_dlr")),
|
||||
tRTRS (tCK * memSpec.memTimingSpec.entries.at("RTRS")),
|
||||
tCPDED (tCK * memSpec.memTimingSpec.entries.at("CPDED")),
|
||||
tPD (tCK * memSpec.memTimingSpec.entries.at("PD")),
|
||||
tXP (tCK * memSpec.memTimingSpec.entries.at("XP")),
|
||||
tACTPDEN (tCK * memSpec.memTimingSpec.entries.at("ACTPDEN")),
|
||||
tPRPDEN (tCK * memSpec.memTimingSpec.entries.at("PRPDEN")),
|
||||
tREFPDEN (tCK * memSpec.memTimingSpec.entries.at("REFPDEN")),
|
||||
tRL (tCK * memSpec.memtimingspec.entries.at("RL")),
|
||||
tRTP (tCK * memSpec.memtimingspec.entries.at("RTP")),
|
||||
tRPRE (tCK * memSpec.memtimingspec.entries.at("RPRE")),
|
||||
tRPST (tCK * memSpec.memtimingspec.entries.at("RPST")),
|
||||
tRDDQS (tCK * memSpec.memtimingspec.entries.at("RDDQS")),
|
||||
tWL (tCK * memSpec.memtimingspec.entries.at("WL")),
|
||||
tWPRE (tCK * memSpec.memtimingspec.entries.at("WPRE")),
|
||||
tWPST (tCK * memSpec.memtimingspec.entries.at("WPST")),
|
||||
tWR (tCK * memSpec.memtimingspec.entries.at("WR")),
|
||||
tCCD_L_slr (tCK * memSpec.memtimingspec.entries.at("CCD_L_slr")),
|
||||
tCCD_L_WR_slr (tCK * memSpec.memtimingspec.entries.at("CCD_L_WR_slr")),
|
||||
tCCD_L_WR2_slr (tCK * memSpec.memtimingspec.entries.at("CCD_L_WR2_slr")),
|
||||
tCCD_M_slr (tCK * memSpec.memtimingspec.entries.at("CCD_M_slr")),
|
||||
tCCD_M_WR_slr (tCK * memSpec.memtimingspec.entries.at("CCD_M_WR_slr")),
|
||||
tCCD_S_slr (tCK * memSpec.memtimingspec.entries.at("CCD_S_slr")),
|
||||
tCCD_S_WR_slr (tCK * memSpec.memtimingspec.entries.at("CCD_S_WR_slr")),
|
||||
tCCD_dlr (tCK * memSpec.memtimingspec.entries.at("CCD_dlr")),
|
||||
tCCD_WR_dlr (tCK * memSpec.memtimingspec.entries.at("CCD_WR_dlr")),
|
||||
tCCD_WR_dpr (tCK * memSpec.memtimingspec.entries.at("CCD_WR_dpr")),
|
||||
tRRD_L_slr (tCK * memSpec.memtimingspec.entries.at("RRD_L_slr")),
|
||||
tRRD_S_slr (tCK * memSpec.memtimingspec.entries.at("RRD_S_slr")),
|
||||
tRRD_dlr (tCK * memSpec.memtimingspec.entries.at("RRD_dlr")),
|
||||
tFAW_slr (tCK * memSpec.memtimingspec.entries.at("FAW_slr")),
|
||||
tFAW_dlr (tCK * memSpec.memtimingspec.entries.at("FAW_dlr")),
|
||||
tWTR_L (tCK * memSpec.memtimingspec.entries.at("WTR_L")),
|
||||
tWTR_M (tCK * memSpec.memtimingspec.entries.at("WTR_M")),
|
||||
tWTR_S (tCK * memSpec.memtimingspec.entries.at("WTR_S")),
|
||||
tRFC_slr ((refMode == 1) ? tCK * memSpec.memtimingspec.entries.at("RFC1_slr")
|
||||
: tCK * memSpec.memtimingspec.entries.at("RFC2_slr")),
|
||||
tRFC_dlr ((refMode == 1) ? tCK * memSpec.memtimingspec.entries.at("RFC1_dlr")
|
||||
: tCK * memSpec.memtimingspec.entries.at("RFC2_dlr")),
|
||||
tRFC_dpr ((refMode == 1) ? tCK * memSpec.memtimingspec.entries.at("RFC1_dpr")
|
||||
: tCK * memSpec.memtimingspec.entries.at("RFC2_dpr")),
|
||||
tRFCsb_slr (tCK * memSpec.memtimingspec.entries.at("RFCsb_slr")),
|
||||
tRFCsb_dlr (tCK * memSpec.memtimingspec.entries.at("RFCsb_dlr")),
|
||||
tREFI ((refMode == 1) ? tCK * memSpec.memtimingspec.entries.at("REFI1")
|
||||
: tCK * memSpec.memtimingspec.entries.at("REFI2")),
|
||||
tREFIsb (tCK * memSpec.memtimingspec.entries.at("REFISB")),
|
||||
tREFSBRD_slr (tCK * memSpec.memtimingspec.entries.at("REFSBRD_slr")),
|
||||
tREFSBRD_dlr (tCK * memSpec.memtimingspec.entries.at("REFSBRD_dlr")),
|
||||
tRTRS (tCK * memSpec.memtimingspec.entries.at("RTRS")),
|
||||
tCPDED (tCK * memSpec.memtimingspec.entries.at("CPDED")),
|
||||
tPD (tCK * memSpec.memtimingspec.entries.at("PD")),
|
||||
tXP (tCK * memSpec.memtimingspec.entries.at("XP")),
|
||||
tACTPDEN (tCK * memSpec.memtimingspec.entries.at("ACTPDEN")),
|
||||
tPRPDEN (tCK * memSpec.memtimingspec.entries.at("PRPDEN")),
|
||||
tREFPDEN (tCK * memSpec.memtimingspec.entries.at("REFPDEN")),
|
||||
shortCmdOffset (cmdMode == 2 ? 1 * tCK : 0 * tCK),
|
||||
longCmdOffset (cmdMode == 2 ? 3 * tCK : 1 * tCK),
|
||||
tBURST16 (tCK * 8),
|
||||
|
||||
@@ -44,51 +44,51 @@ using namespace tlm;
|
||||
|
||||
MemSpecHBM3::MemSpecHBM3(const DRAMSys::Config::MemSpec &memSpec)
|
||||
: MemSpec(memSpec, MemoryType::HBM3,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfChannels"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfPseudoChannels"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfPseudoChannels"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks")
|
||||
/ memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks")
|
||||
* memSpec.memArchitectureSpec.entries.at("nbrOfPseudoChannels"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups")
|
||||
* memSpec.memArchitectureSpec.entries.at("nbrOfPseudoChannels"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfDevices")),
|
||||
RAAIMT(memSpec.memArchitectureSpec.entries.at("RAAIMT")),
|
||||
RAAMMT(memSpec.memArchitectureSpec.entries.at("RAAMMT")),
|
||||
RAACDR(memSpec.memArchitectureSpec.entries.at("RAACDR")),
|
||||
tDQSCK (tCK * memSpec.memTimingSpec.entries.at("DQSCK")),
|
||||
tRC (tCK * memSpec.memTimingSpec.entries.at("RC")),
|
||||
tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")),
|
||||
tRCDRD (tCK * memSpec.memTimingSpec.entries.at("RCDRD")),
|
||||
tRCDWR (tCK * memSpec.memTimingSpec.entries.at("RCDWR")),
|
||||
tRRDL (tCK * memSpec.memTimingSpec.entries.at("RRDL")),
|
||||
tRRDS (tCK * memSpec.memTimingSpec.entries.at("RRDS")),
|
||||
tFAW (tCK * memSpec.memTimingSpec.entries.at("FAW")),
|
||||
tRTP (tCK * memSpec.memTimingSpec.entries.at("RTP")),
|
||||
tRP (tCK * memSpec.memTimingSpec.entries.at("RP")),
|
||||
tRL (tCK * memSpec.memTimingSpec.entries.at("RL")),
|
||||
tWL (tCK * memSpec.memTimingSpec.entries.at("WL")),
|
||||
tPL (tCK * memSpec.memTimingSpec.entries.at("PL")),
|
||||
tWR (tCK * memSpec.memTimingSpec.entries.at("WR")),
|
||||
tCCDL (tCK * memSpec.memTimingSpec.entries.at("CCDL")),
|
||||
tCCDS (tCK * memSpec.memTimingSpec.entries.at("CCDS")),
|
||||
tWTRL (tCK * memSpec.memTimingSpec.entries.at("WTRL")),
|
||||
tWTRS (tCK * memSpec.memTimingSpec.entries.at("WTRS")),
|
||||
tRTW (tCK * memSpec.memTimingSpec.entries.at("RTW")),
|
||||
tXP (tCK * memSpec.memTimingSpec.entries.at("XP")),
|
||||
tCKE (tCK * memSpec.memTimingSpec.entries.at("CKE")),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfChannels"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfPseudoChannels"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfPseudoChannels"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks")
|
||||
/ memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks")
|
||||
* memSpec.memarchitecturespec.entries.at("nbrOfPseudoChannels"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBankGroups")
|
||||
* memSpec.memarchitecturespec.entries.at("nbrOfPseudoChannels"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfDevices")),
|
||||
RAAIMT(memSpec.memarchitecturespec.entries.at("RAAIMT")),
|
||||
RAAMMT(memSpec.memarchitecturespec.entries.at("RAAMMT")),
|
||||
RAACDR(memSpec.memarchitecturespec.entries.at("RAACDR")),
|
||||
tDQSCK (tCK * memSpec.memtimingspec.entries.at("DQSCK")),
|
||||
tRC (tCK * memSpec.memtimingspec.entries.at("RC")),
|
||||
tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")),
|
||||
tRCDRD (tCK * memSpec.memtimingspec.entries.at("RCDRD")),
|
||||
tRCDWR (tCK * memSpec.memtimingspec.entries.at("RCDWR")),
|
||||
tRRDL (tCK * memSpec.memtimingspec.entries.at("RRDL")),
|
||||
tRRDS (tCK * memSpec.memtimingspec.entries.at("RRDS")),
|
||||
tFAW (tCK * memSpec.memtimingspec.entries.at("FAW")),
|
||||
tRTP (tCK * memSpec.memtimingspec.entries.at("RTP")),
|
||||
tRP (tCK * memSpec.memtimingspec.entries.at("RP")),
|
||||
tRL (tCK * memSpec.memtimingspec.entries.at("RL")),
|
||||
tWL (tCK * memSpec.memtimingspec.entries.at("WL")),
|
||||
tPL (tCK * memSpec.memtimingspec.entries.at("PL")),
|
||||
tWR (tCK * memSpec.memtimingspec.entries.at("WR")),
|
||||
tCCDL (tCK * memSpec.memtimingspec.entries.at("CCDL")),
|
||||
tCCDS (tCK * memSpec.memtimingspec.entries.at("CCDS")),
|
||||
tWTRL (tCK * memSpec.memtimingspec.entries.at("WTRL")),
|
||||
tWTRS (tCK * memSpec.memtimingspec.entries.at("WTRS")),
|
||||
tRTW (tCK * memSpec.memtimingspec.entries.at("RTW")),
|
||||
tXP (tCK * memSpec.memtimingspec.entries.at("XP")),
|
||||
tCKE (tCK * memSpec.memtimingspec.entries.at("CKE")),
|
||||
tPD (tCKE),
|
||||
tCKESR (tCKE + tCK),
|
||||
tXS (tCK * memSpec.memTimingSpec.entries.at("XS")),
|
||||
tRFC (tCK * memSpec.memTimingSpec.entries.at("RFC")),
|
||||
tRFCPB (tCK * memSpec.memTimingSpec.entries.at("RFCPB")),
|
||||
tRREFD (tCK * memSpec.memTimingSpec.entries.at("RREFD")),
|
||||
tREFI (tCK * memSpec.memTimingSpec.entries.at("REFI")),
|
||||
tREFIPB (tCK * memSpec.memTimingSpec.entries.at("REFIPB")),
|
||||
tPPD (tCK * memSpec.memTimingSpec.entries.at("PPD"))
|
||||
tXS (tCK * memSpec.memtimingspec.entries.at("XS")),
|
||||
tRFC (tCK * memSpec.memtimingspec.entries.at("RFC")),
|
||||
tRFCPB (tCK * memSpec.memtimingspec.entries.at("RFCPB")),
|
||||
tRREFD (tCK * memSpec.memtimingspec.entries.at("RREFD")),
|
||||
tREFI (tCK * memSpec.memtimingspec.entries.at("REFI")),
|
||||
tREFIPB (tCK * memSpec.memtimingspec.entries.at("REFIPB")),
|
||||
tPPD (tCK * memSpec.memtimingspec.entries.at("PPD"))
|
||||
{
|
||||
commandLengthInCycles[Command::ACT] = 1.5;
|
||||
commandLengthInCycles[Command::PREPB] = 0.5;
|
||||
|
||||
@@ -44,42 +44,42 @@ using namespace tlm;
|
||||
|
||||
MemSpecLPDDR5::MemSpecLPDDR5(const DRAMSys::Config::MemSpec &memSpec)
|
||||
: MemSpec(memSpec, MemoryType::LPDDR5,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfChannels"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfChannels"),
|
||||
1,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks")
|
||||
/ memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks")
|
||||
* memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups")
|
||||
* memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfDevices")),
|
||||
per2BankOffset(memSpec.memArchitectureSpec.entries.at("per2BankOffset")),
|
||||
tREFI (tCK * memSpec.memTimingSpec.entries.at("REFI")),
|
||||
tREFIpb (tCK * memSpec.memTimingSpec.entries.at("REFIpb")),
|
||||
tRFCab (tCK * memSpec.memTimingSpec.entries.at("RFCab")),
|
||||
tRFCpb (tCK * memSpec.memTimingSpec.entries.at("RFCpb")),
|
||||
tRPab (tCK * memSpec.memTimingSpec.entries.at("RPab")),
|
||||
tRPpb (tCK * memSpec.memTimingSpec.entries.at("RPpb")),
|
||||
tRCab (tCK * memSpec.memTimingSpec.entries.at("RCab")),
|
||||
tRCpb (tCK * memSpec.memTimingSpec.entries.at("RCpb")),
|
||||
tPPD (tCK * memSpec.memTimingSpec.entries.at("PPD")),
|
||||
tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")),
|
||||
tRCD_L (tCK * memSpec.memTimingSpec.entries.at("RCD_L")),
|
||||
tRCD_S (tCK * memSpec.memTimingSpec.entries.at("RCD_S")),
|
||||
tFAW (tCK * memSpec.memTimingSpec.entries.at("FAW")),
|
||||
tRRD (tCK * memSpec.memTimingSpec.entries.at("RRD")),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks")
|
||||
/ memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks")
|
||||
* memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBankGroups")
|
||||
* memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfDevices")),
|
||||
per2BankOffset(memSpec.memarchitecturespec.entries.at("per2BankOffset")),
|
||||
tREFI (tCK * memSpec.memtimingspec.entries.at("REFI")),
|
||||
tREFIpb (tCK * memSpec.memtimingspec.entries.at("REFIpb")),
|
||||
tRFCab (tCK * memSpec.memtimingspec.entries.at("RFCab")),
|
||||
tRFCpb (tCK * memSpec.memtimingspec.entries.at("RFCpb")),
|
||||
tRPab (tCK * memSpec.memtimingspec.entries.at("RPab")),
|
||||
tRPpb (tCK * memSpec.memtimingspec.entries.at("RPpb")),
|
||||
tRCab (tCK * memSpec.memtimingspec.entries.at("RCab")),
|
||||
tRCpb (tCK * memSpec.memtimingspec.entries.at("RCpb")),
|
||||
tPPD (tCK * memSpec.memtimingspec.entries.at("PPD")),
|
||||
tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")),
|
||||
tRCD_L (tCK * memSpec.memtimingspec.entries.at("RCD_L")),
|
||||
tRCD_S (tCK * memSpec.memtimingspec.entries.at("RCD_S")),
|
||||
tFAW (tCK * memSpec.memtimingspec.entries.at("FAW")),
|
||||
tRRD (tCK * memSpec.memtimingspec.entries.at("RRD")),
|
||||
//tCCD (tCK * parseUint(memspec["memtimingspec"], "CCD")),
|
||||
tRL (tCK * memSpec.memTimingSpec.entries.at("RL")),
|
||||
tRL (tCK * memSpec.memtimingspec.entries.at("RL")),
|
||||
//tRPST (tCK * parseUint(memspec["memtimingspec"], "RPST")),
|
||||
//tDQSCK (tCK * parseUint(memspec["memtimingspec"], "DQSCK")),
|
||||
tRBTP (tCK * memSpec.memTimingSpec.entries.at("RBTP")),
|
||||
tWL (tCK * memSpec.memTimingSpec.entries.at("WL")),
|
||||
tRBTP (tCK * memSpec.memtimingspec.entries.at("RBTP")),
|
||||
tWL (tCK * memSpec.memtimingspec.entries.at("WL")),
|
||||
//tDQSS (tCK * parseUint(memspec["memtimingspec"], "DQSS")),
|
||||
//tDQS2DQ (tCK * parseUint(memspec["memtimingspec"], "DQS2DQ")),
|
||||
tWR (tCK * memSpec.memTimingSpec.entries.at("WR")),
|
||||
tWR (tCK * memSpec.memtimingspec.entries.at("WR")),
|
||||
//tWPRE (tCK * parseUint(memspec["memtimingspec"], "WPRE")),
|
||||
//tWTR (tCK * parseUint(memspec["memtimingspec"], "WTR")),
|
||||
//tXP (tCK * parseUint(memspec["memtimingspec"] "XP")),
|
||||
@@ -88,20 +88,20 @@ MemSpecLPDDR5::MemSpecLPDDR5(const DRAMSys::Config::MemSpec &memSpec)
|
||||
//tESCKE (tCK * parseUint(memspec["memtimingspec"], "ESCKE")),
|
||||
//tCKE (tCK * parseUint(memspec["memtimingspec"], "CKE")),
|
||||
//tCMDCKE (tCK * parseUint(memspec["memtimingspec"], "CMDCKE")),
|
||||
BL_n_min_16(tCK * memSpec.memTimingSpec.entries.at("BL_n_min_16")),
|
||||
BL_n_max_16(tCK * memSpec.memTimingSpec.entries.at("BL_n_max_16")),
|
||||
BL_n_L_16(tCK * memSpec.memTimingSpec.entries.at("BL_n_L_16")),
|
||||
BL_n_S_16(tCK * memSpec.memTimingSpec.entries.at("BL_n_S_16")),
|
||||
BL_n_min_32(tCK * memSpec.memTimingSpec.entries.at("BL_n_min_32")),
|
||||
BL_n_max_32(tCK * memSpec.memTimingSpec.entries.at("BL_n_max_32")),
|
||||
BL_n_L_32(tCK * memSpec.memTimingSpec.entries.at("BL_n_L_32")),
|
||||
BL_n_S_32(tCK * memSpec.memTimingSpec.entries.at("BL_n_S_32")),
|
||||
tWTR_L (tCK * memSpec.memTimingSpec.entries.at("WTR_L")),
|
||||
tWTR_S (tCK * memSpec.memTimingSpec.entries.at("WTR_S")),
|
||||
tWCK2DQO(tCK * memSpec.memTimingSpec.entries.at("WCK2DQO")),
|
||||
tpbR2act(tCK * memSpec.memTimingSpec.entries.at("pbR2act")),
|
||||
tpbR2pbR(tCK * memSpec.memTimingSpec.entries.at("pbR2pbR")),
|
||||
tRTRS (tCK * memSpec.memTimingSpec.entries.at("RTRS")),
|
||||
BL_n_min_16(tCK * memSpec.memtimingspec.entries.at("BL_n_min_16")),
|
||||
BL_n_max_16(tCK * memSpec.memtimingspec.entries.at("BL_n_max_16")),
|
||||
BL_n_L_16(tCK * memSpec.memtimingspec.entries.at("BL_n_L_16")),
|
||||
BL_n_S_16(tCK * memSpec.memtimingspec.entries.at("BL_n_S_16")),
|
||||
BL_n_min_32(tCK * memSpec.memtimingspec.entries.at("BL_n_min_32")),
|
||||
BL_n_max_32(tCK * memSpec.memtimingspec.entries.at("BL_n_max_32")),
|
||||
BL_n_L_32(tCK * memSpec.memtimingspec.entries.at("BL_n_L_32")),
|
||||
BL_n_S_32(tCK * memSpec.memtimingspec.entries.at("BL_n_S_32")),
|
||||
tWTR_L (tCK * memSpec.memtimingspec.entries.at("WTR_L")),
|
||||
tWTR_S (tCK * memSpec.memtimingspec.entries.at("WTR_S")),
|
||||
tWCK2DQO(tCK * memSpec.memtimingspec.entries.at("WCK2DQO")),
|
||||
tpbR2act(tCK * memSpec.memtimingspec.entries.at("pbR2act")),
|
||||
tpbR2pbR(tCK * memSpec.memtimingspec.entries.at("pbR2pbR")),
|
||||
tRTRS (tCK * memSpec.memtimingspec.entries.at("RTRS")),
|
||||
tBURST16(tCK * 16 / dataRate),
|
||||
tBURST32(tCK * 32 / dataRate),
|
||||
bankMode(groupsPerRank != 1 ? BankMode::MBG : (banksPerRank == 16 ? BankMode::M16B : BankMode::M8B))
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Technische Universität Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. 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.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder 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 HOLDER
|
||||
* 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:
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#include "AddressMapping.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace DRAMSys::Config
|
||||
{
|
||||
|
||||
void to_json(json_t &j, const AddressMapping &m)
|
||||
{
|
||||
auto congen = json_t{{"BYTE_BIT", m.byteBits},
|
||||
{"COLUMN_BIT", m.columnBits},
|
||||
{"ROW_BIT", m.rowBits},
|
||||
{"BANK_BIT", m.bankBits},
|
||||
{"BANKGROUP_BIT", m.bankGroupBits},
|
||||
{"RANK_BIT", m.rankBits},
|
||||
{"CHANNEL_BIT", m.channelBits},
|
||||
{"XOR", m.xorBits}};
|
||||
|
||||
remove_null_values(congen);
|
||||
|
||||
j["CONGEN"] = congen;
|
||||
}
|
||||
|
||||
void from_json(const json_t &j, AddressMapping &m)
|
||||
{
|
||||
json_t j_addressmapping = get_config_json(j, addressMappingPath, "CONGEN");
|
||||
|
||||
json_t congen;
|
||||
if (j_addressmapping["CONGEN"].is_null())
|
||||
congen = j_addressmapping;
|
||||
else
|
||||
congen = j_addressmapping["CONGEN"];
|
||||
|
||||
if (congen.contains("BYTE_BIT"))
|
||||
congen.at("BYTE_BIT").get_to(m.byteBits);
|
||||
|
||||
if (congen.contains("COLUMN_BIT"))
|
||||
congen.at("COLUMN_BIT").get_to(m.columnBits);
|
||||
|
||||
if (congen.contains("ROW_BIT"))
|
||||
congen.at("ROW_BIT").get_to(m.rowBits);
|
||||
|
||||
if (congen.contains("BANK_BIT"))
|
||||
congen.at("BANK_BIT").get_to(m.bankBits);
|
||||
|
||||
if (congen.contains("BANKGROUP_BIT"))
|
||||
congen.at("BANKGROUP_BIT").get_to(m.bankGroupBits);
|
||||
|
||||
if (congen.contains("RANK_BIT"))
|
||||
congen.at("RANK_BIT").get_to(m.rankBits);
|
||||
|
||||
// HBM pseudo channels are internally modelled as ranks
|
||||
if (congen.contains("PSEUDOCHANNEL_BIT"))
|
||||
congen.at("PSEUDOCHANNEL_BIT").get_to(m.rankBits);
|
||||
|
||||
if (congen.contains("CHANNEL_BIT"))
|
||||
congen.at("CHANNEL_BIT").get_to(m.channelBits);
|
||||
|
||||
if (congen.contains("XOR"))
|
||||
congen.at("XOR").get_to(m.xorBits);
|
||||
}
|
||||
|
||||
void to_json(json_t &j, const XorPair &x)
|
||||
{
|
||||
j = json_t{{"FIRST", x.first}, {"SECOND", x.second}};
|
||||
}
|
||||
|
||||
void from_json(const json_t &j, XorPair &x)
|
||||
{
|
||||
j.at("FIRST").get_to(x.first);
|
||||
j.at("SECOND").get_to(x.second);
|
||||
}
|
||||
|
||||
void from_dump(const std::string &dump, AddressMapping &c)
|
||||
{
|
||||
json_t json_addressmapping = json_t::parse(dump).at("addressmapping");
|
||||
json_addressmapping.get_to(c);
|
||||
}
|
||||
|
||||
std::string dump(const AddressMapping &c, unsigned int indentation)
|
||||
{
|
||||
json_t json_addressmapping;
|
||||
json_addressmapping["addressmapping"] = c;
|
||||
return json_addressmapping.dump(indentation);
|
||||
}
|
||||
|
||||
} // namespace DRAMSys::Config
|
||||
@@ -36,40 +36,47 @@
|
||||
#ifndef DRAMSYSCONFIGURATION_ADDRESSMAPPING_H
|
||||
#define DRAMSYSCONFIGURATION_ADDRESSMAPPING_H
|
||||
|
||||
#include "DRAMSys/config/ConfigUtil.h"
|
||||
#include "DRAMSys/util/json.h"
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace DRAMSys::Config
|
||||
{
|
||||
const std::string addressMappingPath = "addressmapping";
|
||||
|
||||
struct XorPair
|
||||
{
|
||||
unsigned int first;
|
||||
unsigned int second;
|
||||
unsigned int FIRST;
|
||||
unsigned int SECOND;
|
||||
};
|
||||
|
||||
void to_json(json_t &j, const XorPair &x);
|
||||
void from_json(const json_t &j, XorPair &x);
|
||||
NLOHMANN_JSONIFY_ALL_THINGS(XorPair, FIRST, SECOND)
|
||||
|
||||
struct AddressMapping
|
||||
{
|
||||
std::optional<std::vector<unsigned int>> byteBits;
|
||||
std::optional<std::vector<unsigned int>> columnBits;
|
||||
std::optional<std::vector<unsigned int>> rowBits;
|
||||
std::optional<std::vector<unsigned int>> bankBits;
|
||||
std::optional<std::vector<unsigned int>> bankGroupBits;
|
||||
std::optional<std::vector<unsigned int>> rankBits;
|
||||
std::optional<std::vector<unsigned int>> channelBits;
|
||||
std::optional<std::vector<XorPair>> xorBits;
|
||||
static constexpr std::string_view KEY = "addressmapping";
|
||||
static constexpr std::string_view SUB_DIR = "addressmapping";
|
||||
|
||||
std::optional<std::vector<unsigned int>> BYTE_BIT;
|
||||
std::optional<std::vector<unsigned int>> COLUMN_BIT;
|
||||
std::optional<std::vector<unsigned int>> ROW_BIT;
|
||||
std::optional<std::vector<unsigned int>> BANK_BIT;
|
||||
std::optional<std::vector<unsigned int>> BANKGROUP_BIT;
|
||||
std::optional<std::vector<unsigned int>> RANK_BIT;
|
||||
std::optional<std::vector<unsigned int>> PSEUDOCHANNEL_BIT;
|
||||
std::optional<std::vector<unsigned int>> CHANNEL_BIT;
|
||||
std::optional<std::vector<XorPair>> XOR;
|
||||
};
|
||||
|
||||
void to_json(json_t &j, const AddressMapping &m);
|
||||
void from_json(const json_t &j, AddressMapping &m);
|
||||
|
||||
void from_dump(const std::string &dump, AddressMapping &c);
|
||||
std::string dump(const AddressMapping &c, unsigned int indentation = -1);
|
||||
NLOHMANN_JSONIFY_ALL_THINGS(AddressMapping,
|
||||
BYTE_BIT,
|
||||
COLUMN_BIT,
|
||||
ROW_BIT,
|
||||
BANK_BIT,
|
||||
BANKGROUP_BIT,
|
||||
RANK_BIT,
|
||||
PSEUDOCHANNEL_BIT,
|
||||
CHANNEL_BIT,
|
||||
XOR)
|
||||
|
||||
} // namespace Configuration
|
||||
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Technische Universität Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. 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.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder 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 HOLDER
|
||||
* 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:
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#ifndef DRAMSYSCONFIGURATION_UTIL_H
|
||||
#define DRAMSYSCONFIGURATION_UTIL_H
|
||||
|
||||
#include "DRAMSys/util/json.h"
|
||||
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
namespace DRAMSys::Config
|
||||
{
|
||||
//using json_t = nlohmann::json;
|
||||
|
||||
// template <typename T>
|
||||
// class Optional : public std::pair<T, bool>
|
||||
// {
|
||||
// public:
|
||||
// Optional() : std::pair<T, bool>{{}, false}
|
||||
// {
|
||||
// }
|
||||
// Optional(const T &v) : std::pair<T, bool>{v, true}
|
||||
// {
|
||||
// }
|
||||
|
||||
// bool isValid() const
|
||||
// {
|
||||
// return this->second;
|
||||
// }
|
||||
|
||||
// const T &getValue() const
|
||||
// {
|
||||
// assert(this->second == true);
|
||||
// return this->first;
|
||||
// }
|
||||
|
||||
// void setValue(const T &v)
|
||||
// {
|
||||
// this->first = v;
|
||||
// this->second = true;
|
||||
// }
|
||||
|
||||
// void invalidate()
|
||||
// {
|
||||
// this->second = false;
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * This methods only purpose is to make a optional type
|
||||
// * valid so that it can be written to by reference.
|
||||
// */
|
||||
// T &setByReference()
|
||||
// {
|
||||
// this->second = true;
|
||||
// return this->first;
|
||||
// }
|
||||
// };
|
||||
|
||||
template <typename T>
|
||||
void invalidateEnum(T& value)
|
||||
{
|
||||
if (value.has_value() && value.value() == T::value_type::Invalid)
|
||||
value.reset();
|
||||
}
|
||||
|
||||
json_t get_config_json(const json_t& j, const std::string& configPath, const std::string& objectName);
|
||||
|
||||
inline void remove_null_values(json_t& j)
|
||||
{
|
||||
std::vector<std::string> keysToRemove;
|
||||
|
||||
for (const auto& element : j.items())
|
||||
{
|
||||
if (element.value() == nullptr)
|
||||
keysToRemove.emplace_back(element.key());
|
||||
}
|
||||
|
||||
std::for_each(keysToRemove.begin(), keysToRemove.end(), [&](const std::string& key) { j.erase(key); });
|
||||
}
|
||||
|
||||
} // namespace DRAMSys::Config
|
||||
|
||||
#endif // DRAMSYSCONFIGURATION_UTIL_H
|
||||
@@ -35,62 +35,97 @@
|
||||
|
||||
#include "DRAMSysConfiguration.h"
|
||||
|
||||
#include "DRAMSys/config/ConfigUtil.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
namespace DRAMSys::Config
|
||||
{
|
||||
|
||||
std::string Configuration::resourceDirectory;
|
||||
|
||||
void to_json(json_t &j, const Configuration &c)
|
||||
Configuration from_path(std::string_view path, std::string_view resourceDirectory)
|
||||
{
|
||||
j = json_t{{"addressmapping", c.addressMapping}, {"mcconfig", c.mcConfig}, {"memspec", c.memSpec},
|
||||
{"simulationid", c.simulationId}, {"simconfig", c.simConfig}, {"tracesetup", c.traceSetup}};
|
||||
std::ifstream file(path.data());
|
||||
|
||||
remove_null_values(j);
|
||||
}
|
||||
|
||||
void from_json(const json_t &j, Configuration &c)
|
||||
{
|
||||
j.at("addressmapping").get_to(c.addressMapping);
|
||||
j.at("mcconfig").get_to(c.mcConfig);
|
||||
j.at("memspec").get_to(c.memSpec);
|
||||
j.at("simulationid").get_to(c.simulationId);
|
||||
j.at("simconfig").get_to(c.simConfig);
|
||||
|
||||
if (j.contains("tracesetup"))
|
||||
j.at("tracesetup").get_to(c.traceSetup);
|
||||
}
|
||||
|
||||
void from_dump(const std::string &dump, Configuration &c)
|
||||
{
|
||||
json_t json_simulation = json_t::parse(dump).at("simulation");
|
||||
json_simulation.get_to(c);
|
||||
}
|
||||
|
||||
std::string dump(const Configuration &c, unsigned int indentation)
|
||||
{
|
||||
json_t json_simulation;
|
||||
json_simulation["simulation"] = c;
|
||||
return json_simulation.dump(indentation);
|
||||
}
|
||||
|
||||
Configuration from_path(const std::string &path, const std::string &resourceDirectory)
|
||||
{
|
||||
Configuration::resourceDirectory = resourceDirectory;
|
||||
|
||||
std::ifstream file(path);
|
||||
|
||||
if (file.is_open())
|
||||
enum class SubConfig
|
||||
{
|
||||
json_t simulation = json_t::parse(file).at("simulation");
|
||||
MemSpec,
|
||||
AddressMapping,
|
||||
McConfig,
|
||||
SimConfig,
|
||||
TraceSetup,
|
||||
Unkown
|
||||
} current_sub_config;
|
||||
|
||||
// This custom parser callback is responsible to swap out the paths to the sub-config json files
|
||||
// with the actual json data.
|
||||
std::function<bool(int depth, nlohmann::detail::parse_event_t event, json_t &parsed)>
|
||||
parser_callback;
|
||||
parser_callback =
|
||||
[&parser_callback, ¤t_sub_config, resourceDirectory](
|
||||
int depth, nlohmann::detail::parse_event_t event, json_t &parsed) -> bool {
|
||||
using nlohmann::detail::parse_event_t;
|
||||
|
||||
if (depth != 2)
|
||||
return true;
|
||||
|
||||
if (event == parse_event_t::key) {
|
||||
assert(parsed.is_string());
|
||||
|
||||
if (parsed == MemSpec::KEY)
|
||||
current_sub_config = SubConfig::MemSpec;
|
||||
else if (parsed == AddressMapping::KEY)
|
||||
current_sub_config = SubConfig::AddressMapping;
|
||||
else if (parsed == McConfig::KEY)
|
||||
current_sub_config = SubConfig::McConfig;
|
||||
else if (parsed == SimConfig::KEY)
|
||||
current_sub_config = SubConfig::SimConfig;
|
||||
else if (parsed == TraceSetupConstants::KEY)
|
||||
current_sub_config = SubConfig::TraceSetup;
|
||||
else
|
||||
current_sub_config = SubConfig::Unkown;
|
||||
}
|
||||
|
||||
// In case we have an value (string) instead of an object, replace the value with the loaded
|
||||
// json object.
|
||||
if (event == parse_event_t::value && current_sub_config != SubConfig::Unkown) {
|
||||
// Replace name of json file with actual json data
|
||||
auto parse_json = [&parser_callback,
|
||||
resourceDirectory](std::string_view base_dir,
|
||||
std::string_view sub_config_key,
|
||||
const std::string &filename) -> json_t {
|
||||
std::filesystem::path path(resourceDirectory);
|
||||
path /= base_dir;
|
||||
path /= filename;
|
||||
|
||||
std::ifstream json_file(path);
|
||||
|
||||
if (!json_file.is_open())
|
||||
throw std::runtime_error("Failed to open file " + std::string(path));
|
||||
|
||||
json_t json =
|
||||
json_t::parse(json_file, parser_callback, true, true).at(sub_config_key);
|
||||
return json;
|
||||
};
|
||||
|
||||
if (current_sub_config == SubConfig::MemSpec)
|
||||
parsed = parse_json(MemSpec::SUB_DIR, MemSpec::KEY, parsed);
|
||||
else if (current_sub_config == SubConfig::AddressMapping)
|
||||
parsed = parse_json(AddressMapping::SUB_DIR, AddressMapping::KEY, parsed);
|
||||
else if (current_sub_config == SubConfig::McConfig)
|
||||
parsed = parse_json(McConfig::SUB_DIR, McConfig::KEY, parsed);
|
||||
else if (current_sub_config == SubConfig::SimConfig)
|
||||
parsed = parse_json(SimConfig::SUB_DIR, SimConfig::KEY, parsed);
|
||||
else if (current_sub_config == SubConfig::TraceSetup)
|
||||
parsed = parse_json(TraceSetupConstants::SUB_DIR, TraceSetupConstants::KEY, parsed);
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
if (file.is_open()) {
|
||||
json_t simulation = json_t::parse(file, parser_callback, true, true).at(Configuration::KEY);
|
||||
return simulation.get<DRAMSys::Config::Configuration>();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("Failed to open file " + path);
|
||||
} else {
|
||||
throw std::runtime_error("Failed to open file " + std::string(path));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,42 +41,45 @@
|
||||
#include "DRAMSys/config/SimConfig.h"
|
||||
#include "DRAMSys/config/TraceSetup.h"
|
||||
#include "DRAMSys/config/memspec/MemSpec.h"
|
||||
#include "DRAMSys/config/ConfigUtil.h"
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* To support polymorphic configurations, a Json "type" tag is used
|
||||
* to determine the correct type before further parsing.
|
||||
*
|
||||
* To support optional values, std::optional is used. The default
|
||||
* values will be provided by DRAMSys itself.
|
||||
*
|
||||
* To achieve static polymorphism, std::variant is used.
|
||||
* To achieve static polymorphism, std::variant is used. The concrete
|
||||
* type is determined by the provided fields automatically.
|
||||
*
|
||||
* To achieve backwards compatibility, this library manipulates the json
|
||||
* data type as it is parsed in to substitute paths to sub-configurations
|
||||
* with the actual json object that is stored at this path.
|
||||
*/
|
||||
|
||||
namespace DRAMSys::Config {
|
||||
|
||||
struct Configuration
|
||||
{
|
||||
AddressMapping addressMapping;
|
||||
McConfig mcConfig;
|
||||
MemSpec memSpec;
|
||||
SimConfig simConfig;
|
||||
std::string simulationId;
|
||||
std::optional<TraceSetup> traceSetup;
|
||||
|
||||
static std::string resourceDirectory;
|
||||
static constexpr std::string_view KEY = "simulation";
|
||||
|
||||
AddressMapping addressmapping;
|
||||
McConfig mcconfig;
|
||||
MemSpec memspec;
|
||||
SimConfig simconfig;
|
||||
std::string simulationid;
|
||||
std::optional<TraceSetup> tracesetup;
|
||||
};
|
||||
|
||||
void to_json(json &j, const Configuration &p);
|
||||
void from_json(const json &j, Configuration &p);
|
||||
NLOHMANN_JSONIFY_ALL_THINGS(Configuration,
|
||||
addressmapping,
|
||||
mcconfig,
|
||||
memspec,
|
||||
simconfig,
|
||||
simulationid,
|
||||
tracesetup)
|
||||
|
||||
void from_dump(const std::string &dump, Configuration &c);
|
||||
std::string dump(const Configuration &c, unsigned int indentation = -1);
|
||||
|
||||
Configuration from_path(const std::string &path, const std::string &resourceDirectory = DRAMSYS_RESOURCE_DIR);
|
||||
Configuration from_path(std::string_view path, std::string_view resourceDirectory = DRAMSYS_RESOURCE_DIR);
|
||||
|
||||
} // namespace DRAMSys::Config
|
||||
|
||||
|
||||
@@ -38,162 +38,36 @@
|
||||
namespace DRAMSys::Config
|
||||
{
|
||||
|
||||
void to_json(json_t &j, const McConfig &c)
|
||||
void to_json(json_t &j, const RefreshPolicyType &r)
|
||||
{
|
||||
j = json_t{{"PagePolicy", c.pagePolicy},
|
||||
{"Scheduler", c.scheduler},
|
||||
{"HighWatermark", c.highWatermark},
|
||||
{"LowWatermark", c.lowWatermark},
|
||||
{"SchedulerBuffer", c.schedulerBuffer},
|
||||
{"RequestBufferSize", c.requestBufferSize},
|
||||
{"CmdMux", c.cmdMux},
|
||||
{"RespQueue", c.respQueue},
|
||||
{"RefreshPolicy", c.refreshPolicy},
|
||||
{"RefreshMaxPostponed", c.refreshMaxPostponed},
|
||||
{"RefreshMaxPulledin", c.refreshMaxPulledin},
|
||||
{"PowerDownPolicy", c.powerDownPolicy},
|
||||
{"Arbiter", c.arbiter},
|
||||
{"MaxActiveTransactions", c.maxActiveTransactions},
|
||||
{"RefreshManagement", c.refreshManagement},
|
||||
{"ArbitrationDelayFw", c.arbitrationDelayFw},
|
||||
{"ArbitrationDelayBw", c.arbitrationDelayBw},
|
||||
{"ThinkDelayFw", c.thinkDelayFw},
|
||||
{"ThinkDelayBw", c.thinkDelayBw},
|
||||
{"PhyDelayFw", c.phyDelayFw},
|
||||
{"PhyDelayBw", c.phyDelayBw},
|
||||
{"BlockingReadDelay", c.blockingReadDelay},
|
||||
{"BlockingWriteDelay", c.blockingWriteDelay}};
|
||||
|
||||
remove_null_values(j);
|
||||
}
|
||||
|
||||
void from_json(const json_t &j, McConfig &c)
|
||||
{
|
||||
json_t j_mcconfig = get_config_json(j, mcConfigPath, "mcconfig");
|
||||
|
||||
if (j_mcconfig.contains("PagePolicy"))
|
||||
j_mcconfig.at("PagePolicy").get_to(c.pagePolicy);
|
||||
|
||||
if (j_mcconfig.contains("Scheduler"))
|
||||
j_mcconfig.at("Scheduler").get_to(c.scheduler);
|
||||
|
||||
if (j_mcconfig.contains("HighWatermark"))
|
||||
j_mcconfig.at("HighWatermark").get_to(c.highWatermark);
|
||||
|
||||
if (j_mcconfig.contains("LowWatermark"))
|
||||
j_mcconfig.at("LowWatermark").get_to(c.lowWatermark);
|
||||
|
||||
if (j_mcconfig.contains("SchedulerBuffer"))
|
||||
j_mcconfig.at("SchedulerBuffer").get_to(c.schedulerBuffer);
|
||||
|
||||
if (j_mcconfig.contains("RequestBufferSize"))
|
||||
j_mcconfig.at("RequestBufferSize").get_to(c.requestBufferSize);
|
||||
|
||||
if (j_mcconfig.contains("CmdMux"))
|
||||
j_mcconfig.at("CmdMux").get_to(c.cmdMux);
|
||||
|
||||
if (j_mcconfig.contains("RespQueue"))
|
||||
j_mcconfig.at("RespQueue").get_to(c.respQueue);
|
||||
|
||||
if (j_mcconfig.contains("RefreshPolicy"))
|
||||
j_mcconfig.at("RefreshPolicy").get_to(c.refreshPolicy);
|
||||
|
||||
if (j_mcconfig.contains("RefreshMaxPostponed"))
|
||||
j_mcconfig.at("RefreshMaxPostponed").get_to(c.refreshMaxPostponed);
|
||||
|
||||
if (j_mcconfig.contains("RefreshMaxPulledin"))
|
||||
j_mcconfig.at("RefreshMaxPulledin").get_to(c.refreshMaxPulledin);
|
||||
|
||||
if (j_mcconfig.contains("PowerDownPolicy"))
|
||||
j_mcconfig.at("PowerDownPolicy").get_to(c.powerDownPolicy);
|
||||
|
||||
if (j_mcconfig.contains("Arbiter"))
|
||||
j_mcconfig.at("Arbiter").get_to(c.arbiter);
|
||||
|
||||
if (j_mcconfig.contains("MaxActiveTransactions"))
|
||||
j_mcconfig.at("MaxActiveTransactions").get_to(c.maxActiveTransactions);
|
||||
|
||||
if (j_mcconfig.contains("RefreshManagement"))
|
||||
j_mcconfig.at("RefreshManagement").get_to(c.refreshManagement);
|
||||
|
||||
if (j_mcconfig.contains("ArbitrationDelayFw"))
|
||||
j_mcconfig.at("ArbitrationDelayFw").get_to(c.arbitrationDelayFw);
|
||||
|
||||
if (j_mcconfig.contains("ArbitrationDelayBw"))
|
||||
j_mcconfig.at("ArbitrationDelayBw").get_to(c.arbitrationDelayBw);
|
||||
|
||||
if (j_mcconfig.contains("ThinkDelayFw"))
|
||||
j_mcconfig.at("ThinkDelayFw").get_to(c.thinkDelayFw);
|
||||
|
||||
if (j_mcconfig.contains("ThinkDelayBw"))
|
||||
j_mcconfig.at("ThinkDelayBw").get_to(c.thinkDelayBw);
|
||||
|
||||
if (j_mcconfig.contains("PhyDelayFw"))
|
||||
j_mcconfig.at("PhyDelayFw").get_to(c.phyDelayFw);
|
||||
|
||||
if (j_mcconfig.contains("PhyDelayBw"))
|
||||
j_mcconfig.at("PhyDelayBw").get_to(c.phyDelayBw);
|
||||
|
||||
if (j_mcconfig.contains("BlockingReadDelay"))
|
||||
j_mcconfig.at("BlockingReadDelay").get_to(c.blockingReadDelay);
|
||||
|
||||
if (j_mcconfig.contains("BlockingWriteDelay"))
|
||||
j_mcconfig.at("BlockingWriteDelay").get_to(c.blockingWriteDelay);
|
||||
|
||||
invalidateEnum(c.pagePolicy);
|
||||
invalidateEnum(c.scheduler);
|
||||
invalidateEnum(c.schedulerBuffer);
|
||||
invalidateEnum(c.cmdMux);
|
||||
invalidateEnum(c.respQueue);
|
||||
invalidateEnum(c.refreshPolicy);
|
||||
invalidateEnum(c.respQueue);
|
||||
invalidateEnum(c.powerDownPolicy);
|
||||
invalidateEnum(c.arbiter);
|
||||
}
|
||||
|
||||
void to_json(json_t &j, const RefreshPolicy &r)
|
||||
{
|
||||
if (r == RefreshPolicy::NoRefresh)
|
||||
if (r == RefreshPolicyType::NoRefresh)
|
||||
j = "NoRefresh";
|
||||
else if (r == RefreshPolicy::AllBank)
|
||||
else if (r == RefreshPolicyType::AllBank)
|
||||
j = "AllBank";
|
||||
else if (r == RefreshPolicy::PerBank)
|
||||
else if (r == RefreshPolicyType::PerBank)
|
||||
j = "PerBank";
|
||||
else if (r == RefreshPolicy::Per2Bank)
|
||||
else if (r == RefreshPolicyType::Per2Bank)
|
||||
j = "Per2Bank";
|
||||
else if (r == RefreshPolicy::SameBank)
|
||||
else if (r == RefreshPolicyType::SameBank)
|
||||
j = "SameBank";
|
||||
else
|
||||
j = nullptr;
|
||||
}
|
||||
|
||||
void from_json(const json_t &j, RefreshPolicy &r)
|
||||
void from_json(const json_t &j, RefreshPolicyType &r)
|
||||
{
|
||||
if (j == "NoRefresh")
|
||||
r = RefreshPolicy::NoRefresh;
|
||||
r = RefreshPolicyType::NoRefresh;
|
||||
else if (j == "AllBank" || j == "Rankwise")
|
||||
r = RefreshPolicy::AllBank;
|
||||
r = RefreshPolicyType::AllBank;
|
||||
else if (j == "PerBank" || j == "Bankwise")
|
||||
r = RefreshPolicy::PerBank;
|
||||
r = RefreshPolicyType::PerBank;
|
||||
else if (j == "SameBank" || j == "Groupwise")
|
||||
r = RefreshPolicy::SameBank;
|
||||
r = RefreshPolicyType::SameBank;
|
||||
else if (j == "Per2Bank")
|
||||
r = RefreshPolicy::Per2Bank;
|
||||
r = RefreshPolicyType::Per2Bank;
|
||||
else
|
||||
r = RefreshPolicy::Invalid;
|
||||
}
|
||||
|
||||
void from_dump(const std::string &dump, McConfig &c)
|
||||
{
|
||||
json_t json_mcconfig = json_t::parse(dump).at("mcconfig");
|
||||
json_mcconfig.get_to(c);
|
||||
}
|
||||
|
||||
std::string dump(const McConfig &c, unsigned int indentation)
|
||||
{
|
||||
json_t json_mcconfig;
|
||||
json_mcconfig["mcconfig"] = c;
|
||||
return json_mcconfig.dump(indentation);
|
||||
r = RefreshPolicyType::Invalid;
|
||||
}
|
||||
|
||||
} // namespace DRAMSys::Config
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
#ifndef DRAMSYSCONFIGURATION_MCCONFIG_H
|
||||
#define DRAMSYSCONFIGURATION_MCCONFIG_H
|
||||
|
||||
#include "DRAMSys/config/ConfigUtil.h"
|
||||
#include "DRAMSys/util/json.h"
|
||||
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
@@ -44,9 +44,8 @@
|
||||
|
||||
namespace DRAMSys::Config
|
||||
{
|
||||
const std::string mcConfigPath = "mcconfig";
|
||||
|
||||
enum class PagePolicy
|
||||
enum class PagePolicyType
|
||||
{
|
||||
Open,
|
||||
OpenAdaptive,
|
||||
@@ -55,15 +54,15 @@ enum class PagePolicy
|
||||
Invalid = -1
|
||||
};
|
||||
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(PagePolicy, {
|
||||
{PagePolicy::Invalid, nullptr},
|
||||
{PagePolicy::Open, "Open"},
|
||||
{PagePolicy::OpenAdaptive, "OpenAdaptive"},
|
||||
{PagePolicy::Closed, "Closed"},
|
||||
{PagePolicy::ClosedAdaptive, "ClosedAdaptive"},
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(PagePolicyType, {
|
||||
{PagePolicyType::Invalid, nullptr},
|
||||
{PagePolicyType::Open, "Open"},
|
||||
{PagePolicyType::OpenAdaptive, "OpenAdaptive"},
|
||||
{PagePolicyType::Closed, "Closed"},
|
||||
{PagePolicyType::ClosedAdaptive, "ClosedAdaptive"},
|
||||
})
|
||||
|
||||
enum class Scheduler
|
||||
enum class SchedulerType
|
||||
{
|
||||
Fifo,
|
||||
FrFcfs,
|
||||
@@ -73,14 +72,14 @@ enum class Scheduler
|
||||
Invalid = -1
|
||||
};
|
||||
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(Scheduler, {{Scheduler::Invalid, nullptr},
|
||||
{Scheduler::Fifo, "Fifo"},
|
||||
{Scheduler::FrFcfs, "FrFcfs"},
|
||||
{Scheduler::FrFcfsGrp, "FrFcfsGrp"},
|
||||
{Scheduler::GrpFrFcfs, "GrpFrFcfs"},
|
||||
{Scheduler::GrpFrFcfsWm, "GrpFrFcfsWm"}})
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(SchedulerType, {{SchedulerType::Invalid, nullptr},
|
||||
{SchedulerType::Fifo, "Fifo"},
|
||||
{SchedulerType::FrFcfs, "FrFcfs"},
|
||||
{SchedulerType::FrFcfsGrp, "FrFcfsGrp"},
|
||||
{SchedulerType::GrpFrFcfs, "GrpFrFcfs"},
|
||||
{SchedulerType::GrpFrFcfsWm, "GrpFrFcfsWm"}})
|
||||
|
||||
enum class SchedulerBuffer
|
||||
enum class SchedulerBufferType
|
||||
{
|
||||
Bankwise,
|
||||
ReadWrite,
|
||||
@@ -88,33 +87,33 @@ enum class SchedulerBuffer
|
||||
Invalid = -1
|
||||
};
|
||||
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(SchedulerBuffer, {{SchedulerBuffer::Invalid, nullptr},
|
||||
{SchedulerBuffer::Bankwise, "Bankwise"},
|
||||
{SchedulerBuffer::ReadWrite, "ReadWrite"},
|
||||
{SchedulerBuffer::Shared, "Shared"}})
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(SchedulerBufferType, {{SchedulerBufferType::Invalid, nullptr},
|
||||
{SchedulerBufferType::Bankwise, "Bankwise"},
|
||||
{SchedulerBufferType::ReadWrite, "ReadWrite"},
|
||||
{SchedulerBufferType::Shared, "Shared"}})
|
||||
|
||||
enum class CmdMux
|
||||
enum class CmdMuxType
|
||||
{
|
||||
Oldest,
|
||||
Strict,
|
||||
Invalid = -1
|
||||
};
|
||||
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(CmdMux,
|
||||
{{CmdMux::Invalid, nullptr}, {CmdMux::Oldest, "Oldest"}, {CmdMux::Strict, "Strict"}})
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(CmdMuxType,
|
||||
{{CmdMuxType::Invalid, nullptr}, {CmdMuxType::Oldest, "Oldest"}, {CmdMuxType::Strict, "Strict"}})
|
||||
|
||||
enum class RespQueue
|
||||
enum class RespQueueType
|
||||
{
|
||||
Fifo,
|
||||
Reorder,
|
||||
Invalid = -1
|
||||
};
|
||||
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(RespQueue, {{RespQueue::Invalid, nullptr},
|
||||
{RespQueue::Fifo, "Fifo"},
|
||||
{RespQueue::Reorder, "Reorder"}})
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(RespQueueType, {{RespQueueType::Invalid, nullptr},
|
||||
{RespQueueType::Fifo, "Fifo"},
|
||||
{RespQueueType::Reorder, "Reorder"}})
|
||||
|
||||
enum class RefreshPolicy
|
||||
enum class RefreshPolicyType
|
||||
{
|
||||
NoRefresh,
|
||||
AllBank,
|
||||
@@ -124,18 +123,18 @@ enum class RefreshPolicy
|
||||
Invalid = -1
|
||||
};
|
||||
|
||||
enum class PowerDownPolicy
|
||||
enum class PowerDownPolicyType
|
||||
{
|
||||
NoPowerDown,
|
||||
Staggered,
|
||||
Invalid = -1
|
||||
};
|
||||
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(PowerDownPolicy, {{PowerDownPolicy::Invalid, nullptr},
|
||||
{PowerDownPolicy::NoPowerDown, "NoPowerDown"},
|
||||
{PowerDownPolicy::Staggered, "Staggered"}})
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(PowerDownPolicyType, {{PowerDownPolicyType::Invalid, nullptr},
|
||||
{PowerDownPolicyType::NoPowerDown, "NoPowerDown"},
|
||||
{PowerDownPolicyType::Staggered, "Staggered"}})
|
||||
|
||||
enum class Arbiter
|
||||
enum class ArbiterType
|
||||
{
|
||||
Simple,
|
||||
Fifo,
|
||||
@@ -143,46 +142,71 @@ enum class Arbiter
|
||||
Invalid = -1
|
||||
};
|
||||
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(Arbiter, {{Arbiter::Invalid, nullptr},
|
||||
{Arbiter::Simple, "Simple"},
|
||||
{Arbiter::Fifo, "Fifo"},
|
||||
{Arbiter::Reorder, "Reorder"}})
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(ArbiterType, {{ArbiterType::Invalid, nullptr},
|
||||
{ArbiterType::Simple, "Simple"},
|
||||
{ArbiterType::Fifo, "Fifo"},
|
||||
{ArbiterType::Reorder, "Reorder"}})
|
||||
|
||||
struct McConfig
|
||||
{
|
||||
std::optional<PagePolicy> pagePolicy;
|
||||
std::optional<Scheduler> scheduler;
|
||||
std::optional<unsigned int> highWatermark;
|
||||
std::optional<unsigned int> lowWatermark;
|
||||
std::optional<SchedulerBuffer> schedulerBuffer;
|
||||
std::optional<unsigned int> requestBufferSize;
|
||||
std::optional<CmdMux> cmdMux;
|
||||
std::optional<RespQueue> respQueue;
|
||||
std::optional<RefreshPolicy> refreshPolicy;
|
||||
std::optional<unsigned int> refreshMaxPostponed;
|
||||
std::optional<unsigned int> refreshMaxPulledin;
|
||||
std::optional<PowerDownPolicy> powerDownPolicy;
|
||||
std::optional<Arbiter> arbiter;
|
||||
std::optional<unsigned int> maxActiveTransactions;
|
||||
std::optional<bool> refreshManagement;
|
||||
std::optional<unsigned int> arbitrationDelayFw;
|
||||
std::optional<unsigned int> arbitrationDelayBw;
|
||||
std::optional<unsigned int> thinkDelayFw;
|
||||
std::optional<unsigned int> thinkDelayBw;
|
||||
std::optional<unsigned int> phyDelayFw;
|
||||
std::optional<unsigned int> phyDelayBw;
|
||||
std::optional<unsigned int> blockingReadDelay;
|
||||
std::optional<unsigned int> blockingWriteDelay;
|
||||
static constexpr std::string_view KEY = "mcconfig";
|
||||
static constexpr std::string_view SUB_DIR = "mcconfig";
|
||||
|
||||
std::optional<PagePolicyType> PagePolicy;
|
||||
std::optional<SchedulerType> Scheduler;
|
||||
std::optional<unsigned int> HighWatermark;
|
||||
std::optional<unsigned int> LowWatermark;
|
||||
std::optional<SchedulerBufferType> SchedulerBuffer;
|
||||
std::optional<unsigned int> RequestBufferSize;
|
||||
std::optional<CmdMuxType> CmdMux;
|
||||
std::optional<RespQueueType> RespQueue;
|
||||
std::optional<RefreshPolicyType> RefreshPolicy;
|
||||
std::optional<unsigned int> RefreshMaxPostponed;
|
||||
std::optional<unsigned int> RefreshMaxPulledin;
|
||||
std::optional<PowerDownPolicyType> PowerDownPolicy;
|
||||
std::optional<ArbiterType> Arbiter;
|
||||
std::optional<unsigned int> MaxActiveTransactions;
|
||||
std::optional<bool> RefreshManagement;
|
||||
std::optional<unsigned int> ArbitrationDelayFw;
|
||||
std::optional<unsigned int> ArbitrationDelayBw;
|
||||
std::optional<unsigned int> ThinkDelayFw;
|
||||
std::optional<unsigned int> ThinkDelayBw;
|
||||
std::optional<unsigned int> PhyDelayFw;
|
||||
std::optional<unsigned int> PhyDelayBw;
|
||||
std::optional<unsigned int> BlockingReadDelay;
|
||||
std::optional<unsigned int> BlockingWriteDelay;
|
||||
};
|
||||
|
||||
void to_json(json_t &j, const McConfig &c);
|
||||
void from_json(const json_t &j, McConfig &c);
|
||||
NLOHMANN_JSONIFY_ALL_THINGS(McConfig,
|
||||
PagePolicy,
|
||||
Scheduler,
|
||||
HighWatermark,
|
||||
LowWatermark,
|
||||
SchedulerBuffer,
|
||||
RequestBufferSize,
|
||||
CmdMux,
|
||||
RespQueue,
|
||||
RefreshPolicy,
|
||||
RefreshMaxPostponed,
|
||||
RefreshMaxPulledin,
|
||||
PowerDownPolicy,
|
||||
Arbiter,
|
||||
MaxActiveTransactions,
|
||||
RefreshManagement,
|
||||
ArbitrationDelayFw,
|
||||
ArbitrationDelayBw,
|
||||
ThinkDelayFw,
|
||||
ThinkDelayBw,
|
||||
PhyDelayFw,
|
||||
PhyDelayBw,
|
||||
BlockingReadDelay,
|
||||
BlockingWriteDelay)
|
||||
|
||||
void to_json(json_t &j, const RefreshPolicy &r);
|
||||
void from_json(const json_t &j, RefreshPolicy &r);
|
||||
void to_json(json_t &j, const RefreshPolicyType &r);
|
||||
void from_json(const json_t &j, RefreshPolicyType &r);
|
||||
|
||||
void from_dump(const std::string &dump, McConfig &c);
|
||||
std::string dump(const McConfig &c, unsigned int indentation = -1);
|
||||
// void from_dump(const std::string &dump, McConfig &c);
|
||||
// std::string dump(const McConfig &c, unsigned int indentation = -1);
|
||||
|
||||
} // namespace Configuration
|
||||
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Technische Universität Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. 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.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder 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 HOLDER
|
||||
* 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:
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#include "SimConfig.h"
|
||||
|
||||
namespace DRAMSys::Config
|
||||
{
|
||||
|
||||
void to_json(json_t &j, const SimConfig &c)
|
||||
{
|
||||
j = json_t{{"AddressOffset", c.addressOffset},
|
||||
{"CheckTLM2Protocol", c.checkTLM2Protocol},
|
||||
{"DatabaseRecording", c.databaseRecording},
|
||||
{"Debug", c.debug},
|
||||
{"EnableWindowing", c.enableWindowing},
|
||||
{"ErrorCSVFile", c.errorCsvFile},
|
||||
{"ErrorChipSeed", c.errorChipSeed},
|
||||
{"PowerAnalysis", c.powerAnalysis},
|
||||
{"SimulationName", c.simulationName},
|
||||
{"SimulationProgressBar", c.simulationProgressBar},
|
||||
{"StoreMode", c.storeMode},
|
||||
{"ThermalSimulation", c.thermalSimulation},
|
||||
{"UseMalloc", c.useMalloc},
|
||||
{"WindowSize", c.windowSize}};
|
||||
}
|
||||
|
||||
void from_json(const json_t &j, SimConfig &c)
|
||||
{
|
||||
json_t j_simconfig = get_config_json(j, simConfigPath, "simconfig");
|
||||
|
||||
if (j_simconfig.contains("AddressOffset"))
|
||||
j_simconfig.at("AddressOffset").get_to(c.addressOffset);
|
||||
|
||||
if (j_simconfig.contains("CheckTLM2Protocol"))
|
||||
j_simconfig.at("CheckTLM2Protocol").get_to(c.checkTLM2Protocol);
|
||||
|
||||
if (j_simconfig.contains("DatabaseRecording"))
|
||||
j_simconfig.at("DatabaseRecording").get_to(c.databaseRecording);
|
||||
|
||||
if (j_simconfig.contains("Debug"))
|
||||
j_simconfig.at("Debug").get_to(c.debug);
|
||||
|
||||
if (j_simconfig.contains("EnableWindowing"))
|
||||
j_simconfig.at("EnableWindowing").get_to(c.enableWindowing);
|
||||
|
||||
if (j_simconfig.contains("ErrorCSVFile"))
|
||||
j_simconfig.at("ErrorCSVFile").get_to(c.errorCsvFile);
|
||||
|
||||
if (j_simconfig.contains("ErrorChipSeed"))
|
||||
j_simconfig.at("ErrorChipSeed").get_to(c.errorChipSeed);
|
||||
|
||||
if (j_simconfig.contains("PowerAnalysis"))
|
||||
j_simconfig.at("PowerAnalysis").get_to(c.powerAnalysis);
|
||||
|
||||
if (j_simconfig.contains("SimulationName"))
|
||||
j_simconfig.at("SimulationName").get_to(c.simulationName);
|
||||
|
||||
if (j_simconfig.contains("SimulationProgressBar"))
|
||||
j_simconfig.at("SimulationProgressBar").get_to(c.simulationProgressBar);
|
||||
|
||||
if (j_simconfig.contains("StoreMode"))
|
||||
j_simconfig.at("StoreMode").get_to(c.storeMode);
|
||||
|
||||
if (j_simconfig.contains("ThermalSimulation"))
|
||||
j_simconfig.at("ThermalSimulation").get_to(c.thermalSimulation);
|
||||
|
||||
if (j_simconfig.contains("UseMalloc"))
|
||||
j_simconfig.at("UseMalloc").get_to(c.useMalloc);
|
||||
|
||||
if (j_simconfig.contains("WindowSize"))
|
||||
j_simconfig.at("WindowSize").get_to(c.windowSize);
|
||||
|
||||
invalidateEnum(c.storeMode);
|
||||
}
|
||||
|
||||
void from_dump(const std::string &dump, SimConfig &c)
|
||||
{
|
||||
json_t json_simconfig = json_t::parse(dump).at("simconfig");
|
||||
json_simconfig.get_to(c);
|
||||
}
|
||||
|
||||
std::string dump(const SimConfig &c, unsigned int indentation)
|
||||
{
|
||||
json_t json_simconfig;
|
||||
json_simconfig["simconfig"] = c;
|
||||
return json_simconfig.dump(indentation);
|
||||
}
|
||||
|
||||
} // namespace DRAMSys::Config
|
||||
@@ -36,15 +36,14 @@
|
||||
#ifndef DRAMSYSCONFIGURATION_SIMCONFIG_H
|
||||
#define DRAMSYSCONFIGURATION_SIMCONFIG_H
|
||||
|
||||
#include "DRAMSys/config/ConfigUtil.h"
|
||||
#include "DRAMSys/util/json.h"
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace DRAMSys::Config
|
||||
{
|
||||
const std::string simConfigPath = "simconfig";
|
||||
|
||||
enum class StoreMode
|
||||
enum class StoreModeType
|
||||
{
|
||||
NoStorage,
|
||||
Store,
|
||||
@@ -52,34 +51,47 @@ enum class StoreMode
|
||||
Invalid = -1
|
||||
};
|
||||
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(StoreMode, {{StoreMode::Invalid, nullptr},
|
||||
{StoreMode::NoStorage, "NoStorage"},
|
||||
{StoreMode::Store, "Store"},
|
||||
{StoreMode::ErrorModel, "ErrorModel"}})
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(StoreModeType, {{StoreModeType::Invalid, nullptr},
|
||||
{StoreModeType::NoStorage, "NoStorage"},
|
||||
{StoreModeType::Store, "Store"},
|
||||
{StoreModeType::ErrorModel, "ErrorModel"}})
|
||||
|
||||
struct SimConfig
|
||||
{
|
||||
std::optional<uint64_t> addressOffset;
|
||||
std::optional<bool> checkTLM2Protocol;
|
||||
std::optional<bool> databaseRecording;
|
||||
std::optional<bool> debug;
|
||||
std::optional<bool> enableWindowing;
|
||||
std::optional<std::string> errorCsvFile;
|
||||
std::optional<unsigned int> errorChipSeed;
|
||||
std::optional<bool> powerAnalysis;
|
||||
std::optional<std::string> simulationName;
|
||||
std::optional<bool> simulationProgressBar;
|
||||
std::optional<StoreMode> storeMode;
|
||||
std::optional<bool> thermalSimulation;
|
||||
std::optional<bool> useMalloc;
|
||||
std::optional<unsigned int> windowSize;
|
||||
static constexpr std::string_view KEY = "simconfig";
|
||||
static constexpr std::string_view SUB_DIR = "simconfig";
|
||||
|
||||
std::optional<uint64_t> AddressOffset;
|
||||
std::optional<bool> CheckTLM2Protocol;
|
||||
std::optional<bool> DatabaseRecording;
|
||||
std::optional<bool> Debug;
|
||||
std::optional<bool> EnableWindowing;
|
||||
std::optional<std::string> ErrorCSVFile;
|
||||
std::optional<unsigned int> ErrorChipSeed;
|
||||
std::optional<bool> PowerAnalysis;
|
||||
std::optional<std::string> SimulationName;
|
||||
std::optional<bool> SimulationProgressBar;
|
||||
std::optional<StoreModeType> StoreMode;
|
||||
std::optional<bool> ThermalSimulation;
|
||||
std::optional<bool> UseMalloc;
|
||||
std::optional<unsigned int> WindowSize;
|
||||
};
|
||||
|
||||
void to_json(json_t &j, const SimConfig &c);
|
||||
void from_json(const json_t &j, SimConfig &c);
|
||||
|
||||
void from_dump(const std::string &dump, SimConfig &c);
|
||||
std::string dump(const SimConfig &c, unsigned int indentation = -1);
|
||||
NLOHMANN_JSONIFY_ALL_THINGS(SimConfig,
|
||||
AddressOffset,
|
||||
CheckTLM2Protocol,
|
||||
DatabaseRecording,
|
||||
Debug,
|
||||
EnableWindowing,
|
||||
ErrorCSVFile,
|
||||
ErrorChipSeed,
|
||||
PowerAnalysis,
|
||||
SimulationName,
|
||||
SimulationProgressBar,
|
||||
StoreMode,
|
||||
ThermalSimulation,
|
||||
UseMalloc,
|
||||
WindowSize)
|
||||
|
||||
} // namespace Configuration
|
||||
|
||||
|
||||
@@ -1,314 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Technische Universität Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. 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.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder 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 HOLDER
|
||||
* 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:
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#include "TraceSetup.h"
|
||||
|
||||
#include <variant>
|
||||
|
||||
namespace DRAMSys::Config
|
||||
{
|
||||
|
||||
TrafficInitiator::~TrafficInitiator()
|
||||
{
|
||||
}
|
||||
|
||||
TraceGeneratorState::~TraceGeneratorState()
|
||||
{
|
||||
}
|
||||
|
||||
void to_json(json_t &j, const TraceSetup &c)
|
||||
{
|
||||
// Create an empty array
|
||||
j = json_t::array();
|
||||
|
||||
for (const auto &initiator : c.initiators)
|
||||
{
|
||||
json_t initiator_j;
|
||||
|
||||
std::visit(
|
||||
[&initiator_j](auto &&initiator)
|
||||
{
|
||||
initiator_j["name"] = initiator.name;
|
||||
initiator_j["clkMhz"] = initiator.clkMhz;
|
||||
initiator_j["maxPendingReadRequests"] = initiator.maxPendingReadRequests;
|
||||
initiator_j["maxPendingWriteRequests"] = initiator.maxPendingWriteRequests;
|
||||
|
||||
using T = std::decay_t<decltype(initiator)>;
|
||||
if constexpr (std::is_same_v<T, TraceGenerator>)
|
||||
{
|
||||
initiator_j["type"] = "generator";
|
||||
initiator_j["seed"] = initiator.seed;
|
||||
initiator_j["maxTransactions"] = initiator.maxTransactions;
|
||||
initiator_j["idleUntil"] = initiator.idleUntil;
|
||||
|
||||
// When there are less than 2 states, flatten out the json.
|
||||
if (initiator.states.size() == 1)
|
||||
{
|
||||
std::visit(
|
||||
[&initiator_j](auto &&state)
|
||||
{
|
||||
using U = std::decay_t<decltype(state)>;
|
||||
|
||||
if constexpr (std::is_same_v<U, TraceGeneratorTrafficState>)
|
||||
{
|
||||
initiator_j["numRequests"] = state.numRequests;
|
||||
initiator_j["rwRatio"] = state.rwRatio;
|
||||
initiator_j["addressDistribution"] = state.addressDistribution;
|
||||
initiator_j["addressIncrement"] = state.addressIncrement;
|
||||
initiator_j["minAddress"] = state.minAddress;
|
||||
initiator_j["maxAddress"] = state.maxAddress;
|
||||
initiator_j["clksPerRequest"] = state.clksPerRequest;
|
||||
initiator_j["notify"] = state.notify;
|
||||
}
|
||||
else // if constexpr (std::is_same_v<U, TraceGeneratorIdleState>)
|
||||
{
|
||||
initiator_j["idleClks"] = state.idleClks;
|
||||
}
|
||||
},
|
||||
initiator.states.at(0));
|
||||
}
|
||||
else
|
||||
{
|
||||
json_t states_j = json_t::array();
|
||||
|
||||
for (const auto &state : initiator.states)
|
||||
{
|
||||
json_t state_j;
|
||||
state_j["id"] = state.first;
|
||||
|
||||
std::visit(
|
||||
[&state_j](auto &&state)
|
||||
{
|
||||
using U = std::decay_t<decltype(state)>;
|
||||
|
||||
if constexpr (std::is_same_v<U, TraceGeneratorTrafficState>)
|
||||
{
|
||||
state_j["numRequests"] = state.numRequests;
|
||||
state_j["rwRatio"] = state.rwRatio;
|
||||
state_j["addressDistribution"] = state.addressDistribution;
|
||||
state_j["addressIncrement"] = state.addressIncrement;
|
||||
state_j["minAddress"] = state.minAddress;
|
||||
state_j["maxAddress"] = state.maxAddress;
|
||||
state_j["clksPerRequest"] = state.clksPerRequest;
|
||||
state_j["notify"] = state.notify;
|
||||
}
|
||||
else // if constexpr (std::is_same_v<U, TraceGeneratorIdleState>)
|
||||
{
|
||||
state_j["idleClks"] = state.idleClks;
|
||||
}
|
||||
},
|
||||
state.second);
|
||||
|
||||
remove_null_values(state_j);
|
||||
states_j.insert(states_j.end(), state_j);
|
||||
}
|
||||
initiator_j["states"] = states_j;
|
||||
|
||||
json_t transitions_j = json_t::array();
|
||||
|
||||
for (const auto &transition : initiator.transitions)
|
||||
{
|
||||
json_t transition_j;
|
||||
transition_j["from"] = transition.first;
|
||||
transition_j["to"] = transition.second.to;
|
||||
transition_j["probability"] = transition.second.probability;
|
||||
remove_null_values(transition_j);
|
||||
transitions_j.insert(transitions_j.end(), transition_j);
|
||||
}
|
||||
initiator_j["transitions"] = transitions_j;
|
||||
}
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, TraceHammer>)
|
||||
{
|
||||
initiator_j["type"] = "hammer";
|
||||
initiator_j["numRequests"] = initiator.numRequests;
|
||||
initiator_j["rowIncrement"] = initiator.rowIncrement;
|
||||
}
|
||||
else // if constexpr (std::is_same_v<T, TracePlayer>)
|
||||
{
|
||||
initiator_j["type"] = "player";
|
||||
}
|
||||
},
|
||||
initiator);
|
||||
|
||||
remove_null_values(initiator_j);
|
||||
j.insert(j.end(), initiator_j);
|
||||
}
|
||||
}
|
||||
|
||||
void from_json(const json_t&j, TraceSetup &c)
|
||||
{
|
||||
for (const auto &initiator_j : j)
|
||||
{
|
||||
// Default to Player, when not specified
|
||||
TrafficInitiatorType type = initiator_j.value("type", TrafficInitiatorType::Player);
|
||||
|
||||
std::variant<TracePlayer, TraceGenerator, TraceHammer> initiator;
|
||||
|
||||
if (type == TrafficInitiatorType::Player)
|
||||
{
|
||||
initiator = TracePlayer{};
|
||||
}
|
||||
else if (type == TrafficInitiatorType::Generator)
|
||||
{
|
||||
TraceGenerator generator;
|
||||
|
||||
auto process_state = [](const json_t&state_j)
|
||||
-> std::pair<unsigned int, std::variant<TraceGeneratorIdleState, TraceGeneratorTrafficState>>
|
||||
{
|
||||
std::variant<TraceGeneratorIdleState, TraceGeneratorTrafficState> state;
|
||||
|
||||
if (state_j.contains("idleClks"))
|
||||
{
|
||||
// Idle state
|
||||
TraceGeneratorIdleState idleState;
|
||||
state_j.at("idleClks").get_to(idleState.idleClks);
|
||||
|
||||
state = std::move(idleState);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Traffic state
|
||||
TraceGeneratorTrafficState trafficState;
|
||||
state_j.at("numRequests").get_to(trafficState.numRequests);
|
||||
state_j.at("rwRatio").get_to(trafficState.rwRatio);
|
||||
state_j.at("addressDistribution").get_to(trafficState.addressDistribution);
|
||||
|
||||
if (state_j.contains("addressIncrement"))
|
||||
state_j.at("addressIncrement").get_to(trafficState.addressIncrement);
|
||||
|
||||
if (state_j.contains("minAddress"))
|
||||
state_j.at("minAddress").get_to(trafficState.minAddress);
|
||||
|
||||
if (state_j.contains("maxAddress"))
|
||||
state_j.at("maxAddress").get_to(trafficState.maxAddress);
|
||||
|
||||
if (state_j.contains("clksPerRequest"))
|
||||
state_j.at("clksPerRequest").get_to(trafficState.clksPerRequest);
|
||||
|
||||
if (state_j.contains("notify"))
|
||||
state_j.at("notify").get_to(trafficState.notify);
|
||||
|
||||
state = std::move(trafficState);
|
||||
}
|
||||
|
||||
// Default to 0
|
||||
unsigned int id = 0;
|
||||
|
||||
if (state_j.contains("id"))
|
||||
id = state_j.at("id");
|
||||
|
||||
return {id, std::move(state)};
|
||||
};
|
||||
|
||||
if (initiator_j.contains("states"))
|
||||
{
|
||||
for (const auto &state_j : initiator_j.at("states"))
|
||||
{
|
||||
auto state = process_state(state_j);
|
||||
generator.states[state.first] = std::move(state.second);
|
||||
}
|
||||
|
||||
for (const auto &transition_j : initiator_j.at("transitions"))
|
||||
{
|
||||
TraceGeneratorStateTransition transition;
|
||||
unsigned int from = transition_j.at("from");
|
||||
transition.to = transition_j.at("to");
|
||||
transition.probability = transition_j.at("probability");
|
||||
generator.transitions.emplace(from, transition);
|
||||
}
|
||||
}
|
||||
else // Only one state will be created
|
||||
{
|
||||
auto state = process_state(initiator_j);
|
||||
generator.states[state.first] = std::move(state.second);
|
||||
}
|
||||
|
||||
if (initiator_j.contains("seed"))
|
||||
initiator_j.at("seed").get_to(generator.seed);
|
||||
|
||||
if (initiator_j.contains("maxTransactions"))
|
||||
initiator_j.at("maxTransactions").get_to(generator.maxTransactions);
|
||||
|
||||
if (initiator_j.contains("dataLength"))
|
||||
initiator_j.at("dataLength").get_to(generator.dataLength);
|
||||
|
||||
if (initiator_j.contains("idleUntil"))
|
||||
initiator_j.at("idleUntil").get_to(generator.idleUntil);
|
||||
|
||||
initiator = generator;
|
||||
}
|
||||
else if (type == TrafficInitiatorType::Hammer)
|
||||
{
|
||||
TraceHammer hammer;
|
||||
|
||||
initiator_j.at("numRequests").get_to(hammer.numRequests);
|
||||
initiator_j.at("rowIncrement").get_to(hammer.rowIncrement);
|
||||
|
||||
initiator = hammer;
|
||||
}
|
||||
|
||||
std::visit(
|
||||
[&initiator_j](auto &&initiator)
|
||||
{
|
||||
initiator_j.at("name").get_to(initiator.name);
|
||||
initiator_j.at("clkMhz").get_to(initiator.clkMhz);
|
||||
|
||||
if (initiator_j.contains("maxPendingReadRequests"))
|
||||
initiator_j.at("maxPendingReadRequests").get_to(initiator.maxPendingReadRequests);
|
||||
|
||||
if (initiator_j.contains("maxPendingWriteRequests"))
|
||||
initiator_j.at("maxPendingWriteRequests").get_to(initiator.maxPendingWriteRequests);
|
||||
},
|
||||
initiator);
|
||||
|
||||
c.initiators.emplace_back(std::move(initiator));
|
||||
}
|
||||
}
|
||||
|
||||
void from_dump(const std::string &dump, TraceSetup &c)
|
||||
{
|
||||
json_t json_tracesetup = json_t::parse(dump).at("tracesetup");
|
||||
json_tracesetup.get_to(c);
|
||||
}
|
||||
|
||||
std::string dump(const TraceSetup &c, unsigned int indentation)
|
||||
{
|
||||
json_t json_tracesetup;
|
||||
json_tracesetup["tracesetup"] = c;
|
||||
return json_tracesetup.dump(indentation);
|
||||
}
|
||||
|
||||
} // namespace DRAMSys::Config
|
||||
@@ -36,7 +36,7 @@
|
||||
#ifndef DRAMSYSCONFIGURATION_TRACESETUP_H
|
||||
#define DRAMSYSCONFIGURATION_TRACESETUP_H
|
||||
|
||||
#include "DRAMSys/config/ConfigUtil.h"
|
||||
#include "DRAMSys/util/json.h"
|
||||
|
||||
#include <optional>
|
||||
#include <variant>
|
||||
@@ -68,74 +68,141 @@ NLOHMANN_JSON_SERIALIZE_ENUM(AddressDistribution, {{AddressDistribution::Invalid
|
||||
{AddressDistribution::Random, "random"},
|
||||
{AddressDistribution::Sequential, "sequential"}})
|
||||
|
||||
struct TrafficInitiator
|
||||
struct TracePlayer
|
||||
{
|
||||
virtual ~TrafficInitiator() = 0;
|
||||
|
||||
uint64_t clkMhz;
|
||||
std::string name;
|
||||
std::optional<unsigned int> maxPendingReadRequests;
|
||||
std::optional<unsigned int> maxPendingWriteRequests;
|
||||
};
|
||||
|
||||
struct TracePlayer : public TrafficInitiator
|
||||
{
|
||||
};
|
||||
NLOHMANN_JSONIFY_ALL_THINGS(
|
||||
TracePlayer, clkMhz, name, maxPendingReadRequests, maxPendingWriteRequests)
|
||||
|
||||
struct TraceGeneratorState
|
||||
struct TrafficGeneratorActiveState
|
||||
{
|
||||
virtual ~TraceGeneratorState() = 0;
|
||||
};
|
||||
unsigned int id;
|
||||
|
||||
struct TraceGeneratorTrafficState : public TraceGeneratorState
|
||||
{
|
||||
uint64_t numRequests;
|
||||
double rwRatio;
|
||||
AddressDistribution addressDistribution;
|
||||
std::optional<uint64_t> addressIncrement;
|
||||
std::optional<uint64_t> minAddress;
|
||||
std::optional<uint64_t> maxAddress;
|
||||
std::optional<uint64_t> clksPerRequest;
|
||||
std::optional<std::string> notify;
|
||||
};
|
||||
|
||||
struct TraceGeneratorIdleState : public TraceGeneratorState
|
||||
NLOHMANN_JSONIFY_ALL_THINGS(TrafficGeneratorActiveState,
|
||||
id,
|
||||
numRequests,
|
||||
rwRatio,
|
||||
addressDistribution,
|
||||
addressIncrement,
|
||||
minAddress,
|
||||
maxAddress)
|
||||
|
||||
struct TrafficGeneratorIdleState
|
||||
{
|
||||
unsigned int id;
|
||||
|
||||
uint64_t idleClks;
|
||||
};
|
||||
|
||||
struct TraceGeneratorStateTransition
|
||||
NLOHMANN_JSONIFY_ALL_THINGS(TrafficGeneratorIdleState, id, idleClks)
|
||||
|
||||
struct TrafficGeneratorStateTransition
|
||||
{
|
||||
unsigned int from;
|
||||
unsigned int to;
|
||||
float probability;
|
||||
};
|
||||
|
||||
struct TraceGenerator : public TrafficInitiator
|
||||
NLOHMANN_JSONIFY_ALL_THINGS(TrafficGeneratorStateTransition, from, to, probability)
|
||||
|
||||
struct TrafficGenerator
|
||||
{
|
||||
uint64_t clkMhz;
|
||||
std::string name;
|
||||
std::optional<unsigned int> maxPendingReadRequests;
|
||||
std::optional<unsigned int> maxPendingWriteRequests;
|
||||
|
||||
std::optional<uint64_t> seed;
|
||||
std::optional<uint64_t> maxTransactions;
|
||||
std::optional<unsigned> dataLength;
|
||||
std::map<unsigned int, std::variant<TraceGeneratorIdleState, TraceGeneratorTrafficState>> states;
|
||||
std::multimap<unsigned int, TraceGeneratorStateTransition> transitions;
|
||||
std::optional<std::string> idleUntil;
|
||||
std::optional<unsigned> dataAlignment;
|
||||
|
||||
uint64_t numRequests;
|
||||
double rwRatio;
|
||||
AddressDistribution addressDistribution;
|
||||
std::optional<uint64_t> addressIncrement;
|
||||
std::optional<uint64_t> minAddress;
|
||||
std::optional<uint64_t> maxAddress;
|
||||
};
|
||||
|
||||
struct TraceHammer : public TrafficInitiator
|
||||
NLOHMANN_JSONIFY_ALL_THINGS(TrafficGenerator,
|
||||
clkMhz,
|
||||
name,
|
||||
maxPendingReadRequests,
|
||||
maxPendingWriteRequests,
|
||||
seed,
|
||||
maxTransactions,
|
||||
dataLength,
|
||||
dataAlignment,
|
||||
numRequests,
|
||||
rwRatio,
|
||||
addressDistribution,
|
||||
addressIncrement,
|
||||
minAddress,
|
||||
maxAddress)
|
||||
|
||||
struct TrafficGeneratorStateMachine
|
||||
{
|
||||
uint64_t clkMhz;
|
||||
std::string name;
|
||||
std::optional<unsigned int> maxPendingReadRequests;
|
||||
std::optional<unsigned int> maxPendingWriteRequests;
|
||||
|
||||
std::optional<uint64_t> seed;
|
||||
std::optional<uint64_t> maxTransactions;
|
||||
std::optional<unsigned> dataLength;
|
||||
std::optional<unsigned> dataAlignment;
|
||||
std::vector<std::variant<TrafficGeneratorActiveState, TrafficGeneratorIdleState>> states;
|
||||
std::vector<TrafficGeneratorStateTransition> transitions;
|
||||
};
|
||||
|
||||
NLOHMANN_JSONIFY_ALL_THINGS(TrafficGeneratorStateMachine,
|
||||
clkMhz,
|
||||
name,
|
||||
maxPendingReadRequests,
|
||||
maxPendingWriteRequests,
|
||||
seed,
|
||||
maxTransactions,
|
||||
dataLength,
|
||||
dataAlignment,
|
||||
states,
|
||||
transitions)
|
||||
|
||||
struct RowHammer
|
||||
{
|
||||
uint64_t clkMhz;
|
||||
std::string name;
|
||||
std::optional<unsigned int> maxPendingReadRequests;
|
||||
std::optional<unsigned int> maxPendingWriteRequests;
|
||||
|
||||
uint64_t numRequests;
|
||||
uint64_t rowIncrement;
|
||||
};
|
||||
|
||||
struct TraceSetup
|
||||
NLOHMANN_JSONIFY_ALL_THINGS(
|
||||
RowHammer, clkMhz, name, maxPendingReadRequests, maxPendingWriteRequests, numRequests, rowIncrement)
|
||||
|
||||
struct TraceSetupConstants
|
||||
{
|
||||
std::vector<std::variant<TracePlayer, TraceGenerator, TraceHammer>> initiators;
|
||||
static constexpr std::string_view KEY = "tracesetup";
|
||||
static constexpr std::string_view SUB_DIR = "tracesetup";
|
||||
};
|
||||
|
||||
void to_json(json_t &j, const TraceSetup &c);
|
||||
void from_json(const json_t &j, TraceSetup &c);
|
||||
|
||||
void from_dump(const std::string &dump, TraceSetup &c);
|
||||
std::string dump(const TraceSetup &c, unsigned int indentation = -1);
|
||||
using TraceSetup = std::vector<
|
||||
std::variant<TracePlayer, TrafficGenerator, TrafficGeneratorStateMachine, RowHammer>>;
|
||||
|
||||
} // namespace Configuration
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
namespace DRAMSys::Config
|
||||
{
|
||||
|
||||
void to_json(json_t &j, const MemArchitectureSpec &c)
|
||||
void to_json(json_t &j, const MemArchitectureSpecType &c)
|
||||
{
|
||||
j = json_t{};
|
||||
|
||||
@@ -48,7 +48,7 @@ void to_json(json_t &j, const MemArchitectureSpec &c)
|
||||
}
|
||||
}
|
||||
|
||||
void from_json(const json_t &j, MemArchitectureSpec &c)
|
||||
void from_json(const json_t &j, MemArchitectureSpecType &c)
|
||||
{
|
||||
for (const auto &entry : j.items())
|
||||
{
|
||||
|
||||
@@ -36,20 +36,20 @@
|
||||
#ifndef DRAMSYSCONFIGURATION_MEMARCHITECTURESPEC_H
|
||||
#define DRAMSYSCONFIGURATION_MEMARCHITECTURESPEC_H
|
||||
|
||||
#include "DRAMSys/config/ConfigUtil.h"
|
||||
#include "DRAMSys/util/json.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace DRAMSys::Config
|
||||
{
|
||||
|
||||
struct MemArchitectureSpec
|
||||
struct MemArchitectureSpecType
|
||||
{
|
||||
std::unordered_map<std::string, unsigned int> entries;
|
||||
};
|
||||
|
||||
void to_json(json_t &j, const MemArchitectureSpec &c);
|
||||
void from_json(const json_t &j, MemArchitectureSpec &c);
|
||||
void to_json(json_t &j, const MemArchitectureSpecType &c);
|
||||
void from_json(const json_t &j, MemArchitectureSpecType &c);
|
||||
|
||||
} // namespace Configuration
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
#ifndef DRAMSYSCONFIGURATION_MEMPOWERSPEC_H
|
||||
#define DRAMSYSCONFIGURATION_MEMPOWERSPEC_H
|
||||
|
||||
#include "DRAMSys/config/ConfigUtil.h"
|
||||
#include "DRAMSys/util/json.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
#ifndef DRAMSYSCONFIGURATION_MEMSPEC_H
|
||||
#define DRAMSYSCONFIGURATION_MEMSPEC_H
|
||||
|
||||
#include "DRAMSys/config/ConfigUtil.h"
|
||||
#include "DRAMSys/util/json.h"
|
||||
#include "DRAMSys/config/memspec/MemArchitectureSpec.h"
|
||||
#include "DRAMSys/config/memspec/MemPowerSpec.h"
|
||||
#include "DRAMSys/config/memspec/MemTimingSpec.h"
|
||||
@@ -45,22 +45,20 @@
|
||||
|
||||
namespace DRAMSys::Config {
|
||||
|
||||
const std::string memSpecPath = "memspec";
|
||||
|
||||
struct MemSpec
|
||||
{
|
||||
MemArchitectureSpec memArchitectureSpec;
|
||||
static constexpr std::string_view KEY = "memspec";
|
||||
static constexpr std::string_view SUB_DIR = "memspec";
|
||||
|
||||
MemArchitectureSpecType memarchitecturespec;
|
||||
std::string memoryId;
|
||||
std::string memoryType;
|
||||
MemTimingSpec memTimingSpec;
|
||||
std::optional<MemPowerSpec> memPowerSpec;
|
||||
MemTimingSpecType memtimingspec;
|
||||
std::optional<MemPowerSpec> mempowerspec;
|
||||
};
|
||||
|
||||
void to_json(json &j, const MemSpec &c);
|
||||
void from_json(const json &j, MemSpec &c);
|
||||
|
||||
void from_dump(const std::string &dump, MemSpec &c);
|
||||
std::string dump(const MemSpec &c, unsigned int indentation = -1);
|
||||
NLOHMANN_JSONIFY_ALL_THINGS(
|
||||
MemSpec, memarchitecturespec, memoryId, memoryType, memtimingspec, mempowerspec)
|
||||
|
||||
} // namespace Configuration
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
namespace DRAMSys::Config
|
||||
{
|
||||
|
||||
void to_json(json_t &j, const MemTimingSpec &c)
|
||||
void to_json(json_t &j, const MemTimingSpecType &c)
|
||||
{
|
||||
j = json_t{};
|
||||
|
||||
@@ -48,7 +48,7 @@ void to_json(json_t &j, const MemTimingSpec &c)
|
||||
}
|
||||
}
|
||||
|
||||
void from_json(const json_t &j, MemTimingSpec &c)
|
||||
void from_json(const json_t &j, MemTimingSpecType &c)
|
||||
{
|
||||
for (const auto &entry : j.items())
|
||||
{
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
#ifndef DRAMSYSCONFIGURATION_MEMTIMINGSPEC_H
|
||||
#define DRAMSYSCONFIGURATION_MEMTIMINGSPEC_H
|
||||
|
||||
#include "DRAMSys/config/ConfigUtil.h"
|
||||
#include "DRAMSys/util/json.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
@@ -44,13 +44,13 @@ namespace DRAMSys::Config
|
||||
{
|
||||
using json = nlohmann::json;
|
||||
|
||||
struct MemTimingSpec
|
||||
struct MemTimingSpecType
|
||||
{
|
||||
std::unordered_map<std::string, unsigned int> entries;
|
||||
};
|
||||
|
||||
void to_json(json &j, const MemTimingSpec &c);
|
||||
void from_json(const json &j, MemTimingSpec &c);
|
||||
void to_json(json &j, const MemTimingSpecType &c);
|
||||
void from_json(const json &j, MemTimingSpecType &c);
|
||||
|
||||
} // namespace Configuration
|
||||
|
||||
|
||||
@@ -288,4 +288,18 @@ public:
|
||||
static bool notifyChildTransCompletion(tlm::tlm_generic_payload& trans);
|
||||
};
|
||||
|
||||
class EccExtension : public tlm::tlm_extension<EccExtension>
|
||||
{
|
||||
public:
|
||||
tlm_extension_base* clone() const override
|
||||
{
|
||||
return new EccExtension;
|
||||
}
|
||||
|
||||
void copy_from(tlm_extension_base const &ext) override
|
||||
{
|
||||
auto const &cpyFrom = static_cast<EccExtension const &>(ext);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // DRAMEXTENSIONS_H
|
||||
|
||||
@@ -86,202 +86,232 @@ enum sc_time_unit string2TimeUnit(const std::string &s)
|
||||
}
|
||||
|
||||
void Configuration::loadSimConfig(const DRAMSys::Config::SimConfig &simConfig)
|
||||
{
|
||||
if (const auto& _addressOffset = simConfig.addressOffset)
|
||||
addressOffset = *_addressOffset;
|
||||
{
|
||||
addressOffset = simConfig.AddressOffset.value_or(addressOffset);
|
||||
checkTLM2Protocol = simConfig.CheckTLM2Protocol.value_or(checkTLM2Protocol);
|
||||
databaseRecording = simConfig.DatabaseRecording.value_or(databaseRecording);
|
||||
debug = simConfig.Debug.value_or(debug);
|
||||
enableWindowing = simConfig.EnableWindowing.value_or(enableWindowing);
|
||||
simulationName = simConfig.SimulationName.value_or(simulationName);
|
||||
simulationProgressBar = simConfig.SimulationProgressBar.value_or(simulationProgressBar);
|
||||
useMalloc = simConfig.UseMalloc.value_or(useMalloc);
|
||||
|
||||
if (const auto& _checkTLM2Protocol = simConfig.checkTLM2Protocol)
|
||||
checkTLM2Protocol = *_checkTLM2Protocol;
|
||||
|
||||
if (const auto& _databaseRecording = simConfig.databaseRecording)
|
||||
databaseRecording = *_databaseRecording;
|
||||
|
||||
if (const auto& _debug = simConfig.debug)
|
||||
debug = *_debug;
|
||||
|
||||
if (const auto& _enableWindowing = simConfig.enableWindowing)
|
||||
enableWindowing = *_enableWindowing;
|
||||
|
||||
if (const auto& _powerAnalysis = simConfig.powerAnalysis)
|
||||
{
|
||||
powerAnalysis = *_powerAnalysis;
|
||||
#ifndef DRAMPOWER
|
||||
if (powerAnalysis)
|
||||
SC_REPORT_FATAL("Configuration", "Power analysis is only supported with included DRAMPower library!");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (const auto& _simulationName = simConfig.simulationName)
|
||||
simulationName = *_simulationName;
|
||||
|
||||
if (const auto& _simulationProgressBar = simConfig.simulationProgressBar)
|
||||
simulationProgressBar = *_simulationProgressBar;
|
||||
|
||||
if (const auto& _useMalloc = simConfig.useMalloc)
|
||||
useMalloc = *_useMalloc;
|
||||
|
||||
if (const auto& _windowSize = simConfig.windowSize)
|
||||
windowSize = *_windowSize;
|
||||
if (const auto &_storeMode = simConfig.StoreMode)
|
||||
storeMode = [=]
|
||||
{
|
||||
switch (*_storeMode)
|
||||
{
|
||||
case DRAMSys::Config::StoreModeType::NoStorage:
|
||||
return StoreMode::NoStorage;
|
||||
case DRAMSys::Config::StoreModeType::Store:
|
||||
return StoreMode::Store;
|
||||
default:
|
||||
SC_REPORT_FATAL("Configuration", "Invalid StoreMode");
|
||||
return StoreMode::NoStorage; // Silence Warning
|
||||
}
|
||||
}();
|
||||
|
||||
windowSize = simConfig.WindowSize.value_or(windowSize);
|
||||
if (windowSize == 0)
|
||||
SC_REPORT_FATAL("Configuration", "Minimum window size is 1");
|
||||
|
||||
if (const auto& _storeMode = simConfig.storeMode)
|
||||
storeMode = [=] {
|
||||
if (_storeMode == DRAMSys::Config::StoreMode::NoStorage)
|
||||
return StoreMode::NoStorage;
|
||||
else // (_storeMode == DRAMSys::Config::StoreMode::Store)
|
||||
return StoreMode::Store;
|
||||
}();
|
||||
powerAnalysis = simConfig.PowerAnalysis.value_or(powerAnalysis);
|
||||
#ifndef DRAMPOWER
|
||||
if (powerAnalysis)
|
||||
SC_REPORT_FATAL("Configuration", "Power analysis is only supported with included DRAMPower library!");
|
||||
#endif
|
||||
}
|
||||
|
||||
void Configuration::loadMCConfig(const DRAMSys::Config::McConfig &mcConfig)
|
||||
{
|
||||
if (const auto& _pagePolicy = mcConfig.pagePolicy)
|
||||
pagePolicy = [=] {
|
||||
if (_pagePolicy == DRAMSys::Config::PagePolicy::Open)
|
||||
if (const auto &_pagePolicy = mcConfig.PagePolicy)
|
||||
pagePolicy = [=]
|
||||
{
|
||||
switch (*_pagePolicy)
|
||||
{
|
||||
case DRAMSys::Config::PagePolicyType::Open:
|
||||
return PagePolicy::Open;
|
||||
else if (_pagePolicy == DRAMSys::Config::PagePolicy::OpenAdaptive)
|
||||
case DRAMSys::Config::PagePolicyType::OpenAdaptive:
|
||||
return PagePolicy::OpenAdaptive;
|
||||
else if (_pagePolicy == DRAMSys::Config::PagePolicy::Closed)
|
||||
case DRAMSys::Config::PagePolicyType::Closed:
|
||||
return PagePolicy::Closed;
|
||||
else
|
||||
case DRAMSys::Config::PagePolicyType::ClosedAdaptive:
|
||||
return PagePolicy::ClosedAdaptive;
|
||||
default:
|
||||
SC_REPORT_FATAL("Configuration", "Invalid PagePolicy");
|
||||
return PagePolicy::Open; // Silence Warning
|
||||
}
|
||||
}();
|
||||
|
||||
if (const auto& _scheduler = mcConfig.scheduler)
|
||||
scheduler = [=] {
|
||||
if (_scheduler == DRAMSys::Config::Scheduler::Fifo)
|
||||
return Scheduler::Fifo;
|
||||
else if (_scheduler == DRAMSys::Config::Scheduler::FrFcfs)
|
||||
return Scheduler::FrFcfs;
|
||||
else if (_scheduler == DRAMSys::Config::Scheduler::FrFcfsGrp)
|
||||
return Scheduler::FrFcfsGrp;
|
||||
else if (_scheduler == DRAMSys::Config::Scheduler::GrpFrFcfs)
|
||||
return Scheduler::GrpFrFcfs;
|
||||
else
|
||||
return Scheduler::GrpFrFcfsWm;
|
||||
if (const auto &_scheduler = mcConfig.Scheduler)
|
||||
scheduler = [=]
|
||||
{
|
||||
switch (*_scheduler)
|
||||
{
|
||||
case DRAMSys::Config::SchedulerType::Fifo:
|
||||
return Scheduler::Fifo;
|
||||
case DRAMSys::Config::SchedulerType::FrFcfs:
|
||||
return Scheduler::FrFcfs;
|
||||
case DRAMSys::Config::SchedulerType::FrFcfsGrp:
|
||||
return Scheduler::FrFcfsGrp;
|
||||
case DRAMSys::Config::SchedulerType::GrpFrFcfs:
|
||||
return Scheduler::GrpFrFcfs;
|
||||
case DRAMSys::Config::SchedulerType::GrpFrFcfsWm:
|
||||
return Scheduler::GrpFrFcfsWm;
|
||||
default:
|
||||
SC_REPORT_FATAL("Configuration", "Invalid Scheduler");
|
||||
return Scheduler::Fifo; // Silence Warning
|
||||
}
|
||||
}();
|
||||
|
||||
if (const auto& _highWatermark = mcConfig.highWatermark)
|
||||
highWatermark = *mcConfig.highWatermark;
|
||||
|
||||
if (const auto& _lowWatermark = mcConfig.lowWatermark)
|
||||
lowWatermark = *mcConfig.lowWatermark;
|
||||
|
||||
if (const auto& _schedulerBuffer = mcConfig.schedulerBuffer)
|
||||
schedulerBuffer = [=] {
|
||||
if (_schedulerBuffer == DRAMSys::Config::SchedulerBuffer::Bankwise)
|
||||
if (const auto &_schedulerBuffer = mcConfig.SchedulerBuffer)
|
||||
schedulerBuffer = [=]
|
||||
{
|
||||
switch (*_schedulerBuffer)
|
||||
{
|
||||
case DRAMSys::Config::SchedulerBufferType::Bankwise:
|
||||
return SchedulerBuffer::Bankwise;
|
||||
else if (_schedulerBuffer == DRAMSys::Config::SchedulerBuffer::ReadWrite)
|
||||
case DRAMSys::Config::SchedulerBufferType::ReadWrite:
|
||||
return SchedulerBuffer::ReadWrite;
|
||||
else
|
||||
case DRAMSys::Config::SchedulerBufferType::Shared:
|
||||
return SchedulerBuffer::Shared;
|
||||
default:
|
||||
SC_REPORT_FATAL("Configuration", "Invalid SchedulerBuffer");
|
||||
return SchedulerBuffer::Bankwise; // Silence Warning
|
||||
}
|
||||
}();
|
||||
|
||||
if (const auto& _requestBufferSize = mcConfig.requestBufferSize)
|
||||
requestBufferSize = *mcConfig.requestBufferSize;
|
||||
if (const auto &_cmdMux = mcConfig.CmdMux)
|
||||
cmdMux = [=]
|
||||
{
|
||||
switch (*_cmdMux)
|
||||
{
|
||||
case DRAMSys::Config::CmdMuxType::Oldest:
|
||||
return CmdMux::Oldest;
|
||||
case DRAMSys::Config::CmdMuxType::Strict:
|
||||
return CmdMux::Strict;
|
||||
default:
|
||||
SC_REPORT_FATAL("Configuration", "Invalid CmdMux");
|
||||
return CmdMux::Oldest; // Silence Warning
|
||||
}
|
||||
}();
|
||||
|
||||
if (const auto &_respQueue = mcConfig.RespQueue)
|
||||
respQueue = [=]
|
||||
{
|
||||
switch (*_respQueue)
|
||||
{
|
||||
case DRAMSys::Config::RespQueueType::Fifo:
|
||||
return RespQueue::Fifo;
|
||||
case DRAMSys::Config::RespQueueType::Reorder:
|
||||
return RespQueue::Reorder;
|
||||
default:
|
||||
SC_REPORT_FATAL("Configuration", "Invalid RespQueue");
|
||||
return RespQueue::Fifo; // Silence Warning
|
||||
}
|
||||
}();
|
||||
|
||||
if (const auto &_refreshPolicy = mcConfig.RefreshPolicy)
|
||||
refreshPolicy = [=]
|
||||
{
|
||||
switch (*_refreshPolicy)
|
||||
{
|
||||
case DRAMSys::Config::RefreshPolicyType::NoRefresh:
|
||||
return RefreshPolicy::NoRefresh;
|
||||
case DRAMSys::Config::RefreshPolicyType::AllBank:
|
||||
return RefreshPolicy::AllBank;
|
||||
case DRAMSys::Config::RefreshPolicyType::PerBank:
|
||||
return RefreshPolicy::PerBank;
|
||||
case DRAMSys::Config::RefreshPolicyType::Per2Bank:
|
||||
return RefreshPolicy::Per2Bank;
|
||||
case DRAMSys::Config::RefreshPolicyType::SameBank:
|
||||
return RefreshPolicy::SameBank;
|
||||
default:
|
||||
SC_REPORT_FATAL("Configuration", "Invalid RefreshPolicy");
|
||||
return RefreshPolicy::NoRefresh; // Silence Warning
|
||||
}
|
||||
}();
|
||||
|
||||
if (const auto &_powerDownPolicy = mcConfig.PowerDownPolicy)
|
||||
powerDownPolicy = [=]
|
||||
{
|
||||
switch (*_powerDownPolicy)
|
||||
{
|
||||
case DRAMSys::Config::PowerDownPolicyType::NoPowerDown:
|
||||
return PowerDownPolicy::NoPowerDown;
|
||||
case DRAMSys::Config::PowerDownPolicyType::Staggered:
|
||||
return PowerDownPolicy::Staggered;
|
||||
default:
|
||||
SC_REPORT_FATAL("Configuration", "Invalid PowerDownPolicy");
|
||||
return PowerDownPolicy::NoPowerDown; // Silence Warning
|
||||
}
|
||||
}();
|
||||
|
||||
if (const auto &_arbiter = mcConfig.Arbiter)
|
||||
arbiter = [=]
|
||||
{
|
||||
switch (*_arbiter)
|
||||
{
|
||||
case DRAMSys::Config::ArbiterType::Simple:
|
||||
return Arbiter::Simple;
|
||||
case DRAMSys::Config::ArbiterType::Fifo:
|
||||
return Arbiter::Fifo;
|
||||
case DRAMSys::Config::ArbiterType::Reorder:
|
||||
return Arbiter::Reorder;
|
||||
default:
|
||||
SC_REPORT_FATAL("Configuration", "Invalid Arbiter");
|
||||
return Arbiter::Simple; // Silence Warning
|
||||
}
|
||||
}();
|
||||
|
||||
refreshMaxPostponed = mcConfig.RefreshMaxPostponed.value_or(refreshMaxPostponed);
|
||||
refreshMaxPulledin = mcConfig.RefreshMaxPulledin.value_or(refreshMaxPulledin);
|
||||
highWatermark = mcConfig.HighWatermark.value_or(highWatermark);
|
||||
lowWatermark = mcConfig.LowWatermark.value_or(lowWatermark);
|
||||
maxActiveTransactions = mcConfig.MaxActiveTransactions.value_or(maxActiveTransactions);
|
||||
refreshManagement = mcConfig.RefreshManagement.value_or(refreshManagement);
|
||||
|
||||
requestBufferSize = mcConfig.RequestBufferSize.value_or(requestBufferSize);
|
||||
if (requestBufferSize == 0)
|
||||
SC_REPORT_FATAL("Configuration", "Minimum request buffer size is 1!");
|
||||
|
||||
if (const auto& _cmdMux = mcConfig.cmdMux)
|
||||
cmdMux = [=] {
|
||||
if (_cmdMux == DRAMSys::Config::CmdMux::Oldest)
|
||||
return CmdMux::Oldest;
|
||||
else
|
||||
return CmdMux::Strict;
|
||||
}();
|
||||
|
||||
if (const auto& _respQueue = mcConfig.respQueue)
|
||||
respQueue = [=] {
|
||||
if (_respQueue == DRAMSys::Config::RespQueue::Fifo)
|
||||
return RespQueue::Fifo;
|
||||
else
|
||||
return RespQueue::Reorder;
|
||||
}();
|
||||
|
||||
if (const auto& _refreshPolicy = mcConfig.refreshPolicy)
|
||||
refreshPolicy = [=] {
|
||||
if (_refreshPolicy == DRAMSys::Config::RefreshPolicy::NoRefresh)
|
||||
return RefreshPolicy::NoRefresh;
|
||||
else if (_refreshPolicy == DRAMSys::Config::RefreshPolicy::AllBank)
|
||||
return RefreshPolicy::AllBank;
|
||||
else if (_refreshPolicy == DRAMSys::Config::RefreshPolicy::PerBank)
|
||||
return RefreshPolicy::PerBank;
|
||||
else if (_refreshPolicy == DRAMSys::Config::RefreshPolicy::Per2Bank)
|
||||
return RefreshPolicy::Per2Bank;
|
||||
else // if (policy == DRAMSys::Config::RefreshPolicy::SameBank)
|
||||
return RefreshPolicy::SameBank;
|
||||
}();
|
||||
|
||||
if (const auto& _refreshMaxPostponed = mcConfig.refreshMaxPostponed)
|
||||
refreshMaxPostponed = *_refreshMaxPostponed;
|
||||
|
||||
if (const auto& _refreshMaxPulledin = mcConfig.refreshMaxPulledin)
|
||||
refreshMaxPulledin = *_refreshMaxPulledin;
|
||||
|
||||
if (const auto& _powerDownPolicy = mcConfig.powerDownPolicy)
|
||||
powerDownPolicy = [=] {
|
||||
if (_powerDownPolicy == DRAMSys::Config::PowerDownPolicy::NoPowerDown)
|
||||
return PowerDownPolicy::NoPowerDown;
|
||||
else
|
||||
return PowerDownPolicy::Staggered;
|
||||
}();
|
||||
|
||||
if (const auto& _arbiter = mcConfig.arbiter)
|
||||
arbiter = [=] {
|
||||
if (_arbiter == DRAMSys::Config::Arbiter::Simple)
|
||||
return Arbiter::Simple;
|
||||
else if (_arbiter == DRAMSys::Config::Arbiter::Fifo)
|
||||
return Arbiter::Fifo;
|
||||
else
|
||||
return Arbiter::Reorder;
|
||||
}();
|
||||
|
||||
if (const auto& _maxActiveTransactions = mcConfig.maxActiveTransactions)
|
||||
maxActiveTransactions = *_maxActiveTransactions;
|
||||
|
||||
if (const auto& _refreshManagement = mcConfig.refreshManagement)
|
||||
refreshManagement = *_refreshManagement;
|
||||
|
||||
if (const auto& _arbitrationDelayFw = mcConfig.arbitrationDelayFw)
|
||||
if (const auto& _arbitrationDelayFw = mcConfig.ArbitrationDelayFw)
|
||||
{
|
||||
arbitrationDelayFw = std::round(sc_time(*_arbitrationDelayFw, SC_NS) / memSpec->tCK) * memSpec->tCK;
|
||||
}
|
||||
|
||||
if (const auto& _arbitrationDelayBw = mcConfig.arbitrationDelayBw)
|
||||
if (const auto& _arbitrationDelayBw = mcConfig.ArbitrationDelayBw)
|
||||
{
|
||||
arbitrationDelayBw = std::round(sc_time(*_arbitrationDelayBw, SC_NS) / memSpec->tCK) * memSpec->tCK;
|
||||
}
|
||||
|
||||
if (const auto& _thinkDelayFw = mcConfig.thinkDelayFw)
|
||||
if (const auto& _thinkDelayFw = mcConfig.ThinkDelayFw)
|
||||
{
|
||||
thinkDelayFw = std::round(sc_time(*_thinkDelayFw, SC_NS) / memSpec->tCK) * memSpec->tCK;
|
||||
}
|
||||
|
||||
if (const auto& _thinkDelayBw = mcConfig.thinkDelayBw)
|
||||
if (const auto& _thinkDelayBw = mcConfig.ThinkDelayBw)
|
||||
{
|
||||
thinkDelayBw = std::round(sc_time(*_thinkDelayBw, SC_NS) / memSpec->tCK) * memSpec->tCK;
|
||||
}
|
||||
|
||||
if (const auto& _phyDelayFw = mcConfig.phyDelayFw)
|
||||
if (const auto& _phyDelayFw = mcConfig.PhyDelayFw)
|
||||
{
|
||||
phyDelayFw = std::round(sc_time(*_phyDelayFw, SC_NS) / memSpec->tCK) * memSpec->tCK;
|
||||
}
|
||||
|
||||
if (const auto& _phyDelayBw = mcConfig.phyDelayBw)
|
||||
if (const auto& _phyDelayBw = mcConfig.PhyDelayBw)
|
||||
{
|
||||
phyDelayBw = std::round(sc_time(*_phyDelayBw, SC_NS) / memSpec->tCK) * memSpec->tCK;
|
||||
}
|
||||
|
||||
{
|
||||
auto _blockingReadDelay = mcConfig.blockingReadDelay.value_or(60);
|
||||
auto _blockingReadDelay = mcConfig.BlockingReadDelay.value_or(60);
|
||||
blockingReadDelay = std::round(sc_time(_blockingReadDelay, SC_NS) / memSpec->tCK) * memSpec->tCK;
|
||||
}
|
||||
|
||||
{
|
||||
auto _blockingWriteDelay = mcConfig.blockingWriteDelay.value_or(60);
|
||||
auto _blockingWriteDelay = mcConfig.BlockingWriteDelay.value_or(60);
|
||||
blockingWriteDelay = std::round(sc_time(_blockingWriteDelay, SC_NS) / memSpec->tCK) * memSpec->tCK;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,20 +55,20 @@ MemSpec::MemSpec(const DRAMSys::Config::MemSpec& memSpec,
|
||||
banksPerChannel(banksPerChannel),
|
||||
bankGroupsPerChannel(bankGroupsPerChannel),
|
||||
devicesPerRank(devicesPerRank),
|
||||
rowsPerBank(memSpec.memArchitectureSpec.entries.at("nbrOfRows")),
|
||||
columnsPerRow(memSpec.memArchitectureSpec.entries.at("nbrOfColumns")),
|
||||
defaultBurstLength(memSpec.memArchitectureSpec.entries.at("burstLength")),
|
||||
maxBurstLength(memSpec.memArchitectureSpec.entries.find("maxBurstLength") !=
|
||||
memSpec.memArchitectureSpec.entries.end()
|
||||
? memSpec.memArchitectureSpec.entries.at("maxBurstLength")
|
||||
rowsPerBank(memSpec.memarchitecturespec.entries.at("nbrOfRows")),
|
||||
columnsPerRow(memSpec.memarchitecturespec.entries.at("nbrOfColumns")),
|
||||
defaultBurstLength(memSpec.memarchitecturespec.entries.at("burstLength")),
|
||||
maxBurstLength(memSpec.memarchitecturespec.entries.find("maxBurstLength") !=
|
||||
memSpec.memarchitecturespec.entries.end()
|
||||
? memSpec.memarchitecturespec.entries.at("maxBurstLength")
|
||||
: defaultBurstLength),
|
||||
dataRate(memSpec.memArchitectureSpec.entries.at("dataRate")),
|
||||
bitWidth(memSpec.memArchitectureSpec.entries.at("width")),
|
||||
dataRate(memSpec.memarchitecturespec.entries.at("dataRate")),
|
||||
bitWidth(memSpec.memarchitecturespec.entries.at("width")),
|
||||
dataBusWidth(bitWidth* devicesPerRank),
|
||||
bytesPerBeat(dataBusWidth / 8),
|
||||
defaultBytesPerBurst((defaultBurstLength* dataBusWidth) / 8),
|
||||
maxBytesPerBurst((maxBurstLength* dataBusWidth) / 8),
|
||||
fCKMHz(memSpec.memTimingSpec.entries.at("clkMhz")),
|
||||
fCKMHz(memSpec.memtimingspec.entries.at("clkMhz")),
|
||||
tCK(sc_time(1.0 / fCKMHz, SC_US)),
|
||||
memoryId(memSpec.memoryId),
|
||||
memoryType(memoryType),
|
||||
|
||||
@@ -45,61 +45,61 @@ using namespace tlm;
|
||||
|
||||
MemSpecDDR3::MemSpecDDR3(const DRAMSys::Config::MemSpec &memSpec)
|
||||
: MemSpec(memSpec, MemoryType::DDR3,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfChannels"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfChannels"),
|
||||
1,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks"),
|
||||
1,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks")
|
||||
* memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfDevices")),
|
||||
tCKE (tCK * memSpec.memTimingSpec.entries.at("CKE")),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks")
|
||||
* memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfDevices")),
|
||||
tCKE (tCK * memSpec.memtimingspec.entries.at("CKE")),
|
||||
tPD (tCKE),
|
||||
tCKESR (tCK * memSpec.memTimingSpec.entries.at("CKESR")),
|
||||
tDQSCK (tCK * memSpec.memTimingSpec.entries.at("DQSCK")),
|
||||
tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")),
|
||||
tRC (tCK * memSpec.memTimingSpec.entries.at("RC")),
|
||||
tRCD (tCK * memSpec.memTimingSpec.entries.at("RCD")),
|
||||
tRL (tCK * memSpec.memTimingSpec.entries.at("RL")),
|
||||
tRTP (tCK * memSpec.memTimingSpec.entries.at("RTP")),
|
||||
tWL (tCK * memSpec.memTimingSpec.entries.at("WL")),
|
||||
tWR (tCK * memSpec.memTimingSpec.entries.at("WR")),
|
||||
tXP (tCK * memSpec.memTimingSpec.entries.at("XP")),
|
||||
tXS (tCK * memSpec.memTimingSpec.entries.at("XS")),
|
||||
tCCD (tCK * memSpec.memTimingSpec.entries.at("CCD")),
|
||||
tFAW (tCK * memSpec.memTimingSpec.entries.at("FAW")),
|
||||
tREFI (tCK * memSpec.memTimingSpec.entries.at("REFI")),
|
||||
tRFC (tCK * memSpec.memTimingSpec.entries.at("RFC")),
|
||||
tRP (tCK * memSpec.memTimingSpec.entries.at("RP")),
|
||||
tRRD (tCK * memSpec.memTimingSpec.entries.at("RRD")),
|
||||
tWTR (tCK * memSpec.memTimingSpec.entries.at("WTR")),
|
||||
tAL (tCK * memSpec.memTimingSpec.entries.at("AL")),
|
||||
tXPDLL (tCK * memSpec.memTimingSpec.entries.at("XPDLL")),
|
||||
tXSDLL (tCK * memSpec.memTimingSpec.entries.at("XSDLL")),
|
||||
tACTPDEN (tCK * memSpec.memTimingSpec.entries.at("ACTPDEN")),
|
||||
tPRPDEN (tCK * memSpec.memTimingSpec.entries.at("PRPDEN")),
|
||||
tREFPDEN (tCK * memSpec.memTimingSpec.entries.at("REFPDEN")),
|
||||
tRTRS (tCK * memSpec.memTimingSpec.entries.at("RTRS")),
|
||||
iDD0 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd0") : 0),
|
||||
iDD2N (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd2n") : 0),
|
||||
iDD3N (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd3n") : 0),
|
||||
iDD4R (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd4r") : 0),
|
||||
iDD4W (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd4w") : 0),
|
||||
iDD5 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd5") : 0),
|
||||
iDD6 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd6") : 0),
|
||||
vDD (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("vdd") : 0),
|
||||
iDD2P0 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd2p0") : 0),
|
||||
iDD2P1 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd2p1") : 0),
|
||||
iDD3P0 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd3p0") : 0),
|
||||
iDD3P1 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd3p1") : 0)
|
||||
tCKESR (tCK * memSpec.memtimingspec.entries.at("CKESR")),
|
||||
tDQSCK (tCK * memSpec.memtimingspec.entries.at("DQSCK")),
|
||||
tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")),
|
||||
tRC (tCK * memSpec.memtimingspec.entries.at("RC")),
|
||||
tRCD (tCK * memSpec.memtimingspec.entries.at("RCD")),
|
||||
tRL (tCK * memSpec.memtimingspec.entries.at("RL")),
|
||||
tRTP (tCK * memSpec.memtimingspec.entries.at("RTP")),
|
||||
tWL (tCK * memSpec.memtimingspec.entries.at("WL")),
|
||||
tWR (tCK * memSpec.memtimingspec.entries.at("WR")),
|
||||
tXP (tCK * memSpec.memtimingspec.entries.at("XP")),
|
||||
tXS (tCK * memSpec.memtimingspec.entries.at("XS")),
|
||||
tCCD (tCK * memSpec.memtimingspec.entries.at("CCD")),
|
||||
tFAW (tCK * memSpec.memtimingspec.entries.at("FAW")),
|
||||
tREFI (tCK * memSpec.memtimingspec.entries.at("REFI")),
|
||||
tRFC (tCK * memSpec.memtimingspec.entries.at("RFC")),
|
||||
tRP (tCK * memSpec.memtimingspec.entries.at("RP")),
|
||||
tRRD (tCK * memSpec.memtimingspec.entries.at("RRD")),
|
||||
tWTR (tCK * memSpec.memtimingspec.entries.at("WTR")),
|
||||
tAL (tCK * memSpec.memtimingspec.entries.at("AL")),
|
||||
tXPDLL (tCK * memSpec.memtimingspec.entries.at("XPDLL")),
|
||||
tXSDLL (tCK * memSpec.memtimingspec.entries.at("XSDLL")),
|
||||
tACTPDEN (tCK * memSpec.memtimingspec.entries.at("ACTPDEN")),
|
||||
tPRPDEN (tCK * memSpec.memtimingspec.entries.at("PRPDEN")),
|
||||
tREFPDEN (tCK * memSpec.memtimingspec.entries.at("REFPDEN")),
|
||||
tRTRS (tCK * memSpec.memtimingspec.entries.at("RTRS")),
|
||||
iDD0 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd0") : 0),
|
||||
iDD2N (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd2n") : 0),
|
||||
iDD3N (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd3n") : 0),
|
||||
iDD4R (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd4r") : 0),
|
||||
iDD4W (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd4w") : 0),
|
||||
iDD5 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd5") : 0),
|
||||
iDD6 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd6") : 0),
|
||||
vDD (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("vdd") : 0),
|
||||
iDD2P0 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd2p0") : 0),
|
||||
iDD2P1 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd2p1") : 0),
|
||||
iDD3P0 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd3p0") : 0),
|
||||
iDD3P1 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd3p1") : 0)
|
||||
{
|
||||
uint64_t deviceSizeBits = static_cast<uint64_t>(banksPerRank) * rowsPerBank * columnsPerRow * bitWidth;
|
||||
uint64_t deviceSizeBytes = deviceSizeBits / 8;
|
||||
memorySizeBytes = deviceSizeBytes * devicesPerRank * ranksPerChannel * numberOfChannels;
|
||||
|
||||
if (!memSpec.memPowerSpec.has_value())
|
||||
if (!memSpec.mempowerspec.has_value())
|
||||
SC_REPORT_FATAL("MemSpec", "No power spec defined!");
|
||||
|
||||
std::cout << headline << std::endl;
|
||||
|
||||
@@ -45,79 +45,79 @@ using namespace tlm;
|
||||
|
||||
MemSpecDDR4::MemSpecDDR4(const DRAMSys::Config::MemSpec &memSpec)
|
||||
: MemSpec(memSpec, MemoryType::DDR4,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfChannels"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfChannels"),
|
||||
1,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks")
|
||||
/ memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks")
|
||||
* memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups")
|
||||
* memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfDevices")),
|
||||
tCKE (tCK * memSpec.memTimingSpec.entries.at("CKE")),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks")
|
||||
/ memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks")
|
||||
* memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBankGroups")
|
||||
* memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfDevices")),
|
||||
tCKE (tCK * memSpec.memtimingspec.entries.at("CKE")),
|
||||
tPD (tCKE),
|
||||
tCKESR (tCK * memSpec.memTimingSpec.entries.at("CKESR")),
|
||||
tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")),
|
||||
tRC (tCK * memSpec.memTimingSpec.entries.at("RC")),
|
||||
tRCD (tCK * memSpec.memTimingSpec.entries.at("RCD")),
|
||||
tRL (tCK * memSpec.memTimingSpec.entries.at("RL")),
|
||||
tRPRE (tCK * memSpec.memTimingSpec.entries.at("RPRE")),
|
||||
tRTP (tCK * memSpec.memTimingSpec.entries.at("RTP")),
|
||||
tWL (tCK * memSpec.memTimingSpec.entries.at("WL")),
|
||||
tWPRE (tCK * memSpec.memTimingSpec.entries.at("WPRE")),
|
||||
tWR (tCK * memSpec.memTimingSpec.entries.at("WR")),
|
||||
tXP (tCK * memSpec.memTimingSpec.entries.at("XP")),
|
||||
tXS (tCK * memSpec.memTimingSpec.entries.at("XS")),
|
||||
tREFI ((memSpec.memTimingSpec.entries.at("REFM") == 4) ?
|
||||
(tCK * (static_cast<double>(memSpec.memTimingSpec.entries.at("REFI")) / 4)) :
|
||||
((memSpec.memTimingSpec.entries.at("REFM") == 2) ?
|
||||
(tCK * (static_cast<double>(memSpec.memTimingSpec.entries.at("REFI")) / 2)) :
|
||||
(tCK * memSpec.memTimingSpec.entries.at("REFI")))),
|
||||
tRFC ((memSpec.memTimingSpec.entries.at("REFM") == 4) ?
|
||||
(tCK * memSpec.memTimingSpec.entries.at("RFC4")) :
|
||||
((memSpec.memTimingSpec.entries.at("REFM") == 2) ?
|
||||
(tCK * memSpec.memTimingSpec.entries.at("RFC2")) :
|
||||
(tCK * memSpec.memTimingSpec.entries.at("RFC")))),
|
||||
tRP (tCK * memSpec.memTimingSpec.entries.at("RP")),
|
||||
tDQSCK (tCK * memSpec.memTimingSpec.entries.at("DQSCK")),
|
||||
tCCD_S (tCK * memSpec.memTimingSpec.entries.at("CCD_S")),
|
||||
tCCD_L (tCK * memSpec.memTimingSpec.entries.at("CCD_L")),
|
||||
tFAW (tCK * memSpec.memTimingSpec.entries.at("FAW")),
|
||||
tRRD_S (tCK * memSpec.memTimingSpec.entries.at("RRD_S")),
|
||||
tRRD_L (tCK * memSpec.memTimingSpec.entries.at("RRD_L")),
|
||||
tWTR_S (tCK * memSpec.memTimingSpec.entries.at("WTR_S")),
|
||||
tWTR_L (tCK * memSpec.memTimingSpec.entries.at("WTR_L")),
|
||||
tAL (tCK * memSpec.memTimingSpec.entries.at("AL")),
|
||||
tXPDLL (tCK * memSpec.memTimingSpec.entries.at("XPDLL")),
|
||||
tXSDLL (tCK * memSpec.memTimingSpec.entries.at("XSDLL")),
|
||||
tACTPDEN (tCK * memSpec.memTimingSpec.entries.at("ACTPDEN")),
|
||||
tPRPDEN (tCK * memSpec.memTimingSpec.entries.at("PRPDEN")),
|
||||
tREFPDEN (tCK * memSpec.memTimingSpec.entries.at("REFPDEN")),
|
||||
tRTRS (tCK * memSpec.memTimingSpec.entries.at("RTRS")),
|
||||
iDD0 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd0") : 0),
|
||||
iDD2N (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd2n") : 0),
|
||||
iDD3N (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd3n") : 0),
|
||||
iDD4R (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd4r") : 0),
|
||||
iDD4W (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd4w") : 0),
|
||||
iDD5 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd5") : 0),
|
||||
iDD6 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd6") : 0),
|
||||
vDD (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("vdd") : 0),
|
||||
iDD02 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd02") : 0),
|
||||
iDD2P0 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd2p0") : 0),
|
||||
iDD2P1 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd2p1") : 0),
|
||||
iDD3P0 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd3p0") : 0),
|
||||
iDD3P1 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd3p1") : 0),
|
||||
iDD62 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd62") : 0),
|
||||
vDD2 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("vdd2") : 0)
|
||||
tCKESR (tCK * memSpec.memtimingspec.entries.at("CKESR")),
|
||||
tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")),
|
||||
tRC (tCK * memSpec.memtimingspec.entries.at("RC")),
|
||||
tRCD (tCK * memSpec.memtimingspec.entries.at("RCD")),
|
||||
tRL (tCK * memSpec.memtimingspec.entries.at("RL")),
|
||||
tRPRE (tCK * memSpec.memtimingspec.entries.at("RPRE")),
|
||||
tRTP (tCK * memSpec.memtimingspec.entries.at("RTP")),
|
||||
tWL (tCK * memSpec.memtimingspec.entries.at("WL")),
|
||||
tWPRE (tCK * memSpec.memtimingspec.entries.at("WPRE")),
|
||||
tWR (tCK * memSpec.memtimingspec.entries.at("WR")),
|
||||
tXP (tCK * memSpec.memtimingspec.entries.at("XP")),
|
||||
tXS (tCK * memSpec.memtimingspec.entries.at("XS")),
|
||||
tREFI ((memSpec.memtimingspec.entries.at("REFM") == 4) ?
|
||||
(tCK * (static_cast<double>(memSpec.memtimingspec.entries.at("REFI")) / 4)) :
|
||||
((memSpec.memtimingspec.entries.at("REFM") == 2) ?
|
||||
(tCK * (static_cast<double>(memSpec.memtimingspec.entries.at("REFI")) / 2)) :
|
||||
(tCK * memSpec.memtimingspec.entries.at("REFI")))),
|
||||
tRFC ((memSpec.memtimingspec.entries.at("REFM") == 4) ?
|
||||
(tCK * memSpec.memtimingspec.entries.at("RFC4")) :
|
||||
((memSpec.memtimingspec.entries.at("REFM") == 2) ?
|
||||
(tCK * memSpec.memtimingspec.entries.at("RFC2")) :
|
||||
(tCK * memSpec.memtimingspec.entries.at("RFC")))),
|
||||
tRP (tCK * memSpec.memtimingspec.entries.at("RP")),
|
||||
tDQSCK (tCK * memSpec.memtimingspec.entries.at("DQSCK")),
|
||||
tCCD_S (tCK * memSpec.memtimingspec.entries.at("CCD_S")),
|
||||
tCCD_L (tCK * memSpec.memtimingspec.entries.at("CCD_L")),
|
||||
tFAW (tCK * memSpec.memtimingspec.entries.at("FAW")),
|
||||
tRRD_S (tCK * memSpec.memtimingspec.entries.at("RRD_S")),
|
||||
tRRD_L (tCK * memSpec.memtimingspec.entries.at("RRD_L")),
|
||||
tWTR_S (tCK * memSpec.memtimingspec.entries.at("WTR_S")),
|
||||
tWTR_L (tCK * memSpec.memtimingspec.entries.at("WTR_L")),
|
||||
tAL (tCK * memSpec.memtimingspec.entries.at("AL")),
|
||||
tXPDLL (tCK * memSpec.memtimingspec.entries.at("XPDLL")),
|
||||
tXSDLL (tCK * memSpec.memtimingspec.entries.at("XSDLL")),
|
||||
tACTPDEN (tCK * memSpec.memtimingspec.entries.at("ACTPDEN")),
|
||||
tPRPDEN (tCK * memSpec.memtimingspec.entries.at("PRPDEN")),
|
||||
tREFPDEN (tCK * memSpec.memtimingspec.entries.at("REFPDEN")),
|
||||
tRTRS (tCK * memSpec.memtimingspec.entries.at("RTRS")),
|
||||
iDD0 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd0") : 0),
|
||||
iDD2N (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd2n") : 0),
|
||||
iDD3N (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd3n") : 0),
|
||||
iDD4R (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd4r") : 0),
|
||||
iDD4W (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd4w") : 0),
|
||||
iDD5 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd5") : 0),
|
||||
iDD6 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd6") : 0),
|
||||
vDD (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("vdd") : 0),
|
||||
iDD02 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd02") : 0),
|
||||
iDD2P0 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd2p0") : 0),
|
||||
iDD2P1 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd2p1") : 0),
|
||||
iDD3P0 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd3p0") : 0),
|
||||
iDD3P1 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd3p1") : 0),
|
||||
iDD62 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd62") : 0),
|
||||
vDD2 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("vdd2") : 0)
|
||||
{
|
||||
uint64_t deviceSizeBits = static_cast<uint64_t>(banksPerRank) * rowsPerBank * columnsPerRow * bitWidth;
|
||||
uint64_t deviceSizeBytes = deviceSizeBits / 8;
|
||||
memorySizeBytes = deviceSizeBytes * devicesPerRank * ranksPerChannel * numberOfChannels;
|
||||
|
||||
if (!memSpec.memPowerSpec.has_value())
|
||||
if (!memSpec.mempowerspec.has_value())
|
||||
SC_REPORT_WARNING("MemSpec", "No power spec defined!");
|
||||
|
||||
std::cout << headline << std::endl;
|
||||
|
||||
@@ -45,52 +45,52 @@ using namespace tlm;
|
||||
|
||||
MemSpecGDDR5::MemSpecGDDR5(const DRAMSys::Config::MemSpec &memSpec)
|
||||
: MemSpec(memSpec, MemoryType::GDDR5,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfChannels"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfChannels"),
|
||||
1,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks")
|
||||
/ memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks")
|
||||
* memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups")
|
||||
* memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfDevices")),
|
||||
tRP (tCK * memSpec.memTimingSpec.entries.at("RP")),
|
||||
tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")),
|
||||
tRC (tCK * memSpec.memTimingSpec.entries.at("RC")),
|
||||
tRCDRD (tCK * memSpec.memTimingSpec.entries.at("RCDRD")),
|
||||
tRCDWR (tCK * memSpec.memTimingSpec.entries.at("RCDWR")),
|
||||
tRTP (tCK * memSpec.memTimingSpec.entries.at("RTP")),
|
||||
tRRDS (tCK * memSpec.memTimingSpec.entries.at("RRDS")),
|
||||
tRRDL (tCK * memSpec.memTimingSpec.entries.at("RRDL")),
|
||||
tCCDS (tCK * memSpec.memTimingSpec.entries.at("CCDS")),
|
||||
tCCDL (tCK * memSpec.memTimingSpec.entries.at("CCDL")),
|
||||
tCL (tCK * memSpec.memTimingSpec.entries.at("CL")),
|
||||
tWCK2CKPIN (tCK * memSpec.memTimingSpec.entries.at("WCK2CKPIN")),
|
||||
tWCK2CK (tCK * memSpec.memTimingSpec.entries.at("WCK2CK")),
|
||||
tWCK2DQO (tCK * memSpec.memTimingSpec.entries.at("WCK2DQO")),
|
||||
tRTW (tCK * memSpec.memTimingSpec.entries.at("RTW")),
|
||||
tWL (tCK * memSpec.memTimingSpec.entries.at("WL")),
|
||||
tWCK2DQI (tCK * memSpec.memTimingSpec.entries.at("WCK2DQI")),
|
||||
tWR (tCK * memSpec.memTimingSpec.entries.at("WR")),
|
||||
tWTRS (tCK * memSpec.memTimingSpec.entries.at("WTRS")),
|
||||
tWTRL (tCK * memSpec.memTimingSpec.entries.at("WTRL")),
|
||||
tCKE (tCK * memSpec.memTimingSpec.entries.at("CKE")),
|
||||
tPD (tCK * memSpec.memTimingSpec.entries.at("PD")),
|
||||
tXPN (tCK * memSpec.memTimingSpec.entries.at("XPN")),
|
||||
tREFI (tCK * memSpec.memTimingSpec.entries.at("REFI")),
|
||||
tREFIPB (tCK * memSpec.memTimingSpec.entries.at("REFIPB")),
|
||||
tRFC (tCK * memSpec.memTimingSpec.entries.at("RFC")),
|
||||
tRFCPB (tCK * memSpec.memTimingSpec.entries.at("RFCPB")),
|
||||
tRREFD (tCK * memSpec.memTimingSpec.entries.at("RREFD")),
|
||||
tXS (tCK * memSpec.memTimingSpec.entries.at("XS")),
|
||||
tFAW (tCK * memSpec.memTimingSpec.entries.at("FAW")),
|
||||
t32AW (tCK * memSpec.memTimingSpec.entries.at("32AW")),
|
||||
tPPD (tCK * memSpec.memTimingSpec.entries.at("PPD")),
|
||||
tLK (tCK * memSpec.memTimingSpec.entries.at("LK")),
|
||||
tRTRS (tCK * memSpec.memTimingSpec.entries.at("RTRS"))
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks")
|
||||
/ memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks")
|
||||
* memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBankGroups")
|
||||
* memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfDevices")),
|
||||
tRP (tCK * memSpec.memtimingspec.entries.at("RP")),
|
||||
tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")),
|
||||
tRC (tCK * memSpec.memtimingspec.entries.at("RC")),
|
||||
tRCDRD (tCK * memSpec.memtimingspec.entries.at("RCDRD")),
|
||||
tRCDWR (tCK * memSpec.memtimingspec.entries.at("RCDWR")),
|
||||
tRTP (tCK * memSpec.memtimingspec.entries.at("RTP")),
|
||||
tRRDS (tCK * memSpec.memtimingspec.entries.at("RRDS")),
|
||||
tRRDL (tCK * memSpec.memtimingspec.entries.at("RRDL")),
|
||||
tCCDS (tCK * memSpec.memtimingspec.entries.at("CCDS")),
|
||||
tCCDL (tCK * memSpec.memtimingspec.entries.at("CCDL")),
|
||||
tCL (tCK * memSpec.memtimingspec.entries.at("CL")),
|
||||
tWCK2CKPIN (tCK * memSpec.memtimingspec.entries.at("WCK2CKPIN")),
|
||||
tWCK2CK (tCK * memSpec.memtimingspec.entries.at("WCK2CK")),
|
||||
tWCK2DQO (tCK * memSpec.memtimingspec.entries.at("WCK2DQO")),
|
||||
tRTW (tCK * memSpec.memtimingspec.entries.at("RTW")),
|
||||
tWL (tCK * memSpec.memtimingspec.entries.at("WL")),
|
||||
tWCK2DQI (tCK * memSpec.memtimingspec.entries.at("WCK2DQI")),
|
||||
tWR (tCK * memSpec.memtimingspec.entries.at("WR")),
|
||||
tWTRS (tCK * memSpec.memtimingspec.entries.at("WTRS")),
|
||||
tWTRL (tCK * memSpec.memtimingspec.entries.at("WTRL")),
|
||||
tCKE (tCK * memSpec.memtimingspec.entries.at("CKE")),
|
||||
tPD (tCK * memSpec.memtimingspec.entries.at("PD")),
|
||||
tXPN (tCK * memSpec.memtimingspec.entries.at("XPN")),
|
||||
tREFI (tCK * memSpec.memtimingspec.entries.at("REFI")),
|
||||
tREFIPB (tCK * memSpec.memtimingspec.entries.at("REFIPB")),
|
||||
tRFC (tCK * memSpec.memtimingspec.entries.at("RFC")),
|
||||
tRFCPB (tCK * memSpec.memtimingspec.entries.at("RFCPB")),
|
||||
tRREFD (tCK * memSpec.memtimingspec.entries.at("RREFD")),
|
||||
tXS (tCK * memSpec.memtimingspec.entries.at("XS")),
|
||||
tFAW (tCK * memSpec.memtimingspec.entries.at("FAW")),
|
||||
t32AW (tCK * memSpec.memtimingspec.entries.at("32AW")),
|
||||
tPPD (tCK * memSpec.memtimingspec.entries.at("PPD")),
|
||||
tLK (tCK * memSpec.memtimingspec.entries.at("LK")),
|
||||
tRTRS (tCK * memSpec.memtimingspec.entries.at("RTRS"))
|
||||
{
|
||||
uint64_t deviceSizeBits = static_cast<uint64_t>(banksPerRank) * rowsPerBank * columnsPerRow * bitWidth;
|
||||
uint64_t deviceSizeBytes = deviceSizeBits / 8;
|
||||
|
||||
@@ -45,52 +45,52 @@ using namespace tlm;
|
||||
|
||||
MemSpecGDDR5X::MemSpecGDDR5X(const DRAMSys::Config::MemSpec &memSpec)
|
||||
: MemSpec(memSpec, MemoryType::GDDR5X,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfChannels"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfChannels"),
|
||||
1,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks")
|
||||
/ memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks")
|
||||
* memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups")
|
||||
* memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfDevices")),
|
||||
tRP (tCK * memSpec.memTimingSpec.entries.at("RP")),
|
||||
tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")),
|
||||
tRC (tCK * memSpec.memTimingSpec.entries.at("RC")),
|
||||
tRCDRD (tCK * memSpec.memTimingSpec.entries.at("RCDRD")),
|
||||
tRCDWR (tCK * memSpec.memTimingSpec.entries.at("RCDWR")),
|
||||
tRTP (tCK * memSpec.memTimingSpec.entries.at("RTP")),
|
||||
tRRDS (tCK * memSpec.memTimingSpec.entries.at("RRDS")),
|
||||
tRRDL (tCK * memSpec.memTimingSpec.entries.at("RRDL")),
|
||||
tCCDS (tCK * memSpec.memTimingSpec.entries.at("CCDS")),
|
||||
tCCDL (tCK * memSpec.memTimingSpec.entries.at("CCDL")),
|
||||
tRL (tCK * memSpec.memTimingSpec.entries.at("CL")),
|
||||
tWCK2CKPIN (tCK * memSpec.memTimingSpec.entries.at("WCK2CKPIN")),
|
||||
tWCK2CK (tCK * memSpec.memTimingSpec.entries.at("WCK2CK")),
|
||||
tWCK2DQO (tCK * memSpec.memTimingSpec.entries.at("WCK2DQO")),
|
||||
tRTW (tCK * memSpec.memTimingSpec.entries.at("RTW")),
|
||||
tWL (tCK * memSpec.memTimingSpec.entries.at("WL")),
|
||||
tWCK2DQI (tCK * memSpec.memTimingSpec.entries.at("WCK2DQI")),
|
||||
tWR (tCK * memSpec.memTimingSpec.entries.at("WR")),
|
||||
tWTRS (tCK * memSpec.memTimingSpec.entries.at("WTRS")),
|
||||
tWTRL (tCK * memSpec.memTimingSpec.entries.at("WTRL")),
|
||||
tCKE (tCK * memSpec.memTimingSpec.entries.at("CKE")),
|
||||
tPD (tCK * memSpec.memTimingSpec.entries.at("PD")),
|
||||
tXP (tCK * memSpec.memTimingSpec.entries.at("XP")),
|
||||
tREFI (tCK * memSpec.memTimingSpec.entries.at("REFI")),
|
||||
tREFIPB (tCK * memSpec.memTimingSpec.entries.at("REFIPB")),
|
||||
tRFC (tCK * memSpec.memTimingSpec.entries.at("RFC")),
|
||||
tRFCPB (tCK * memSpec.memTimingSpec.entries.at("RFCPB")),
|
||||
tRREFD (tCK * memSpec.memTimingSpec.entries.at("RREFD")),
|
||||
tXS (tCK * memSpec.memTimingSpec.entries.at("XS")),
|
||||
tFAW (tCK * memSpec.memTimingSpec.entries.at("FAW")),
|
||||
t32AW (tCK * memSpec.memTimingSpec.entries.at("32AW")),
|
||||
tPPD (tCK * memSpec.memTimingSpec.entries.at("PPD")),
|
||||
tLK (tCK * memSpec.memTimingSpec.entries.at("LK")),
|
||||
tRTRS (tCK * memSpec.memTimingSpec.entries.at("TRS"))
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks")
|
||||
/ memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks")
|
||||
* memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBankGroups")
|
||||
* memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfDevices")),
|
||||
tRP (tCK * memSpec.memtimingspec.entries.at("RP")),
|
||||
tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")),
|
||||
tRC (tCK * memSpec.memtimingspec.entries.at("RC")),
|
||||
tRCDRD (tCK * memSpec.memtimingspec.entries.at("RCDRD")),
|
||||
tRCDWR (tCK * memSpec.memtimingspec.entries.at("RCDWR")),
|
||||
tRTP (tCK * memSpec.memtimingspec.entries.at("RTP")),
|
||||
tRRDS (tCK * memSpec.memtimingspec.entries.at("RRDS")),
|
||||
tRRDL (tCK * memSpec.memtimingspec.entries.at("RRDL")),
|
||||
tCCDS (tCK * memSpec.memtimingspec.entries.at("CCDS")),
|
||||
tCCDL (tCK * memSpec.memtimingspec.entries.at("CCDL")),
|
||||
tRL (tCK * memSpec.memtimingspec.entries.at("CL")),
|
||||
tWCK2CKPIN (tCK * memSpec.memtimingspec.entries.at("WCK2CKPIN")),
|
||||
tWCK2CK (tCK * memSpec.memtimingspec.entries.at("WCK2CK")),
|
||||
tWCK2DQO (tCK * memSpec.memtimingspec.entries.at("WCK2DQO")),
|
||||
tRTW (tCK * memSpec.memtimingspec.entries.at("RTW")),
|
||||
tWL (tCK * memSpec.memtimingspec.entries.at("WL")),
|
||||
tWCK2DQI (tCK * memSpec.memtimingspec.entries.at("WCK2DQI")),
|
||||
tWR (tCK * memSpec.memtimingspec.entries.at("WR")),
|
||||
tWTRS (tCK * memSpec.memtimingspec.entries.at("WTRS")),
|
||||
tWTRL (tCK * memSpec.memtimingspec.entries.at("WTRL")),
|
||||
tCKE (tCK * memSpec.memtimingspec.entries.at("CKE")),
|
||||
tPD (tCK * memSpec.memtimingspec.entries.at("PD")),
|
||||
tXP (tCK * memSpec.memtimingspec.entries.at("XP")),
|
||||
tREFI (tCK * memSpec.memtimingspec.entries.at("REFI")),
|
||||
tREFIPB (tCK * memSpec.memtimingspec.entries.at("REFIPB")),
|
||||
tRFC (tCK * memSpec.memtimingspec.entries.at("RFC")),
|
||||
tRFCPB (tCK * memSpec.memtimingspec.entries.at("RFCPB")),
|
||||
tRREFD (tCK * memSpec.memtimingspec.entries.at("RREFD")),
|
||||
tXS (tCK * memSpec.memtimingspec.entries.at("XS")),
|
||||
tFAW (tCK * memSpec.memtimingspec.entries.at("FAW")),
|
||||
t32AW (tCK * memSpec.memtimingspec.entries.at("32AW")),
|
||||
tPPD (tCK * memSpec.memtimingspec.entries.at("PPD")),
|
||||
tLK (tCK * memSpec.memtimingspec.entries.at("LK")),
|
||||
tRTRS (tCK * memSpec.memtimingspec.entries.at("TRS"))
|
||||
{
|
||||
uint64_t deviceSizeBits = static_cast<uint64_t>(banksPerRank) * rowsPerBank * columnsPerRow * bitWidth;
|
||||
uint64_t deviceSizeBytes = deviceSizeBits / 8;
|
||||
|
||||
@@ -45,55 +45,55 @@ using namespace tlm;
|
||||
|
||||
MemSpecGDDR6::MemSpecGDDR6(const DRAMSys::Config::MemSpec &memSpec)
|
||||
: MemSpec(memSpec, MemoryType::GDDR6,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfChannels"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfChannels"),
|
||||
1,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks"),
|
||||
memSpec.memArchitectureSpec.entries.at( "nbrOfBankGroups"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks")
|
||||
/ memSpec.memArchitectureSpec.entries.at( "nbrOfBankGroups"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks")
|
||||
* memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at( "nbrOfBankGroups")
|
||||
* memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfDevices")),
|
||||
per2BankOffset(memSpec.memArchitectureSpec.entries.at("per2BankOffset")),
|
||||
tRP (tCK * memSpec.memTimingSpec.entries.at("RP")),
|
||||
tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")),
|
||||
tRC (tCK * memSpec.memTimingSpec.entries.at("RC")),
|
||||
tRCDRD (tCK * memSpec.memTimingSpec.entries.at("RCDRD")),
|
||||
tRCDWR (tCK * memSpec.memTimingSpec.entries.at("RCDWR")),
|
||||
tRTP (tCK * memSpec.memTimingSpec.entries.at("RTP")),
|
||||
tRRDS (tCK * memSpec.memTimingSpec.entries.at("RRDS")),
|
||||
tRRDL (tCK * memSpec.memTimingSpec.entries.at("RRDL")),
|
||||
tCCDS (tCK * memSpec.memTimingSpec.entries.at("CCDS")),
|
||||
tCCDL (tCK * memSpec.memTimingSpec.entries.at("CCDL")),
|
||||
tRL (tCK * memSpec.memTimingSpec.entries.at("RL")),
|
||||
tWCK2CKPIN (tCK * memSpec.memTimingSpec.entries.at("WCK2CKPIN")),
|
||||
tWCK2CK (tCK * memSpec.memTimingSpec.entries.at("WCK2CK")),
|
||||
tWCK2DQO (tCK * memSpec.memTimingSpec.entries.at("WCK2DQO")),
|
||||
tRTW (tCK * memSpec.memTimingSpec.entries.at("RTW")),
|
||||
tWL (tCK * memSpec.memTimingSpec.entries.at("WL")),
|
||||
tWCK2DQI (tCK * memSpec.memTimingSpec.entries.at("WCK2DQI")),
|
||||
tWR (tCK * memSpec.memTimingSpec.entries.at("WR")),
|
||||
tWTRS (tCK * memSpec.memTimingSpec.entries.at("WTRS")),
|
||||
tWTRL (tCK * memSpec.memTimingSpec.entries.at("WTRL")),
|
||||
tPD (tCK * memSpec.memTimingSpec.entries.at("PD")),
|
||||
tCKESR (tCK * memSpec.memTimingSpec.entries.at("CKESR")),
|
||||
tXP (tCK * memSpec.memTimingSpec.entries.at("XP")),
|
||||
tREFI (tCK * memSpec.memTimingSpec.entries.at("REFI")),
|
||||
tREFIpb (tCK * memSpec.memTimingSpec.entries.at("REFIpb")),
|
||||
tRFCab (tCK * memSpec.memTimingSpec.entries.at("RFCab")),
|
||||
tRFCpb (tCK * memSpec.memTimingSpec.entries.at("RFCpb")),
|
||||
tRREFD (tCK * memSpec.memTimingSpec.entries.at("RREFD")),
|
||||
tXS (tCK * memSpec.memTimingSpec.entries.at("XS")),
|
||||
tFAW (tCK * memSpec.memTimingSpec.entries.at("FAW")),
|
||||
tPPD (tCK * memSpec.memTimingSpec.entries.at("PPD")),
|
||||
tLK (tCK * memSpec.memTimingSpec.entries.at("LK")),
|
||||
tACTPDE (tCK * memSpec.memTimingSpec.entries.at("ACTPDE")),
|
||||
tPREPDE (tCK * memSpec.memTimingSpec.entries.at("PREPDE")),
|
||||
tREFPDE (tCK * memSpec.memTimingSpec.entries.at("REFPDE")),
|
||||
tRTRS (tCK * memSpec.memTimingSpec.entries.at("RTRS"))
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks"),
|
||||
memSpec.memarchitecturespec.entries.at( "nbrOfBankGroups"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks")
|
||||
/ memSpec.memarchitecturespec.entries.at( "nbrOfBankGroups"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks")
|
||||
* memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at( "nbrOfBankGroups")
|
||||
* memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfDevices")),
|
||||
per2BankOffset(memSpec.memarchitecturespec.entries.at("per2BankOffset")),
|
||||
tRP (tCK * memSpec.memtimingspec.entries.at("RP")),
|
||||
tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")),
|
||||
tRC (tCK * memSpec.memtimingspec.entries.at("RC")),
|
||||
tRCDRD (tCK * memSpec.memtimingspec.entries.at("RCDRD")),
|
||||
tRCDWR (tCK * memSpec.memtimingspec.entries.at("RCDWR")),
|
||||
tRTP (tCK * memSpec.memtimingspec.entries.at("RTP")),
|
||||
tRRDS (tCK * memSpec.memtimingspec.entries.at("RRDS")),
|
||||
tRRDL (tCK * memSpec.memtimingspec.entries.at("RRDL")),
|
||||
tCCDS (tCK * memSpec.memtimingspec.entries.at("CCDS")),
|
||||
tCCDL (tCK * memSpec.memtimingspec.entries.at("CCDL")),
|
||||
tRL (tCK * memSpec.memtimingspec.entries.at("RL")),
|
||||
tWCK2CKPIN (tCK * memSpec.memtimingspec.entries.at("WCK2CKPIN")),
|
||||
tWCK2CK (tCK * memSpec.memtimingspec.entries.at("WCK2CK")),
|
||||
tWCK2DQO (tCK * memSpec.memtimingspec.entries.at("WCK2DQO")),
|
||||
tRTW (tCK * memSpec.memtimingspec.entries.at("RTW")),
|
||||
tWL (tCK * memSpec.memtimingspec.entries.at("WL")),
|
||||
tWCK2DQI (tCK * memSpec.memtimingspec.entries.at("WCK2DQI")),
|
||||
tWR (tCK * memSpec.memtimingspec.entries.at("WR")),
|
||||
tWTRS (tCK * memSpec.memtimingspec.entries.at("WTRS")),
|
||||
tWTRL (tCK * memSpec.memtimingspec.entries.at("WTRL")),
|
||||
tPD (tCK * memSpec.memtimingspec.entries.at("PD")),
|
||||
tCKESR (tCK * memSpec.memtimingspec.entries.at("CKESR")),
|
||||
tXP (tCK * memSpec.memtimingspec.entries.at("XP")),
|
||||
tREFI (tCK * memSpec.memtimingspec.entries.at("REFI")),
|
||||
tREFIpb (tCK * memSpec.memtimingspec.entries.at("REFIpb")),
|
||||
tRFCab (tCK * memSpec.memtimingspec.entries.at("RFCab")),
|
||||
tRFCpb (tCK * memSpec.memtimingspec.entries.at("RFCpb")),
|
||||
tRREFD (tCK * memSpec.memtimingspec.entries.at("RREFD")),
|
||||
tXS (tCK * memSpec.memtimingspec.entries.at("XS")),
|
||||
tFAW (tCK * memSpec.memtimingspec.entries.at("FAW")),
|
||||
tPPD (tCK * memSpec.memtimingspec.entries.at("PPD")),
|
||||
tLK (tCK * memSpec.memtimingspec.entries.at("LK")),
|
||||
tACTPDE (tCK * memSpec.memtimingspec.entries.at("ACTPDE")),
|
||||
tPREPDE (tCK * memSpec.memtimingspec.entries.at("PREPDE")),
|
||||
tREFPDE (tCK * memSpec.memtimingspec.entries.at("REFPDE")),
|
||||
tRTRS (tCK * memSpec.memtimingspec.entries.at("RTRS"))
|
||||
{
|
||||
uint64_t deviceSizeBits = static_cast<uint64_t>(banksPerRank) * rowsPerBank * columnsPerRow * bitWidth;
|
||||
uint64_t deviceSizeBytes = deviceSizeBits / 8;
|
||||
|
||||
@@ -45,47 +45,47 @@ using namespace tlm;
|
||||
|
||||
MemSpecHBM2::MemSpecHBM2(const DRAMSys::Config::MemSpec &memSpec)
|
||||
: MemSpec(memSpec, MemoryType::HBM2,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfChannels"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfPseudoChannels"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfPseudoChannels"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks")
|
||||
/ memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks")
|
||||
* memSpec.memArchitectureSpec.entries.at("nbrOfPseudoChannels"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups")
|
||||
* memSpec.memArchitectureSpec.entries.at("nbrOfPseudoChannels"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfDevices")),
|
||||
tDQSCK (tCK * memSpec.memTimingSpec.entries.at("DQSCK")),
|
||||
tRC (tCK * memSpec.memTimingSpec.entries.at("RC")),
|
||||
tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")),
|
||||
tRCDRD (tCK * memSpec.memTimingSpec.entries.at("RCDRD")),
|
||||
tRCDWR (tCK * memSpec.memTimingSpec.entries.at("RCDWR")),
|
||||
tRRDL (tCK * memSpec.memTimingSpec.entries.at("RRDL")),
|
||||
tRRDS (tCK * memSpec.memTimingSpec.entries.at("RRDS")),
|
||||
tFAW (tCK * memSpec.memTimingSpec.entries.at("FAW")),
|
||||
tRTP (tCK * memSpec.memTimingSpec.entries.at("RTP")),
|
||||
tRP (tCK * memSpec.memTimingSpec.entries.at("RP")),
|
||||
tRL (tCK * memSpec.memTimingSpec.entries.at("RL")),
|
||||
tWL (tCK * memSpec.memTimingSpec.entries.at("WL")),
|
||||
tPL (tCK * memSpec.memTimingSpec.entries.at("PL")),
|
||||
tWR (tCK * memSpec.memTimingSpec.entries.at("WR")),
|
||||
tCCDL (tCK * memSpec.memTimingSpec.entries.at("CCDL")),
|
||||
tCCDS (tCK * memSpec.memTimingSpec.entries.at("CCDS")),
|
||||
tWTRL (tCK * memSpec.memTimingSpec.entries.at("WTRL")),
|
||||
tWTRS (tCK * memSpec.memTimingSpec.entries.at("WTRS")),
|
||||
tRTW (tCK * memSpec.memTimingSpec.entries.at("RTW")),
|
||||
tXP (tCK * memSpec.memTimingSpec.entries.at("XP")),
|
||||
tCKE (tCK * memSpec.memTimingSpec.entries.at("CKE")),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfChannels"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfPseudoChannels"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfPseudoChannels"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks")
|
||||
/ memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks")
|
||||
* memSpec.memarchitecturespec.entries.at("nbrOfPseudoChannels"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBankGroups")
|
||||
* memSpec.memarchitecturespec.entries.at("nbrOfPseudoChannels"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfDevices")),
|
||||
tDQSCK (tCK * memSpec.memtimingspec.entries.at("DQSCK")),
|
||||
tRC (tCK * memSpec.memtimingspec.entries.at("RC")),
|
||||
tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")),
|
||||
tRCDRD (tCK * memSpec.memtimingspec.entries.at("RCDRD")),
|
||||
tRCDWR (tCK * memSpec.memtimingspec.entries.at("RCDWR")),
|
||||
tRRDL (tCK * memSpec.memtimingspec.entries.at("RRDL")),
|
||||
tRRDS (tCK * memSpec.memtimingspec.entries.at("RRDS")),
|
||||
tFAW (tCK * memSpec.memtimingspec.entries.at("FAW")),
|
||||
tRTP (tCK * memSpec.memtimingspec.entries.at("RTP")),
|
||||
tRP (tCK * memSpec.memtimingspec.entries.at("RP")),
|
||||
tRL (tCK * memSpec.memtimingspec.entries.at("RL")),
|
||||
tWL (tCK * memSpec.memtimingspec.entries.at("WL")),
|
||||
tPL (tCK * memSpec.memtimingspec.entries.at("PL")),
|
||||
tWR (tCK * memSpec.memtimingspec.entries.at("WR")),
|
||||
tCCDL (tCK * memSpec.memtimingspec.entries.at("CCDL")),
|
||||
tCCDS (tCK * memSpec.memtimingspec.entries.at("CCDS")),
|
||||
tWTRL (tCK * memSpec.memtimingspec.entries.at("WTRL")),
|
||||
tWTRS (tCK * memSpec.memtimingspec.entries.at("WTRS")),
|
||||
tRTW (tCK * memSpec.memtimingspec.entries.at("RTW")),
|
||||
tXP (tCK * memSpec.memtimingspec.entries.at("XP")),
|
||||
tCKE (tCK * memSpec.memtimingspec.entries.at("CKE")),
|
||||
tPD (tCKE),
|
||||
tCKESR (tCKE + tCK),
|
||||
tXS (tCK * memSpec.memTimingSpec.entries.at("XS")),
|
||||
tRFC (tCK * memSpec.memTimingSpec.entries.at("RFC")),
|
||||
tRFCSB (tCK * memSpec.memTimingSpec.entries.at("RFCSB")),
|
||||
tRREFD (tCK * memSpec.memTimingSpec.entries.at("RREFD")),
|
||||
tREFI (tCK * memSpec.memTimingSpec.entries.at("REFI")),
|
||||
tREFISB (tCK * memSpec.memTimingSpec.entries.at("REFISB"))
|
||||
tXS (tCK * memSpec.memtimingspec.entries.at("XS")),
|
||||
tRFC (tCK * memSpec.memtimingspec.entries.at("RFC")),
|
||||
tRFCSB (tCK * memSpec.memtimingspec.entries.at("RFCSB")),
|
||||
tRREFD (tCK * memSpec.memtimingspec.entries.at("RREFD")),
|
||||
tREFI (tCK * memSpec.memtimingspec.entries.at("REFI")),
|
||||
tREFISB (tCK * memSpec.memtimingspec.entries.at("REFISB"))
|
||||
{
|
||||
commandLengthInCycles[Command::ACT] = 2;
|
||||
|
||||
|
||||
@@ -45,47 +45,47 @@ using namespace tlm;
|
||||
|
||||
MemSpecLPDDR4::MemSpecLPDDR4(const DRAMSys::Config::MemSpec &memSpec)
|
||||
: MemSpec(memSpec, MemoryType::LPDDR4,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfChannels"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfChannels"),
|
||||
1,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks"),
|
||||
1,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks")
|
||||
* memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfDevices")),
|
||||
tREFI (tCK * memSpec.memTimingSpec.entries.at("REFI")),
|
||||
tREFIpb (tCK * memSpec.memTimingSpec.entries.at("REFIPB")),
|
||||
tRFCab (tCK * memSpec.memTimingSpec.entries.at("RFCAB")),
|
||||
tRFCpb (tCK * memSpec.memTimingSpec.entries.at("RFCPB")),
|
||||
tRPab (tCK * memSpec.memTimingSpec.entries.at("RPAB")),
|
||||
tRPpb (tCK * memSpec.memTimingSpec.entries.at("RPPB")),
|
||||
tRCab (tCK * memSpec.memTimingSpec.entries.at("RCAB")),
|
||||
tRCpb (tCK * memSpec.memTimingSpec.entries.at("RCPB")),
|
||||
tPPD (tCK * memSpec.memTimingSpec.entries.at("PPD")),
|
||||
tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")),
|
||||
tRCD (tCK * memSpec.memTimingSpec.entries.at("RCD")),
|
||||
tFAW (tCK * memSpec.memTimingSpec.entries.at("FAW")),
|
||||
tRRD (tCK * memSpec.memTimingSpec.entries.at("RRD")),
|
||||
tCCD (tCK * memSpec.memTimingSpec.entries.at("CCD")),
|
||||
tRL (tCK * memSpec.memTimingSpec.entries.at("RL")),
|
||||
tRPST (tCK * memSpec.memTimingSpec.entries.at("RPST")),
|
||||
tDQSCK (tCK * memSpec.memTimingSpec.entries.at("DQSCK")),
|
||||
tRTP (tCK * memSpec.memTimingSpec.entries.at("RTP")),
|
||||
tWL (tCK * memSpec.memTimingSpec.entries.at("WL")),
|
||||
tDQSS (tCK * memSpec.memTimingSpec.entries.at("DQSS")),
|
||||
tDQS2DQ (tCK * memSpec.memTimingSpec.entries.at("DQS2DQ")),
|
||||
tWR (tCK * memSpec.memTimingSpec.entries.at("WR")),
|
||||
tWPRE (tCK * memSpec.memTimingSpec.entries.at("WPRE")),
|
||||
tWTR (tCK * memSpec.memTimingSpec.entries.at("WTR")),
|
||||
tXP (tCK * memSpec.memTimingSpec.entries.at("XP")),
|
||||
tSR (tCK * memSpec.memTimingSpec.entries.at("SR")),
|
||||
tXSR (tCK * memSpec.memTimingSpec.entries.at("XSR")),
|
||||
tESCKE (tCK * memSpec.memTimingSpec.entries.at("ESCKE")),
|
||||
tCKE (tCK * memSpec.memTimingSpec.entries.at("CKE")),
|
||||
tCMDCKE (tCK * memSpec.memTimingSpec.entries.at("CMDCKE")),
|
||||
tRTRS (tCK * memSpec.memTimingSpec.entries.at("RTRS"))
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks")
|
||||
* memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfDevices")),
|
||||
tREFI (tCK * memSpec.memtimingspec.entries.at("REFI")),
|
||||
tREFIpb (tCK * memSpec.memtimingspec.entries.at("REFIPB")),
|
||||
tRFCab (tCK * memSpec.memtimingspec.entries.at("RFCAB")),
|
||||
tRFCpb (tCK * memSpec.memtimingspec.entries.at("RFCPB")),
|
||||
tRPab (tCK * memSpec.memtimingspec.entries.at("RPAB")),
|
||||
tRPpb (tCK * memSpec.memtimingspec.entries.at("RPPB")),
|
||||
tRCab (tCK * memSpec.memtimingspec.entries.at("RCAB")),
|
||||
tRCpb (tCK * memSpec.memtimingspec.entries.at("RCPB")),
|
||||
tPPD (tCK * memSpec.memtimingspec.entries.at("PPD")),
|
||||
tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")),
|
||||
tRCD (tCK * memSpec.memtimingspec.entries.at("RCD")),
|
||||
tFAW (tCK * memSpec.memtimingspec.entries.at("FAW")),
|
||||
tRRD (tCK * memSpec.memtimingspec.entries.at("RRD")),
|
||||
tCCD (tCK * memSpec.memtimingspec.entries.at("CCD")),
|
||||
tRL (tCK * memSpec.memtimingspec.entries.at("RL")),
|
||||
tRPST (tCK * memSpec.memtimingspec.entries.at("RPST")),
|
||||
tDQSCK (tCK * memSpec.memtimingspec.entries.at("DQSCK")),
|
||||
tRTP (tCK * memSpec.memtimingspec.entries.at("RTP")),
|
||||
tWL (tCK * memSpec.memtimingspec.entries.at("WL")),
|
||||
tDQSS (tCK * memSpec.memtimingspec.entries.at("DQSS")),
|
||||
tDQS2DQ (tCK * memSpec.memtimingspec.entries.at("DQS2DQ")),
|
||||
tWR (tCK * memSpec.memtimingspec.entries.at("WR")),
|
||||
tWPRE (tCK * memSpec.memtimingspec.entries.at("WPRE")),
|
||||
tWTR (tCK * memSpec.memtimingspec.entries.at("WTR")),
|
||||
tXP (tCK * memSpec.memtimingspec.entries.at("XP")),
|
||||
tSR (tCK * memSpec.memtimingspec.entries.at("SR")),
|
||||
tXSR (tCK * memSpec.memtimingspec.entries.at("XSR")),
|
||||
tESCKE (tCK * memSpec.memtimingspec.entries.at("ESCKE")),
|
||||
tCKE (tCK * memSpec.memtimingspec.entries.at("CKE")),
|
||||
tCMDCKE (tCK * memSpec.memtimingspec.entries.at("CMDCKE")),
|
||||
tRTRS (tCK * memSpec.memtimingspec.entries.at("RTRS"))
|
||||
{
|
||||
commandLengthInCycles[Command::ACT] = 4;
|
||||
commandLengthInCycles[Command::PREPB] = 2;
|
||||
|
||||
@@ -45,40 +45,40 @@ using namespace tlm;
|
||||
|
||||
MemSpecSTTMRAM::MemSpecSTTMRAM(const DRAMSys::Config::MemSpec &memSpec)
|
||||
: MemSpec(memSpec, MemoryType::STTMRAM,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfChannels"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfChannels"),
|
||||
1,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks"),
|
||||
1,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks")
|
||||
* memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfDevices")),
|
||||
tCKE (tCK * memSpec.memTimingSpec.entries.at("CKE")),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks")
|
||||
* memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfDevices")),
|
||||
tCKE (tCK * memSpec.memtimingspec.entries.at("CKE")),
|
||||
tPD (tCKE),
|
||||
tCKESR (tCK * memSpec.memTimingSpec.entries.at("CKESR")),
|
||||
tDQSCK (tCK * memSpec.memTimingSpec.entries.at("DQSCK")),
|
||||
tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")),
|
||||
tRC (tCK * memSpec.memTimingSpec.entries.at("RC")),
|
||||
tRCD (tCK * memSpec.memTimingSpec.entries.at("RCD")),
|
||||
tRL (tCK * memSpec.memTimingSpec.entries.at("RL")),
|
||||
tRTP (tCK * memSpec.memTimingSpec.entries.at("RTP")),
|
||||
tWL (tCK * memSpec.memTimingSpec.entries.at("WL")),
|
||||
tWR (tCK * memSpec.memTimingSpec.entries.at("WR")),
|
||||
tXP (tCK * memSpec.memTimingSpec.entries.at("XP")),
|
||||
tXS (tCK * memSpec.memTimingSpec.entries.at("XS")),
|
||||
tCCD (tCK * memSpec.memTimingSpec.entries.at("CCD")),
|
||||
tFAW (tCK * memSpec.memTimingSpec.entries.at("FAW")),
|
||||
tRP (tCK * memSpec.memTimingSpec.entries.at("RP")),
|
||||
tRRD (tCK * memSpec.memTimingSpec.entries.at("RRD")),
|
||||
tWTR (tCK * memSpec.memTimingSpec.entries.at("WTR")),
|
||||
tAL (tCK * memSpec.memTimingSpec.entries.at("AL")),
|
||||
tXPDLL (tCK * memSpec.memTimingSpec.entries.at("XPDLL")),
|
||||
tXSDLL (tCK * memSpec.memTimingSpec.entries.at("XSDLL")),
|
||||
tACTPDEN (tCK * memSpec.memTimingSpec.entries.at("ACTPDEN")),
|
||||
tPRPDEN (tCK * memSpec.memTimingSpec.entries.at("PRPDEN")),
|
||||
tRTRS (tCK * memSpec.memTimingSpec.entries.at("RTRS"))
|
||||
tCKESR (tCK * memSpec.memtimingspec.entries.at("CKESR")),
|
||||
tDQSCK (tCK * memSpec.memtimingspec.entries.at("DQSCK")),
|
||||
tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")),
|
||||
tRC (tCK * memSpec.memtimingspec.entries.at("RC")),
|
||||
tRCD (tCK * memSpec.memtimingspec.entries.at("RCD")),
|
||||
tRL (tCK * memSpec.memtimingspec.entries.at("RL")),
|
||||
tRTP (tCK * memSpec.memtimingspec.entries.at("RTP")),
|
||||
tWL (tCK * memSpec.memtimingspec.entries.at("WL")),
|
||||
tWR (tCK * memSpec.memtimingspec.entries.at("WR")),
|
||||
tXP (tCK * memSpec.memtimingspec.entries.at("XP")),
|
||||
tXS (tCK * memSpec.memtimingspec.entries.at("XS")),
|
||||
tCCD (tCK * memSpec.memtimingspec.entries.at("CCD")),
|
||||
tFAW (tCK * memSpec.memtimingspec.entries.at("FAW")),
|
||||
tRP (tCK * memSpec.memtimingspec.entries.at("RP")),
|
||||
tRRD (tCK * memSpec.memtimingspec.entries.at("RRD")),
|
||||
tWTR (tCK * memSpec.memtimingspec.entries.at("WTR")),
|
||||
tAL (tCK * memSpec.memtimingspec.entries.at("AL")),
|
||||
tXPDLL (tCK * memSpec.memtimingspec.entries.at("XPDLL")),
|
||||
tXSDLL (tCK * memSpec.memtimingspec.entries.at("XSDLL")),
|
||||
tACTPDEN (tCK * memSpec.memtimingspec.entries.at("ACTPDEN")),
|
||||
tPRPDEN (tCK * memSpec.memtimingspec.entries.at("PRPDEN")),
|
||||
tRTRS (tCK * memSpec.memtimingspec.entries.at("RTRS"))
|
||||
{
|
||||
uint64_t deviceSizeBits = static_cast<uint64_t>(banksPerRank) * rowsPerBank * columnsPerRow * bitWidth;
|
||||
uint64_t deviceSizeBytes = deviceSizeBits / 8;
|
||||
|
||||
@@ -45,67 +45,67 @@ using namespace tlm;
|
||||
|
||||
MemSpecWideIO::MemSpecWideIO(const DRAMSys::Config::MemSpec &memSpec)
|
||||
: MemSpec(memSpec, MemoryType::WideIO,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfChannels"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfChannels"),
|
||||
1,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks"),
|
||||
1,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks")
|
||||
* memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfDevices")),
|
||||
tCKE (tCK * memSpec.memTimingSpec.entries.at("CKE")),
|
||||
tCKESR (tCK * memSpec.memTimingSpec.entries.at("CKESR")),
|
||||
tDQSCK (tCK * memSpec.memTimingSpec.entries.at("DQSCK")),
|
||||
tAC (tCK * memSpec.memTimingSpec.entries.at("AC")),
|
||||
tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")),
|
||||
tRC (tCK * memSpec.memTimingSpec.entries.at("RC")),
|
||||
tRCD (tCK * memSpec.memTimingSpec.entries.at("RCD")),
|
||||
tRL (tCK * memSpec.memTimingSpec.entries.at("RL")),
|
||||
tWL (tCK * memSpec.memTimingSpec.entries.at("WL")),
|
||||
tWR (tCK * memSpec.memTimingSpec.entries.at("WR")),
|
||||
tXP (tCK * memSpec.memTimingSpec.entries.at("XP")),
|
||||
tXSR (tCK * memSpec.memTimingSpec.entries.at("XSR")),
|
||||
tCCD_R (tCK * memSpec.memTimingSpec.entries.at("CCD_R")),
|
||||
tCCD_W (tCK * memSpec.memTimingSpec.entries.at("CCD_W")),
|
||||
tREFI (tCK * memSpec.memTimingSpec.entries.at("REFI")),
|
||||
tRFC (tCK * memSpec.memTimingSpec.entries.at("RFC")),
|
||||
tRP (tCK * memSpec.memTimingSpec.entries.at("RP")),
|
||||
tRRD (tCK * memSpec.memTimingSpec.entries.at("RRD")),
|
||||
tTAW (tCK * memSpec.memTimingSpec.entries.at("TAW")),
|
||||
tWTR (tCK * memSpec.memTimingSpec.entries.at("WTR")),
|
||||
tRTRS (tCK * memSpec.memTimingSpec.entries.at("RTRS")),
|
||||
iDD0 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd0") : 0),
|
||||
iDD2N (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd2n") : 0),
|
||||
iDD3N (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd3n") : 0),
|
||||
iDD4R (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd4r") : 0),
|
||||
iDD4W (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd4w") : 0),
|
||||
iDD5 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd5") : 0),
|
||||
iDD6 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd6") : 0),
|
||||
vDD (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("vdd") : 0),
|
||||
iDD02 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd02") : 0),
|
||||
iDD2P0 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd2p0") : 0),
|
||||
iDD2P02 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd2p02") : 0),
|
||||
iDD2P1 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd2p1") : 0),
|
||||
iDD2P12 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd2p12") : 0),
|
||||
iDD2N2 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd2n2") : 0),
|
||||
iDD3P0 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd3p0") : 0),
|
||||
iDD3P02 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd3p02") : 0),
|
||||
iDD3P1 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd3p1") : 0),
|
||||
iDD3P12 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd3p12") : 0),
|
||||
iDD3N2 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd3n2") : 0),
|
||||
iDD4R2 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd4r2") : 0),
|
||||
iDD4W2 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd4w2") : 0),
|
||||
iDD52 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd52") : 0),
|
||||
iDD62 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd62") : 0),
|
||||
vDD2 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("vdd2") : 0)
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks")
|
||||
* memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfDevices")),
|
||||
tCKE (tCK * memSpec.memtimingspec.entries.at("CKE")),
|
||||
tCKESR (tCK * memSpec.memtimingspec.entries.at("CKESR")),
|
||||
tDQSCK (tCK * memSpec.memtimingspec.entries.at("DQSCK")),
|
||||
tAC (tCK * memSpec.memtimingspec.entries.at("AC")),
|
||||
tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")),
|
||||
tRC (tCK * memSpec.memtimingspec.entries.at("RC")),
|
||||
tRCD (tCK * memSpec.memtimingspec.entries.at("RCD")),
|
||||
tRL (tCK * memSpec.memtimingspec.entries.at("RL")),
|
||||
tWL (tCK * memSpec.memtimingspec.entries.at("WL")),
|
||||
tWR (tCK * memSpec.memtimingspec.entries.at("WR")),
|
||||
tXP (tCK * memSpec.memtimingspec.entries.at("XP")),
|
||||
tXSR (tCK * memSpec.memtimingspec.entries.at("XSR")),
|
||||
tCCD_R (tCK * memSpec.memtimingspec.entries.at("CCD_R")),
|
||||
tCCD_W (tCK * memSpec.memtimingspec.entries.at("CCD_W")),
|
||||
tREFI (tCK * memSpec.memtimingspec.entries.at("REFI")),
|
||||
tRFC (tCK * memSpec.memtimingspec.entries.at("RFC")),
|
||||
tRP (tCK * memSpec.memtimingspec.entries.at("RP")),
|
||||
tRRD (tCK * memSpec.memtimingspec.entries.at("RRD")),
|
||||
tTAW (tCK * memSpec.memtimingspec.entries.at("TAW")),
|
||||
tWTR (tCK * memSpec.memtimingspec.entries.at("WTR")),
|
||||
tRTRS (tCK * memSpec.memtimingspec.entries.at("RTRS")),
|
||||
iDD0 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd0") : 0),
|
||||
iDD2N (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd2n") : 0),
|
||||
iDD3N (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd3n") : 0),
|
||||
iDD4R (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd4r") : 0),
|
||||
iDD4W (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd4w") : 0),
|
||||
iDD5 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd5") : 0),
|
||||
iDD6 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd6") : 0),
|
||||
vDD (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("vdd") : 0),
|
||||
iDD02 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd02") : 0),
|
||||
iDD2P0 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd2p0") : 0),
|
||||
iDD2P02 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd2p02") : 0),
|
||||
iDD2P1 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd2p1") : 0),
|
||||
iDD2P12 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd2p12") : 0),
|
||||
iDD2N2 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd2n2") : 0),
|
||||
iDD3P0 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd3p0") : 0),
|
||||
iDD3P02 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd3p02") : 0),
|
||||
iDD3P1 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd3p1") : 0),
|
||||
iDD3P12 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd3p12") : 0),
|
||||
iDD3N2 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd3n2") : 0),
|
||||
iDD4R2 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd4r2") : 0),
|
||||
iDD4W2 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd4w2") : 0),
|
||||
iDD52 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd52") : 0),
|
||||
iDD62 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd62") : 0),
|
||||
vDD2 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("vdd2") : 0)
|
||||
{
|
||||
uint64_t deviceSizeBits = static_cast<uint64_t>(banksPerRank) * rowsPerBank * columnsPerRow * bitWidth;
|
||||
uint64_t deviceSizeBytes = deviceSizeBits / 8;
|
||||
memorySizeBytes = deviceSizeBytes * ranksPerChannel * numberOfChannels;
|
||||
|
||||
if (!memSpec.memPowerSpec.has_value())
|
||||
if (!memSpec.mempowerspec.has_value())
|
||||
SC_REPORT_FATAL("MemSpec", "No power spec defined!");
|
||||
|
||||
std::cout << headline << std::endl;
|
||||
|
||||
@@ -45,43 +45,43 @@ using namespace tlm;
|
||||
|
||||
MemSpecWideIO2::MemSpecWideIO2(const DRAMSys::Config::MemSpec &memSpec)
|
||||
: MemSpec(memSpec, MemoryType::WideIO2,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfChannels"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfChannels"),
|
||||
1,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks"),
|
||||
1,
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfBanks")
|
||||
* memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfRanks"),
|
||||
memSpec.memArchitectureSpec.entries.at("nbrOfDevices")),
|
||||
tDQSCK (tCK * memSpec.memTimingSpec.entries.at("DQSCK")),
|
||||
tDQSS (tCK * memSpec.memTimingSpec.entries.at("DQSS")),
|
||||
tCKE (tCK * memSpec.memTimingSpec.entries.at("CKE")),
|
||||
tRL (tCK * memSpec.memTimingSpec.entries.at("RL")),
|
||||
tWL (tCK * memSpec.memTimingSpec.entries.at("WL")),
|
||||
tRCpb (tCK * memSpec.memTimingSpec.entries.at("RCPB")),
|
||||
tRCab (tCK * memSpec.memTimingSpec.entries.at("RCAB")),
|
||||
tCKESR (tCK * memSpec.memTimingSpec.entries.at("CKESR")),
|
||||
tXSR (tCK * memSpec.memTimingSpec.entries.at("XSR")),
|
||||
tXP (tCK * memSpec.memTimingSpec.entries.at("XP")),
|
||||
tCCD (tCK * memSpec.memTimingSpec.entries.at("CCD")),
|
||||
tRTP (tCK * memSpec.memTimingSpec.entries.at("RTP")),
|
||||
tRCD (tCK * memSpec.memTimingSpec.entries.at("RCD")),
|
||||
tRPpb (tCK * memSpec.memTimingSpec.entries.at("RPPB")),
|
||||
tRPab (tCK * memSpec.memTimingSpec.entries.at("RPAB")),
|
||||
tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")),
|
||||
tWR (tCK * memSpec.memTimingSpec.entries.at("WR")),
|
||||
tWTR (tCK * memSpec.memTimingSpec.entries.at("WTR")),
|
||||
tRRD (tCK * memSpec.memTimingSpec.entries.at("RRD")),
|
||||
tFAW (tCK * memSpec.memTimingSpec.entries.at("FAW")),
|
||||
tREFI (tCK * static_cast<unsigned>(memSpec.memTimingSpec.entries.at("REFI")
|
||||
* memSpec.memTimingSpec.entries.at("REFM"))),
|
||||
tREFIpb (tCK * static_cast<unsigned>(memSpec.memTimingSpec.entries.at("REFIPB")
|
||||
* memSpec.memTimingSpec.entries.at("REFM"))),
|
||||
tRFCab (tCK * memSpec.memTimingSpec.entries.at("RFCAB")),
|
||||
tRFCpb (tCK * memSpec.memTimingSpec.entries.at("RFCPB")),
|
||||
tRTRS (tCK * memSpec.memTimingSpec.entries.at("RTRS"))
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfBanks")
|
||||
* memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfRanks"),
|
||||
memSpec.memarchitecturespec.entries.at("nbrOfDevices")),
|
||||
tDQSCK (tCK * memSpec.memtimingspec.entries.at("DQSCK")),
|
||||
tDQSS (tCK * memSpec.memtimingspec.entries.at("DQSS")),
|
||||
tCKE (tCK * memSpec.memtimingspec.entries.at("CKE")),
|
||||
tRL (tCK * memSpec.memtimingspec.entries.at("RL")),
|
||||
tWL (tCK * memSpec.memtimingspec.entries.at("WL")),
|
||||
tRCpb (tCK * memSpec.memtimingspec.entries.at("RCPB")),
|
||||
tRCab (tCK * memSpec.memtimingspec.entries.at("RCAB")),
|
||||
tCKESR (tCK * memSpec.memtimingspec.entries.at("CKESR")),
|
||||
tXSR (tCK * memSpec.memtimingspec.entries.at("XSR")),
|
||||
tXP (tCK * memSpec.memtimingspec.entries.at("XP")),
|
||||
tCCD (tCK * memSpec.memtimingspec.entries.at("CCD")),
|
||||
tRTP (tCK * memSpec.memtimingspec.entries.at("RTP")),
|
||||
tRCD (tCK * memSpec.memtimingspec.entries.at("RCD")),
|
||||
tRPpb (tCK * memSpec.memtimingspec.entries.at("RPPB")),
|
||||
tRPab (tCK * memSpec.memtimingspec.entries.at("RPAB")),
|
||||
tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")),
|
||||
tWR (tCK * memSpec.memtimingspec.entries.at("WR")),
|
||||
tWTR (tCK * memSpec.memtimingspec.entries.at("WTR")),
|
||||
tRRD (tCK * memSpec.memtimingspec.entries.at("RRD")),
|
||||
tFAW (tCK * memSpec.memtimingspec.entries.at("FAW")),
|
||||
tREFI (tCK * static_cast<unsigned>(memSpec.memtimingspec.entries.at("REFI")
|
||||
* memSpec.memtimingspec.entries.at("REFM"))),
|
||||
tREFIpb (tCK * static_cast<unsigned>(memSpec.memtimingspec.entries.at("REFIPB")
|
||||
* memSpec.memtimingspec.entries.at("REFM"))),
|
||||
tRFCab (tCK * memSpec.memtimingspec.entries.at("RFCAB")),
|
||||
tRFCpb (tCK * memSpec.memtimingspec.entries.at("RFCPB")),
|
||||
tRTRS (tCK * memSpec.memtimingspec.entries.at("RTRS"))
|
||||
{
|
||||
uint64_t deviceSizeBits = static_cast<uint64_t>(banksPerRank) * rowsPerBank * columnsPerRow * bitWidth;
|
||||
uint64_t deviceSizeBytes = deviceSizeBits / 8;
|
||||
|
||||
@@ -515,7 +515,10 @@ void Controller::manageResponses()
|
||||
tlm_generic_payload* nextTransInRespQueue = respQueue->nextPayload();
|
||||
if (nextTransInRespQueue != nullptr)
|
||||
{
|
||||
numberOfBeatsServed += ControllerExtension::getBurstLength(*nextTransInRespQueue);
|
||||
// Ignore ECC requests
|
||||
if (nextTransInRespQueue->get_extension<EccExtension>() == nullptr)
|
||||
numberOfBeatsServed += ControllerExtension::getBurstLength(*nextTransInRespQueue);
|
||||
|
||||
if (ChildExtension::isChildTrans(*nextTransInRespQueue))
|
||||
{
|
||||
tlm_generic_payload& parentTrans = ChildExtension::getParentTrans(*nextTransInRespQueue);
|
||||
|
||||
@@ -37,53 +37,54 @@
|
||||
*/
|
||||
|
||||
#include "AddressDecoder.h"
|
||||
#include "DRAMSys/configuration/Configuration.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <bitset>
|
||||
|
||||
AddressDecoder::AddressDecoder(const Configuration& config, const DRAMSys::Config::AddressMapping& addressMapping)
|
||||
AddressDecoder::AddressDecoder(const DRAMSys::Config::AddressMapping &addressMapping, const MemSpec &memSpec)
|
||||
{
|
||||
if (const auto& channelBits = addressMapping.channelBits)
|
||||
if (const auto &channelBits = addressMapping.CHANNEL_BIT)
|
||||
{
|
||||
std::copy(channelBits->begin(), channelBits->end(), std::back_inserter(vChannelBits));
|
||||
}
|
||||
|
||||
if (const auto& rankBits = addressMapping.rankBits)
|
||||
if (const auto &rankBits = addressMapping.RANK_BIT)
|
||||
{
|
||||
std::copy(rankBits->begin(), rankBits->end(), std::back_inserter(vRankBits));
|
||||
}
|
||||
|
||||
if (const auto& bankGroupBits = addressMapping.bankGroupBits)
|
||||
if (const auto& bankGroupBits = addressMapping.BANKGROUP_BIT)
|
||||
{
|
||||
std::copy(bankGroupBits->begin(), bankGroupBits->end(), std::back_inserter(vBankGroupBits));
|
||||
}
|
||||
|
||||
if (const auto& byteBits = addressMapping.byteBits)
|
||||
if (const auto &byteBits = addressMapping.BYTE_BIT)
|
||||
{
|
||||
std::copy(byteBits->begin(), byteBits->end(), std::back_inserter(vByteBits));
|
||||
}
|
||||
|
||||
if (const auto& xorBits = addressMapping.xorBits)
|
||||
if (const auto &xorBits = addressMapping.XOR)
|
||||
{
|
||||
for (const auto& xorBit : *xorBits)
|
||||
{
|
||||
vXor.emplace_back(xorBit.first, xorBit.second);
|
||||
vXor.emplace_back(xorBit.FIRST, xorBit.SECOND);
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto& bankBits = addressMapping.bankBits)
|
||||
if (const auto &bankBits = addressMapping.BANK_BIT)
|
||||
{
|
||||
std::copy(bankBits->begin(), bankBits->end(), std::back_inserter(vBankBits));
|
||||
}
|
||||
|
||||
if (const auto& rowBits = addressMapping.rowBits)
|
||||
if (const auto &rowBits = addressMapping.ROW_BIT)
|
||||
{
|
||||
std::copy(rowBits->begin(), rowBits->end(), std::back_inserter(vRowBits));
|
||||
}
|
||||
|
||||
if (const auto& columnBits = addressMapping.columnBits)
|
||||
if (const auto &columnBits = addressMapping.COLUMN_BIT)
|
||||
{
|
||||
std::copy(columnBits->begin(), columnBits->end(), std::back_inserter(vColumnBits));
|
||||
}
|
||||
@@ -113,8 +114,6 @@ AddressDecoder::AddressDecoder(const Configuration& config, const DRAMSys::Confi
|
||||
SC_REPORT_FATAL("AddressDecoder", "Not all address bits occur exactly once");
|
||||
}
|
||||
|
||||
const MemSpec& memSpec = *config.memSpec;
|
||||
|
||||
unsigned highestByteBit = *std::max_element(vByteBits.begin(), vByteBits.end());
|
||||
|
||||
for (unsigned bitPosition = 0; bitPosition <= highestByteBit; bitPosition++)
|
||||
@@ -213,6 +212,41 @@ unsigned AddressDecoder::decodeChannel(uint64_t encAddr) const
|
||||
return channel;
|
||||
}
|
||||
|
||||
uint64_t AddressDecoder::encodeAddress(DecodedAddress decodedAddress) const
|
||||
{
|
||||
// Convert absoulte addressing for bank, bankgroup to relative
|
||||
decodedAddress.bankgroup = decodedAddress.bankgroup % bankgroupsPerRank;
|
||||
decodedAddress.bank = decodedAddress.bank % banksPerGroup;
|
||||
|
||||
uint64_t address = 0;
|
||||
|
||||
for (unsigned i = 0; i < vChannelBits.size(); i++)
|
||||
address |= ((decodedAddress.channel >> i) & 0x1) << vChannelBits[i];
|
||||
|
||||
for (unsigned i = 0; i < vRankBits.size(); i++)
|
||||
address |= ((decodedAddress.rank >> i) & 0x1) << vRankBits[i];
|
||||
|
||||
for (unsigned i = 0; i < vBankGroupBits.size(); i++)
|
||||
address |= ((decodedAddress.bankgroup >> i) & 0x1) << vBankGroupBits[i];
|
||||
|
||||
for (unsigned i = 0; i < vBankBits.size(); i++)
|
||||
address |= ((decodedAddress.bank >> i) & 0x1) << vBankBits[i];
|
||||
|
||||
for (unsigned i = 0; i < vRowBits.size(); i++)
|
||||
address |= ((decodedAddress.row >> i) & 0x1) << vRowBits[i];
|
||||
|
||||
for (unsigned i = 0; i < vColumnBits.size(); i++)
|
||||
address |= ((decodedAddress.column >> i) & 0x1) << vColumnBits[i];
|
||||
|
||||
for (unsigned i = 0; i < vByteBits.size(); i++)
|
||||
address |= ((decodedAddress.byte >> i) & 0x1) << vByteBits[i];
|
||||
|
||||
// TODO: XOR encoding
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
|
||||
void AddressDecoder::print() const
|
||||
{
|
||||
std::cout << headline << std::endl;
|
||||
|
||||
@@ -39,9 +39,8 @@
|
||||
#ifndef ADDRESSDECODER_H
|
||||
#define ADDRESSDECODER_H
|
||||
|
||||
#include "DRAMSys/configuration/Configuration.h"
|
||||
|
||||
#include "DRAMSys/config/DRAMSysConfiguration.h"
|
||||
#include "DRAMSys/configuration/Configuration.h"
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
@@ -69,9 +68,10 @@ struct DecodedAddress
|
||||
class AddressDecoder
|
||||
{
|
||||
public:
|
||||
AddressDecoder(const Configuration& config, const DRAMSys::Config::AddressMapping& addressMapping);
|
||||
AddressDecoder(const DRAMSys::Config::AddressMapping &addressMapping, const MemSpec &memSpec);
|
||||
[[nodiscard]] DecodedAddress decodeAddress(uint64_t encAddr) const;
|
||||
[[nodiscard]] unsigned decodeChannel(uint64_t encAddr) const;
|
||||
[[nodiscard]] uint64_t encodeAddress(DecodedAddress decodedAddress) const;
|
||||
void print() const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -86,9 +86,9 @@ DRAMSys::DRAMSys(const sc_core::sc_module_name& name,
|
||||
|
||||
// Load configLib and initialize modules
|
||||
// Important: The memSpec needs to be the first configuration to be loaded!
|
||||
config.loadMemSpec(configLib.memSpec);
|
||||
config.loadMCConfig(configLib.mcConfig);
|
||||
config.loadSimConfig(configLib.simConfig);
|
||||
config.loadMemSpec(configLib.memspec);
|
||||
config.loadMCConfig(configLib.mcconfig);
|
||||
config.loadSimConfig(configLib.simconfig);
|
||||
|
||||
// Setup the debug manager:
|
||||
setupDebugManager(config.simulationName);
|
||||
@@ -96,7 +96,7 @@ DRAMSys::DRAMSys(const sc_core::sc_module_name& name,
|
||||
if (initAndBind)
|
||||
{
|
||||
// Instantiate all internal DRAMSys modules:
|
||||
instantiateModules(configLib.addressMapping);
|
||||
instantiateModules(configLib.addressmapping);
|
||||
// Connect all internal DRAMSys modules:
|
||||
bindSockets();
|
||||
report(headline);
|
||||
@@ -157,7 +157,7 @@ void DRAMSys::setupDebugManager(NDEBUG_UNUSED(const std::string& traceName)) con
|
||||
|
||||
void DRAMSys::instantiateModules(const ::DRAMSys::Config::AddressMapping& addressMapping)
|
||||
{
|
||||
addressDecoder = std::make_unique<AddressDecoder>(config, addressMapping);
|
||||
addressDecoder = std::make_unique<AddressDecoder>(addressMapping, *config.memSpec);
|
||||
addressDecoder->print();
|
||||
|
||||
// Create arbiter
|
||||
|
||||
@@ -70,6 +70,7 @@ public:
|
||||
const ::DRAMSys::Config::Configuration& configLib);
|
||||
|
||||
const Configuration& getConfig() const;
|
||||
const AddressDecoder &getAddressDecoder() const { return *addressDecoder; }
|
||||
|
||||
protected:
|
||||
DRAMSys(const sc_core::sc_module_name& name,
|
||||
|
||||
@@ -71,9 +71,9 @@ DRAMSysRecordable::DRAMSysRecordable(const sc_core::sc_module_name& name, const
|
||||
// is prepended to the simulation name if found.
|
||||
std::string traceName;
|
||||
|
||||
if (!configLib.simulationId.empty())
|
||||
if (!configLib.simulationid.empty())
|
||||
{
|
||||
std::string sid = configLib.simulationId;
|
||||
std::string sid = configLib.simulationid;
|
||||
traceName = sid + '_' + config.simulationName;
|
||||
}
|
||||
else
|
||||
@@ -110,9 +110,14 @@ void DRAMSysRecordable::setupTlmRecorders(const std::string& traceName,
|
||||
std::string dbName = std::string(name()) + "_" + traceName + "_ch" + std::to_string(i) + ".tdb";
|
||||
std::string recorderName = "tlmRecorder" + std::to_string(i);
|
||||
|
||||
nlohmann::json mcconfig;
|
||||
nlohmann::json memspec;
|
||||
mcconfig[Config::McConfig::KEY] = configLib.mcconfig;
|
||||
memspec[Config::MemSpec::KEY] = configLib.memspec;
|
||||
|
||||
tlmRecorders.emplace_back(recorderName, config, dbName);
|
||||
tlmRecorders.back().recordMcConfig(::DRAMSys::Config::dump(configLib.mcConfig));
|
||||
tlmRecorders.back().recordMemspec(::DRAMSys::Config::dump(configLib.memSpec));
|
||||
tlmRecorders.back().recordMcConfig(mcconfig.dump());
|
||||
tlmRecorders.back().recordMemspec(memspec.dump());
|
||||
tlmRecorders.back().recordTraceNames(config.simulationName);
|
||||
}
|
||||
}
|
||||
@@ -120,7 +125,7 @@ void DRAMSysRecordable::setupTlmRecorders(const std::string& traceName,
|
||||
void DRAMSysRecordable::instantiateModules(const std::string& traceName,
|
||||
const ::DRAMSys::Config::Configuration& configLib)
|
||||
{
|
||||
addressDecoder = std::make_unique<AddressDecoder>(config, configLib.addressMapping);
|
||||
addressDecoder = std::make_unique<AddressDecoder>(configLib.addressmapping, *config.memSpec);
|
||||
addressDecoder->print();
|
||||
|
||||
// Create and properly initialize TLM recorders.
|
||||
|
||||
@@ -43,15 +43,25 @@ project(DRAMSys_Simulator)
|
||||
file(GLOB_RECURSE SOURCE_FILES CONFIGURE_DEPENDS *.cpp)
|
||||
file(GLOB_RECURSE HEADER_FILES CONFIGURE_DEPENDS *.h;*.hpp)
|
||||
|
||||
add_executable(DRAMSys ${SOURCE_FILES} ${HEADER_FILES})
|
||||
target_include_directories(DRAMSys PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
list(FILTER SOURCE_FILES EXCLUDE REGEX "main.cpp")
|
||||
|
||||
add_library(${PROJECT_NAME} STATIC ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
Threads::Threads
|
||||
DRAMSys::libdramsys
|
||||
)
|
||||
|
||||
add_executable(DRAMSys
|
||||
main.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(DRAMSys
|
||||
PRIVATE
|
||||
Threads::Threads
|
||||
SystemC::systemc
|
||||
DRAMSys::libdramsys
|
||||
DRAMSys_Simulator
|
||||
)
|
||||
|
||||
build_source_group()
|
||||
diagnostics_print(DRAMSys)
|
||||
19
src/simulator/README.md
Normal file
19
src/simulator/README.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Simulator
|
||||
The **standalone** simulator features a set of trace players, traffic generators and miscellaneous components that can be coupled with DRAMSys.
|
||||
|
||||
## Concept
|
||||
Initiators in the simulator are split up into two disctinct components: **RequestProducers** and **RequestIssuers**.
|
||||
|
||||
**RequestProducers** are simple C++ classes that implement the `RequestProducer` interface. Upon calling the `nextRequest()` method of a producer, a new `Request` is either generated on-the-fly or constructed from a trace file.
|
||||
|
||||
**RequestIssuers** are the SystemC modules that connect with DRAMSys. Issuers have no knowledge of where the requests are coming from. They simply call their `nextRequest()` callback that it has been passed in the constructor to obtain the next request to be sent to DRAMSys. Using this concept, the generation and the issuing of request is completely decoupled to make very flexible initiator designs possible.
|
||||
|
||||
**Initiators** implement the `Initiator` interface, which describes how the initiator is bound to DRAMSys. This abstracts over the actual socket type used by the initiator.
|
||||
Complex initiators may implement the interface directly, but for simple cases, there exists the templated `SimpleInitiator<Producer>` class. This specialized initiator consists of only one producer and one issuer that operate together. The `StlPlayer` and `RowHammer` issuers make use of the `SimpleInitiator`.
|
||||
The `TrafficGenerator` is one example of a direct implementation of the `Initiator` interface, as it consists of many producers (which represent the states of the state machine) but of only one issuer.
|
||||
|
||||
**Requests** are an abstraction over the TLM payloads the issuer generates. A request describes whether it is a read or a write access or an internal `Stop` request that tells the initiator to terminate.
|
||||
The **delay** field specifies the time that should pass between the issuance of the previous and the current request.
|
||||
|
||||
## Configuration
|
||||
A detailed description on how to configure the traffic generators of the simulator can be found [here](../../configs/README.md).
|
||||
197
src/simulator/main.cpp
Normal file
197
src/simulator/main.cpp
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Technische Universität Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. 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.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder 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 HOLDER
|
||||
* 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:
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#include "simulator/Initiator.h"
|
||||
#include "simulator/MemoryManager.h"
|
||||
#include "simulator/SimpleInitiator.h"
|
||||
#include "simulator/generator/TrafficGenerator.h"
|
||||
#include "simulator/hammer/RowHammer.h"
|
||||
#include "simulator/player/StlPlayer.h"
|
||||
#include "simulator/util.h"
|
||||
|
||||
#include <DRAMSys/simulation/DRAMSysRecordable.h>
|
||||
|
||||
#include <systemc>
|
||||
#include <tlm>
|
||||
#include <tlm_utils/peq_with_cb_and_phase.h>
|
||||
#include <tlm_utils/simple_initiator_socket.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <random>
|
||||
|
||||
static constexpr std::string_view TRACE_DIRECTORY = "traces";
|
||||
|
||||
int sc_main(int argc, char **argv)
|
||||
{
|
||||
std::filesystem::path resourceDirectory = DRAMSYS_RESOURCE_DIR;
|
||||
if (argc >= 3)
|
||||
{
|
||||
resourceDirectory = argv[2];
|
||||
}
|
||||
|
||||
std::filesystem::path baseConfig = resourceDirectory / "ddr5-example.json";
|
||||
if (argc >= 2)
|
||||
{
|
||||
baseConfig = argv[1];
|
||||
}
|
||||
|
||||
DRAMSys::Config::Configuration configuration =
|
||||
DRAMSys::Config::from_path(baseConfig.c_str(), resourceDirectory.c_str());
|
||||
|
||||
if (!configuration.tracesetup.has_value())
|
||||
SC_REPORT_FATAL("Simulator", "No traffic initiators specified");
|
||||
|
||||
std::unique_ptr<DRAMSys::DRAMSys> dramSys;
|
||||
if (configuration.simconfig.DatabaseRecording)
|
||||
{
|
||||
dramSys = std::make_unique<DRAMSys::DRAMSysRecordable>("DRAMSys", configuration);
|
||||
}
|
||||
else
|
||||
{
|
||||
dramSys = std::make_unique<DRAMSys::DRAMSys>("DRAMSys", configuration);
|
||||
}
|
||||
|
||||
bool storageEnabled = dramSys->getConfig().storeMode == Configuration::StoreMode::Store;
|
||||
MemoryManager memoryManager(storageEnabled);
|
||||
|
||||
std::vector<std::unique_ptr<Initiator>> initiators;
|
||||
|
||||
unsigned int terminatedInitiators = 0;
|
||||
auto termianteInitiator = [&initiators, &terminatedInitiators]()
|
||||
{
|
||||
terminatedInitiators++;
|
||||
|
||||
if (terminatedInitiators == initiators.size())
|
||||
sc_core::sc_stop();
|
||||
};
|
||||
|
||||
uint64_t totalTransactions{};
|
||||
uint64_t transactionsFinished = 0;
|
||||
auto transactionFinished = [&totalTransactions, &transactionsFinished]()
|
||||
{
|
||||
transactionsFinished++;
|
||||
loadBar(transactionsFinished, totalTransactions);
|
||||
};
|
||||
|
||||
for (auto const &initiator_config : configuration.tracesetup.value())
|
||||
{
|
||||
uint64_t memorySize = dramSys->getConfig().memSpec->getSimMemSizeInBytes();
|
||||
unsigned int defaultDataLength = dramSys->getConfig().memSpec->defaultBytesPerBurst;
|
||||
|
||||
auto initiator = std::visit(
|
||||
[=, &memoryManager](auto &&config) -> std::unique_ptr<Initiator>
|
||||
{
|
||||
using T = std::decay_t<decltype(config)>;
|
||||
if constexpr (std::is_same_v<T, DRAMSys::Config::TrafficGenerator> ||
|
||||
std::is_same_v<T, DRAMSys::Config::TrafficGeneratorStateMachine>)
|
||||
{
|
||||
return std::make_unique<TrafficGenerator>(config,
|
||||
memoryManager,
|
||||
memorySize,
|
||||
defaultDataLength,
|
||||
transactionFinished,
|
||||
termianteInitiator);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, DRAMSys::Config::TracePlayer>)
|
||||
{
|
||||
std::filesystem::path tracePath =
|
||||
resourceDirectory / TRACE_DIRECTORY / config.name;
|
||||
|
||||
StlPlayer::TraceType traceType;
|
||||
|
||||
auto extension = tracePath.extension();
|
||||
if (extension == ".stl")
|
||||
traceType = StlPlayer::TraceType::Absolute;
|
||||
else if (extension == ".rtl")
|
||||
traceType = StlPlayer::TraceType::Relative;
|
||||
else
|
||||
{
|
||||
std::string report = extension.string() + " is not a valid trace format.";
|
||||
SC_REPORT_FATAL("Simulator", report.c_str());
|
||||
}
|
||||
|
||||
StlPlayer player(
|
||||
tracePath.c_str(), config.clkMhz, defaultDataLength, traceType, false);
|
||||
|
||||
return std::make_unique<SimpleInitiator<StlPlayer>>(config.name.c_str(),
|
||||
memoryManager,
|
||||
std::nullopt,
|
||||
std::nullopt,
|
||||
transactionFinished,
|
||||
termianteInitiator,
|
||||
std::move(player));
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, DRAMSys::Config::RowHammer>)
|
||||
{
|
||||
RowHammer hammer(
|
||||
config.numRequests, config.clkMhz, config.rowIncrement, defaultDataLength);
|
||||
|
||||
return std::make_unique<SimpleInitiator<RowHammer>>(config.name.c_str(),
|
||||
memoryManager,
|
||||
1,
|
||||
1,
|
||||
transactionFinished,
|
||||
termianteInitiator,
|
||||
std::move(hammer));
|
||||
}
|
||||
},
|
||||
initiator_config);
|
||||
|
||||
totalTransactions += initiator->totalRequests();
|
||||
|
||||
initiator->bind(dramSys->tSocket);
|
||||
initiators.push_back(std::move(initiator));
|
||||
}
|
||||
|
||||
// Store the starting of the simulation in wall-clock time:
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
// Start the SystemC simulation
|
||||
sc_set_stop_mode(sc_core::SC_STOP_FINISH_DELTA);
|
||||
sc_core::sc_start();
|
||||
|
||||
if (!sc_core::sc_end_of_simulation_invoked())
|
||||
{
|
||||
SC_REPORT_WARNING("sc_main", "Simulation stopped without explicit sc_stop()");
|
||||
sc_core::sc_stop();
|
||||
}
|
||||
|
||||
auto finish = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> elapsed = finish - start;
|
||||
std::cout << "Simulation took " + std::to_string(elapsed.count()) + " seconds." << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
639
src/simulator/simulator/Cache.cpp
Normal file
639
src/simulator/simulator/Cache.cpp
Normal file
@@ -0,0 +1,639 @@
|
||||
#include "Cache.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <sysc/kernel/sc_simcontext.h>
|
||||
#include <sysc/kernel/sc_time.h>
|
||||
#include <sysc/utils/sc_report.h>
|
||||
#include <tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h>
|
||||
#include <tlm_core/tlm_2/tlm_generic_payload/tlm_phase.h>
|
||||
|
||||
using namespace tlm;
|
||||
using namespace sc_core;
|
||||
|
||||
DECLARE_EXTENDED_PHASE(HIT_HANDLING);
|
||||
DECLARE_EXTENDED_PHASE(MISS_HANDLING);
|
||||
|
||||
Cache::Cache(const sc_module_name &name,
|
||||
std::size_t size,
|
||||
std::size_t associativity,
|
||||
std::size_t lineSize,
|
||||
std::size_t mshrDepth,
|
||||
std::size_t writeBufferDepth,
|
||||
std::size_t maxTargetListSize,
|
||||
bool storageEnabled,
|
||||
sc_core::sc_time cycleTime,
|
||||
std::size_t hitCycles,
|
||||
MemoryManager &memoryManager) :
|
||||
sc_module(name),
|
||||
payloadEventQueue(this, &Cache::peqCallback),
|
||||
storageEnabled(storageEnabled),
|
||||
cycleTime(cycleTime),
|
||||
hitLatency(cycleTime * static_cast<double>(hitCycles)),
|
||||
size(size),
|
||||
associativity(associativity),
|
||||
lineSize(lineSize),
|
||||
numberOfSets(size / (lineSize * associativity)),
|
||||
indexShifts(static_cast<std::size_t>(std::log2(lineSize))),
|
||||
indexMask(numberOfSets - 1),
|
||||
tagShifts(indexShifts + static_cast<std::size_t>(std::log2(numberOfSets))),
|
||||
mshrDepth(mshrDepth),
|
||||
writeBufferDepth(writeBufferDepth),
|
||||
maxTargetListSize(maxTargetListSize),
|
||||
memoryManager(memoryManager)
|
||||
{
|
||||
iSocket.register_nb_transport_bw(this, &Cache::nb_transport_bw);
|
||||
tSocket.register_nb_transport_fw(this, &Cache::nb_transport_fw);
|
||||
|
||||
lineTable = std::vector<std::vector<CacheLine>>(numberOfSets, std::vector<CacheLine>(associativity));
|
||||
|
||||
if (storageEnabled)
|
||||
{
|
||||
dataMemory.reserve(size);
|
||||
|
||||
for (std::size_t set = 0; set < lineTable.size(); set++)
|
||||
{
|
||||
for (std::size_t way = 0; way < lineTable[set].size(); way++)
|
||||
lineTable[set][way].dataPtr = dataMemory.data() + set * associativity * lineSize + way * lineSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tlm_sync_enum Cache::nb_transport_fw(tlm_generic_payload &trans, tlm_phase &phase, sc_time &delay) // core side --->
|
||||
{
|
||||
if (phase == BEGIN_REQ)
|
||||
{
|
||||
if (trans.get_data_length() > lineSize)
|
||||
{
|
||||
SC_REPORT_FATAL(name(), "Accesses larger than line size in non-blocking mode not supported!");
|
||||
}
|
||||
|
||||
trans.acquire();
|
||||
}
|
||||
|
||||
// TODO: early completion would be possible
|
||||
payloadEventQueue.notify(trans, phase, ceilDelay(delay));
|
||||
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
tlm_sync_enum Cache::nb_transport_bw(tlm_generic_payload &trans, tlm_phase &phase, sc_time &bwDelay) // DRAM side <---
|
||||
{
|
||||
// TODO: early completion would be possible
|
||||
payloadEventQueue.notify(trans, phase, ceilDelay(bwDelay));
|
||||
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
void Cache::peqCallback(tlm_generic_payload &trans, const tlm_phase &phase)
|
||||
{
|
||||
if (phase == BEGIN_REQ) // core side --->
|
||||
{
|
||||
assert(!endRequestPending);
|
||||
fetchLineAndSendEndRequest(trans);
|
||||
return;
|
||||
}
|
||||
else if (phase == END_REQ) // <--- DRAM side
|
||||
{
|
||||
lastEndReq = sc_time_stamp();
|
||||
clearInitiatorBackpressureAndProcessBuffers();
|
||||
return;
|
||||
}
|
||||
else if (phase == BEGIN_RESP && &trans == requestInProgress) // <--- DRAM side
|
||||
{
|
||||
// Shortcut, 2 phases in one
|
||||
clearInitiatorBackpressureAndProcessBuffers();
|
||||
sendEndResponseAndFillLine(trans);
|
||||
return;
|
||||
}
|
||||
else if (phase == BEGIN_RESP) // <--- DRAM side
|
||||
{
|
||||
sendEndResponseAndFillLine(trans);
|
||||
return;
|
||||
}
|
||||
else if (phase == END_RESP) // core side --->
|
||||
{
|
||||
clearTargetBackpressureAndProcessLines(trans);
|
||||
return;
|
||||
}
|
||||
else if (phase == HIT_HANDLING) // direct hit, account for the hit delay
|
||||
{
|
||||
index_t index;
|
||||
tag_t tag;
|
||||
std::tie(index, tag, std::ignore) = decodeAddress(trans.get_address());
|
||||
|
||||
hitQueue.emplace_back(index, tag, &trans);
|
||||
processHitQueue();
|
||||
}
|
||||
else if (phase == MISS_HANDLING) // fetched MSHR entry available, account for the hit delay
|
||||
{
|
||||
accessCacheAndSendResponse(trans);
|
||||
|
||||
index_t index;
|
||||
tag_t tag;
|
||||
std::tie(index, tag, std::ignore) = decodeAddress(trans.get_address());
|
||||
|
||||
auto mshrIt = std::find_if(mshrQueue.begin(), mshrQueue.end(),
|
||||
[index, tag](const Mshr &mshr) { return mshr.index == index && mshr.tag == tag; });
|
||||
|
||||
assert(mshrIt != mshrQueue.end());
|
||||
mshrIt->hitDelayAccounted = true;
|
||||
|
||||
if (mshrIt->requestList.empty())
|
||||
{
|
||||
mshrQueue.erase(mshrIt);
|
||||
|
||||
if (endRequestPending != nullptr && hasBufferSpace())
|
||||
{
|
||||
payloadEventQueue.notify(*endRequestPending, BEGIN_REQ, SC_ZERO_TIME);
|
||||
endRequestPending = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL("Cache", "PEQ was triggered with unknown phase");
|
||||
}
|
||||
}
|
||||
|
||||
/// Handler for begin request from core side.
|
||||
void Cache::fetchLineAndSendEndRequest(tlm_generic_payload &trans)
|
||||
{
|
||||
if (hasBufferSpace())
|
||||
{
|
||||
index_t index;
|
||||
tag_t tag;
|
||||
std::tie(index, tag, std::ignore) = decodeAddress(trans.get_address());
|
||||
|
||||
auto mshrEntry =
|
||||
std::find_if(mshrQueue.begin(), mshrQueue.end(),
|
||||
[index, tag](const Mshr &entry) { return (index == entry.index) && (tag == entry.tag); });
|
||||
|
||||
if (isHit(index, tag))
|
||||
{
|
||||
numberOfHits++;
|
||||
|
||||
// Handle hit
|
||||
// Account for the 1 cycle accept delay.
|
||||
payloadEventQueue.notify(trans, HIT_HANDLING, hitLatency + cycleTime);
|
||||
}
|
||||
else if (mshrEntry != mshrQueue.end()) // Miss with outstanding previous Miss, noted in MSHR
|
||||
{
|
||||
numberOfSecondaryMisses++;
|
||||
assert(isAllocated(index, tag));
|
||||
|
||||
// A fetch for this cache line is already in progress
|
||||
// Add request to the existing Mshr entry
|
||||
|
||||
if (mshrEntry->requestList.size() == maxTargetListSize)
|
||||
{
|
||||
// Insertion into requestList in mshrEntry not possible.
|
||||
endRequestPending = &trans;
|
||||
return;
|
||||
}
|
||||
|
||||
mshrEntry->requestList.emplace_back(&trans);
|
||||
}
|
||||
else // Miss without MSHR entry:
|
||||
{
|
||||
numberOfPrimaryMisses++;
|
||||
assert(!isAllocated(index, tag));
|
||||
|
||||
// Cache miss and no fetch in progress.
|
||||
// So evict line and allocate empty line.
|
||||
auto evictedLine = evictLine(index);
|
||||
if (!evictedLine)
|
||||
{
|
||||
// Line eviction not possible.
|
||||
endRequestPending = &trans;
|
||||
return;
|
||||
}
|
||||
|
||||
allocateLine(evictedLine, tag);
|
||||
mshrQueue.emplace_back(index, tag, &trans);
|
||||
|
||||
processMshrQueue();
|
||||
processWriteBuffer();
|
||||
}
|
||||
|
||||
tlm_phase bwPhase = END_REQ;
|
||||
sc_time bwDelay = SC_ZERO_TIME;
|
||||
tSocket->nb_transport_bw(trans, bwPhase, bwDelay);
|
||||
}
|
||||
else
|
||||
{
|
||||
endRequestPending = &trans;
|
||||
}
|
||||
}
|
||||
|
||||
/// Handler for end request from DRAM side.
|
||||
void Cache::clearInitiatorBackpressureAndProcessBuffers()
|
||||
{
|
||||
requestInProgress = nullptr;
|
||||
|
||||
processMshrQueue();
|
||||
processWriteBuffer();
|
||||
}
|
||||
|
||||
/// Handler for begin response from DRAM side.
|
||||
void Cache::sendEndResponseAndFillLine(tlm_generic_payload &trans)
|
||||
{
|
||||
tlm_phase fwPhase = END_RESP;
|
||||
sc_time fwDelay = SC_ZERO_TIME;
|
||||
iSocket->nb_transport_fw(trans, fwPhase, fwDelay);
|
||||
|
||||
if (trans.is_read())
|
||||
{
|
||||
fillLine(trans);
|
||||
processMshrResponse();
|
||||
}
|
||||
|
||||
trans.release();
|
||||
}
|
||||
|
||||
/// Handler for end response from core side.
|
||||
void Cache::clearTargetBackpressureAndProcessLines(tlm_generic_payload &trans)
|
||||
{
|
||||
trans.release();
|
||||
tSocketBackpressure = false;
|
||||
|
||||
processHitQueue();
|
||||
processMshrResponse();
|
||||
|
||||
// When the cache currently only handles hits from the hit queue and
|
||||
// no other requests to the DRAM side are pending, there is a chance
|
||||
// that a endRequestPending will never be served.
|
||||
// To circumvent this, pass it into the system again at this point.
|
||||
if (endRequestPending != nullptr && hasBufferSpace())
|
||||
{
|
||||
payloadEventQueue.notify(*endRequestPending, BEGIN_REQ, SC_ZERO_TIME);
|
||||
endRequestPending = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int Cache::transport_dbg(tlm_generic_payload &trans)
|
||||
{
|
||||
return iSocket->transport_dbg(trans);
|
||||
}
|
||||
|
||||
bool Cache::isHit(index_t index, tag_t tag) const
|
||||
{
|
||||
return std::find_if(lineTable[index].begin(), lineTable[index].end(),
|
||||
[tag](const CacheLine &cacheLine)
|
||||
{ return (cacheLine.tag == tag) && cacheLine.valid; }) != lineTable[index].end();
|
||||
}
|
||||
|
||||
bool Cache::isHit(uint64_t address) const
|
||||
{
|
||||
index_t index;
|
||||
tag_t tag;
|
||||
std::tie(index, tag, std::ignore) = decodeAddress(address);
|
||||
|
||||
return isHit(index, tag);
|
||||
}
|
||||
|
||||
std::tuple<Cache::index_t, Cache::tag_t, Cache::lineOffset_t> Cache::decodeAddress(uint64_t address) const
|
||||
{
|
||||
return {(address >> indexShifts) & indexMask, address >> tagShifts, address % lineSize};
|
||||
}
|
||||
|
||||
uint64_t Cache::encodeAddress(Cache::index_t index, Cache::tag_t tag, Cache::lineOffset_t lineOffset) const
|
||||
{
|
||||
return static_cast<uint64_t>(tag << tagShifts) | index << indexShifts | lineOffset;
|
||||
}
|
||||
|
||||
/// Write data to an available cache line, update flags
|
||||
void Cache::writeLine(
|
||||
index_t index, tag_t tag, lineOffset_t lineOffset, unsigned int dataLength, const unsigned char *dataPtr)
|
||||
{
|
||||
// SC_REPORT_ERROR("cache", "Write to Cache not allowed!");
|
||||
|
||||
CacheLine ¤tLine = *std::find_if(lineTable[index].begin(), lineTable[index].end(),
|
||||
[tag](const CacheLine &cacheLine) { return cacheLine.tag == tag; });
|
||||
|
||||
assert(currentLine.valid);
|
||||
currentLine.lastAccessTime = sc_time_stamp();
|
||||
currentLine.dirty = true;
|
||||
|
||||
if (storageEnabled)
|
||||
std::copy(dataPtr, dataPtr + dataLength, currentLine.dataPtr + lineOffset);
|
||||
}
|
||||
|
||||
/// Read data from an available cache line, update flags
|
||||
void Cache::readLine(index_t index, tag_t tag, lineOffset_t lineOffset, unsigned int dataLength, unsigned char *dataPtr)
|
||||
{
|
||||
CacheLine ¤tLine = *std::find_if(lineTable[index].begin(), lineTable[index].end(),
|
||||
[tag](const CacheLine &cacheLine) { return cacheLine.tag == tag; });
|
||||
|
||||
assert(currentLine.valid);
|
||||
currentLine.lastAccessTime = sc_time_stamp();
|
||||
|
||||
if (storageEnabled)
|
||||
std::copy(currentLine.dataPtr + lineOffset, currentLine.dataPtr + lineOffset + dataLength, dataPtr);
|
||||
}
|
||||
|
||||
/// Tries to evict oldest line (insert into write memory)
|
||||
/// Returns the line or a nullptr if not possible
|
||||
Cache::CacheLine *Cache::evictLine(Cache::index_t index)
|
||||
{
|
||||
CacheLine &oldestLine = *std::min_element(lineTable[index].begin(), lineTable[index].end(),
|
||||
[](const CacheLine &lhs, const CacheLine &rhs)
|
||||
{ return lhs.lastAccessTime < rhs.lastAccessTime; });
|
||||
|
||||
if (oldestLine.allocated && !oldestLine.valid)
|
||||
{
|
||||
// oldestline is allocated but not yet valid -> fetch in progress
|
||||
return nullptr;
|
||||
}
|
||||
else if (std::find_if(mshrQueue.begin(), mshrQueue.end(),
|
||||
[index, oldestLine](const Mshr &entry)
|
||||
{ return (index == entry.index) && (oldestLine.tag == entry.tag); }) != mshrQueue.end())
|
||||
{
|
||||
// TODO: solve this in a more clever way
|
||||
// There are still entries in mshrQueue to the oldest line -> do not evict it
|
||||
return nullptr;
|
||||
}
|
||||
else if (std::find_if(hitQueue.begin(), hitQueue.end(),
|
||||
[index, oldestLine](const BufferEntry &entry)
|
||||
{ return (index == entry.index) && (oldestLine.tag == entry.tag); }) != hitQueue.end())
|
||||
{
|
||||
// TODO: solve this in a more clever way
|
||||
// There are still hits in hitQueue to the oldest line -> do not evict it
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (oldestLine.valid && oldestLine.dirty)
|
||||
{
|
||||
auto &wbTrans = memoryManager.allocate(lineSize);
|
||||
wbTrans.acquire();
|
||||
wbTrans.set_address(encodeAddress(index, oldestLine.tag));
|
||||
wbTrans.set_write();
|
||||
wbTrans.set_data_length(lineSize);
|
||||
wbTrans.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
|
||||
|
||||
if (storageEnabled)
|
||||
std::copy(oldestLine.dataPtr, oldestLine.dataPtr + lineSize, wbTrans.get_data_ptr());
|
||||
|
||||
writeBuffer.emplace_back(index, oldestLine.tag, &wbTrans);
|
||||
}
|
||||
|
||||
oldestLine.allocated = false;
|
||||
oldestLine.valid = false;
|
||||
oldestLine.dirty = false;
|
||||
|
||||
return &oldestLine;
|
||||
}
|
||||
}
|
||||
|
||||
/// Align address to cache line size
|
||||
uint64_t Cache::getAlignedAddress(uint64_t address) const
|
||||
{
|
||||
return address - (address % lineSize);
|
||||
}
|
||||
|
||||
/// Issue read requests for entries in the MshrQueue to the target
|
||||
void Cache::processMshrQueue()
|
||||
{
|
||||
if (!requestInProgress && !mshrQueue.empty())
|
||||
{
|
||||
// Get the first entry that wasn't already issued to the target
|
||||
auto mshrIt = std::find_if(mshrQueue.begin(), mshrQueue.end(), [](const Mshr &entry) { return !entry.issued; });
|
||||
|
||||
if (mshrIt == mshrQueue.end())
|
||||
return;
|
||||
|
||||
// Note: This is the same address for all entries in the requests list
|
||||
uint64_t alignedAddress = getAlignedAddress(mshrIt->requestList.front()->get_address());
|
||||
|
||||
index_t index;
|
||||
tag_t tag;
|
||||
std::tie(index, tag, std::ignore) = decodeAddress(alignedAddress);
|
||||
|
||||
// Search through the writeBuffer in reverse order to get the most recent entry.
|
||||
auto writeBufferEntry = std::find_if(writeBuffer.rbegin(), writeBuffer.rbegin(),
|
||||
[index, tag](const BufferEntry &entry)
|
||||
{ return (index == entry.index) && (tag == entry.tag); });
|
||||
|
||||
if (writeBufferEntry != writeBuffer.rbegin())
|
||||
{
|
||||
// There is an entry for the required line in the write buffer.
|
||||
// Snoop into it and get the data from there instead of the dram.
|
||||
mshrIt->issued = true;
|
||||
clearInitiatorBackpressureAndProcessBuffers();
|
||||
|
||||
fillLine(*writeBufferEntry->trans);
|
||||
processMshrResponse();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevents that the cache line will get fetched multiple times from the target
|
||||
mshrIt->issued = true;
|
||||
|
||||
auto &fetchTrans = memoryManager.allocate(lineSize);
|
||||
fetchTrans.acquire();
|
||||
fetchTrans.set_read();
|
||||
fetchTrans.set_data_length(lineSize);
|
||||
fetchTrans.set_streaming_width(lineSize);
|
||||
fetchTrans.set_address(alignedAddress);
|
||||
fetchTrans.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
|
||||
|
||||
tlm_phase fwPhase = BEGIN_REQ;
|
||||
|
||||
// Always account for the cycle as either we just received the BEGIN_REQ
|
||||
// or we cleared the backpressure from another END_REQ.
|
||||
sc_time fwDelay = cycleTime;
|
||||
|
||||
requestInProgress = &fetchTrans;
|
||||
tlm_sync_enum returnValue = iSocket->nb_transport_fw(fetchTrans, fwPhase, fwDelay);
|
||||
|
||||
if (returnValue == tlm::TLM_UPDATED)
|
||||
{
|
||||
// END_REQ or BEGIN_RESP
|
||||
payloadEventQueue.notify(fetchTrans, fwPhase, fwDelay);
|
||||
}
|
||||
else if (returnValue == tlm::TLM_COMPLETED)
|
||||
{
|
||||
clearInitiatorBackpressureAndProcessBuffers();
|
||||
|
||||
fillLine(fetchTrans);
|
||||
processMshrResponse();
|
||||
|
||||
fetchTrans.release();
|
||||
}
|
||||
|
||||
if (endRequestPending != nullptr && hasBufferSpace())
|
||||
{
|
||||
payloadEventQueue.notify(*endRequestPending, BEGIN_REQ, SC_ZERO_TIME);
|
||||
endRequestPending = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Processes writeBuffer (dirty cache line evictions)
|
||||
void Cache::processWriteBuffer()
|
||||
{
|
||||
if (!requestInProgress && !writeBuffer.empty())
|
||||
{
|
||||
tlm_generic_payload &wbTrans = *writeBuffer.front().trans;
|
||||
|
||||
tlm_phase fwPhase = BEGIN_REQ;
|
||||
sc_time fwDelay = (lastEndReq == sc_time_stamp()) ? cycleTime : SC_ZERO_TIME;
|
||||
|
||||
requestInProgress = &wbTrans;
|
||||
tlm_sync_enum returnValue = iSocket->nb_transport_fw(wbTrans, fwPhase, fwDelay);
|
||||
|
||||
if (returnValue == tlm::TLM_UPDATED)
|
||||
{
|
||||
// END_REQ or BEGIN_RESP
|
||||
payloadEventQueue.notify(wbTrans, fwPhase, fwDelay);
|
||||
}
|
||||
else if (returnValue == tlm::TLM_COMPLETED)
|
||||
{
|
||||
clearInitiatorBackpressureAndProcessBuffers();
|
||||
wbTrans.release();
|
||||
}
|
||||
|
||||
if (endRequestPending != nullptr && hasBufferSpace())
|
||||
{
|
||||
payloadEventQueue.notify(*endRequestPending, BEGIN_REQ, SC_ZERO_TIME);
|
||||
endRequestPending = nullptr;
|
||||
}
|
||||
|
||||
writeBuffer.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
/// Fill allocated cache line with data from memory
|
||||
void Cache::fillLine(tlm_generic_payload &trans)
|
||||
{
|
||||
index_t index;
|
||||
tag_t tag;
|
||||
std::tie(index, tag, std::ignore) = decodeAddress(trans.get_address());
|
||||
|
||||
CacheLine &allocatedLine =
|
||||
*std::find_if(lineTable[index].begin(), lineTable[index].end(),
|
||||
[tag](const CacheLine &cacheLine) { return cacheLine.allocated && cacheLine.tag == tag; });
|
||||
|
||||
allocatedLine.valid = true;
|
||||
allocatedLine.dirty = false;
|
||||
|
||||
if (storageEnabled)
|
||||
std::copy(trans.get_data_ptr(), trans.get_data_ptr() + lineSize, allocatedLine.dataPtr);
|
||||
}
|
||||
|
||||
/// Make cache access for pending hits
|
||||
void Cache::processHitQueue()
|
||||
{
|
||||
if (!tSocketBackpressure && !hitQueue.empty())
|
||||
{
|
||||
auto hit = hitQueue.front();
|
||||
hitQueue.pop_front();
|
||||
|
||||
accessCacheAndSendResponse(*hit.trans);
|
||||
}
|
||||
}
|
||||
|
||||
/// Access the available cache line and send the response
|
||||
void Cache::accessCacheAndSendResponse(tlm_generic_payload &trans)
|
||||
{
|
||||
assert(!tSocketBackpressure);
|
||||
assert(isHit(trans.get_address()));
|
||||
|
||||
auto [index, tag, lineOffset] = decodeAddress(trans.get_address());
|
||||
|
||||
if (trans.is_read())
|
||||
readLine(index, tag, lineOffset, trans.get_data_length(), trans.get_data_ptr());
|
||||
else
|
||||
writeLine(index, tag, lineOffset, trans.get_data_length(), trans.get_data_ptr());
|
||||
|
||||
tlm_phase bwPhase = BEGIN_RESP;
|
||||
sc_time bwDelay = SC_ZERO_TIME;
|
||||
|
||||
trans.set_response_status(tlm::TLM_OK_RESPONSE);
|
||||
|
||||
tlm_sync_enum returnValue = tSocket->nb_transport_bw(trans, bwPhase, bwDelay);
|
||||
if (returnValue == tlm::TLM_UPDATED) // TODO tlm_completed
|
||||
payloadEventQueue.notify(trans, bwPhase, bwDelay);
|
||||
|
||||
tSocketBackpressure = true;
|
||||
}
|
||||
|
||||
/// Allocates an empty line for later filling (lastAccessTime = sc_max_time())
|
||||
void Cache::allocateLine(CacheLine *line, tag_t tag)
|
||||
{
|
||||
line->allocated = true;
|
||||
line->tag = tag;
|
||||
line->lastAccessTime = sc_max_time();
|
||||
}
|
||||
|
||||
/// Checks whether a line with the corresponding tag is already allocated (fetch in progress or already valid)
|
||||
bool Cache::isAllocated(Cache::index_t index, Cache::tag_t tag) const
|
||||
{
|
||||
return std::find_if(lineTable[index].begin(), lineTable[index].end(),
|
||||
[tag](const CacheLine &cacheLine)
|
||||
{ return (cacheLine.tag == tag) && cacheLine.allocated; }) != lineTable[index].end();
|
||||
}
|
||||
|
||||
/// Process oldest hit in mshrQueue, accept pending request from initiator
|
||||
void Cache::processMshrResponse()
|
||||
{
|
||||
if (!tSocketBackpressure) // TODO: Bedingung eigentlich zu streng, wenn man Hit delay berücksichtigt.
|
||||
{
|
||||
const auto hitIt = std::find_if(mshrQueue.begin(), mshrQueue.end(),
|
||||
[this](const Mshr &entry) { return isHit(entry.index, entry.tag); });
|
||||
|
||||
// In case there are hits in mshrActive, handle them. Otherwise try again later.
|
||||
if (hitIt == mshrQueue.end())
|
||||
return;
|
||||
|
||||
// Another MSHR target already started the modeling of the hit delay.
|
||||
// Try again later.
|
||||
if (hitIt->hitDelayStarted && !hitIt->hitDelayAccounted)
|
||||
return;
|
||||
|
||||
// Get the first request in the list and respond to it
|
||||
tlm_generic_payload &returnTrans = *hitIt->requestList.front();
|
||||
hitIt->requestList.pop_front();
|
||||
|
||||
if (hitIt->hitDelayAccounted)
|
||||
accessCacheAndSendResponse(returnTrans);
|
||||
else
|
||||
{
|
||||
hitIt->hitDelayStarted = true;
|
||||
payloadEventQueue.notify(returnTrans, MISS_HANDLING, hitLatency);
|
||||
return;
|
||||
}
|
||||
|
||||
if (hitIt->requestList.empty())
|
||||
{
|
||||
mshrQueue.erase(hitIt);
|
||||
|
||||
if (endRequestPending != nullptr && hasBufferSpace())
|
||||
{
|
||||
payloadEventQueue.notify(*endRequestPending, BEGIN_REQ, SC_ZERO_TIME);
|
||||
endRequestPending = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks whether both mshrActive and writeBuffer have memory space
|
||||
bool Cache::hasBufferSpace() const
|
||||
{
|
||||
return mshrQueue.size() < mshrDepth && writeBuffer.size() < writeBufferDepth;
|
||||
}
|
||||
|
||||
sc_time Cache::ceilTime(const sc_time &inTime) const
|
||||
{
|
||||
return std::ceil(inTime / cycleTime) * cycleTime;
|
||||
}
|
||||
|
||||
sc_time Cache::ceilDelay(const sc_time &inDelay) const
|
||||
{
|
||||
sc_time inTime = sc_time_stamp() + inDelay;
|
||||
sc_time outTime = ceilTime(inTime);
|
||||
sc_time outDelay = outTime - sc_time_stamp();
|
||||
return outDelay;
|
||||
}
|
||||
216
src/simulator/simulator/Cache.h
Normal file
216
src/simulator/simulator/Cache.h
Normal file
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Technische Universität Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. 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.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder 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 HOLDER
|
||||
* 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:
|
||||
* Christian Malek
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "MemoryManager.h"
|
||||
|
||||
#include <list>
|
||||
#include <queue>
|
||||
#include <systemc>
|
||||
#include <tlm>
|
||||
#include <tlm_utils/peq_with_cb_and_phase.h>
|
||||
#include <tlm_utils/simple_initiator_socket.h>
|
||||
#include <tlm_utils/simple_target_socket.h>
|
||||
|
||||
class Cache : public sc_core::sc_module
|
||||
{
|
||||
public:
|
||||
tlm_utils::simple_initiator_socket<Cache> iSocket;
|
||||
tlm_utils::simple_target_socket<Cache> tSocket;
|
||||
|
||||
Cache(const sc_core::sc_module_name &name,
|
||||
std::size_t size,
|
||||
std::size_t associativity,
|
||||
std::size_t lineSize,
|
||||
std::size_t mshrDepth,
|
||||
std::size_t writeBufferDepth,
|
||||
std::size_t maxTargetListSize,
|
||||
bool storageEnabled,
|
||||
sc_core::sc_time cycleTime,
|
||||
std::size_t hitCycles,
|
||||
MemoryManager &memoryManager);
|
||||
SC_HAS_PROCESS(Cache);
|
||||
|
||||
private:
|
||||
void peqCallback(tlm::tlm_generic_payload &trans, const tlm::tlm_phase &phase);
|
||||
|
||||
tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload &trans,
|
||||
tlm::tlm_phase &phase,
|
||||
sc_core::sc_time &fwDelay);
|
||||
tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &trans,
|
||||
tlm::tlm_phase &phase,
|
||||
sc_core::sc_time &bwDelay);
|
||||
unsigned int transport_dbg(tlm::tlm_generic_payload &trans);
|
||||
|
||||
void fetchLineAndSendEndRequest(tlm::tlm_generic_payload &trans);
|
||||
void clearInitiatorBackpressureAndProcessBuffers();
|
||||
void sendEndResponseAndFillLine(tlm::tlm_generic_payload &trans);
|
||||
void clearTargetBackpressureAndProcessLines(tlm::tlm_generic_payload &trans);
|
||||
|
||||
tlm_utils::peq_with_cb_and_phase<Cache> payloadEventQueue;
|
||||
|
||||
const bool storageEnabled;
|
||||
sc_core::sc_time cycleTime;
|
||||
const sc_core::sc_time hitLatency;
|
||||
const std::size_t size;
|
||||
|
||||
// Lines per set.
|
||||
const std::size_t associativity;
|
||||
|
||||
const std::size_t lineSize;
|
||||
const std::size_t numberOfSets;
|
||||
const std::size_t indexShifts;
|
||||
const std::size_t indexMask;
|
||||
const std::size_t tagShifts;
|
||||
|
||||
const std::size_t mshrDepth;
|
||||
const std::size_t writeBufferDepth;
|
||||
const std::size_t maxTargetListSize;
|
||||
|
||||
using index_t = std::uint64_t;
|
||||
using tag_t = std::uint64_t;
|
||||
using lineOffset_t = std::uint64_t;
|
||||
|
||||
struct CacheLine
|
||||
{
|
||||
tag_t tag = 0;
|
||||
unsigned char *dataPtr = nullptr;
|
||||
bool allocated = false;
|
||||
bool valid = false;
|
||||
bool dirty = false;
|
||||
sc_core::sc_time lastAccessTime = sc_core::SC_ZERO_TIME;
|
||||
};
|
||||
|
||||
std::vector<std::vector<CacheLine>> lineTable;
|
||||
std::vector<uint8_t> dataMemory;
|
||||
|
||||
bool isHit(index_t index, tag_t tag) const;
|
||||
bool isHit(std::uint64_t address) const;
|
||||
|
||||
void writeLine(index_t index,
|
||||
tag_t tag,
|
||||
lineOffset_t lineOffset,
|
||||
unsigned int dataLength,
|
||||
const unsigned char *dataPtr);
|
||||
|
||||
void readLine(index_t index,
|
||||
tag_t tag,
|
||||
lineOffset_t lineOffset,
|
||||
unsigned int dataLength,
|
||||
unsigned char *dataPtr);
|
||||
|
||||
CacheLine *evictLine(index_t index);
|
||||
|
||||
std::tuple<index_t, tag_t, lineOffset_t> decodeAddress(std::uint64_t address) const;
|
||||
std::uint64_t encodeAddress(index_t index, tag_t tag, lineOffset_t lineOffset = 0) const;
|
||||
|
||||
struct BufferEntry
|
||||
{
|
||||
index_t index;
|
||||
tag_t tag;
|
||||
tlm::tlm_generic_payload *trans;
|
||||
|
||||
BufferEntry(index_t index, tag_t tag, tlm::tlm_generic_payload *trans)
|
||||
: index(index), tag(tag), trans(trans)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct Mshr
|
||||
{
|
||||
index_t index;
|
||||
tag_t tag;
|
||||
std::list<tlm::tlm_generic_payload *> requestList;
|
||||
|
||||
/// Whether the Mshr entry was already issued to the target.
|
||||
bool issued = false;
|
||||
|
||||
/// Whether the hit delay was already accounted for.
|
||||
/// Used to determine if the next entry in the request list
|
||||
/// should be sent out without the hit delay.
|
||||
bool hitDelayAccounted = false;
|
||||
|
||||
/// Whether the hit delay is being awaited on.
|
||||
/// Used prevent other MSHR targets to wait on the hit
|
||||
/// delay when it is already being waited on.
|
||||
bool hitDelayStarted = false;
|
||||
|
||||
Mshr(index_t index, tag_t tag, tlm::tlm_generic_payload *request)
|
||||
: index(index), tag(tag), requestList{request}
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
std::deque<Mshr> mshrQueue;
|
||||
std::deque<BufferEntry> hitQueue;
|
||||
|
||||
using WriteBuffer = std::list<BufferEntry>;
|
||||
WriteBuffer writeBuffer;
|
||||
|
||||
uint64_t numberOfHits = 0;
|
||||
uint64_t numberOfPrimaryMisses = 0;
|
||||
uint64_t numberOfSecondaryMisses = 0;
|
||||
|
||||
std::uint64_t getAlignedAddress(std::uint64_t address) const;
|
||||
|
||||
void processMshrResponse();
|
||||
void processWriteBuffer();
|
||||
void processHitQueue();
|
||||
void processMshrQueue();
|
||||
|
||||
bool tSocketBackpressure = false;
|
||||
|
||||
// Request to the target
|
||||
tlm::tlm_generic_payload *requestInProgress = nullptr;
|
||||
|
||||
// Backpressure on initiator
|
||||
tlm::tlm_generic_payload *endRequestPending = nullptr;
|
||||
|
||||
sc_core::sc_time lastEndReq = sc_core::sc_max_time();
|
||||
|
||||
void fillLine(tlm::tlm_generic_payload &trans);
|
||||
void accessCacheAndSendResponse(tlm::tlm_generic_payload &trans);
|
||||
void allocateLine(CacheLine *line, tag_t tag);
|
||||
|
||||
bool isAllocated(index_t index, tag_t tag) const;
|
||||
bool hasBufferSpace() const;
|
||||
|
||||
sc_core::sc_time ceilTime(const sc_core::sc_time &inTime) const;
|
||||
sc_core::sc_time ceilDelay(const sc_core::sc_time &inDelay) const;
|
||||
|
||||
MemoryManager &memoryManager;
|
||||
};
|
||||
313
src/simulator/simulator/EccModule.cpp
Normal file
313
src/simulator/simulator/EccModule.cpp
Normal file
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Technische Universität Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. 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.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder 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 HOLDER
|
||||
* 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:
|
||||
* Christian Malek
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#include "EccModule.h"
|
||||
|
||||
#include "DRAMSys/common/dramExtensions.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
using namespace sc_core;
|
||||
using namespace tlm;
|
||||
|
||||
EccModule::EccModule(sc_module_name name, AddressDecoder const &addressDecoder) :
|
||||
sc_core::sc_module(name),
|
||||
payloadEventQueue(this, &EccModule::peqCallback),
|
||||
addressDecoder(addressDecoder),
|
||||
memoryManager(false)
|
||||
{
|
||||
iSocket.register_nb_transport_bw(this, &EccModule::nb_transport_bw);
|
||||
tSocket.register_nb_transport_fw(this, &EccModule::nb_transport_fw);
|
||||
}
|
||||
|
||||
tlm::tlm_sync_enum EccModule::nb_transport_fw(tlm::tlm_generic_payload &payload,
|
||||
tlm::tlm_phase &phase,
|
||||
sc_core::sc_time &fwDelay)
|
||||
{
|
||||
if (phase == BEGIN_REQ)
|
||||
{
|
||||
payload.acquire();
|
||||
}
|
||||
|
||||
payloadEventQueue.notify(payload, phase, fwDelay);
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
tlm::tlm_sync_enum EccModule::nb_transport_bw(tlm::tlm_generic_payload &payload,
|
||||
tlm::tlm_phase &phase,
|
||||
sc_core::sc_time &bwDelay)
|
||||
{
|
||||
payloadEventQueue.notify(payload, phase, bwDelay);
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
void EccModule::peqCallback(tlm::tlm_generic_payload &cbPayload, const tlm::tlm_phase &cbPhase)
|
||||
{
|
||||
if (cbPhase == BEGIN_REQ) // from initiator
|
||||
{
|
||||
// Put transaction into latency map
|
||||
payloadMap.emplace(&cbPayload, sc_time_stamp());
|
||||
|
||||
if (!targetBusy)
|
||||
{
|
||||
targetBusy = true;
|
||||
|
||||
tlm_phase tPhase = BEGIN_REQ;
|
||||
sc_time tDelay = SC_ZERO_TIME;
|
||||
|
||||
DecodedAddress decodedAddress = addressDecoder.decodeAddress(cbPayload.get_address());
|
||||
decodedAddress = calculateOffsetAddress(decodedAddress);
|
||||
|
||||
// Update the original address to account for the offsets
|
||||
cbPayload.set_address(addressDecoder.encodeAddress(decodedAddress));
|
||||
|
||||
auto currentBlock = alignToBlock(decodedAddress.column);
|
||||
|
||||
// In case there is no entry yet.
|
||||
activeEccBlocks.try_emplace(decodedAddress.bank);
|
||||
|
||||
#ifdef ECC_ENABLE
|
||||
if (!activeEccBlock(decodedAddress.bank, decodedAddress.row, currentBlock))
|
||||
{
|
||||
blockedRequest = &cbPayload;
|
||||
|
||||
auto &eccFifo = activeEccBlocks[decodedAddress.bank];
|
||||
eccFifo.push_back({currentBlock, decodedAddress.row});
|
||||
|
||||
// Only hold 4 elements at max.
|
||||
if (eccFifo.size() >= 4)
|
||||
eccFifo.pop_front();
|
||||
|
||||
tlm::tlm_generic_payload *eccPayload = generateEccPayload(decodedAddress);
|
||||
|
||||
iSocket->nb_transport_fw(*eccPayload, tPhase, tDelay);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
iSocket->nb_transport_fw(cbPayload, tPhase, tDelay);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pendingRequest = &cbPayload;
|
||||
}
|
||||
}
|
||||
else if (cbPhase == END_REQ) // from target
|
||||
{
|
||||
// Send payload to inititator in case it is not an ECC transaction
|
||||
if (cbPayload.get_extension<EccExtension>() == nullptr)
|
||||
{
|
||||
tlm_phase tPhase = END_REQ;
|
||||
sc_time tDelay = SC_ZERO_TIME;
|
||||
|
||||
tSocket->nb_transport_bw(cbPayload, tPhase, tDelay);
|
||||
}
|
||||
|
||||
if (blockedRequest != nullptr)
|
||||
{
|
||||
tlm_generic_payload &tPayload = *blockedRequest;
|
||||
blockedRequest = nullptr;
|
||||
|
||||
tlm_phase tPhase = BEGIN_REQ;
|
||||
sc_time tDelay = SC_ZERO_TIME;
|
||||
|
||||
iSocket->nb_transport_fw(tPayload, tPhase, tDelay);
|
||||
|
||||
// Do not attempt to send another pending request and hold targetBusy high
|
||||
return;
|
||||
}
|
||||
|
||||
if (pendingRequest != nullptr)
|
||||
{
|
||||
tlm_generic_payload &tPayload = *pendingRequest;
|
||||
|
||||
tlm_phase tPhase = BEGIN_REQ;
|
||||
sc_time tDelay = SC_ZERO_TIME;
|
||||
|
||||
DecodedAddress decodedAddress = addressDecoder.decodeAddress(tPayload.get_address());
|
||||
decodedAddress = calculateOffsetAddress(decodedAddress);
|
||||
auto currentBlock = alignToBlock(decodedAddress.column);
|
||||
#ifdef ECC_ENABLE
|
||||
if (!activeEccBlock(decodedAddress.bank, decodedAddress.row, currentBlock))
|
||||
{
|
||||
blockedRequest = pendingRequest;
|
||||
pendingRequest = nullptr;
|
||||
|
||||
auto &eccFifo = activeEccBlocks[decodedAddress.bank];
|
||||
eccFifo.push_back({currentBlock, decodedAddress.row});
|
||||
|
||||
// Only hold 4 elements at max.
|
||||
if (eccFifo.size() >= 4)
|
||||
eccFifo.pop_front();
|
||||
|
||||
tlm::tlm_generic_payload *eccPayload = generateEccPayload(decodedAddress);
|
||||
|
||||
iSocket->nb_transport_fw(*eccPayload, tPhase, tDelay);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
iSocket->nb_transport_fw(tPayload, tPhase, tDelay);
|
||||
pendingRequest = nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(!pendingRequest);
|
||||
assert(!blockedRequest);
|
||||
targetBusy = false;
|
||||
}
|
||||
}
|
||||
else if (cbPhase == BEGIN_RESP) // from memory controller
|
||||
{
|
||||
// Send payload to inititator in case it is not an ECC transaction
|
||||
if (cbPayload.get_extension<EccExtension>() == nullptr)
|
||||
{
|
||||
tlm_phase tPhase = BEGIN_RESP;
|
||||
sc_time tDelay = SC_ZERO_TIME;
|
||||
|
||||
tlm_sync_enum returnValue = tSocket->nb_transport_bw(cbPayload, tPhase, tDelay);
|
||||
|
||||
// Early completion from initiator
|
||||
if (returnValue == TLM_UPDATED)
|
||||
{
|
||||
payloadEventQueue.notify(cbPayload, tPhase, tDelay);
|
||||
}
|
||||
|
||||
Latency latency = sc_time_stamp() - payloadMap.at(&cbPayload);
|
||||
payloadMap.erase(&cbPayload);
|
||||
|
||||
latency = roundLatency(latency);
|
||||
latencyMap.try_emplace(latency, 0);
|
||||
latencyMap.at(latency)++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Send END_RESP by ourselfes
|
||||
tlm_phase tPhase = END_RESP;
|
||||
sc_time tDelay = SC_ZERO_TIME;
|
||||
|
||||
iSocket->nb_transport_fw(cbPayload, tPhase, tDelay);
|
||||
}
|
||||
}
|
||||
else if (cbPhase == END_RESP) // from initiator
|
||||
{
|
||||
{
|
||||
tlm_phase tPhase = END_RESP;
|
||||
sc_time tDelay = SC_ZERO_TIME;
|
||||
|
||||
iSocket->nb_transport_fw(cbPayload, tPhase, tDelay);
|
||||
}
|
||||
|
||||
cbPayload.release();
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL(0, "Payload event queue in arbiter was triggered with unknown phase");
|
||||
}
|
||||
}
|
||||
|
||||
tlm::tlm_generic_payload *EccModule::generateEccPayload(DecodedAddress decodedAddress)
|
||||
{
|
||||
unsigned int eccAtom = decodedAddress.column / 512;
|
||||
uint64_t eccColumn = 1792 + eccAtom * 32;
|
||||
|
||||
decodedAddress.column = eccColumn;
|
||||
uint64_t eccAddress = addressDecoder.encodeAddress(decodedAddress);
|
||||
|
||||
tlm_generic_payload &payload = memoryManager.allocate(32);
|
||||
payload.acquire();
|
||||
payload.set_address(eccAddress);
|
||||
payload.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
|
||||
payload.set_dmi_allowed(false);
|
||||
payload.set_byte_enable_length(0);
|
||||
payload.set_data_length(32);
|
||||
payload.set_streaming_width(32);
|
||||
payload.set_command(tlm::TLM_READ_COMMAND);
|
||||
payload.set_extension<EccExtension>(new EccExtension);
|
||||
|
||||
return &payload;
|
||||
}
|
||||
|
||||
unsigned int EccModule::alignToBlock(unsigned column)
|
||||
{
|
||||
return column & ~(512 - 1);
|
||||
}
|
||||
|
||||
DecodedAddress EccModule::calculateOffsetAddress(DecodedAddress decodedAddress)
|
||||
{
|
||||
unsigned int newRow =
|
||||
std::floor((decodedAddress.row * 256 + decodedAddress.column) / 1792) + decodedAddress.row;
|
||||
unsigned int newColumn = (decodedAddress.row * 256 + decodedAddress.column) % 1792;
|
||||
|
||||
DecodedAddress offsetAddress(decodedAddress);
|
||||
offsetAddress.row = newRow;
|
||||
offsetAddress.column = newColumn;
|
||||
return offsetAddress;
|
||||
}
|
||||
|
||||
void EccModule::end_of_simulation()
|
||||
{
|
||||
uint64_t latencies = 0;
|
||||
uint64_t numberOfLatencies = 0;
|
||||
|
||||
for (auto const &[latency, occurences] : latencyMap)
|
||||
{
|
||||
latencies += (latency.to_double() / 1000.0) * occurences;
|
||||
numberOfLatencies += occurences;
|
||||
}
|
||||
|
||||
std::cout << "Average latency: " << static_cast<double>(latencies) / numberOfLatencies << std::endl;
|
||||
}
|
||||
|
||||
sc_time EccModule::roundLatency(sc_time latency)
|
||||
{
|
||||
static const sc_time BUCKET_SIZE = sc_time(1, SC_NS);
|
||||
latency += BUCKET_SIZE / 2;
|
||||
latency = latency - (latency % BUCKET_SIZE);
|
||||
return latency;
|
||||
}
|
||||
|
||||
bool EccModule::activeEccBlock(Bank bank, Row row, Block block) const
|
||||
{
|
||||
auto eccIt = std::find_if(activeEccBlocks.at(bank).cbegin(), activeEccBlocks.at(bank).cend(),
|
||||
[block, row](EccIdentifier identifier) {
|
||||
return (identifier.first == block) && (identifier.second == row);
|
||||
});
|
||||
|
||||
return eccIt != activeEccBlocks.at(bank).cend();
|
||||
}
|
||||
107
src/simulator/simulator/EccModule.h
Normal file
107
src/simulator/simulator/EccModule.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Technische Universität Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. 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.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder 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 HOLDER
|
||||
* 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:
|
||||
* Christian Malek
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#ifndef ECCMODULE_H
|
||||
#define ECCMODULE_H
|
||||
|
||||
#include "simulator/MemoryManager.h"
|
||||
|
||||
#include <DRAMSys/simulation/AddressDecoder.h>
|
||||
|
||||
#include <systemc>
|
||||
#include <tlm_utils/peq_with_cb_and_phase.h>
|
||||
#include <tlm_utils/simple_initiator_socket.h>
|
||||
#include <tlm_utils/simple_target_socket.h>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <deque>
|
||||
|
||||
class EccModule : public sc_core::sc_module
|
||||
{
|
||||
public:
|
||||
tlm_utils::simple_initiator_socket<EccModule> iSocket;
|
||||
tlm_utils::simple_target_socket<EccModule> tSocket;
|
||||
|
||||
EccModule(sc_core::sc_module_name name, AddressDecoder const &addressDecoder);
|
||||
SC_HAS_PROCESS(EccModule);
|
||||
|
||||
private:
|
||||
using Block = uint64_t;
|
||||
using Row = uint64_t;
|
||||
using Bank = unsigned int;
|
||||
using EccIdentifier = std::pair<Block, Row>;
|
||||
using EccQueue = std::deque<EccIdentifier>;
|
||||
|
||||
static DecodedAddress calculateOffsetAddress(DecodedAddress decodedAddress);
|
||||
static sc_core::sc_time roundLatency(sc_core::sc_time latency);
|
||||
bool activeEccBlock(Bank bank, Row row, Block block) const;
|
||||
|
||||
void end_of_simulation() override;
|
||||
|
||||
void peqCallback(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase);
|
||||
|
||||
tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload &payload,
|
||||
tlm::tlm_phase &phase,
|
||||
sc_core::sc_time &fwDelay);
|
||||
tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &payload,
|
||||
tlm::tlm_phase &phase,
|
||||
sc_core::sc_time &bwDelay);
|
||||
|
||||
tlm::tlm_generic_payload *generateEccPayload(DecodedAddress decodedAddress);
|
||||
|
||||
static unsigned int alignToBlock(unsigned int column);
|
||||
|
||||
tlm_utils::peq_with_cb_and_phase<EccModule> payloadEventQueue;
|
||||
|
||||
tlm::tlm_generic_payload *pendingRequest = nullptr;
|
||||
tlm::tlm_generic_payload *blockedRequest = nullptr;
|
||||
bool targetBusy = false;
|
||||
|
||||
const sc_core::sc_time tCK;
|
||||
MemoryManager memoryManager;
|
||||
AddressDecoder const &addressDecoder;
|
||||
|
||||
std::unordered_map<Bank, EccQueue> activeEccBlocks;
|
||||
|
||||
using EccPayload = tlm::tlm_generic_payload *;
|
||||
using StartTime = sc_core::sc_time;
|
||||
std::unordered_map<tlm::tlm_generic_payload*, StartTime> payloadMap;
|
||||
|
||||
using Latency = sc_core::sc_time;
|
||||
std::map<Latency, uint64_t> latencyMap;
|
||||
};
|
||||
|
||||
#endif // ECCMODULE_H
|
||||
47
src/simulator/simulator/Initiator.h
Normal file
47
src/simulator/simulator/Initiator.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Technische Universität Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. 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.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder 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 HOLDER
|
||||
* 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:
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tlm_utils/multi_socket_bases.h>
|
||||
|
||||
class Initiator
|
||||
{
|
||||
public:
|
||||
virtual ~Initiator() = default;
|
||||
|
||||
virtual void bind(tlm_utils::multi_target_base<> &target) = 0;
|
||||
virtual uint64_t totalRequests() = 0;
|
||||
};
|
||||
70
src/simulator/simulator/SimpleInitiator.h
Normal file
70
src/simulator/simulator/SimpleInitiator.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Technische Universität Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. 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.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder 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 HOLDER
|
||||
* 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:
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Initiator.h"
|
||||
#include "request/RequestIssuer.h"
|
||||
|
||||
template <typename Producer>
|
||||
class SimpleInitiator : public Initiator
|
||||
{
|
||||
public:
|
||||
SimpleInitiator(sc_core::sc_module_name const &name,
|
||||
MemoryManager &memoryManager,
|
||||
std::optional<unsigned int> maxPendingReadRequests,
|
||||
std::optional<unsigned int> maxPendingWriteRequests,
|
||||
std::function<void()> transactionFinished,
|
||||
std::function<void()> terminate,
|
||||
Producer &&producer)
|
||||
: producer(std::forward<Producer>(producer)),
|
||||
issuer(
|
||||
name,
|
||||
memoryManager,
|
||||
maxPendingReadRequests,
|
||||
maxPendingWriteRequests,
|
||||
[this] { return this->producer.nextRequest(); },
|
||||
std::move(transactionFinished),
|
||||
std::move(terminate))
|
||||
{
|
||||
}
|
||||
|
||||
void bind(tlm_utils::multi_target_base<> &target) override { issuer.iSocket.bind(target); }
|
||||
uint64_t totalRequests() override { return producer.totalRequests(); };
|
||||
|
||||
private:
|
||||
Producer producer;
|
||||
RequestIssuer issuer;
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user