/* * dram.h * * Created on: Mar 16, 2014 * Author: robert */ #ifndef DRAM_H_ #define DRAM_H_ #include #include #include #include #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 struct Dram: sc_module { tlm_utils::simple_target_socket 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_ */