1 /*========================== begin_copyright_notice ============================ 2 3 Copyright (C) 2017-2021 Intel Corporation 4 5 SPDX-License-Identifier: MIT 6 7 ============================= end_copyright_notice ===========================*/ 8 9 #ifndef _IGA_SWSBSETTER_H_ 10 #define _IGA_SWSBSETTER_H_ 11 12 #include "Instruction.hpp" 13 #include "Block.hpp" 14 #include "Kernel.hpp" 15 #include "Operand.hpp" 16 #include "../ErrorHandler.hpp" 17 #include "RegDeps.hpp" 18 19 namespace iga 20 { 21 // Bucket represents a GRF and maps to all instructions that access it 22 class Bucket 23 { 24 public: Bucket()25 Bucket() { dependencies.reserve(5); } clearDependency()26 void clearDependency() { dependencies.clear(); } isEmpty() const27 bool isEmpty() const { return dependencies.empty(); } getNumDependencies() const28 size_t getNumDependencies() const { return dependencies.size(); } getDepSet(uint32_t index)29 DepSet * getDepSet(uint32_t index) { return dependencies[index]; } clearDepSet(uint32_t index)30 void clearDepSet(uint32_t index) { dependencies[index] = nullptr; } 31 //Most of the time dependecy vector will have 1 or two entries addDepSet(DepSet * dep)32 void addDepSet(DepSet *dep) { 33 bool depSet = false; 34 for (size_t i = 0; i < dependencies.size(); ++i) 35 { 36 if (!dependencies[i]) 37 { 38 dependencies[i] = dep; 39 depSet = true; 40 break; 41 } 42 } 43 if (!depSet) 44 { 45 dependencies.push_back(dep); 46 } 47 } 48 private: 49 std::vector<DepSet*> dependencies; 50 }; 51 52 class SWSBAnalyzer 53 { 54 public: 55 typedef DepSet::InstIDs InstIDs; 56 public: 57 //Blocks have already been created SWSBAnalyzer(Kernel & k,ErrorHandler & errHandler,SWSB_ENCODE_MODE encode_mode,int sbid_count)58 SWSBAnalyzer(Kernel &k, ErrorHandler &errHandler, 59 SWSB_ENCODE_MODE encode_mode, int sbid_count) 60 : m_kernel(k), 61 m_errorHandler(errHandler), 62 m_SBIDRRCounter(0), 63 m_initPoint(false), 64 MAX_VALID_DISTANCE(k.getModel().getSWSBMaxValidDistance()) 65 { 66 // Set SWSB_ENCODE_MODE 67 if (encode_mode != SWSB_ENCODE_MODE::SWSBInvalidMode) 68 m_swsbMode = encode_mode; 69 else 70 m_swsbMode = k.getModel().getSWSBEncodeMode(); 71 72 if (m_swsbMode == SWSB_ENCODE_MODE::FourDistPipeReduction 73 ) { 74 m_LatencyLong64Pipe = 12; 75 } 76 77 m_DB = new DepSetBuilder(k.getModel()); 78 m_buckets = new Bucket[m_DB->getTOTAL_BUCKETS()]; 79 80 // set sbid count to 16 if not given 81 if (sbid_count) 82 m_SBIDCount = sbid_count; 83 else 84 m_SBIDCount = 16; 85 m_freeSBIDList.resize(m_SBIDCount); 86 } 87 ~SWSBAnalyzer()88 ~SWSBAnalyzer() 89 { 90 delete m_DB; 91 delete[] m_buckets; 92 } 93 94 void run(); 95 96 // getNumOfDistPipe - get number of in-order distance pipes of the given mode 97 static uint32_t getNumOfDistPipe(SWSB_ENCODE_MODE mode); 98 99 private: 100 // postProcess - last step of "run" 101 void postProcess(); 102 103 private: 104 // activeSBID: input list that the sbid this dep has dependency on will be added into. This list 105 // will later on be pass to processActiveSBID to set the swsb id dependency to inst accordingly 106 // needSyncForShootDownInst: if the sync to the sbid on the instruction is required. If the instruction 107 // is possiblely being shoot down, we have to add a sync to the id is synced with because we will 108 // clear the dependency 109 void calculateDependence(DepSet &dep, 110 SWSB &distanceDependency, 111 const Instruction &currInst, 112 std::vector<SBID> &activeSBID, 113 bool &needSyncForShootDownInst); 114 void processActiveSBID(SWSB &distanceDependency, 115 const DepSet* input, 116 Block *bb, 117 InstList::iterator iter, 118 std::vector<SBID>& activeSBID); 119 120 // helper function to pick a free SBID and set it to distanceDependency. 121 // This function only set SBID to distanceDependency, will not assign distanceDependency to 122 // the inst 123 SBID& assignSBID(DepSet* input, DepSet* output, Instruction& inst, SWSB& distanceDependency, 124 InstList::iterator insertPoint, Block *curBB, bool needSyncForShootDown); 125 126 // helper fuction to set out-of-order dependecy. Called by calculateDependence. 127 // This function create SBID with depedency to given dep, and add it to activeSBID 128 // it also set needSyncForShootDownInst if required. 129 void setSbidDependency(DepSet& dep, const Instruction& currInst, 130 bool& needSyncForShootDownInst, std::vector<SBID>& activeSBID); 131 132 // clear dependency of the given dep 133 void clearDepBuckets(DepSet &dep); 134 // clear all sbid, set ids to all free and insert sync to sync with all pipes 135 void clearSBIDDependence(InstList::iterator insertPoint, Instruction *lastInst, Block *bb); 136 // clear given input and output dependency in the buckets (for in-order pipes only) 137 void clearBuckets(DepSet* input, DepSet* output); 138 139 // helper function to insert sync.allrd and sync.allwr before the given inserPoint of given bb 140 void insertSyncAllRdWr(InstList::iterator insertPoint, Block *bb); 141 142 // a helper function to increase inst id counter based on the current encoding mode 143 void advanceInorderInstCounter(DEP_PIPE dep_pipe); 144 145 // get number of dist pipe according to SWSB_ENCODE_MODE 146 uint32_t getNumOfDistPipe(); 147 148 // addRMWDependencyIfReqruied - add read dependnecy to input DepSet if the instruction has RMW 149 // behavior, which is, has byte type dst 150 // XeHPC+ feature 151 void addRMWDependencyIfReqruied(DepSet& input, DepSet& output); 152 153 // add swsb into instruction, insert sync if the added swsb is not compatible 154 // with the existed swsb in the inst 155 void addSWSBToInst(Instruction& inst, const SWSB& swsb, 156 Block& block, InstListIterator inst_it); 157 158 private: 159 const uint32_t MAX_GRF_BUCKETS = 128; 160 // Instruction having 64-bit type destination having 14 latency 161 // All the other instructions having 10 latency 162 int m_LatencyLong64Pipe = 14; 163 int m_LatencyInOrderMath = 18; 164 int m_LatencyInOrderPipe = 10; 165 166 private: 167 // m_SBIDCound - number of SBID can be used 168 uint32_t m_SBIDCount; 169 170 // m_InstIdCounter - record the current instruction state 171 InstIDs m_InstIdCounter; 172 173 Kernel &m_kernel; 174 ErrorHandler &m_errorHandler; 175 176 Bucket* m_buckets = nullptr; 177 DepSetBuilder* m_DB = nullptr; 178 179 // This is the list to recored all sbid, if it's free or not 180 std::vector<SBID> m_freeSBIDList; 181 182 // m_SBIDRRCounter - the round robin counter for SB id reuse 183 unsigned int m_SBIDRRCounter; 184 185 // id to dep set mapping, this tracks for which instructions' dependency that this id 186 // is currently on. While we're re-using id, we clean up the dependency 187 std::map<uint32_t, std::pair<DepSet*, DepSet*>> m_IdToDepSetMap; 188 189 // m_distanceTracker - Track the DepSet of in-order instructions to see if their latency 190 // is satisfied. If the distance to current instruction is larger then the latency, then 191 // we no need to track the dependency anymore, remove the node from m_distanceTracker 192 struct distanceTrackerNode { distanceTrackerNodeiga::SWSBAnalyzer::distanceTrackerNode193 distanceTrackerNode(DepSet *in, DepSet *out) 194 : input(in), output(out) 195 {} 196 DepSet *input; 197 DepSet *output; 198 }; 199 std::list<distanceTrackerNode> m_distanceTracker; 200 201 bool m_initPoint; 202 203 SWSB_ENCODE_MODE m_swsbMode; 204 205 const int MAX_VALID_DISTANCE; 206 }; 207 } 208 #endif 209