| 1 | /* |
| 2 | * ========== Copyright Header Begin ========================================== |
| 3 | * |
| 4 | * OpenSPARC T2 Processor File: TsoNode.h |
| 5 | * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. |
| 6 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. |
| 7 | * |
| 8 | * The above named program is free software; you can redistribute it and/or |
| 9 | * modify it under the terms of the GNU General Public |
| 10 | * License version 2 as published by the Free Software Foundation. |
| 11 | * |
| 12 | * The above named program is distributed in the hope that it will be |
| 13 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 15 | * General Public License for more details. |
| 16 | * |
| 17 | * You should have received a copy of the GNU General Public |
| 18 | * License along with this work; if not, write to the Free Software |
| 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. |
| 20 | * |
| 21 | * ========== Copyright Header End ============================================ |
| 22 | */ |
| 23 | #ifndef _TSONODE_H |
| 24 | #define _TSONODE_H |
| 25 | /************************************************************************ |
| 26 | ** |
| 27 | ** Copyright (C) 2002, Sun Microsystems, Inc. |
| 28 | ** |
| 29 | ** Sun considers its source code as an unpublished, proprietary |
| 30 | ** trade secret and it is available only under strict license provisions. |
| 31 | ** This copyright notice is placed here only to protect Sun in the event |
| 32 | ** the source is deemed a published work. Disassembly, decompilation, |
| 33 | ** or other means of reducing the object code to human readable form |
| 34 | ** is prohibited by the license agreement under which this code is |
| 35 | ** provided to the user or company in possession of this copy." |
| 36 | ** |
| 37 | *************************************************************************/ |
| 38 | #include <iostream> |
| 39 | |
| 40 | #include "MemorySyncDefs.h" |
| 41 | #include <list> |
| 42 | |
| 43 | #include "TsoCheckerDefs.h" |
| 44 | #include "TsoEdge.h" |
| 45 | #include "TsoCheckerCmd.h" |
| 46 | |
| 47 | namespace Tso { |
| 48 | class TsoEdge; |
| 49 | |
| 50 | class TsoNode { |
| 51 | |
| 52 | public: |
| 53 | /** |
| 54 | * Default constructor |
| 55 | */ |
| 56 | TsoNode(); |
| 57 | |
| 58 | |
| 59 | /** |
| 60 | * constructor |
| 61 | */ |
| 62 | TsoNode(const TsoCheckerCmd& cmd); |
| 63 | |
| 64 | /** |
| 65 | * Copy constructor |
| 66 | * |
| 67 | * @param orig The TsoNode object to copy. |
| 68 | */ |
| 69 | TsoNode( const TsoNode &orig ); |
| 70 | |
| 71 | /** |
| 72 | * Destructor |
| 73 | */ |
| 74 | virtual ~TsoNode(); |
| 75 | |
| 76 | /** |
| 77 | * Equality operator |
| 78 | * |
| 79 | * @param rhs The right hand side of the equality operator |
| 80 | * @return Return true if this objec and rhs are equal, |
| 81 | * otherwise return false |
| 82 | */ |
| 83 | bool operator==( const TsoNode &rhs ) const; |
| 84 | |
| 85 | /** |
| 86 | * Assignment operator |
| 87 | * |
| 88 | * @param rhs The right hand side of the assignment operator. |
| 89 | * @return The lvalue of the assignment. |
| 90 | */ |
| 91 | const TsoNode & operator=( const TsoNode &rhs ); |
| 92 | |
| 93 | /** |
| 94 | * Return a string representation of this TsoNode object. |
| 95 | */ |
| 96 | std::string toString() const; |
| 97 | |
| 98 | /** |
| 99 | * Remove all edge pointers in the in_ list. The function also removes the |
| 100 | * edge pointer in the edge's source node's out_ list. |
| 101 | */ |
| 102 | void removeInEdges(); |
| 103 | |
| 104 | /** |
| 105 | * Remove all edge pointers in the out_ list. The function also removes the |
| 106 | * edge pointer in the edge's destination node's in_ list. |
| 107 | */ |
| 108 | void removeOutEdges(); |
| 109 | |
| 110 | /** |
| 111 | * Remove all edge pointers in the in_ & out_ list. This method calls |
| 112 | * removeInEdges() and removeOutEdges(). |
| 113 | */ |
| 114 | void removeEdges(); |
| 115 | |
| 116 | /** |
| 117 | * Check to see if all nodes corresponding to the node's instructions has |
| 118 | * arrived or not. |
| 119 | * @return a boolean to relect this check |
| 120 | */ |
| 121 | bool allEntriesArrive(); |
| 122 | |
| 123 | /** |
| 124 | * Check to see if the node coresponds to a store instruction |
| 125 | * Note that atomic is also counted as a store instruction. |
| 126 | * @return a boolean to relect this check |
| 127 | */ |
| 128 | isStore() { return (itype_ == ITYPE_STORE || |
| 129 | itype_ == ITYPE_BLOCK_STORE || |
| 130 | itype_ == ITYPE_STORE_INIT || |
| 131 | itype_ == ITYPE_ATOMIC); } |
| 132 | |
| 133 | /** |
| 134 | * Check to see if the node coresponds to a load instruction |
| 135 | * Note that atomic is also counted as a load instruction. |
| 136 | * @return a boolean to relect this check |
| 137 | */ |
| 138 | isLoad() { return (itype_ == ITYPE_LOAD || |
| 139 | itype_ == ITYPE_BLOCK_LOAD || |
| 140 | itype_ == ITYPE_QUAD_LOAD || |
| 141 | itype_ == ITYPE_DOUBLE_LOAD || |
| 142 | itype_ == ITYPE_ATOMIC); } |
| 143 | |
| 144 | /** |
| 145 | * Check to see if the node coresponds to a RMO instruction |
| 146 | * @return a boolean to relect this check |
| 147 | */ |
| 148 | isRMO() { return (itype_ == ITYPE_BLOCK_STORE || |
| 149 | itype_ == ITYPE_STORE_INIT || |
| 150 | itype_ == ITYPE_BLOCK_LOAD); } |
| 151 | |
| 152 | /** |
| 153 | * Check to see if the node coresponds to an atomic instruction |
| 154 | * @return a boolean to relect this check |
| 155 | */ |
| 156 | isAtomic() { return (itype_ == ITYPE_ATOMIC); } |
| 157 | |
| 158 | /** |
| 159 | * Check to see if the node's addres is in I/O range |
| 160 | * @return a boolean to relect this check |
| 161 | */ |
| 162 | isIO() { return ((addr_ & IO_ADDR_BIT_MASK) != 0); } |
| 163 | |
| 164 | /** |
| 165 | * Check to see if the node corresponds to a TSO load instruction |
| 166 | * A TSO load is defined as a load whose address is not in I/O space |
| 167 | * and is not a RMO load |
| 168 | * @return a boolean |
| 169 | */ |
| 170 | isTsoLoad() { return (isLoad() && !isRMO() && !isIO()); } |
| 171 | |
| 172 | /** |
| 173 | * Check to see if the node corresponds to a TSO store instruction |
| 174 | * A TSO store is defined as a store whose address is not in I/O space |
| 175 | * and is not a RMO store |
| 176 | * @return a boolean |
| 177 | */ |
| 178 | isTsoStore() { return (isStore() && !isRMO() && !isIO()); } |
| 179 | |
| 180 | /** |
| 181 | * Check to see if the node corresponds to a TSO instruction |
| 182 | * A TSO instruciton is defined as an instruction whose address is not |
| 183 | * in I/O space and is not a RMO instruction |
| 184 | * @return a boolean |
| 185 | */ |
| 186 | isTSO() { return (isTsoLoad() || isTsoStore()); } |
| 187 | |
| 188 | /** |
| 189 | * Check the if the node is MEM_STORE_COMMIT |
| 190 | * @return a bollena |
| 191 | */ |
| 192 | isStoreCommit() { return (cmd_ == MEM_STORE_COMMIT); } |
| 193 | |
| 194 | /** |
| 195 | * Check the if the node is MEM_LOAD_DATA |
| 196 | * @return a bollena |
| 197 | */ |
| 198 | isLoadData() { return (cmd_ == MEM_LOAD_DATA); } |
| 199 | |
| 200 | /** |
| 201 | * Get the begin iterator of the in_ list |
| 202 | */ |
| 203 | std::list<TsoEdge*>::iterator inBegin() { return in_.begin(); }; |
| 204 | |
| 205 | /** |
| 206 | * Get the end iterator of the in_ list |
| 207 | */ |
| 208 | std::list<TsoEdge*>::iterator inEnd() { return in_.end(); } |
| 209 | |
| 210 | /** |
| 211 | * Get the begin iterator of the out_ list |
| 212 | */ |
| 213 | std::list<TsoEdge*>::iterator outBegin() { return out_.begin(); } |
| 214 | |
| 215 | /** |
| 216 | * Get the end iterator of the out_ list |
| 217 | */ |
| 218 | std::list<TsoEdge*>::iterator outEnd() { return out_.end(); } |
| 219 | |
| 220 | /** |
| 221 | * Get the size of in_ |
| 222 | */ |
| 223 | std::list<TsoEdge*>::size_type inSize() { return in_.size(); } |
| 224 | |
| 225 | /** |
| 226 | * Get the size of out_ |
| 227 | */ |
| 228 | std::list<TsoEdge*>::size_type outSize() { return out_.size(); } |
| 229 | |
| 230 | /** |
| 231 | * Push an edge point to the front of the in_ list |
| 232 | * @param edge The edge pointer to be pushed |
| 233 | */ |
| 234 | void inPushFront (TsoEdge* edge) { in_.push_front(edge); } |
| 235 | |
| 236 | /** |
| 237 | * Push an edge point to the front of the out_ list |
| 238 | * @param edge The edge pointer to be pushed |
| 239 | */ |
| 240 | void outPushFront (TsoEdge* edge) { out_.push_front(edge); } |
| 241 | |
| 242 | /** |
| 243 | * Erase in_ entry |
| 244 | * @param ei The iterator whose corresponding entry is to be erase |
| 245 | */ |
| 246 | void inErase(std::list<TsoEdge*>::iterator ei) { in_.erase(ei); } |
| 247 | |
| 248 | /** |
| 249 | * Erase out_ entry |
| 250 | * @param ei The iterator whose corresponding entry is to be erase |
| 251 | */ |
| 252 | void outErase(std::list<TsoEdge*>::iterator ei) { out_.erase(ei); } |
| 253 | |
| 254 | /** |
| 255 | * Clear all entries in in_ list |
| 256 | */ |
| 257 | void inClear() { in_.clear(); } |
| 258 | |
| 259 | /** |
| 260 | * Clear all entries in out_ list |
| 261 | */ |
| 262 | void outClear() { out_.clear(); } |
| 263 | |
| 264 | /** |
| 265 | * Push a node pointer to the back of the nodes_ list |
| 266 | * @param np The node pointer to be pushed |
| 267 | */ |
| 268 | void nodePush (TsoNode* np) { nodes_.push_back(np); }; |
| 269 | |
| 270 | /****************************************************************** |
| 271 | * Private variable get/set methods |
| 272 | ******************************************************************/ |
| 273 | void setIseq (uint64_t iseq) { iseq_ = iseq; } |
| 274 | void setCommit (uint64_t commit) { commit_ = commit; } |
| 275 | void setGobs (uint64_t gobs) { gobs_ = gobs; } |
| 276 | void setRetire (uint64_t retire) { retire_ = retire; } |
| 277 | void setAddr (uint64_t addr) { addr_ = addr; } |
| 278 | void setData (uint64_t data) { data_ = data; } |
| 279 | void setNcnt (uint32_t ncnt) { ncnt_ = ncnt; } |
| 280 | void incNcnt () { ncnt_++; } |
| 281 | void setThrdId (uint32_t tid) { tid_ = tid; } |
| 282 | void setItype (enum INSTR_TYPE itype) { itype_ = itype; } |
| 283 | void setCmd (enum MEM_CMD cmd) { cmd_ = cmd; } |
| 284 | void setNtype (enum MEM_CMD ntype) { cmd_ = ntype; } |
| 285 | void setDsrc (enum DATA_SRC dsrc) { dsrc_ = dsrc; } |
| 286 | void setSizeV (uint8_t sizeV) { sizeV_ = sizeV; } |
| 287 | void setOld (uint8_t old) { old_ = old; } |
| 288 | void orOld (uint8_t old) { old_ = old_ | old; } |
| 289 | void setLastStore (bool tf) { lastStore_ = tf; } |
| 290 | void setLastLoad (bool tf) { lastLoad_ = tf; } |
| 291 | |
| 292 | char* getNodeName() { return nodeName_; } |
| 293 | uint64_t getIseq() const { return iseq_; } |
| 294 | uint64_t getCommit() const { return commit_; } |
| 295 | uint64_t getGobs() const { return gobs_; } |
| 296 | uint64_t getRetire() const { return retire_; } |
| 297 | uint64_t getAddr() const { return addr_; } |
| 298 | uint64_t getData() const { return data_; } |
| 299 | uint32_t getNcnt() const { return ncnt_; } |
| 300 | uint32_t getThrdId() const { return tid_; } |
| 301 | enum INSTR_TYPE getItype() const { return itype_; } |
| 302 | enum MEM_CMD getCmd() const { return cmd_; } |
| 303 | enum MEM_CMD getNtype() const { return cmd_; } |
| 304 | enum DATA_SRC getDsrc() const { return dsrc_; } |
| 305 | uint8_t getSizeV() const { return sizeV_; } |
| 306 | uint8_t getOld() const { return old_; } |
| 307 | |
| 308 | bool noInEdges() const { return (in_.empty()); } |
| 309 | bool noOutEdges() const { return (out_.empty()); } |
| 310 | bool hasInEdges() const { return (!in_.empty()); } |
| 311 | bool hasOutEdges() const { return (!out_.empty()); } |
| 312 | bool isAllOld() const { return ((sizeV_ ^ old_) == 0); } |
| 313 | |
| 314 | bool isLastStore() const { return lastStore_; } |
| 315 | bool isLastLoad() const { return lastLoad_; } |
| 316 | |
| 317 | protected: |
| 318 | |
| 319 | private: |
| 320 | /** |
| 321 | * nodeName_, node's name, is used as the node lable in TSO digraph |
| 322 | */ |
| 323 | char nodeName_[150]; |
| 324 | |
| 325 | /** |
| 326 | * in_ contains the pointers of edges coming to this node |
| 327 | */ |
| 328 | std::list<TsoEdge*> in_; |
| 329 | |
| 330 | /** |
| 331 | * out_ contains the pointers of edges coming from this node |
| 332 | */ |
| 333 | std::list<TsoEdge*> out_; |
| 334 | |
| 335 | /** |
| 336 | * nodes_ contains the pointers of nodes that belong to the same instruction as this node. |
| 337 | */ |
| 338 | std::list<TsoNode*> nodes_; // additional TSO nodes for atomic/quad load, block load/store |
| 339 | |
| 340 | /** |
| 341 | * iseq_ is the load/store instruction sequence, must consecutive |
| 342 | * but can be out-of-order |
| 343 | */ |
| 344 | uint64_t iseq_; // load/store instruction sequence number |
| 345 | |
| 346 | /** |
| 347 | * commit_ has different definitions for store and load. <br> |
| 348 | * <p> |
| 349 | * For store it is the time when a store commits (for N2, |
| 350 | * it is the time when the data is written into L2 and can be seen |
| 351 | * by other L2 access). <br> |
| 352 | * <p> |
| 353 | * For load, it is any time in the duration when the whole data can |
| 354 | * be seen in the L2 access. Note the source of a load may come from |
| 355 | * several stores. |
| 356 | * <p> This variable has the same meaning as macc_ in TsoCheckerCmd.h |
| 357 | * @see TsoCheckerCmd.h |
| 358 | */ |
| 359 | uint64_t commit_; |
| 360 | |
| 361 | /** |
| 362 | * gobs_ is the global observed time of a store. Note that a store |
| 363 | * may have stale data in L1 caches of other cores, or caches of |
| 364 | * other chips. Before a store data can be globally observed, all |
| 365 | * those stale data must be either invalidated or be updated. <br> |
| 366 | * <p> |
| 367 | * The gobs_ must be no earlier than its L2 commit time, commit_. |
| 368 | */ |
| 369 | uint64_t gobs_; |
| 370 | |
| 371 | /** |
| 372 | * retire_ is the time when the node can be retired. Note that different |
| 373 | * byte of data may have different retire time. This records the latest. |
| 374 | */ |
| 375 | uint64_t retire_; |
| 376 | |
| 377 | /** |
| 378 | * addr_ is the physical address. |
| 379 | */ |
| 380 | uint64_t addr_; // address |
| 381 | |
| 382 | /** |
| 383 | * data_ is either the load data or store data. |
| 384 | */ |
| 385 | uint64_t data_; // data |
| 386 | |
| 387 | /** |
| 388 | * ncnt_ equals nnodes_.size() + 1 (itself) |
| 389 | */ |
| 390 | uint32_t ncnt_; |
| 391 | |
| 392 | /** |
| 393 | * tid_ is a flat thread ID; each thread must have a unique ID. |
| 394 | */ |
| 395 | uint32_t tid_; // thread ID |
| 396 | |
| 397 | /** |
| 398 | * itype_ is the instruction type, such as load, store, block load/store, |
| 399 | * etc, whose definition is in |
| 400 | * @see MemorySyncDefs.h |
| 401 | */ |
| 402 | enum INSTR_TYPE itype_; // instruction type |
| 403 | |
| 404 | |
| 405 | /** |
| 406 | * cmd_ is the entry type, such as StoreCommit and LoadData, whose |
| 407 | * defintion is in |
| 408 | * @see MemorySyncDefs.h |
| 409 | */ |
| 410 | enum MEM_CMD cmd_; // command |
| 411 | |
| 412 | /** |
| 413 | * dsrc_ is the source of a load data, which could be L1, STB, or |
| 414 | * L2/Memory. |
| 415 | * @see MemorySyncDefs.h |
| 416 | */ |
| 417 | enum DATA_SRC dsrc_; // data source |
| 418 | |
| 419 | /** |
| 420 | * The data format is as follows: (Big Edian) |
| 421 | * |
| 422 | * bit 63 0 |
| 423 | * +--------+--------+------------+--------+ |
| 424 | * data | byte 0 | byte 1 | --- | byte 7 | |
| 425 | * (64 bits) +--------+--------+------------+--------+ |
| 426 | * |
| 427 | * sizeV_: bit 7 bit 6 bit 0 |
| 428 | * (8 bits) |
| 429 | * |
| 430 | * sizeV_ is to indicates which byte is valid: bit 0 for data_[7:0], |
| 431 | * bit 1 for data_[15:8], and so on. |
| 432 | */ |
| 433 | uint8_t sizeV_; // size vector: 1 -> valid byte |
| 434 | |
| 435 | /** |
| 436 | * old_ indicates if the corresponding byte of data in this node is old or not. |
| 437 | * Similar to sizeV_, bit 0 is the indicator of data_[7:0]; bit 1, data_[15:8], |
| 438 | * and so on. |
| 439 | */ |
| 440 | uint8_t old_; // bit vector: 1 -> old data in MemoryAccessHistory |
| 441 | |
| 442 | /** |
| 443 | * lastStore_ indicates if the node is the last store in the program order list, |
| 444 | * nodeList_ in TsoChecker.h, or not. |
| 445 | * @see TsoChecker.h |
| 446 | */ |
| 447 | bool lastStore_; // need both lastStore_ and lastLoad_ is because atomic |
| 448 | |
| 449 | /** |
| 450 | * lastStore_ indicates if the node is the last load in the program order list, |
| 451 | * nodeList_ in TsoChecker.h, or not. |
| 452 | * @see TsoChecker.h |
| 453 | */ |
| 454 | bool lastLoad_; // can have both |
| 455 | }; |
| 456 | |
| 457 | } /* namespace Tso */ |
| 458 | |
| 459 | #endif /* _TSONODE_H */ |