diff --git a/DRAMSys/library/src/common/TlmRecorder.cpp b/DRAMSys/library/src/common/TlmRecorder.cpp index c062999e..390aacf5 100644 --- a/DRAMSys/library/src/common/TlmRecorder.cpp +++ b/DRAMSys/library/src/common/TlmRecorder.cpp @@ -119,22 +119,41 @@ void TlmRecorder::recordPhase(tlm_generic_payload& trans, const tlm_phase& phase { const sc_time& currentTime = sc_time_stamp(); - if (currentTransactionsInSystem.find(&trans) == currentTransactionsInSystem.end()) - introduceTransactionSystem(trans); - - if (phase == BEGIN_REQ || phase == BEGIN_RESP) + if (phase == BEGIN_REQ) + { + introduceTransactionToSystem(trans); + std::string phaseName = getPhaseName(phase).substr(6); + currentTransactionsInSystem.at(&trans).recordedPhases.emplace_back(phaseName, currentTime + delay); + } + if (phase == BEGIN_RESP) { std::string phaseName = getPhaseName(phase).substr(6); currentTransactionsInSystem.at(&trans).recordedPhases.emplace_back(phaseName, currentTime + delay); } - else if (phase == END_REQ || phase == END_RESP) + else if (phase == END_REQ) { - assert(getPhaseName(phase).substr(4) == currentTransactionsInSystem.at(&trans).recordedPhases.back().name); - // TODO: this assumes that the controller does not start with a transaction until END_REQ has been sent, which is not true any more for big transactions + // BEGIN_REQ is always the first phase of a normal transaction + currentTransactionsInSystem.at(&trans).recordedPhases.front().interval.end = currentTime + delay; + } + else if (phase == END_RESP) + { + // BEGIN_RESP is always the last phase of a normal transaction at this point currentTransactionsInSystem.at(&trans).recordedPhases.back().interval.end = currentTime + delay; } else if (isFixedCommandPhase(phase)) { + tlm_generic_payload* keyTrans; + if (ChildExtension::isChildTrans(trans)) + { + keyTrans = &trans.get_extension()->getParentTrans(); + } + else + { + if (currentTransactionsInSystem.find(&trans) == currentTransactionsInSystem.end()) + introduceTransactionToSystem(trans); + keyTrans = &trans; + } + std::string phaseName = getPhaseName(phase).substr(6); // remove "BEGIN_" const ControllerExtension& extension = ControllerExtension::getExtension(trans); TimeInterval intervalOnDataStrobe; @@ -145,7 +164,7 @@ void TlmRecorder::recordPhase(tlm_generic_payload& trans, const tlm_phase& phase intervalOnDataStrobe.end = currentTime + intervalOnDataStrobe.end; } - currentTransactionsInSystem.at(&trans).recordedPhases.emplace_back(std::move(phaseName), + currentTransactionsInSystem.at(keyTrans).recordedPhases.emplace_back(std::move(phaseName), std::move(TimeInterval(currentTime + delay, currentTime + delay + memSpec.getExecutionTime(Command(phase), trans))), std::move(intervalOnDataStrobe), extension.getRank(), extension.getBankGroup(), extension.getBank(), @@ -181,7 +200,7 @@ void TlmRecorder::recordDebugMessage(const std::string &message, const sc_time & // ------------- internal ----------------------- -void TlmRecorder::introduceTransactionSystem(tlm_generic_payload& trans) +void TlmRecorder::introduceTransactionToSystem(tlm_generic_payload& trans) { totalNumTransactions++; diff --git a/DRAMSys/library/src/common/TlmRecorder.h b/DRAMSys/library/src/common/TlmRecorder.h index 70664e63..c11985a6 100644 --- a/DRAMSys/library/src/common/TlmRecorder.h +++ b/DRAMSys/library/src/common/TlmRecorder.h @@ -136,7 +136,7 @@ private: void openDB(const std::string &dbName); void closeConnection(); - void introduceTransactionSystem(tlm::tlm_generic_payload &trans); + void introduceTransactionToSystem(tlm::tlm_generic_payload &trans); void removeTransactionFromSystem(tlm::tlm_generic_payload &trans); void terminateRemainingTransactions(); diff --git a/DRAMSys/library/src/common/dramExtensions.cpp b/DRAMSys/library/src/common/dramExtensions.cpp index 3c486087..9bb02758 100644 --- a/DRAMSys/library/src/common/dramExtensions.cpp +++ b/DRAMSys/library/src/common/dramExtensions.cpp @@ -360,3 +360,103 @@ bool operator !=(const Column &lhs, const Column &rhs) { return !(lhs == rhs); } + + +tlm::tlm_extension_base* ChildExtension::clone() const +{ + return new ChildExtension(*parentTrans); +} + +void ChildExtension::copy_from(const tlm::tlm_extension_base& ext) +{ + const auto& cpyFrom = dynamic_cast(ext); + parentTrans = cpyFrom.parentTrans; +} + +tlm::tlm_generic_payload& ChildExtension::getParentTrans() +{ + return *parentTrans; +} + +void ChildExtension::setExtension(tlm::tlm_generic_payload& childTrans, tlm::tlm_generic_payload& parentTrans) +{ + auto* extension = childTrans.get_extension(); + + if (extension != nullptr) + { + extension->parentTrans = &parentTrans; + } + else + { + extension = new ChildExtension(parentTrans); + childTrans.set_auto_extension(extension); + } +} + +bool ChildExtension::isChildTrans(const tlm::tlm_generic_payload& trans) +{ + if (trans.get_extension() != nullptr) + return true; + else + return false; +} + +bool ChildExtension::notifyChildTransCompletion() +{ + return parentTrans->get_extension()->notifyChildTransCompletion(); +} + +tlm_extension_base* ParentExtension::clone() const +{ + return new ParentExtension(childTranses); +} + +void ParentExtension::copy_from(const tlm_extension_base& ext) +{ + const auto& cpyFrom = dynamic_cast(ext); + childTranses = cpyFrom.childTranses; +} + +bool ParentExtension::isParentTrans(const tlm::tlm_generic_payload& trans) +{ + auto* extension = trans.get_extension(); + if (extension != nullptr) + return !extension->childTranses.empty(); + else + return false; +} + +void ParentExtension::setExtension(tlm::tlm_generic_payload& parentTrans, std::vector childTranses) +{ + auto* extension = parentTrans.get_extension(); + + if (extension != nullptr) + { + extension->childTranses = std::move(childTranses); + extension->nextEndReqChildId = 0; + extension->completedChildTranses = 0; + } + else + { + extension = new ParentExtension(std::move(childTranses)); + parentTrans.set_auto_extension(extension); + } +} + +const std::vector& ParentExtension::getChildTranses() +{ + return childTranses; +} + +bool ParentExtension::notifyChildTransCompletion() +{ + completedChildTranses++; + return completedChildTranses == childTranses.size(); +} + +void ParentExtension::releaseChildTranses() +{ + std::for_each(childTranses.begin(), childTranses.end(), + [](tlm::tlm_generic_payload* childTrans){childTrans->release();}); + childTranses.clear(); +} \ No newline at end of file diff --git a/DRAMSys/library/src/common/dramExtensions.h b/DRAMSys/library/src/common/dramExtensions.h index 7f164186..76e61e8c 100644 --- a/DRAMSys/library/src/common/dramExtensions.h +++ b/DRAMSys/library/src/common/dramExtensions.h @@ -252,4 +252,42 @@ bool operator!=(const Row &lhs, const Row &rhs); bool operator==(const Column &lhs, const Column &rhs); bool operator!=(const Column &lhs, const Column &rhs); +class ChildExtension : public tlm::tlm_extension +{ +private: + tlm::tlm_generic_payload* parentTrans; + explicit ChildExtension(tlm::tlm_generic_payload& parentTrans) : parentTrans(&parentTrans) {} + +public: + //ChildExtension() = delete; + + tlm::tlm_extension_base* clone() const override; + void copy_from(const tlm::tlm_extension_base& ext) override; + tlm::tlm_generic_payload& getParentTrans(); + static void setExtension(tlm::tlm_generic_payload& childTrans, tlm::tlm_generic_payload& parentTrans); + static bool isChildTrans(const tlm::tlm_generic_payload& trans); + bool notifyChildTransCompletion(); +}; + +class ParentExtension : public tlm::tlm_extension +{ +private: + std::vector childTranses; + unsigned nextEndReqChildId = 0; + unsigned completedChildTranses = 0; + explicit ParentExtension(std::vector _childTranses) + : childTranses(std::move(_childTranses)) {} + +public: + ParentExtension() = delete; + + tlm_extension_base* clone() const override; + void copy_from(const tlm_extension_base& ext) override; + static bool isParentTrans(const tlm::tlm_generic_payload& trans); + static void setExtension(tlm::tlm_generic_payload& parentTrans, std::vector childTranses); + const std::vector& getChildTranses(); + bool notifyChildTransCompletion(); + void releaseChildTranses(); +}; + #endif // DRAMEXTENSIONS_H diff --git a/DRAMSys/library/src/controller/Controller.cpp b/DRAMSys/library/src/controller/Controller.cpp index 990958bd..b735d97f 100644 --- a/DRAMSys/library/src/controller/Controller.cpp +++ b/DRAMSys/library/src/controller/Controller.cpp @@ -72,7 +72,8 @@ using namespace tlm; Controller::Controller(const sc_module_name& name, const Configuration& config, const AddressDecoder& addressDecoder) : ControllerIF(name, config), addressDecoder(addressDecoder), thinkDelayFw(config.thinkDelayFw), thinkDelayBw(config.thinkDelayBw), - phyDelayFw(config.phyDelayFw), phyDelayBw(config.phyDelayBw) + phyDelayFw(config.phyDelayFw), phyDelayBw(config.phyDelayBw), + maxBytesPerBurst(config.memSpec->maxBytesPerBurst) { SC_METHOD(controllerMethod); sensitive << beginReqEvent << endRespEvent << controllerEvent << dataResponseEvent; @@ -370,13 +371,6 @@ tlm_sync_enum Controller::nb_transport_fw(tlm_generic_payload &trans, transToAcquire.payload = &trans; transToAcquire.time = sc_time_stamp() + delay; beginReqEvent.notify(delay); - - DecodedAddress decodedAddress = addressDecoder.decodeAddress(transToAcquire.payload->get_address()); - ControllerExtension::setAutoExtension(*transToAcquire.payload, nextChannelPayloadIDToAppend++, - Rank(decodedAddress.rank), BankGroup(decodedAddress.bankgroup), - Bank(decodedAddress.bank), Row(decodedAddress.row), - Column(decodedAddress.column), - transToAcquire.payload->get_data_length() / memSpec.bytesPerBeat); } else if (phase == END_RESP) { @@ -408,34 +402,62 @@ void Controller::manageRequests(const sc_time &delay) { if (transToAcquire.payload != nullptr && transToAcquire.time <= sc_time_stamp()) { - // Check size of transaction -// unsigned numSubTrans = transToAcquire.payload->get_data_length() / memSpec.maxBytesPerBurst; -// if (numSubTrans > 1) -// { -// // Split create child transactions -// // Address decoding!!! -// } - + // TODO: here we assume that the scheduler always has space not only for a single burst transaction but for a maximum size transaction if (scheduler->hasBufferSpace()) { - NDEBUG_UNUSED(uint64_t id) = ControllerExtension::getChannelPayloadID(*transToAcquire.payload); - PRINTDEBUGMESSAGE(name(), "Payload " + std::to_string(id) + " entered system."); + //NDEBUG_UNUSED(uint64_t id) = ControllerExtension::getChannelPayloadID(*transToAcquire.payload); + //PRINTDEBUGMESSAGE(name(), "Payload " + std::to_string(id) + " entered system."); if (totalNumberOfPayloads == 0) idleTimeCollector.end(); - totalNumberOfPayloads++; + totalNumberOfPayloads++; // seems to be ok - Rank rank = ControllerExtension::getRank(*transToAcquire.payload); - if (ranksNumberOfPayloads[rank.ID()] == 0) - powerDownManagers[rank.ID()]->triggerExit(); - - ranksNumberOfPayloads[rank.ID()]++; - - scheduler->storeRequest(*transToAcquire.payload); transToAcquire.payload->acquire(); - Bank bank = ControllerExtension::getBank(*transToAcquire.payload); - bankMachines[bank.ID()]->start(); + unsigned numChildTranses = transToAcquire.payload->get_data_length() / maxBytesPerBurst; + if (numChildTranses <= 1) + { + DecodedAddress decodedAddress = addressDecoder.decodeAddress(transToAcquire.payload->get_address()); + ControllerExtension::setAutoExtension(*transToAcquire.payload, nextChannelPayloadIDToAppend++, + Rank(decodedAddress.rank), BankGroup(decodedAddress.bankgroup), + Bank(decodedAddress.bank), Row(decodedAddress.row), + Column(decodedAddress.column), + transToAcquire.payload->get_data_length() / memSpec.bytesPerBeat); + + Rank rank = Rank(decodedAddress.rank); + if (ranksNumberOfPayloads[rank.ID()] == 0) + powerDownManagers[rank.ID()]->triggerExit(); + ranksNumberOfPayloads[rank.ID()]++; + + scheduler->storeRequest(*transToAcquire.payload); + Bank bank = Bank(decodedAddress.bank); + bankMachines[bank.ID()]->start(); + } + else + { + createChildTranses(*transToAcquire.payload, numChildTranses); + const std::vector& childTranses = + transToAcquire.payload->get_extension()->getChildTranses(); + for (auto* childTrans : childTranses) + { + DecodedAddress decodedAddress = addressDecoder.decodeAddress(childTrans->get_address()); + ControllerExtension::setAutoExtension(*childTrans, nextChannelPayloadIDToAppend, + Rank(decodedAddress.rank), BankGroup(decodedAddress.bankgroup), + Bank(decodedAddress.bank), Row(decodedAddress.row), + Column(decodedAddress.column), + childTrans->get_data_length() / memSpec.bytesPerBeat); + + Rank rank = Rank(decodedAddress.rank); + if (ranksNumberOfPayloads[rank.ID()] == 0) + powerDownManagers[rank.ID()]->triggerExit(); + ranksNumberOfPayloads[rank.ID()]++; + + scheduler->storeRequest(*childTrans); + Bank bank = Bank(decodedAddress.bank); + bankMachines[bank.ID()]->start(); + } + nextChannelPayloadIDToAppend++; + } transToAcquire.payload->set_response_status(TLM_OK_RESPONSE); tlm_phase bwPhase = END_REQ; @@ -463,7 +485,7 @@ void Controller::manageResponses() numberOfBeatsServed += ControllerExtension::getBurstLength(*transToRelease.payload); transToRelease.payload->release(); transToRelease.payload = nullptr; - totalNumberOfPayloads--; + totalNumberOfPayloads--; // Important!! has to be done once for parent transaction if (totalNumberOfPayloads == 0) { @@ -471,15 +493,42 @@ void Controller::manageResponses() } else { - transToRelease.payload = respQueue->nextPayload(); + // TODO: hier fehlt noch was + tlm_generic_payload* nextPayloadInQueue = respQueue->nextPayload(); + //transToRelease.payload = respQueue->nextPayload(); - if (transToRelease.payload != nullptr) + if (nextPayloadInQueue != nullptr) { - // last payload was released in this cycle - tlm_phase bwPhase = BEGIN_RESP; - sc_time bwDelay = memSpec.tCK; - sendToFrontend(*transToRelease.payload, bwPhase, bwDelay); - transToRelease.time = sc_max_time(); + if (ChildExtension::isChildTrans(*nextPayloadInQueue)) + { + tlm_generic_payload& parentTrans = nextPayloadInQueue->get_extension()->getParentTrans(); + bool allChildTransesCompleted = parentTrans.get_extension()->notifyChildTransCompletion(); + if (allChildTransesCompleted) + { + parentTrans.get_extension()->releaseChildTranses(); + transToRelease.payload = &parentTrans; + // last payload was released in this cycle + tlm_phase bwPhase = BEGIN_RESP; + sc_time bwDelay = memSpec.tCK; + sendToFrontend(*transToRelease.payload, bwPhase, bwDelay); + transToRelease.time = sc_max_time(); + } + else + { + sc_time triggerTime = respQueue->getTriggerTime(); + if (triggerTime != sc_max_time()) + dataResponseEvent.notify(triggerTime - sc_time_stamp()); + } + } + else + { + transToRelease.payload = nextPayloadInQueue; + // last payload was released in this cycle + tlm_phase bwPhase = BEGIN_RESP; + sc_time bwDelay = memSpec.tCK; + sendToFrontend(*transToRelease.payload, bwPhase, bwDelay); + transToRelease.time = sc_max_time(); + } } else { @@ -492,19 +541,50 @@ void Controller::manageResponses() } else { - transToRelease.payload = respQueue->nextPayload(); + tlm_generic_payload* nextPayloadInQueue = respQueue->nextPayload(); - if (transToRelease.payload != nullptr) + if (nextPayloadInQueue != nullptr) { - tlm_phase bwPhase = BEGIN_RESP; - sc_time bwDelay; - if (transToRelease.time == sc_time_stamp()) // last payload was released in this cycle - bwDelay = memSpec.tCK; - else - bwDelay = SC_ZERO_TIME; + if (ChildExtension::isChildTrans(*nextPayloadInQueue)) + { + tlm_generic_payload& parentTrans = nextPayloadInQueue->get_extension()->getParentTrans(); + bool allChildTransesCompleted = parentTrans.get_extension()->notifyChildTransCompletion(); + if (allChildTransesCompleted) + { + parentTrans.get_extension()->releaseChildTranses(); + transToRelease.payload = &parentTrans; + // last payload was released in this cycle + tlm_phase bwPhase = BEGIN_RESP; + sc_time bwDelay; + if (transToRelease.time == sc_time_stamp()) // last payload was released in this cycle + bwDelay = memSpec.tCK; + else + bwDelay = SC_ZERO_TIME; - sendToFrontend(*transToRelease.payload, bwPhase, bwDelay); - transToRelease.time = sc_max_time(); + sendToFrontend(*transToRelease.payload, bwPhase, bwDelay); + transToRelease.time = sc_max_time(); + } + else + { + sc_time triggerTime = respQueue->getTriggerTime(); + if (triggerTime != sc_max_time()) + dataResponseEvent.notify(triggerTime - sc_time_stamp()); + } + } + else + { + transToRelease.payload = nextPayloadInQueue; + // last payload was released in this cycle + tlm_phase bwPhase = BEGIN_RESP; + sc_time bwDelay; + if (transToRelease.time == sc_time_stamp()) // last payload was released in this cycle + bwDelay = memSpec.tCK; + else + bwDelay = SC_ZERO_TIME; + + sendToFrontend(*transToRelease.payload, bwPhase, bwDelay); + transToRelease.time = sc_max_time(); + } } else { @@ -519,3 +599,52 @@ void Controller::sendToFrontend(tlm_generic_payload& payload, tlm_phase& phase, { tSocket->nb_transport_bw(payload, phase, delay); } + +Controller::MemoryManager::~MemoryManager() +{ + while (!freePayloads.empty()) + { + tlm_generic_payload* payload = freePayloads.top(); + freePayloads.pop(); + payload->reset(); + delete payload; + } + +} + +tlm::tlm_generic_payload& Controller::MemoryManager::allocate() +{ + if (freePayloads.empty()) + { + return *new tlm_generic_payload(this); + } + else + { + tlm_generic_payload* result = freePayloads.top(); + freePayloads.pop(); + return *result; + } +} + +void Controller::MemoryManager::free(tlm::tlm_generic_payload* payload) +{ + freePayloads.push(payload); +} + +void Controller::createChildTranses(tlm::tlm_generic_payload& parentTrans, unsigned int numChildTranses) +{ + std::vector childTranses; + + for (unsigned childId = 0; childId < numChildTranses; childId++) + { + tlm_generic_payload& childTrans = memoryManager.allocate(); + childTrans.acquire(); + childTrans.set_command(parentTrans.get_command()); + childTrans.set_address(parentTrans.get_address() + childId * maxBytesPerBurst); + childTrans.set_data_length(maxBytesPerBurst); + childTrans.set_data_ptr(parentTrans.get_data_ptr() + childId * maxBytesPerBurst); + ChildExtension::setExtension(childTrans, parentTrans); + childTranses.push_back(&childTrans); + } + ParentExtension::setExtension(parentTrans, std::move(childTranses)); +} \ No newline at end of file diff --git a/DRAMSys/library/src/controller/Controller.h b/DRAMSys/library/src/controller/Controller.h index e8339bc7..2432099d 100644 --- a/DRAMSys/library/src/controller/Controller.h +++ b/DRAMSys/library/src/controller/Controller.h @@ -37,6 +37,7 @@ #include +#include #include #include @@ -100,6 +101,21 @@ private: void manageRequests(const sc_core::sc_time &delay); sc_core::sc_event beginReqEvent, endRespEvent, controllerEvent, dataResponseEvent; + + const unsigned maxBytesPerBurst; + + void createChildTranses(tlm::tlm_generic_payload& parentTrans, unsigned numChildTranses); + + class MemoryManager : public tlm::tlm_mm_interface + { + public: + ~MemoryManager() override; + tlm::tlm_generic_payload& allocate(); + void free(tlm::tlm_generic_payload* payload) override; + + private: + std::stack freePayloads; + } memoryManager; }; #endif // CONTROLLER_H