359 lines
14 KiB
C++
359 lines
14 KiB
C++
/*
|
|
* Copyright (c) 2015, 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:
|
|
* Janik Schlemminger
|
|
* Matthias Jung
|
|
* Éder F. Zulian
|
|
* Felipe S. Prado
|
|
* Lukas Steiner
|
|
* Luiza Correa
|
|
* Derek Christ
|
|
*/
|
|
|
|
#include "Configuration.h"
|
|
#include "memspec/MemSpecDDR3.h"
|
|
#include "memspec/MemSpecDDR4.h"
|
|
#include "memspec/MemSpecDDR5.h"
|
|
#include "memspec/MemSpecWideIO.h"
|
|
#include "memspec/MemSpecLPDDR4.h"
|
|
#include "memspec/MemSpecLPDDR5.h"
|
|
#include "memspec/MemSpecWideIO2.h"
|
|
#include "memspec/MemSpecHBM2.h"
|
|
#include "memspec/MemSpecGDDR5.h"
|
|
#include "memspec/MemSpecGDDR5X.h"
|
|
#include "memspec/MemSpecGDDR6.h"
|
|
#include "memspec/MemSpecSTTMRAM.h"
|
|
|
|
using namespace sc_core;
|
|
|
|
enum sc_time_unit string2TimeUnit(const std::string &s)
|
|
{
|
|
if (s == "s")
|
|
return SC_SEC;
|
|
else if (s == "ms")
|
|
return SC_MS;
|
|
else if (s == "us")
|
|
return SC_US;
|
|
else if (s == "ns")
|
|
return SC_NS;
|
|
else if (s == "ps")
|
|
return SC_PS;
|
|
else if (s == "fs")
|
|
return SC_FS;
|
|
else {
|
|
SC_REPORT_FATAL("Configuration",
|
|
("Could not convert to enum sc_time_unit: " + s).c_str());
|
|
throw;
|
|
}
|
|
}
|
|
|
|
void Configuration::loadSimConfig(Configuration &config, const DRAMSysConfiguration::SimConfig &simConfig)
|
|
{
|
|
if (simConfig.addressOffset.isValid())
|
|
config.addressOffset = simConfig.addressOffset.getValue();
|
|
|
|
if (simConfig.addressOffset.isValid())
|
|
config.checkTLM2Protocol = simConfig.checkTLM2Protocol.getValue();
|
|
|
|
if (simConfig.databaseRecording.isValid())
|
|
config.databaseRecording = simConfig.databaseRecording.getValue();
|
|
|
|
if (simConfig.debug.isValid())
|
|
config.debug = simConfig.debug.getValue();
|
|
|
|
if (simConfig.enableWindowing.isValid())
|
|
config.enableWindowing = simConfig.enableWindowing.getValue();
|
|
|
|
if (simConfig.powerAnalysis.isValid())
|
|
config.powerAnalysis = simConfig.powerAnalysis.getValue();
|
|
|
|
if (simConfig.simulationName.isValid())
|
|
config.simulationName = simConfig.simulationName.getValue();
|
|
|
|
if (simConfig.simulationProgressBar.isValid())
|
|
config.simulationProgressBar = simConfig.simulationProgressBar.getValue();
|
|
|
|
if (simConfig.thermalSimulation.isValid())
|
|
config.thermalSimulation = simConfig.thermalSimulation.getValue();
|
|
|
|
if (simConfig.useMalloc.isValid())
|
|
config.useMalloc = simConfig.useMalloc.getValue();
|
|
|
|
if (simConfig.windowSize.isValid())
|
|
config.windowSize = simConfig.windowSize.getValue();
|
|
|
|
if (config.windowSize == 0)
|
|
SC_REPORT_FATAL("Configuration", "Minimum window size is 1");
|
|
|
|
if (simConfig.errorCsvFile.isValid())
|
|
config.errorCSVFile = simConfig.errorCsvFile.getValue();
|
|
|
|
if (simConfig.errorChipSeed.isValid())
|
|
config.errorChipSeed = simConfig.errorChipSeed.getValue();
|
|
|
|
if (simConfig.storeMode.isValid())
|
|
config.storeMode = [=] {
|
|
auto mode = simConfig.storeMode.getValue();
|
|
|
|
if (mode == DRAMSysConfiguration::StoreMode::NoStorage)
|
|
return StoreMode::NoStorage;
|
|
else if (mode == DRAMSysConfiguration::StoreMode::Store)
|
|
return StoreMode::Store;
|
|
else
|
|
return StoreMode::ErrorModel;
|
|
}();
|
|
}
|
|
|
|
void Configuration::loadTemperatureSimConfig(Configuration &config, const DRAMSysConfiguration::ThermalConfig &thermalConfig)
|
|
{
|
|
config.temperatureSim.temperatureScale = [=] {
|
|
if (thermalConfig.temperatureScale == DRAMSysConfiguration::TemperatureScale::Celsius)
|
|
return TemperatureSimConfig::TemperatureScale::Celsius;
|
|
else if (thermalConfig.temperatureScale == DRAMSysConfiguration::TemperatureScale::Fahrenheit)
|
|
return TemperatureSimConfig::TemperatureScale::Fahrenheit;
|
|
else
|
|
return TemperatureSimConfig::TemperatureScale::Kelvin;
|
|
}();
|
|
|
|
config.temperatureSim.staticTemperatureDefaultValue = thermalConfig.staticTemperatureDefaultValue;
|
|
config.temperatureSim.thermalSimPeriod = thermalConfig.thermalSimPeriod;
|
|
|
|
config.temperatureSim.thermalSimUnit = [=] {
|
|
if (thermalConfig.thermalSimUnit == DRAMSysConfiguration::ThermalSimUnit::Seconds)
|
|
return sc_core::SC_SEC;
|
|
else if (thermalConfig.thermalSimUnit == DRAMSysConfiguration::ThermalSimUnit::Milliseconds)
|
|
return sc_core::SC_MS;
|
|
else if (thermalConfig.thermalSimUnit == DRAMSysConfiguration::ThermalSimUnit::Microseconds)
|
|
return sc_core::SC_US;
|
|
else if (thermalConfig.thermalSimUnit == DRAMSysConfiguration::ThermalSimUnit::Nanoseconds)
|
|
return sc_core::SC_NS;
|
|
else if (thermalConfig.thermalSimUnit == DRAMSysConfiguration::ThermalSimUnit::Picoseconds)
|
|
return sc_core::SC_PS;
|
|
else
|
|
return sc_core::SC_FS;
|
|
}();
|
|
|
|
for (const auto &channel : thermalConfig.powerInfo.channels)
|
|
{
|
|
config.temperatureSim.powerInitialValues.push_back(channel.init_pow);
|
|
config.temperatureSim.powerThresholds.push_back(channel.threshold);
|
|
}
|
|
|
|
config.temperatureSim.iceServerIp = thermalConfig.iceServerIp;
|
|
config.temperatureSim.iceServerPort = thermalConfig.iceServerPort;
|
|
config.temperatureSim.simPeriodAdjustFactor = thermalConfig.simPeriodAdjustFactor;
|
|
config.temperatureSim.nPowStableCyclesToIncreasePeriod = thermalConfig.nPowStableCyclesToIncreasePeriod;
|
|
config.temperatureSim.generateTemperatureMap = thermalConfig.generateTemperatureMap;
|
|
config.temperatureSim.generatePowerMap = thermalConfig.generatePowerMap;
|
|
|
|
config.temperatureSim.showTemperatureSimConfig();
|
|
}
|
|
|
|
void Configuration::loadMCConfig(Configuration &config, const DRAMSysConfiguration::McConfig &mcConfig)
|
|
{
|
|
if (mcConfig.pagePolicy.isValid())
|
|
config.pagePolicy = [=] {
|
|
auto policy = mcConfig.pagePolicy.getValue();
|
|
|
|
if (policy == DRAMSysConfiguration::PagePolicy::Open)
|
|
return PagePolicy::Open;
|
|
else if (policy == DRAMSysConfiguration::PagePolicy::OpenAdaptive)
|
|
return PagePolicy::OpenAdaptive;
|
|
else if (policy == DRAMSysConfiguration::PagePolicy::Closed)
|
|
return PagePolicy::Closed;
|
|
else
|
|
return PagePolicy::ClosedAdaptive;
|
|
}();
|
|
|
|
if (mcConfig.scheduler.isValid())
|
|
config.scheduler = [=] {
|
|
auto scheduler = mcConfig.scheduler.getValue();
|
|
|
|
if (scheduler == DRAMSysConfiguration::Scheduler::Fifo)
|
|
return Scheduler::Fifo;
|
|
else if (scheduler == DRAMSysConfiguration::Scheduler::FrFcfs)
|
|
return Scheduler::FrFcfs;
|
|
else
|
|
return Scheduler::FrFcfsGrp;
|
|
}();
|
|
|
|
if (mcConfig.schedulerBuffer.isValid())
|
|
config.schedulerBuffer = [=] {
|
|
auto schedulerBuffer = mcConfig.schedulerBuffer.getValue();
|
|
|
|
if (schedulerBuffer == DRAMSysConfiguration::SchedulerBuffer::Bankwise)
|
|
return SchedulerBuffer::Bankwise;
|
|
else if (schedulerBuffer == DRAMSysConfiguration::SchedulerBuffer::ReadWrite)
|
|
return SchedulerBuffer::ReadWrite;
|
|
else
|
|
return SchedulerBuffer::Shared;
|
|
}();
|
|
|
|
if (mcConfig.requestBufferSize.isValid())
|
|
config.requestBufferSize = mcConfig.requestBufferSize.getValue();
|
|
|
|
if (config.requestBufferSize == 0)
|
|
SC_REPORT_FATAL("Configuration", "Minimum request buffer size is 1!");
|
|
|
|
if (mcConfig.cmdMux.isValid())
|
|
config.cmdMux = [=] {
|
|
auto cmdMux = mcConfig.cmdMux.getValue();
|
|
|
|
if (cmdMux == DRAMSysConfiguration::CmdMux::Oldest)
|
|
return CmdMux::Oldest;
|
|
else
|
|
return CmdMux::Strict;
|
|
}();
|
|
|
|
if (mcConfig.respQueue.isValid())
|
|
config.respQueue = [=] {
|
|
auto respQueue = mcConfig.respQueue.getValue();
|
|
|
|
if (respQueue == DRAMSysConfiguration::RespQueue::Fifo)
|
|
return RespQueue::Fifo;
|
|
else
|
|
return RespQueue::Reorder;
|
|
}();
|
|
|
|
if (mcConfig.refreshPolicy.isValid())
|
|
config.refreshPolicy = [=] {
|
|
auto policy = mcConfig.refreshPolicy.getValue();
|
|
|
|
if (policy == DRAMSysConfiguration::RefreshPolicy::NoRefresh)
|
|
return RefreshPolicy::NoRefresh;
|
|
else if (policy == DRAMSysConfiguration::RefreshPolicy::AllBank || policy == DRAMSysConfiguration::RefreshPolicy::Rankwise)
|
|
return RefreshPolicy::AllBank;
|
|
else if (policy == DRAMSysConfiguration::RefreshPolicy::PerBank || policy == DRAMSysConfiguration::RefreshPolicy::Bankwise)
|
|
return RefreshPolicy::PerBank;
|
|
else if (policy == DRAMSysConfiguration::RefreshPolicy::Per2Bank)
|
|
return RefreshPolicy::Per2Bank;
|
|
else // if (policy == DRAMSysConfiguration::RefreshPolicy::SameBank || policy == DRAMSysConfiguration::RefreshPolicy::Groupwise)
|
|
return RefreshPolicy::SameBank;
|
|
}();
|
|
|
|
if (mcConfig.refreshMaxPostponed.isValid())
|
|
config.refreshMaxPostponed = mcConfig.refreshMaxPostponed.getValue();
|
|
|
|
if (mcConfig.refreshMaxPulledin.isValid())
|
|
config.refreshMaxPulledin = mcConfig.refreshMaxPulledin.getValue();
|
|
|
|
if (mcConfig.powerDownPolicy.isValid())
|
|
config.powerDownPolicy = [=] {
|
|
auto policy = mcConfig.powerDownPolicy.getValue();
|
|
|
|
if (policy == DRAMSysConfiguration::PowerDownPolicy::NoPowerDown)
|
|
return PowerDownPolicy::NoPowerDown;
|
|
else
|
|
return PowerDownPolicy::Staggered;
|
|
}();
|
|
|
|
if (mcConfig.arbiter.isValid())
|
|
config.arbiter = [=] {
|
|
auto arbiter = mcConfig.arbiter.getValue();
|
|
|
|
if (arbiter == DRAMSysConfiguration::Arbiter::Simple)
|
|
return Arbiter::Simple;
|
|
else if (arbiter == DRAMSysConfiguration::Arbiter::Fifo)
|
|
return Arbiter::Fifo;
|
|
else
|
|
return Arbiter::Reorder;
|
|
}();
|
|
|
|
if (mcConfig.maxActiveTransactions.isValid())
|
|
config.maxActiveTransactions = mcConfig.maxActiveTransactions.getValue();
|
|
|
|
if (mcConfig.refreshManagement.isValid())
|
|
config.refreshManagement = mcConfig.refreshManagement.getValue();
|
|
|
|
if (mcConfig.arbitrationDelayFw.isValid())
|
|
{
|
|
config.arbitrationDelayFw = std::round(sc_time(mcConfig.arbitrationDelayFw.getValue(), SC_NS) / config.memSpec->tCK) * config.memSpec->tCK;
|
|
}
|
|
|
|
if (mcConfig.arbitrationDelayBw.isValid())
|
|
{
|
|
config.arbitrationDelayBw = std::round(sc_time(mcConfig.arbitrationDelayBw.getValue(), SC_NS) / config.memSpec->tCK) * config.memSpec->tCK;
|
|
}
|
|
|
|
if (mcConfig.thinkDelayFw.isValid())
|
|
{
|
|
config.thinkDelayFw = std::round(sc_time(mcConfig.thinkDelayFw.getValue(), SC_NS) / config.memSpec->tCK) * config.memSpec->tCK;
|
|
}
|
|
|
|
if (mcConfig.thinkDelayBw.isValid())
|
|
{
|
|
config.thinkDelayBw = std::round(sc_time(mcConfig.thinkDelayBw.getValue(), SC_NS) / config.memSpec->tCK) * config.memSpec->tCK;
|
|
}
|
|
|
|
if (mcConfig.phyDelayFw.isValid())
|
|
{
|
|
config.phyDelayFw = std::round(sc_time(mcConfig.phyDelayFw.getValue(), SC_NS) / config.memSpec->tCK) * config.memSpec->tCK;
|
|
}
|
|
|
|
if (mcConfig.phyDelayBw.isValid())
|
|
{
|
|
config.phyDelayBw = std::round(sc_time(mcConfig.phyDelayBw.getValue(), SC_NS) / config.memSpec->tCK) * config.memSpec->tCK;
|
|
}
|
|
}
|
|
|
|
void Configuration::loadMemSpec(Configuration &config, const DRAMSysConfiguration::MemSpec &memSpecConfig)
|
|
{
|
|
std::string memoryType = memSpecConfig.memoryType;
|
|
|
|
if (memoryType == "DDR3")
|
|
config.memSpec = new MemSpecDDR3(memSpecConfig);
|
|
else if (memoryType == "DDR4")
|
|
config.memSpec = new MemSpecDDR4(memSpecConfig);
|
|
else if (memoryType == "DDR5")
|
|
config.memSpec = new MemSpecDDR5(memSpecConfig);
|
|
else if (memoryType == "LPDDR4")
|
|
config.memSpec = new MemSpecLPDDR4(memSpecConfig);
|
|
else if (memoryType == "LPDDR5")
|
|
config.memSpec = new MemSpecLPDDR5(memSpecConfig);
|
|
else if (memoryType == "WIDEIO_SDR")
|
|
config.memSpec = new MemSpecWideIO(memSpecConfig);
|
|
else if (memoryType == "WIDEIO2")
|
|
config.memSpec = new MemSpecWideIO2(memSpecConfig);
|
|
else if (memoryType == "HBM2")
|
|
config.memSpec = new MemSpecHBM2(memSpecConfig);
|
|
else if (memoryType == "GDDR5")
|
|
config.memSpec = new MemSpecGDDR5(memSpecConfig);
|
|
else if (memoryType == "GDDR5X")
|
|
config.memSpec = new MemSpecGDDR5X(memSpecConfig);
|
|
else if (memoryType == "GDDR6")
|
|
config.memSpec = new MemSpecGDDR6(memSpecConfig);
|
|
else if (memoryType == "STT-MRAM")
|
|
config.memSpec = new MemSpecSTTMRAM(memSpecConfig);
|
|
else
|
|
SC_REPORT_FATAL("Configuration", "Unsupported DRAM type");
|
|
}
|