211 lines
7.4 KiB
C++
211 lines
7.4 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/LibDRAMPower.h"
|
|
#include "../common/third_party/DRAMPower/src/xmlparser/MemSpecParser.h"
|
|
#include "../common/third_party/DRAMPower/src/MemorySpecification.h"
|
|
#include "../common/third_party/DRAMPower/src/MemCommand.h"
|
|
|
|
using namespace std;
|
|
using namespace tlm;
|
|
using namespace Data;
|
|
|
|
|
|
//#define POWER
|
|
//not better to define in simulation xml? also flag for storage simulation
|
|
//configuration->PowerAnalysys
|
|
//configuration->ModelStorage
|
|
//configuration->ModelErrotInjection
|
|
|
|
#ifdef POWER
|
|
#define IFPOW(x) x
|
|
#else
|
|
#define IFPOW(x)
|
|
#endif
|
|
|
|
|
|
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;
|
|
IFPOW(libDRAMPower *DRAMPower);
|
|
|
|
map< unsigned long int, unsigned char[BUSWIDTH/2] > memory;
|
|
|
|
SC_CTOR(Dram) : tSocket("socket")
|
|
{
|
|
tSocket.register_nb_transport_fw(this, &Dram::nb_transport_fw);
|
|
|
|
IFPOW( MemorySpecification memSpec(MemSpecParser::getMemSpecFromXML(Configuration::getInstance().memspecUri)) );
|
|
IFPOW( DRAMPower = new libDRAMPower( memSpec, 0 ) );
|
|
}
|
|
|
|
~Dram()
|
|
{
|
|
IFPOW( DRAMPower->updateCounters(true));
|
|
IFPOW( DRAMPower->calcEnergy() );
|
|
IFPOW( cout << endl << endl << "Total Energy" << "\t" << DRAMPower->getEnergy().total_energy << endl);
|
|
IFPOW( cout << "Average Power" << "\t" << DRAMPower->getPower().average_power << endl );
|
|
std::cout << "Simulated Memory Size: " << memory.size() << 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().memSpec.clk.value();
|
|
unsigned int bank = DramExtension::getExtension(payload).getBank().ID();
|
|
|
|
if (phase == BEGIN_PRE)
|
|
{
|
|
IFPOW(DRAMPower->doCommand(MemCommand::PRE, bank, cycle));
|
|
sendToController(payload, END_PRE, delay + getExecutionTime(Command::Precharge, payload));
|
|
}
|
|
else if (phase == BEGIN_PRE_ALL)
|
|
{
|
|
IFPOW(DRAMPower->doCommand(MemCommand::PREA, bank, cycle));
|
|
sendToController(payload, END_PRE_ALL,delay + getExecutionTime(Command::PrechargeAll, payload));
|
|
}
|
|
else if (phase == BEGIN_ACT)
|
|
{
|
|
IFPOW(DRAMPower->doCommand(MemCommand::ACT, bank, cycle));
|
|
sendToController(payload, END_ACT, delay + getExecutionTime(Command::Activate, payload));
|
|
}
|
|
else if (phase == BEGIN_WR)
|
|
{
|
|
IFPOW(DRAMPower->doCommand(MemCommand::WR, bank, cycle));
|
|
//save data:
|
|
memcpy(&memory[payload.get_address()], payload.get_data_ptr(), BUSWIDTH/8);
|
|
sendToController(payload, END_WR, delay + getExecutionTime(Command::Write, payload));
|
|
}
|
|
else if (phase == BEGIN_RD)
|
|
{
|
|
IFPOW(DRAMPower->doCommand(MemCommand::RD, bank, cycle));
|
|
sendToController(payload, END_RD, delay + getExecutionTime(Command::Read, payload));
|
|
|
|
// Load data:
|
|
if(memory.count(payload.get_address()) == 1)
|
|
{
|
|
memcpy(payload.get_data_ptr(), &memory[payload.get_address()], BUSWIDTH/8);
|
|
}
|
|
else
|
|
{
|
|
//SC_REPORT_WARNING ("DRAM", "Reading from an empty memory location.");
|
|
}
|
|
}
|
|
else if (phase == BEGIN_WRA)
|
|
{
|
|
IFPOW(DRAMPower->doCommand(MemCommand::WRA, bank, cycle));
|
|
sendToController(payload, END_WRA, delay + getExecutionTime(Command::WriteA, payload));
|
|
}
|
|
else if (phase == BEGIN_RDA)
|
|
{
|
|
IFPOW(DRAMPower->doCommand(MemCommand::RDA, bank, cycle));
|
|
sendToController(payload, END_RDA, delay + getExecutionTime(Command::ReadA, payload));
|
|
}
|
|
else if (phase == BEGIN_REFA)
|
|
{
|
|
IFPOW(DRAMPower->doCommand(MemCommand::REF, bank, cycle));
|
|
sendToController(payload, END_REFA, delay + getExecutionTime(Command::AutoRefresh, payload));
|
|
}
|
|
|
|
else if (phase == BEGIN_REFB)
|
|
{
|
|
IFPOW( SC_REPORT_FATAL("DRAM", "Power calculation for bankwise logic not supported") );
|
|
sendToController(payload, END_REFB, 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_PDNA)
|
|
{
|
|
IFPOW(DRAMPower->doCommand(MemCommand::PDN_S_ACT, bank, cycle));
|
|
}
|
|
else if (phase == END_PDNA)
|
|
{
|
|
IFPOW(DRAMPower->doCommand(MemCommand::PUP_ACT, bank, cycle));
|
|
}
|
|
else if (phase == BEGIN_PDNAB)
|
|
{
|
|
IFPOW(SC_REPORT_FATAL("DRAM", "Power calculation for bankwise logic not supported"));
|
|
}
|
|
else if (phase == END_PDNAB)
|
|
{
|
|
IFPOW(SC_REPORT_FATAL("DRAM", "Power calculation for bankwise logic not supported"));
|
|
}
|
|
else if (phase == BEGIN_PDNP)
|
|
{
|
|
IFPOW(DRAMPower->doCommand(MemCommand::PDN_S_PRE, bank, cycle));
|
|
}
|
|
else if (phase == END_PDNP)
|
|
{
|
|
IFPOW(DRAMPower->doCommand(MemCommand::PUP_PRE, bank, cycle));
|
|
}
|
|
else if (phase == BEGIN_PDNPB)
|
|
{
|
|
IFPOW(SC_REPORT_FATAL("DRAM", "Power calculation for bankwise logic not supported"));
|
|
}
|
|
else if (phase == END_PDNPB)
|
|
{
|
|
IFPOW(SC_REPORT_FATAL("DRAM", "Power calculation for bankwise logic not supported"));
|
|
}
|
|
else if (phase == BEGIN_SREF)
|
|
{
|
|
IFPOW(DRAMPower->doCommand(MemCommand::SREN, bank, cycle));
|
|
}
|
|
else if (phase == END_SREF)
|
|
{
|
|
IFPOW(DRAMPower->doCommand(MemCommand::SREX, bank, cycle));
|
|
}
|
|
else if (phase == BEGIN_SREFB)
|
|
{
|
|
IFPOW(SC_REPORT_FATAL("DRAM", "Power calculation for bankwise logic not supported"));
|
|
}
|
|
else if (phase == END_SREFB)
|
|
{
|
|
IFPOW(SC_REPORT_FATAL("DRAM", "Power calculation for bankwise logic not supported"));
|
|
}
|
|
else
|
|
{
|
|
IFPOW(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_ */
|