111308Santhony.gutierrez@amd.com/* 211308Santhony.gutierrez@amd.com * Copyright (c) 2014-2015 Advanced Micro Devices, Inc. 311308Santhony.gutierrez@amd.com * All rights reserved. 411308Santhony.gutierrez@amd.com * 511308Santhony.gutierrez@amd.com * For use for simulation and test purposes only 611308Santhony.gutierrez@amd.com * 711308Santhony.gutierrez@amd.com * Redistribution and use in source and binary forms, with or without 811308Santhony.gutierrez@amd.com * modification, are permitted provided that the following conditions are met: 911308Santhony.gutierrez@amd.com * 1011308Santhony.gutierrez@amd.com * 1. Redistributions of source code must retain the above copyright notice, 1111308Santhony.gutierrez@amd.com * this list of conditions and the following disclaimer. 1211308Santhony.gutierrez@amd.com * 1311308Santhony.gutierrez@amd.com * 2. Redistributions in binary form must reproduce the above copyright notice, 1411308Santhony.gutierrez@amd.com * this list of conditions and the following disclaimer in the documentation 1511308Santhony.gutierrez@amd.com * and/or other materials provided with the distribution. 1611308Santhony.gutierrez@amd.com * 1712697Santhony.gutierrez@amd.com * 3. Neither the name of the copyright holder nor the names of its 1812697Santhony.gutierrez@amd.com * contributors may be used to endorse or promote products derived from this 1912697Santhony.gutierrez@amd.com * software without specific prior written permission. 2011308Santhony.gutierrez@amd.com * 2111308Santhony.gutierrez@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2211308Santhony.gutierrez@amd.com * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2311308Santhony.gutierrez@amd.com * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2411308Santhony.gutierrez@amd.com * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 2511308Santhony.gutierrez@amd.com * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2611308Santhony.gutierrez@amd.com * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2711308Santhony.gutierrez@amd.com * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2811308Santhony.gutierrez@amd.com * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2911308Santhony.gutierrez@amd.com * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3011308Santhony.gutierrez@amd.com * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3111308Santhony.gutierrez@amd.com * POSSIBILITY OF SUCH DAMAGE. 3211308Santhony.gutierrez@amd.com * 3312697Santhony.gutierrez@amd.com * Authors: John Kalamatianos, 3412697Santhony.gutierrez@amd.com * Joe Gross 3511308Santhony.gutierrez@amd.com */ 3611308Santhony.gutierrez@amd.com 3711308Santhony.gutierrez@amd.com#ifndef __LDS_STATE_HH__ 3811308Santhony.gutierrez@amd.com#define __LDS_STATE_HH__ 3911308Santhony.gutierrez@amd.com 4011308Santhony.gutierrez@amd.com#include <array> 4111308Santhony.gutierrez@amd.com#include <queue> 4211308Santhony.gutierrez@amd.com#include <string> 4311308Santhony.gutierrez@amd.com#include <unordered_map> 4411308Santhony.gutierrez@amd.com#include <utility> 4511308Santhony.gutierrez@amd.com#include <vector> 4611308Santhony.gutierrez@amd.com 4711308Santhony.gutierrez@amd.com#include "enums/MemType.hh" 4811308Santhony.gutierrez@amd.com#include "gpu-compute/misc.hh" 4911308Santhony.gutierrez@amd.com#include "mem/port.hh" 5011308Santhony.gutierrez@amd.com#include "params/LdsState.hh" 5113892Sgabeblack@google.com#include "sim/clocked_object.hh" 5211308Santhony.gutierrez@amd.com 5311308Santhony.gutierrez@amd.comclass ComputeUnit; 5411308Santhony.gutierrez@amd.com 5511308Santhony.gutierrez@amd.com/** 5611308Santhony.gutierrez@amd.com * this represents a slice of the overall LDS, intended to be associated with an 5711308Santhony.gutierrez@amd.com * individual workgroup 5811308Santhony.gutierrez@amd.com */ 5911308Santhony.gutierrez@amd.comclass LdsChunk 6011308Santhony.gutierrez@amd.com{ 6111308Santhony.gutierrez@amd.com public: 6211308Santhony.gutierrez@amd.com LdsChunk(const uint32_t x_size): 6311308Santhony.gutierrez@amd.com chunk(x_size) 6411308Santhony.gutierrez@amd.com { 6511308Santhony.gutierrez@amd.com } 6611308Santhony.gutierrez@amd.com 6711308Santhony.gutierrez@amd.com LdsChunk() {} 6811308Santhony.gutierrez@amd.com 6911308Santhony.gutierrez@amd.com /** 7011308Santhony.gutierrez@amd.com * a read operation 7111308Santhony.gutierrez@amd.com */ 7211308Santhony.gutierrez@amd.com template<class T> 7311308Santhony.gutierrez@amd.com T 7411308Santhony.gutierrez@amd.com read(const uint32_t index) 7511308Santhony.gutierrez@amd.com { 7611308Santhony.gutierrez@amd.com fatal_if(!chunk.size(), "cannot read from an LDS chunk of size 0"); 7711308Santhony.gutierrez@amd.com fatal_if(index >= chunk.size(), "out-of-bounds access to an LDS chunk"); 7811308Santhony.gutierrez@amd.com T *p0 = (T *) (&(chunk.at(index))); 7911308Santhony.gutierrez@amd.com return *p0; 8011308Santhony.gutierrez@amd.com } 8111308Santhony.gutierrez@amd.com 8211308Santhony.gutierrez@amd.com /** 8311308Santhony.gutierrez@amd.com * a write operation 8411308Santhony.gutierrez@amd.com */ 8511308Santhony.gutierrez@amd.com template<class T> 8611308Santhony.gutierrez@amd.com void 8711308Santhony.gutierrez@amd.com write(const uint32_t index, const T value) 8811308Santhony.gutierrez@amd.com { 8911308Santhony.gutierrez@amd.com fatal_if(!chunk.size(), "cannot write to an LDS chunk of size 0"); 9011308Santhony.gutierrez@amd.com fatal_if(index >= chunk.size(), "out-of-bounds access to an LDS chunk"); 9111308Santhony.gutierrez@amd.com T *p0 = (T *) (&(chunk.at(index))); 9211308Santhony.gutierrez@amd.com *p0 = value; 9311308Santhony.gutierrez@amd.com } 9411308Santhony.gutierrez@amd.com 9511308Santhony.gutierrez@amd.com /** 9611308Santhony.gutierrez@amd.com * get the size of this chunk 9711308Santhony.gutierrez@amd.com */ 9811308Santhony.gutierrez@amd.com std::vector<uint8_t>::size_type 9911308Santhony.gutierrez@amd.com size() const 10011308Santhony.gutierrez@amd.com { 10111308Santhony.gutierrez@amd.com return chunk.size(); 10211308Santhony.gutierrez@amd.com } 10311308Santhony.gutierrez@amd.com 10411308Santhony.gutierrez@amd.com protected: 10511308Santhony.gutierrez@amd.com // the actual data store for this slice of the LDS 10611308Santhony.gutierrez@amd.com std::vector<uint8_t> chunk; 10711308Santhony.gutierrez@amd.com}; 10811308Santhony.gutierrez@amd.com 10911308Santhony.gutierrez@amd.com// Local Data Share (LDS) State per Wavefront (contents of the LDS region 11011308Santhony.gutierrez@amd.com// allocated to the WorkGroup of this Wavefront) 11113892Sgabeblack@google.comclass LdsState: public ClockedObject 11211308Santhony.gutierrez@amd.com{ 11311308Santhony.gutierrez@amd.com protected: 11411308Santhony.gutierrez@amd.com 11511308Santhony.gutierrez@amd.com /** 11611308Santhony.gutierrez@amd.com * an event to allow event-driven execution 11711308Santhony.gutierrez@amd.com */ 11811308Santhony.gutierrez@amd.com class TickEvent: public Event 11911308Santhony.gutierrez@amd.com { 12011308Santhony.gutierrez@amd.com protected: 12111308Santhony.gutierrez@amd.com 12211308Santhony.gutierrez@amd.com LdsState *ldsState = nullptr; 12311308Santhony.gutierrez@amd.com 12411308Santhony.gutierrez@amd.com Tick nextTick = 0; 12511308Santhony.gutierrez@amd.com 12611308Santhony.gutierrez@amd.com public: 12711308Santhony.gutierrez@amd.com 12811308Santhony.gutierrez@amd.com TickEvent(LdsState *_ldsState) : 12911308Santhony.gutierrez@amd.com ldsState(_ldsState) 13011308Santhony.gutierrez@amd.com { 13111308Santhony.gutierrez@amd.com } 13211308Santhony.gutierrez@amd.com 13311308Santhony.gutierrez@amd.com virtual void 13411308Santhony.gutierrez@amd.com process(); 13511308Santhony.gutierrez@amd.com 13611308Santhony.gutierrez@amd.com void 13711308Santhony.gutierrez@amd.com schedule(Tick when) 13811308Santhony.gutierrez@amd.com { 13911308Santhony.gutierrez@amd.com mainEventQueue[0]->schedule(this, when); 14011308Santhony.gutierrez@amd.com } 14111308Santhony.gutierrez@amd.com 14211308Santhony.gutierrez@amd.com void 14311308Santhony.gutierrez@amd.com deschedule() 14411308Santhony.gutierrez@amd.com { 14511308Santhony.gutierrez@amd.com mainEventQueue[0]->deschedule(this); 14611308Santhony.gutierrez@amd.com } 14711308Santhony.gutierrez@amd.com }; 14811308Santhony.gutierrez@amd.com 14911308Santhony.gutierrez@amd.com /** 15011308Santhony.gutierrez@amd.com * CuSidePort is the LDS Port closer to the CU side 15111308Santhony.gutierrez@amd.com */ 15211308Santhony.gutierrez@amd.com class CuSidePort: public SlavePort 15311308Santhony.gutierrez@amd.com { 15411308Santhony.gutierrez@amd.com public: 15511308Santhony.gutierrez@amd.com CuSidePort(const std::string &_name, LdsState *_ownerLds) : 15611308Santhony.gutierrez@amd.com SlavePort(_name, _ownerLds), ownerLds(_ownerLds) 15711308Santhony.gutierrez@amd.com { 15811308Santhony.gutierrez@amd.com } 15911308Santhony.gutierrez@amd.com 16011308Santhony.gutierrez@amd.com protected: 16111308Santhony.gutierrez@amd.com LdsState *ownerLds; 16211308Santhony.gutierrez@amd.com 16311308Santhony.gutierrez@amd.com virtual bool 16411308Santhony.gutierrez@amd.com recvTimingReq(PacketPtr pkt); 16511308Santhony.gutierrez@amd.com 16611308Santhony.gutierrez@amd.com virtual Tick 16711308Santhony.gutierrez@amd.com recvAtomic(PacketPtr pkt) 16811308Santhony.gutierrez@amd.com { 16911308Santhony.gutierrez@amd.com return 0; 17011308Santhony.gutierrez@amd.com } 17111308Santhony.gutierrez@amd.com 17211308Santhony.gutierrez@amd.com virtual void 17311308Santhony.gutierrez@amd.com recvFunctional(PacketPtr pkt); 17411308Santhony.gutierrez@amd.com 17511308Santhony.gutierrez@amd.com virtual void 17611308Santhony.gutierrez@amd.com recvRangeChange() 17711308Santhony.gutierrez@amd.com { 17811308Santhony.gutierrez@amd.com } 17911308Santhony.gutierrez@amd.com 18011308Santhony.gutierrez@amd.com virtual void 18111308Santhony.gutierrez@amd.com recvRetry(); 18211308Santhony.gutierrez@amd.com 18311308Santhony.gutierrez@amd.com virtual void 18411308Santhony.gutierrez@amd.com recvRespRetry(); 18511308Santhony.gutierrez@amd.com 18611308Santhony.gutierrez@amd.com virtual AddrRangeList 18711308Santhony.gutierrez@amd.com getAddrRanges() const 18811308Santhony.gutierrez@amd.com { 18911308Santhony.gutierrez@amd.com AddrRangeList ranges; 19011308Santhony.gutierrez@amd.com ranges.push_back(ownerLds->getAddrRange()); 19111308Santhony.gutierrez@amd.com return ranges; 19211308Santhony.gutierrez@amd.com } 19311308Santhony.gutierrez@amd.com 19411308Santhony.gutierrez@amd.com template<typename T> 19511308Santhony.gutierrez@amd.com void 19611308Santhony.gutierrez@amd.com loadData(PacketPtr packet); 19711308Santhony.gutierrez@amd.com 19811308Santhony.gutierrez@amd.com template<typename T> 19911308Santhony.gutierrez@amd.com void 20011308Santhony.gutierrez@amd.com storeData(PacketPtr packet); 20111308Santhony.gutierrez@amd.com 20211308Santhony.gutierrez@amd.com template<typename T> 20311308Santhony.gutierrez@amd.com void 20411308Santhony.gutierrez@amd.com atomicOperation(PacketPtr packet); 20511308Santhony.gutierrez@amd.com }; 20611308Santhony.gutierrez@amd.com 20711308Santhony.gutierrez@amd.com protected: 20811308Santhony.gutierrez@amd.com 20911308Santhony.gutierrez@amd.com // the lds reference counter 21011308Santhony.gutierrez@amd.com // The key is the workgroup ID and dispatch ID 21111308Santhony.gutierrez@amd.com // The value is the number of wavefronts that reference this LDS, as 21211308Santhony.gutierrez@amd.com // wavefronts are launched, the counter goes up for that workgroup and when 21311308Santhony.gutierrez@amd.com // they return it decreases, once it reaches 0 then this chunk of the LDS is 21411308Santhony.gutierrez@amd.com // returned to the available pool. However,it is deallocated on the 1->0 21511308Santhony.gutierrez@amd.com // transition, not whenever the counter is 0 as it always starts with 0 when 21611308Santhony.gutierrez@amd.com // the workgroup asks for space 21711308Santhony.gutierrez@amd.com std::unordered_map<uint32_t, 21811308Santhony.gutierrez@amd.com std::unordered_map<uint32_t, int32_t>> refCounter; 21911308Santhony.gutierrez@amd.com 22011308Santhony.gutierrez@amd.com // the map that allows workgroups to access their own chunk of the LDS 22111308Santhony.gutierrez@amd.com std::unordered_map<uint32_t, 22211308Santhony.gutierrez@amd.com std::unordered_map<uint32_t, LdsChunk>> chunkMap; 22311308Santhony.gutierrez@amd.com 22411308Santhony.gutierrez@amd.com // an event to allow the LDS to wake up at a specified time 22511308Santhony.gutierrez@amd.com TickEvent tickEvent; 22611308Santhony.gutierrez@amd.com 22711308Santhony.gutierrez@amd.com // the queue of packets that are going back to the CU after a 22811308Santhony.gutierrez@amd.com // read/write/atomic op 22911308Santhony.gutierrez@amd.com // TODO need to make this have a maximum size to create flow control 23011308Santhony.gutierrez@amd.com std::queue<std::pair<Tick, PacketPtr>> returnQueue; 23111308Santhony.gutierrez@amd.com 23211308Santhony.gutierrez@amd.com // whether or not there are pending responses 23311308Santhony.gutierrez@amd.com bool retryResp = false; 23411308Santhony.gutierrez@amd.com 23511308Santhony.gutierrez@amd.com bool 23611308Santhony.gutierrez@amd.com process(); 23711308Santhony.gutierrez@amd.com 23811308Santhony.gutierrez@amd.com GPUDynInstPtr 23911308Santhony.gutierrez@amd.com getDynInstr(PacketPtr packet); 24011308Santhony.gutierrez@amd.com 24111308Santhony.gutierrez@amd.com bool 24211308Santhony.gutierrez@amd.com processPacket(PacketPtr packet); 24311308Santhony.gutierrez@amd.com 24411308Santhony.gutierrez@amd.com unsigned 24511308Santhony.gutierrez@amd.com countBankConflicts(PacketPtr packet, unsigned *bankAccesses); 24611308Santhony.gutierrez@amd.com 24711308Santhony.gutierrez@amd.com unsigned 24811308Santhony.gutierrez@amd.com countBankConflicts(GPUDynInstPtr gpuDynInst, 24911308Santhony.gutierrez@amd.com unsigned *numBankAccesses); 25011308Santhony.gutierrez@amd.com 25111308Santhony.gutierrez@amd.com public: 25211308Santhony.gutierrez@amd.com typedef LdsStateParams Params; 25311308Santhony.gutierrez@amd.com 25411308Santhony.gutierrez@amd.com LdsState(const Params *params); 25511308Santhony.gutierrez@amd.com 25611308Santhony.gutierrez@amd.com // prevent copy construction 25711308Santhony.gutierrez@amd.com LdsState(const LdsState&) = delete; 25811308Santhony.gutierrez@amd.com 25911308Santhony.gutierrez@amd.com ~LdsState() 26011308Santhony.gutierrez@amd.com { 26111308Santhony.gutierrez@amd.com parent = nullptr; 26211308Santhony.gutierrez@amd.com } 26311308Santhony.gutierrez@amd.com 26411308Santhony.gutierrez@amd.com const Params * 26511308Santhony.gutierrez@amd.com params() const 26611308Santhony.gutierrez@amd.com { 26711308Santhony.gutierrez@amd.com return dynamic_cast<const Params *>(_params); 26811308Santhony.gutierrez@amd.com } 26911308Santhony.gutierrez@amd.com 27011308Santhony.gutierrez@amd.com bool 27111308Santhony.gutierrez@amd.com isRetryResp() const 27211308Santhony.gutierrez@amd.com { 27311308Santhony.gutierrez@amd.com return retryResp; 27411308Santhony.gutierrez@amd.com } 27511308Santhony.gutierrez@amd.com 27611308Santhony.gutierrez@amd.com void 27711308Santhony.gutierrez@amd.com setRetryResp(const bool value) 27811308Santhony.gutierrez@amd.com { 27911308Santhony.gutierrez@amd.com retryResp = value; 28011308Santhony.gutierrez@amd.com } 28111308Santhony.gutierrez@amd.com 28211308Santhony.gutierrez@amd.com // prevent assignment 28311308Santhony.gutierrez@amd.com LdsState & 28411308Santhony.gutierrez@amd.com operator=(const LdsState &) = delete; 28511308Santhony.gutierrez@amd.com 28611308Santhony.gutierrez@amd.com /** 28711308Santhony.gutierrez@amd.com * use the dynamic wave id to create or just increase the reference count 28811308Santhony.gutierrez@amd.com */ 28911308Santhony.gutierrez@amd.com int 29011308Santhony.gutierrez@amd.com increaseRefCounter(const uint32_t dispatchId, const uint32_t wgId) 29111308Santhony.gutierrez@amd.com { 29211308Santhony.gutierrez@amd.com int refCount = getRefCounter(dispatchId, wgId); 29311308Santhony.gutierrez@amd.com fatal_if(refCount < 0, 29411308Santhony.gutierrez@amd.com "reference count should not be below zero"); 29511308Santhony.gutierrez@amd.com return ++refCounter[dispatchId][wgId]; 29611308Santhony.gutierrez@amd.com } 29711308Santhony.gutierrez@amd.com 29811308Santhony.gutierrez@amd.com /** 29911308Santhony.gutierrez@amd.com * decrease the reference count after making sure it is in the list 30011308Santhony.gutierrez@amd.com * give back this chunk if the ref counter has reached 0 30111308Santhony.gutierrez@amd.com */ 30211308Santhony.gutierrez@amd.com int 30311308Santhony.gutierrez@amd.com decreaseRefCounter(const uint32_t dispatchId, const uint32_t wgId) 30411308Santhony.gutierrez@amd.com { 30511308Santhony.gutierrez@amd.com int refCount = getRefCounter(dispatchId, wgId); 30611308Santhony.gutierrez@amd.com 30711308Santhony.gutierrez@amd.com fatal_if(refCount <= 0, 30811308Santhony.gutierrez@amd.com "reference count should not be below zero or at zero to" 30911308Santhony.gutierrez@amd.com "decrement"); 31011308Santhony.gutierrez@amd.com 31111308Santhony.gutierrez@amd.com refCounter[dispatchId][wgId]--; 31211308Santhony.gutierrez@amd.com 31311308Santhony.gutierrez@amd.com if (refCounter[dispatchId][wgId] == 0) { 31411308Santhony.gutierrez@amd.com releaseSpace(dispatchId, wgId); 31511308Santhony.gutierrez@amd.com return 0; 31611308Santhony.gutierrez@amd.com } else { 31711308Santhony.gutierrez@amd.com return refCounter[dispatchId][wgId]; 31811308Santhony.gutierrez@amd.com } 31911308Santhony.gutierrez@amd.com } 32011308Santhony.gutierrez@amd.com 32111308Santhony.gutierrez@amd.com /** 32211308Santhony.gutierrez@amd.com * return the current reference count for this workgroup id 32311308Santhony.gutierrez@amd.com */ 32411308Santhony.gutierrez@amd.com int 32511308Santhony.gutierrez@amd.com getRefCounter(const uint32_t dispatchId, const uint32_t wgId) const 32611308Santhony.gutierrez@amd.com { 32711308Santhony.gutierrez@amd.com auto dispatchIter = chunkMap.find(dispatchId); 32811308Santhony.gutierrez@amd.com fatal_if(dispatchIter == chunkMap.end(), 32911308Santhony.gutierrez@amd.com "could not locate this dispatch id [%d]", dispatchId); 33011308Santhony.gutierrez@amd.com 33111308Santhony.gutierrez@amd.com auto workgroup = dispatchIter->second.find(wgId); 33211308Santhony.gutierrez@amd.com fatal_if(workgroup == dispatchIter->second.end(), 33311308Santhony.gutierrez@amd.com "could not find this workgroup id within this dispatch id" 33411308Santhony.gutierrez@amd.com " did[%d] wgid[%d]", dispatchId, wgId); 33511308Santhony.gutierrez@amd.com 33611308Santhony.gutierrez@amd.com auto refCountIter = refCounter.find(dispatchId); 33711308Santhony.gutierrez@amd.com if (refCountIter == refCounter.end()) { 33811308Santhony.gutierrez@amd.com fatal("could not locate this dispatch id [%d]", dispatchId); 33911308Santhony.gutierrez@amd.com } else { 34011308Santhony.gutierrez@amd.com auto workgroup = refCountIter->second.find(wgId); 34111308Santhony.gutierrez@amd.com if (workgroup == refCountIter->second.end()) { 34211308Santhony.gutierrez@amd.com fatal("could not find this workgroup id within this dispatch id" 34311308Santhony.gutierrez@amd.com " did[%d] wgid[%d]", dispatchId, wgId); 34411308Santhony.gutierrez@amd.com } else { 34511308Santhony.gutierrez@amd.com return refCounter.at(dispatchId).at(wgId); 34611308Santhony.gutierrez@amd.com } 34711308Santhony.gutierrez@amd.com } 34811308Santhony.gutierrez@amd.com 34911308Santhony.gutierrez@amd.com fatal("should not reach this point"); 35011308Santhony.gutierrez@amd.com return 0; 35111308Santhony.gutierrez@amd.com } 35211308Santhony.gutierrez@amd.com 35311308Santhony.gutierrez@amd.com /** 35411308Santhony.gutierrez@amd.com * assign a parent and request this amount of space be set aside 35511308Santhony.gutierrez@amd.com * for this wgid 35611308Santhony.gutierrez@amd.com */ 35711308Santhony.gutierrez@amd.com LdsChunk * 35811308Santhony.gutierrez@amd.com reserveSpace(const uint32_t dispatchId, const uint32_t wgId, 35911308Santhony.gutierrez@amd.com const uint32_t size) 36011308Santhony.gutierrez@amd.com { 36111308Santhony.gutierrez@amd.com if (chunkMap.find(dispatchId) != chunkMap.end()) { 36211308Santhony.gutierrez@amd.com fatal_if( 36311308Santhony.gutierrez@amd.com chunkMap[dispatchId].find(wgId) != chunkMap[dispatchId].end(), 36411308Santhony.gutierrez@amd.com "duplicate workgroup ID asking for space in the LDS " 36511308Santhony.gutierrez@amd.com "did[%d] wgid[%d]", dispatchId, wgId); 36611308Santhony.gutierrez@amd.com } 36711308Santhony.gutierrez@amd.com 36811308Santhony.gutierrez@amd.com fatal_if(bytesAllocated + size > maximumSize, 36911308Santhony.gutierrez@amd.com "request would ask for more space than is available"); 37011308Santhony.gutierrez@amd.com 37111308Santhony.gutierrez@amd.com bytesAllocated += size; 37211308Santhony.gutierrez@amd.com 37311308Santhony.gutierrez@amd.com chunkMap[dispatchId].emplace(wgId, LdsChunk(size)); 37411308Santhony.gutierrez@amd.com // make an entry for this workgroup 37511308Santhony.gutierrez@amd.com refCounter[dispatchId][wgId] = 0; 37611308Santhony.gutierrez@amd.com 37711308Santhony.gutierrez@amd.com return &chunkMap[dispatchId][wgId]; 37811308Santhony.gutierrez@amd.com } 37911308Santhony.gutierrez@amd.com 38011308Santhony.gutierrez@amd.com bool 38111308Santhony.gutierrez@amd.com returnQueuePush(std::pair<Tick, PacketPtr> thePair); 38211308Santhony.gutierrez@amd.com 38311308Santhony.gutierrez@amd.com Tick 38411308Santhony.gutierrez@amd.com earliestReturnTime() const 38511308Santhony.gutierrez@amd.com { 38611308Santhony.gutierrez@amd.com // TODO set to max(lastCommand+1, curTick()) 38711308Santhony.gutierrez@amd.com return returnQueue.empty() ? curTick() : returnQueue.back().first; 38811308Santhony.gutierrez@amd.com } 38911308Santhony.gutierrez@amd.com 39011308Santhony.gutierrez@amd.com void 39111308Santhony.gutierrez@amd.com setParent(ComputeUnit *x_parent); 39211308Santhony.gutierrez@amd.com 39311308Santhony.gutierrez@amd.com // accessors 39411308Santhony.gutierrez@amd.com ComputeUnit * 39511308Santhony.gutierrez@amd.com getParent() const 39611308Santhony.gutierrez@amd.com { 39711308Santhony.gutierrez@amd.com return parent; 39811308Santhony.gutierrez@amd.com } 39911308Santhony.gutierrez@amd.com 40011308Santhony.gutierrez@amd.com std::string 40111308Santhony.gutierrez@amd.com getName() 40211308Santhony.gutierrez@amd.com { 40311308Santhony.gutierrez@amd.com return _name; 40411308Santhony.gutierrez@amd.com } 40511308Santhony.gutierrez@amd.com 40611308Santhony.gutierrez@amd.com int 40711308Santhony.gutierrez@amd.com getBanks() const 40811308Santhony.gutierrez@amd.com { 40911308Santhony.gutierrez@amd.com return banks; 41011308Santhony.gutierrez@amd.com } 41111308Santhony.gutierrez@amd.com 41211308Santhony.gutierrez@amd.com ComputeUnit * 41311308Santhony.gutierrez@amd.com getComputeUnit() const 41411308Santhony.gutierrez@amd.com { 41511308Santhony.gutierrez@amd.com return parent; 41611308Santhony.gutierrez@amd.com } 41711308Santhony.gutierrez@amd.com 41811308Santhony.gutierrez@amd.com int 41911308Santhony.gutierrez@amd.com getBankConflictPenalty() const 42011308Santhony.gutierrez@amd.com { 42111308Santhony.gutierrez@amd.com return bankConflictPenalty; 42211308Santhony.gutierrez@amd.com } 42311308Santhony.gutierrez@amd.com 42411308Santhony.gutierrez@amd.com /** 42511308Santhony.gutierrez@amd.com * get the allocated size for this workgroup 42611308Santhony.gutierrez@amd.com */ 42711308Santhony.gutierrez@amd.com std::size_t 42811308Santhony.gutierrez@amd.com ldsSize(const uint32_t x_wgId) 42911308Santhony.gutierrez@amd.com { 43011308Santhony.gutierrez@amd.com return chunkMap[x_wgId].size(); 43111308Santhony.gutierrez@amd.com } 43211308Santhony.gutierrez@amd.com 43311308Santhony.gutierrez@amd.com AddrRange 43411308Santhony.gutierrez@amd.com getAddrRange() const 43511308Santhony.gutierrez@amd.com { 43611308Santhony.gutierrez@amd.com return range; 43711308Santhony.gutierrez@amd.com } 43811308Santhony.gutierrez@amd.com 43913784Sgabeblack@google.com Port & 44013784Sgabeblack@google.com getPort(const std::string &if_name, PortID idx) 44111308Santhony.gutierrez@amd.com { 44211308Santhony.gutierrez@amd.com if (if_name == "cuPort") { 44311308Santhony.gutierrez@amd.com // TODO need to set name dynamically at this point? 44411308Santhony.gutierrez@amd.com return cuPort; 44511308Santhony.gutierrez@amd.com } else { 44611308Santhony.gutierrez@amd.com fatal("cannot resolve the port name " + if_name); 44711308Santhony.gutierrez@amd.com } 44811308Santhony.gutierrez@amd.com } 44911308Santhony.gutierrez@amd.com 45011308Santhony.gutierrez@amd.com /** 45111308Santhony.gutierrez@amd.com * can this much space be reserved for a workgroup? 45211308Santhony.gutierrez@amd.com */ 45311308Santhony.gutierrez@amd.com bool 45411308Santhony.gutierrez@amd.com canReserve(uint32_t x_size) const 45511308Santhony.gutierrez@amd.com { 45611308Santhony.gutierrez@amd.com return bytesAllocated + x_size <= maximumSize; 45711308Santhony.gutierrez@amd.com } 45811308Santhony.gutierrez@amd.com 45911308Santhony.gutierrez@amd.com private: 46011308Santhony.gutierrez@amd.com /** 46111308Santhony.gutierrez@amd.com * give back the space 46211308Santhony.gutierrez@amd.com */ 46311308Santhony.gutierrez@amd.com bool 46411308Santhony.gutierrez@amd.com releaseSpace(const uint32_t x_dispatchId, const uint32_t x_wgId) 46511308Santhony.gutierrez@amd.com { 46611308Santhony.gutierrez@amd.com auto dispatchIter = chunkMap.find(x_dispatchId); 46711308Santhony.gutierrez@amd.com 46811308Santhony.gutierrez@amd.com if (dispatchIter == chunkMap.end()) { 46911308Santhony.gutierrez@amd.com fatal("dispatch id not found [%d]", x_dispatchId); 47011308Santhony.gutierrez@amd.com } else { 47111308Santhony.gutierrez@amd.com auto workgroupIter = dispatchIter->second.find(x_wgId); 47211308Santhony.gutierrez@amd.com if (workgroupIter == dispatchIter->second.end()) { 47311308Santhony.gutierrez@amd.com fatal("workgroup id [%d] not found in dispatch id [%d]", 47411308Santhony.gutierrez@amd.com x_wgId, x_dispatchId); 47511308Santhony.gutierrez@amd.com } 47611308Santhony.gutierrez@amd.com } 47711308Santhony.gutierrez@amd.com 47811308Santhony.gutierrez@amd.com fatal_if(bytesAllocated < chunkMap[x_dispatchId][x_wgId].size(), 47911308Santhony.gutierrez@amd.com "releasing more space than was allocated"); 48011308Santhony.gutierrez@amd.com 48111308Santhony.gutierrez@amd.com bytesAllocated -= chunkMap[x_dispatchId][x_wgId].size(); 48211308Santhony.gutierrez@amd.com chunkMap[x_dispatchId].erase(chunkMap[x_dispatchId].find(x_wgId)); 48311308Santhony.gutierrez@amd.com return true; 48411308Santhony.gutierrez@amd.com } 48511308Santhony.gutierrez@amd.com 48611308Santhony.gutierrez@amd.com // the port that connects this LDS to its owner CU 48711308Santhony.gutierrez@amd.com CuSidePort cuPort; 48811308Santhony.gutierrez@amd.com 48911308Santhony.gutierrez@amd.com ComputeUnit* parent = nullptr; 49011308Santhony.gutierrez@amd.com 49111308Santhony.gutierrez@amd.com std::string _name; 49211308Santhony.gutierrez@amd.com 49311308Santhony.gutierrez@amd.com // the number of bytes currently reserved by all workgroups 49411308Santhony.gutierrez@amd.com int bytesAllocated = 0; 49511308Santhony.gutierrez@amd.com 49611308Santhony.gutierrez@amd.com // the size of the LDS, the most bytes available 49711308Santhony.gutierrez@amd.com int maximumSize; 49811308Santhony.gutierrez@amd.com 49911308Santhony.gutierrez@amd.com // Address range of this memory 50011308Santhony.gutierrez@amd.com AddrRange range; 50111308Santhony.gutierrez@amd.com 50211308Santhony.gutierrez@amd.com // the penalty, in cycles, for each LDS bank conflict 50311308Santhony.gutierrez@amd.com int bankConflictPenalty = 0; 50411308Santhony.gutierrez@amd.com 50511308Santhony.gutierrez@amd.com // the number of banks in the LDS underlying data store 50611308Santhony.gutierrez@amd.com int banks = 0; 50711308Santhony.gutierrez@amd.com}; 50811308Santhony.gutierrez@amd.com 50911308Santhony.gutierrez@amd.com#endif // __LDS_STATE_HH__ 510