Files
DRAMSys/dram/src/simulation/Dram.h
2014-07-23 13:51:51 +02:00

174 lines
5.7 KiB
C++

/*
* dram.h
*
* Created on: Mar 16, 2014
* Author: robert
*/
#ifndef DRAM_H_
#define DRAM_H_
#include <tlm.h>
#include <systemc.h>
#include <tlm_utils/peq_with_cb_and_phase.h>
#include <tlm_utils/simple_target_socket.h>
#include "../common/DebugManager.h"
#include "../common/dramExtension.h"
#include "../controller/core/TimingCalculation.h"
#include "../controller/core/configuration/Configuration.h"
#include "../common/protocol.h"
#include "../common/Utils.h"
#include "../common/TlmRecorder.h"
#include "../common/third_party/DRAMPower/src/LibDRAMPower.h"
using namespace std;
using namespace tlm;
using namespace core;
template<unsigned int BUSWIDTH = 128, unsigned int WORDS = 4096, bool STORE = true, bool FIXED_BL = false,
unsigned int FIXED_BL_VALUE = 0>
struct Dram: sc_module
{
tlm_utils::simple_target_socket<Dram, BUSWIDTH, tlm::tlm_base_protocol_types> tSocket;
libDRAMPower *DRAMPower;
SC_CTOR(Dram) :
tSocket("socket")
{
tSocket.register_nb_transport_fw(this, &Dram::nb_transport_fw);
MemorySpecification memSpec(MemorySpecification::getMemSpecFromXML(Configuration::getInstance().memspecUri));
DRAMPower = new libDRAMPower( memSpec, 1,1,1,0,0 );
}
~Dram()
{
DRAMPower->getEnergy();
cout << "Total Energy" << "\t" << DRAMPower->mpm.energy.total_energy << endl;
cout << "Average Power" << "\t" << DRAMPower->mpm.power.average_power << endl;
}
virtual tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload& payload, tlm::tlm_phase& phase, sc_time& delay)
{
TlmRecorder::getInstance().recordPhase(payload, phase, sc_time_stamp() + delay);
// This is only needed for power simulation:
unsigned long long cycle = sc_time_stamp().value()/Configuration::getInstance().Timings.clk.value();
unsigned int bank = DramExtension::getExtension(payload).getBank().ID();
if (phase == BEGIN_PRE)
{
DRAMPower->doCommand(MemCommand::PRE, bank, cycle);
sendToController(payload, END_PRE, delay + getExecutionTime(Command::Precharge, payload));
}
else if (phase == BEGIN_PRE_ALL)
{
DRAMPower->doCommand(MemCommand::PREA, bank, cycle);
sendToController(payload, END_PRE_ALL,delay + getExecutionTime(Command::PrechargeAll, payload));
}
else if (phase == BEGIN_ACT)
{
DRAMPower->doCommand(MemCommand::ACT, bank, cycle);
sendToController(payload, END_ACT, delay + getExecutionTime(Command::Activate, payload));
}
else if (phase == BEGIN_WR)
{
DRAMPower->doCommand(MemCommand::WR, bank, cycle);
sendToController(payload, END_WR, delay + getExecutionTime(Command::Write, payload));
}
else if (phase == BEGIN_RD)
{
DRAMPower->doCommand(MemCommand::RD, bank, cycle);
sendToController(payload, END_RD, delay + getExecutionTime(Command::Read, payload));
}
else if (phase == BEGIN_WRA)
{
DRAMPower->doCommand(MemCommand::WRA, bank, cycle);
sendToController(payload, END_WRA, delay + getExecutionTime(Command::WriteA, payload));
}
else if (phase == BEGIN_RDA)
{
DRAMPower->doCommand(MemCommand::RDA, bank, cycle);
sendToController(payload, END_RDA, delay + getExecutionTime(Command::ReadA, payload));
}
else if (phase == BEGIN_AUTO_REFRESH)
{
DRAMPower->doCommand(MemCommand::REF, bank, cycle);
sendToController(payload, END_AUTO_REFRESH, delay + getExecutionTime(Command::AutoRefresh, payload));
}
//Powerdown phases have to be started and ended by the controller, because they do not have a fixed length
else if (phase == BEGIN_PDNP)
{
if(Configuration::getInstance().BankwiseLogic == false)
{
if(bank == 0)
{
DRAMPower->doCommand(MemCommand::PDN_S_PRE, bank, cycle);
}
}
}
else if (phase == END_PDNP)
{
if(Configuration::getInstance().BankwiseLogic == false)
{
if(bank == 0)
{
DRAMPower->doCommand(MemCommand::PUP_PRE, bank, cycle);
}
}
}
else if (phase == BEGIN_PDNA)
{
if(Configuration::getInstance().BankwiseLogic == false)
{
if(bank == 0)
{
DRAMPower->doCommand(MemCommand::PDN_S_ACT, bank, cycle);
}
}
}
else if (phase == END_PDNA)
{
if(Configuration::getInstance().BankwiseLogic ==false)
{
if(bank == 0)
{
DRAMPower->doCommand(MemCommand::PUP_ACT, bank, cycle);
}
}
}
else if (phase == BEGIN_SREF)
{
DRAMPower->doCommand(MemCommand::SREN, bank, cycle);
}
else if (phase == END_SREF)
{
DRAMPower->doCommand(MemCommand::SREX, bank, cycle);
}
else
{
SC_REPORT_FATAL("DRAM", "DRAM PEQ was called with unknown phase");
}
return tlm::TLM_ACCEPTED;
}
void sendToController(tlm_generic_payload& payload, const tlm_phase& phase, const sc_time& delay)
{
tlm_phase TPhase = phase;
sc_time TDelay = delay;
tSocket->nb_transport_bw(payload, TPhase, TDelay);
}
void printDebugMessage(string message)
{
DebugManager::getInstance().printDebugMessage(name(), message);
}
};
#endif /* DRAM_H_ */