Files
DRAMSys/DRAMSys/library/src/simulation/dram/DramWideIO.cpp

220 lines
9.1 KiB
C++

/*
* Copyright (c) 2019, University of 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:
* Lukas Steiner
*/
#include "DramWideIO.h"
#include <systemc.h>
#include <tlm.h>
#include "Dram.h"
#include "../../configuration/Configuration.h"
#include "../../error/errormodel.h"
#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h"
#include "../../configuration/memspec/MemSpecWideIO.h"
using namespace tlm;
using namespace DRAMPower;
DramWideIO::DramWideIO(sc_module_name name) : Dram(name)
{
if (Configuration::getInstance().powerAnalysis)
{
MemSpecWideIO *memSpec = dynamic_cast<MemSpecWideIO *>(this->memSpec);
if (memSpec == nullptr)
SC_REPORT_FATAL("DramWideIO", "Wrong MemSpec chosen");
MemArchitectureSpec memArchSpec;
memArchSpec.burstLength = memSpec->burstLength;
memArchSpec.dataRate = memSpec->dataRate;
memArchSpec.nbrOfRows = memSpec->numberOfRows;
memArchSpec.nbrOfBanks = memSpec->numberOfBanks;
memArchSpec.nbrOfColumns = memSpec->numberOfColumns;
memArchSpec.nbrOfRanks = memSpec->numberOfRanks;
memArchSpec.width = memSpec->bitWidth;
memArchSpec.nbrOfBankGroups = memSpec->numberOfBankGroups;
memArchSpec.twoVoltageDomains = true;
memArchSpec.dll = false;
MemTimingSpec memTimingSpec;
//FIXME: memTimingSpec.FAWB = memSpec->tTAW / memSpec->tCK;
//FIXME: memTimingSpec.RASB = memSpec->tRAS / memSpec->tCK;
//FIXME: memTimingSpec.RCB = memSpec->tRC / memSpec->tCK;
//FIXME: memTimingSpec.RPB = memSpec->tRP / memSpec->tCK;
//FIXME: memTimingSpec.RRDB = memSpec->tRRD / memSpec->tCK;
//FIXME: memTimingSpec.RRDB_L = memSpec->tRRD / memSpec->tCK;
//FIXME: memTimingSpec.RRDB_S = memSpec->tRRD / memSpec->tCK;
memTimingSpec.AL = 0;
memTimingSpec.CCD = memSpec->burstLength;
memTimingSpec.CCD_L = memSpec->burstLength;
memTimingSpec.CCD_S = memSpec->burstLength;
memTimingSpec.CKE = memSpec->tCKE / memSpec->tCK;
memTimingSpec.CKESR = memSpec->tCKESR / memSpec->tCK;
memTimingSpec.clkMhz = memSpec->fCKMHz;
// See also MemTimingSpec.cc in DRAMPower
memTimingSpec.clkPeriod = 1000.0 / memSpec->fCKMHz;
memTimingSpec.DQSCK = memSpec->tDQSCK / memSpec->tCK;
memTimingSpec.FAW = memSpec->tTAW / memSpec->tCK;
memTimingSpec.RAS = memSpec->tRAS / memSpec->tCK;
memTimingSpec.RC = memSpec->tRC / memSpec->tCK;
memTimingSpec.RCD = memSpec->tRCD / memSpec->tCK;
memTimingSpec.REFI = memSpec->tREFI / memSpec->tCK;
memTimingSpec.RFC = memSpec->tRFC / memSpec->tCK;
memTimingSpec.RL = memSpec->tRL / memSpec->tCK;
memTimingSpec.RP = memSpec->tRP / memSpec->tCK;
memTimingSpec.RRD = memSpec->tRRD / memSpec->tCK;
memTimingSpec.RRD_L = memSpec->tRRD / memSpec->tCK;
memTimingSpec.RRD_S = memSpec->tRRD / memSpec->tCK;
memTimingSpec.RTP = memSpec->burstLength;
memTimingSpec.TAW = memSpec->tTAW / memSpec->tCK;
memTimingSpec.WL = memSpec->tWL / memSpec->tCK;
memTimingSpec.WR = memSpec->tWR / memSpec->tCK;
memTimingSpec.WTR = memSpec->tWTR / memSpec->tCK;
memTimingSpec.WTR_L = memSpec->tWTR / memSpec->tCK;
memTimingSpec.WTR_S = memSpec->tWTR / memSpec->tCK;
memTimingSpec.XP = memSpec->tXP / memSpec->tCK;
memTimingSpec.XPDLL = memSpec->tXP / memSpec->tCK;
memTimingSpec.XS = memSpec->tXS / memSpec->tCK;
memTimingSpec.XSDLL = memSpec->tXS / memSpec->tCK;
MemPowerSpec memPowerSpec;
memPowerSpec.idd0 = memSpec->iDD0;
memPowerSpec.idd02 = memSpec->iDD02;
memPowerSpec.idd2p0 = memSpec->iDD2P0;
memPowerSpec.idd2p02 = memSpec->iDD2P02;
memPowerSpec.idd2p1 = memSpec->iDD2P1;
memPowerSpec.idd2p12 = memSpec->iDD2P12;
memPowerSpec.idd2n = memSpec->iDD2N;
memPowerSpec.idd2n2 = memSpec->iDD2N2;
memPowerSpec.idd3p0 = memSpec->iDD3P0;
memPowerSpec.idd3p02 = memSpec->iDD3P02;
memPowerSpec.idd3p1 = memSpec->iDD3P1;
memPowerSpec.idd3p12 = memSpec->iDD3P12;
memPowerSpec.idd3n = memSpec->iDD3N;
memPowerSpec.idd3n2 = memSpec->iDD3N2;
memPowerSpec.idd4r = memSpec->iDD4R;
memPowerSpec.idd4r2 = memSpec->iDD4R2;
memPowerSpec.idd4w = memSpec->iDD4W;
memPowerSpec.idd4w2 = memSpec->iDD4W2;
memPowerSpec.idd5 = memSpec->iDD5;
memPowerSpec.idd52 = memSpec->iDD52;
memPowerSpec.idd6 = memSpec->iDD6;
memPowerSpec.idd62 = memSpec->iDD62;
memPowerSpec.vdd = memSpec->vDD;
memPowerSpec.vdd2 = memSpec->vDD2;
MemorySpecification powerSpec;
powerSpec.id = memSpec->memoryId;
powerSpec.memoryType = memSpec->memoryType;
powerSpec.memTimingSpec = memTimingSpec;
powerSpec.memPowerSpec = memPowerSpec;
powerSpec.memArchSpec = memArchSpec;
DRAMPower = new libDRAMPower(powerSpec, 0);
// For each bank in a channel a error Model is created:
if (storeMode == StorageMode::ErrorModel)
{
for (unsigned i = 0; i < memSpec->numberOfBanks; i++)
{
errorModel *em;
std::string errorModelStr = "errorModel_bank" + std::to_string(i);
em = new errorModel(errorModelStr.c_str(), DRAMPower);
ememory.push_back(em);
}
}
}
else
{
if (storeMode == StorageMode::ErrorModel)
{
for (unsigned i = 0; i < memSpec->numberOfBanks; i++)
{
errorModel *em;
std::string errorModelStr = "errorModel_bank" + std::to_string(i);
em = new errorModel(errorModelStr.c_str());
ememory.push_back(em);
}
}
}
}
DramWideIO::~DramWideIO()
{
// Clean up:
for (auto e : ememory)
delete e;
}
tlm_sync_enum DramWideIO::nb_transport_fw(tlm_generic_payload &payload,
tlm_phase &phase, sc_time &)
{
assert(phase >= 5 && phase <= 19);
if (Configuration::getInstance().powerAnalysis)
{
unsigned bank = DramExtension::getExtension(payload).getBank().ID();
unsigned long long cycle = sc_time_stamp() / memSpec->tCK;
DRAMPower->doCommand(phaseToDRAMPowerCommand(phase), bank, cycle);
}
if (storeMode == StorageMode::Store)
{
if (phase == BEGIN_RD || phase == BEGIN_RDA)
{
unsigned char *phyAddr = memory + payload.get_address();
memcpy(payload.get_data_ptr(), phyAddr, payload.get_data_length());
}
else if (phase == BEGIN_WR || phase == BEGIN_WRA)
{
unsigned char *phyAddr = memory + payload.get_address();
memcpy(phyAddr, payload.get_data_ptr(), payload.get_data_length());
}
}
else if (storeMode == StorageMode::ErrorModel)
{
unsigned bank = DramExtension::getExtension(payload).getBank().ID();
if (phase == BEGIN_ACT)
ememory[bank]->activate(DramExtension::getExtension(payload).getRow().ID());
else if (phase == BEGIN_RD || phase == BEGIN_RDA)
ememory[bank]->load(payload);
else if (phase == BEGIN_WR || phase == BEGIN_WRA)
ememory[bank]->store(payload);
else if (phase == BEGIN_REFA)
ememory[bank]->refresh(DramExtension::getExtension(payload).getRow().ID());
}
return TLM_ACCEPTED;
}