diff options
Diffstat (limited to 'src')
44 files changed, 16302 insertions, 17112 deletions
diff --git a/src/gpgpu-sim/addrdec.cc b/src/gpgpu-sim/addrdec.cc index f781632..e3713f3 100644 --- a/src/gpgpu-sim/addrdec.cc +++ b/src/gpgpu-sim/addrdec.cc @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -27,607 +25,532 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include "addrdec.h" + #include <string.h> -#include "../option_parser.h" +#include "addrdec.h" #include "gpu-sim.h" +#include "../option_parser.h" + -static long int powli(long int x, long int y); -static unsigned int LOGB2_32(unsigned int v); -static new_addr_type addrdec_packbits(new_addr_type mask, new_addr_type val, - unsigned char high, unsigned char low); -static void addrdec_getmasklimit(new_addr_type mask, unsigned char *high, - unsigned char *low); -linear_to_raw_address_translation::linear_to_raw_address_translation() { - addrdec_option = NULL; - ADDR_CHIP_S = 10; - memset(addrdec_mklow, 0, N_ADDRDEC); - memset(addrdec_mkhigh, 64, N_ADDRDEC); - addrdec_mask[0] = 0x0000000000001C00; - addrdec_mask[1] = 0x0000000000000300; - addrdec_mask[2] = 0x000000000FFF0000; - addrdec_mask[3] = 0x000000000000E0FF; - addrdec_mask[4] = 0x000000000000000F; +static long int powli( long int x, long int y ); +static unsigned int LOGB2_32( unsigned int v ); +static new_addr_type addrdec_packbits( new_addr_type mask, new_addr_type val, unsigned char high, unsigned char low); +static void addrdec_getmasklimit(new_addr_type mask, unsigned char *high, unsigned char *low); + +linear_to_raw_address_translation::linear_to_raw_address_translation() +{ + addrdec_option = NULL; + ADDR_CHIP_S = 10; + memset(addrdec_mklow,0,N_ADDRDEC); + memset(addrdec_mkhigh,64,N_ADDRDEC); + addrdec_mask[0] = 0x0000000000001C00; + addrdec_mask[1] = 0x0000000000000300; + addrdec_mask[2] = 0x000000000FFF0000; + addrdec_mask[3] = 0x000000000000E0FF; + addrdec_mask[4] = 0x000000000000000F; } -void linear_to_raw_address_translation::addrdec_setoption(option_parser_t opp) { - option_parser_register(opp, "-gpgpu_mem_addr_mapping", OPT_CSTR, - &addrdec_option, - "mapping memory address to dram model {dramid@<start " - "bit>;<memory address map>}", - NULL); - option_parser_register( - opp, "-gpgpu_mem_addr_test", OPT_BOOL, &run_test, - "run sweep test to check address mapping for aliased address", "0"); - option_parser_register(opp, "-gpgpu_mem_address_mask", OPT_INT32, - &gpgpu_mem_address_mask, - "0 = old addressing mask, 1 = new addressing mask, 2 " - "= new add. mask + flipped bank sel and chip sel bits", - "0"); - option_parser_register( - opp, "-memory_partition_indexing", OPT_UINT32, &memory_partition_indexing, - "0 = no indexing, 1 = bitwise xoring, 2 = IPoly, 3 = custom indexing", +void linear_to_raw_address_translation::addrdec_setoption(option_parser_t opp) +{ + option_parser_register(opp, "-gpgpu_mem_addr_mapping", OPT_CSTR, &addrdec_option, + "mapping memory address to dram model {dramid@<start bit>;<memory address map>}", + NULL); + option_parser_register(opp, "-gpgpu_mem_addr_test", OPT_BOOL, &run_test, + "run sweep test to check address mapping for aliased address", "0"); + option_parser_register(opp, "-gpgpu_mem_address_mask", OPT_INT32, &gpgpu_mem_address_mask, + "0 = old addressing mask, 1 = new addressing mask, 2 = new add. mask + flipped bank sel and chip sel bits", + "0"); + option_parser_register(opp, "-memory_partition_indexing", OPT_UINT32, &memory_partition_indexing, + "0 = no indexing, 1 = bitwise xoring, 2 = IPoly, 3 = custom indexing", + "0"); } -new_addr_type linear_to_raw_address_translation::partition_address( - new_addr_type addr) const { - if (!gap) { - return addrdec_packbits(~(addrdec_mask[CHIP] | sub_partition_id_mask), addr, - 64, 0); - } else { - // see addrdec_tlx for explanation - unsigned long long int partition_addr; - partition_addr = ((addr >> ADDR_CHIP_S) / m_n_channel) << ADDR_CHIP_S; - partition_addr |= addr & ((1 << ADDR_CHIP_S) - 1); - // remove the part of address that constributes to the sub partition ID - partition_addr = - addrdec_packbits(~sub_partition_id_mask, partition_addr, 64, 0); - return partition_addr; - } +new_addr_type linear_to_raw_address_translation::partition_address( new_addr_type addr ) const +{ + if (!gap) { + return addrdec_packbits( ~(addrdec_mask[CHIP] | sub_partition_id_mask), addr, 64, 0 ); + } else { + // see addrdec_tlx for explanation + unsigned long long int partition_addr; + partition_addr = ( (addr>>ADDR_CHIP_S) / m_n_channel) << ADDR_CHIP_S; + partition_addr |= addr & ((1 << ADDR_CHIP_S) - 1); + // remove the part of address that constributes to the sub partition ID + partition_addr = addrdec_packbits( ~sub_partition_id_mask, partition_addr, 64, 0); + return partition_addr; + } } -void linear_to_raw_address_translation::addrdec_tlx(new_addr_type addr, - addrdec_t *tlx) const { - unsigned long long int addr_for_chip, rest_of_addr; - if (!gap) { - tlx->chip = addrdec_packbits(addrdec_mask[CHIP], addr, addrdec_mkhigh[CHIP], - addrdec_mklow[CHIP]); - tlx->bk = addrdec_packbits(addrdec_mask[BK], addr, addrdec_mkhigh[BK], - addrdec_mklow[BK]); - tlx->row = addrdec_packbits(addrdec_mask[ROW], addr, addrdec_mkhigh[ROW], - addrdec_mklow[ROW]); - tlx->col = addrdec_packbits(addrdec_mask[COL], addr, addrdec_mkhigh[COL], - addrdec_mklow[COL]); - tlx->burst = addrdec_packbits(addrdec_mask[BURST], addr, - addrdec_mkhigh[BURST], addrdec_mklow[BURST]); - } else { - // Split the given address at ADDR_CHIP_S into (MSBs,LSBs) - // - extract chip address using modulus of MSBs - // - recreate the rest of the address by stitching the quotient of MSBs and - // the LSBs - addr_for_chip = (addr >> ADDR_CHIP_S) % m_n_channel; - rest_of_addr = ((addr >> ADDR_CHIP_S) / m_n_channel) << ADDR_CHIP_S; - rest_of_addr |= addr & ((1 << ADDR_CHIP_S) - 1); +void linear_to_raw_address_translation::addrdec_tlx(new_addr_type addr, addrdec_t *tlx) const +{ + unsigned long long int addr_for_chip,rest_of_addr; + if (!gap) { + tlx->chip = addrdec_packbits(addrdec_mask[CHIP], addr, addrdec_mkhigh[CHIP], addrdec_mklow[CHIP]); + tlx->bk = addrdec_packbits(addrdec_mask[BK], addr, addrdec_mkhigh[BK], addrdec_mklow[BK]); + tlx->row = addrdec_packbits(addrdec_mask[ROW], addr, addrdec_mkhigh[ROW], addrdec_mklow[ROW]); + tlx->col = addrdec_packbits(addrdec_mask[COL], addr, addrdec_mkhigh[COL], addrdec_mklow[COL]); + tlx->burst= addrdec_packbits(addrdec_mask[BURST], addr, addrdec_mkhigh[BURST], addrdec_mklow[BURST]); + } else { + // Split the given address at ADDR_CHIP_S into (MSBs,LSBs) + // - extract chip address using modulus of MSBs + // - recreate the rest of the address by stitching the quotient of MSBs and the LSBs + addr_for_chip = (addr>>ADDR_CHIP_S) % m_n_channel; + rest_of_addr = ( (addr>>ADDR_CHIP_S) / m_n_channel) << ADDR_CHIP_S; + rest_of_addr |= addr & ((1 << ADDR_CHIP_S) - 1); - tlx->chip = addr_for_chip; - tlx->bk = addrdec_packbits(addrdec_mask[BK], rest_of_addr, - addrdec_mkhigh[BK], addrdec_mklow[BK]); - tlx->row = addrdec_packbits(addrdec_mask[ROW], rest_of_addr, - addrdec_mkhigh[ROW], addrdec_mklow[ROW]); - tlx->col = addrdec_packbits(addrdec_mask[COL], rest_of_addr, - addrdec_mkhigh[COL], addrdec_mklow[COL]); - tlx->burst = addrdec_packbits(addrdec_mask[BURST], rest_of_addr, - addrdec_mkhigh[BURST], addrdec_mklow[BURST]); - } + tlx->chip = addr_for_chip; + tlx->bk = addrdec_packbits(addrdec_mask[BK], rest_of_addr, addrdec_mkhigh[BK], addrdec_mklow[BK]); + tlx->row = addrdec_packbits(addrdec_mask[ROW], rest_of_addr, addrdec_mkhigh[ROW], addrdec_mklow[ROW]); + tlx->col = addrdec_packbits(addrdec_mask[COL], rest_of_addr, addrdec_mkhigh[COL], addrdec_mklow[COL]); + tlx->burst= addrdec_packbits(addrdec_mask[BURST], rest_of_addr, addrdec_mkhigh[BURST], addrdec_mklow[BURST]); + } - switch (memory_partition_indexing) { - case CONSECUTIVE: - // Do nothing - break; - case BITWISE_PERMUTATION: { - assert(!gap); - tlx->chip = (tlx->chip) ^ (tlx->row & (m_n_channel - 1)); - assert(tlx->chip < m_n_channel); - break; - } - case IPOLY: { - /* - * Set Indexing function from "Pseudo-randomly interleaved memory." - * Rau, B. R et al. - * ISCA 1991 - * - * equations are adopted from: - * "Sacat: streaming-aware conflict-avoiding thrashing-resistant gpgpu - * cache management scheme." - * Khairy et al. - * IEEE TPDS 2017. - */ - if (m_n_channel == 32) { - std::bitset<64> a(tlx->row); - std::bitset<5> chip(tlx->chip); - chip[0] = a[13] ^ a[12] ^ a[11] ^ a[10] ^ a[9] ^ a[6] ^ a[5] ^ a[3] ^ - a[0] ^ chip[0]; - chip[1] = a[14] ^ a[13] ^ a[12] ^ a[11] ^ a[10] ^ a[7] ^ a[6] ^ a[4] ^ - a[1] ^ chip[1]; - chip[2] = a[14] ^ a[10] ^ a[9] ^ a[8] ^ a[7] ^ a[6] ^ a[3] ^ a[2] ^ - a[0] ^ chip[2]; - chip[3] = - a[11] ^ a[10] ^ a[9] ^ a[8] ^ a[7] ^ a[4] ^ a[3] ^ a[1] ^ chip[3]; - chip[4] = - a[12] ^ a[11] ^ a[10] ^ a[9] ^ a[8] ^ a[5] ^ a[4] ^ a[2] ^ chip[4]; - tlx->chip = chip.to_ulong(); + switch(memory_partition_indexing){ + case CONSECUTIVE: + //Do nothing + break; + case BITWISE_PERMUTATION: + { + assert(!gap); + tlx->chip = (tlx->chip) ^ (tlx->row & (m_n_channel-1)); + assert(tlx->chip < m_n_channel); + break; + } + case IPOLY: + { + /* + * Set Indexing function from "Pseudo-randomly interleaved memory." + * Rau, B. R et al. + * ISCA 1991 + * + * equations are adopted from: + * "Sacat: streaming-aware conflict-avoiding thrashing-resistant gpgpu cache management scheme." + * Khairy et al. + * IEEE TPDS 2017. + */ + if(m_n_channel == 32) { + std::bitset<64> a(tlx->row); + std::bitset<5> chip(tlx->chip); + chip[0] = a[13]^a[12]^a[11]^a[10]^a[9]^a[6]^a[5]^a[3]^a[0]^chip[0]; + chip[1] = a[14]^a[13]^a[12]^a[11]^a[10]^a[7]^a[6]^a[4]^a[1]^chip[1]; + chip[2] = a[14]^a[10]^a[9]^a[8]^a[7]^a[6]^a[3]^a[2]^a[0]^chip[2]; + chip[3] = a[11]^a[10]^a[9]^a[8]^a[7]^a[4]^a[3]^a[1]^chip[3]; + chip[4] = a[12]^a[11]^a[10]^a[9]^a[8]^a[5]^a[4]^a[2]^chip[4]; + tlx->chip = chip.to_ulong(); + + } + else{ /* Else incorrect number of channels for the hashing function */ + assert("\nGPGPU-Sim memory_partition_indexing error: The number of channels should be " + "32 for the hashing IPOLY index function.\n" && 0); + } + assert(tlx->chip < m_n_channel); + break; + } + case PAE: + { + //Page Address Entropy + //random selected bits from the page and bank bits + //similar to + //Liu, Yuxi, et al. "Get Out of the Valley: Power-Efficient Address Mapping for GPUs." ISCA 2018 + std::bitset<64> a(tlx->row); + std::bitset<5> chip(tlx->chip); + std::bitset<4> b(tlx->bk); + chip[0] = a[13]^a[10]^a[9]^a[5]^a[0]^b[3]^b[0]^chip[0]; + chip[1] = a[12]^a[11]^a[6]^a[1]^b[3]^b[2]^b[1]^chip[1]; + chip[2] = a[14]^a[9]^a[8]^a[7]^a[2]^b[1]^chip[2]; + chip[3] = a[11]^a[10]^a[8]^a[3]^b[2]^b[3]^chip[3]; + chip[4] = a[12]^a[9]^a[8]^a[5]^a[4]^b[1]^b[0]^chip[4]; + tlx->chip = chip.to_ulong(); + assert(tlx->chip < m_n_channel); + break; + } + case RANDOM: + { + //This is an unrealistic hashing using software hashtable + //we generate a random set for each memory address and save the value in a big hashtable for future reuse + new_addr_type chip_address = (addr>>ADDR_CHIP_S); + tr1_hash_map<new_addr_type,unsigned>::const_iterator got = address_random_interleaving.find (chip_address); + if ( got == address_random_interleaving.end() ) { + unsigned new_chip_id = rand() % (m_n_channel*m_n_sub_partition_in_channel); + address_random_interleaving[chip_address] = new_chip_id; + tlx->chip = new_chip_id/m_n_sub_partition_in_channel; + tlx->sub_partition = new_chip_id; + } + else { + unsigned new_chip_id = got->second; + tlx->chip = new_chip_id/m_n_sub_partition_in_channel; + tlx->sub_partition = new_chip_id; + } - } else { /* Else incorrect number of channels for the hashing function */ - assert( - "\nGPGPU-Sim memory_partition_indexing error: The number of " - "channels should be " - "32 for the hashing IPOLY index function.\n" && - 0); - } - assert(tlx->chip < m_n_channel); - break; - } - case PAE: { - // Page Address Entropy - // random selected bits from the page and bank bits - // similar to - // Liu, Yuxi, et al. "Get Out of the Valley: Power-Efficient Address - // Mapping for GPUs." ISCA 2018 - std::bitset<64> a(tlx->row); - std::bitset<5> chip(tlx->chip); - std::bitset<4> b(tlx->bk); - chip[0] = a[13] ^ a[10] ^ a[9] ^ a[5] ^ a[0] ^ b[3] ^ b[0] ^ chip[0]; - chip[1] = a[12] ^ a[11] ^ a[6] ^ a[1] ^ b[3] ^ b[2] ^ b[1] ^ chip[1]; - chip[2] = a[14] ^ a[9] ^ a[8] ^ a[7] ^ a[2] ^ b[1] ^ chip[2]; - chip[3] = a[11] ^ a[10] ^ a[8] ^ a[3] ^ b[2] ^ b[3] ^ chip[3]; - chip[4] = a[12] ^ a[9] ^ a[8] ^ a[5] ^ a[4] ^ b[1] ^ b[0] ^ chip[4]; - tlx->chip = chip.to_ulong(); - assert(tlx->chip < m_n_channel); - break; - } - case RANDOM: { - // This is an unrealistic hashing using software hashtable - // we generate a random set for each memory address and save the value in - // a big hashtable for future reuse - new_addr_type chip_address = (addr >> ADDR_CHIP_S); - tr1_hash_map<new_addr_type, unsigned>::const_iterator got = - address_random_interleaving.find(chip_address); - if (got == address_random_interleaving.end()) { - unsigned new_chip_id = - rand() % (m_n_channel * m_n_sub_partition_in_channel); - address_random_interleaving[chip_address] = new_chip_id; - tlx->chip = new_chip_id / m_n_sub_partition_in_channel; - tlx->sub_partition = new_chip_id; - } else { - unsigned new_chip_id = got->second; - tlx->chip = new_chip_id / m_n_sub_partition_in_channel; - tlx->sub_partition = new_chip_id; - } + assert(tlx->chip < m_n_channel); + assert(tlx->sub_partition < m_n_channel * m_n_sub_partition_in_channel); + return; + break; + } + case CUSTOM: + /* No custom set function implemented */ + //Do you custom index here + break; + default: + assert("\nUndefined set index function.\n" && 0); + break; + } - assert(tlx->chip < m_n_channel); - assert(tlx->sub_partition < m_n_channel * m_n_sub_partition_in_channel); - return; - break; - } - case CUSTOM: - /* No custom set function implemented */ - // Do you custom index here - break; - default: - assert("\nUndefined set index function.\n" && 0); - break; - } - - // combine the chip address and the lower bits of DRAM bank address to form - // the subpartition ID - unsigned sub_partition_addr_mask = m_n_sub_partition_in_channel - 1; - tlx->sub_partition = tlx->chip * m_n_sub_partition_in_channel + - (tlx->bk & sub_partition_addr_mask); + // combine the chip address and the lower bits of DRAM bank address to form the subpartition ID + unsigned sub_partition_addr_mask = m_n_sub_partition_in_channel - 1; + tlx->sub_partition = tlx->chip * m_n_sub_partition_in_channel + + (tlx->bk & sub_partition_addr_mask); } -void linear_to_raw_address_translation::addrdec_parseoption( - const char *option) { - unsigned int dramid_start = 0; - int dramid_parsed = sscanf(option, "dramid@%d", &dramid_start); - if (dramid_parsed == 1) { - ADDR_CHIP_S = dramid_start; - } else { - ADDR_CHIP_S = -1; - } - - const char *cmapping = strchr(option, ';'); - if (cmapping == NULL) { - cmapping = option; - } else { - cmapping += 1; - } - - addrdec_mask[CHIP] = 0x0; - addrdec_mask[BK] = 0x0; - addrdec_mask[ROW] = 0x0; - addrdec_mask[COL] = 0x0; - addrdec_mask[BURST] = 0x0; +void linear_to_raw_address_translation::addrdec_parseoption(const char *option) +{ + unsigned int dramid_start = 0; + int dramid_parsed = sscanf(option, "dramid@%d", &dramid_start); + if (dramid_parsed == 1) { + ADDR_CHIP_S = dramid_start; + } else { + ADDR_CHIP_S = -1; + } + + const char *cmapping = strchr(option, ';'); + if (cmapping == NULL) { + cmapping = option; + } else { + cmapping += 1; + } - int ofs = 63; - while ((*cmapping) != '\0') { - switch (*cmapping) { - case 'D': - case 'd': - assert(dramid_parsed != 1); - addrdec_mask[CHIP] |= (1ULL << ofs); - ofs--; - break; - case 'B': - case 'b': - addrdec_mask[BK] |= (1ULL << ofs); - ofs--; - break; - case 'R': - case 'r': - addrdec_mask[ROW] |= (1ULL << ofs); - ofs--; - break; - case 'C': - case 'c': - addrdec_mask[COL] |= (1ULL << ofs); - ofs--; - break; - case 'S': - case 's': - addrdec_mask[BURST] |= (1ULL << ofs); - addrdec_mask[COL] |= (1ULL << ofs); - ofs--; - break; - // ignore bit - case '0': - ofs--; - break; - // ignore character - case '|': - case ' ': - case '.': - break; - default: - fprintf( - stderr, - "ERROR: Invalid address mapping character '%c' in option '%s'\n", - *cmapping, option); - } - cmapping += 1; - } + addrdec_mask[CHIP] = 0x0; + addrdec_mask[BK] = 0x0; + addrdec_mask[ROW] = 0x0; + addrdec_mask[COL] = 0x0; + addrdec_mask[BURST]= 0x0; + + int ofs = 63; + while ((*cmapping) != '\0') { + switch (*cmapping) { + case 'D': case 'd': + assert(dramid_parsed != 1); addrdec_mask[CHIP] |= (1ULL << ofs); ofs--; break; + case 'B': case 'b': addrdec_mask[BK] |= (1ULL << ofs); ofs--; break; + case 'R': case 'r': addrdec_mask[ROW] |= (1ULL << ofs); ofs--; break; + case 'C': case 'c': addrdec_mask[COL] |= (1ULL << ofs); ofs--; break; + case 'S': case 's': addrdec_mask[BURST] |= (1ULL << ofs); addrdec_mask[COL] |= (1ULL << ofs); ofs--; break; + // ignore bit + case '0': ofs--; break; + // ignore character + case '|': + case ' ': + case '.': break; + default: + fprintf(stderr, "ERROR: Invalid address mapping character '%c' in option '%s'\n", *cmapping, option); + } + cmapping += 1; + } - if (ofs != -1) { - fprintf(stderr, - "ERROR: Invalid address mapping length (%d) in option '%s'\n", - 63 - ofs, option); - assert(ofs == -1); - } + if (ofs != -1) { + fprintf(stderr, "ERROR: Invalid address mapping length (%d) in option '%s'\n", 63 - ofs, option); + assert(ofs == -1); + } } -void linear_to_raw_address_translation::init( - unsigned int n_channel, unsigned int n_sub_partition_in_channel) { - unsigned i; - unsigned long long int mask; - unsigned int nchipbits = ::LOGB2_32(n_channel); - m_n_channel = n_channel; - m_n_sub_partition_in_channel = n_sub_partition_in_channel; +void linear_to_raw_address_translation::init(unsigned int n_channel, unsigned int n_sub_partition_in_channel) +{ + unsigned i; + unsigned long long int mask; + unsigned int nchipbits = ::LOGB2_32(n_channel); + m_n_channel = n_channel; + m_n_sub_partition_in_channel = n_sub_partition_in_channel; - gap = (n_channel - ::powli(2, nchipbits)); - if (gap) { - nchipbits++; - } - switch (gpgpu_mem_address_mask) { - case 0: - // old, added 2row bits, use #define ADDR_CHIP_S 10 + gap = (n_channel - ::powli(2,nchipbits)); + if (gap) { + nchipbits++; + } + switch (gpgpu_mem_address_mask) { + case 0: + //old, added 2row bits, use #define ADDR_CHIP_S 10 ADDR_CHIP_S = 10; addrdec_mask[CHIP] = 0x0000000000000000; - addrdec_mask[BK] = 0x0000000000000300; - addrdec_mask[ROW] = 0x0000000007FFE000; - addrdec_mask[COL] = 0x0000000000001CFF; + addrdec_mask[BK] = 0x0000000000000300; + addrdec_mask[ROW] = 0x0000000007FFE000; + addrdec_mask[COL] = 0x0000000000001CFF; break; - case 1: + case 1: ADDR_CHIP_S = 13; addrdec_mask[CHIP] = 0x0000000000000000; - addrdec_mask[BK] = 0x0000000000001800; - addrdec_mask[ROW] = 0x0000000007FFE000; - addrdec_mask[COL] = 0x00000000000007FF; + addrdec_mask[BK] = 0x0000000000001800; + addrdec_mask[ROW] = 0x0000000007FFE000; + addrdec_mask[COL] = 0x00000000000007FF; break; - case 2: + case 2: ADDR_CHIP_S = 11; addrdec_mask[CHIP] = 0x0000000000000000; - addrdec_mask[BK] = 0x0000000000001800; - addrdec_mask[ROW] = 0x0000000007FFE000; - addrdec_mask[COL] = 0x00000000000007FF; + addrdec_mask[BK] = 0x0000000000001800; + addrdec_mask[ROW] = 0x0000000007FFE000; + addrdec_mask[COL] = 0x00000000000007FF; break; - case 3: + case 3: ADDR_CHIP_S = 11; addrdec_mask[CHIP] = 0x0000000000000000; - addrdec_mask[BK] = 0x0000000000001800; - addrdec_mask[ROW] = 0x000000000FFFE000; - addrdec_mask[COL] = 0x00000000000007FF; + addrdec_mask[BK] = 0x0000000000001800; + addrdec_mask[ROW] = 0x000000000FFFE000; + addrdec_mask[COL] = 0x00000000000007FF; break; - case 14: + case 14: ADDR_CHIP_S = 14; addrdec_mask[CHIP] = 0x0000000000000000; - addrdec_mask[BK] = 0x0000000000001800; - addrdec_mask[ROW] = 0x0000000007FFE000; - addrdec_mask[COL] = 0x00000000000007FF; + addrdec_mask[BK] = 0x0000000000001800; + addrdec_mask[ROW] = 0x0000000007FFE000; + addrdec_mask[COL] = 0x00000000000007FF; break; - case 15: + case 15: ADDR_CHIP_S = 15; addrdec_mask[CHIP] = 0x0000000000000000; - addrdec_mask[BK] = 0x0000000000001800; - addrdec_mask[ROW] = 0x0000000007FFE000; - addrdec_mask[COL] = 0x00000000000007FF; + addrdec_mask[BK] = 0x0000000000001800; + addrdec_mask[ROW] = 0x0000000007FFE000; + addrdec_mask[COL] = 0x00000000000007FF; break; - case 16: + case 16: ADDR_CHIP_S = 16; addrdec_mask[CHIP] = 0x0000000000000000; - addrdec_mask[BK] = 0x0000000000001800; - addrdec_mask[ROW] = 0x0000000007FFE000; - addrdec_mask[COL] = 0x00000000000007FF; + addrdec_mask[BK] = 0x0000000000001800; + addrdec_mask[ROW] = 0x0000000007FFE000; + addrdec_mask[COL] = 0x00000000000007FF; break; - case 6: + case 6: ADDR_CHIP_S = 6; addrdec_mask[CHIP] = 0x0000000000000000; - addrdec_mask[BK] = 0x0000000000001800; - addrdec_mask[ROW] = 0x0000000007FFE000; - addrdec_mask[COL] = 0x00000000000007FF; + addrdec_mask[BK] = 0x0000000000001800; + addrdec_mask[ROW] = 0x0000000007FFE000; + addrdec_mask[COL] = 0x00000000000007FF; break; - case 5: + case 5: ADDR_CHIP_S = 5; addrdec_mask[CHIP] = 0x0000000000000000; - addrdec_mask[BK] = 0x0000000000001800; - addrdec_mask[ROW] = 0x0000000007FFE000; - addrdec_mask[COL] = 0x00000000000007FF; - break; - case 100: + addrdec_mask[BK] = 0x0000000000001800; + addrdec_mask[ROW] = 0x0000000007FFE000; + addrdec_mask[COL] = 0x00000000000007FF; + break; + case 100: ADDR_CHIP_S = 1; addrdec_mask[CHIP] = 0x0000000000000000; - addrdec_mask[BK] = 0x0000000000000003; - addrdec_mask[ROW] = 0x0000000007FFE000; - addrdec_mask[COL] = 0x0000000000001FFC; + addrdec_mask[BK] = 0x0000000000000003; + addrdec_mask[ROW] = 0x0000000007FFE000; + addrdec_mask[COL] = 0x0000000000001FFC; break; - case 103: + case 103: ADDR_CHIP_S = 3; addrdec_mask[CHIP] = 0x0000000000000000; - addrdec_mask[BK] = 0x0000000000000003; - addrdec_mask[ROW] = 0x0000000007FFE000; - addrdec_mask[COL] = 0x0000000000001FFC; + addrdec_mask[BK] = 0x0000000000000003; + addrdec_mask[ROW] = 0x0000000007FFE000; + addrdec_mask[COL] = 0x0000000000001FFC; break; - case 106: + case 106: ADDR_CHIP_S = 6; addrdec_mask[CHIP] = 0x0000000000000000; - addrdec_mask[BK] = 0x0000000000001800; - addrdec_mask[ROW] = 0x0000000007FFE000; - addrdec_mask[COL] = 0x00000000000007FF; + addrdec_mask[BK] = 0x0000000000001800; + addrdec_mask[ROW] = 0x0000000007FFE000; + addrdec_mask[COL] = 0x00000000000007FF; break; - case 160: - // old, added 2row bits, use #define ADDR_CHIP_S 10 + case 160: + //old, added 2row bits, use #define ADDR_CHIP_S 10 ADDR_CHIP_S = 6; addrdec_mask[CHIP] = 0x0000000000000000; - addrdec_mask[BK] = 0x0000000000000300; - addrdec_mask[ROW] = 0x0000000007FFE000; - addrdec_mask[COL] = 0x0000000000001CFF; + addrdec_mask[BK] = 0x0000000000000300; + addrdec_mask[ROW] = 0x0000000007FFE000; + addrdec_mask[COL] = 0x0000000000001CFF; - default: + default: break; - } + } - if (addrdec_option != NULL) addrdec_parseoption(addrdec_option); + if (addrdec_option != NULL) + addrdec_parseoption(addrdec_option); - if (ADDR_CHIP_S != -1) { - if (!gap) { - // number of chip is power of two: - // - insert CHIP mask starting at the bit position ADDR_CHIP_S - mask = ((unsigned long long int)1 << ADDR_CHIP_S) - 1; - addrdec_mask[BK] = - ((addrdec_mask[BK] & ~mask) << nchipbits) | (addrdec_mask[BK] & mask); - addrdec_mask[ROW] = ((addrdec_mask[ROW] & ~mask) << nchipbits) | - (addrdec_mask[ROW] & mask); - addrdec_mask[COL] = ((addrdec_mask[COL] & ~mask) << nchipbits) | - (addrdec_mask[COL] & mask); + if (ADDR_CHIP_S != -1) { + if (!gap) { + // number of chip is power of two: + // - insert CHIP mask starting at the bit position ADDR_CHIP_S + mask = ((unsigned long long int)1 << ADDR_CHIP_S) - 1; + addrdec_mask[BK] = ((addrdec_mask[BK] & ~mask) << nchipbits) | (addrdec_mask[BK] & mask); + addrdec_mask[ROW] = ((addrdec_mask[ROW] & ~mask) << nchipbits) | (addrdec_mask[ROW] & mask); + addrdec_mask[COL] = ((addrdec_mask[COL] & ~mask) << nchipbits) | (addrdec_mask[COL] & mask); - for (i = ADDR_CHIP_S; i < (ADDR_CHIP_S + nchipbits); i++) { - mask = (unsigned long long int)1 << i; - addrdec_mask[CHIP] |= mask; - } - } // otherwise, no need to change the masks - } else { - // make sure n_channel is power of two when explicit dram id mask is used - assert((n_channel & (n_channel - 1)) == 0); - } - // make sure m_n_sub_partition_in_channel is power of two - assert((m_n_sub_partition_in_channel & (m_n_sub_partition_in_channel - 1)) == - 0); + for (i=ADDR_CHIP_S;i<(ADDR_CHIP_S+nchipbits);i++) { + mask = (unsigned long long int)1 << i; + addrdec_mask[CHIP] |= mask; + } + } // otherwise, no need to change the masks + } else { + // make sure n_channel is power of two when explicit dram id mask is used + assert((n_channel & (n_channel - 1)) == 0); + } + // make sure m_n_sub_partition_in_channel is power of two + assert((m_n_sub_partition_in_channel & (m_n_sub_partition_in_channel - 1)) == 0); - addrdec_getmasklimit(addrdec_mask[CHIP], &addrdec_mkhigh[CHIP], - &addrdec_mklow[CHIP]); - addrdec_getmasklimit(addrdec_mask[BK], &addrdec_mkhigh[BK], - &addrdec_mklow[BK]); - addrdec_getmasklimit(addrdec_mask[ROW], &addrdec_mkhigh[ROW], - &addrdec_mklow[ROW]); - addrdec_getmasklimit(addrdec_mask[COL], &addrdec_mkhigh[COL], - &addrdec_mklow[COL]); - addrdec_getmasklimit(addrdec_mask[BURST], &addrdec_mkhigh[BURST], - &addrdec_mklow[BURST]); + addrdec_getmasklimit(addrdec_mask[CHIP], &addrdec_mkhigh[CHIP], &addrdec_mklow[CHIP] ); + addrdec_getmasklimit(addrdec_mask[BK], &addrdec_mkhigh[BK], &addrdec_mklow[BK] ); + addrdec_getmasklimit(addrdec_mask[ROW], &addrdec_mkhigh[ROW], &addrdec_mklow[ROW] ); + addrdec_getmasklimit(addrdec_mask[COL], &addrdec_mkhigh[COL], &addrdec_mklow[COL] ); + addrdec_getmasklimit(addrdec_mask[BURST], &addrdec_mkhigh[BURST], &addrdec_mklow[BURST]); - printf("addr_dec_mask[CHIP] = %016llx \thigh:%d low:%d\n", - addrdec_mask[CHIP], addrdec_mkhigh[CHIP], addrdec_mklow[CHIP]); - printf("addr_dec_mask[BK] = %016llx \thigh:%d low:%d\n", addrdec_mask[BK], - addrdec_mkhigh[BK], addrdec_mklow[BK]); - printf("addr_dec_mask[ROW] = %016llx \thigh:%d low:%d\n", addrdec_mask[ROW], - addrdec_mkhigh[ROW], addrdec_mklow[ROW]); - printf("addr_dec_mask[COL] = %016llx \thigh:%d low:%d\n", addrdec_mask[COL], - addrdec_mkhigh[COL], addrdec_mklow[COL]); - printf("addr_dec_mask[BURST] = %016llx \thigh:%d low:%d\n", - addrdec_mask[BURST], addrdec_mkhigh[BURST], addrdec_mklow[BURST]); + printf("addr_dec_mask[CHIP] = %016llx \thigh:%d low:%d\n", addrdec_mask[CHIP], addrdec_mkhigh[CHIP], addrdec_mklow[CHIP] ); + printf("addr_dec_mask[BK] = %016llx \thigh:%d low:%d\n", addrdec_mask[BK], addrdec_mkhigh[BK], addrdec_mklow[BK] ); + printf("addr_dec_mask[ROW] = %016llx \thigh:%d low:%d\n", addrdec_mask[ROW], addrdec_mkhigh[ROW], addrdec_mklow[ROW] ); + printf("addr_dec_mask[COL] = %016llx \thigh:%d low:%d\n", addrdec_mask[COL], addrdec_mkhigh[COL], addrdec_mklow[COL] ); + printf("addr_dec_mask[BURST] = %016llx \thigh:%d low:%d\n", addrdec_mask[BURST], addrdec_mkhigh[BURST], addrdec_mklow[BURST]); - // create the sub partition ID mask (for removing the sub partition ID from - // the partition address) - sub_partition_id_mask = 0; - if (m_n_sub_partition_in_channel > 1) { - unsigned n_sub_partition_log2 = LOGB2_32(m_n_sub_partition_in_channel); - unsigned pos = 0; - for (unsigned i = addrdec_mklow[BK]; i < addrdec_mkhigh[BK]; i++) { - if ((addrdec_mask[BK] & ((unsigned long long int)1 << i)) != 0) { - sub_partition_id_mask |= ((unsigned long long int)1 << i); - pos++; - if (pos >= n_sub_partition_log2) break; + // create the sub partition ID mask (for removing the sub partition ID from the partition address) + sub_partition_id_mask = 0; + if (m_n_sub_partition_in_channel > 1) { + unsigned n_sub_partition_log2 = LOGB2_32(m_n_sub_partition_in_channel); + unsigned pos=0; + for (unsigned i=addrdec_mklow[BK];i<addrdec_mkhigh[BK];i++) { + if ((addrdec_mask[BK] & ((unsigned long long int)1<<i)) != 0) { + sub_partition_id_mask |= ((unsigned long long int)1<<i); + pos++; + if (pos >= n_sub_partition_log2) + break; + } } - } - } - printf("sub_partition_id_mask = %016llx\n", sub_partition_id_mask); + } + printf("sub_partition_id_mask = %016llx\n", sub_partition_id_mask); + + if (run_test) { + sweep_test(); + } - if (run_test) { - sweep_test(); - } + if(memory_partition_indexing == RANDOM) + srand (1); - if (memory_partition_indexing == RANDOM) srand(1); } -#include "../tr1_hash_map.h" +#include "../tr1_hash_map.h" -bool operator==(const addrdec_t &x, const addrdec_t &y) { - return (memcmp(&x, &y, sizeof(addrdec_t)) == 0); +bool operator==(const addrdec_t &x, const addrdec_t &y) +{ + return ( memcmp(&x, &y, sizeof(addrdec_t)) == 0 ); } -bool operator<(const addrdec_t &x, const addrdec_t &y) { - if (x.chip >= y.chip) - return false; - else if (x.bk >= y.bk) - return false; - else if (x.row >= y.row) - return false; - else if (x.col >= y.col) - return false; - else if (x.burst >= y.burst) - return false; - else - return true; +bool operator<(const addrdec_t &x, const addrdec_t &y) +{ + if (x.chip >= y.chip) return false; + else if (x.bk >= y.bk) return false; + else if (x.row >= y.row) return false; + else if (x.col >= y.col) return false; + else if (x.burst >= y.burst) return false; + else return true; } -class hash_addrdec_t { - public: - size_t operator()(const addrdec_t &x) const { - return (x.chip ^ x.bk ^ x.row ^ x.col ^ x.burst); - } +class hash_addrdec_t +{ +public: + size_t operator()(const addrdec_t &x) const { + return (x.chip ^ x.bk ^ x.row ^ x.col ^ x.burst); + } }; -// a simple sweep test to ensure that two linear addresses are not mapped to the -// same raw address -void linear_to_raw_address_translation::sweep_test() const { - new_addr_type sweep_range = 16 * 1024 * 1024; +// a simple sweep test to ensure that two linear addresses are not mapped to the same raw address +void linear_to_raw_address_translation::sweep_test() const +{ + new_addr_type sweep_range = 16 * 1024 * 1024; #if tr1_hash_map_ismap == 1 - typedef tr1_hash_map<addrdec_t, new_addr_type> history_map_t; + typedef tr1_hash_map<addrdec_t, new_addr_type> history_map_t; #else - typedef tr1_hash_map<addrdec_t, new_addr_type, hash_addrdec_t> history_map_t; + typedef tr1_hash_map<addrdec_t, new_addr_type, hash_addrdec_t> history_map_t; #endif - history_map_t history_map; + history_map_t history_map; - for (new_addr_type raw_addr = 4; raw_addr < sweep_range; raw_addr += 4) { - addrdec_t tlx; - addrdec_tlx(raw_addr, &tlx); + for (new_addr_type raw_addr = 4; raw_addr < sweep_range; raw_addr += 4) { + addrdec_t tlx; + addrdec_tlx(raw_addr, &tlx); - history_map_t::iterator h = history_map.find(tlx); + history_map_t::iterator h = history_map.find(tlx); - if (h != history_map.end()) { - printf( - "[AddrDec] ** Error: address decoding mapping aliases two addresses " - "to same partition with same intra-partition address: %llx %llx\n", - h->second, raw_addr); - abort(); - } else { - assert((int)tlx.chip < m_n_channel); - // ensure that partition_address() returns the concatenated address - if ((ADDR_CHIP_S != -1 and raw_addr >= (1ULL << ADDR_CHIP_S)) or - (ADDR_CHIP_S == -1 and raw_addr >= (1ULL << addrdec_mklow[CHIP]))) { - assert(raw_addr != partition_address(raw_addr)); + if (h != history_map.end()) { + printf("[AddrDec] ** Error: address decoding mapping aliases two addresses to same partition with same intra-partition address: %llx %llx\n", h->second, raw_addr); + abort(); + } else { + assert((int)tlx.chip < m_n_channel); + // ensure that partition_address() returns the concatenated address + if ((ADDR_CHIP_S != -1 and raw_addr >= (1ULL << ADDR_CHIP_S)) or + (ADDR_CHIP_S == -1 and raw_addr >= (1ULL << addrdec_mklow[CHIP]))) { + assert(raw_addr != partition_address(raw_addr)); + } + history_map[tlx] = raw_addr; } - history_map[tlx] = raw_addr; - } - if ((raw_addr & 0xffff) == 0) printf("%llu scaned\n", raw_addr); - } + if ((raw_addr & 0xffff) == 0) printf("%llu scaned\n", raw_addr); + } } -void addrdec_t::print(FILE *fp) const { - fprintf(fp, "\tchip:%x ", chip); - fprintf(fp, "\trow:%x ", row); - fprintf(fp, "\tcol:%x ", col); - fprintf(fp, "\tbk:%x ", bk); - fprintf(fp, "\tburst:%x ", burst); - fprintf(fp, "\tsub_partition:%x ", sub_partition); -} +void addrdec_t::print( FILE *fp ) const +{ + fprintf(fp,"\tchip:%x ", chip); + fprintf(fp,"\trow:%x ", row); + fprintf(fp,"\tcol:%x ", col); + fprintf(fp,"\tbk:%x ", bk); + fprintf(fp,"\tburst:%x ", burst); + fprintf(fp,"\tsub_partition:%x ", sub_partition); +} + -static long int powli(long int x, long int y) // compute x to the y +static long int powli( long int x, long int y ) // compute x to the y { - long int r = 1; - int i; - for (i = 0; i < y; ++i) { - r *= x; - } - return r; + long int r = 1; + int i; + for (i = 0; i < y; ++i ) { + r *= x; + } + return r; } -static unsigned int LOGB2_32(unsigned int v) { - unsigned int shift; - unsigned int r; +static unsigned int LOGB2_32( unsigned int v ) +{ + unsigned int shift; + unsigned int r; - r = 0; + r = 0; - shift = ((v & 0xFFFF0000) != 0) << 4; - v >>= shift; - r |= shift; - shift = ((v & 0xFF00) != 0) << 3; - v >>= shift; - r |= shift; - shift = ((v & 0xF0) != 0) << 2; - v >>= shift; - r |= shift; - shift = ((v & 0xC) != 0) << 1; - v >>= shift; - r |= shift; - shift = ((v & 0x2) != 0) << 0; - v >>= shift; - r |= shift; + shift = (( v & 0xFFFF0000) != 0 ) << 4; v >>= shift; r |= shift; + shift = (( v & 0xFF00 ) != 0 ) << 3; v >>= shift; r |= shift; + shift = (( v & 0xF0 ) != 0 ) << 2; v >>= shift; r |= shift; + shift = (( v & 0xC ) != 0 ) << 1; v >>= shift; r |= shift; + shift = (( v & 0x2 ) != 0 ) << 0; v >>= shift; r |= shift; - return r; + return r; } -static new_addr_type addrdec_packbits(new_addr_type mask, new_addr_type val, - unsigned char high, unsigned char low) { - unsigned pos = 0; - new_addr_type result = 0; - for (unsigned i = low; i < high; i++) { - if ((mask & ((unsigned long long int)1 << i)) != 0) { - result |= ((val & ((unsigned long long int)1 << i)) >> i) << pos; - pos++; - } - } - return result; +static new_addr_type addrdec_packbits( new_addr_type mask, new_addr_type val, unsigned char high, unsigned char low) +{ + unsigned pos=0; + new_addr_type result = 0; + for (unsigned i=low;i<high;i++) { + if ((mask & ((unsigned long long int)1<<i)) != 0) { + result |= ((val & ((unsigned long long int)1<<i)) >> i) << pos; + pos++; + } + } + return result; } -static void addrdec_getmasklimit(new_addr_type mask, unsigned char *high, - unsigned char *low) { - *high = 64; - *low = 0; - int i; - int low_found = 0; +static void addrdec_getmasklimit(new_addr_type mask, unsigned char *high, unsigned char *low) +{ + *high = 64; + *low = 0; + int i; + int low_found = 0; - for (i = 0; i < 64; i++) { - if ((mask & ((unsigned long long int)1 << i)) != 0) { - if (low_found) { - *high = i + 1; - } else { - *high = i + 1; - *low = i; - low_found = 1; + for (i=0;i<64;i++) { + if ((mask & ((unsigned long long int)1<<i)) != 0) { + if (low_found) { + *high = i + 1; + } else { + *high = i + 1; + *low = i; + low_found = 1; + } } - } - } + } } diff --git a/src/gpgpu-sim/addrdec.h b/src/gpgpu-sim/addrdec.h index 0919942..c9a1420 100644 --- a/src/gpgpu-sim/addrdec.h +++ b/src/gpgpu-sim/addrdec.h @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -27,9 +25,9 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include <assert.h> #include <stdio.h> #include <stdlib.h> +#include <assert.h> #include "../option_parser.h" #ifndef ADDRDEC_H @@ -37,57 +35,66 @@ #include "../abstract_hardware_model.h" -enum partition_index_function { - CONSECUTIVE = 0, - BITWISE_PERMUTATION, - IPOLY, - PAE, - RANDOM, - CUSTOM +enum partition_index_function{ + CONSECUTIVE = 0, + BITWISE_PERMUTATION, + IPOLY, + PAE, + RANDOM, + CUSTOM }; struct addrdec_t { - void print(FILE *fp) const; - - unsigned chip; - unsigned bk; - unsigned row; - unsigned col; - unsigned burst; + void print( FILE *fp ) const; + + unsigned chip; + unsigned bk; + unsigned row; + unsigned col; + unsigned burst; - unsigned sub_partition; + unsigned sub_partition; }; + class linear_to_raw_address_translation { - public: - linear_to_raw_address_translation(); - void addrdec_setoption(option_parser_t opp); - void init(unsigned int n_channel, unsigned int n_sub_partition_in_channel); +public: + linear_to_raw_address_translation(); + void addrdec_setoption(option_parser_t opp); + void init(unsigned int n_channel, unsigned int n_sub_partition_in_channel); + + // accessors + void addrdec_tlx(new_addr_type addr, addrdec_t *tlx) const; + new_addr_type partition_address( new_addr_type addr ) const; - // accessors - void addrdec_tlx(new_addr_type addr, addrdec_t *tlx) const; - new_addr_type partition_address(new_addr_type addr) const; +private: + void addrdec_parseoption(const char *option); + void sweep_test() const; // sanity check to ensure no overlapping - private: - void addrdec_parseoption(const char *option); - void sweep_test() const; // sanity check to ensure no overlapping + enum { + CHIP = 0, + BK = 1, + ROW = 2, + COL = 3, + BURST = 4, + N_ADDRDEC + }; - enum { CHIP = 0, BK = 1, ROW = 2, COL = 3, BURST = 4, N_ADDRDEC }; + const char *addrdec_option; + int gpgpu_mem_address_mask; + partition_index_function memory_partition_indexing; + bool run_test; - const char *addrdec_option; - int gpgpu_mem_address_mask; - partition_index_function memory_partition_indexing; - bool run_test; + int ADDR_CHIP_S; + unsigned char addrdec_mklow[N_ADDRDEC]; + unsigned char addrdec_mkhigh[N_ADDRDEC]; + new_addr_type addrdec_mask[N_ADDRDEC]; + new_addr_type sub_partition_id_mask; - int ADDR_CHIP_S; - unsigned char addrdec_mklow[N_ADDRDEC]; - unsigned char addrdec_mkhigh[N_ADDRDEC]; - new_addr_type addrdec_mask[N_ADDRDEC]; - new_addr_type sub_partition_id_mask; + unsigned int gap; + unsigned m_n_channel; + int m_n_sub_partition_in_channel; - unsigned int gap; - unsigned m_n_channel; - int m_n_sub_partition_in_channel; }; #endif diff --git a/src/gpgpu-sim/delayqueue.h b/src/gpgpu-sim/delayqueue.h index d96454c..0caa5d4 100644 --- a/src/gpgpu-sim/delayqueue.h +++ b/src/gpgpu-sim/delayqueue.h @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -27,8 +25,8 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include <assert.h> #include <stdio.h> +#include <assert.h> #include <stdlib.h> #ifndef DELAYQUEUE_H @@ -39,150 +37,157 @@ template <class T> struct fifo_data { - T* m_data; - fifo_data* m_next; + T *m_data; + fifo_data *m_next; }; -template <class T> +template <class T> class fifo_pipeline { - public: - fifo_pipeline(const char* nm, unsigned int minlen, unsigned int maxlen) { - assert(maxlen); - m_name = nm; - m_min_len = minlen; - m_max_len = maxlen; - m_length = 0; - m_n_element = 0; - m_head = NULL; - m_tail = NULL; - for (unsigned i = 0; i < m_min_len; i++) push(NULL); - } - - ~fifo_pipeline() { - while (m_head) { - m_tail = m_head; - m_head = m_head->m_next; - delete m_tail; - } - } +public: + fifo_pipeline(const char* nm, unsigned int minlen, unsigned int maxlen ) + { + assert(maxlen); + m_name = nm; + m_min_len = minlen; + m_max_len = maxlen; + m_length = 0; + m_n_element = 0; + m_head = NULL; + m_tail = NULL; + for (unsigned i=0;i<m_min_len;i++) + push(NULL); + } - void push(T* data) { - assert(m_length < m_max_len); - if (m_head) { - if (m_tail->m_data || m_length < m_min_len) { - m_tail->m_next = new fifo_data<T>(); - m_tail = m_tail->m_next; - m_length++; - m_n_element++; + ~fifo_pipeline() + { + while (m_head) { + m_tail = m_head; + m_head = m_head->m_next; + delete m_tail; } - } else { - m_head = m_tail = new fifo_data<T>(); - m_length++; - m_n_element++; - } - m_tail->m_next = NULL; - m_tail->m_data = data; - } + } - T* pop() { - fifo_data<T>* next; - T* data; - if (m_head) { - next = m_head->m_next; - data = m_head->m_data; - if (m_head == m_tail) { - assert(next == NULL); - m_tail = NULL; + void push(T* data ) + { + assert(m_length < m_max_len); + if (m_head) { + if (m_tail->m_data || m_length < m_min_len) { + m_tail->m_next = new fifo_data<T>(); + m_tail = m_tail->m_next; + m_length++; + m_n_element++; + } + } else { + m_head = m_tail = new fifo_data<T>(); + m_length++; + m_n_element++; } - delete m_head; - m_head = next; - m_length--; - if (m_length == 0) { - assert(m_head == NULL); - m_tail = m_head; - } - m_n_element--; - if (m_min_len && m_length < m_min_len) { - push(NULL); - m_n_element--; // uncount NULL elements inserted to create delays - } - } else { - data = NULL; - } - return data; - } - - T* top() const { - if (m_head) { - return m_head->m_data; - } else { - return NULL; - } - } + m_tail->m_next = NULL; + m_tail->m_data = data; + } - void set_min_length(unsigned int new_min_len) { - if (new_min_len == m_min_len) return; + T* pop() + { + fifo_data<T>* next; + T* data; + if (m_head) { + next = m_head->m_next; + data = m_head->m_data; + if ( m_head == m_tail ) { + assert( next == NULL ); + m_tail = NULL; + } + delete m_head; + m_head = next; + m_length--; + if (m_length == 0) { + assert( m_head == NULL ); + m_tail = m_head; + } + m_n_element--; + if (m_min_len && m_length < m_min_len) { + push(NULL); + m_n_element--; // uncount NULL elements inserted to create delays + } + } else { + data = NULL; + } + return data; + } - if (new_min_len > m_min_len) { - m_min_len = new_min_len; - while (m_length < m_min_len) { - push(NULL); - m_n_element--; // uncount NULL elements inserted to create delays + T* top() const + { + if (m_head) { + return m_head->m_data; + } else { + return NULL; } - } else { - // in this branch imply that the original min_len is larger then 0 - // ie. head != 0 - assert(m_head); - m_min_len = new_min_len; - while ((m_length > m_min_len) && (m_tail->m_data == 0)) { - fifo_data<T>* iter; - iter = m_head; - while (iter && (iter->m_next != m_tail)) iter = iter->m_next; - if (!iter) { - // there is only one node, and that node is empty - assert(m_head->m_data == 0); - pop(); - } else { - // there are more than one node, and tail node is empty - assert(iter->m_next == m_tail); - delete m_tail; - m_tail = iter; - m_tail->m_next = 0; - m_length--; - } + } + + void set_min_length(unsigned int new_min_len) + { + if (new_min_len == m_min_len) return; + + if (new_min_len > m_min_len) { + m_min_len = new_min_len; + while (m_length < m_min_len) { + push(NULL); + m_n_element--; // uncount NULL elements inserted to create delays + } + } else { + // in this branch imply that the original min_len is larger then 0 + // ie. head != 0 + assert(m_head); + m_min_len = new_min_len; + while ((m_length > m_min_len) && (m_tail->m_data == 0)) { + fifo_data<T> *iter; + iter = m_head; + while (iter && (iter->m_next != m_tail)) + iter = iter->m_next; + if (!iter) { + // there is only one node, and that node is empty + assert(m_head->m_data == 0); + pop(); + } else { + // there are more than one node, and tail node is empty + assert(iter->m_next == m_tail); + delete m_tail; + m_tail = iter; + m_tail->m_next = 0; + m_length--; + } + } } - } - } + } - bool full() const { return (m_max_len && m_length >= m_max_len); } - bool is_avilable_size(unsigned size) const { - return (m_max_len && m_length + size - 1 >= m_max_len); - } - bool empty() const { return m_head == NULL; } - unsigned get_n_element() const { return m_n_element; } - unsigned get_length() const { return m_length; } - unsigned get_max_len() const { return m_max_len; } + bool full() const { return (m_max_len && m_length >= m_max_len); } + bool is_avilable_size(unsigned size) const { return (m_max_len && m_length+size-1 >= m_max_len); } + bool empty() const { return m_head == NULL; } + unsigned get_n_element() const { return m_n_element; } + unsigned get_length() const { return m_length; } + unsigned get_max_len() const { return m_max_len; } - void print() const { - fifo_data<T>* ddp = m_head; - printf("%s(%d): ", m_name, m_length); - while (ddp) { - printf("%p ", ddp->m_data); - ddp = ddp->m_next; - } - printf("\n"); - } + void print() const + { + fifo_data<T>* ddp = m_head; + printf("%s(%d): ", m_name, m_length); + while (ddp) { + printf("%p ", ddp->m_data); + ddp = ddp->m_next; + } + printf("\n"); + } - private: - const char* m_name; +private: + const char* m_name; - unsigned int m_min_len; - unsigned int m_max_len; - unsigned int m_length; - unsigned int m_n_element; + unsigned int m_min_len; + unsigned int m_max_len; + unsigned int m_length; + unsigned int m_n_element; - fifo_data<T>* m_head; - fifo_data<T>* m_tail; + fifo_data<T> *m_head; + fifo_data<T> *m_tail; }; #endif diff --git a/src/gpgpu-sim/dram.cc b/src/gpgpu-sim/dram.cc index 0a4bc86..9c33822 100644 --- a/src/gpgpu-sim/dram.cc +++ b/src/gpgpu-sim/dram.cc @@ -8,16 +8,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -28,13 +26,13 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include "gpu-sim.h" +#include "gpu-misc.h" #include "dram.h" +#include "mem_latency_stat.h" #include "dram_sched.h" -#include "gpu-misc.h" -#include "gpu-sim.h" -#include "l2cache.h" #include "mem_fetch.h" -#include "mem_latency_stat.h" +#include "l2cache.h" #ifdef DRAM_VERIFY int PRINT_CYCLE = 0; @@ -43,828 +41,869 @@ int PRINT_CYCLE = 0; template class fifo_pipeline<mem_fetch>; template class fifo_pipeline<dram_req_t>; -dram_t::dram_t(unsigned int partition_id, const memory_config *config, - memory_stats_t *stats, memory_partition_unit *mp, - gpgpu_sim *gpu) { - id = partition_id; - m_memory_partition_unit = mp; - m_stats = stats; - m_config = config; - m_gpu = gpu; +dram_t::dram_t( unsigned int partition_id, const memory_config *config, memory_stats_t *stats, + memory_partition_unit *mp, gpgpu_sim* gpu ) +{ + id = partition_id; + m_memory_partition_unit = mp; + m_stats = stats; + m_config = config; + m_gpu = gpu; - // rowblp - access_num = 0; - hits_num = 0; - read_num = 0; - write_num = 0; - hits_read_num = 0; - hits_write_num = 0; - banks_1time = 0; - banks_acess_total = 0; - banks_acess_total_after = 0; - banks_time_ready = 0; - banks_access_ready_total = 0; - issued_two = 0; - issued_total = 0; - issued_total_row = 0; - issued_total_col = 0; + //rowblp + access_num=0; + hits_num=0; + read_num=0; + write_num=0; + hits_read_num=0; + hits_write_num=0; + banks_1time=0; + banks_acess_total=0; + banks_acess_total_after=0; + banks_time_ready=0; + banks_access_ready_total=0; + issued_two=0; + issued_total=0; + issued_total_row=0; + issued_total_col=0; - CCDc = 0; - RRDc = 0; - RTWc = 0; - WTRc = 0; + CCDc = 0; + RRDc = 0; + RTWc = 0; + WTRc = 0; - wasted_bw_row = 0; - wasted_bw_col = 0; - util_bw = 0; - idle_bw = 0; - RCDc_limit = 0; - CCDLc_limit = 0; - CCDLc_limit_alone = 0; - CCDc_limit = 0; - WTRc_limit = 0; - WTRc_limit_alone = 0; - RCDWRc_limit = 0; - RTWc_limit = 0; - RTWc_limit_alone = 0; - rwq_limit = 0; - write_to_read_ratio_blp_rw_average = 0; - bkgrp_parallsim_rw = 0; + wasted_bw_row=0; + wasted_bw_col=0; + util_bw=0; + idle_bw=0; + RCDc_limit=0; + CCDLc_limit=0; + CCDLc_limit_alone=0; + CCDc_limit=0; + WTRc_limit=0; + WTRc_limit_alone=0; + RCDWRc_limit=0; + RTWc_limit=0; + RTWc_limit_alone=0; + rwq_limit=0; + write_to_read_ratio_blp_rw_average=0; + bkgrp_parallsim_rw=0; - rw = READ; // read mode is default + rw = READ; //read mode is default - bkgrp = (bankgrp_t **)calloc(sizeof(bankgrp_t *), m_config->nbkgrp); - bkgrp[0] = (bankgrp_t *)calloc(sizeof(bank_t), m_config->nbkgrp); - for (unsigned i = 1; i < m_config->nbkgrp; i++) { - bkgrp[i] = bkgrp[0] + i; - } - for (unsigned i = 0; i < m_config->nbkgrp; i++) { - bkgrp[i]->CCDLc = 0; - bkgrp[i]->RTPLc = 0; - } + bkgrp = (bankgrp_t**) calloc(sizeof(bankgrp_t*), m_config->nbkgrp); + bkgrp[0] = (bankgrp_t*) calloc(sizeof(bank_t), m_config->nbkgrp); + for (unsigned i=1; i<m_config->nbkgrp; i++) { + bkgrp[i] = bkgrp[0] + i; + } + for (unsigned i=0; i<m_config->nbkgrp; i++) { + bkgrp[i]->CCDLc = 0; + bkgrp[i]->RTPLc = 0; + } - bk = (bank_t **)calloc(sizeof(bank_t *), m_config->nbk); - bk[0] = (bank_t *)calloc(sizeof(bank_t), m_config->nbk); - for (unsigned i = 1; i < m_config->nbk; i++) bk[i] = bk[0] + i; - for (unsigned i = 0; i < m_config->nbk; i++) { - bk[i]->state = BANK_IDLE; - bk[i]->bkgrpindex = i / (m_config->nbk / m_config->nbkgrp); - } - prio = 0; + bk = (bank_t**) calloc(sizeof(bank_t*),m_config->nbk); + bk[0] = (bank_t*) calloc(sizeof(bank_t),m_config->nbk); + for (unsigned i=1;i<m_config->nbk;i++) + bk[i] = bk[0] + i; + for (unsigned i=0;i<m_config->nbk;i++) { + bk[i]->state = BANK_IDLE; + bk[i]->bkgrpindex = i/(m_config->nbk/m_config->nbkgrp); + } + prio = 0; - rwq = new fifo_pipeline<dram_req_t>("rwq", m_config->CL, m_config->CL + 1); - mrqq = new fifo_pipeline<dram_req_t>("mrqq", 0, 2); - returnq = new fifo_pipeline<mem_fetch>( - "dramreturnq", 0, m_config->gpgpu_dram_return_queue_size == 0 - ? 1024 - : m_config->gpgpu_dram_return_queue_size); - m_frfcfs_scheduler = NULL; - if (m_config->scheduler_type == DRAM_FRFCFS) - m_frfcfs_scheduler = new frfcfs_scheduler(m_config, this, stats); - n_cmd = 0; - n_activity = 0; - n_nop = 0; - n_act = 0; - n_pre = 0; - n_rd = 0; - n_wr = 0; - n_wr_WB = 0; - n_rd_L2_A = 0; - n_req = 0; - max_mrqs_temp = 0; - bwutil = 0; - max_mrqs = 0; - ave_mrqs = 0; + rwq = new fifo_pipeline<dram_req_t>("rwq",m_config->CL,m_config->CL+1); + mrqq = new fifo_pipeline<dram_req_t>("mrqq",0,2); + returnq = new fifo_pipeline<mem_fetch>("dramreturnq",0,m_config->gpgpu_dram_return_queue_size==0?1024:m_config->gpgpu_dram_return_queue_size); + m_frfcfs_scheduler = NULL; + if ( m_config->scheduler_type == DRAM_FRFCFS) + m_frfcfs_scheduler = new frfcfs_scheduler(m_config,this,stats); + n_cmd = 0; + n_activity = 0; + n_nop = 0; + n_act = 0; + n_pre = 0; + n_rd = 0; + n_wr = 0; + n_wr_WB=0; + n_rd_L2_A=0; + n_req = 0; + max_mrqs_temp = 0; + bwutil = 0; + max_mrqs = 0; + ave_mrqs = 0; - for (unsigned i = 0; i < 10; i++) { - dram_util_bins[i] = 0; - dram_eff_bins[i] = 0; - } - last_n_cmd = last_n_activity = last_bwutil = 0; + for (unsigned i=0;i<10;i++) { + dram_util_bins[i]=0; + dram_eff_bins[i]=0; + } + last_n_cmd = last_n_activity = last_bwutil = 0; - n_cmd_partial = 0; - n_activity_partial = 0; - n_nop_partial = 0; - n_act_partial = 0; - n_pre_partial = 0; - n_req_partial = 0; - ave_mrqs_partial = 0; - bwutil_partial = 0; + n_cmd_partial = 0; + n_activity_partial = 0; + n_nop_partial = 0; + n_act_partial = 0; + n_pre_partial = 0; + n_req_partial = 0; + ave_mrqs_partial = 0; + bwutil_partial = 0; + + if ( queue_limit() ) + mrqq_Dist = StatCreate("mrqq_length",1, queue_limit()); + else //queue length is unlimited; + mrqq_Dist = StatCreate("mrqq_length",1,64); //track up to 64 entries - if (queue_limit()) - mrqq_Dist = StatCreate("mrqq_length", 1, queue_limit()); - else // queue length is unlimited; - mrqq_Dist = StatCreate("mrqq_length", 1, 64); // track up to 64 entries } -bool dram_t::full(bool is_write) const { - if (m_config->scheduler_type == DRAM_FRFCFS) { - if (m_config->gpgpu_frfcfs_dram_sched_queue_size == 0) return false; - if (m_config->seperate_write_queue_enabled) { - if (is_write) - return m_frfcfs_scheduler->num_write_pending() >= - m_config->gpgpu_frfcfs_dram_write_queue_size; - else - return m_frfcfs_scheduler->num_pending() >= - m_config->gpgpu_frfcfs_dram_sched_queue_size; - } else - return m_frfcfs_scheduler->num_pending() >= - m_config->gpgpu_frfcfs_dram_sched_queue_size; - } else - return mrqq->full(); +bool dram_t::full(bool is_write) const +{ + if(m_config->scheduler_type == DRAM_FRFCFS){ + if(m_config->gpgpu_frfcfs_dram_sched_queue_size == 0 ) return false; + if(m_config->seperate_write_queue_enabled){ + if(is_write) + return m_frfcfs_scheduler->num_write_pending() >= m_config->gpgpu_frfcfs_dram_write_queue_size; + else + return m_frfcfs_scheduler->num_pending() >= m_config->gpgpu_frfcfs_dram_sched_queue_size; + } + else + return m_frfcfs_scheduler->num_pending() >= m_config->gpgpu_frfcfs_dram_sched_queue_size; + } + else return mrqq->full(); } -unsigned dram_t::que_length() const { - unsigned nreqs = 0; - if (m_config->scheduler_type == DRAM_FRFCFS) { - nreqs = m_frfcfs_scheduler->num_pending(); - } else { - nreqs = mrqq->get_length(); - } - return nreqs; +unsigned dram_t::que_length() const +{ + unsigned nreqs = 0; + if (m_config->scheduler_type == DRAM_FRFCFS) { + nreqs = m_frfcfs_scheduler->num_pending(); + } else { + nreqs = mrqq->get_length(); + } + return nreqs; } -bool dram_t::returnq_full() const { return returnq->full(); } +bool dram_t::returnq_full() const +{ + return returnq->full(); +} -unsigned int dram_t::queue_limit() const { - return m_config->gpgpu_frfcfs_dram_sched_queue_size; +unsigned int dram_t::queue_limit() const +{ + return m_config->gpgpu_frfcfs_dram_sched_queue_size; } -dram_req_t::dram_req_t(class mem_fetch *mf, unsigned banks, - unsigned dram_bnk_indexing_policy, - class gpgpu_sim *gpu) { - txbytes = 0; - dqbytes = 0; - data = mf; - m_gpu = gpu; - const addrdec_t &tlx = mf->get_tlx_addr(); +dram_req_t::dram_req_t( class mem_fetch *mf, unsigned banks, unsigned dram_bnk_indexing_policy, class gpgpu_sim* gpu) +{ + txbytes = 0; + dqbytes = 0; + data = mf; + m_gpu = gpu; - switch (dram_bnk_indexing_policy) { - case LINEAR_BK_INDEX: { - bk = tlx.bk; - break; - } - case BITWISE_XORING_BK_INDEX: { - // xoring bank bits with lower bits of the page - int lbank = log2(banks); - bk = tlx.bk ^ (tlx.row & ((1 << lbank) - 1)); - break; - } - case CUSTOM_BK_INDEX: - /* No custom set function implemented */ - // Do you custom index here - break; - default: - assert("\nUndefined bank index function.\n" && 0); - break; - } + const addrdec_t &tlx = mf->get_tlx_addr(); + + switch(dram_bnk_indexing_policy){ + case LINEAR_BK_INDEX: + { + bk = tlx.bk; + break; + } + case BITWISE_XORING_BK_INDEX: + { + //xoring bank bits with lower bits of the page + int lbank = log2(banks); + bk = tlx.bk ^ (tlx.row & ((1<<lbank)-1)); + break; + } + case CUSTOM_BK_INDEX: + /* No custom set function implemented */ + //Do you custom index here + break; + default: + assert("\nUndefined bank index function.\n" && 0); + break; + } - row = tlx.row; - col = tlx.col; - nbytes = mf->get_data_size(); - timestamp = m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle; - addr = mf->get_addr(); - insertion_time = (unsigned)m_gpu->gpu_sim_cycle; - rw = data->get_is_write() ? WRITE : READ; + row = tlx.row; + col = tlx.col; + nbytes = mf->get_data_size(); + + timestamp = m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle; + addr = mf->get_addr(); + insertion_time = (unsigned) m_gpu->gpu_sim_cycle; + rw = data->get_is_write()?WRITE:READ; } -void dram_t::push(class mem_fetch *data) { - assert(id == - data->get_tlx_addr() - .chip); // Ensure request is in correct memory partition +void dram_t::push( class mem_fetch *data ) +{ + assert(id == data->get_tlx_addr().chip); // Ensure request is in correct memory partition - dram_req_t *mrq = - new dram_req_t(data, m_config->nbk, m_config->dram_bnk_indexing_policy, - m_memory_partition_unit->get_mgpu()); + dram_req_t *mrq = new dram_req_t(data,m_config->nbk,m_config->dram_bnk_indexing_policy,m_memory_partition_unit->get_mgpu()); - data->set_status(IN_PARTITION_MC_INTERFACE_QUEUE, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - mrqq->push(mrq); + data->set_status(IN_PARTITION_MC_INTERFACE_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); + mrqq->push(mrq); - // stats... - n_req += 1; - n_req_partial += 1; - if (m_config->scheduler_type == DRAM_FRFCFS) { - unsigned nreqs = m_frfcfs_scheduler->num_pending(); - if (nreqs > max_mrqs_temp) max_mrqs_temp = nreqs; - } else { - max_mrqs_temp = (max_mrqs_temp > mrqq->get_length()) ? max_mrqs_temp - : mrqq->get_length(); - } - m_stats->memlatstat_dram_access(data); + // stats... + n_req += 1; + n_req_partial += 1; + if ( m_config->scheduler_type == DRAM_FRFCFS) { + unsigned nreqs = m_frfcfs_scheduler->num_pending(); + if ( nreqs > max_mrqs_temp) + max_mrqs_temp = nreqs; + } else { + max_mrqs_temp = (max_mrqs_temp > mrqq->get_length())? max_mrqs_temp : mrqq->get_length(); + } + m_stats->memlatstat_dram_access(data); } -void dram_t::scheduler_fifo() { - if (!mrqq->empty()) { - unsigned int bkn; - dram_req_t *head_mrqq = mrqq->top(); - head_mrqq->data->set_status( - IN_PARTITION_MC_BANK_ARB_QUEUE, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - bkn = head_mrqq->bk; - if (!bk[bkn]->mrq) bk[bkn]->mrq = mrqq->pop(); - } +void dram_t::scheduler_fifo() +{ + if (!mrqq->empty()) { + unsigned int bkn; + dram_req_t *head_mrqq = mrqq->top(); + head_mrqq->data->set_status(IN_PARTITION_MC_BANK_ARB_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); + bkn = head_mrqq->bk; + if (!bk[bkn]->mrq) + bk[bkn]->mrq = mrqq->pop(); + } } -#define DEC2ZERO(x) x = (x) ? (x - 1) : 0; -#define SWAP(a, b) \ - a ^= b; \ - b ^= a; \ - a ^= b; -void dram_t::cycle() { - if (!returnq->full()) { - dram_req_t *cmd = rwq->pop(); - if (cmd) { -#ifdef DRAM_VIEWCMD - printf("\tDQ: BK%d Row:%03x Col:%03x", cmd->bk, cmd->row, - cmd->col + cmd->dqbytes); +#define DEC2ZERO(x) x = (x)? (x-1) : 0; +#define SWAP(a,b) a ^= b; b ^= a; a ^= b; + +void dram_t::cycle() +{ + + if( !returnq->full() ) { + dram_req_t *cmd = rwq->pop(); + if( cmd ) { +#ifdef DRAM_VIEWCMD + printf("\tDQ: BK%d Row:%03x Col:%03x", cmd->bk, cmd->row, cmd->col + cmd->dqbytes); #endif - cmd->dqbytes += m_config->dram_atom_size; + cmd->dqbytes += m_config->dram_atom_size; - if (cmd->dqbytes >= cmd->nbytes) { - mem_fetch *data = cmd->data; - data->set_status(IN_PARTITION_MC_RETURNQ, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - if (data->get_access_type() != L1_WRBK_ACC && - data->get_access_type() != L2_WRBK_ACC) { - data->set_reply(); - returnq->push(data); - } else { - m_memory_partition_unit->set_done(data); - delete data; - } - delete cmd; - } -#ifdef DRAM_VIEWCMD - printf("\n"); + if (cmd->dqbytes >= cmd->nbytes) { + mem_fetch *data = cmd->data; + data->set_status(IN_PARTITION_MC_RETURNQ,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); + if( data->get_access_type() != L1_WRBK_ACC && data->get_access_type() != L2_WRBK_ACC ) { + data->set_reply(); + returnq->push(data); + } else { + m_memory_partition_unit->set_done(data); + delete data; + } + delete cmd; + } +#ifdef DRAM_VIEWCMD + printf("\n"); #endif - } - } + } + } - /* check if the upcoming request is on an idle bank */ - /* Should we modify this so that multiple requests are checked? */ + /* check if the upcoming request is on an idle bank */ + /* Should we modify this so that multiple requests are checked? */ - switch (m_config->scheduler_type) { - case DRAM_FIFO: - scheduler_fifo(); - break; - case DRAM_FRFCFS: - scheduler_frfcfs(); - break; - default: - printf("Error: Unknown DRAM scheduler type\n"); - assert(0); - } - if (m_config->scheduler_type == DRAM_FRFCFS) { - unsigned nreqs = m_frfcfs_scheduler->num_pending(); - if (nreqs > max_mrqs) { - max_mrqs = nreqs; - } - ave_mrqs += nreqs; - ave_mrqs_partial += nreqs; - } else { - if (mrqq->get_length() > max_mrqs) { - max_mrqs = mrqq->get_length(); - } - ave_mrqs += mrqq->get_length(); - ave_mrqs_partial += mrqq->get_length(); - } + switch (m_config->scheduler_type) { + case DRAM_FIFO: scheduler_fifo(); break; + case DRAM_FRFCFS: scheduler_frfcfs(); break; + default: + printf("Error: Unknown DRAM scheduler type\n"); + assert(0); + } + if ( m_config->scheduler_type == DRAM_FRFCFS) { + unsigned nreqs = m_frfcfs_scheduler->num_pending(); + if ( nreqs > max_mrqs) { + max_mrqs = nreqs; + } + ave_mrqs += nreqs; + ave_mrqs_partial += nreqs; + } else { + if (mrqq->get_length() > max_mrqs) { + max_mrqs = mrqq->get_length(); + } + ave_mrqs += mrqq->get_length(); + ave_mrqs_partial += mrqq->get_length(); + } - unsigned k = m_config->nbk; - bool issued = false; + unsigned k=m_config->nbk; + bool issued = false; - // collect row buffer locality, BLP and other statistics - ///////////////////////////////////////////////////////////////////////// - unsigned int memory_pending = 0; - for (unsigned i = 0; i < m_config->nbk; i++) { - if (bk[i]->mrq) memory_pending++; - } - banks_1time += memory_pending; - if (memory_pending > 0) banks_acess_total++; + //collect row buffer locality, BLP and other statistics + ///////////////////////////////////////////////////////////////////////// + unsigned int memory_pending=0; + for (unsigned i=0;i<m_config->nbk;i++) { + if (bk[i]->mrq) + memory_pending++; + } + banks_1time += memory_pending; + if(memory_pending >0) + banks_acess_total++; - unsigned int memory_pending_rw = 0; - unsigned read_blp_rw = 0; - unsigned write_blp_rw = 0; - std::bitset<8> bnkgrp_rw_found; // assume max we have 8 bank groups + unsigned int memory_pending_rw=0; + unsigned read_blp_rw=0; + unsigned write_blp_rw=0; + std::bitset<8> bnkgrp_rw_found; //assume max we have 8 bank groups - for (unsigned j = 0; j < m_config->nbk; j++) { - unsigned grp = get_bankgrp_number(j); - if (bk[j]->mrq && - (((bk[j]->curr_row == bk[j]->mrq->row) && (bk[j]->mrq->rw == READ) && - (bk[j]->state == BANK_ACTIVE)))) { - memory_pending_rw++; - read_blp_rw++; - bnkgrp_rw_found.set(grp); - } else if (bk[j]->mrq && - (((bk[j]->curr_row == bk[j]->mrq->row) && - (bk[j]->mrq->rw == WRITE) && (bk[j]->state == BANK_ACTIVE)))) { - memory_pending_rw++; - write_blp_rw++; - bnkgrp_rw_found.set(grp); - } - } - banks_time_rw += memory_pending_rw; - bkgrp_parallsim_rw += bnkgrp_rw_found.count(); - if (memory_pending_rw > 0) { - write_to_read_ratio_blp_rw_average += - (double)write_blp_rw / (write_blp_rw + read_blp_rw); - banks_access_rw_total++; - } + for (unsigned j=0;j<m_config->nbk;j++) { + unsigned grp = get_bankgrp_number(j); + if (bk[j]->mrq && (((bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == READ) && + (bk[j]->state == BANK_ACTIVE)))) + { + memory_pending_rw++; + read_blp_rw++; + bnkgrp_rw_found.set(grp); + } + else if + (bk[j]->mrq && (((bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == WRITE) && + (bk[j]->state == BANK_ACTIVE)))) + { + memory_pending_rw++; + write_blp_rw++; + bnkgrp_rw_found.set(grp); + } + } + banks_time_rw += memory_pending_rw; + bkgrp_parallsim_rw += bnkgrp_rw_found.count(); + if(memory_pending_rw >0) + { + write_to_read_ratio_blp_rw_average += (double)write_blp_rw/(write_blp_rw+read_blp_rw); + banks_access_rw_total++; + } - unsigned int memory_Pending_ready = 0; - for (unsigned j = 0; j < m_config->nbk; j++) { - unsigned grp = get_bankgrp_number(j); - if (bk[j]->mrq && - ((!CCDc && !bk[j]->RCDc && !(bkgrp[grp]->CCDLc) && - (bk[j]->curr_row == bk[j]->mrq->row) && (bk[j]->mrq->rw == READ) && - (WTRc == 0) && (bk[j]->state == BANK_ACTIVE) && !rwq->full()) || - (!CCDc && !bk[j]->RCDWRc && !(bkgrp[grp]->CCDLc) && - (bk[j]->curr_row == bk[j]->mrq->row) && (bk[j]->mrq->rw == WRITE) && - (RTWc == 0) && (bk[j]->state == BANK_ACTIVE) && !rwq->full()))) { - memory_Pending_ready++; - } - } - banks_time_ready += memory_Pending_ready; - if (memory_Pending_ready > 0) banks_access_ready_total++; - /////////////////////////////////////////////////////////////////////////////////// + unsigned int memory_Pending_ready=0; + for (unsigned j=0;j<m_config->nbk;j++) { + unsigned grp = get_bankgrp_number(j); + if (bk[j]->mrq && ((!CCDc && !bk[j]->RCDc && + !(bkgrp[grp]->CCDLc) && + (bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == READ) && (WTRc == 0 ) && + (bk[j]->state == BANK_ACTIVE) && + !rwq->full()) + || + (!CCDc && !bk[j]->RCDWRc && + !(bkgrp[grp]->CCDLc) && + (bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == WRITE) && (RTWc == 0 ) && + (bk[j]->state == BANK_ACTIVE) && + !rwq->full()))) + { + memory_Pending_ready++; + } + } + banks_time_ready += memory_Pending_ready; + if(memory_Pending_ready >0) + banks_access_ready_total++; + /////////////////////////////////////////////////////////////////////////////////// - bool issued_col_cmd = false; - bool issued_row_cmd = false; + bool issued_col_cmd = false; + bool issued_row_cmd = false; - if (m_config->dual_bus_interface) { - // dual bus interface - // issue one row command and one column command - for (unsigned i = 0; i < m_config->nbk; i++) { - unsigned j = (i + prio) % m_config->nbk; - issued_col_cmd = issue_col_command(j); - if (issued_col_cmd) break; - } - for (unsigned i = 0; i < m_config->nbk; i++) { - unsigned j = (i + prio) % m_config->nbk; - issued_row_cmd = issue_row_command(j); - if (issued_row_cmd) break; - } - for (unsigned i = 0; i < m_config->nbk; i++) { - unsigned j = (i + prio) % m_config->nbk; - if (!bk[j]->mrq) { - if (!CCDc && !RRDc && !RTWc && !WTRc && !bk[j]->RCDc && !bk[j]->RASc && - !bk[j]->RCc && !bk[j]->RPc && !bk[j]->RCDWRc) - k--; - bk[j]->n_idle++; - } - } - } else { - // single bus interface - // issue only one row/column command - for (unsigned i = 0; i < m_config->nbk; i++) { - unsigned j = (i + prio) % m_config->nbk; - if (!issued_col_cmd) issued_col_cmd = issue_col_command(j); + if(m_config->dual_bus_interface) + { + //dual bus interface + //issue one row command and one column command + for (unsigned i=0;i<m_config->nbk;i++) { + unsigned j = (i + prio) % m_config->nbk; + issued_col_cmd = issue_col_command(j); + if(issued_col_cmd) break; + } + for (unsigned i=0;i<m_config->nbk;i++) { + unsigned j = (i + prio) % m_config->nbk; + issued_row_cmd = issue_row_command(j); + if(issued_row_cmd) break; + } + for (unsigned i=0;i<m_config->nbk;i++) { + unsigned j = (i + prio) % m_config->nbk; + if(!bk[j]->mrq) { + if (!CCDc && !RRDc && !RTWc && !WTRc && !bk[j]->RCDc && !bk[j]->RASc + && !bk[j]->RCc && !bk[j]->RPc && !bk[j]->RCDWRc) k--; + bk[j]->n_idle++; + } + } + } + else + { + //single bus interface + //issue only one row/column command + for (unsigned i=0;i<m_config->nbk;i++) { + unsigned j = (i + prio) % m_config->nbk; + if(!issued_col_cmd) + issued_col_cmd = issue_col_command(j); - if (!issued_col_cmd && !issued_row_cmd) - issued_row_cmd = issue_row_command(j); + if(!issued_col_cmd && !issued_row_cmd) + issued_row_cmd = issue_row_command(j); - if (!bk[j]->mrq) { - if (!CCDc && !RRDc && !RTWc && !WTRc && !bk[j]->RCDc && !bk[j]->RASc && - !bk[j]->RCc && !bk[j]->RPc && !bk[j]->RCDWRc) - k--; - bk[j]->n_idle++; - } - } - } + if(!bk[j]->mrq) { + if (!CCDc && !RRDc && !RTWc && !WTRc && !bk[j]->RCDc && !bk[j]->RASc + && !bk[j]->RCc && !bk[j]->RPc && !bk[j]->RCDWRc) k--; + bk[j]->n_idle++; + } + + } + } - issued = issued_row_cmd || issued_col_cmd; - if (!issued) { - n_nop++; - n_nop_partial++; + issued = issued_row_cmd || issued_col_cmd; + if (!issued) { + n_nop++; + n_nop_partial++; #ifdef DRAM_VIEWCMD - printf("\tNOP "); + printf("\tNOP "); #endif - } - if (k) { - n_activity++; - n_activity_partial++; - } - n_cmd++; - n_cmd_partial++; - if (issued) { - issued_total++; - if (issued_col_cmd && issued_row_cmd) issued_two++; - } - if (issued_col_cmd) issued_total_col++; - if (issued_row_cmd) issued_total_row++; + } + if (k) { + n_activity++; + n_activity_partial++; + } + n_cmd++; + n_cmd_partial++; + if(issued) + { + issued_total++; + if(issued_col_cmd && issued_row_cmd) + issued_two++; + } + if(issued_col_cmd) issued_total_col++; + if(issued_row_cmd) issued_total_row++; - // Collect some statistics - // check the limitation, see where BW is wasted? - ///////////////////////////////////////////////////////// - unsigned int memory_pending_found = 0; - for (unsigned i = 0; i < m_config->nbk; i++) { - if (bk[i]->mrq) memory_pending_found++; - } - if (memory_pending_found > 0) banks_acess_total_after++; - bool memory_pending_rw_found = false; - for (unsigned j = 0; j < m_config->nbk; j++) { - if (bk[j]->mrq && - (((bk[j]->curr_row == bk[j]->mrq->row) && (bk[j]->mrq->rw == READ) && - (bk[j]->state == BANK_ACTIVE)) || - ((bk[j]->curr_row == bk[j]->mrq->row) && (bk[j]->mrq->rw == WRITE) && - (bk[j]->state == BANK_ACTIVE)))) - memory_pending_rw_found = true; - } - - if (issued_col_cmd || CCDc) - util_bw++; - else if (memory_pending_rw_found) { - wasted_bw_col++; - for (unsigned j = 0; j < m_config->nbk; j++) { - unsigned grp = get_bankgrp_number(j); - // read - if (bk[j]->mrq && - (((bk[j]->curr_row == bk[j]->mrq->row) && (bk[j]->mrq->rw == READ) && - (bk[j]->state == BANK_ACTIVE)))) { - if (bk[j]->RCDc) RCDc_limit++; - if (bkgrp[grp]->CCDLc) CCDLc_limit++; - if (WTRc) WTRc_limit++; - if (CCDc) CCDc_limit++; - if (rwq->full()) rwq_limit++; - if (bkgrp[grp]->CCDLc && !WTRc) CCDLc_limit_alone++; - if (!bkgrp[grp]->CCDLc && WTRc) WTRc_limit_alone++; - } - // write - else if (bk[j]->mrq && - ((bk[j]->curr_row == bk[j]->mrq->row) && - (bk[j]->mrq->rw == WRITE) && (bk[j]->state == BANK_ACTIVE))) { - if (bk[j]->RCDWRc) RCDWRc_limit++; - if (bkgrp[grp]->CCDLc) CCDLc_limit++; - if (RTWc) RTWc_limit++; - if (CCDc) CCDc_limit++; - if (rwq->full()) rwq_limit++; - if (bkgrp[grp]->CCDLc && !RTWc) CCDLc_limit_alone++; - if (!bkgrp[grp]->CCDLc && RTWc) RTWc_limit_alone++; + //Collect some statistics + //check the limitation, see where BW is wasted? + ///////////////////////////////////////////////////////// + unsigned int memory_pending_found=0; + for (unsigned i=0;i<m_config->nbk;i++) { + if (bk[i]->mrq) + memory_pending_found++; } - } - } else if (memory_pending_found) - wasted_bw_row++; - else if (!memory_pending_found) - idle_bw++; - else - assert(1); + if(memory_pending_found>0) + banks_acess_total_after++; + + bool memory_pending_rw_found=false; + for (unsigned j=0;j<m_config->nbk;j++) { + if (bk[j]->mrq && (((bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == READ) && + (bk[j]->state == BANK_ACTIVE)) + || + ( + (bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == WRITE) && + (bk[j]->state == BANK_ACTIVE)))) + memory_pending_rw_found=true; + } + + + if(issued_col_cmd || CCDc) + util_bw++; + else if (memory_pending_rw_found) + { + wasted_bw_col++; + for (unsigned j=0;j<m_config->nbk;j++) { + unsigned grp = get_bankgrp_number(j); + //read + if (bk[j]->mrq && (((bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == READ) && + (bk[j]->state == BANK_ACTIVE)))) + { + if(bk[j]->RCDc) RCDc_limit++; + if(bkgrp[grp]->CCDLc) CCDLc_limit++; + if(WTRc) WTRc_limit++; + if(CCDc) CCDc_limit++; + if(rwq->full()) rwq_limit++; + if(bkgrp[grp]->CCDLc && !WTRc) CCDLc_limit_alone++; + if(!bkgrp[grp]->CCDLc && WTRc) WTRc_limit_alone++; + } + //write + else if (bk[j]->mrq && ((bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == WRITE) && + (bk[j]->state == BANK_ACTIVE))) + { + if(bk[j]->RCDWRc) RCDWRc_limit++; + if(bkgrp[grp]->CCDLc) CCDLc_limit++; + if(RTWc) RTWc_limit++; + if(CCDc) CCDc_limit++; + if(rwq->full()) rwq_limit++; + if(bkgrp[grp]->CCDLc && !RTWc) CCDLc_limit_alone++; + if(!bkgrp[grp]->CCDLc && RTWc) RTWc_limit_alone++; + } + } + } + else if (memory_pending_found) + wasted_bw_row++; + else if (!memory_pending_found) + idle_bw++; + else + assert(1); - ///////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////// - // decrements counters once for each time dram_issueCMD is called - DEC2ZERO(RRDc); - DEC2ZERO(CCDc); - DEC2ZERO(RTWc); - DEC2ZERO(WTRc); - for (unsigned j = 0; j < m_config->nbk; j++) { - DEC2ZERO(bk[j]->RCDc); - DEC2ZERO(bk[j]->RASc); - DEC2ZERO(bk[j]->RCc); - DEC2ZERO(bk[j]->RPc); - DEC2ZERO(bk[j]->RCDWRc); - DEC2ZERO(bk[j]->WTPc); - DEC2ZERO(bk[j]->RTPc); - } - for (unsigned j = 0; j < m_config->nbkgrp; j++) { - DEC2ZERO(bkgrp[j]->CCDLc); - DEC2ZERO(bkgrp[j]->RTPLc); - } + // decrements counters once for each time dram_issueCMD is called + DEC2ZERO(RRDc); + DEC2ZERO(CCDc); + DEC2ZERO(RTWc); + DEC2ZERO(WTRc); + for (unsigned j=0;j<m_config->nbk;j++) { + DEC2ZERO(bk[j]->RCDc); + DEC2ZERO(bk[j]->RASc); + DEC2ZERO(bk[j]->RCc); + DEC2ZERO(bk[j]->RPc); + DEC2ZERO(bk[j]->RCDWRc); + DEC2ZERO(bk[j]->WTPc); + DEC2ZERO(bk[j]->RTPc); + } + for (unsigned j=0; j<m_config->nbkgrp; j++) { + DEC2ZERO(bkgrp[j]->CCDLc); + DEC2ZERO(bkgrp[j]->RTPLc); + } #ifdef DRAM_VISUALIZE - visualize(); + visualize(); #endif } -bool dram_t::issue_col_command(int j) { - bool issued = false; - unsigned grp = get_bankgrp_number(j); - if (bk[j]->mrq) { // if currently servicing a memory request - bk[j]->mrq->data->set_status( - IN_PARTITION_DRAM, m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - // correct row activated for a READ - if (!issued && !CCDc && !bk[j]->RCDc && !(bkgrp[grp]->CCDLc) && - (bk[j]->curr_row == bk[j]->mrq->row) && (bk[j]->mrq->rw == READ) && - (WTRc == 0) && (bk[j]->state == BANK_ACTIVE) && !rwq->full()) { - if (rw == WRITE) { - rw = READ; - rwq->set_min_length(m_config->CL); - } - rwq->push(bk[j]->mrq); - bk[j]->mrq->txbytes += m_config->dram_atom_size; - CCDc = m_config->tCCD; - bkgrp[grp]->CCDLc = m_config->tCCDL; - RTWc = m_config->tRTW; - bk[j]->RTPc = m_config->BL / m_config->data_command_freq_ratio; - bkgrp[grp]->RTPLc = m_config->tRTPL; - issued = true; - if (bk[j]->mrq->data->get_access_type() == L2_WR_ALLOC_R) - n_rd_L2_A++; - else - n_rd++; +bool dram_t::issue_col_command(int j) +{ + bool issued = false; + unsigned grp = get_bankgrp_number(j); + if (bk[j]->mrq) { //if currently servicing a memory request + bk[j]->mrq->data->set_status(IN_PARTITION_DRAM,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); + // correct row activated for a READ + if ( !issued && !CCDc && !bk[j]->RCDc && + !(bkgrp[grp]->CCDLc) && + (bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == READ) && (WTRc == 0 ) && + (bk[j]->state == BANK_ACTIVE) && + !rwq->full() ) { + if (rw==WRITE) { + rw=READ; + rwq->set_min_length(m_config->CL); + } + rwq->push(bk[j]->mrq); + bk[j]->mrq->txbytes += m_config->dram_atom_size; + CCDc = m_config->tCCD; + bkgrp[grp]->CCDLc = m_config->tCCDL; + RTWc = m_config->tRTW; + bk[j]->RTPc = m_config->BL/m_config->data_command_freq_ratio; + bkgrp[grp]->RTPLc = m_config->tRTPL; + issued = true; + if(bk[j]->mrq->data->get_access_type() == L2_WR_ALLOC_R) + n_rd_L2_A++; + else + n_rd++; - bwutil += m_config->BL / m_config->data_command_freq_ratio; - bwutil_partial += m_config->BL / m_config->data_command_freq_ratio; - bk[j]->n_access++; + bwutil += m_config->BL/m_config->data_command_freq_ratio; + bwutil_partial += m_config->BL/m_config->data_command_freq_ratio; + bk[j]->n_access++; #ifdef DRAM_VERIFY - PRINT_CYCLE = 1; - printf("\tRD Bk:%d Row:%03x Col:%03x \n", j, bk[j]->curr_row, - bk[j]->mrq->col + bk[j]->mrq->txbytes - m_config->dram_atom_size); + PRINT_CYCLE=1; + printf("\tRD Bk:%d Row:%03x Col:%03x \n", + j, bk[j]->curr_row, + bk[j]->mrq->col + bk[j]->mrq->txbytes - m_config->dram_atom_size); #endif - // transfer done - if (!(bk[j]->mrq->txbytes < bk[j]->mrq->nbytes)) { - bk[j]->mrq = NULL; - } - } else - // correct row activated for a WRITE - if (!issued && !CCDc && !bk[j]->RCDWRc && !(bkgrp[grp]->CCDLc) && - (bk[j]->curr_row == bk[j]->mrq->row) && (bk[j]->mrq->rw == WRITE) && - (RTWc == 0) && (bk[j]->state == BANK_ACTIVE) && !rwq->full()) { - if (rw == READ) { - rw = WRITE; - rwq->set_min_length(m_config->WL); - } - rwq->push(bk[j]->mrq); + // transfer done + if ( !(bk[j]->mrq->txbytes < bk[j]->mrq->nbytes) ) { + bk[j]->mrq = NULL; + } + } else + // correct row activated for a WRITE + if ( !issued && !CCDc && !bk[j]->RCDWRc && + !(bkgrp[grp]->CCDLc) && + (bk[j]->curr_row == bk[j]->mrq->row) && + (bk[j]->mrq->rw == WRITE) && (RTWc == 0 ) && + (bk[j]->state == BANK_ACTIVE) && + !rwq->full() ) { + if (rw==READ) { + rw=WRITE; + rwq->set_min_length(m_config->WL); + } + rwq->push(bk[j]->mrq); - bk[j]->mrq->txbytes += m_config->dram_atom_size; - CCDc = m_config->tCCD; - bkgrp[grp]->CCDLc = m_config->tCCDL; - WTRc = m_config->tWTR; - bk[j]->WTPc = m_config->tWTP; - issued = true; + bk[j]->mrq->txbytes += m_config->dram_atom_size; + CCDc = m_config->tCCD; + bkgrp[grp]->CCDLc = m_config->tCCDL; + WTRc = m_config->tWTR; + bk[j]->WTPc = m_config->tWTP; + issued = true; - if (bk[j]->mrq->data->get_access_type() == L2_WRBK_ACC) - n_wr_WB++; - else - n_wr++; - bwutil += m_config->BL / m_config->data_command_freq_ratio; - bwutil_partial += m_config->BL / m_config->data_command_freq_ratio; + if(bk[j]->mrq->data->get_access_type() == L2_WRBK_ACC) + n_wr_WB++; + else + n_wr++; + bwutil += m_config->BL/m_config->data_command_freq_ratio; + bwutil_partial += m_config->BL/m_config->data_command_freq_ratio; #ifdef DRAM_VERIFY - PRINT_CYCLE = 1; - printf("\tWR Bk:%d Row:%03x Col:%03x \n", j, bk[j]->curr_row, - bk[j]->mrq->col + bk[j]->mrq->txbytes - m_config->dram_atom_size); + PRINT_CYCLE=1; + printf("\tWR Bk:%d Row:%03x Col:%03x \n", + j, bk[j]->curr_row, + bk[j]->mrq->col + bk[j]->mrq->txbytes - m_config->dram_atom_size); #endif - // transfer done - if (!(bk[j]->mrq->txbytes < bk[j]->mrq->nbytes)) { - bk[j]->mrq = NULL; - } + // transfer done + if ( !(bk[j]->mrq->txbytes < bk[j]->mrq->nbytes) ) { + bk[j]->mrq = NULL; + } + } + } - } - return issued; + return issued; } -bool dram_t::issue_row_command(int j) { - bool issued = false; - unsigned grp = get_bankgrp_number(j); - if (bk[j]->mrq) { // if currently servicing a memory request - bk[j]->mrq->data->set_status( - IN_PARTITION_DRAM, m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - // bank is idle - // else - if (!issued && !RRDc && (bk[j]->state == BANK_IDLE) && !bk[j]->RPc && - !bk[j]->RCc) { // +bool dram_t::issue_row_command(int j) +{ + bool issued = false; + unsigned grp = get_bankgrp_number(j); + if (bk[j]->mrq) { //if currently servicing a memory request + bk[j]->mrq->data->set_status(IN_PARTITION_DRAM,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); + // bank is idle + //else + if ( !issued && !RRDc && + (bk[j]->state == BANK_IDLE) && + !bk[j]->RPc && !bk[j]->RCc) { // #ifdef DRAM_VERIFY - PRINT_CYCLE = 1; - printf("\tACT BK:%d NewRow:%03x From:%03x \n", j, bk[j]->mrq->row, - bk[j]->curr_row); + PRINT_CYCLE=1; + printf("\tACT BK:%d NewRow:%03x From:%03x \n", + j,bk[j]->mrq->row,bk[j]->curr_row); #endif - // activate the row with current memory request - bk[j]->curr_row = bk[j]->mrq->row; - bk[j]->state = BANK_ACTIVE; - RRDc = m_config->tRRD; - bk[j]->RCDc = m_config->tRCD; - bk[j]->RCDWRc = m_config->tRCDWR; - bk[j]->RASc = m_config->tRAS; - bk[j]->RCc = m_config->tRC; - prio = (j + 1) % m_config->nbk; - issued = true; - n_act_partial++; - n_act++; - } + // activate the row with current memory request + bk[j]->curr_row = bk[j]->mrq->row; + bk[j]->state = BANK_ACTIVE; + RRDc = m_config->tRRD; + bk[j]->RCDc = m_config->tRCD; + bk[j]->RCDWRc = m_config->tRCDWR; + bk[j]->RASc = m_config->tRAS; + bk[j]->RCc = m_config->tRC; + prio = (j + 1) % m_config->nbk; + issued = true; + n_act_partial++; + n_act++; + } - else - // different row activated - if ((!issued) && (bk[j]->curr_row != bk[j]->mrq->row) && - (bk[j]->state == BANK_ACTIVE) && - (!bk[j]->RASc && !bk[j]->WTPc && !bk[j]->RTPc && - !bkgrp[grp]->RTPLc)) { - // make the bank idle again - bk[j]->state = BANK_IDLE; - bk[j]->RPc = m_config->tRP; - prio = (j + 1) % m_config->nbk; - issued = true; - n_pre++; - n_pre_partial++; + else + // different row activated + if ( (!issued) && + (bk[j]->curr_row != bk[j]->mrq->row) && + (bk[j]->state == BANK_ACTIVE) && + (!bk[j]->RASc && !bk[j]->WTPc && + !bk[j]->RTPc && + !bkgrp[grp]->RTPLc) ) { + // make the bank idle again + bk[j]->state = BANK_IDLE; + bk[j]->RPc = m_config->tRP; + prio = (j + 1) % m_config->nbk; + issued = true; + n_pre++; + n_pre_partial++; #ifdef DRAM_VERIFY - PRINT_CYCLE = 1; - printf("\tPRE BK:%d Row:%03x \n", j, bk[j]->curr_row); + PRINT_CYCLE=1; + printf("\tPRE BK:%d Row:%03x \n", j,bk[j]->curr_row); #endif + } } - } - return issued; + return issued; } -// if mrq is being serviced by dram, gets popped after CL latency fulfilled -class mem_fetch *dram_t::return_queue_pop() { - return returnq->pop(); + +//if mrq is being serviced by dram, gets popped after CL latency fulfilled +class mem_fetch* dram_t::return_queue_pop() +{ + return returnq->pop(); } -class mem_fetch *dram_t::return_queue_top() { - return returnq->top(); +class mem_fetch* dram_t::return_queue_top() +{ + return returnq->top(); } -void dram_t::print(FILE *simFile) const { - unsigned i; - fprintf(simFile, "DRAM[%d]: %d bks, busW=%d BL=%d CL=%d, ", id, m_config->nbk, - m_config->busW, m_config->BL, m_config->CL); - fprintf(simFile, "tRRD=%d tCCD=%d, tRCD=%d tRAS=%d tRP=%d tRC=%d\n", - m_config->tRRD, m_config->tCCD, m_config->tRCD, m_config->tRAS, - m_config->tRP, m_config->tRC); - fprintf(simFile, - "n_cmd=%llu n_nop=%llu n_act=%llu n_pre=%llu n_ref_event=%llu " - "n_req=%llu n_rd=%llu n_rd_L2_A=%llu n_write=%llu n_wr_bk=%llu " - "bw_util=%.4g\n", - n_cmd, n_nop, n_act, n_pre, n_ref, n_req, n_rd, n_rd_L2_A, n_wr, - n_wr_WB, (float)bwutil / n_cmd); - fprintf(simFile, "n_activity=%llu dram_eff=%.4g\n", n_activity, - (float)bwutil / n_activity); - for (i = 0; i < m_config->nbk; i++) { - fprintf(simFile, "bk%d: %da %di ", i, bk[i]->n_access, bk[i]->n_idle); - } - fprintf(simFile, "\n"); - fprintf(simFile, - "\n------------------------------------------------------------------" - "------\n"); - printf("\nRow_Buffer_Locality = %.6f", (float)hits_num / access_num); - printf("\nRow_Buffer_Locality_read = %.6f", (float)hits_read_num / read_num); - printf("\nRow_Buffer_Locality_write = %.6f", - (float)hits_write_num / write_num); - printf("\nBank_Level_Parallism = %.6f", - (float)banks_1time / banks_acess_total); - printf("\nBank_Level_Parallism_Col = %.6f", - (float)banks_time_rw / banks_access_rw_total); - printf("\nBank_Level_Parallism_Ready = %.6f", - (float)banks_time_ready / banks_access_ready_total); - printf("\nwrite_to_read_ratio_blp_rw_average = %.6f", - write_to_read_ratio_blp_rw_average / banks_access_rw_total); - printf("\nGrpLevelPara = %.6f \n", - (float)bkgrp_parallsim_rw / banks_access_rw_total); +void dram_t::print( FILE* simFile) const +{ + unsigned i; + fprintf(simFile,"DRAM[%d]: %d bks, busW=%d BL=%d CL=%d, ", + id, m_config->nbk, m_config->busW, m_config->BL, m_config->CL ); + fprintf(simFile,"tRRD=%d tCCD=%d, tRCD=%d tRAS=%d tRP=%d tRC=%d\n", + m_config->tRRD, m_config->tCCD, m_config->tRCD, m_config->tRAS, m_config->tRP, m_config->tRC ); + fprintf(simFile,"n_cmd=%llu n_nop=%llu n_act=%llu n_pre=%llu n_ref_event=%llu n_req=%llu n_rd=%llu n_rd_L2_A=%llu n_write=%llu n_wr_bk=%llu bw_util=%.4g\n", + n_cmd, n_nop, n_act, n_pre, n_ref, n_req, n_rd, n_rd_L2_A, n_wr, n_wr_WB, + (float)bwutil/n_cmd); + fprintf(simFile,"n_activity=%llu dram_eff=%.4g\n", + n_activity, (float)bwutil/n_activity); + for (i=0;i<m_config->nbk;i++) { + fprintf(simFile, "bk%d: %da %di ",i,bk[i]->n_access,bk[i]->n_idle); + } + fprintf(simFile, "\n"); + fprintf(simFile, "\n------------------------------------------------------------------------\n"); - printf("\nBW Util details:\n"); - printf("bwutil = %.6f \n", (float)bwutil / n_cmd); - printf("total_CMD = %llu \n", n_cmd); - printf("util_bw = %llu \n", util_bw); - printf("Wasted_Col = %llu \n", wasted_bw_col); - printf("Wasted_Row = %llu \n", wasted_bw_row); - printf("Idle = %llu \n", idle_bw); + printf("\nRow_Buffer_Locality = %.6f", (float)hits_num / access_num); + printf("\nRow_Buffer_Locality_read = %.6f", (float)hits_read_num / read_num); + printf("\nRow_Buffer_Locality_write = %.6f", (float)hits_write_num / write_num); + printf("\nBank_Level_Parallism = %.6f", (float)banks_1time / banks_acess_total); + printf("\nBank_Level_Parallism_Col = %.6f", (float)banks_time_rw / banks_access_rw_total); + printf("\nBank_Level_Parallism_Ready = %.6f", (float)banks_time_ready /banks_access_ready_total); + printf("\nwrite_to_read_ratio_blp_rw_average = %.6f", write_to_read_ratio_blp_rw_average /banks_access_rw_total); + printf("\nGrpLevelPara = %.6f \n", (float)bkgrp_parallsim_rw /banks_access_rw_total); - printf("\nBW Util Bottlenecks: \n"); - printf("RCDc_limit = %llu \n", RCDc_limit); - printf("RCDWRc_limit = %llu \n", RCDWRc_limit); - printf("WTRc_limit = %llu \n", WTRc_limit); - printf("RTWc_limit = %llu \n", RTWc_limit); - printf("CCDLc_limit = %llu \n", CCDLc_limit); - printf("rwq = %llu \n", rwq_limit); - printf("CCDLc_limit_alone = %llu \n", CCDLc_limit_alone); - printf("WTRc_limit_alone = %llu \n", WTRc_limit_alone); - printf("RTWc_limit_alone = %llu \n", RTWc_limit_alone); + printf("\nBW Util details:\n"); + printf("bwutil = %.6f \n", (float)bwutil/n_cmd); + printf("total_CMD = %llu \n", n_cmd); + printf("util_bw = %llu \n", util_bw); + printf("Wasted_Col = %llu \n", wasted_bw_col); + printf("Wasted_Row = %llu \n", wasted_bw_row); + printf("Idle = %llu \n", idle_bw); - printf("\nCommands details: \n"); - printf("total_CMD = %llu \n", n_cmd); - printf("n_nop = %llu \n", n_nop); - printf("Read = %llu \n", n_rd); - printf("Write = %llu \n", n_wr); - printf("L2_Alloc = %llu \n", n_rd_L2_A); - printf("L2_WB = %llu \n", n_wr_WB); - printf("n_act = %llu \n", n_act); - printf("n_pre = %llu \n", n_pre); - printf("n_ref = %llu \n", n_ref); - printf("n_req = %llu \n", n_req); - printf("total_req = %llu \n", n_rd + n_wr + n_rd_L2_A + n_wr_WB); + printf("\nBW Util Bottlenecks: \n"); + printf("RCDc_limit = %llu \n", RCDc_limit); + printf("RCDWRc_limit = %llu \n", RCDWRc_limit); + printf("WTRc_limit = %llu \n", WTRc_limit); + printf("RTWc_limit = %llu \n", RTWc_limit); + printf("CCDLc_limit = %llu \n", CCDLc_limit); + printf("rwq = %llu \n", rwq_limit); + printf("CCDLc_limit_alone = %llu \n", CCDLc_limit_alone); + printf("WTRc_limit_alone = %llu \n", WTRc_limit_alone); + printf("RTWc_limit_alone = %llu \n", RTWc_limit_alone); - printf("\nDual Bus Interface Util: \n"); - printf("issued_total_row = %llu \n", issued_total_row); - printf("issued_total_col = %llu \n", issued_total_col); - printf("Row_Bus_Util = %.6f \n", (float)issued_total_row / n_cmd); - printf("CoL_Bus_Util = %.6f \n", (float)issued_total_col / n_cmd); - printf("Either_Row_CoL_Bus_Util = %.6f \n", (float)issued_total / n_cmd); - printf("Issued_on_Two_Bus_Simul_Util = %.6f \n", (float)issued_two / n_cmd); - printf("issued_two_Eff = %.6f \n", (float)issued_two / issued_total); - printf("queue_avg = %.6f \n\n", (float)ave_mrqs / n_cmd); + printf("\nCommands details: \n"); + printf("total_CMD = %llu \n", n_cmd); + printf("n_nop = %llu \n", n_nop); + printf("Read = %llu \n", n_rd); + printf("Write = %llu \n",n_wr); + printf("L2_Alloc = %llu \n", n_rd_L2_A); + printf("L2_WB = %llu \n", n_wr_WB); + printf("n_act = %llu \n", n_act); + printf("n_pre = %llu \n", n_pre); + printf("n_ref = %llu \n", n_ref); + printf("n_req = %llu \n", n_req ); + printf("total_req = %llu \n", n_rd+n_wr+n_rd_L2_A+n_wr_WB); - fprintf(simFile, "\n"); - fprintf(simFile, "dram_util_bins:"); - for (i = 0; i < 10; i++) fprintf(simFile, " %d", dram_util_bins[i]); - fprintf(simFile, "\ndram_eff_bins:"); - for (i = 0; i < 10; i++) fprintf(simFile, " %d", dram_eff_bins[i]); - fprintf(simFile, "\n"); - if (m_config->scheduler_type == DRAM_FRFCFS) - fprintf(simFile, "mrqq: max=%d avg=%g\n", max_mrqs, - (float)ave_mrqs / n_cmd); + printf("\nDual Bus Interface Util: \n"); + printf("issued_total_row = %llu \n", issued_total_row); + printf("issued_total_col = %llu \n", issued_total_col); + printf("Row_Bus_Util = %.6f \n", (float)issued_total_row / n_cmd); + printf("CoL_Bus_Util = %.6f \n", (float)issued_total_col / n_cmd); + printf("Either_Row_CoL_Bus_Util = %.6f \n", (float)issued_total / n_cmd); + printf("Issued_on_Two_Bus_Simul_Util = %.6f \n", (float)issued_two /n_cmd); + printf("issued_two_Eff = %.6f \n", (float)issued_two /issued_total); + printf("queue_avg = %.6f \n\n", (float)ave_mrqs/n_cmd ); + + fprintf(simFile, "\n"); + fprintf(simFile, "dram_util_bins:"); + for (i=0;i<10;i++) fprintf(simFile, " %d", dram_util_bins[i]); + fprintf(simFile, "\ndram_eff_bins:"); + for (i=0;i<10;i++) fprintf(simFile, " %d", dram_eff_bins[i]); + fprintf(simFile, "\n"); + if(m_config->scheduler_type== DRAM_FRFCFS) + fprintf(simFile, "mrqq: max=%d avg=%g\n", max_mrqs, (float)ave_mrqs/n_cmd); } -void dram_t::visualize() const { - printf("RRDc=%d CCDc=%d mrqq.Length=%d rwq.Length=%d\n", RRDc, CCDc, - mrqq->get_length(), rwq->get_length()); - for (unsigned i = 0; i < m_config->nbk; i++) { - printf("BK%d: state=%c curr_row=%03x, %2d %2d %2d %2d %p ", i, bk[i]->state, - bk[i]->curr_row, bk[i]->RCDc, bk[i]->RASc, bk[i]->RPc, bk[i]->RCc, - bk[i]->mrq); - if (bk[i]->mrq) - printf("txf: %d %d", bk[i]->mrq->nbytes, bk[i]->mrq->txbytes); - printf("\n"); - } - if (m_frfcfs_scheduler) m_frfcfs_scheduler->print(stdout); +void dram_t::visualize() const +{ + printf("RRDc=%d CCDc=%d mrqq.Length=%d rwq.Length=%d\n", + RRDc, CCDc, mrqq->get_length(),rwq->get_length()); + for (unsigned i=0;i<m_config->nbk;i++) { + printf("BK%d: state=%c curr_row=%03x, %2d %2d %2d %2d %p ", + i, bk[i]->state, bk[i]->curr_row, + bk[i]->RCDc, bk[i]->RASc, + bk[i]->RPc, bk[i]->RCc, + bk[i]->mrq ); + if (bk[i]->mrq) + printf("txf: %d %d", bk[i]->mrq->nbytes, bk[i]->mrq->txbytes); + printf("\n"); + } + if ( m_frfcfs_scheduler ) + m_frfcfs_scheduler->print(stdout); } -void dram_t::print_stat(FILE *simFile) { - fprintf(simFile, - "DRAM (%u): n_cmd=%llu n_nop=%llu n_act=%llu n_pre=%llu n_ref=%llu " - "n_req=%llu n_rd=%llu n_write=%llu bw_util=%.4g ", - id, n_cmd, n_nop, n_act, n_pre, n_ref, n_req, n_rd, n_wr, - (float)bwutil / n_cmd); - fprintf(simFile, "mrqq: %d %.4g mrqsmax=%llu ", max_mrqs, - (float)ave_mrqs / n_cmd, max_mrqs_temp); - fprintf(simFile, "\n"); - fprintf(simFile, "dram_util_bins:"); - for (unsigned i = 0; i < 10; i++) fprintf(simFile, " %d", dram_util_bins[i]); - fprintf(simFile, "\ndram_eff_bins:"); - for (unsigned i = 0; i < 10; i++) fprintf(simFile, " %d", dram_eff_bins[i]); - fprintf(simFile, "\n"); - max_mrqs_temp = 0; +void dram_t::print_stat( FILE* simFile ) +{ + fprintf(simFile,"DRAM (%u): n_cmd=%llu n_nop=%llu n_act=%llu n_pre=%llu n_ref=%llu n_req=%llu n_rd=%llu n_write=%llu bw_util=%.4g ", + id, n_cmd, n_nop, n_act, n_pre, n_ref, n_req, n_rd, n_wr, + (float)bwutil/n_cmd); + fprintf(simFile, "mrqq: %d %.4g mrqsmax=%llu ", max_mrqs, (float)ave_mrqs/n_cmd, max_mrqs_temp); + fprintf(simFile, "\n"); + fprintf(simFile, "dram_util_bins:"); + for (unsigned i=0;i<10;i++) fprintf(simFile, " %d", dram_util_bins[i]); + fprintf(simFile, "\ndram_eff_bins:"); + for (unsigned i=0;i<10;i++) fprintf(simFile, " %d", dram_eff_bins[i]); + fprintf(simFile, "\n"); + max_mrqs_temp = 0; } -void dram_t::visualizer_print(gzFile visualizer_file) { - // dram specific statistics - gzprintf(visualizer_file, "dramncmd: %u %u\n", id, n_cmd_partial); - gzprintf(visualizer_file, "dramnop: %u %u\n", id, n_nop_partial); - gzprintf(visualizer_file, "dramnact: %u %u\n", id, n_act_partial); - gzprintf(visualizer_file, "dramnpre: %u %u\n", id, n_pre_partial); - gzprintf(visualizer_file, "dramnreq: %u %u\n", id, n_req_partial); - gzprintf(visualizer_file, "dramavemrqs: %u %u\n", id, - n_cmd_partial ? (ave_mrqs_partial / n_cmd_partial) : 0); +void dram_t::visualizer_print( gzFile visualizer_file ) +{ + // dram specific statistics + gzprintf(visualizer_file,"dramncmd: %u %u\n",id, n_cmd_partial); + gzprintf(visualizer_file,"dramnop: %u %u\n",id,n_nop_partial); + gzprintf(visualizer_file,"dramnact: %u %u\n",id,n_act_partial); + gzprintf(visualizer_file,"dramnpre: %u %u\n",id,n_pre_partial); + gzprintf(visualizer_file,"dramnreq: %u %u\n",id,n_req_partial); + gzprintf(visualizer_file,"dramavemrqs: %u %u\n",id, + n_cmd_partial?(ave_mrqs_partial/n_cmd_partial ):0); - // utilization and efficiency - gzprintf(visualizer_file, "dramutil: %u %u\n", id, - n_cmd_partial ? 100 * bwutil_partial / n_cmd_partial : 0); - gzprintf(visualizer_file, "drameff: %u %u\n", id, - n_activity_partial ? 100 * bwutil_partial / n_activity_partial : 0); + // utilization and efficiency + gzprintf(visualizer_file,"dramutil: %u %u\n", + id,n_cmd_partial?100*bwutil_partial/n_cmd_partial:0); + gzprintf(visualizer_file,"drameff: %u %u\n", + id,n_activity_partial?100*bwutil_partial/n_activity_partial:0); - // reset for next interval - bwutil_partial = 0; - n_activity_partial = 0; - ave_mrqs_partial = 0; - n_cmd_partial = 0; - n_nop_partial = 0; - n_act_partial = 0; - n_pre_partial = 0; - n_req_partial = 0; + // reset for next interval + bwutil_partial = 0; + n_activity_partial = 0; + ave_mrqs_partial = 0; + n_cmd_partial = 0; + n_nop_partial = 0; + n_act_partial = 0; + n_pre_partial = 0; + n_req_partial = 0; - // dram access type classification - for (unsigned j = 0; j < m_config->nbk; j++) { - gzprintf(visualizer_file, "dramglobal_acc_r: %u %u %u\n", id, j, - m_stats->mem_access_type_stats[GLOBAL_ACC_R][id][j]); - gzprintf(visualizer_file, "dramglobal_acc_w: %u %u %u\n", id, j, - m_stats->mem_access_type_stats[GLOBAL_ACC_W][id][j]); - gzprintf(visualizer_file, "dramlocal_acc_r: %u %u %u\n", id, j, - m_stats->mem_access_type_stats[LOCAL_ACC_R][id][j]); - gzprintf(visualizer_file, "dramlocal_acc_w: %u %u %u\n", id, j, - m_stats->mem_access_type_stats[LOCAL_ACC_W][id][j]); - gzprintf(visualizer_file, "dramconst_acc_r: %u %u %u\n", id, j, - m_stats->mem_access_type_stats[CONST_ACC_R][id][j]); - gzprintf(visualizer_file, "dramtexture_acc_r: %u %u %u\n", id, j, - m_stats->mem_access_type_stats[TEXTURE_ACC_R][id][j]); - } + + // dram access type classification + for (unsigned j = 0; j < m_config->nbk; j++) { + gzprintf(visualizer_file,"dramglobal_acc_r: %u %u %u\n", id, j, + m_stats->mem_access_type_stats[GLOBAL_ACC_R][id][j]); + gzprintf(visualizer_file,"dramglobal_acc_w: %u %u %u\n", id, j, + m_stats->mem_access_type_stats[GLOBAL_ACC_W][id][j]); + gzprintf(visualizer_file,"dramlocal_acc_r: %u %u %u\n", id, j, + m_stats->mem_access_type_stats[LOCAL_ACC_R][id][j]); + gzprintf(visualizer_file,"dramlocal_acc_w: %u %u %u\n", id, j, + m_stats->mem_access_type_stats[LOCAL_ACC_W][id][j]); + gzprintf(visualizer_file,"dramconst_acc_r: %u %u %u\n", id, j, + m_stats->mem_access_type_stats[CONST_ACC_R][id][j]); + gzprintf(visualizer_file,"dramtexture_acc_r: %u %u %u\n", id, j, + m_stats->mem_access_type_stats[TEXTURE_ACC_R][id][j]); + } } -void dram_t::set_dram_power_stats(unsigned &cmd, unsigned &activity, - unsigned &nop, unsigned &act, unsigned &pre, - unsigned &rd, unsigned &wr, - unsigned &req) const { - // Point power performance counters to low-level DRAM counters - cmd = n_cmd; - activity = n_activity; - nop = n_nop; - act = n_act; - pre = n_pre; - rd = n_rd; - wr = n_wr; - req = n_req; + +void dram_t::set_dram_power_stats( unsigned &cmd, + unsigned &activity, + unsigned &nop, + unsigned &act, + unsigned &pre, + unsigned &rd, + unsigned &wr, + unsigned &req) const{ + + // Point power performance counters to low-level DRAM counters + cmd = n_cmd; + activity = n_activity; + nop = n_nop; + act = n_act; + pre = n_pre; + rd = n_rd; + wr = n_wr; + req = n_req; } -unsigned dram_t::get_bankgrp_number(unsigned i) { - if (m_config->dram_bnkgrp_indexing_policy == HIGHER_BITS) { // higher bits - return i >> m_config->bk_tag_length; - } else if (m_config->dram_bnkgrp_indexing_policy == - LOWER_BITS) { // lower bits - return i & ((m_config->nbkgrp - 1)); - } else { - assert(1); - } +unsigned dram_t::get_bankgrp_number(unsigned i) +{ + if(m_config->dram_bnkgrp_indexing_policy == HIGHER_BITS) { //higher bits + return i >> m_config->bk_tag_length; + } + else if (m_config->dram_bnkgrp_indexing_policy == LOWER_BITS) { //lower bits + return i & ((m_config->nbkgrp - 1)); + } + else { + assert(1); + } } diff --git a/src/gpgpu-sim/dram.h b/src/gpgpu-sim/dram.h index 29ce831..0bd9725 100644 --- a/src/gpgpu-sim/dram.h +++ b/src/gpgpu-sim/dram.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2011, Tor M. Aamodt, Ivan Sham, Ali Bakhoda, +// Copyright (c) 2009-2011, Tor M. Aamodt, Ivan Sham, Ali Bakhoda, // George L. Yuan, Wilson W.L. Fung // The University of British Columbia // All rights reserved. @@ -8,16 +8,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -31,217 +29,227 @@ #ifndef DRAM_H #define DRAM_H -#include <stdio.h> -#include <stdlib.h> -#include <zlib.h> -#include <bitset> -#include <fstream> -#include <iomanip> +#include "delayqueue.h" #include <set> +#include <vector> +#include <bitset> #include <sstream> #include <string> -#include <vector> -#include "delayqueue.h" +#include <fstream> +#include <zlib.h> +#include <stdio.h> +#include <stdlib.h> +#include<iomanip> -#define READ 'R' // define read and write states +#define READ 'R' //define read and write states #define WRITE 'W' #define BANK_IDLE 'I' #define BANK_ACTIVE 'A' class dram_req_t { - public: - dram_req_t(class mem_fetch *data, unsigned banks, - unsigned dram_bnk_indexing_policy, class gpgpu_sim *gpu); +public: + dram_req_t( class mem_fetch *data , unsigned banks, unsigned dram_bnk_indexing_policy, class gpgpu_sim* gpu); - unsigned int row; - unsigned int col; - unsigned int bk; - unsigned int nbytes; - unsigned int txbytes; - unsigned int dqbytes; - unsigned int age; - unsigned int timestamp; - unsigned char rw; // is the request a read or a write? - unsigned long long int addr; - unsigned int insertion_time; - class mem_fetch *data; - class gpgpu_sim *m_gpu; + unsigned int row; + unsigned int col; + unsigned int bk; + unsigned int nbytes; + unsigned int txbytes; + unsigned int dqbytes; + unsigned int age; + unsigned int timestamp; + unsigned char rw; //is the request a read or a write? + unsigned long long int addr; + unsigned int insertion_time; + class mem_fetch * data; + class gpgpu_sim * m_gpu; }; -struct bankgrp_t { - unsigned int CCDLc; - unsigned int RTPLc; +struct bankgrp_t +{ + unsigned int CCDLc; + unsigned int RTPLc; }; -struct bank_t { - unsigned int RCDc; - unsigned int RCDWRc; - unsigned int RASc; - unsigned int RPc; - unsigned int RCc; - unsigned int WTPc; // write to precharge - unsigned int RTPc; // read to precharge +struct bank_t +{ + unsigned int RCDc; + unsigned int RCDWRc; + unsigned int RASc; + unsigned int RPc; + unsigned int RCc; + unsigned int WTPc; // write to precharge + unsigned int RTPc; // read to precharge - unsigned char rw; // is the bank reading or writing? - unsigned char state; // is the bank active or idle? - unsigned int curr_row; + unsigned char rw; //is the bank reading or writing? + unsigned char state; //is the bank active or idle? + unsigned int curr_row; - dram_req_t *mrq; + dram_req_t *mrq; - unsigned int n_access; - unsigned int n_writes; - unsigned int n_idle; + unsigned int n_access; + unsigned int n_writes; + unsigned int n_idle; - unsigned int bkgrpindex; + unsigned int bkgrpindex; }; -enum bank_index_function { - LINEAR_BK_INDEX = 0, - BITWISE_XORING_BK_INDEX, - CUSTOM_BK_INDEX +enum bank_index_function{ + LINEAR_BK_INDEX = 0, + BITWISE_XORING_BK_INDEX, + CUSTOM_BK_INDEX }; -enum bank_grp_bits_position { HIGHER_BITS = 0, LOWER_BITS }; +enum bank_grp_bits_position{ + HIGHER_BITS = 0, + LOWER_BITS +}; class mem_fetch; class memory_config; -class dram_t { - public: - dram_t(unsigned int parition_id, const memory_config *config, - class memory_stats_t *stats, class memory_partition_unit *mp, - class gpgpu_sim *gpu); +class dram_t +{ +public: + dram_t( unsigned int parition_id, const memory_config *config, class memory_stats_t *stats, + class memory_partition_unit *mp, class gpgpu_sim* gpu ); + + bool full(bool is_write) const; + void print( FILE* simFile ) const; + void visualize() const; + void print_stat( FILE* simFile ); + unsigned que_length() const; + bool returnq_full() const; + unsigned int queue_limit() const; + void visualizer_print( gzFile visualizer_file ); + + class mem_fetch* return_queue_pop(); + class mem_fetch* return_queue_top(); - bool full(bool is_write) const; - void print(FILE *simFile) const; - void visualize() const; - void print_stat(FILE *simFile); - unsigned que_length() const; - bool returnq_full() const; - unsigned int queue_limit() const; - void visualizer_print(gzFile visualizer_file); + void push( class mem_fetch *data ); + void cycle(); + void dram_log (int task); - class mem_fetch *return_queue_pop(); - class mem_fetch *return_queue_top(); + class memory_partition_unit *m_memory_partition_unit; + class gpgpu_sim* m_gpu; + unsigned int id; - void push(class mem_fetch *data); - void cycle(); - void dram_log(int task); + // Power Model + void set_dram_power_stats(unsigned &cmd, + unsigned &activity, + unsigned &nop, + unsigned &act, + unsigned &pre, + unsigned &rd, + unsigned &wr, + unsigned &req) const; - class memory_partition_unit *m_memory_partition_unit; - class gpgpu_sim *m_gpu; - unsigned int id; - // Power Model - void set_dram_power_stats(unsigned &cmd, unsigned &activity, unsigned &nop, - unsigned &act, unsigned &pre, unsigned &rd, - unsigned &wr, unsigned &req) const; - const memory_config *m_config; + const memory_config *m_config; - private: - bankgrp_t **bkgrp; +private: + bankgrp_t **bkgrp; - bank_t **bk; - unsigned int prio; + bank_t **bk; + unsigned int prio; - unsigned get_bankgrp_number(unsigned i); + unsigned get_bankgrp_number(unsigned i); - void scheduler_fifo(); - void scheduler_frfcfs(); + void scheduler_fifo(); + void scheduler_frfcfs(); - bool issue_col_command(int j); - bool issue_row_command(int j); + bool issue_col_command(int j); + bool issue_row_command(int j); - unsigned int RRDc; - unsigned int CCDc; - unsigned int RTWc; // read to write penalty applies across banks - unsigned int WTRc; // write to read penalty applies across banks + unsigned int RRDc; + unsigned int CCDc; + unsigned int RTWc; //read to write penalty applies across banks + unsigned int WTRc; //write to read penalty applies across banks - unsigned char - rw; // was last request a read or write? (important for RTW, WTR) + unsigned char rw; //was last request a read or write? (important for RTW, WTR) - unsigned int pending_writes; + unsigned int pending_writes; - fifo_pipeline<dram_req_t> *rwq; - fifo_pipeline<dram_req_t> *mrqq; - // buffer to hold packets when DRAM processing is over - // should be filled with dram clock and popped with l2or icnt clock - fifo_pipeline<mem_fetch> *returnq; + fifo_pipeline<dram_req_t> *rwq; + fifo_pipeline<dram_req_t> *mrqq; + //buffer to hold packets when DRAM processing is over + //should be filled with dram clock and popped with l2or icnt clock + fifo_pipeline<mem_fetch> *returnq; - unsigned int dram_util_bins[10]; - unsigned int dram_eff_bins[10]; - unsigned int last_n_cmd, last_n_activity, last_bwutil; + unsigned int dram_util_bins[10]; + unsigned int dram_eff_bins[10]; + unsigned int last_n_cmd, last_n_activity, last_bwutil; - unsigned long long n_cmd; - unsigned long long n_activity; - unsigned long long n_nop; - unsigned long long n_act; - unsigned long long n_pre; - unsigned long long n_ref; - unsigned long long n_rd; - unsigned long long n_rd_L2_A; - unsigned long long n_wr; - unsigned long long n_wr_WB; - unsigned long long n_req; - unsigned long long max_mrqs_temp; + unsigned long long n_cmd; + unsigned long long n_activity; + unsigned long long n_nop; + unsigned long long n_act; + unsigned long long n_pre; + unsigned long long n_ref; + unsigned long long n_rd; + unsigned long long n_rd_L2_A; + unsigned long long n_wr; + unsigned long long n_wr_WB; + unsigned long long n_req; + unsigned long long max_mrqs_temp; - // some statistics to see where BW is wasted? - unsigned long long wasted_bw_row; - unsigned long long wasted_bw_col; - unsigned long long util_bw; - unsigned long long idle_bw; - unsigned long long RCDc_limit; - unsigned long long CCDLc_limit; - unsigned long long CCDLc_limit_alone; - unsigned long long CCDc_limit; - unsigned long long WTRc_limit; - unsigned long long WTRc_limit_alone; - unsigned long long RCDWRc_limit; - unsigned long long RTWc_limit; - unsigned long long RTWc_limit_alone; - unsigned long long rwq_limit; + //some statistics to see where BW is wasted? + unsigned long long wasted_bw_row; + unsigned long long wasted_bw_col; + unsigned long long util_bw; + unsigned long long idle_bw; + unsigned long long RCDc_limit; + unsigned long long CCDLc_limit; + unsigned long long CCDLc_limit_alone; + unsigned long long CCDc_limit; + unsigned long long WTRc_limit; + unsigned long long WTRc_limit_alone; + unsigned long long RCDWRc_limit; + unsigned long long RTWc_limit; + unsigned long long RTWc_limit_alone; + unsigned long long rwq_limit; - // row locality, BLP and other statistics - unsigned long long access_num; - unsigned long long read_num; - unsigned long long write_num; - unsigned long long hits_num; - unsigned long long hits_read_num; - unsigned long long hits_write_num; - unsigned long long banks_1time; - unsigned long long banks_acess_total; - unsigned long long banks_acess_total_after; - unsigned long long banks_time_rw; - unsigned long long banks_access_rw_total; - unsigned long long banks_time_ready; - unsigned long long banks_access_ready_total; - unsigned long long issued_two; - unsigned long long issued_total; - unsigned long long issued_total_row; - unsigned long long issued_total_col; - double write_to_read_ratio_blp_rw_average; - unsigned long long bkgrp_parallsim_rw; + //row locality, BLP and other statistics + unsigned long long access_num; + unsigned long long read_num; + unsigned long long write_num; + unsigned long long hits_num; + unsigned long long hits_read_num; + unsigned long long hits_write_num; + unsigned long long banks_1time; + unsigned long long banks_acess_total; + unsigned long long banks_acess_total_after; + unsigned long long banks_time_rw; + unsigned long long banks_access_rw_total; + unsigned long long banks_time_ready; + unsigned long long banks_access_ready_total; + unsigned long long issued_two; + unsigned long long issued_total; + unsigned long long issued_total_row; + unsigned long long issued_total_col; + double write_to_read_ratio_blp_rw_average; + unsigned long long bkgrp_parallsim_rw; - unsigned int bwutil; - unsigned int max_mrqs; - unsigned int ave_mrqs; + unsigned int bwutil; + unsigned int max_mrqs; + unsigned int ave_mrqs; - class frfcfs_scheduler *m_frfcfs_scheduler; + class frfcfs_scheduler* m_frfcfs_scheduler; - unsigned int n_cmd_partial; - unsigned int n_activity_partial; - unsigned int n_nop_partial; - unsigned int n_act_partial; - unsigned int n_pre_partial; - unsigned int n_req_partial; - unsigned int ave_mrqs_partial; - unsigned int bwutil_partial; + unsigned int n_cmd_partial; + unsigned int n_activity_partial; + unsigned int n_nop_partial; + unsigned int n_act_partial; + unsigned int n_pre_partial; + unsigned int n_req_partial; + unsigned int ave_mrqs_partial; + unsigned int bwutil_partial; - class memory_stats_t *m_stats; - class Stats *mrqq_Dist; // memory request queue inside DRAM + class memory_stats_t *m_stats; + class Stats* mrqq_Dist; //memory request queue inside DRAM - friend class frfcfs_scheduler; + friend class frfcfs_scheduler; }; #endif /*DRAM_H*/ diff --git a/src/gpgpu-sim/dram_sched.cc b/src/gpgpu-sim/dram_sched.cc index da93aa1..6ee6271 100644 --- a/src/gpgpu-sim/dram_sched.cc +++ b/src/gpgpu-sim/dram_sched.cc @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -28,232 +26,224 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "dram_sched.h" -#include "../abstract_hardware_model.h" #include "gpu-misc.h" #include "gpu-sim.h" +#include "../abstract_hardware_model.h" #include "mem_latency_stat.h" -frfcfs_scheduler::frfcfs_scheduler(const memory_config *config, dram_t *dm, - memory_stats_t *stats) { - m_config = config; - m_stats = stats; - m_num_pending = 0; - m_num_write_pending = 0; - m_dram = dm; - m_queue = new std::list<dram_req_t *>[m_config->nbk]; - m_bins = new std::map< - unsigned, std::list<std::list<dram_req_t *>::iterator> >[m_config->nbk]; - m_last_row = - new std::list<std::list<dram_req_t *>::iterator> *[m_config->nbk]; - curr_row_service_time = new unsigned[m_config->nbk]; - row_service_timestamp = new unsigned[m_config->nbk]; - for (unsigned i = 0; i < m_config->nbk; i++) { - m_queue[i].clear(); - m_bins[i].clear(); - m_last_row[i] = NULL; - curr_row_service_time[i] = 0; - row_service_timestamp[i] = 0; - } - if (m_config->seperate_write_queue_enabled) { - m_write_queue = new std::list<dram_req_t *>[m_config->nbk]; - m_write_bins = new std::map< - unsigned, std::list<std::list<dram_req_t *>::iterator> >[m_config->nbk]; - m_last_write_row = - new std::list<std::list<dram_req_t *>::iterator> *[m_config->nbk]; +frfcfs_scheduler::frfcfs_scheduler( const memory_config *config, dram_t *dm, memory_stats_t *stats ) +{ + m_config = config; + m_stats = stats; + m_num_pending = 0; + m_num_write_pending = 0; + m_dram = dm; + m_queue = new std::list<dram_req_t*>[m_config->nbk]; + m_bins = new std::map<unsigned,std::list<std::list<dram_req_t*>::iterator> >[ m_config->nbk ]; + m_last_row = new std::list<std::list<dram_req_t*>::iterator>*[ m_config->nbk ]; + curr_row_service_time = new unsigned[m_config->nbk]; + row_service_timestamp = new unsigned[m_config->nbk]; + for ( unsigned i=0; i < m_config->nbk; i++ ) { + m_queue[i].clear(); + m_bins[i].clear(); + m_last_row[i] = NULL; + curr_row_service_time[i] = 0; + row_service_timestamp[i] = 0; + } + if(m_config->seperate_write_queue_enabled) { + m_write_queue = new std::list<dram_req_t*>[m_config->nbk]; + m_write_bins = new std::map<unsigned,std::list<std::list<dram_req_t*>::iterator> >[ m_config->nbk ]; + m_last_write_row = new std::list<std::list<dram_req_t*>::iterator>*[ m_config->nbk ]; + + for ( unsigned i=0; i < m_config->nbk; i++ ) { + m_write_queue[i].clear(); + m_write_bins[i].clear(); + m_last_write_row[i] = NULL; + } + } + m_mode = READ_MODE; - for (unsigned i = 0; i < m_config->nbk; i++) { - m_write_queue[i].clear(); - m_write_bins[i].clear(); - m_last_write_row[i] = NULL; - } - } - m_mode = READ_MODE; } -void frfcfs_scheduler::add_req(dram_req_t *req) { - if (m_config->seperate_write_queue_enabled && req->data->is_write()) { - assert(m_num_write_pending < m_config->gpgpu_frfcfs_dram_write_queue_size); - m_num_write_pending++; - m_write_queue[req->bk].push_front(req); - std::list<dram_req_t *>::iterator ptr = m_write_queue[req->bk].begin(); - m_write_bins[req->bk][req->row].push_front(ptr); // newest reqs to the - // front +void frfcfs_scheduler::add_req( dram_req_t *req ) +{ + if(m_config->seperate_write_queue_enabled && req->data->is_write()) { + assert(m_num_write_pending < m_config->gpgpu_frfcfs_dram_write_queue_size); + m_num_write_pending++; + m_write_queue[req->bk].push_front(req); + std::list<dram_req_t*>::iterator ptr = m_write_queue[req->bk].begin(); + m_write_bins[req->bk][req->row].push_front( ptr ); //newest reqs to the front } else { - assert(m_num_pending < m_config->gpgpu_frfcfs_dram_sched_queue_size); - m_num_pending++; - m_queue[req->bk].push_front(req); - std::list<dram_req_t *>::iterator ptr = m_queue[req->bk].begin(); - m_bins[req->bk][req->row].push_front(ptr); // newest reqs to the front + assert(m_num_pending < m_config->gpgpu_frfcfs_dram_sched_queue_size); + m_num_pending++; + m_queue[req->bk].push_front(req); + std::list<dram_req_t*>::iterator ptr = m_queue[req->bk].begin(); + m_bins[req->bk][req->row].push_front( ptr ); //newest reqs to the front } } -void frfcfs_scheduler::data_collection(unsigned int bank) { - if (m_dram->m_gpu->gpu_sim_cycle > row_service_timestamp[bank]) { - curr_row_service_time[bank] = - m_dram->m_gpu->gpu_sim_cycle - row_service_timestamp[bank]; - if (curr_row_service_time[bank] > - m_stats->max_servicetime2samerow[m_dram->id][bank]) - m_stats->max_servicetime2samerow[m_dram->id][bank] = - curr_row_service_time[bank]; - } - curr_row_service_time[bank] = 0; - row_service_timestamp[bank] = m_dram->m_gpu->gpu_sim_cycle; - if (m_stats->concurrent_row_access[m_dram->id][bank] > - m_stats->max_conc_access2samerow[m_dram->id][bank]) { - m_stats->max_conc_access2samerow[m_dram->id][bank] = - m_stats->concurrent_row_access[m_dram->id][bank]; - } - m_stats->concurrent_row_access[m_dram->id][bank] = 0; - m_stats->num_activates[m_dram->id][bank]++; +void frfcfs_scheduler::data_collection(unsigned int bank) +{ + if (m_dram->m_gpu->gpu_sim_cycle > row_service_timestamp[bank]) { + curr_row_service_time[bank] = m_dram->m_gpu->gpu_sim_cycle - row_service_timestamp[bank]; + if (curr_row_service_time[bank] > m_stats->max_servicetime2samerow[m_dram->id][bank]) + m_stats->max_servicetime2samerow[m_dram->id][bank] = curr_row_service_time[bank]; + } + curr_row_service_time[bank] = 0; + row_service_timestamp[bank] = m_dram->m_gpu->gpu_sim_cycle; + if (m_stats->concurrent_row_access[m_dram->id][bank] > m_stats->max_conc_access2samerow[m_dram->id][bank]) { + m_stats->max_conc_access2samerow[m_dram->id][bank] = m_stats->concurrent_row_access[m_dram->id][bank]; + } + m_stats->concurrent_row_access[m_dram->id][bank] = 0; + m_stats->num_activates[m_dram->id][bank]++; } -dram_req_t *frfcfs_scheduler::schedule(unsigned bank, unsigned curr_row) { - // row - bool rowhit = true; - std::list<dram_req_t *> *m_current_queue = m_queue; - std::map<unsigned, std::list<std::list<dram_req_t *>::iterator> > - *m_current_bins = m_bins; - std::list<std::list<dram_req_t *>::iterator> **m_current_last_row = - m_last_row; +dram_req_t *frfcfs_scheduler::schedule( unsigned bank, unsigned curr_row ) +{ + //row + bool rowhit = true; + std::list<dram_req_t*> *m_current_queue = m_queue; + std::map<unsigned,std::list<std::list<dram_req_t*>::iterator> > *m_current_bins = m_bins ; + std::list<std::list<dram_req_t*>::iterator> **m_current_last_row = m_last_row; - if (m_config->seperate_write_queue_enabled) { - if (m_mode == READ_MODE && - ((m_num_write_pending >= m_config->write_high_watermark) - // || (m_queue[bank].empty() && !m_write_queue[bank].empty()) - )) { - m_mode = WRITE_MODE; - } else if (m_mode == WRITE_MODE && - ((m_num_write_pending < m_config->write_low_watermark) - // || (!m_queue[bank].empty() && m_write_queue[bank].empty()) - )) { - m_mode = READ_MODE; - } - } + if(m_config->seperate_write_queue_enabled) { + if(m_mode == READ_MODE && + ((m_num_write_pending >= m_config->write_high_watermark ) + // || (m_queue[bank].empty() && !m_write_queue[bank].empty()) + )) { + m_mode = WRITE_MODE; + } + else if(m_mode == WRITE_MODE && + (( m_num_write_pending < m_config->write_low_watermark ) + // || (!m_queue[bank].empty() && m_write_queue[bank].empty()) + )){ + m_mode = READ_MODE; + } + } - if (m_mode == WRITE_MODE) { - m_current_queue = m_write_queue; - m_current_bins = m_write_bins; - m_current_last_row = m_last_write_row; - } + if(m_mode == WRITE_MODE) { + m_current_queue = m_write_queue; + m_current_bins = m_write_bins ; + m_current_last_row = m_last_write_row; + } - if (m_current_last_row[bank] == NULL) { - if (m_current_queue[bank].empty()) return NULL; + if ( m_current_last_row[bank] == NULL ) { + if ( m_current_queue[bank].empty() ) + return NULL; - std::map<unsigned, std::list<std::list<dram_req_t *>::iterator> >::iterator - bin_ptr = m_current_bins[bank].find(curr_row); - if (bin_ptr == m_current_bins[bank].end()) { - dram_req_t *req = m_current_queue[bank].back(); - bin_ptr = m_current_bins[bank].find(req->row); - assert(bin_ptr != - m_current_bins[bank].end()); // where did the request go??? - m_current_last_row[bank] = &(bin_ptr->second); - data_collection(bank); - rowhit = false; - } else { - m_current_last_row[bank] = &(bin_ptr->second); - rowhit = true; - } - } - std::list<dram_req_t *>::iterator next = m_current_last_row[bank]->back(); - dram_req_t *req = (*next); - - // rowblp stats - m_dram->access_num++; - bool is_write = req->data->is_write(); - if (is_write) - m_dram->write_num++; - else - m_dram->read_num++; + std::map<unsigned,std::list<std::list<dram_req_t*>::iterator> >::iterator bin_ptr = m_current_bins[bank].find( curr_row ); + if ( bin_ptr == m_current_bins[bank].end()) { + dram_req_t *req = m_current_queue[bank].back(); + bin_ptr = m_current_bins[bank].find( req->row ); + assert( bin_ptr != m_current_bins[bank].end() ); // where did the request go??? + m_current_last_row[bank] = &(bin_ptr->second); + data_collection(bank); + rowhit = false; + } else { + m_current_last_row[bank] = &(bin_ptr->second); + rowhit = true; + } + } + std::list<dram_req_t*>::iterator next = m_current_last_row[bank]->back(); + dram_req_t *req = (*next); - if (rowhit) { - m_dram->hits_num++; - if (is_write) - m_dram->hits_write_num++; + //rowblp stats + m_dram->access_num++; + bool is_write = req->data->is_write(); + if(is_write) + m_dram->write_num++; else - m_dram->hits_read_num++; - } + m_dram->read_num++; + + if(rowhit) { + m_dram->hits_num++; + if(is_write) + m_dram->hits_write_num++; + else + m_dram->hits_read_num++; + } - m_stats->concurrent_row_access[m_dram->id][bank]++; - m_stats->row_access[m_dram->id][bank]++; - m_current_last_row[bank]->pop_back(); + m_stats->concurrent_row_access[m_dram->id][bank]++; + m_stats->row_access[m_dram->id][bank]++; + m_current_last_row[bank]->pop_back(); - m_current_queue[bank].erase(next); - if (m_current_last_row[bank]->empty()) { - m_current_bins[bank].erase(req->row); - m_current_last_row[bank] = NULL; - } + m_current_queue[bank].erase(next); + if ( m_current_last_row[bank]->empty() ) { + m_current_bins[bank].erase( req->row ); + m_current_last_row[bank] = NULL; + } #ifdef DEBUG_FAST_IDEAL_SCHED - if (req) - printf("%08u : DRAM(%u) scheduling memory request to bank=%u, row=%u\n", - (unsigned)gpu_sim_cycle, m_dram->id, req->bk, req->row); + if ( req ) + printf("%08u : DRAM(%u) scheduling memory request to bank=%u, row=%u\n", + (unsigned)gpu_sim_cycle, m_dram->id, req->bk, req->row ); #endif - if (m_config->seperate_write_queue_enabled && req->data->is_write()) { - assert(req != NULL && m_num_write_pending != 0); - m_num_write_pending--; - } else { - assert(req != NULL && m_num_pending != 0); - m_num_pending--; - } + if(m_config->seperate_write_queue_enabled && req->data->is_write()) { + assert( req != NULL && m_num_write_pending != 0 ); + m_num_write_pending--; + } + else { + assert( req != NULL && m_num_pending != 0 ); + m_num_pending--; + } - return req; + return req; } -void frfcfs_scheduler::print(FILE *fp) { - for (unsigned b = 0; b < m_config->nbk; b++) { - printf(" %u: queue length = %u\n", b, (unsigned)m_queue[b].size()); - } + +void frfcfs_scheduler::print( FILE *fp ) +{ + for ( unsigned b=0; b < m_config->nbk; b++ ) { + printf(" %u: queue length = %u\n", b, (unsigned)m_queue[b].size() ); + } } -void dram_t::scheduler_frfcfs() { - unsigned mrq_latency; - frfcfs_scheduler *sched = m_frfcfs_scheduler; - while (!mrqq->empty()) { - dram_req_t *req = mrqq->pop(); +void dram_t::scheduler_frfcfs() +{ + unsigned mrq_latency; + frfcfs_scheduler *sched = m_frfcfs_scheduler; + while ( !mrqq->empty() ) { + dram_req_t *req = mrqq->pop(); - // Power stats - // if(req->data->get_type() != READ_REPLY && req->data->get_type() != - // WRITE_ACK) - m_stats->total_n_access++; + // Power stats + //if(req->data->get_type() != READ_REPLY && req->data->get_type() != WRITE_ACK) + m_stats->total_n_access++; - if (req->data->get_type() == WRITE_REQUEST) { - m_stats->total_n_writes++; - } else if (req->data->get_type() == READ_REQUEST) { - m_stats->total_n_reads++; - } + if(req->data->get_type() == WRITE_REQUEST){ + m_stats->total_n_writes++; + }else if(req->data->get_type() == READ_REQUEST){ + m_stats->total_n_reads++; + } - req->data->set_status(IN_PARTITION_MC_INPUT_QUEUE, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - sched->add_req(req); - } + req->data->set_status(IN_PARTITION_MC_INPUT_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); + sched->add_req(req); + } - dram_req_t *req; - unsigned i; - for (i = 0; i < m_config->nbk; i++) { - unsigned b = (i + prio) % m_config->nbk; - if (!bk[b]->mrq) { - req = sched->schedule(b, bk[b]->curr_row); + dram_req_t *req; + unsigned i; + for ( i=0; i < m_config->nbk; i++ ) { + unsigned b = (i+prio)%m_config->nbk; + if ( !bk[b]->mrq ) { - if (req) { - req->data->set_status(IN_PARTITION_MC_BANK_ARB_QUEUE, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - prio = (prio + 1) % m_config->nbk; - bk[b]->mrq = req; - if (m_config->gpgpu_memlatency_stat) { - mrq_latency = m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle - - bk[b]->mrq->timestamp; - m_stats->tot_mrq_latency += mrq_latency; - m_stats->tot_mrq_num++; - bk[b]->mrq->timestamp = - m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle; - m_stats->mrq_lat_table[LOGB2(mrq_latency)]++; - if (mrq_latency > m_stats->max_mrq_latency) { - m_stats->max_mrq_latency = mrq_latency; - } - } + req = sched->schedule(b, bk[b]->curr_row); - break; + if ( req ) { + req->data->set_status(IN_PARTITION_MC_BANK_ARB_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); + prio = (prio+1)%m_config->nbk; + bk[b]->mrq = req; + if (m_config->gpgpu_memlatency_stat) { + mrq_latency = m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle - bk[b]->mrq->timestamp; + m_stats->tot_mrq_latency += mrq_latency; + m_stats->tot_mrq_num++; + bk[b]->mrq->timestamp =m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle; + m_stats->mrq_lat_table[LOGB2(mrq_latency)]++; + if (mrq_latency > m_stats->max_mrq_latency) { + m_stats->max_mrq_latency = mrq_latency; + } + } + + break; + } } - } - } + } } diff --git a/src/gpgpu-sim/dram_sched.h b/src/gpgpu-sim/dram_sched.h index e003075..63f5831 100644 --- a/src/gpgpu-sim/dram_sched.h +++ b/src/gpgpu-sim/dram_sched.h @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -30,45 +28,45 @@ #ifndef dram_sched_h_INCLUDED #define dram_sched_h_INCLUDED -#include <list> -#include <map> #include "dram.h" -#include "gpu-misc.h" -#include "gpu-sim.h" #include "shader.h" +#include "gpu-sim.h" +#include "gpu-misc.h" +#include <list> +#include <map> -enum memory_mode { READ_MODE = 0, WRITE_MODE }; +enum memory_mode { + READ_MODE = 0, + WRITE_MODE +}; class frfcfs_scheduler { - public: - frfcfs_scheduler(const memory_config *config, dram_t *dm, - memory_stats_t *stats); - void add_req(dram_req_t *req); - void data_collection(unsigned bank); - dram_req_t *schedule(unsigned bank, unsigned curr_row); - void print(FILE *fp); - unsigned num_pending() const { return m_num_pending; } - unsigned num_write_pending() const { return m_num_write_pending; } +public: + frfcfs_scheduler( const memory_config *config, dram_t *dm, memory_stats_t *stats ); + void add_req( dram_req_t *req ); + void data_collection(unsigned bank); + dram_req_t *schedule( unsigned bank, unsigned curr_row ); + void print( FILE *fp ); + unsigned num_pending() const { return m_num_pending;} + unsigned num_write_pending() const { return m_num_write_pending;} - private: - const memory_config *m_config; - dram_t *m_dram; - unsigned m_num_pending; - unsigned m_num_write_pending; - std::list<dram_req_t *> *m_queue; - std::map<unsigned, std::list<std::list<dram_req_t *>::iterator> > *m_bins; - std::list<std::list<dram_req_t *>::iterator> **m_last_row; - unsigned *curr_row_service_time; // one set of variables for each bank. - unsigned *row_service_timestamp; // tracks when scheduler began servicing - // current row +private: + const memory_config *m_config; + dram_t *m_dram; + unsigned m_num_pending; + unsigned m_num_write_pending; + std::list<dram_req_t*> *m_queue; + std::map<unsigned,std::list<std::list<dram_req_t*>::iterator> > *m_bins; + std::list<std::list<dram_req_t*>::iterator> **m_last_row; + unsigned *curr_row_service_time; //one set of variables for each bank. + unsigned *row_service_timestamp; //tracks when scheduler began servicing current row - std::list<dram_req_t *> *m_write_queue; - std::map<unsigned, std::list<std::list<dram_req_t *>::iterator> > - *m_write_bins; - std::list<std::list<dram_req_t *>::iterator> **m_last_write_row; + std::list<dram_req_t*> *m_write_queue; + std::map<unsigned,std::list<std::list<dram_req_t*>::iterator> > *m_write_bins; + std::list<std::list<dram_req_t*>::iterator> **m_last_write_row; - enum memory_mode m_mode; - memory_stats_t *m_stats; + enum memory_mode m_mode; + memory_stats_t *m_stats; }; #endif diff --git a/src/gpgpu-sim/gpu-cache.cc b/src/gpgpu-sim/gpu-cache.cc index d126880..1e99fec 100644 --- a/src/gpgpu-sim/gpu-cache.cc +++ b/src/gpgpu-sim/gpu-cache.cc @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -28,1621 +26,1618 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "gpu-cache.h" -#include <assert.h> #include "gpu-sim.h" #include "stat-tool.h" +#include <assert.h> -// used to allocate memory that is large enough to adapt the changes in cache -// size across kernels +// used to allocate memory that is large enough to adapt the changes in cache size across kernels -const char *cache_request_status_str(enum cache_request_status status) { - static const char *static_cache_request_status_str[] = { - "HIT", "HIT_RESERVED", "MISS", "RESERVATION_FAIL", "SECTOR_MISS"}; +const char * cache_request_status_str(enum cache_request_status status) +{ + static const char * static_cache_request_status_str[] = { + "HIT", + "HIT_RESERVED", + "MISS", + "RESERVATION_FAIL", + "SECTOR_MISS" + }; - assert(sizeof(static_cache_request_status_str) / sizeof(const char *) == - NUM_CACHE_REQUEST_STATUS); - assert(status < NUM_CACHE_REQUEST_STATUS); + assert(sizeof(static_cache_request_status_str) / sizeof(const char*) == NUM_CACHE_REQUEST_STATUS); + assert(status < NUM_CACHE_REQUEST_STATUS); - return static_cache_request_status_str[status]; + return static_cache_request_status_str[status]; } -const char *cache_fail_status_str(enum cache_reservation_fail_reason status) { - static const char *static_cache_reservation_fail_reason_str[] = { - "LINE_ALLOC_FAIL", "MISS_QUEUE_FULL", "MSHR_ENRTY_FAIL", - "MSHR_MERGE_ENRTY_FAIL", "MSHR_RW_PENDING"}; +const char * cache_fail_status_str(enum cache_reservation_fail_reason status) +{ + static const char * static_cache_reservation_fail_reason_str[] = { + "LINE_ALLOC_FAIL", + "MISS_QUEUE_FULL", + "MSHR_ENRTY_FAIL", + "MSHR_MERGE_ENRTY_FAIL", + "MSHR_RW_PENDING" + }; - assert(sizeof(static_cache_reservation_fail_reason_str) / - sizeof(const char *) == - NUM_CACHE_RESERVATION_FAIL_STATUS); - assert(status < NUM_CACHE_RESERVATION_FAIL_STATUS); + assert(sizeof(static_cache_reservation_fail_reason_str) / sizeof(const char*) == NUM_CACHE_RESERVATION_FAIL_STATUS); + assert(status < NUM_CACHE_RESERVATION_FAIL_STATUS); - return static_cache_reservation_fail_reason_str[status]; + return static_cache_reservation_fail_reason_str[status]; } -unsigned l1d_cache_config::set_bank(new_addr_type addr) const { - if (m_cache_type == SECTOR) - return (addr >> m_sector_sz_log2) & (l1_banks - 1); - else - return (addr >> m_line_sz_log2) & (l1_banks - 1); +unsigned l1d_cache_config::set_bank(new_addr_type addr) const{ + + if(m_cache_type == SECTOR) + return (addr >> m_sector_sz_log2) & (l1_banks-1); + else + return (addr >> m_line_sz_log2) & (l1_banks-1); } -unsigned l1d_cache_config::set_index(new_addr_type addr) const { - unsigned set_index = m_nset; // Default to linear set index function - unsigned lower_xor = 0; - unsigned upper_xor = 0; +unsigned l1d_cache_config::set_index(new_addr_type addr) const{ + unsigned set_index = m_nset; // Default to linear set index function + unsigned lower_xor = 0; + unsigned upper_xor = 0; - switch (m_set_index_function) { + switch(m_set_index_function){ case FERMI_HASH_SET_FUNCTION: case BITWISE_XORING_FUNCTION: - /* - * Set Indexing function from "A Detailed GPU Cache Model Based on Reuse - * Distance Theory" - * Cedric Nugteren et al. - * HPCA 2014 - */ - if (m_nset == 32 || m_nset == 64) { - // Lower xor value is bits 7-11 - lower_xor = (addr >> m_line_sz_log2) & 0x1F; + /* + * Set Indexing function from "A Detailed GPU Cache Model Based on Reuse Distance Theory" + * Cedric Nugteren et al. + * HPCA 2014 + */ + if(m_nset == 32 || m_nset == 64){ + // Lower xor value is bits 7-11 + lower_xor = (addr >> m_line_sz_log2) & 0x1F; - // Upper xor value is bits 13, 14, 15, 17, and 19 - upper_xor = (addr & 0xE000) >> 13; // Bits 13, 14, 15 - upper_xor |= (addr & 0x20000) >> 14; // Bit 17 - upper_xor |= (addr & 0x80000) >> 15; // Bit 19 + // Upper xor value is bits 13, 14, 15, 17, and 19 + upper_xor = (addr & 0xE000) >> 13; // Bits 13, 14, 15 + upper_xor |= (addr & 0x20000) >> 14; // Bit 17 + upper_xor |= (addr & 0x80000) >> 15; // Bit 19 - set_index = (lower_xor ^ upper_xor); + set_index = (lower_xor ^ upper_xor); - // 48KB cache prepends the set_index with bit 12 - if (m_nset == 64) set_index |= (addr & 0x1000) >> 7; + // 48KB cache prepends the set_index with bit 12 + if(m_nset == 64) + set_index |= (addr & 0x1000) >> 7; - } else { /* Else incorrect number of sets for the hashing function */ - assert( - "\nGPGPU-Sim cache configuration error: The number of sets should " - "be " - "32 or 64 for the hashing set index function.\n" && - 0); - } - break; + }else{ /* Else incorrect number of sets for the hashing function */ + assert("\nGPGPU-Sim cache configuration error: The number of sets should be " + "32 or 64 for the hashing set index function.\n" && 0); + } + break; case HASH_IPOLY_FUNCTION: - /* - * Set Indexing function from "Pseudo-randomly interleaved memory." - * Rau, B. R et al. - * ISCA 1991 - * - * "Sacat: streaming-aware conflict-avoiding thrashing-resistant - * gpgpu cache management scheme." - * Khairy et al. - * IEEE TPDS 2017. - */ - if (m_nset == 32 || m_nset == 64) { - std::bitset<64> a(addr); - std::bitset<6> index; - index[0] = a[25] ^ a[24] ^ a[23] ^ a[22] ^ a[21] ^ a[18] ^ a[17] ^ - a[15] ^ a[12] ^ a[7]; // 10 - index[1] = a[26] ^ a[25] ^ a[24] ^ a[23] ^ a[22] ^ a[19] ^ a[18] ^ - a[16] ^ a[13] ^ a[8]; // 10 - index[2] = a[26] ^ a[22] ^ a[21] ^ a[20] ^ a[19] ^ a[18] ^ a[15] ^ - a[14] ^ a[12] ^ a[9]; // 10 - index[3] = a[23] ^ a[22] ^ a[21] ^ a[20] ^ a[19] ^ a[16] ^ a[15] ^ - a[13] ^ a[10]; // 9 - index[4] = a[24] ^ a[23] ^ a[22] ^ a[21] ^ a[20] ^ a[17] ^ a[16] ^ - a[14] ^ a[11]; // 9 + /* + * Set Indexing function from "Pseudo-randomly interleaved memory." + * Rau, B. R et al. + * ISCA 1991 + * + * "Sacat: streaming-aware conflict-avoiding thrashing-resistant gpgpu cache management scheme." + * Khairy et al. + * IEEE TPDS 2017. + */ + if(m_nset == 32 || m_nset == 64){ + std::bitset<64> a(addr); + std::bitset<6> index; + index[0] = a[25]^a[24]^a[23]^a[22]^a[21]^a[18]^a[17]^a[15]^a[12]^a[7]; //10 + index[1] = a[26]^a[25]^a[24]^a[23]^a[22]^a[19]^a[18]^a[16]^a[13]^a[8]; //10 + index[2] = a[26]^a[22]^a[21]^a[20]^a[19]^a[18]^a[15]^a[14]^a[12]^a[9]; //10 + index[3] = a[23]^a[22]^a[21]^a[20]^a[19]^a[16]^a[15]^a[13]^a[10]; //9 + index[4] = a[24]^a[23]^a[22]^a[21]^a[20]^a[17]^a[16]^a[14]^a[11]; //9 - if (m_nset == 64) index[5] = a[12]; + if(m_nset == 64) + index[5] = a[12]; - set_index = index.to_ulong(); + set_index = index.to_ulong(); - } else { /* Else incorrect number of sets for the hashing function */ - assert( - "\nGPGPU-Sim cache configuration error: The number of sets should " - "be " - "32 or 64 for the hashing set index function.\n" && - 0); - } - break; + }else{ /* Else incorrect number of sets for the hashing function */ + assert("\nGPGPU-Sim cache configuration error: The number of sets should be " + "32 or 64 for the hashing set index function.\n" && 0); + } + break; case CUSTOM_SET_FUNCTION: - /* No custom set function implemented */ - break; + /* No custom set function implemented */ + break; case LINEAR_SET_FUNCTION: - set_index = (addr >> m_line_sz_log2) & (m_nset - 1); - break; + set_index = (addr >> m_line_sz_log2) & (m_nset-1); + break; default: - assert("\nUndefined set index function.\n" && 0); - break; - } + assert("\nUndefined set index function.\n" && 0); + break; + } - // Linear function selected or custom set index function not implemented - assert((set_index < m_nset) && - "\nError: Set index out of bounds. This is caused by " - "an incorrect or unimplemented custom set index function.\n"); + // Linear function selected or custom set index function not implemented + assert((set_index < m_nset) && "\nError: Set index out of bounds. This is caused by " + "an incorrect or unimplemented custom set index function.\n"); - return set_index; + return set_index; } -void l2_cache_config::init(linear_to_raw_address_translation *address_mapping) { - cache_config::init(m_config_string, FuncCachePreferNone); - m_address_mapping = address_mapping; +void l2_cache_config::init(linear_to_raw_address_translation *address_mapping){ + cache_config::init(m_config_string,FuncCachePreferNone); + m_address_mapping = address_mapping; } -unsigned l2_cache_config::set_index(new_addr_type addr) const { - if (!m_address_mapping) { - return (addr >> m_line_sz_log2) & (m_nset - 1); - } else { - // Calculate set index without memory partition bits to reduce set camping - new_addr_type part_addr = m_address_mapping->partition_address(addr); - return (part_addr >> m_line_sz_log2) & (m_nset - 1); - } +unsigned l2_cache_config::set_index(new_addr_type addr) const{ + if(!m_address_mapping){ + return(addr >> m_line_sz_log2) & (m_nset-1); + }else{ + // Calculate set index without memory partition bits to reduce set camping + new_addr_type part_addr = m_address_mapping->partition_address(addr); + return(part_addr >> m_line_sz_log2) & (m_nset -1); + } } -tag_array::~tag_array() { - unsigned cache_lines_num = m_config.get_max_num_lines(); - for (unsigned i = 0; i < cache_lines_num; ++i) delete m_lines[i]; - delete[] m_lines; +tag_array::~tag_array() +{ + unsigned cache_lines_num = m_config.get_max_num_lines(); + for(unsigned i=0; i<cache_lines_num; ++i) + delete m_lines[i]; + delete[] m_lines; } -tag_array::tag_array(cache_config &config, int core_id, int type_id, - cache_block_t **new_lines) - : m_config(config), m_lines(new_lines) { - init(core_id, type_id); +tag_array::tag_array( cache_config &config, + int core_id, + int type_id, + cache_block_t** new_lines) + : m_config( config ), + m_lines( new_lines ) +{ + init( core_id, type_id ); } -void tag_array::update_cache_parameters(cache_config &config) { - m_config = config; +void tag_array::update_cache_parameters(cache_config &config) +{ + m_config=config; } -tag_array::tag_array(cache_config &config, int core_id, int type_id) - : m_config(config) { - // assert( m_config.m_write_policy == READ_ONLY ); Old assert - unsigned cache_lines_num = config.get_max_num_lines(); - m_lines = new cache_block_t *[cache_lines_num]; - if (config.m_cache_type == NORMAL) { - for (unsigned i = 0; i < cache_lines_num; ++i) - m_lines[i] = new line_cache_block(); - } else if (config.m_cache_type == SECTOR) { - for (unsigned i = 0; i < cache_lines_num; ++i) - m_lines[i] = new sector_cache_block(); - } else - assert(0); +tag_array::tag_array( cache_config &config, + int core_id, + int type_id ) + : m_config( config ) +{ + //assert( m_config.m_write_policy == READ_ONLY ); Old assert + unsigned cache_lines_num = config.get_max_num_lines(); + m_lines = new cache_block_t*[cache_lines_num]; + if(config.m_cache_type == NORMAL) + { + for(unsigned i=0; i<cache_lines_num; ++i) + m_lines[i] = new line_cache_block(); + } + else if(config.m_cache_type == SECTOR) + { + for(unsigned i=0; i<cache_lines_num; ++i) + m_lines[i] = new sector_cache_block(); + } + else + assert(0); - init(core_id, type_id); + init( core_id, type_id ); } -void tag_array::init(int core_id, int type_id) { - m_access = 0; - m_miss = 0; - m_pending_hit = 0; - m_res_fail = 0; - m_sector_miss = 0; - // initialize snapshot counters for visualizer - m_prev_snapshot_access = 0; - m_prev_snapshot_miss = 0; - m_prev_snapshot_pending_hit = 0; - m_core_id = core_id; - m_type_id = type_id; - is_used = false; +void tag_array::init( int core_id, int type_id ) +{ + m_access = 0; + m_miss = 0; + m_pending_hit = 0; + m_res_fail = 0; + m_sector_miss = 0; + // initialize snapshot counters for visualizer + m_prev_snapshot_access = 0; + m_prev_snapshot_miss = 0; + m_prev_snapshot_pending_hit = 0; + m_core_id = core_id; + m_type_id = type_id; + is_used = false; } -void tag_array::add_pending_line(mem_fetch *mf) { - assert(mf); - new_addr_type addr = m_config.block_addr(mf->get_addr()); - line_table::const_iterator i = pending_lines.find(addr); - if (i == pending_lines.end()) { - pending_lines[addr] = mf->get_inst().get_uid(); - } +void tag_array::add_pending_line(mem_fetch *mf){ + assert(mf); + new_addr_type addr = m_config.block_addr(mf->get_addr()); + line_table::const_iterator i = pending_lines.find(addr); + if ( i == pending_lines.end() ) { + pending_lines[addr] = mf->get_inst().get_uid(); + } } -void tag_array::remove_pending_line(mem_fetch *mf) { - assert(mf); - new_addr_type addr = m_config.block_addr(mf->get_addr()); - line_table::const_iterator i = pending_lines.find(addr); - if (i != pending_lines.end()) { - pending_lines.erase(addr); - } +void tag_array::remove_pending_line(mem_fetch *mf){ + assert(mf); + new_addr_type addr = m_config.block_addr(mf->get_addr()); + line_table::const_iterator i = pending_lines.find(addr); + if ( i != pending_lines.end() ) { + pending_lines.erase(addr); + } } -enum cache_request_status tag_array::probe(new_addr_type addr, unsigned &idx, - mem_fetch *mf, - bool probe_mode) const { - mem_access_sector_mask_t mask = mf->get_access_sector_mask(); - return probe(addr, idx, mask, probe_mode, mf); +enum cache_request_status tag_array::probe( new_addr_type addr, unsigned &idx, mem_fetch* mf, bool probe_mode) const { + mem_access_sector_mask_t mask = mf->get_access_sector_mask(); + return probe(addr, idx, mask, probe_mode, mf); } -enum cache_request_status tag_array::probe(new_addr_type addr, unsigned &idx, - mem_access_sector_mask_t mask, - bool probe_mode, - mem_fetch *mf) const { - // assert( m_config.m_write_policy == READ_ONLY ); - unsigned set_index = m_config.set_index(addr); - new_addr_type tag = m_config.tag(addr); - unsigned invalid_line = (unsigned)-1; - unsigned valid_line = (unsigned)-1; - unsigned long long valid_timestamp = (unsigned)-1; +enum cache_request_status tag_array::probe( new_addr_type addr, unsigned &idx, mem_access_sector_mask_t mask, bool probe_mode, mem_fetch* mf) const { + //assert( m_config.m_write_policy == READ_ONLY ); + unsigned set_index = m_config.set_index(addr); + new_addr_type tag = m_config.tag(addr); - bool all_reserved = true; + unsigned invalid_line = (unsigned)-1; + unsigned valid_line = (unsigned)-1; + unsigned long long valid_timestamp = (unsigned)-1; - // check for hit or pending hit - for (unsigned way = 0; way < m_config.m_assoc; way++) { - unsigned index = set_index * m_config.m_assoc + way; - cache_block_t *line = m_lines[index]; - if (line->m_tag == tag) { - if (line->get_status(mask) == RESERVED) { - idx = index; - return HIT_RESERVED; - } else if (line->get_status(mask) == VALID) { - idx = index; - return HIT; - } else if (line->get_status(mask) == MODIFIED) { - if (line->is_readable(mask)) { - idx = index; - return HIT; - } else { - idx = index; - return SECTOR_MISS; - } + bool all_reserved = true; - } else if (line->is_valid_line() && line->get_status(mask) == INVALID) { - idx = index; - return SECTOR_MISS; - } else { - assert(line->get_status(mask) == INVALID); - } - } - if (!line->is_reserved_line()) { - all_reserved = false; - if (line->is_invalid_line()) { - invalid_line = index; - } else { - // valid line : keep track of most appropriate replacement candidate - if (m_config.m_replacement_policy == LRU) { - if (line->get_last_access_time() < valid_timestamp) { - valid_timestamp = line->get_last_access_time(); - valid_line = index; - } - } else if (m_config.m_replacement_policy == FIFO) { - if (line->get_alloc_time() < valid_timestamp) { - valid_timestamp = line->get_alloc_time(); - valid_line = index; - } + // check for hit or pending hit + for (unsigned way=0; way<m_config.m_assoc; way++) { + unsigned index = set_index*m_config.m_assoc+way; + cache_block_t *line = m_lines[index]; + if (line->m_tag == tag) { + if ( line->get_status(mask) == RESERVED ) { + idx = index; + return HIT_RESERVED; + } else if ( line->get_status(mask) == VALID ) { + idx = index; + return HIT; + } else if ( line->get_status(mask) == MODIFIED) { + if(line->is_readable(mask)) { + idx = index; + return HIT; + } + else { + idx = index; + return SECTOR_MISS; + } + + } else if ( line->is_valid_line() && line->get_status(mask) == INVALID ) { + idx = index; + return SECTOR_MISS; + }else { + assert( line->get_status(mask) == INVALID ); + } } - } + if (!line->is_reserved_line()) { + all_reserved = false; + if (line->is_invalid_line()) { + invalid_line = index; + } else { + // valid line : keep track of most appropriate replacement candidate + if ( m_config.m_replacement_policy == LRU ) { + if ( line->get_last_access_time() < valid_timestamp ) { + valid_timestamp = line->get_last_access_time(); + valid_line = index; + } + } else if ( m_config.m_replacement_policy == FIFO ) { + if ( line->get_alloc_time() < valid_timestamp ) { + valid_timestamp = line->get_alloc_time(); + valid_line = index; + } + } + } + } + } + if ( all_reserved ) { + assert( m_config.m_alloc_policy == ON_MISS ); + return RESERVATION_FAIL; // miss and not enough space in cache to allocate on miss } - } - if (all_reserved) { - assert(m_config.m_alloc_policy == ON_MISS); - return RESERVATION_FAIL; // miss and not enough space in cache to allocate - // on miss - } - if (invalid_line != (unsigned)-1) { - idx = invalid_line; - } else if (valid_line != (unsigned)-1) { - idx = valid_line; - } else - abort(); // if an unreserved block exists, it is either invalid or - // replaceable + if ( invalid_line != (unsigned)-1 ) { + idx = invalid_line; + } else if ( valid_line != (unsigned)-1) { + idx = valid_line; + } else abort(); // if an unreserved block exists, it is either invalid or replaceable + - if (probe_mode && m_config.is_streaming()) { - line_table::const_iterator i = - pending_lines.find(m_config.block_addr(addr)); - assert(mf); - if (!mf->is_write() && i != pending_lines.end()) { - if (i->second != mf->get_inst().get_uid()) return SECTOR_MISS; + if(probe_mode && m_config.is_streaming()){ + line_table::const_iterator i = pending_lines.find(m_config.block_addr(addr)); + assert(mf); + if ( !mf->is_write() && i != pending_lines.end() ) { + if(i->second != mf->get_inst().get_uid()) + return SECTOR_MISS; + } } - } - return MISS; + return MISS; } -enum cache_request_status tag_array::access(new_addr_type addr, unsigned time, - unsigned &idx, mem_fetch *mf) { - bool wb = false; - evicted_block_info evicted; - enum cache_request_status result = access(addr, time, idx, wb, evicted, mf); - assert(!wb); - return result; +enum cache_request_status tag_array::access( new_addr_type addr, unsigned time, unsigned &idx, mem_fetch* mf) +{ + bool wb=false; + evicted_block_info evicted; + enum cache_request_status result = access(addr,time,idx,wb,evicted,mf); + assert(!wb); + return result; } -enum cache_request_status tag_array::access(new_addr_type addr, unsigned time, - unsigned &idx, bool &wb, - evicted_block_info &evicted, - mem_fetch *mf) { - m_access++; - is_used = true; - shader_cache_access_log(m_core_id, m_type_id, 0); // log accesses to cache - enum cache_request_status status = probe(addr, idx, mf); - switch (status) { - case HIT_RESERVED: - m_pending_hit++; - case HIT: - m_lines[idx]->set_last_access_time(time, mf->get_access_sector_mask()); - break; +enum cache_request_status tag_array::access( new_addr_type addr, unsigned time, unsigned &idx, bool &wb, evicted_block_info &evicted, mem_fetch* mf ) +{ + m_access++; + is_used = true; + shader_cache_access_log(m_core_id, m_type_id, 0); // log accesses to cache + enum cache_request_status status = probe(addr,idx,mf); + switch (status) { + case HIT_RESERVED: + m_pending_hit++; + case HIT: + m_lines[idx]->set_last_access_time(time, mf->get_access_sector_mask()); + break; case MISS: - m_miss++; - shader_cache_access_log(m_core_id, m_type_id, 1); // log cache misses - if (m_config.m_alloc_policy == ON_MISS) { - if (m_lines[idx]->is_modified_line()) { - wb = true; - evicted.set_info(m_lines[idx]->m_block_addr, - m_lines[idx]->get_modified_size()); + m_miss++; + shader_cache_access_log(m_core_id, m_type_id, 1); // log cache misses + if ( m_config.m_alloc_policy == ON_MISS ) { + if( m_lines[idx]->is_modified_line()) { + wb = true; + evicted.set_info(m_lines[idx]->m_block_addr, m_lines[idx]->get_modified_size()); + } + m_lines[idx]->allocate( m_config.tag(addr), m_config.block_addr(addr), time, mf->get_access_sector_mask()); } - m_lines[idx]->allocate(m_config.tag(addr), m_config.block_addr(addr), - time, mf->get_access_sector_mask()); - } - break; + break; case SECTOR_MISS: - assert(m_config.m_cache_type == SECTOR); - m_sector_miss++; - shader_cache_access_log(m_core_id, m_type_id, 1); // log cache misses - if (m_config.m_alloc_policy == ON_MISS) { - ((sector_cache_block *)m_lines[idx]) - ->allocate_sector(time, mf->get_access_sector_mask()); - } - break; + assert(m_config.m_cache_type == SECTOR); + m_sector_miss++; + shader_cache_access_log(m_core_id, m_type_id, 1); // log cache misses + if ( m_config.m_alloc_policy == ON_MISS ) { + ((sector_cache_block*)m_lines[idx])->allocate_sector( time, mf->get_access_sector_mask() ); + } + break; case RESERVATION_FAIL: - m_res_fail++; - shader_cache_access_log(m_core_id, m_type_id, 1); // log cache misses - break; + m_res_fail++; + shader_cache_access_log(m_core_id, m_type_id, 1); // log cache misses + break; default: - fprintf(stderr, - "tag_array::access - Error: Unknown" - "cache_request_status %d\n", - status); - abort(); - } - return status; + fprintf( stderr, "tag_array::access - Error: Unknown" + "cache_request_status %d\n", status ); + abort(); + } + return status; } -void tag_array::fill(new_addr_type addr, unsigned time, mem_fetch *mf) { - fill(addr, time, mf->get_access_sector_mask()); +void tag_array::fill( new_addr_type addr, unsigned time, mem_fetch* mf) +{ + fill(addr, time, mf->get_access_sector_mask()); } -void tag_array::fill(new_addr_type addr, unsigned time, - mem_access_sector_mask_t mask) { - // assert( m_config.m_alloc_policy == ON_FILL ); - unsigned idx; - enum cache_request_status status = probe(addr, idx, mask); - // assert(status==MISS||status==SECTOR_MISS); // MSHR should have prevented - // redundant memory request - if (status == MISS) - m_lines[idx]->allocate(m_config.tag(addr), m_config.block_addr(addr), time, - mask); - else if (status == SECTOR_MISS) { - assert(m_config.m_cache_type == SECTOR); - ((sector_cache_block *)m_lines[idx])->allocate_sector(time, mask); - } +void tag_array::fill( new_addr_type addr, unsigned time, mem_access_sector_mask_t mask ) +{ + //assert( m_config.m_alloc_policy == ON_FILL ); + unsigned idx; + enum cache_request_status status = probe(addr,idx,mask); + //assert(status==MISS||status==SECTOR_MISS); // MSHR should have prevented redundant memory request + if(status==MISS) + m_lines[idx]->allocate( m_config.tag(addr), m_config.block_addr(addr), time, mask ); + else if (status==SECTOR_MISS) { + assert(m_config.m_cache_type == SECTOR); + ((sector_cache_block*)m_lines[idx])->allocate_sector( time, mask ); + } - m_lines[idx]->fill(time, mask); + m_lines[idx]->fill(time, mask); } -void tag_array::fill(unsigned index, unsigned time, mem_fetch *mf) { - assert(m_config.m_alloc_policy == ON_MISS); - m_lines[index]->fill(time, mf->get_access_sector_mask()); +void tag_array::fill( unsigned index, unsigned time, mem_fetch* mf) +{ + assert( m_config.m_alloc_policy == ON_MISS ); + m_lines[index]->fill(time, mf->get_access_sector_mask()); } -// TODO: we need write back the flushed data to the upper level -void tag_array::flush() { - if (!is_used) return; - for (unsigned i = 0; i < m_config.get_num_lines(); i++) - if (m_lines[i]->is_modified_line()) { - for (unsigned j = 0; j < SECTOR_CHUNCK_SIZE; j++) - m_lines[i]->set_status(INVALID, mem_access_sector_mask_t().set(j)); - } +//TODO: we need write back the flushed data to the upper level +void tag_array::flush() +{ + if(!is_used) + return; + + for (unsigned i=0; i < m_config.get_num_lines(); i++) + if(m_lines[i]->is_modified_line()) { + for(unsigned j=0; j < SECTOR_CHUNCK_SIZE; j++) + m_lines[i]->set_status(INVALID, mem_access_sector_mask_t().set(j)) ; + } - is_used = false; + is_used = false; } -void tag_array::invalidate() { - if (!is_used) return; +void tag_array::invalidate() +{ + if(!is_used) + return; - for (unsigned i = 0; i < m_config.get_num_lines(); i++) - for (unsigned j = 0; j < SECTOR_CHUNCK_SIZE; j++) - m_lines[i]->set_status(INVALID, mem_access_sector_mask_t().set(j)); + for (unsigned i=0; i < m_config.get_num_lines(); i++) + for(unsigned j=0; j < SECTOR_CHUNCK_SIZE; j++) + m_lines[i]->set_status(INVALID, mem_access_sector_mask_t().set(j)) ; - is_used = false; + is_used = false; } -float tag_array::windowed_miss_rate() const { - unsigned n_access = m_access - m_prev_snapshot_access; - unsigned n_miss = (m_miss + m_sector_miss) - m_prev_snapshot_miss; - // unsigned n_pending_hit = m_pending_hit - m_prev_snapshot_pending_hit; +float tag_array::windowed_miss_rate( ) const +{ + unsigned n_access = m_access - m_prev_snapshot_access; + unsigned n_miss = (m_miss+m_sector_miss) - m_prev_snapshot_miss; + // unsigned n_pending_hit = m_pending_hit - m_prev_snapshot_pending_hit; - float missrate = 0.0f; - if (n_access != 0) missrate = (float)(n_miss + m_sector_miss) / n_access; - return missrate; + float missrate = 0.0f; + if (n_access != 0) + missrate = (float) (n_miss+m_sector_miss) / n_access; + return missrate; } -void tag_array::new_window() { - m_prev_snapshot_access = m_access; - m_prev_snapshot_miss = m_miss; - m_prev_snapshot_miss = m_miss + m_sector_miss; - m_prev_snapshot_pending_hit = m_pending_hit; +void tag_array::new_window() +{ + m_prev_snapshot_access = m_access; + m_prev_snapshot_miss = m_miss; + m_prev_snapshot_miss = m_miss + m_sector_miss; + m_prev_snapshot_pending_hit = m_pending_hit; } -void tag_array::print(FILE *stream, unsigned &total_access, - unsigned &total_misses) const { - m_config.print(stream); - fprintf(stream, - "\t\tAccess = %d, Miss = %d, Sector_Miss = %d, Total_Miss = %d " - "(%.3g), PendingHit = %d (%.3g)\n", - m_access, m_miss, m_sector_miss, (m_miss + m_sector_miss), - (float)(m_miss + m_sector_miss) / m_access, m_pending_hit, - (float)m_pending_hit / m_access); - total_misses += (m_miss + m_sector_miss); - total_access += m_access; +void tag_array::print( FILE *stream, unsigned &total_access, unsigned &total_misses ) const +{ + m_config.print(stream); + fprintf( stream, "\t\tAccess = %d, Miss = %d, Sector_Miss = %d, Total_Miss = %d (%.3g), PendingHit = %d (%.3g)\n", + m_access, m_miss, m_sector_miss, (m_miss+m_sector_miss), (float) (m_miss+m_sector_miss) / m_access, + m_pending_hit, (float) m_pending_hit / m_access); + total_misses+=(m_miss+m_sector_miss); + total_access+=m_access; } -void tag_array::get_stats(unsigned &total_access, unsigned &total_misses, - unsigned &total_hit_res, - unsigned &total_res_fail) const { - // Update statistics from the tag array - total_access = m_access; - total_misses = (m_miss + m_sector_miss); - total_hit_res = m_pending_hit; - total_res_fail = m_res_fail; +void tag_array::get_stats(unsigned &total_access, unsigned &total_misses, unsigned &total_hit_res, unsigned &total_res_fail) const{ + // Update statistics from the tag array + total_access = m_access; + total_misses = (m_miss+m_sector_miss); + total_hit_res = m_pending_hit; + total_res_fail = m_res_fail; } -bool was_write_sent(const std::list<cache_event> &events) { - for (std::list<cache_event>::const_iterator e = events.begin(); - e != events.end(); e++) { - if ((*e).m_cache_event_type == WRITE_REQUEST_SENT) return true; - } - return false; + +bool was_write_sent( const std::list<cache_event> &events ) +{ + for( std::list<cache_event>::const_iterator e=events.begin(); e!=events.end(); e++ ) { + if( (*e).m_cache_event_type == WRITE_REQUEST_SENT ) + return true; + } + return false; } -bool was_writeback_sent(const std::list<cache_event> &events, - cache_event &wb_event) { - for (std::list<cache_event>::const_iterator e = events.begin(); - e != events.end(); e++) { - if ((*e).m_cache_event_type == WRITE_BACK_REQUEST_SENT) wb_event = *e; - return true; - } - return false; +bool was_writeback_sent( const std::list<cache_event> &events, cache_event& wb_event) +{ + for( std::list<cache_event>::const_iterator e=events.begin(); e!=events.end(); e++ ) { + if( (*e).m_cache_event_type == WRITE_BACK_REQUEST_SENT ) + wb_event = *e; + return true; + } + return false; } -bool was_read_sent(const std::list<cache_event> &events) { - for (std::list<cache_event>::const_iterator e = events.begin(); - e != events.end(); e++) { - if ((*e).m_cache_event_type == READ_REQUEST_SENT) return true; - } - return false; +bool was_read_sent( const std::list<cache_event> &events ) +{ + for( std::list<cache_event>::const_iterator e=events.begin(); e!=events.end(); e++ ) { + if( (*e).m_cache_event_type == READ_REQUEST_SENT ) + return true; + } + return false; } -bool was_writeallocate_sent(const std::list<cache_event> &events) { - for (std::list<cache_event>::const_iterator e = events.begin(); - e != events.end(); e++) { - if ((*e).m_cache_event_type == WRITE_ALLOCATE_SENT) return true; - } - return false; +bool was_writeallocate_sent( const std::list<cache_event> &events ) +{ + for( std::list<cache_event>::const_iterator e=events.begin(); e!=events.end(); e++ ) { + if( (*e).m_cache_event_type == WRITE_ALLOCATE_SENT ) + return true; + } + return false; } -/****************************************************************** MSHR - * ******************************************************************/ +/****************************************************************** MSHR ******************************************************************/ /// Checks if there is a pending request to the lower memory level already -bool mshr_table::probe(new_addr_type block_addr) const { - table::const_iterator a = m_data.find(block_addr); - return a != m_data.end(); +bool mshr_table::probe( new_addr_type block_addr ) const{ + table::const_iterator a = m_data.find(block_addr); + return a != m_data.end(); } /// Checks if there is space for tracking a new memory access -bool mshr_table::full(new_addr_type block_addr) const { - table::const_iterator i = m_data.find(block_addr); - if (i != m_data.end()) - return i->second.m_list.size() >= m_max_merged; - else - return m_data.size() >= m_num_entries; +bool mshr_table::full( new_addr_type block_addr ) const{ + table::const_iterator i=m_data.find(block_addr); + if ( i != m_data.end() ) + return i->second.m_list.size() >= m_max_merged; + else + return m_data.size() >= m_num_entries; } /// Add or merge this access -void mshr_table::add(new_addr_type block_addr, mem_fetch *mf) { - m_data[block_addr].m_list.push_back(mf); - assert(m_data.size() <= m_num_entries); - assert(m_data[block_addr].m_list.size() <= m_max_merged); - // indicate that this MSHR entry contains an atomic operation - if (mf->isatomic()) { - m_data[block_addr].m_has_atomic = true; - } +void mshr_table::add( new_addr_type block_addr, mem_fetch *mf ){ + m_data[block_addr].m_list.push_back(mf); + assert( m_data.size() <= m_num_entries ); + assert( m_data[block_addr].m_list.size() <= m_max_merged ); + // indicate that this MSHR entry contains an atomic operation + if ( mf->isatomic() ) { + m_data[block_addr].m_has_atomic = true; + } } /// check is_read_after_write_pending -bool mshr_table::is_read_after_write_pending(new_addr_type block_addr) { - std::list<mem_fetch *> my_list = m_data[block_addr].m_list; - bool write_found = false; - for (std::list<mem_fetch *>::iterator it = my_list.begin(); - it != my_list.end(); ++it) { - if ((*it)->is_write()) // Pending Write Request - write_found = true; - else if (write_found) // Pending Read Request and we found previous Write - return true; - } +bool mshr_table::is_read_after_write_pending( new_addr_type block_addr){ + std::list<mem_fetch*> my_list = m_data[block_addr].m_list; + bool write_found = false; + for (std::list<mem_fetch*>::iterator it=my_list.begin(); it != my_list.end(); ++it) + { + if((*it)->is_write()) //Pending Write Request + write_found = true; + else if(write_found) //Pending Read Request and we found previous Write + return true; + } + + return false; - return false; } /// Accept a new cache fill response: mark entry ready for processing -void mshr_table::mark_ready(new_addr_type block_addr, bool &has_atomic) { - assert(!busy()); - table::iterator a = m_data.find(block_addr); - assert(a != m_data.end()); - m_current_response.push_back(block_addr); - has_atomic = a->second.m_has_atomic; - assert(m_current_response.size() <= m_data.size()); +void mshr_table::mark_ready( new_addr_type block_addr, bool &has_atomic ){ + assert( !busy() ); + table::iterator a = m_data.find(block_addr); + assert( a != m_data.end() ); + m_current_response.push_back( block_addr ); + has_atomic = a->second.m_has_atomic; + assert( m_current_response.size() <= m_data.size() ); } /// Returns next ready access -mem_fetch *mshr_table::next_access() { - assert(access_ready()); - new_addr_type block_addr = m_current_response.front(); - assert(!m_data[block_addr].m_list.empty()); - mem_fetch *result = m_data[block_addr].m_list.front(); - m_data[block_addr].m_list.pop_front(); - if (m_data[block_addr].m_list.empty()) { - // release entry - m_data.erase(block_addr); - m_current_response.pop_front(); - } - return result; +mem_fetch *mshr_table::next_access(){ + assert( access_ready() ); + new_addr_type block_addr = m_current_response.front(); + assert( !m_data[block_addr].m_list.empty() ); + mem_fetch *result = m_data[block_addr].m_list.front(); + m_data[block_addr].m_list.pop_front(); + if ( m_data[block_addr].m_list.empty() ) { + // release entry + m_data.erase(block_addr); + m_current_response.pop_front(); + } + return result; } -void mshr_table::display(FILE *fp) const { - fprintf(fp, "MSHR contents\n"); - for (table::const_iterator e = m_data.begin(); e != m_data.end(); ++e) { - unsigned block_addr = e->first; - fprintf(fp, "MSHR: tag=0x%06x, atomic=%d %zu entries : ", block_addr, - e->second.m_has_atomic, e->second.m_list.size()); - if (!e->second.m_list.empty()) { - mem_fetch *mf = e->second.m_list.front(); - fprintf(fp, "%p :", mf); - mf->print(fp); - } else { - fprintf(fp, " no memory requests???\n"); +void mshr_table::display( FILE *fp ) const{ + fprintf(fp,"MSHR contents\n"); + for ( table::const_iterator e=m_data.begin(); e!=m_data.end(); ++e ) { + unsigned block_addr = e->first; + fprintf(fp,"MSHR: tag=0x%06x, atomic=%d %zu entries : ", block_addr, e->second.m_has_atomic, e->second.m_list.size()); + if ( !e->second.m_list.empty() ) { + mem_fetch *mf = e->second.m_list.front(); + fprintf(fp,"%p :",mf); + mf->print(fp); + } else { + fprintf(fp," no memory requests???\n"); + } } - } } -/***************************************************************** Caches - * *****************************************************************/ -cache_stats::cache_stats() { - m_stats.resize(NUM_MEM_ACCESS_TYPE); - m_stats_pw.resize(NUM_MEM_ACCESS_TYPE); - m_fail_stats.resize(NUM_MEM_ACCESS_TYPE); - for (unsigned i = 0; i < NUM_MEM_ACCESS_TYPE; ++i) { - m_stats[i].resize(NUM_CACHE_REQUEST_STATUS, 0); - m_stats_pw[i].resize(NUM_CACHE_REQUEST_STATUS, 0); - m_fail_stats[i].resize(NUM_CACHE_RESERVATION_FAIL_STATUS, 0); - } - m_cache_port_available_cycles = 0; - m_cache_data_port_busy_cycles = 0; - m_cache_fill_port_busy_cycles = 0; +/***************************************************************** Caches *****************************************************************/ +cache_stats::cache_stats(){ + m_stats.resize(NUM_MEM_ACCESS_TYPE); + m_stats_pw.resize(NUM_MEM_ACCESS_TYPE); + m_fail_stats.resize(NUM_MEM_ACCESS_TYPE); + for(unsigned i=0; i<NUM_MEM_ACCESS_TYPE; ++i){ + m_stats[i].resize(NUM_CACHE_REQUEST_STATUS, 0); + m_stats_pw[i].resize(NUM_CACHE_REQUEST_STATUS, 0); + m_fail_stats[i].resize(NUM_CACHE_RESERVATION_FAIL_STATUS, 0); + } + m_cache_port_available_cycles = 0; + m_cache_data_port_busy_cycles = 0; + m_cache_fill_port_busy_cycles = 0; } -void cache_stats::clear() { - /// - /// Zero out all current cache statistics - /// - for (unsigned i = 0; i < NUM_MEM_ACCESS_TYPE; ++i) { - std::fill(m_stats[i].begin(), m_stats[i].end(), 0); - std::fill(m_fail_stats[i].begin(), m_fail_stats[i].end(), 0); - } - m_cache_port_available_cycles = 0; - m_cache_data_port_busy_cycles = 0; - m_cache_fill_port_busy_cycles = 0; +void cache_stats::clear(){ + /// + /// Zero out all current cache statistics + /// + for(unsigned i=0; i<NUM_MEM_ACCESS_TYPE; ++i){ + std::fill(m_stats[i].begin(), m_stats[i].end(), 0); + std::fill(m_fail_stats[i].begin(), m_fail_stats[i].end(), 0); + } + m_cache_port_available_cycles = 0; + m_cache_data_port_busy_cycles = 0; + m_cache_fill_port_busy_cycles = 0; } -void cache_stats::clear_pw() { - /// - /// Zero out per-window cache statistics - /// - for (unsigned i = 0; i < NUM_MEM_ACCESS_TYPE; ++i) { - std::fill(m_stats_pw[i].begin(), m_stats_pw[i].end(), 0); - } +void cache_stats::clear_pw(){ + /// + /// Zero out per-window cache statistics + /// + for(unsigned i=0; i<NUM_MEM_ACCESS_TYPE; ++i){ + std::fill(m_stats_pw[i].begin(), m_stats_pw[i].end(), 0); + } } -void cache_stats::inc_stats(int access_type, int access_outcome) { - /// - /// Increment the stat corresponding to (access_type, access_outcome) by 1. - /// - if (!check_valid(access_type, access_outcome)) - assert(0 && "Unknown cache access type or access outcome"); +void cache_stats::inc_stats(int access_type, int access_outcome){ + /// + /// Increment the stat corresponding to (access_type, access_outcome) by 1. + /// + if(!check_valid(access_type, access_outcome)) + assert(0 && "Unknown cache access type or access outcome"); - m_stats[access_type][access_outcome]++; + m_stats[access_type][access_outcome]++; } -void cache_stats::inc_stats_pw(int access_type, int access_outcome) { - /// - /// Increment the corresponding per-window cache stat - /// - if (!check_valid(access_type, access_outcome)) - assert(0 && "Unknown cache access type or access outcome"); - m_stats_pw[access_type][access_outcome]++; +void cache_stats::inc_stats_pw(int access_type, int access_outcome){ + /// + /// Increment the corresponding per-window cache stat + /// + if(!check_valid(access_type, access_outcome)) + assert(0 && "Unknown cache access type or access outcome"); + m_stats_pw[access_type][access_outcome]++; } -void cache_stats::inc_fail_stats(int access_type, int fail_outcome) { - if (!check_fail_valid(access_type, fail_outcome)) - assert(0 && "Unknown cache access type or access fail"); +void cache_stats::inc_fail_stats(int access_type, int fail_outcome){ + + if(!check_fail_valid(access_type, fail_outcome)) + assert(0 && "Unknown cache access type or access fail"); - m_fail_stats[access_type][fail_outcome]++; + m_fail_stats[access_type][fail_outcome]++; } -enum cache_request_status cache_stats::select_stats_status( - enum cache_request_status probe, enum cache_request_status access) const { - /// - /// This function selects how the cache access outcome should be counted. - /// HIT_RESERVED is considered as a MISS - /// in the cores, however, it should be counted as a HIT_RESERVED in the - /// caches. - /// - if (probe == HIT_RESERVED && access != RESERVATION_FAIL) - return probe; - else if (probe == SECTOR_MISS && access == MISS) - return probe; - else - return access; + +enum cache_request_status cache_stats::select_stats_status(enum cache_request_status probe, enum cache_request_status access) const { + /// + /// This function selects how the cache access outcome should be counted. HIT_RESERVED is considered as a MISS + /// in the cores, however, it should be counted as a HIT_RESERVED in the caches. + /// + if(probe == HIT_RESERVED && access != RESERVATION_FAIL) + return probe; + else if(probe == SECTOR_MISS && access == MISS) + return probe; + else + return access; } -unsigned long long &cache_stats::operator()(int access_type, int access_outcome, - bool fail_outcome) { - /// - /// Simple method to read/modify the stat corresponding to (access_type, - /// access_outcome) - /// Used overloaded () to avoid the need for separate read/write member - /// functions - /// - if (fail_outcome) { - if (!check_fail_valid(access_type, access_outcome)) - assert(0 && "Unknown cache access type or fail outcome"); +unsigned long long &cache_stats::operator()(int access_type, int access_outcome, bool fail_outcome){ + /// + /// Simple method to read/modify the stat corresponding to (access_type, access_outcome) + /// Used overloaded () to avoid the need for separate read/write member functions + /// + if(fail_outcome) { + if(!check_fail_valid(access_type, access_outcome)) + assert(0 && "Unknown cache access type or fail outcome"); - return m_fail_stats[access_type][access_outcome]; - } else { - if (!check_valid(access_type, access_outcome)) - assert(0 && "Unknown cache access type or access outcome"); + return m_fail_stats[access_type][access_outcome]; + } + else { + if(!check_valid(access_type, access_outcome)) + assert(0 && "Unknown cache access type or access outcome"); - return m_stats[access_type][access_outcome]; - } + return m_stats[access_type][access_outcome]; + } } -unsigned long long cache_stats::operator()(int access_type, int access_outcome, - bool fail_outcome) const { - /// - /// Const accessor into m_stats. - /// - if (fail_outcome) { - if (!check_fail_valid(access_type, access_outcome)) - assert(0 && "Unknown cache access type or fail outcome"); +unsigned long long cache_stats::operator()(int access_type, int access_outcome, bool fail_outcome) const{ + /// + /// Const accessor into m_stats. + /// + if(fail_outcome) { + if(!check_fail_valid(access_type, access_outcome)) + assert(0 && "Unknown cache access type or fail outcome"); - return m_fail_stats[access_type][access_outcome]; - } else { - if (!check_valid(access_type, access_outcome)) - assert(0 && "Unknown cache access type or access outcome"); + return m_fail_stats[access_type][access_outcome]; + } + else { + if(!check_valid(access_type, access_outcome)) + assert(0 && "Unknown cache access type or access outcome"); - return m_stats[access_type][access_outcome]; - } + return m_stats[access_type][access_outcome]; + } } -cache_stats cache_stats::operator+(const cache_stats &cs) { - /// - /// Overloaded + operator to allow for simple stat accumulation - /// - cache_stats ret; - for (unsigned type = 0; type < NUM_MEM_ACCESS_TYPE; ++type) { - for (unsigned status = 0; status < NUM_CACHE_REQUEST_STATUS; ++status) { - ret(type, status, false) = - m_stats[type][status] + cs(type, status, false); - } - for (unsigned status = 0; status < NUM_CACHE_RESERVATION_FAIL_STATUS; - ++status) { - ret(type, status, true) = - m_fail_stats[type][status] + cs(type, status, true); - } - } - ret.m_cache_port_available_cycles = - m_cache_port_available_cycles + cs.m_cache_port_available_cycles; - ret.m_cache_data_port_busy_cycles = - m_cache_data_port_busy_cycles + cs.m_cache_data_port_busy_cycles; - ret.m_cache_fill_port_busy_cycles = - m_cache_fill_port_busy_cycles + cs.m_cache_fill_port_busy_cycles; - return ret; +cache_stats cache_stats::operator+(const cache_stats &cs){ + /// + /// Overloaded + operator to allow for simple stat accumulation + /// + cache_stats ret; + for(unsigned type=0; type<NUM_MEM_ACCESS_TYPE; ++type){ + for(unsigned status=0; status<NUM_CACHE_REQUEST_STATUS; ++status){ + ret(type, status, false) = m_stats[type][status] + cs(type, status, false); + } + for(unsigned status=0; status<NUM_CACHE_RESERVATION_FAIL_STATUS; ++status){ + ret(type, status, true) = m_fail_stats[type][status] + cs(type, status, true); + } + } + ret.m_cache_port_available_cycles = m_cache_port_available_cycles + cs.m_cache_port_available_cycles; + ret.m_cache_data_port_busy_cycles = m_cache_data_port_busy_cycles + cs.m_cache_data_port_busy_cycles; + ret.m_cache_fill_port_busy_cycles = m_cache_fill_port_busy_cycles + cs.m_cache_fill_port_busy_cycles; + return ret; } -cache_stats &cache_stats::operator+=(const cache_stats &cs) { - /// - /// Overloaded += operator to allow for simple stat accumulation - /// - for (unsigned type = 0; type < NUM_MEM_ACCESS_TYPE; ++type) { - for (unsigned status = 0; status < NUM_CACHE_REQUEST_STATUS; ++status) { - m_stats[type][status] += cs(type, status, false); - } - for (unsigned status = 0; status < NUM_CACHE_REQUEST_STATUS; ++status) { - m_stats_pw[type][status] += cs(type, status, false); - } - for (unsigned status = 0; status < NUM_CACHE_RESERVATION_FAIL_STATUS; - ++status) { - m_fail_stats[type][status] += cs(type, status, true); +cache_stats &cache_stats::operator+=(const cache_stats &cs){ + /// + /// Overloaded += operator to allow for simple stat accumulation + /// + for(unsigned type=0; type<NUM_MEM_ACCESS_TYPE; ++type){ + for(unsigned status=0; status<NUM_CACHE_REQUEST_STATUS; ++status){ + m_stats[type][status] += cs(type, status, false); + } + for(unsigned status=0; status<NUM_CACHE_REQUEST_STATUS; ++status){ + m_stats_pw[type][status] += cs(type, status, false); + } + for(unsigned status=0; status<NUM_CACHE_RESERVATION_FAIL_STATUS; ++status){ + m_fail_stats[type][status] += cs(type, status, true); + } } - } - m_cache_port_available_cycles += cs.m_cache_port_available_cycles; - m_cache_data_port_busy_cycles += cs.m_cache_data_port_busy_cycles; - m_cache_fill_port_busy_cycles += cs.m_cache_fill_port_busy_cycles; - return *this; + m_cache_port_available_cycles += cs.m_cache_port_available_cycles; + m_cache_data_port_busy_cycles += cs.m_cache_data_port_busy_cycles; + m_cache_fill_port_busy_cycles += cs.m_cache_fill_port_busy_cycles; + return *this; } -void cache_stats::print_stats(FILE *fout, const char *cache_name) const { - /// - /// Print out each non-zero cache statistic for every memory access type and - /// status - /// "cache_name" defaults to "Cache_stats" when no argument is provided, - /// otherwise - /// the provided name is used. - /// The printed format is "<cache_name>[<request_type>][<request_status>] = - /// <stat_value>" - /// - std::vector<unsigned> total_access; - total_access.resize(NUM_MEM_ACCESS_TYPE, 0); - std::string m_cache_name = cache_name; - for (unsigned type = 0; type < NUM_MEM_ACCESS_TYPE; ++type) { - for (unsigned status = 0; status < NUM_CACHE_REQUEST_STATUS; ++status) { - fprintf(fout, "\t%s[%s][%s] = %llu\n", m_cache_name.c_str(), - mem_access_type_str((enum mem_access_type)type), - cache_request_status_str((enum cache_request_status)status), - m_stats[type][status]); +void cache_stats::print_stats(FILE *fout, const char *cache_name) const{ + /// + /// Print out each non-zero cache statistic for every memory access type and status + /// "cache_name" defaults to "Cache_stats" when no argument is provided, otherwise + /// the provided name is used. + /// The printed format is "<cache_name>[<request_type>][<request_status>] = <stat_value>" + /// + std::vector< unsigned > total_access; + total_access.resize(NUM_MEM_ACCESS_TYPE, 0); + std::string m_cache_name = cache_name; + for (unsigned type = 0; type < NUM_MEM_ACCESS_TYPE; ++type) { + for (unsigned status = 0; status < NUM_CACHE_REQUEST_STATUS; ++status) { + fprintf(fout, "\t%s[%s][%s] = %llu\n", + m_cache_name.c_str(), + mem_access_type_str((enum mem_access_type)type), + cache_request_status_str((enum cache_request_status)status), + m_stats[type][status]); - if (status != RESERVATION_FAIL) - total_access[type] += m_stats[type][status]; + if(status != RESERVATION_FAIL) + total_access[type]+= m_stats[type][status]; + } + } + for (unsigned type = 0; type < NUM_MEM_ACCESS_TYPE; ++type) { + if(total_access[type] > 0) + fprintf(fout, "\t%s[%s][%s] = %u\n", + m_cache_name.c_str(), + mem_access_type_str((enum mem_access_type)type), + "TOTAL_ACCESS", + total_access[type]); } - } - for (unsigned type = 0; type < NUM_MEM_ACCESS_TYPE; ++type) { - if (total_access[type] > 0) - fprintf(fout, "\t%s[%s][%s] = %u\n", m_cache_name.c_str(), - mem_access_type_str((enum mem_access_type)type), "TOTAL_ACCESS", - total_access[type]); - } } -void cache_stats::print_fail_stats(FILE *fout, const char *cache_name) const { - std::string m_cache_name = cache_name; - for (unsigned type = 0; type < NUM_MEM_ACCESS_TYPE; ++type) { - for (unsigned fail = 0; fail < NUM_CACHE_RESERVATION_FAIL_STATUS; ++fail) { - if (m_fail_stats[type][fail] > 0) { - fprintf(fout, "\t%s[%s][%s] = %llu\n", m_cache_name.c_str(), - mem_access_type_str((enum mem_access_type)type), - cache_fail_status_str((enum cache_reservation_fail_reason)fail), - m_fail_stats[type][fail]); - } - } - } +void cache_stats::print_fail_stats(FILE *fout, const char *cache_name) const{ + std::string m_cache_name = cache_name; + for (unsigned type = 0; type < NUM_MEM_ACCESS_TYPE; ++type) { + for (unsigned fail = 0; fail < NUM_CACHE_RESERVATION_FAIL_STATUS; ++fail) { + if(m_fail_stats[type][fail] > 0){ + fprintf(fout, "\t%s[%s][%s] = %llu\n", + m_cache_name.c_str(), + mem_access_type_str((enum mem_access_type)type), + cache_fail_status_str((enum cache_reservation_fail_reason)fail), + m_fail_stats[type][fail]); + } + } + } } -void cache_sub_stats::print_port_stats(FILE *fout, - const char *cache_name) const { - float data_port_util = 0.0f; - if (port_available_cycles > 0) { - data_port_util = (float)data_port_busy_cycles / port_available_cycles; - } - fprintf(fout, "%s_data_port_util = %.3f\n", cache_name, data_port_util); - float fill_port_util = 0.0f; - if (port_available_cycles > 0) { - fill_port_util = (float)fill_port_busy_cycles / port_available_cycles; - } - fprintf(fout, "%s_fill_port_util = %.3f\n", cache_name, fill_port_util); +void cache_sub_stats::print_port_stats(FILE *fout, const char *cache_name) const +{ + float data_port_util = 0.0f; + if (port_available_cycles > 0) { + data_port_util = (float) data_port_busy_cycles / port_available_cycles; + } + fprintf(fout, "%s_data_port_util = %.3f\n", cache_name, data_port_util); + float fill_port_util = 0.0f; + if (port_available_cycles > 0) { + fill_port_util = (float) fill_port_busy_cycles / port_available_cycles; + } + fprintf(fout, "%s_fill_port_util = %.3f\n", cache_name, fill_port_util); } -unsigned long long cache_stats::get_stats( - enum mem_access_type *access_type, unsigned num_access_type, - enum cache_request_status *access_status, - unsigned num_access_status) const { - /// - /// Returns a sum of the stats corresponding to each "access_type" and - /// "access_status" pair. - /// "access_type" is an array of "num_access_type" mem_access_types. - /// "access_status" is an array of "num_access_status" cache_request_statuses. - /// - unsigned long long total = 0; - for (unsigned type = 0; type < num_access_type; ++type) { - for (unsigned status = 0; status < num_access_status; ++status) { - if (!check_valid((int)access_type[type], (int)access_status[status])) - assert(0 && "Unknown cache access type or access outcome"); - total += m_stats[access_type[type]][access_status[status]]; +unsigned long long cache_stats::get_stats(enum mem_access_type *access_type, unsigned num_access_type, enum cache_request_status *access_status, unsigned num_access_status) const{ + /// + /// Returns a sum of the stats corresponding to each "access_type" and "access_status" pair. + /// "access_type" is an array of "num_access_type" mem_access_types. + /// "access_status" is an array of "num_access_status" cache_request_statuses. + /// + unsigned long long total=0; + for(unsigned type =0; type < num_access_type; ++type){ + for(unsigned status=0; status < num_access_status; ++status){ + if(!check_valid((int)access_type[type], (int)access_status[status])) + assert(0 && "Unknown cache access type or access outcome"); + total += m_stats[access_type[type]][access_status[status]]; + } } - } - return total; + return total; } -void cache_stats::get_sub_stats(struct cache_sub_stats &css) const { - /// - /// Overwrites "css" with the appropriate statistics from this cache. - /// - struct cache_sub_stats t_css; - t_css.clear(); +void cache_stats::get_sub_stats(struct cache_sub_stats &css) const{ + /// + /// Overwrites "css" with the appropriate statistics from this cache. + /// + struct cache_sub_stats t_css; + t_css.clear(); - for (unsigned type = 0; type < NUM_MEM_ACCESS_TYPE; ++type) { - for (unsigned status = 0; status < NUM_CACHE_REQUEST_STATUS; ++status) { - if (status == HIT || status == MISS || status == SECTOR_MISS || - status == HIT_RESERVED) - t_css.accesses += m_stats[type][status]; + for (unsigned type = 0; type < NUM_MEM_ACCESS_TYPE; ++type) { + for (unsigned status = 0; status < NUM_CACHE_REQUEST_STATUS; ++status) { + if(status == HIT || status == MISS || status == SECTOR_MISS || status == HIT_RESERVED) + t_css.accesses += m_stats[type][status]; - if (status == MISS || status == SECTOR_MISS) - t_css.misses += m_stats[type][status]; + if(status == MISS || status == SECTOR_MISS) + t_css.misses += m_stats[type][status]; - if (status == HIT_RESERVED) t_css.pending_hits += m_stats[type][status]; + if(status == HIT_RESERVED) + t_css.pending_hits += m_stats[type][status]; - if (status == RESERVATION_FAIL) t_css.res_fails += m_stats[type][status]; + if(status == RESERVATION_FAIL) + t_css.res_fails += m_stats[type][status]; + } } - } - t_css.port_available_cycles = m_cache_port_available_cycles; - t_css.data_port_busy_cycles = m_cache_data_port_busy_cycles; - t_css.fill_port_busy_cycles = m_cache_fill_port_busy_cycles; + t_css.port_available_cycles = m_cache_port_available_cycles; + t_css.data_port_busy_cycles = m_cache_data_port_busy_cycles; + t_css.fill_port_busy_cycles = m_cache_fill_port_busy_cycles; - css = t_css; + css = t_css; } -void cache_stats::get_sub_stats_pw(struct cache_sub_stats_pw &css) const { - /// - /// Overwrites "css" with the appropriate statistics from this cache. - /// - struct cache_sub_stats_pw t_css; - t_css.clear(); +void cache_stats::get_sub_stats_pw(struct cache_sub_stats_pw &css) const{ + /// + /// Overwrites "css" with the appropriate statistics from this cache. + /// + struct cache_sub_stats_pw t_css; + t_css.clear(); - for (unsigned type = 0; type < NUM_MEM_ACCESS_TYPE; ++type) { - for (unsigned status = 0; status < NUM_CACHE_REQUEST_STATUS; ++status) { - if (status == HIT || status == MISS || status == SECTOR_MISS || - status == HIT_RESERVED) - t_css.accesses += m_stats_pw[type][status]; + for (unsigned type = 0; type < NUM_MEM_ACCESS_TYPE; ++type) { + for (unsigned status = 0; status < NUM_CACHE_REQUEST_STATUS; ++status) { + if(status == HIT || status == MISS || status == SECTOR_MISS || status == HIT_RESERVED) + t_css.accesses += m_stats_pw[type][status]; - if (status == HIT) { - if (type == GLOBAL_ACC_R || type == CONST_ACC_R || type == INST_ACC_R) { - t_css.read_hits += m_stats_pw[type][status]; - } else if (type == GLOBAL_ACC_W) { - t_css.write_hits += m_stats_pw[type][status]; - } - } + if(status == HIT){ + if(type == GLOBAL_ACC_R || type == CONST_ACC_R || type == INST_ACC_R){ + t_css.read_hits += m_stats_pw[type][status]; + } else if(type == GLOBAL_ACC_W){ + t_css.write_hits += m_stats_pw[type][status]; + } + } - if (status == MISS || status == SECTOR_MISS) { - if (type == GLOBAL_ACC_R || type == CONST_ACC_R || type == INST_ACC_R) { - t_css.read_misses += m_stats_pw[type][status]; - } else if (type == GLOBAL_ACC_W) { - t_css.write_misses += m_stats_pw[type][status]; - } - } + if(status == MISS || status == SECTOR_MISS){ + if(type == GLOBAL_ACC_R || type == CONST_ACC_R || type == INST_ACC_R){ + t_css.read_misses += m_stats_pw[type][status]; + } else if(type == GLOBAL_ACC_W){ + t_css.write_misses += m_stats_pw[type][status]; + } + } - if (status == HIT_RESERVED) { - if (type == GLOBAL_ACC_R || type == CONST_ACC_R || type == INST_ACC_R) { - t_css.read_pending_hits += m_stats_pw[type][status]; - } else if (type == GLOBAL_ACC_W) { - t_css.write_pending_hits += m_stats_pw[type][status]; - } - } + if(status == HIT_RESERVED){ + if(type == GLOBAL_ACC_R || type == CONST_ACC_R || type == INST_ACC_R){ + t_css.read_pending_hits += m_stats_pw[type][status]; + } else if(type == GLOBAL_ACC_W){ + t_css.write_pending_hits += m_stats_pw[type][status]; + } + } - if (status == RESERVATION_FAIL) { - if (type == GLOBAL_ACC_R || type == CONST_ACC_R || type == INST_ACC_R) { - t_css.read_res_fails += m_stats_pw[type][status]; - } else if (type == GLOBAL_ACC_W) { - t_css.write_res_fails += m_stats_pw[type][status]; + if(status == RESERVATION_FAIL){ + if(type == GLOBAL_ACC_R || type == CONST_ACC_R || type == INST_ACC_R){ + t_css.read_res_fails += m_stats_pw[type][status]; + } else if(type == GLOBAL_ACC_W){ + t_css.write_res_fails += m_stats_pw[type][status]; + } + } } - } } - } - css = t_css; + css = t_css; } -bool cache_stats::check_valid(int type, int status) const { - /// - /// Verify a valid access_type/access_status - /// - if ((type >= 0) && (type < NUM_MEM_ACCESS_TYPE) && (status >= 0) && - (status < NUM_CACHE_REQUEST_STATUS)) - return true; - else - return false; +bool cache_stats::check_valid(int type, int status) const{ + /// + /// Verify a valid access_type/access_status + /// + if((type >= 0) && (type < NUM_MEM_ACCESS_TYPE) && (status >= 0) && (status < NUM_CACHE_REQUEST_STATUS)) + return true; + else + return false; } -bool cache_stats::check_fail_valid(int type, int fail) const { - /// - /// Verify a valid access_type/access_status - /// - if ((type >= 0) && (type < NUM_MEM_ACCESS_TYPE) && (fail >= 0) && - (fail < NUM_CACHE_RESERVATION_FAIL_STATUS)) - return true; - else - return false; +bool cache_stats::check_fail_valid(int type, int fail) const{ + /// + /// Verify a valid access_type/access_status + /// + if((type >= 0) && (type < NUM_MEM_ACCESS_TYPE) && (fail >= 0) && (fail < NUM_CACHE_RESERVATION_FAIL_STATUS)) + return true; + else + return false; } -void cache_stats::sample_cache_port_utility(bool data_port_busy, - bool fill_port_busy) { - m_cache_port_available_cycles += 1; - if (data_port_busy) { - m_cache_data_port_busy_cycles += 1; - } - if (fill_port_busy) { - m_cache_fill_port_busy_cycles += 1; - } +void cache_stats::sample_cache_port_utility(bool data_port_busy, bool fill_port_busy) +{ + m_cache_port_available_cycles += 1; + if (data_port_busy) { + m_cache_data_port_busy_cycles += 1; + } + if (fill_port_busy) { + m_cache_fill_port_busy_cycles += 1; + } } -baseline_cache::bandwidth_management::bandwidth_management(cache_config &config) - : m_config(config) { - m_data_port_occupied_cycles = 0; - m_fill_port_occupied_cycles = 0; +baseline_cache::bandwidth_management::bandwidth_management(cache_config &config) +: m_config(config) +{ + m_data_port_occupied_cycles = 0; + m_fill_port_occupied_cycles = 0; } -/// use the data port based on the outcome and events generated by the mem_fetch -/// request -void baseline_cache::bandwidth_management::use_data_port( - mem_fetch *mf, enum cache_request_status outcome, - const std::list<cache_event> &events) { - unsigned data_size = mf->get_data_size(); - unsigned port_width = m_config.m_data_port_width; - switch (outcome) { +/// use the data port based on the outcome and events generated by the mem_fetch request +void baseline_cache::bandwidth_management::use_data_port(mem_fetch *mf, enum cache_request_status outcome, const std::list<cache_event> &events) +{ + unsigned data_size = mf->get_data_size(); + unsigned port_width = m_config.m_data_port_width; + switch (outcome) { case HIT: { - unsigned data_cycles = - data_size / port_width + ((data_size % port_width > 0) ? 1 : 0); - m_data_port_occupied_cycles += data_cycles; - } break; + unsigned data_cycles = data_size / port_width + ((data_size % port_width > 0)? 1 : 0); + m_data_port_occupied_cycles += data_cycles; + } break; case HIT_RESERVED: case MISS: { - // the data array is accessed to read out the entire line for write-back - // in case of sector cache we need to write bank only the modified sectors - cache_event ev(WRITE_BACK_REQUEST_SENT); - if (was_writeback_sent(events, ev)) { - unsigned data_cycles = ev.m_evicted_block.m_modified_size / port_width; - m_data_port_occupied_cycles += data_cycles; - } - } break; + // the data array is accessed to read out the entire line for write-back + // in case of sector cache we need to write bank only the modified sectors + cache_event ev(WRITE_BACK_REQUEST_SENT); + if (was_writeback_sent(events, ev)) { + unsigned data_cycles = ev.m_evicted_block.m_modified_size / port_width; + m_data_port_occupied_cycles += data_cycles; + } + } break; case SECTOR_MISS: case RESERVATION_FAIL: - // Does not consume any port bandwidth - break; - default: - assert(0); - break; - } + // Does not consume any port bandwidth + break; + default: + assert(0); + break; + } } -/// use the fill port -void baseline_cache::bandwidth_management::use_fill_port(mem_fetch *mf) { - // assume filling the entire line with the returned request - unsigned fill_cycles = m_config.get_atom_sz() / m_config.m_data_port_width; - m_fill_port_occupied_cycles += fill_cycles; +/// use the fill port +void baseline_cache::bandwidth_management::use_fill_port(mem_fetch *mf) +{ + // assume filling the entire line with the returned request + unsigned fill_cycles = m_config.get_atom_sz() / m_config.m_data_port_width; + m_fill_port_occupied_cycles += fill_cycles; } -/// called every cache cycle to free up the ports -void baseline_cache::bandwidth_management::replenish_port_bandwidth() { - if (m_data_port_occupied_cycles > 0) { - m_data_port_occupied_cycles -= 1; - } - assert(m_data_port_occupied_cycles >= 0); +/// called every cache cycle to free up the ports +void baseline_cache::bandwidth_management::replenish_port_bandwidth() +{ + if (m_data_port_occupied_cycles > 0) { + m_data_port_occupied_cycles -= 1; + } + assert(m_data_port_occupied_cycles >= 0); - if (m_fill_port_occupied_cycles > 0) { - m_fill_port_occupied_cycles -= 1; - } - assert(m_fill_port_occupied_cycles >= 0); + if (m_fill_port_occupied_cycles > 0) { + m_fill_port_occupied_cycles -= 1; + } + assert(m_fill_port_occupied_cycles >= 0); } -/// query for data port availability -bool baseline_cache::bandwidth_management::data_port_free() const { - return (m_data_port_occupied_cycles == 0); +/// query for data port availability +bool baseline_cache::bandwidth_management::data_port_free() const +{ + return (m_data_port_occupied_cycles == 0); } -/// query for fill port availability -bool baseline_cache::bandwidth_management::fill_port_free() const { - return (m_fill_port_occupied_cycles == 0); +/// query for fill port availability +bool baseline_cache::bandwidth_management::fill_port_free() const +{ + return (m_fill_port_occupied_cycles == 0); } /// Sends next request to lower level of memory -void baseline_cache::cycle() { - if (!m_miss_queue.empty()) { - mem_fetch *mf = m_miss_queue.front(); - if (!m_memport->full(mf->size(), mf->get_is_write())) { - m_miss_queue.pop_front(); - m_memport->push(mf); +void baseline_cache::cycle(){ + if ( !m_miss_queue.empty() ) { + mem_fetch *mf = m_miss_queue.front(); + if ( !m_memport->full(mf->size(),mf->get_is_write()) ) { + m_miss_queue.pop_front(); + m_memport->push(mf); + } } - } - bool data_port_busy = !m_bandwidth_management.data_port_free(); - bool fill_port_busy = !m_bandwidth_management.fill_port_free(); - m_stats.sample_cache_port_utility(data_port_busy, fill_port_busy); - m_bandwidth_management.replenish_port_bandwidth(); + bool data_port_busy = !m_bandwidth_management.data_port_free(); + bool fill_port_busy = !m_bandwidth_management.fill_port_free(); + m_stats.sample_cache_port_utility(data_port_busy, fill_port_busy); + m_bandwidth_management.replenish_port_bandwidth(); } -/// Interface for response from lower memory level (model bandwidth restictions -/// in caller) -void baseline_cache::fill(mem_fetch *mf, unsigned time) { - if (m_config.m_mshr_type == SECTOR_ASSOC) { - assert(mf->get_original_mf()); - extra_mf_fields_lookup::iterator e = - m_extra_mf_fields.find(mf->get_original_mf()); - assert(e != m_extra_mf_fields.end()); +/// Interface for response from lower memory level (model bandwidth restictions in caller) +void baseline_cache::fill(mem_fetch *mf, unsigned time){ + + if(m_config.m_mshr_type == SECTOR_ASSOC) { + assert(mf->get_original_mf()); + extra_mf_fields_lookup::iterator e = m_extra_mf_fields.find(mf->get_original_mf()); + assert( e != m_extra_mf_fields.end() ); e->second.pending_read--; - if (e->second.pending_read > 0) { - // wait for the other requests to come back - delete mf; - return; - } else { - mem_fetch *temp = mf; - mf = mf->get_original_mf(); - delete temp; - } - } + if(e->second.pending_read > 0) { + //wait for the other requests to come back + delete mf; + return; + } else { + mem_fetch *temp = mf; + mf = mf->get_original_mf(); + delete temp; + } + } - extra_mf_fields_lookup::iterator e = m_extra_mf_fields.find(mf); - assert(e != m_extra_mf_fields.end()); - assert(e->second.m_valid); - mf->set_data_size(e->second.m_data_size); - mf->set_addr(e->second.m_addr); - if (m_config.m_alloc_policy == ON_MISS) - m_tag_array->fill(e->second.m_cache_index, time, mf); - else if (m_config.m_alloc_policy == ON_FILL) { - m_tag_array->fill(e->second.m_block_addr, time, mf); - if (m_config.is_streaming()) m_tag_array->remove_pending_line(mf); - } else - abort(); - bool has_atomic = false; - m_mshrs.mark_ready(e->second.m_block_addr, has_atomic); - if (has_atomic) { - assert(m_config.m_alloc_policy == ON_MISS); - cache_block_t *block = m_tag_array->get_block(e->second.m_cache_index); - block->set_status(MODIFIED, mf->get_access_sector_mask()); // mark line as - // dirty for - // atomic - // operation - } - m_extra_mf_fields.erase(mf); - m_bandwidth_management.use_fill_port(mf); + extra_mf_fields_lookup::iterator e = m_extra_mf_fields.find(mf); + assert( e != m_extra_mf_fields.end() ); + assert( e->second.m_valid ); + mf->set_data_size( e->second.m_data_size ); + mf->set_addr( e->second.m_addr ); + if ( m_config.m_alloc_policy == ON_MISS ) + m_tag_array->fill(e->second.m_cache_index,time,mf); + else if ( m_config.m_alloc_policy == ON_FILL ) { + m_tag_array->fill(e->second.m_block_addr,time,mf); + if(m_config.is_streaming()) + m_tag_array->remove_pending_line(mf); + } + else abort(); + bool has_atomic = false; + m_mshrs.mark_ready(e->second.m_block_addr, has_atomic); + if (has_atomic) { + assert(m_config.m_alloc_policy == ON_MISS); + cache_block_t* block = m_tag_array->get_block(e->second.m_cache_index); + block->set_status(MODIFIED, mf->get_access_sector_mask()); // mark line as dirty for atomic operation + } + m_extra_mf_fields.erase(mf); + m_bandwidth_management.use_fill_port(mf); } /// Checks if mf is waiting to be filled by lower memory level -bool baseline_cache::waiting_for_fill(mem_fetch *mf) { - extra_mf_fields_lookup::iterator e = m_extra_mf_fields.find(mf); - return e != m_extra_mf_fields.end(); +bool baseline_cache::waiting_for_fill( mem_fetch *mf ){ + extra_mf_fields_lookup::iterator e = m_extra_mf_fields.find(mf); + return e != m_extra_mf_fields.end(); } -void baseline_cache::print(FILE *fp, unsigned &accesses, - unsigned &misses) const { - fprintf(fp, "Cache %s:\t", m_name.c_str()); - m_tag_array->print(fp, accesses, misses); +void baseline_cache::print(FILE *fp, unsigned &accesses, unsigned &misses) const{ + fprintf( fp, "Cache %s:\t", m_name.c_str() ); + m_tag_array->print(fp,accesses,misses); } -void baseline_cache::display_state(FILE *fp) const { - fprintf(fp, "Cache %s:\n", m_name.c_str()); - m_mshrs.display(fp); - fprintf(fp, "\n"); +void baseline_cache::display_state( FILE *fp ) const{ + fprintf(fp,"Cache %s:\n", m_name.c_str() ); + m_mshrs.display(fp); + fprintf(fp,"\n"); } /// Read miss handler without writeback -void baseline_cache::send_read_request(new_addr_type addr, - new_addr_type block_addr, - unsigned cache_index, mem_fetch *mf, - unsigned time, bool &do_miss, - std::list<cache_event> &events, - bool read_only, bool wa) { - bool wb = false; - evicted_block_info e; - send_read_request(addr, block_addr, cache_index, mf, time, do_miss, wb, e, - events, read_only, wa); +void baseline_cache::send_read_request(new_addr_type addr, new_addr_type block_addr, unsigned cache_index, mem_fetch *mf, + unsigned time, bool &do_miss, std::list<cache_event> &events, bool read_only, bool wa){ + + bool wb=false; + evicted_block_info e; + send_read_request(addr, block_addr, cache_index, mf, time, do_miss, wb, e, events, read_only, wa); } /// Read miss handler. Check MSHR hit or MSHR available -void baseline_cache::send_read_request(new_addr_type addr, - new_addr_type block_addr, - unsigned cache_index, mem_fetch *mf, - unsigned time, bool &do_miss, bool &wb, - evicted_block_info &evicted, - std::list<cache_event> &events, - bool read_only, bool wa) { - new_addr_type mshr_addr = m_config.mshr_addr(mf->get_addr()); - bool mshr_hit = m_mshrs.probe(mshr_addr); - bool mshr_avail = !m_mshrs.full(mshr_addr); - if (mshr_hit && mshr_avail) { - if (read_only) - m_tag_array->access(block_addr, time, cache_index, mf); - else - m_tag_array->access(block_addr, time, cache_index, wb, evicted, mf); +void baseline_cache::send_read_request(new_addr_type addr, new_addr_type block_addr, unsigned cache_index, mem_fetch *mf, + unsigned time, bool &do_miss, bool &wb, evicted_block_info &evicted, std::list<cache_event> &events, bool read_only, bool wa){ - m_mshrs.add(mshr_addr, mf); - do_miss = true; + new_addr_type mshr_addr = m_config.mshr_addr(mf->get_addr()); + bool mshr_hit = m_mshrs.probe(mshr_addr); + bool mshr_avail = !m_mshrs.full(mshr_addr); + if ( mshr_hit && mshr_avail ) { + if(read_only) + m_tag_array->access(block_addr,time,cache_index,mf); + else + m_tag_array->access(block_addr,time,cache_index,wb,evicted,mf); - } else if (!mshr_hit && mshr_avail && - (m_miss_queue.size() < m_config.m_miss_queue_size)) { - if (read_only) - m_tag_array->access(block_addr, time, cache_index, mf); - else - m_tag_array->access(block_addr, time, cache_index, wb, evicted, mf); + m_mshrs.add(mshr_addr,mf); + do_miss = true; - m_mshrs.add(mshr_addr, mf); - if (m_config.is_streaming() && m_config.m_cache_type == SECTOR) { - m_tag_array->add_pending_line(mf); - } - m_extra_mf_fields[mf] = extra_mf_fields( - mshr_addr, mf->get_addr(), cache_index, mf->get_data_size(), m_config); - mf->set_data_size(m_config.get_atom_sz()); - mf->set_addr(mshr_addr); - m_miss_queue.push_back(mf); - mf->set_status(m_miss_queue_status, time); - if (!wa) events.push_back(cache_event(READ_REQUEST_SENT)); + } else if ( !mshr_hit && mshr_avail && (m_miss_queue.size() < m_config.m_miss_queue_size) ) { + if(read_only) + m_tag_array->access(block_addr,time,cache_index,mf); + else + m_tag_array->access(block_addr,time,cache_index,wb,evicted,mf); + + m_mshrs.add(mshr_addr,mf); + if(m_config.is_streaming() && m_config.m_cache_type == SECTOR){ + m_tag_array->add_pending_line(mf); + } + m_extra_mf_fields[mf] = extra_mf_fields(mshr_addr,mf->get_addr(),cache_index, mf->get_data_size(), m_config); + mf->set_data_size( m_config.get_atom_sz() ); + mf->set_addr( mshr_addr ); + m_miss_queue.push_back(mf); + mf->set_status(m_miss_queue_status,time); + if(!wa) + events.push_back(cache_event(READ_REQUEST_SENT)); - do_miss = true; - } else if (mshr_hit && !mshr_avail) - m_stats.inc_fail_stats(mf->get_access_type(), MSHR_MERGE_ENRTY_FAIL); - else if (!mshr_hit && !mshr_avail) - m_stats.inc_fail_stats(mf->get_access_type(), MSHR_ENRTY_FAIL); - else - assert(0); + do_miss = true; + } + else if(mshr_hit && !mshr_avail) + m_stats.inc_fail_stats(mf->get_access_type(), MSHR_MERGE_ENRTY_FAIL); + else if (!mshr_hit && !mshr_avail) + m_stats.inc_fail_stats(mf->get_access_type(), MSHR_ENRTY_FAIL); + else + assert(0); } + /// Sends write request to lower level memory (write or writeback) -void data_cache::send_write_request(mem_fetch *mf, cache_event request, - unsigned time, - std::list<cache_event> &events) { - events.push_back(request); - m_miss_queue.push_back(mf); - mf->set_status(m_miss_queue_status, time); +void data_cache::send_write_request(mem_fetch *mf, cache_event request, unsigned time, std::list<cache_event> &events){ + + events.push_back(request); + m_miss_queue.push_back(mf); + mf->set_status(m_miss_queue_status,time); } + /****** Write-hit functions (Set by config file) ******/ /// Write-back hit: Mark block as modified -cache_request_status data_cache::wr_hit_wb(new_addr_type addr, - unsigned cache_index, mem_fetch *mf, - unsigned time, - std::list<cache_event> &events, - enum cache_request_status status) { - new_addr_type block_addr = m_config.block_addr(addr); - m_tag_array->access(block_addr, time, cache_index, mf); // update LRU state - cache_block_t *block = m_tag_array->get_block(cache_index); - block->set_status(MODIFIED, mf->get_access_sector_mask()); +cache_request_status data_cache::wr_hit_wb(new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, std::list<cache_event> &events, enum cache_request_status status ){ + new_addr_type block_addr = m_config.block_addr(addr); + m_tag_array->access(block_addr,time,cache_index,mf); // update LRU state + cache_block_t* block = m_tag_array->get_block(cache_index); + block->set_status(MODIFIED, mf->get_access_sector_mask()); - return HIT; + return HIT; } /// Write-through hit: Directly send request to lower level memory -cache_request_status data_cache::wr_hit_wt(new_addr_type addr, - unsigned cache_index, mem_fetch *mf, - unsigned time, - std::list<cache_event> &events, - enum cache_request_status status) { - if (miss_queue_full(0)) { - m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); - return RESERVATION_FAIL; // cannot handle request this cycle - } +cache_request_status data_cache::wr_hit_wt(new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, std::list<cache_event> &events, enum cache_request_status status ){ + if(miss_queue_full(0)) { + m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); + return RESERVATION_FAIL; // cannot handle request this cycle + } - new_addr_type block_addr = m_config.block_addr(addr); - m_tag_array->access(block_addr, time, cache_index, mf); // update LRU state - cache_block_t *block = m_tag_array->get_block(cache_index); - block->set_status(MODIFIED, mf->get_access_sector_mask()); + new_addr_type block_addr = m_config.block_addr(addr); + m_tag_array->access(block_addr,time,cache_index,mf); // update LRU state + cache_block_t* block = m_tag_array->get_block(cache_index); + block->set_status(MODIFIED, mf->get_access_sector_mask()); - // generate a write-through - send_write_request(mf, cache_event(WRITE_REQUEST_SENT), time, events); + // generate a write-through + send_write_request(mf, cache_event(WRITE_REQUEST_SENT), time, events); - return HIT; + return HIT; } -/// Write-evict hit: Send request to lower level memory and invalidate -/// corresponding block -cache_request_status data_cache::wr_hit_we(new_addr_type addr, - unsigned cache_index, mem_fetch *mf, - unsigned time, - std::list<cache_event> &events, - enum cache_request_status status) { - if (miss_queue_full(0)) { - m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); - return RESERVATION_FAIL; // cannot handle request this cycle - } +/// Write-evict hit: Send request to lower level memory and invalidate corresponding block +cache_request_status data_cache::wr_hit_we(new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, std::list<cache_event> &events, enum cache_request_status status ){ + if(miss_queue_full(0)) { + m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); + return RESERVATION_FAIL; // cannot handle request this cycle + } - // generate a write-through/evict - cache_block_t *block = m_tag_array->get_block(cache_index); - send_write_request(mf, cache_event(WRITE_REQUEST_SENT), time, events); + // generate a write-through/evict + cache_block_t* block = m_tag_array->get_block(cache_index); + send_write_request(mf, cache_event(WRITE_REQUEST_SENT), time, events); - // Invalidate block - block->set_status(INVALID, mf->get_access_sector_mask()); + // Invalidate block + block->set_status(INVALID, mf->get_access_sector_mask()); - return HIT; + return HIT; } /// Global write-evict, local write-back: Useful for private caches -enum cache_request_status data_cache::wr_hit_global_we_local_wb( - new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, - std::list<cache_event> &events, enum cache_request_status status) { - bool evict = (mf->get_access_type() == - GLOBAL_ACC_W); // evict a line that hits on global memory write - if (evict) - return wr_hit_we(addr, cache_index, mf, time, events, - status); // Write-evict - else - return wr_hit_wb(addr, cache_index, mf, time, events, - status); // Write-back +enum cache_request_status data_cache::wr_hit_global_we_local_wb(new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, std::list<cache_event> &events, enum cache_request_status status ){ + bool evict = (mf->get_access_type() == GLOBAL_ACC_W); // evict a line that hits on global memory write + if(evict) + return wr_hit_we(addr, cache_index, mf, time, events, status); // Write-evict + else + return wr_hit_wb(addr, cache_index, mf, time, events, status); // Write-back } /****** Write-miss functions (Set by config file) ******/ /// Write-allocate miss: Send write request to lower level memory // and send a read request for the same block -enum cache_request_status data_cache::wr_miss_wa_naive( - new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, - std::list<cache_event> &events, enum cache_request_status status) { - new_addr_type block_addr = m_config.block_addr(addr); - new_addr_type mshr_addr = m_config.mshr_addr(mf->get_addr()); +enum cache_request_status +data_cache::wr_miss_wa_naive( new_addr_type addr, + unsigned cache_index, mem_fetch *mf, + unsigned time, std::list<cache_event> &events, + enum cache_request_status status ) +{ + new_addr_type block_addr = m_config.block_addr(addr); + new_addr_type mshr_addr = m_config.mshr_addr(mf->get_addr()); - // Write allocate, maximum 3 requests (write miss, read request, write back - // request) - // Conservatively ensure the worst-case request can be handled this cycle - bool mshr_hit = m_mshrs.probe(mshr_addr); - bool mshr_avail = !m_mshrs.full(mshr_addr); - if (miss_queue_full(2) || - (!(mshr_hit && mshr_avail) && - !(!mshr_hit && mshr_avail && - (m_miss_queue.size() < m_config.m_miss_queue_size)))) { - // check what is the exactly the failure reason - if (miss_queue_full(2)) - m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); - else if (mshr_hit && !mshr_avail) - m_stats.inc_fail_stats(mf->get_access_type(), MSHR_MERGE_ENRTY_FAIL); - else if (!mshr_hit && !mshr_avail) - m_stats.inc_fail_stats(mf->get_access_type(), MSHR_ENRTY_FAIL); - else - assert(0); + // Write allocate, maximum 3 requests (write miss, read request, write back request) + // Conservatively ensure the worst-case request can be handled this cycle + bool mshr_hit = m_mshrs.probe(mshr_addr); + bool mshr_avail = !m_mshrs.full(mshr_addr); + if(miss_queue_full(2) + || (!(mshr_hit && mshr_avail) + && !(!mshr_hit && mshr_avail && (m_miss_queue.size() < m_config.m_miss_queue_size)))) { + //check what is the exactly the failure reason + if(miss_queue_full(2) ) + m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); + else if(mshr_hit && !mshr_avail) + m_stats.inc_fail_stats(mf->get_access_type(), MSHR_MERGE_ENRTY_FAIL); + else if (!mshr_hit && !mshr_avail) + m_stats.inc_fail_stats(mf->get_access_type(), MSHR_ENRTY_FAIL); + else + assert(0); - return RESERVATION_FAIL; - } + return RESERVATION_FAIL; + } - send_write_request(mf, cache_event(WRITE_REQUEST_SENT), time, events); - // Tries to send write allocate request, returns true on success and false on - // failure - // if(!send_write_allocate(mf, addr, block_addr, cache_index, time, events)) - // return RESERVATION_FAIL; + send_write_request(mf, cache_event(WRITE_REQUEST_SENT), time, events); + // Tries to send write allocate request, returns true on success and false on failure + //if(!send_write_allocate(mf, addr, block_addr, cache_index, time, events)) + // return RESERVATION_FAIL; - const mem_access_t *ma = - new mem_access_t(m_wr_alloc_type, mf->get_addr(), m_config.get_atom_sz(), - false, // Now performing a read - mf->get_access_warp_mask(), mf->get_access_byte_mask(), - mf->get_access_sector_mask(), m_gpu->gpgpu_ctx); + const mem_access_t *ma = new mem_access_t( m_wr_alloc_type, + mf->get_addr(), + m_config.get_atom_sz(), + false, // Now performing a read + mf->get_access_warp_mask(), + mf->get_access_byte_mask(), + mf->get_access_sector_mask(), + m_gpu->gpgpu_ctx); - mem_fetch *n_mf = - new mem_fetch(*ma, NULL, mf->get_ctrl_size(), mf->get_wid(), - mf->get_sid(), mf->get_tpc(), mf->get_mem_config(), - m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle); + mem_fetch *n_mf = new mem_fetch( *ma, + NULL, + mf->get_ctrl_size(), + mf->get_wid(), + mf->get_sid(), + mf->get_tpc(), + mf->get_mem_config(), + m_gpu->gpu_tot_sim_cycle+m_gpu->gpu_sim_cycle); - bool do_miss = false; - bool wb = false; - evicted_block_info evicted; + bool do_miss = false; + bool wb = false; + evicted_block_info evicted; - // Send read request resulting from write miss - send_read_request(addr, block_addr, cache_index, n_mf, time, do_miss, wb, - evicted, events, false, true); + // Send read request resulting from write miss + send_read_request(addr, block_addr, cache_index, n_mf, time, do_miss, wb, + evicted, events, false, true); - events.push_back(cache_event(WRITE_ALLOCATE_SENT)); + events.push_back(cache_event(WRITE_ALLOCATE_SENT)); - if (do_miss) { - // If evicted block is modified and not a write-through - // (already modified lower level) - if (wb && (m_config.m_write_policy != WRITE_THROUGH)) { - assert(status == - MISS); // SECTOR_MISS and HIT_RESERVED should not send write back - mem_fetch *wb = m_memfetch_creator->alloc( - evicted.m_block_addr, m_wrbk_type, evicted.m_modified_size, true, - m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle); - send_write_request(wb, cache_event(WRITE_BACK_REQUEST_SENT, evicted), - time, events); + if( do_miss ){ + // If evicted block is modified and not a write-through + // (already modified lower level) + if( wb && (m_config.m_write_policy != WRITE_THROUGH) ) { + assert(status == MISS); //SECTOR_MISS and HIT_RESERVED should not send write back + mem_fetch *wb = m_memfetch_creator->alloc(evicted.m_block_addr, + m_wrbk_type,evicted.m_modified_size,true,m_gpu->gpu_tot_sim_cycle+m_gpu->gpu_sim_cycle); + send_write_request(wb, cache_event(WRITE_BACK_REQUEST_SENT, evicted), time, events); + } + return MISS; } - return MISS; - } - return RESERVATION_FAIL; + return RESERVATION_FAIL; } -enum cache_request_status data_cache::wr_miss_wa_fetch_on_write( - new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, - std::list<cache_event> &events, enum cache_request_status status) { - new_addr_type block_addr = m_config.block_addr(addr); - new_addr_type mshr_addr = m_config.mshr_addr(mf->get_addr()); - if (mf->get_access_byte_mask().count() == m_config.get_atom_sz()) { - // if the request writes to the whole cache line/sector, then, write and set - // cache line Modified. - // and no need to send read request to memory or reserve mshr +enum cache_request_status +data_cache::wr_miss_wa_fetch_on_write( new_addr_type addr, + unsigned cache_index, mem_fetch *mf, + unsigned time, std::list<cache_event> &events, + enum cache_request_status status ) +{ + new_addr_type block_addr = m_config.block_addr(addr); + new_addr_type mshr_addr = m_config.mshr_addr(mf->get_addr()); - if (miss_queue_full(0)) { - m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); - return RESERVATION_FAIL; // cannot handle request this cycle - } + if(mf->get_access_byte_mask().count() == m_config.get_atom_sz()) + { + //if the request writes to the whole cache line/sector, then, write and set cache line Modified. + //and no need to send read request to memory or reserve mshr - bool wb = false; - evicted_block_info evicted; + if(miss_queue_full(0)) { + m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); + return RESERVATION_FAIL; // cannot handle request this cycle + } - cache_request_status status = - m_tag_array->access(block_addr, time, cache_index, wb, evicted, mf); - assert(status != HIT); - cache_block_t *block = m_tag_array->get_block(cache_index); - block->set_status(MODIFIED, mf->get_access_sector_mask()); - if (status == HIT_RESERVED) - block->set_ignore_on_fill(true, mf->get_access_sector_mask()); + bool wb = false; + evicted_block_info evicted; - if (status != RESERVATION_FAIL) { - // If evicted block is modified and not a write-through - // (already modified lower level) - if (wb && (m_config.m_write_policy != WRITE_THROUGH)) { - mem_fetch *wb = m_memfetch_creator->alloc( - evicted.m_block_addr, m_wrbk_type, evicted.m_modified_size, true, - m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle); - send_write_request(wb, cache_event(WRITE_BACK_REQUEST_SENT, evicted), - time, events); - } - return MISS; - } - return RESERVATION_FAIL; - } else { - bool mshr_hit = m_mshrs.probe(mshr_addr); - bool mshr_avail = !m_mshrs.full(mshr_addr); - if (miss_queue_full(1) || - (!(mshr_hit && mshr_avail) && - !(!mshr_hit && mshr_avail && - (m_miss_queue.size() < m_config.m_miss_queue_size)))) { - // check what is the exactly the failure reason - if (miss_queue_full(1)) - m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); - else if (mshr_hit && !mshr_avail) - m_stats.inc_fail_stats(mf->get_access_type(), MSHR_MERGE_ENRTY_FAIL); - else if (!mshr_hit && !mshr_avail) - m_stats.inc_fail_stats(mf->get_access_type(), MSHR_ENRTY_FAIL); - else - assert(0); + cache_request_status status = m_tag_array->access(block_addr,time,cache_index,wb,evicted,mf); + assert(status != HIT); + cache_block_t* block = m_tag_array->get_block(cache_index); + block->set_status(MODIFIED, mf->get_access_sector_mask()); + if(status == HIT_RESERVED) + block->set_ignore_on_fill(true, mf->get_access_sector_mask()); - return RESERVATION_FAIL; - } + if( status != RESERVATION_FAIL ){ + // If evicted block is modified and not a write-through + // (already modified lower level) + if( wb && (m_config.m_write_policy != WRITE_THROUGH) ) { + mem_fetch *wb = m_memfetch_creator->alloc(evicted.m_block_addr, + m_wrbk_type,evicted.m_modified_size,true,m_gpu->gpu_tot_sim_cycle+m_gpu->gpu_sim_cycle); + send_write_request(wb, cache_event(WRITE_BACK_REQUEST_SENT, evicted), time, events); + } + return MISS; + } + return RESERVATION_FAIL; + } + else + { + bool mshr_hit = m_mshrs.probe(mshr_addr); + bool mshr_avail = !m_mshrs.full(mshr_addr); + if(miss_queue_full(1) + || (!(mshr_hit && mshr_avail) + && !(!mshr_hit && mshr_avail && (m_miss_queue.size() < m_config.m_miss_queue_size)))) { + //check what is the exactly the failure reason + if(miss_queue_full(1) ) + m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); + else if(mshr_hit && !mshr_avail) + m_stats.inc_fail_stats(mf->get_access_type(), MSHR_MERGE_ENRTY_FAIL); + else if (!mshr_hit && !mshr_avail) + m_stats.inc_fail_stats(mf->get_access_type(), MSHR_ENRTY_FAIL); + else + assert(0); - // prevent Write - Read - Write in pending mshr - // allowing another write will override the value of the first write, and - // the pending read request will read incorrect result from the second write - if (m_mshrs.probe(mshr_addr) && - m_mshrs.is_read_after_write_pending(mshr_addr) && mf->is_write()) { - // assert(0); - m_stats.inc_fail_stats(mf->get_access_type(), MSHR_RW_PENDING); - return RESERVATION_FAIL; - } + return RESERVATION_FAIL; + } - const mem_access_t *ma = new mem_access_t( - m_wr_alloc_type, mf->get_addr(), m_config.get_atom_sz(), - false, // Now performing a read - mf->get_access_warp_mask(), mf->get_access_byte_mask(), - mf->get_access_sector_mask(), m_gpu->gpgpu_ctx); - mem_fetch *n_mf = new mem_fetch( - *ma, NULL, mf->get_ctrl_size(), mf->get_wid(), mf->get_sid(), - mf->get_tpc(), mf->get_mem_config(), - m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle, NULL, mf); + //prevent Write - Read - Write in pending mshr + //allowing another write will override the value of the first write, and the pending read request will read incorrect result from the second write + if(m_mshrs.probe(mshr_addr) && m_mshrs.is_read_after_write_pending(mshr_addr) && mf->is_write()) + { + //assert(0); + m_stats.inc_fail_stats(mf->get_access_type(), MSHR_RW_PENDING); + return RESERVATION_FAIL; + } - new_addr_type block_addr = m_config.block_addr(addr); - bool do_miss = false; - bool wb = false; - evicted_block_info evicted; - send_read_request(addr, block_addr, cache_index, n_mf, time, do_miss, wb, - evicted, events, false, true); + const mem_access_t *ma = new mem_access_t( m_wr_alloc_type, + mf->get_addr(), + m_config.get_atom_sz(), + false, // Now performing a read + mf->get_access_warp_mask(), + mf->get_access_byte_mask(), + mf->get_access_sector_mask(), + m_gpu->gpgpu_ctx); - cache_block_t *block = m_tag_array->get_block(cache_index); - block->set_modified_on_fill(true, mf->get_access_sector_mask()); + mem_fetch *n_mf = new mem_fetch( *ma, + NULL, + mf->get_ctrl_size(), + mf->get_wid(), + mf->get_sid(), + mf->get_tpc(), + mf->get_mem_config(), + m_gpu->gpu_tot_sim_cycle+m_gpu->gpu_sim_cycle, + NULL, + mf); - events.push_back(cache_event(WRITE_ALLOCATE_SENT)); - if (do_miss) { - // If evicted block is modified and not a write-through - // (already modified lower level) - if (wb && (m_config.m_write_policy != WRITE_THROUGH)) { - mem_fetch *wb = m_memfetch_creator->alloc( - evicted.m_block_addr, m_wrbk_type, evicted.m_modified_size, true, - m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle); - send_write_request(wb, cache_event(WRITE_BACK_REQUEST_SENT, evicted), - time, events); - } - return MISS; - } - return RESERVATION_FAIL; - } + new_addr_type block_addr = m_config.block_addr(addr); + bool do_miss = false; + bool wb = false; + evicted_block_info evicted; + send_read_request( addr, + block_addr, + cache_index, + n_mf, time, do_miss, wb, evicted, events, false, true); + + cache_block_t* block = m_tag_array->get_block(cache_index); + block->set_modified_on_fill(true, mf->get_access_sector_mask()); + + events.push_back(cache_event(WRITE_ALLOCATE_SENT)); + + if( do_miss ){ + // If evicted block is modified and not a write-through + // (already modified lower level) + if(wb && (m_config.m_write_policy != WRITE_THROUGH) ){ + mem_fetch *wb = m_memfetch_creator->alloc(evicted.m_block_addr, + m_wrbk_type,evicted.m_modified_size,true,m_gpu->gpu_tot_sim_cycle+m_gpu->gpu_sim_cycle); + send_write_request(wb, cache_event(WRITE_BACK_REQUEST_SENT, evicted), time, events); + } + return MISS; + } + return RESERVATION_FAIL; + } } -enum cache_request_status data_cache::wr_miss_wa_lazy_fetch_on_read( - new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, - std::list<cache_event> &events, enum cache_request_status status) { - new_addr_type block_addr = m_config.block_addr(addr); +enum cache_request_status +data_cache::wr_miss_wa_lazy_fetch_on_read( new_addr_type addr, + unsigned cache_index, mem_fetch *mf, + unsigned time, std::list<cache_event> &events, + enum cache_request_status status ) +{ - // if the request writes to the whole cache line/sector, then, write and set - // cache line Modified. - // and no need to send read request to memory or reserve mshr + new_addr_type block_addr = m_config.block_addr(addr); - if (miss_queue_full(0)) { - m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); - return RESERVATION_FAIL; // cannot handle request this cycle - } + //if the request writes to the whole cache line/sector, then, write and set cache line Modified. + //and no need to send read request to memory or reserve mshr - bool wb = false; - evicted_block_info evicted; + if(miss_queue_full(0)) { + m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); + return RESERVATION_FAIL; // cannot handle request this cycle + } - cache_request_status m_status = - m_tag_array->access(block_addr, time, cache_index, wb, evicted, mf); - assert(m_status != HIT); - cache_block_t *block = m_tag_array->get_block(cache_index); - block->set_status(MODIFIED, mf->get_access_sector_mask()); - if (m_status == HIT_RESERVED) { - block->set_ignore_on_fill(true, mf->get_access_sector_mask()); - block->set_modified_on_fill(true, mf->get_access_sector_mask()); - } + bool wb = false; + evicted_block_info evicted; - if (mf->get_access_byte_mask().count() == m_config.get_atom_sz()) { - block->set_m_readable(true, mf->get_access_sector_mask()); - } else { - block->set_m_readable(false, mf->get_access_sector_mask()); - } + cache_request_status m_status = m_tag_array->access(block_addr,time,cache_index,wb,evicted,mf); + assert(m_status != HIT); + cache_block_t* block = m_tag_array->get_block(cache_index); + block->set_status(MODIFIED, mf->get_access_sector_mask()); + if(m_status == HIT_RESERVED) { + block->set_ignore_on_fill(true, mf->get_access_sector_mask()); + block->set_modified_on_fill(true, mf->get_access_sector_mask()); + } - if (m_status != RESERVATION_FAIL) { - // If evicted block is modified and not a write-through - // (already modified lower level) - if (wb && (m_config.m_write_policy != WRITE_THROUGH)) { - mem_fetch *wb = m_memfetch_creator->alloc( - evicted.m_block_addr, m_wrbk_type, evicted.m_modified_size, true, - m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle); - send_write_request(wb, cache_event(WRITE_BACK_REQUEST_SENT, evicted), - time, events); - } - return MISS; - } - return RESERVATION_FAIL; + if(mf->get_access_byte_mask().count() == m_config.get_atom_sz()) + { + block->set_m_readable(true, mf->get_access_sector_mask()); + } else + { + block->set_m_readable(false, mf->get_access_sector_mask()); + } + + if( m_status != RESERVATION_FAIL ){ + // If evicted block is modified and not a write-through + // (already modified lower level) + if( wb && (m_config.m_write_policy != WRITE_THROUGH) ) { + mem_fetch *wb = m_memfetch_creator->alloc(evicted.m_block_addr, + m_wrbk_type,evicted.m_modified_size,true,m_gpu->gpu_tot_sim_cycle+m_gpu->gpu_sim_cycle); + send_write_request(wb, cache_event(WRITE_BACK_REQUEST_SENT, evicted), time, events); + } + return MISS; + } + return RESERVATION_FAIL; } /// No write-allocate miss: Simply send write request to lower level memory -enum cache_request_status data_cache::wr_miss_no_wa( - new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, - std::list<cache_event> &events, enum cache_request_status status) { - if (miss_queue_full(0)) { - m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); - return RESERVATION_FAIL; // cannot handle request this cycle - } +enum cache_request_status +data_cache::wr_miss_no_wa( new_addr_type addr, + unsigned cache_index, + mem_fetch *mf, + unsigned time, + std::list<cache_event> &events, + enum cache_request_status status ) +{ + if(miss_queue_full(0)) { + m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); + return RESERVATION_FAIL; // cannot handle request this cycle + } - // on miss, generate write through (no write buffering -- too many threads for - // that) - send_write_request(mf, cache_event(WRITE_REQUEST_SENT), time, events); - return MISS; + // on miss, generate write through (no write buffering -- too many threads for that) + send_write_request(mf, cache_event(WRITE_REQUEST_SENT), time, events); + + return MISS; } /****** Read hit functions (Set by config file) ******/ /// Baseline read hit: Update LRU status of block. // Special case for atomic instructions -> Mark block as modified -enum cache_request_status data_cache::rd_hit_base( - new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, - std::list<cache_event> &events, enum cache_request_status status) { - new_addr_type block_addr = m_config.block_addr(addr); - m_tag_array->access(block_addr, time, cache_index, mf); - // Atomics treated as global read/write requests - Perform read, mark line as - // MODIFIED - if (mf->isatomic()) { - assert(mf->get_access_type() == GLOBAL_ACC_R); - cache_block_t *block = m_tag_array->get_block(cache_index); - block->set_status(MODIFIED, - mf->get_access_sector_mask()); // mark line as dirty - } - return HIT; +enum cache_request_status +data_cache::rd_hit_base( new_addr_type addr, + unsigned cache_index, + mem_fetch *mf, + unsigned time, + std::list<cache_event> &events, + enum cache_request_status status ) +{ + new_addr_type block_addr = m_config.block_addr(addr); + m_tag_array->access(block_addr,time,cache_index,mf); + // Atomics treated as global read/write requests - Perform read, mark line as + // MODIFIED + if(mf->isatomic()){ + assert(mf->get_access_type() == GLOBAL_ACC_R); + cache_block_t* block = m_tag_array->get_block(cache_index); + block->set_status(MODIFIED, mf->get_access_sector_mask()) ; // mark line as dirty + } + return HIT; } /****** Read miss functions (Set by config file) ******/ /// Baseline read miss: Send read request to lower level memory, // perform write-back as necessary -enum cache_request_status data_cache::rd_miss_base( - new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, - std::list<cache_event> &events, enum cache_request_status status) { - if (miss_queue_full(1)) { - // cannot handle request this cycle - // (might need to generate two requests) - m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); - return RESERVATION_FAIL; - } +enum cache_request_status +data_cache::rd_miss_base( new_addr_type addr, + unsigned cache_index, + mem_fetch *mf, + unsigned time, + std::list<cache_event> &events, + enum cache_request_status status ){ + if(miss_queue_full(1)) { + // cannot handle request this cycle + // (might need to generate two requests) + m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); + return RESERVATION_FAIL; + } - new_addr_type block_addr = m_config.block_addr(addr); - bool do_miss = false; - bool wb = false; - evicted_block_info evicted; - send_read_request(addr, block_addr, cache_index, mf, time, do_miss, wb, - evicted, events, false, false); + new_addr_type block_addr = m_config.block_addr(addr); + bool do_miss = false; + bool wb = false; + evicted_block_info evicted; + send_read_request( addr, + block_addr, + cache_index, + mf, time, do_miss, wb, evicted, events, false, false); - if (do_miss) { - // If evicted block is modified and not a write-through - // (already modified lower level) - if (wb && (m_config.m_write_policy != WRITE_THROUGH)) { - mem_fetch *wb = m_memfetch_creator->alloc( - evicted.m_block_addr, m_wrbk_type, evicted.m_modified_size, true, - m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle); - send_write_request(wb, WRITE_BACK_REQUEST_SENT, time, events); + if( do_miss ){ + // If evicted block is modified and not a write-through + // (already modified lower level) + if(wb && (m_config.m_write_policy != WRITE_THROUGH) ){ + mem_fetch *wb = m_memfetch_creator->alloc(evicted.m_block_addr, + m_wrbk_type,evicted.m_modified_size,true,m_gpu->gpu_tot_sim_cycle+m_gpu->gpu_sim_cycle); + send_write_request(wb, WRITE_BACK_REQUEST_SENT, time, events); } - return MISS; - } - return RESERVATION_FAIL; + return MISS; + } + return RESERVATION_FAIL; } /// Access cache for read_only_cache: returns RESERVATION_FAIL if // request could not be accepted (for any reason) -enum cache_request_status read_only_cache::access( - new_addr_type addr, mem_fetch *mf, unsigned time, - std::list<cache_event> &events) { - assert(mf->get_data_size() <= m_config.get_atom_sz()); - assert(m_config.m_write_policy == READ_ONLY); - assert(!mf->get_is_write()); - new_addr_type block_addr = m_config.block_addr(addr); - unsigned cache_index = (unsigned)-1; - enum cache_request_status status = - m_tag_array->probe(block_addr, cache_index, mf); - enum cache_request_status cache_status = RESERVATION_FAIL; +enum cache_request_status +read_only_cache::access( new_addr_type addr, + mem_fetch *mf, + unsigned time, + std::list<cache_event> &events ) +{ + assert( mf->get_data_size() <= m_config.get_atom_sz()); + assert(m_config.m_write_policy == READ_ONLY); + assert(!mf->get_is_write()); + new_addr_type block_addr = m_config.block_addr(addr); + unsigned cache_index = (unsigned)-1; + enum cache_request_status status = m_tag_array->probe(block_addr,cache_index,mf); + enum cache_request_status cache_status = RESERVATION_FAIL; - if (status == HIT) { - cache_status = m_tag_array->access(block_addr, time, cache_index, - mf); // update LRU state - } else if (status != RESERVATION_FAIL) { - if (!miss_queue_full(0)) { - bool do_miss = false; - send_read_request(addr, block_addr, cache_index, mf, time, do_miss, - events, true, false); - if (do_miss) - cache_status = MISS; - else - cache_status = RESERVATION_FAIL; - } else { - cache_status = RESERVATION_FAIL; - m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); + if ( status == HIT ) { + cache_status = m_tag_array->access(block_addr,time,cache_index,mf); // update LRU state + }else if ( status != RESERVATION_FAIL ) { + if(!miss_queue_full(0)){ + bool do_miss=false; + send_read_request(addr, block_addr, cache_index, mf, time, do_miss, events, true, false); + if(do_miss) + cache_status = MISS; + else + cache_status = RESERVATION_FAIL; + }else{ + cache_status = RESERVATION_FAIL; + m_stats.inc_fail_stats(mf->get_access_type(), MISS_QUEUE_FULL); + } + }else { + m_stats.inc_fail_stats(mf->get_access_type(), LINE_ALLOC_FAIL); } - } else { - m_stats.inc_fail_stats(mf->get_access_type(), LINE_ALLOC_FAIL); - } - m_stats.inc_stats(mf->get_access_type(), - m_stats.select_stats_status(status, cache_status)); - m_stats.inc_stats_pw(mf->get_access_type(), - m_stats.select_stats_status(status, cache_status)); - return cache_status; + m_stats.inc_stats(mf->get_access_type(), m_stats.select_stats_status(status, cache_status)); + m_stats.inc_stats_pw(mf->get_access_type(), m_stats.select_stats_status(status, cache_status)); + return cache_status; } //! A general function that takes the result of a tag_array probe // and performs the correspding functions based on the cache configuration // The access fucntion calls this function -enum cache_request_status data_cache::process_tag_probe( - bool wr, enum cache_request_status probe_status, new_addr_type addr, - unsigned cache_index, mem_fetch *mf, unsigned time, - std::list<cache_event> &events) { - // Each function pointer ( m_[rd/wr]_[hit/miss] ) is set in the - // data_cache constructor to reflect the corresponding cache configuration - // options. Function pointers were used to avoid many long conditional - // branches resulting from many cache configuration options. - cache_request_status access_status = probe_status; - if (wr) { // Write - if (probe_status == HIT) { - access_status = - (this->*m_wr_hit)(addr, cache_index, mf, time, events, probe_status); - } else if ((probe_status != RESERVATION_FAIL) || - (probe_status == RESERVATION_FAIL && - m_config.m_write_alloc_policy == NO_WRITE_ALLOCATE)) { - access_status = - (this->*m_wr_miss)(addr, cache_index, mf, time, events, probe_status); - } else { - // the only reason for reservation fail here is LINE_ALLOC_FAIL (i.e all - // lines are reserved) - m_stats.inc_fail_stats(mf->get_access_type(), LINE_ALLOC_FAIL); - } - } else { // Read - if (probe_status == HIT) { - access_status = - (this->*m_rd_hit)(addr, cache_index, mf, time, events, probe_status); - } else if (probe_status != RESERVATION_FAIL) { - access_status = - (this->*m_rd_miss)(addr, cache_index, mf, time, events, probe_status); - } else { - // the only reason for reservation fail here is LINE_ALLOC_FAIL (i.e all - // lines are reserved) - m_stats.inc_fail_stats(mf->get_access_type(), LINE_ALLOC_FAIL); +enum cache_request_status +data_cache::process_tag_probe( bool wr, + enum cache_request_status probe_status, + new_addr_type addr, + unsigned cache_index, + mem_fetch* mf, + unsigned time, + std::list<cache_event>& events ) +{ + // Each function pointer ( m_[rd/wr]_[hit/miss] ) is set in the + // data_cache constructor to reflect the corresponding cache configuration + // options. Function pointers were used to avoid many long conditional + // branches resulting from many cache configuration options. + cache_request_status access_status = probe_status; + if(wr){ // Write + if(probe_status == HIT){ + access_status = (this->*m_wr_hit)( addr, + cache_index, + mf, time, events, probe_status ); + }else if ( (probe_status != RESERVATION_FAIL) || (probe_status == RESERVATION_FAIL && m_config.m_write_alloc_policy == NO_WRITE_ALLOCATE) ) { + access_status = (this->*m_wr_miss)( addr, + cache_index, + mf, time, events, probe_status ); + }else { + //the only reason for reservation fail here is LINE_ALLOC_FAIL (i.e all lines are reserved) + m_stats.inc_fail_stats(mf->get_access_type(), LINE_ALLOC_FAIL); + } + }else{ // Read + if(probe_status == HIT){ + access_status = (this->*m_rd_hit)( addr, + cache_index, + mf, time, events, probe_status ); + }else if ( probe_status != RESERVATION_FAIL ) { + access_status = (this->*m_rd_miss)( addr, + cache_index, + mf, time, events, probe_status ); + }else { + //the only reason for reservation fail here is LINE_ALLOC_FAIL (i.e all lines are reserved) + m_stats.inc_fail_stats(mf->get_access_type(), LINE_ALLOC_FAIL); + } } - } - m_bandwidth_management.use_data_port(mf, access_status, events); - return access_status; + m_bandwidth_management.use_data_port(mf, access_status, events); + return access_status; } // Both the L1 and L2 currently use the same access function. @@ -1650,41 +1645,51 @@ enum cache_request_status data_cache::process_tag_probe( // of caching policies. // Both the L1 and L2 override this function to provide a means of // performing actions specific to each cache when such actions are implemnted. -enum cache_request_status data_cache::access(new_addr_type addr, mem_fetch *mf, - unsigned time, - std::list<cache_event> &events) { - assert(mf->get_data_size() <= m_config.get_atom_sz()); - bool wr = mf->get_is_write(); - new_addr_type block_addr = m_config.block_addr(addr); - unsigned cache_index = (unsigned)-1; - enum cache_request_status probe_status = - m_tag_array->probe(block_addr, cache_index, mf, true); - enum cache_request_status access_status = - process_tag_probe(wr, probe_status, addr, cache_index, mf, time, events); - m_stats.inc_stats(mf->get_access_type(), - m_stats.select_stats_status(probe_status, access_status)); - m_stats.inc_stats_pw(mf->get_access_type(), m_stats.select_stats_status( - probe_status, access_status)); - return access_status; +enum cache_request_status +data_cache::access( new_addr_type addr, + mem_fetch *mf, + unsigned time, + std::list<cache_event> &events ) +{ + + assert( mf->get_data_size() <= m_config.get_atom_sz()); + bool wr = mf->get_is_write(); + new_addr_type block_addr = m_config.block_addr(addr); + unsigned cache_index = (unsigned)-1; + enum cache_request_status probe_status + = m_tag_array->probe( block_addr, cache_index, mf, true); + enum cache_request_status access_status + = process_tag_probe( wr, probe_status, addr, cache_index, mf, time, events ); + m_stats.inc_stats(mf->get_access_type(), + m_stats.select_stats_status(probe_status, access_status)); + m_stats.inc_stats_pw(mf->get_access_type(), + m_stats.select_stats_status(probe_status, access_status)); + return access_status; } /// This is meant to model the first level data cache in Fermi. /// It is write-evict (global) or write-back (local) at the /// granularity of individual blocks (Set by GPGPU-Sim configuration file) /// (the policy used in fermi according to the CUDA manual) -enum cache_request_status l1_cache::access(new_addr_type addr, mem_fetch *mf, - unsigned time, - std::list<cache_event> &events) { - return data_cache::access(addr, mf, time, events); +enum cache_request_status +l1_cache::access( new_addr_type addr, + mem_fetch *mf, + unsigned time, + std::list<cache_event> &events ) +{ + return data_cache::access( addr, mf, time, events ); } // The l2 cache access function calls the base data_cache access // implementation. When the L2 needs to diverge from L1, L2 specific // changes should be made here. -enum cache_request_status l2_cache::access(new_addr_type addr, mem_fetch *mf, - unsigned time, - std::list<cache_event> &events) { - return data_cache::access(addr, mf, time, events); +enum cache_request_status +l2_cache::access( new_addr_type addr, + mem_fetch *mf, + unsigned time, + std::list<cache_event> &events ) +{ + return data_cache::access( addr, mf, time, events ); } /// Access function for tex_cache @@ -1692,144 +1697,141 @@ enum cache_request_status l2_cache::access(new_addr_type addr, mem_fetch *mf, /// otherwise returns HIT_RESERVED or MISS; NOTE: *never* returns HIT /// since unlike a normal CPU cache, a "HIT" in texture cache does not /// mean the data is ready (still need to get through fragment fifo) -enum cache_request_status tex_cache::access(new_addr_type addr, mem_fetch *mf, - unsigned time, - std::list<cache_event> &events) { - if (m_fragment_fifo.full() || m_request_fifo.full() || m_rob.full()) - return RESERVATION_FAIL; +enum cache_request_status tex_cache::access( new_addr_type addr, mem_fetch *mf, + unsigned time, std::list<cache_event> &events ) +{ + if ( m_fragment_fifo.full() || m_request_fifo.full() || m_rob.full() ) + return RESERVATION_FAIL; - assert(mf->get_data_size() <= m_config.get_line_sz()); + assert( mf->get_data_size() <= m_config.get_line_sz()); - // at this point, we will accept the request : access tags and immediately - // allocate line - new_addr_type block_addr = m_config.block_addr(addr); - unsigned cache_index = (unsigned)-1; - enum cache_request_status status = - m_tags.access(block_addr, time, cache_index, mf); - enum cache_request_status cache_status = RESERVATION_FAIL; - assert(status != RESERVATION_FAIL); - assert(status != HIT_RESERVED); // as far as tags are concerned: HIT or MISS - m_fragment_fifo.push( - fragment_entry(mf, cache_index, status == MISS, mf->get_data_size())); - if (status == MISS) { - // we need to send a memory request... - unsigned rob_index = m_rob.push(rob_entry(cache_index, mf, block_addr)); - m_extra_mf_fields[mf] = extra_mf_fields(rob_index, m_config); - mf->set_data_size(m_config.get_line_sz()); - m_tags.fill(cache_index, time, mf); // mark block as valid - m_request_fifo.push(mf); - mf->set_status(m_request_queue_status, time); - events.push_back(cache_event(READ_REQUEST_SENT)); - cache_status = MISS; - } else { - // the value *will* *be* in the cache already - cache_status = HIT_RESERVED; - } - m_stats.inc_stats(mf->get_access_type(), - m_stats.select_stats_status(status, cache_status)); - m_stats.inc_stats_pw(mf->get_access_type(), - m_stats.select_stats_status(status, cache_status)); - return cache_status; + // at this point, we will accept the request : access tags and immediately allocate line + new_addr_type block_addr = m_config.block_addr(addr); + unsigned cache_index = (unsigned)-1; + enum cache_request_status status = m_tags.access(block_addr,time,cache_index,mf); + enum cache_request_status cache_status = RESERVATION_FAIL; + assert( status != RESERVATION_FAIL ); + assert( status != HIT_RESERVED ); // as far as tags are concerned: HIT or MISS + m_fragment_fifo.push( fragment_entry(mf,cache_index,status==MISS,mf->get_data_size()) ); + if ( status == MISS ) { + // we need to send a memory request... + unsigned rob_index = m_rob.push( rob_entry(cache_index, mf, block_addr) ); + m_extra_mf_fields[mf] = extra_mf_fields(rob_index, m_config); + mf->set_data_size(m_config.get_line_sz()); + m_tags.fill(cache_index,time,mf); // mark block as valid + m_request_fifo.push(mf); + mf->set_status(m_request_queue_status,time); + events.push_back(cache_event(READ_REQUEST_SENT)); + cache_status = MISS; + } else { + // the value *will* *be* in the cache already + cache_status = HIT_RESERVED; + } + m_stats.inc_stats(mf->get_access_type(), m_stats.select_stats_status(status, cache_status)); + m_stats.inc_stats_pw(mf->get_access_type(), m_stats.select_stats_status(status, cache_status)); + return cache_status; } -void tex_cache::cycle() { - // send next request to lower level of memory - if (!m_request_fifo.empty()) { - mem_fetch *mf = m_request_fifo.peek(); - if (!m_memport->full(mf->get_ctrl_size(), false)) { - m_request_fifo.pop(); - m_memport->push(mf); +void tex_cache::cycle(){ + // send next request to lower level of memory + if ( !m_request_fifo.empty() ) { + mem_fetch *mf = m_request_fifo.peek(); + if ( !m_memport->full(mf->get_ctrl_size(),false) ) { + m_request_fifo.pop(); + m_memport->push(mf); + } } - } - // read ready lines from cache - if (!m_fragment_fifo.empty() && !m_result_fifo.full()) { - const fragment_entry &e = m_fragment_fifo.peek(); - if (e.m_miss) { - // check head of reorder buffer to see if data is back from memory - unsigned rob_index = m_rob.next_pop_index(); - const rob_entry &r = m_rob.peek(rob_index); - assert(r.m_request == e.m_request); - // assert( r.m_block_addr == m_config.block_addr(e.m_request->get_addr()) - // ); - if (r.m_ready) { - assert(r.m_index == e.m_cache_index); - m_cache[r.m_index].m_valid = true; - m_cache[r.m_index].m_block_addr = r.m_block_addr; - m_result_fifo.push(e.m_request); - m_rob.pop(); - m_fragment_fifo.pop(); - } - } else { - // hit: - assert(m_cache[e.m_cache_index].m_valid); - assert(m_cache[e.m_cache_index].m_block_addr == - m_config.block_addr(e.m_request->get_addr())); - m_result_fifo.push(e.m_request); - m_fragment_fifo.pop(); + // read ready lines from cache + if ( !m_fragment_fifo.empty() && !m_result_fifo.full() ) { + const fragment_entry &e = m_fragment_fifo.peek(); + if ( e.m_miss ) { + // check head of reorder buffer to see if data is back from memory + unsigned rob_index = m_rob.next_pop_index(); + const rob_entry &r = m_rob.peek(rob_index); + assert( r.m_request == e.m_request ); + //assert( r.m_block_addr == m_config.block_addr(e.m_request->get_addr()) ); + if ( r.m_ready ) { + assert( r.m_index == e.m_cache_index ); + m_cache[r.m_index].m_valid = true; + m_cache[r.m_index].m_block_addr = r.m_block_addr; + m_result_fifo.push(e.m_request); + m_rob.pop(); + m_fragment_fifo.pop(); + } + } else { + // hit: + assert( m_cache[e.m_cache_index].m_valid ); + assert( m_cache[e.m_cache_index].m_block_addr + == m_config.block_addr(e.m_request->get_addr()) ); + m_result_fifo.push( e.m_request ); + m_fragment_fifo.pop(); + } } - } } /// Place returning cache block into reorder buffer -void tex_cache::fill(mem_fetch *mf, unsigned time) { - if (m_config.m_mshr_type == SECTOR_TEX_FIFO) { - assert(mf->get_original_mf()); - extra_mf_fields_lookup::iterator e = - m_extra_mf_fields.find(mf->get_original_mf()); - assert(e != m_extra_mf_fields.end()); +void tex_cache::fill( mem_fetch *mf, unsigned time ) +{ + if(m_config.m_mshr_type == SECTOR_TEX_FIFO) { + assert(mf->get_original_mf()); + extra_mf_fields_lookup::iterator e = m_extra_mf_fields.find(mf->get_original_mf()); + assert( e != m_extra_mf_fields.end() ); e->second.pending_read--; - if (e->second.pending_read > 0) { - // wait for the other requests to come back - delete mf; - return; - } else { - mem_fetch *temp = mf; - mf = mf->get_original_mf(); - delete temp; - } - } + if(e->second.pending_read > 0) { + //wait for the other requests to come back + delete mf; + return; + } else { + mem_fetch *temp = mf; + mf = mf->get_original_mf(); + delete temp; + } + } - extra_mf_fields_lookup::iterator e = m_extra_mf_fields.find(mf); - assert(e != m_extra_mf_fields.end()); - assert(e->second.m_valid); - assert(!m_rob.empty()); - mf->set_status(m_rob_status, time); + extra_mf_fields_lookup::iterator e = m_extra_mf_fields.find(mf); + assert( e != m_extra_mf_fields.end() ); + assert( e->second.m_valid ); + assert( !m_rob.empty() ); + mf->set_status(m_rob_status,time); - unsigned rob_index = e->second.m_rob_index; - rob_entry &r = m_rob.peek(rob_index); - assert(!r.m_ready); - r.m_ready = true; - r.m_time = time; - assert(r.m_block_addr == m_config.block_addr(mf->get_addr())); + unsigned rob_index = e->second.m_rob_index; + rob_entry &r = m_rob.peek(rob_index); + assert( !r.m_ready ); + r.m_ready = true; + r.m_time = time; + assert( r.m_block_addr == m_config.block_addr(mf->get_addr()) ); } -void tex_cache::display_state(FILE *fp) const { - fprintf(fp, "%s (texture cache) state:\n", m_name.c_str()); - fprintf(fp, "fragment fifo entries = %u / %u\n", m_fragment_fifo.size(), - m_fragment_fifo.capacity()); - fprintf(fp, "reorder buffer entries = %u / %u\n", m_rob.size(), - m_rob.capacity()); - fprintf(fp, "request fifo entries = %u / %u\n", m_request_fifo.size(), - m_request_fifo.capacity()); - if (!m_rob.empty()) fprintf(fp, "reorder buffer contents:\n"); - for (int n = m_rob.size() - 1; n >= 0; n--) { - unsigned index = (m_rob.next_pop_index() + n) % m_rob.capacity(); - const rob_entry &r = m_rob.peek(index); - fprintf(fp, "tex rob[%3d] : %s ", index, - (r.m_ready ? "ready " : "pending")); - if (r.m_ready) - fprintf(fp, "@%6u", r.m_time); - else - fprintf(fp, " "); - fprintf(fp, "[idx=%4u]", r.m_index); - r.m_request->print(fp, false); - } - if (!m_fragment_fifo.empty()) { - fprintf(fp, "fragment fifo (oldest) :"); - fragment_entry &f = m_fragment_fifo.peek(); - fprintf(fp, "%s: ", f.m_miss ? "miss" : "hit "); - f.m_request->print(fp, false); - } +void tex_cache::display_state( FILE *fp ) const +{ + fprintf(fp,"%s (texture cache) state:\n", m_name.c_str() ); + fprintf(fp,"fragment fifo entries = %u / %u\n", + m_fragment_fifo.size(), m_fragment_fifo.capacity() ); + fprintf(fp,"reorder buffer entries = %u / %u\n", + m_rob.size(), m_rob.capacity() ); + fprintf(fp,"request fifo entries = %u / %u\n", + m_request_fifo.size(), m_request_fifo.capacity() ); + if ( !m_rob.empty() ) + fprintf(fp,"reorder buffer contents:\n"); + for ( int n=m_rob.size()-1; n>=0; n-- ) { + unsigned index = (m_rob.next_pop_index() + n)%m_rob.capacity(); + const rob_entry &r = m_rob.peek(index); + fprintf(fp, "tex rob[%3d] : %s ", + index, (r.m_ready?"ready ":"pending") ); + if ( r.m_ready ) + fprintf(fp,"@%6u", r.m_time ); + else + fprintf(fp," "); + fprintf(fp,"[idx=%4u]",r.m_index); + r.m_request->print(fp,false); + } + if ( !m_fragment_fifo.empty() ) { + fprintf(fp,"fragment fifo (oldest) :"); + fragment_entry &f = m_fragment_fifo.peek(); + fprintf(fp,"%s: ", f.m_miss?"miss":"hit "); + f.m_request->print(fp,false); + } } /******************************************************************************************************************************************/ + diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index 9b9898e..6f39221 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -32,420 +30,464 @@ #include <stdio.h> #include <stdlib.h> -#include "../abstract_hardware_model.h" -#include "../tr1_hash_map.h" #include "gpu-misc.h" #include "mem_fetch.h" +#include "../abstract_hardware_model.h" +#include "../tr1_hash_map.h" -#include <iostream> #include "addrdec.h" +#include <iostream> #define MAX_DEFAULT_CACHE_SIZE_MULTIBLIER 4 -enum cache_block_state { INVALID = 0, RESERVED, VALID, MODIFIED }; +enum cache_block_state { + INVALID=0, + RESERVED, + VALID, + MODIFIED +}; enum cache_request_status { - HIT = 0, - HIT_RESERVED, - MISS, - RESERVATION_FAIL, - SECTOR_MISS, - NUM_CACHE_REQUEST_STATUS + HIT = 0, + HIT_RESERVED, + MISS, + RESERVATION_FAIL, + SECTOR_MISS, + NUM_CACHE_REQUEST_STATUS }; enum cache_reservation_fail_reason { - LINE_ALLOC_FAIL = 0, // all line are reserved - MISS_QUEUE_FULL, // MISS queue (i.e. interconnect or DRAM) is full - MSHR_ENRTY_FAIL, - MSHR_MERGE_ENRTY_FAIL, - MSHR_RW_PENDING, - NUM_CACHE_RESERVATION_FAIL_STATUS + LINE_ALLOC_FAIL= 0,// all line are reserved + MISS_QUEUE_FULL, // MISS queue (i.e. interconnect or DRAM) is full + MSHR_ENRTY_FAIL, + MSHR_MERGE_ENRTY_FAIL, + MSHR_RW_PENDING, + NUM_CACHE_RESERVATION_FAIL_STATUS }; enum cache_event_type { - WRITE_BACK_REQUEST_SENT, - READ_REQUEST_SENT, - WRITE_REQUEST_SENT, - WRITE_ALLOCATE_SENT + WRITE_BACK_REQUEST_SENT, + READ_REQUEST_SENT, + WRITE_REQUEST_SENT, + WRITE_ALLOCATE_SENT }; struct evicted_block_info { - new_addr_type m_block_addr; - unsigned m_modified_size; - evicted_block_info() { - m_block_addr = 0; - m_modified_size = 0; - } - void set_info(new_addr_type block_addr, unsigned modified_size) { - m_block_addr = block_addr; - m_modified_size = modified_size; - } + new_addr_type m_block_addr; + unsigned m_modified_size; + evicted_block_info() { + m_block_addr = 0; + m_modified_size = 0; + } + void set_info(new_addr_type block_addr, unsigned modified_size){ + m_block_addr = block_addr; + m_modified_size = modified_size; + } }; struct cache_event { - enum cache_event_type m_cache_event_type; - evicted_block_info m_evicted_block; // if it was write_back event, fill the - // the evicted block info + enum cache_event_type m_cache_event_type; + evicted_block_info m_evicted_block; //if it was write_back event, fill the the evicted block info - cache_event(enum cache_event_type m_cache_event) { - m_cache_event_type = m_cache_event; - } + cache_event(enum cache_event_type m_cache_event){ + m_cache_event_type = m_cache_event; + } - cache_event(enum cache_event_type cache_event, - evicted_block_info evicted_block) { - m_cache_event_type = cache_event; - m_evicted_block = evicted_block; - } + cache_event(enum cache_event_type cache_event, evicted_block_info evicted_block){ + m_cache_event_type = cache_event; + m_evicted_block = evicted_block; + } }; -const char *cache_request_status_str(enum cache_request_status status); +const char * cache_request_status_str(enum cache_request_status status); struct cache_block_t { - cache_block_t() { - m_tag = 0; - m_block_addr = 0; - } + cache_block_t() + { + m_tag=0; + m_block_addr=0; + } - virtual void allocate(new_addr_type tag, new_addr_type block_addr, - unsigned time, - mem_access_sector_mask_t sector_mask) = 0; - virtual void fill(unsigned time, mem_access_sector_mask_t sector_mask) = 0; + virtual void allocate( new_addr_type tag, new_addr_type block_addr, unsigned time, mem_access_sector_mask_t sector_mask) = 0; + virtual void fill( unsigned time, mem_access_sector_mask_t sector_mask) = 0; - virtual bool is_invalid_line() = 0; - virtual bool is_valid_line() = 0; - virtual bool is_reserved_line() = 0; - virtual bool is_modified_line() = 0; + virtual bool is_invalid_line() = 0; + virtual bool is_valid_line() = 0; + virtual bool is_reserved_line() = 0; + virtual bool is_modified_line() = 0; - virtual enum cache_block_state get_status( - mem_access_sector_mask_t sector_mask) = 0; - virtual void set_status(enum cache_block_state m_status, - mem_access_sector_mask_t sector_mask) = 0; + virtual enum cache_block_state get_status( mem_access_sector_mask_t sector_mask) = 0; + virtual void set_status(enum cache_block_state m_status, mem_access_sector_mask_t sector_mask) = 0; - virtual unsigned long long get_last_access_time() = 0; - virtual void set_last_access_time(unsigned long long time, - mem_access_sector_mask_t sector_mask) = 0; - virtual unsigned long long get_alloc_time() = 0; - virtual void set_ignore_on_fill(bool m_ignore, - mem_access_sector_mask_t sector_mask) = 0; - virtual void set_modified_on_fill(bool m_modified, - mem_access_sector_mask_t sector_mask) = 0; - virtual unsigned get_modified_size() = 0; - virtual void set_m_readable(bool readable, - mem_access_sector_mask_t sector_mask) = 0; - virtual bool is_readable(mem_access_sector_mask_t sector_mask) = 0; - virtual void print_status() = 0; - virtual ~cache_block_t() {} + virtual unsigned long long get_last_access_time() = 0; + virtual void set_last_access_time(unsigned long long time, mem_access_sector_mask_t sector_mask) = 0; + virtual unsigned long long get_alloc_time() = 0; + virtual void set_ignore_on_fill(bool m_ignore, mem_access_sector_mask_t sector_mask) = 0; + virtual void set_modified_on_fill(bool m_modified, mem_access_sector_mask_t sector_mask) = 0; + virtual unsigned get_modified_size() = 0; + virtual void set_m_readable(bool readable, mem_access_sector_mask_t sector_mask)=0; + virtual bool is_readable(mem_access_sector_mask_t sector_mask)=0; + virtual void print_status()=0; + virtual ~cache_block_t() {} + + + new_addr_type m_tag; + new_addr_type m_block_addr; - new_addr_type m_tag; - new_addr_type m_block_addr; }; -struct line_cache_block : public cache_block_t { - line_cache_block() { - m_alloc_time = 0; - m_fill_time = 0; - m_last_access_time = 0; - m_status = INVALID; - m_ignore_on_fill_status = false; - m_set_modified_on_fill = false; - m_readable = true; - } - void allocate(new_addr_type tag, new_addr_type block_addr, unsigned time, - mem_access_sector_mask_t sector_mask) { - m_tag = tag; - m_block_addr = block_addr; - m_alloc_time = time; - m_last_access_time = time; - m_fill_time = 0; - m_status = RESERVED; - m_ignore_on_fill_status = false; - m_set_modified_on_fill = false; - } - void fill(unsigned time, mem_access_sector_mask_t sector_mask) { - // if(!m_ignore_on_fill_status) - // assert( m_status == RESERVED ); +struct line_cache_block: public cache_block_t { + line_cache_block() + { + m_alloc_time=0; + m_fill_time=0; + m_last_access_time=0; + m_status=INVALID; + m_ignore_on_fill_status = false; + m_set_modified_on_fill = false; + m_readable = true; + } + void allocate( new_addr_type tag, new_addr_type block_addr, unsigned time, mem_access_sector_mask_t sector_mask) + { + m_tag=tag; + m_block_addr=block_addr; + m_alloc_time=time; + m_last_access_time=time; + m_fill_time=0; + m_status=RESERVED; + m_ignore_on_fill_status = false; + m_set_modified_on_fill = false; + } + void fill( unsigned time, mem_access_sector_mask_t sector_mask ) + { + //if(!m_ignore_on_fill_status) + // assert( m_status == RESERVED ); + + m_status = m_set_modified_on_fill? MODIFIED : VALID; - m_status = m_set_modified_on_fill ? MODIFIED : VALID; + m_fill_time=time; + } + virtual bool is_invalid_line() + { + return m_status == INVALID; + } + virtual bool is_valid_line() + { + return m_status == VALID; + } + virtual bool is_reserved_line() + { + return m_status == RESERVED; + } + virtual bool is_modified_line() + { + return m_status == MODIFIED; + } - m_fill_time = time; - } - virtual bool is_invalid_line() { return m_status == INVALID; } - virtual bool is_valid_line() { return m_status == VALID; } - virtual bool is_reserved_line() { return m_status == RESERVED; } - virtual bool is_modified_line() { return m_status == MODIFIED; } + virtual enum cache_block_state get_status(mem_access_sector_mask_t sector_mask) + { + return m_status; + } + virtual void set_status(enum cache_block_state status, mem_access_sector_mask_t sector_mask) + { + m_status = status; + } + virtual unsigned long long get_last_access_time() + { + return m_last_access_time; + } + virtual void set_last_access_time(unsigned long long time, mem_access_sector_mask_t sector_mask) + { + m_last_access_time = time; + } + virtual unsigned long long get_alloc_time() + { + return m_alloc_time; + } + virtual void set_ignore_on_fill(bool m_ignore, mem_access_sector_mask_t sector_mask) + { + m_ignore_on_fill_status = m_ignore; + } + virtual void set_modified_on_fill(bool m_modified, mem_access_sector_mask_t sector_mask) + { + m_set_modified_on_fill = m_modified; + } + virtual unsigned get_modified_size() + { + return SECTOR_CHUNCK_SIZE * SECTOR_SIZE; //i.e. cache line size + } + virtual void set_m_readable(bool readable, mem_access_sector_mask_t sector_mask) + { + m_readable = readable; + } + virtual bool is_readable(mem_access_sector_mask_t sector_mask) { + return m_readable; + } + virtual void print_status() { + printf("m_block_addr is %llu, status = %u\n", m_block_addr, m_status); + } - virtual enum cache_block_state get_status( - mem_access_sector_mask_t sector_mask) { - return m_status; - } - virtual void set_status(enum cache_block_state status, - mem_access_sector_mask_t sector_mask) { - m_status = status; - } - virtual unsigned long long get_last_access_time() { - return m_last_access_time; - } - virtual void set_last_access_time(unsigned long long time, - mem_access_sector_mask_t sector_mask) { - m_last_access_time = time; - } - virtual unsigned long long get_alloc_time() { return m_alloc_time; } - virtual void set_ignore_on_fill(bool m_ignore, - mem_access_sector_mask_t sector_mask) { - m_ignore_on_fill_status = m_ignore; - } - virtual void set_modified_on_fill(bool m_modified, - mem_access_sector_mask_t sector_mask) { - m_set_modified_on_fill = m_modified; - } - virtual unsigned get_modified_size() { - return SECTOR_CHUNCK_SIZE * SECTOR_SIZE; // i.e. cache line size - } - virtual void set_m_readable(bool readable, - mem_access_sector_mask_t sector_mask) { - m_readable = readable; - } - virtual bool is_readable(mem_access_sector_mask_t sector_mask) { - return m_readable; - } - virtual void print_status() { - printf("m_block_addr is %llu, status = %u\n", m_block_addr, m_status); - } - private: - unsigned long long m_alloc_time; - unsigned long long m_last_access_time; - unsigned long long m_fill_time; - cache_block_state m_status; - bool m_ignore_on_fill_status; - bool m_set_modified_on_fill; - bool m_readable; +private: + unsigned long long m_alloc_time; + unsigned long long m_last_access_time; + unsigned long long m_fill_time; + cache_block_state m_status; + bool m_ignore_on_fill_status; + bool m_set_modified_on_fill; + bool m_readable; }; struct sector_cache_block : public cache_block_t { - sector_cache_block() { init(); } - - void init() { - for (unsigned i = 0; i < SECTOR_CHUNCK_SIZE; ++i) { - m_sector_alloc_time[i] = 0; - m_sector_fill_time[i] = 0; - m_last_sector_access_time[i] = 0; - m_status[i] = INVALID; - m_ignore_on_fill_status[i] = false; - m_set_modified_on_fill[i] = false; - m_readable[i] = true; + sector_cache_block() + { + init(); } - m_line_alloc_time = 0; - m_line_last_access_time = 0; - m_line_fill_time = 0; - } - virtual void allocate(new_addr_type tag, new_addr_type block_addr, - unsigned time, mem_access_sector_mask_t sector_mask) { - allocate_line(tag, block_addr, time, sector_mask); - } + void init() { + for(unsigned i =0; i< SECTOR_CHUNCK_SIZE; ++i) { + m_sector_alloc_time[i]= 0; + m_sector_fill_time[i]= 0; + m_last_sector_access_time[i]= 0; + m_status[i]= INVALID; + m_ignore_on_fill_status[i] = false; + m_set_modified_on_fill[i] = false; + m_readable[i] = true; + } + m_line_alloc_time=0; + m_line_last_access_time=0; + m_line_fill_time=0; + } + + virtual void allocate( new_addr_type tag, new_addr_type block_addr, unsigned time, mem_access_sector_mask_t sector_mask ) + { + allocate_line( tag, block_addr, time, sector_mask ); + } - void allocate_line(new_addr_type tag, new_addr_type block_addr, unsigned time, - mem_access_sector_mask_t sector_mask) { - // allocate a new line - // assert(m_block_addr != 0 && m_block_addr != block_addr); - init(); - m_tag = tag; - m_block_addr = block_addr; + void allocate_line( new_addr_type tag, new_addr_type block_addr, unsigned time, mem_access_sector_mask_t sector_mask ) + { + //allocate a new line + //assert(m_block_addr != 0 && m_block_addr != block_addr); + init(); + m_tag=tag; + m_block_addr=block_addr; - unsigned sidx = get_sector_index(sector_mask); + unsigned sidx = get_sector_index(sector_mask); - // set sector stats - m_sector_alloc_time[sidx] = time; - m_last_sector_access_time[sidx] = time; - m_sector_fill_time[sidx] = 0; - m_status[sidx] = RESERVED; - m_ignore_on_fill_status[sidx] = false; - m_set_modified_on_fill[sidx] = false; + //set sector stats + m_sector_alloc_time[sidx]=time; + m_last_sector_access_time[sidx]=time; + m_sector_fill_time[sidx]=0; + m_status[sidx]=RESERVED; + m_ignore_on_fill_status[sidx] = false; + m_set_modified_on_fill[sidx] = false; - // set line stats - m_line_alloc_time = time; // only set this for the first allocated sector - m_line_last_access_time = time; - m_line_fill_time = 0; - } + //set line stats + m_line_alloc_time=time; //only set this for the first allocated sector + m_line_last_access_time=time; + m_line_fill_time=0; + } - void allocate_sector(unsigned time, mem_access_sector_mask_t sector_mask) { - // allocate invalid sector of this allocated valid line - assert(is_valid_line()); - unsigned sidx = get_sector_index(sector_mask); + void allocate_sector(unsigned time, mem_access_sector_mask_t sector_mask ) + { + //allocate invalid sector of this allocated valid line + assert(is_valid_line()); + unsigned sidx = get_sector_index(sector_mask); - // set sector stats - m_sector_alloc_time[sidx] = time; - m_last_sector_access_time[sidx] = time; - m_sector_fill_time[sidx] = 0; - if (m_status[sidx] == MODIFIED) // this should be the case only for - // fetch-on-write policy //TO DO - m_set_modified_on_fill[sidx] = true; - else - m_set_modified_on_fill[sidx] = false; + //set sector stats + m_sector_alloc_time[sidx]=time; + m_last_sector_access_time[sidx]=time; + m_sector_fill_time[sidx]=0; + if(m_status[sidx]==MODIFIED) //this should be the case only for fetch-on-write policy //TO DO + m_set_modified_on_fill[sidx] = true; + else + m_set_modified_on_fill[sidx] = false; - m_status[sidx] = RESERVED; - m_ignore_on_fill_status[sidx] = false; - // m_set_modified_on_fill[sidx] = false; - m_readable[sidx] = true; + m_status[sidx]=RESERVED; + m_ignore_on_fill_status[sidx] = false; + //m_set_modified_on_fill[sidx] = false; + m_readable[sidx] = true; - // set line stats - m_line_last_access_time = time; - m_line_fill_time = 0; - } + //set line stats + m_line_last_access_time=time; + m_line_fill_time=0; + } - virtual void fill(unsigned time, mem_access_sector_mask_t sector_mask) { - unsigned sidx = get_sector_index(sector_mask); + virtual void fill( unsigned time, mem_access_sector_mask_t sector_mask) + { + unsigned sidx = get_sector_index(sector_mask); // if(!m_ignore_on_fill_status[sidx]) // assert( m_status[sidx] == RESERVED ); - m_status[sidx] = m_set_modified_on_fill[sidx] ? MODIFIED : VALID; + m_status[sidx] = m_set_modified_on_fill[sidx]? MODIFIED : VALID; - m_sector_fill_time[sidx] = time; - m_line_fill_time = time; - } - virtual bool is_invalid_line() { - // all the sectors should be invalid - for (unsigned i = 0; i < SECTOR_CHUNCK_SIZE; ++i) { - if (m_status[i] != INVALID) return false; + m_sector_fill_time[sidx]=time; + m_line_fill_time=time; } - return true; - } - virtual bool is_valid_line() { return !(is_invalid_line()); } - virtual bool is_reserved_line() { - // if any of the sector is reserved, then the line is reserved - for (unsigned i = 0; i < SECTOR_CHUNCK_SIZE; ++i) { - if (m_status[i] == RESERVED) return true; + virtual bool is_invalid_line() { + //all the sectors should be invalid + for(unsigned i =0; i< SECTOR_CHUNCK_SIZE; ++i) { + if (m_status[i] != INVALID) + return false; + } + return true; } - return false; - } - virtual bool is_modified_line() { - // if any of the sector is modified, then the line is modified - for (unsigned i = 0; i < SECTOR_CHUNCK_SIZE; ++i) { - if (m_status[i] == MODIFIED) return true; + virtual bool is_valid_line() { return !(is_invalid_line()); } + virtual bool is_reserved_line() { + //if any of the sector is reserved, then the line is reserved + for(unsigned i =0; i< SECTOR_CHUNCK_SIZE; ++i) { + if (m_status[i] == RESERVED) + return true; + } + return false; } - return false; - } + virtual bool is_modified_line() { + //if any of the sector is modified, then the line is modified + for(unsigned i =0; i< SECTOR_CHUNCK_SIZE; ++i) { + if (m_status[i] == MODIFIED) + return true; + } + return false; + } + + virtual enum cache_block_state get_status(mem_access_sector_mask_t sector_mask) + { + unsigned sidx = get_sector_index(sector_mask); - virtual enum cache_block_state get_status( - mem_access_sector_mask_t sector_mask) { - unsigned sidx = get_sector_index(sector_mask); + return m_status[sidx]; + } - return m_status[sidx]; - } + virtual void set_status(enum cache_block_state status, mem_access_sector_mask_t sector_mask) + { + unsigned sidx = get_sector_index(sector_mask); + m_status[sidx] = status; + } - virtual void set_status(enum cache_block_state status, - mem_access_sector_mask_t sector_mask) { - unsigned sidx = get_sector_index(sector_mask); - m_status[sidx] = status; - } + virtual unsigned long long get_last_access_time() + { + return m_line_last_access_time; + } - virtual unsigned long long get_last_access_time() { - return m_line_last_access_time; - } + virtual void set_last_access_time(unsigned long long time, mem_access_sector_mask_t sector_mask) + { + unsigned sidx = get_sector_index(sector_mask); - virtual void set_last_access_time(unsigned long long time, - mem_access_sector_mask_t sector_mask) { - unsigned sidx = get_sector_index(sector_mask); + m_last_sector_access_time[sidx] = time; + m_line_last_access_time = time; + } - m_last_sector_access_time[sidx] = time; - m_line_last_access_time = time; - } + virtual unsigned long long get_alloc_time() + { + return m_line_alloc_time; + } - virtual unsigned long long get_alloc_time() { return m_line_alloc_time; } + virtual void set_ignore_on_fill(bool m_ignore, mem_access_sector_mask_t sector_mask) + { + unsigned sidx = get_sector_index(sector_mask); + m_ignore_on_fill_status[sidx] = m_ignore; + } - virtual void set_ignore_on_fill(bool m_ignore, - mem_access_sector_mask_t sector_mask) { - unsigned sidx = get_sector_index(sector_mask); - m_ignore_on_fill_status[sidx] = m_ignore; - } + virtual void set_modified_on_fill(bool m_modified, mem_access_sector_mask_t sector_mask) + { + unsigned sidx = get_sector_index(sector_mask); + m_set_modified_on_fill[sidx] = m_modified; + } - virtual void set_modified_on_fill(bool m_modified, - mem_access_sector_mask_t sector_mask) { - unsigned sidx = get_sector_index(sector_mask); - m_set_modified_on_fill[sidx] = m_modified; - } + virtual void set_m_readable(bool readable, mem_access_sector_mask_t sector_mask) + { + unsigned sidx = get_sector_index(sector_mask); + m_readable[sidx] = readable; + } - virtual void set_m_readable(bool readable, - mem_access_sector_mask_t sector_mask) { - unsigned sidx = get_sector_index(sector_mask); - m_readable[sidx] = readable; - } + virtual bool is_readable(mem_access_sector_mask_t sector_mask) { + unsigned sidx = get_sector_index(sector_mask); + return m_readable[sidx]; + } - virtual bool is_readable(mem_access_sector_mask_t sector_mask) { - unsigned sidx = get_sector_index(sector_mask); - return m_readable[sidx]; - } + virtual unsigned get_modified_size() + { + unsigned modified=0; + for(unsigned i =0; i< SECTOR_CHUNCK_SIZE; ++i) { + if (m_status[i] == MODIFIED) + modified++; + } + return modified * SECTOR_SIZE; + } - virtual unsigned get_modified_size() { - unsigned modified = 0; - for (unsigned i = 0; i < SECTOR_CHUNCK_SIZE; ++i) { - if (m_status[i] == MODIFIED) modified++; + virtual void print_status() { + printf("m_block_addr is %llu, status = %u %u %u %u\n", m_block_addr, m_status[0], m_status[1], m_status[2], m_status[3]); } - return modified * SECTOR_SIZE; - } - virtual void print_status() { - printf("m_block_addr is %llu, status = %u %u %u %u\n", m_block_addr, - m_status[0], m_status[1], m_status[2], m_status[3]); - } - private: - unsigned m_sector_alloc_time[SECTOR_CHUNCK_SIZE]; - unsigned m_last_sector_access_time[SECTOR_CHUNCK_SIZE]; - unsigned m_sector_fill_time[SECTOR_CHUNCK_SIZE]; - unsigned m_line_alloc_time; - unsigned m_line_last_access_time; - unsigned m_line_fill_time; - cache_block_state m_status[SECTOR_CHUNCK_SIZE]; - bool m_ignore_on_fill_status[SECTOR_CHUNCK_SIZE]; - bool m_set_modified_on_fill[SECTOR_CHUNCK_SIZE]; - bool m_readable[SECTOR_CHUNCK_SIZE]; +private: + unsigned m_sector_alloc_time[SECTOR_CHUNCK_SIZE]; + unsigned m_last_sector_access_time[SECTOR_CHUNCK_SIZE]; + unsigned m_sector_fill_time[SECTOR_CHUNCK_SIZE]; + unsigned m_line_alloc_time; + unsigned m_line_last_access_time; + unsigned m_line_fill_time; + cache_block_state m_status[SECTOR_CHUNCK_SIZE]; + bool m_ignore_on_fill_status[SECTOR_CHUNCK_SIZE]; + bool m_set_modified_on_fill[SECTOR_CHUNCK_SIZE]; + bool m_readable[SECTOR_CHUNCK_SIZE]; - unsigned get_sector_index(mem_access_sector_mask_t sector_mask) { - assert(sector_mask.count() == 1); - for (unsigned i = 0; i < SECTOR_CHUNCK_SIZE; ++i) { - if (sector_mask.to_ulong() & (1 << i)) return i; + unsigned get_sector_index(mem_access_sector_mask_t sector_mask) + { + assert(sector_mask.count() == 1); + for(unsigned i =0; i< SECTOR_CHUNCK_SIZE; ++i) { + if(sector_mask.to_ulong() & (1<<i)) + return i; + } } - } }; -enum replacement_policy_t { LRU, FIFO }; +enum replacement_policy_t { + LRU, + FIFO +}; enum write_policy_t { - READ_ONLY, - WRITE_BACK, - WRITE_THROUGH, - WRITE_EVICT, - LOCAL_WB_GLOBAL_WT + READ_ONLY, + WRITE_BACK, + WRITE_THROUGH, + WRITE_EVICT, + LOCAL_WB_GLOBAL_WT +}; + +enum allocation_policy_t { + ON_MISS, + ON_FILL, + STREAMING }; -enum allocation_policy_t { ON_MISS, ON_FILL, STREAMING }; enum write_allocate_policy_t { - NO_WRITE_ALLOCATE, - WRITE_ALLOCATE, - FETCH_ON_WRITE, - LAZY_FETCH_ON_READ + NO_WRITE_ALLOCATE, + WRITE_ALLOCATE, + FETCH_ON_WRITE, + LAZY_FETCH_ON_READ }; enum mshr_config_t { - TEX_FIFO, // Tex cache - ASSOC, // normal cache - SECTOR_TEX_FIFO, // Tex cache sends requests to high-level sector cache - SECTOR_ASSOC // normal cache sends requests to high-level sector cache + TEX_FIFO, // Tex cache + ASSOC, // normal cache + SECTOR_TEX_FIFO, //Tex cache sends requests to high-level sector cache + SECTOR_ASSOC // normal cache sends requests to high-level sector cache }; -enum set_index_function { - LINEAR_SET_FUNCTION = 0, - BITWISE_XORING_FUNCTION, - HASH_IPOLY_FUNCTION, - FERMI_HASH_SET_FUNCTION, - CUSTOM_SET_FUNCTION +enum set_index_function{ + LINEAR_SET_FUNCTION = 0, + BITWISE_XORING_FUNCTION, + HASH_IPOLY_FUNCTION, + FERMI_HASH_SET_FUNCTION, + CUSTOM_SET_FUNCTION }; -enum cache_type { NORMAL = 0, SECTOR }; +enum cache_type{ + NORMAL = 0, + SECTOR +}; #define MAX_WARP_PER_SHADER 64 #define INCT_TOTAL_BUFFER 64 @@ -454,612 +496,542 @@ enum cache_type { NORMAL = 0, SECTOR }; #define MAX_WARP_PER_SHADER 64 class cache_config { - public: - cache_config() { - m_valid = false; - m_disabled = false; - m_config_string = NULL; // set by option parser - m_config_stringPrefL1 = NULL; - m_config_stringPrefShared = NULL; - m_data_port_width = 0; - m_set_index_function = LINEAR_SET_FUNCTION; - m_is_streaming = false; - } - void init(char *config, FuncCache status) { - cache_status = status; - assert(config); - char ct, rp, wp, ap, mshr_type, wap, sif; +public: + cache_config() + { + m_valid = false; + m_disabled = false; + m_config_string = NULL; // set by option parser + m_config_stringPrefL1 = NULL; + m_config_stringPrefShared = NULL; + m_data_port_width = 0; + m_set_index_function = LINEAR_SET_FUNCTION; + m_is_streaming = false; + } + void init(char * config, FuncCache status) + { + cache_status= status; + assert( config ); + char ct, rp, wp, ap, mshr_type, wap, sif; - int ntok = - sscanf(config, "%c:%u:%u:%u,%c:%c:%c:%c:%c,%c:%u:%u,%u:%u,%u", &ct, - &m_nset, &m_line_sz, &m_assoc, &rp, &wp, &ap, &wap, &sif, - &mshr_type, &m_mshr_entries, &m_mshr_max_merge, - &m_miss_queue_size, &m_result_fifo_entries, &m_data_port_width); - if (ntok < 12) { - if (!strcmp(config, "none")) { - m_disabled = true; - return; - } - exit_parse_error(); - } + int ntok = sscanf(config,"%c:%u:%u:%u,%c:%c:%c:%c:%c,%c:%u:%u,%u:%u,%u", + &ct, &m_nset, &m_line_sz, &m_assoc, &rp, &wp, &ap, &wap, + &sif,&mshr_type,&m_mshr_entries,&m_mshr_max_merge, + &m_miss_queue_size, &m_result_fifo_entries, + &m_data_port_width); - switch (ct) { - case 'N': - m_cache_type = NORMAL; - break; - case 'S': - m_cache_type = SECTOR; - break; - default: - exit_parse_error(); - } - switch (rp) { - case 'L': - m_replacement_policy = LRU; - break; - case 'F': - m_replacement_policy = FIFO; - break; - default: - exit_parse_error(); - } - switch (rp) { - case 'L': - m_replacement_policy = LRU; - break; - case 'F': - m_replacement_policy = FIFO; - break; - default: - exit_parse_error(); + if ( ntok < 12 ) { + if ( !strcmp(config,"none") ) { + m_disabled = true; + return; + } + exit_parse_error(); + } + + switch (ct) { + case 'N': m_cache_type = NORMAL; break; + case 'S': m_cache_type = SECTOR; break; + default: exit_parse_error(); + } + switch (rp) { + case 'L': m_replacement_policy = LRU; break; + case 'F': m_replacement_policy = FIFO; break; + default: exit_parse_error(); + } + switch (rp) { + case 'L': m_replacement_policy = LRU; break; + case 'F': m_replacement_policy = FIFO; break; + default: exit_parse_error(); + } + switch (wp) { + case 'R': m_write_policy = READ_ONLY; break; + case 'B': m_write_policy = WRITE_BACK; break; + case 'T': m_write_policy = WRITE_THROUGH; break; + case 'E': m_write_policy = WRITE_EVICT; break; + case 'L': m_write_policy = LOCAL_WB_GLOBAL_WT; break; + default: exit_parse_error(); + } + switch (ap) { + case 'm': m_alloc_policy = ON_MISS; break; + case 'f': m_alloc_policy = ON_FILL; break; + case 's': m_alloc_policy = STREAMING; break; + default: exit_parse_error(); + } + if(m_alloc_policy == STREAMING) { + //For streaming cache, we set the alloc policy to be on-fill to remove all line_alloc_fail stalls + //we set the MSHRs to be equal to max allocated cache lines. This is possible by moving TAG to be shared between cache line and MSHR enrty (i.e. for each cache line, there is an MSHR rntey associated with it) + //This is the easiest think we can think about to model (mimic) L1 streaming cache in Pascal and Volta + //Based on our microbenchmakrs, MSHRs entries have been increasing substantially in Pascal and Volta + //For more information about streaming cache, see: + // http://on-demand.gputechconf.com/gtc/2017/presentation/s7798-luke-durant-inside-volta.pdf + // https://ieeexplore.ieee.org/document/8344474/ + m_is_streaming = true; + m_alloc_policy = ON_FILL; + m_mshr_entries = m_nset*m_assoc*MAX_DEFAULT_CACHE_SIZE_MULTIBLIER; + if(m_cache_type == SECTOR) + m_mshr_entries *= SECTOR_CHUNCK_SIZE; + m_mshr_max_merge = MAX_WARP_PER_SM; + } + switch (mshr_type) { + case 'F': m_mshr_type = TEX_FIFO; assert(ntok==14); break; + case 'T': m_mshr_type = SECTOR_TEX_FIFO; assert(ntok==14); break; + case 'A': m_mshr_type = ASSOC; break; + case 'S' : m_mshr_type = SECTOR_ASSOC; break; + default: exit_parse_error(); + } + m_line_sz_log2 = LOGB2(m_line_sz); + m_nset_log2 = LOGB2(m_nset); + m_valid = true; + m_atom_sz = (m_cache_type == SECTOR)? SECTOR_SIZE : m_line_sz; + m_sector_sz_log2 = LOGB2(SECTOR_SIZE); + original_m_assoc = m_assoc; + + //For more details about difference between FETCH_ON_WRITE and WRITE VALIDAE policies + //Read: Jouppi, Norman P. "Cache write policies and performance". ISCA 93. + //WRITE_ALLOCATE is the old write policy in GPGPU-sim 3.x, that send WRITE and READ for every write request + switch(wap){ + case 'N': m_write_alloc_policy = NO_WRITE_ALLOCATE; break; + case 'W': m_write_alloc_policy = WRITE_ALLOCATE; break; + case 'F': m_write_alloc_policy = FETCH_ON_WRITE; break; + case 'L': m_write_alloc_policy = LAZY_FETCH_ON_READ; break; + default: exit_parse_error(); + } + + // detect invalid configuration + if (m_alloc_policy == ON_FILL and m_write_policy == WRITE_BACK) { + // A writeback cache with allocate-on-fill policy will inevitably lead to deadlock: + // The deadlock happens when an incoming cache-fill evicts a dirty + // line, generating a writeback request. If the memory subsystem + // is congested, the interconnection network may not have + // sufficient buffer for the writeback request. This stalls the + // incoming cache-fill. The stall may propagate through the memory + // subsystem back to the output port of the same core, creating a + // deadlock where the wrtieback request and the incoming cache-fill + // are stalling each other. + assert(0 && "Invalid cache configuration: Writeback cache cannot allocate new line on fill. "); + } + + if((m_write_alloc_policy == FETCH_ON_WRITE || m_write_alloc_policy == LAZY_FETCH_ON_READ )&& m_alloc_policy == ON_FILL) + { + assert(0 && "Invalid cache configuration: FETCH_ON_WRITE and LAZY_FETCH_ON_READ cannot work properly with ON_FILL policy. Cache must be ON_MISS. "); + } + if(m_cache_type == SECTOR) + { + assert(m_line_sz / SECTOR_SIZE == SECTOR_CHUNCK_SIZE && m_line_sz % SECTOR_SIZE == 0); + } + + // default: port to data array width and granularity = line size + if (m_data_port_width == 0) { + m_data_port_width = m_line_sz; + } + assert(m_line_sz % m_data_port_width == 0); + + switch(sif){ + case 'H': m_set_index_function = FERMI_HASH_SET_FUNCTION; break; + case 'P': m_set_index_function = HASH_IPOLY_FUNCTION; break; + case 'C': m_set_index_function = CUSTOM_SET_FUNCTION; break; + case 'L': m_set_index_function = LINEAR_SET_FUNCTION; break; + default: exit_parse_error(); + } } - switch (wp) { - case 'R': - m_write_policy = READ_ONLY; - break; - case 'B': - m_write_policy = WRITE_BACK; - break; - case 'T': - m_write_policy = WRITE_THROUGH; - break; - case 'E': - m_write_policy = WRITE_EVICT; - break; - case 'L': - m_write_policy = LOCAL_WB_GLOBAL_WT; - break; - default: - exit_parse_error(); + bool disabled() const { return m_disabled;} + unsigned get_line_sz() const + { + assert( m_valid ); + return m_line_sz; } - switch (ap) { - case 'm': - m_alloc_policy = ON_MISS; - break; - case 'f': - m_alloc_policy = ON_FILL; - break; - case 's': - m_alloc_policy = STREAMING; - break; - default: - exit_parse_error(); + unsigned get_atom_sz() const + { + assert( m_valid ); + return m_atom_sz; + } + unsigned get_num_lines() const + { + assert( m_valid ); + return m_nset * m_assoc; } - if (m_alloc_policy == STREAMING) { - // For streaming cache, we set the alloc policy to be on-fill to remove - // all line_alloc_fail stalls - // we set the MSHRs to be equal to max allocated cache lines. This is - // possible by moving TAG to be shared between cache line and MSHR enrty - // (i.e. for each cache line, there is an MSHR rntey associated with it) - // This is the easiest think we can think about to model (mimic) L1 - // streaming cache in Pascal and Volta - // Based on our microbenchmakrs, MSHRs entries have been increasing - // substantially in Pascal and Volta - // For more information about streaming cache, see: - // http://on-demand.gputechconf.com/gtc/2017/presentation/s7798-luke-durant-inside-volta.pdf - // https://ieeexplore.ieee.org/document/8344474/ - m_is_streaming = true; - m_alloc_policy = ON_FILL; - m_mshr_entries = m_nset * m_assoc * MAX_DEFAULT_CACHE_SIZE_MULTIBLIER; - if (m_cache_type == SECTOR) m_mshr_entries *= SECTOR_CHUNCK_SIZE; - m_mshr_max_merge = MAX_WARP_PER_SM; + unsigned get_max_num_lines() const + { + assert( m_valid ); + return MAX_DEFAULT_CACHE_SIZE_MULTIBLIER * m_nset * original_m_assoc; } - switch (mshr_type) { - case 'F': - m_mshr_type = TEX_FIFO; - assert(ntok == 14); - break; - case 'T': - m_mshr_type = SECTOR_TEX_FIFO; - assert(ntok == 14); - break; - case 'A': - m_mshr_type = ASSOC; - break; - case 'S': - m_mshr_type = SECTOR_ASSOC; - break; - default: - exit_parse_error(); + void print( FILE *fp ) const + { + fprintf( fp, "Size = %d B (%d Set x %d-way x %d byte line)\n", + m_line_sz * m_nset * m_assoc, + m_nset, m_assoc, m_line_sz ); } - m_line_sz_log2 = LOGB2(m_line_sz); - m_nset_log2 = LOGB2(m_nset); - m_valid = true; - m_atom_sz = (m_cache_type == SECTOR) ? SECTOR_SIZE : m_line_sz; - m_sector_sz_log2 = LOGB2(SECTOR_SIZE); - original_m_assoc = m_assoc; - // For more details about difference between FETCH_ON_WRITE and WRITE - // VALIDAE policies - // Read: Jouppi, Norman P. "Cache write policies and performance". ISCA 93. - // WRITE_ALLOCATE is the old write policy in GPGPU-sim 3.x, that send WRITE - // and READ for every write request - switch (wap) { - case 'N': - m_write_alloc_policy = NO_WRITE_ALLOCATE; - break; - case 'W': - m_write_alloc_policy = WRITE_ALLOCATE; - break; - case 'F': - m_write_alloc_policy = FETCH_ON_WRITE; - break; - case 'L': - m_write_alloc_policy = LAZY_FETCH_ON_READ; - break; - default: - exit_parse_error(); + virtual unsigned set_index( new_addr_type addr ) const + { + if(m_set_index_function != LINEAR_SET_FUNCTION){ + printf("\nGPGPU-Sim cache configuration error: Hashing or " + "custom set index function selected in configuration " + "file for a cache that has not overloaded the set_index " + "function\n"); + abort(); + } + return(addr >> m_line_sz_log2) & (m_nset-1); } - // detect invalid configuration - if (m_alloc_policy == ON_FILL and m_write_policy == WRITE_BACK) { - // A writeback cache with allocate-on-fill policy will inevitably lead to - // deadlock: - // The deadlock happens when an incoming cache-fill evicts a dirty - // line, generating a writeback request. If the memory subsystem - // is congested, the interconnection network may not have - // sufficient buffer for the writeback request. This stalls the - // incoming cache-fill. The stall may propagate through the memory - // subsystem back to the output port of the same core, creating a - // deadlock where the wrtieback request and the incoming cache-fill - // are stalling each other. - assert(0 && - "Invalid cache configuration: Writeback cache cannot allocate new " - "line on fill. "); - } + new_addr_type tag( new_addr_type addr ) const + { + // For generality, the tag includes both index and tag. This allows for more complex set index + // calculations that can result in different indexes mapping to the same set, thus the full + // tag + index is required to check for hit/miss. Tag is now identical to the block address. - if ((m_write_alloc_policy == FETCH_ON_WRITE || - m_write_alloc_policy == LAZY_FETCH_ON_READ) && - m_alloc_policy == ON_FILL) { - assert(0 && - "Invalid cache configuration: FETCH_ON_WRITE and " - "LAZY_FETCH_ON_READ cannot work properly with ON_FILL policy. " - "Cache must be ON_MISS. "); - } - if (m_cache_type == SECTOR) { - assert(m_line_sz / SECTOR_SIZE == SECTOR_CHUNCK_SIZE && - m_line_sz % SECTOR_SIZE == 0); + //return addr >> (m_line_sz_log2+m_nset_log2); + return addr & ~(new_addr_type)(m_line_sz-1); } - - // default: port to data array width and granularity = line size - if (m_data_port_width == 0) { - m_data_port_width = m_line_sz; + new_addr_type block_addr( new_addr_type addr ) const + { + return addr & ~(new_addr_type)(m_line_sz-1); } - assert(m_line_sz % m_data_port_width == 0); - - switch (sif) { - case 'H': - m_set_index_function = FERMI_HASH_SET_FUNCTION; - break; - case 'P': - m_set_index_function = HASH_IPOLY_FUNCTION; - break; - case 'C': - m_set_index_function = CUSTOM_SET_FUNCTION; - break; - case 'L': - m_set_index_function = LINEAR_SET_FUNCTION; - break; - default: - exit_parse_error(); + new_addr_type mshr_addr( new_addr_type addr ) const + { + return addr & ~(new_addr_type)(m_atom_sz-1); + } + enum mshr_config_t get_mshr_type() const + { + return m_mshr_type; + } + void set_assoc(unsigned n) + { + //set new assoc. L1 cache dynamically resized in Volta + m_assoc = n; + } + unsigned get_nset() const + { + assert( m_valid ); + return m_nset; + } + unsigned get_total_size_inKB() const + { + assert( m_valid ); + return (m_assoc*m_nset*m_line_sz)/1024; + } + bool is_streaming() { + return m_is_streaming; } - } - bool disabled() const { return m_disabled; } - unsigned get_line_sz() const { - assert(m_valid); - return m_line_sz; - } - unsigned get_atom_sz() const { - assert(m_valid); - return m_atom_sz; - } - unsigned get_num_lines() const { - assert(m_valid); - return m_nset * m_assoc; - } - unsigned get_max_num_lines() const { - assert(m_valid); - return MAX_DEFAULT_CACHE_SIZE_MULTIBLIER * m_nset * original_m_assoc; - } - void print(FILE *fp) const { - fprintf(fp, "Size = %d B (%d Set x %d-way x %d byte line)\n", - m_line_sz * m_nset * m_assoc, m_nset, m_assoc, m_line_sz); - } + FuncCache get_cache_status() {return cache_status;} + char *m_config_string; + char *m_config_stringPrefL1; + char *m_config_stringPrefShared; + FuncCache cache_status; - virtual unsigned set_index(new_addr_type addr) const { - if (m_set_index_function != LINEAR_SET_FUNCTION) { - printf( - "\nGPGPU-Sim cache configuration error: Hashing or " - "custom set index function selected in configuration " - "file for a cache that has not overloaded the set_index " - "function\n"); - abort(); +protected: + void exit_parse_error() + { + printf("GPGPU-Sim uArch: cache configuration parsing error (%s)\n", m_config_string ); + abort(); } - return (addr >> m_line_sz_log2) & (m_nset - 1); - } - - new_addr_type tag(new_addr_type addr) const { - // For generality, the tag includes both index and tag. This allows for more - // complex set index - // calculations that can result in different indexes mapping to the same - // set, thus the full - // tag + index is required to check for hit/miss. Tag is now identical to - // the block address. - // return addr >> (m_line_sz_log2+m_nset_log2); - return addr & ~(new_addr_type)(m_line_sz - 1); - } - new_addr_type block_addr(new_addr_type addr) const { - return addr & ~(new_addr_type)(m_line_sz - 1); - } - new_addr_type mshr_addr(new_addr_type addr) const { - return addr & ~(new_addr_type)(m_atom_sz - 1); - } - enum mshr_config_t get_mshr_type() const { return m_mshr_type; } - void set_assoc(unsigned n) { - // set new assoc. L1 cache dynamically resized in Volta - m_assoc = n; - } - unsigned get_nset() const { - assert(m_valid); - return m_nset; - } - unsigned get_total_size_inKB() const { - assert(m_valid); - return (m_assoc * m_nset * m_line_sz) / 1024; - } - bool is_streaming() { return m_is_streaming; } - FuncCache get_cache_status() { return cache_status; } - char *m_config_string; - char *m_config_stringPrefL1; - char *m_config_stringPrefShared; - FuncCache cache_status; - - protected: - void exit_parse_error() { - printf("GPGPU-Sim uArch: cache configuration parsing error (%s)\n", - m_config_string); - abort(); - } - - bool m_valid; - bool m_disabled; - unsigned m_line_sz; - unsigned m_line_sz_log2; - unsigned m_nset; - unsigned m_nset_log2; - unsigned m_assoc; - unsigned m_atom_sz; - unsigned m_sector_sz_log2; - unsigned original_m_assoc; - bool m_is_streaming; + bool m_valid; + bool m_disabled; + unsigned m_line_sz; + unsigned m_line_sz_log2; + unsigned m_nset; + unsigned m_nset_log2; + unsigned m_assoc; + unsigned m_atom_sz; + unsigned m_sector_sz_log2; + unsigned original_m_assoc; + bool m_is_streaming; - enum replacement_policy_t m_replacement_policy; // 'L' = LRU, 'F' = FIFO - enum write_policy_t - m_write_policy; // 'T' = write through, 'B' = write back, 'R' = read only - enum allocation_policy_t - m_alloc_policy; // 'm' = allocate on miss, 'f' = allocate on fill - enum mshr_config_t m_mshr_type; - enum cache_type m_cache_type; + enum replacement_policy_t m_replacement_policy; // 'L' = LRU, 'F' = FIFO + enum write_policy_t m_write_policy; // 'T' = write through, 'B' = write back, 'R' = read only + enum allocation_policy_t m_alloc_policy; // 'm' = allocate on miss, 'f' = allocate on fill + enum mshr_config_t m_mshr_type; + enum cache_type m_cache_type; - write_allocate_policy_t - m_write_alloc_policy; // 'W' = Write allocate, 'N' = No write allocate + write_allocate_policy_t m_write_alloc_policy; // 'W' = Write allocate, 'N' = No write allocate - union { - unsigned m_mshr_entries; - unsigned m_fragment_fifo_entries; - }; - union { - unsigned m_mshr_max_merge; - unsigned m_request_fifo_entries; - }; - union { - unsigned m_miss_queue_size; - unsigned m_rob_entries; - }; - unsigned m_result_fifo_entries; - unsigned m_data_port_width; //< number of byte the cache can access per cycle - enum set_index_function - m_set_index_function; // Hash, linear, or custom set index function + union { + unsigned m_mshr_entries; + unsigned m_fragment_fifo_entries; + }; + union { + unsigned m_mshr_max_merge; + unsigned m_request_fifo_entries; + }; + union { + unsigned m_miss_queue_size; + unsigned m_rob_entries; + }; + unsigned m_result_fifo_entries; + unsigned m_data_port_width; //< number of byte the cache can access per cycle + enum set_index_function m_set_index_function; // Hash, linear, or custom set index function - friend class tag_array; - friend class baseline_cache; - friend class read_only_cache; - friend class tex_cache; - friend class data_cache; - friend class l1_cache; - friend class l2_cache; - friend class memory_sub_partition; + friend class tag_array; + friend class baseline_cache; + friend class read_only_cache; + friend class tex_cache; + friend class data_cache; + friend class l1_cache; + friend class l2_cache; + friend class memory_sub_partition; }; -class l1d_cache_config : public cache_config { - public: - l1d_cache_config() : cache_config() {} - virtual unsigned set_index(new_addr_type addr) const; - unsigned set_bank(new_addr_type addr) const; - unsigned l1_latency; - unsigned l1_banks; +class l1d_cache_config : public cache_config{ +public: + l1d_cache_config() : cache_config(){} + virtual unsigned set_index(new_addr_type addr) const; + unsigned set_bank(new_addr_type addr) const; + unsigned l1_latency; + unsigned l1_banks; }; class l2_cache_config : public cache_config { - public: - l2_cache_config() : cache_config() {} - void init(linear_to_raw_address_translation *address_mapping); - virtual unsigned set_index(new_addr_type addr) const; +public: + l2_cache_config() : cache_config(){} + void init(linear_to_raw_address_translation *address_mapping); + virtual unsigned set_index(new_addr_type addr) const; - private: - linear_to_raw_address_translation *m_address_mapping; +private: + linear_to_raw_address_translation *m_address_mapping; }; class tag_array { - public: - // Use this constructor - tag_array(cache_config &config, int core_id, int type_id); - ~tag_array(); +public: + // Use this constructor + tag_array(cache_config &config, int core_id, int type_id ); + ~tag_array(); - enum cache_request_status probe(new_addr_type addr, unsigned &idx, - mem_fetch *mf, bool probe_mode = false) const; - enum cache_request_status probe(new_addr_type addr, unsigned &idx, - mem_access_sector_mask_t mask, - bool probe_mode = false, - mem_fetch *mf = NULL) const; - enum cache_request_status access(new_addr_type addr, unsigned time, - unsigned &idx, mem_fetch *mf); - enum cache_request_status access(new_addr_type addr, unsigned time, - unsigned &idx, bool &wb, - evicted_block_info &evicted, mem_fetch *mf); + enum cache_request_status probe( new_addr_type addr, unsigned &idx, mem_fetch* mf, bool probe_mode=false ) const; + enum cache_request_status probe( new_addr_type addr, unsigned &idx, mem_access_sector_mask_t mask, bool probe_mode=false, mem_fetch* mf = NULL ) const; + enum cache_request_status access( new_addr_type addr, unsigned time, unsigned &idx, mem_fetch* mf ); + enum cache_request_status access( new_addr_type addr, unsigned time, unsigned &idx, bool &wb, evicted_block_info &evicted, mem_fetch* mf ); - void fill(new_addr_type addr, unsigned time, mem_fetch *mf); - void fill(unsigned idx, unsigned time, mem_fetch *mf); - void fill(new_addr_type addr, unsigned time, mem_access_sector_mask_t mask); + void fill( new_addr_type addr, unsigned time, mem_fetch* mf ); + void fill( unsigned idx, unsigned time, mem_fetch* mf ); + void fill( new_addr_type addr, unsigned time, mem_access_sector_mask_t mask ); - unsigned size() const { return m_config.get_num_lines(); } - cache_block_t *get_block(unsigned idx) { return m_lines[idx]; } + unsigned size() const { return m_config.get_num_lines();} + cache_block_t* get_block(unsigned idx) { return m_lines[idx];} - void flush(); // flush all written entries - void invalidate(); // invalidate all entries - void new_window(); + void flush(); // flush all written entries + void invalidate(); // invalidate all entries + void new_window(); - void print(FILE *stream, unsigned &total_access, - unsigned &total_misses) const; - float windowed_miss_rate() const; - void get_stats(unsigned &total_access, unsigned &total_misses, - unsigned &total_hit_res, unsigned &total_res_fail) const; + void print( FILE *stream, unsigned &total_access, unsigned &total_misses ) const; + float windowed_miss_rate( ) const; + void get_stats(unsigned &total_access, unsigned &total_misses, unsigned &total_hit_res, unsigned &total_res_fail) const; - void update_cache_parameters(cache_config &config); - void add_pending_line(mem_fetch *mf); - void remove_pending_line(mem_fetch *mf); + void update_cache_parameters(cache_config &config); + void add_pending_line(mem_fetch *mf); + void remove_pending_line(mem_fetch *mf); +protected: + // This constructor is intended for use only from derived classes that wish to + // avoid unnecessary memory allocation that takes place in the + // other tag_array constructor + tag_array( cache_config &config, + int core_id, + int type_id, + cache_block_t** new_lines ); + void init( int core_id, int type_id ); - protected: - // This constructor is intended for use only from derived classes that wish to - // avoid unnecessary memory allocation that takes place in the - // other tag_array constructor - tag_array(cache_config &config, int core_id, int type_id, - cache_block_t **new_lines); - void init(int core_id, int type_id); +protected: - protected: - cache_config &m_config; + cache_config &m_config; - cache_block_t **m_lines; /* nbanks x nset x assoc lines in total */ + cache_block_t **m_lines; /* nbanks x nset x assoc lines in total */ - unsigned m_access; - unsigned m_miss; - unsigned m_pending_hit; // number of cache miss that hit a line that is - // allocated but not filled - unsigned m_res_fail; - unsigned m_sector_miss; + unsigned m_access; + unsigned m_miss; + unsigned m_pending_hit; // number of cache miss that hit a line that is allocated but not filled + unsigned m_res_fail; + unsigned m_sector_miss; - // performance counters for calculating the amount of misses within a time - // window - unsigned m_prev_snapshot_access; - unsigned m_prev_snapshot_miss; - unsigned m_prev_snapshot_pending_hit; + // performance counters for calculating the amount of misses within a time window + unsigned m_prev_snapshot_access; + unsigned m_prev_snapshot_miss; + unsigned m_prev_snapshot_pending_hit; - int m_core_id; // which shader core is using this - int m_type_id; // what kind of cache is this (normal, texture, constant) + int m_core_id; // which shader core is using this + int m_type_id; // what kind of cache is this (normal, texture, constant) - bool is_used; // a flag if the whole cache has ever been accessed before + bool is_used; //a flag if the whole cache has ever been accessed before - typedef tr1_hash_map<new_addr_type, unsigned> line_table; - line_table pending_lines; + typedef tr1_hash_map<new_addr_type,unsigned> line_table; + line_table pending_lines; }; class mshr_table { - public: - mshr_table(unsigned num_entries, unsigned max_merged) - : m_num_entries(num_entries), - m_max_merged(max_merged) +public: + mshr_table( unsigned num_entries, unsigned max_merged) + : m_num_entries(num_entries), + m_max_merged(max_merged) #if (tr1_hash_map_ismap == 0) - , - m_data(2 * num_entries) + ,m_data(2*num_entries) #endif - { - } + { + } + + /// Checks if there is a pending request to the lower memory level already + bool probe( new_addr_type block_addr ) const; + /// Checks if there is space for tracking a new memory access + bool full( new_addr_type block_addr ) const; + /// Add or merge this access + void add( new_addr_type block_addr, mem_fetch *mf ); + /// Returns true if cannot accept new fill responses + bool busy() const {return false;} + /// Accept a new cache fill response: mark entry ready for processing + void mark_ready( new_addr_type block_addr, bool &has_atomic ); + /// Returns true if ready accesses exist + bool access_ready() const {return !m_current_response.empty();} + /// Returns next ready access + mem_fetch *next_access(); + void display( FILE *fp ) const; + // Returns true if there is a pending read after write + bool is_read_after_write_pending(new_addr_type block_addr); - /// Checks if there is a pending request to the lower memory level already - bool probe(new_addr_type block_addr) const; - /// Checks if there is space for tracking a new memory access - bool full(new_addr_type block_addr) const; - /// Add or merge this access - void add(new_addr_type block_addr, mem_fetch *mf); - /// Returns true if cannot accept new fill responses - bool busy() const { return false; } - /// Accept a new cache fill response: mark entry ready for processing - void mark_ready(new_addr_type block_addr, bool &has_atomic); - /// Returns true if ready accesses exist - bool access_ready() const { return !m_current_response.empty(); } - /// Returns next ready access - mem_fetch *next_access(); - void display(FILE *fp) const; - // Returns true if there is a pending read after write - bool is_read_after_write_pending(new_addr_type block_addr); + void check_mshr_parameters( unsigned num_entries, unsigned max_merged ) + { + assert(m_num_entries==num_entries && "Change of MSHR parameters between kernels is not allowed"); + assert(m_max_merged==max_merged && "Change of MSHR parameters between kernels is not allowed"); + } - void check_mshr_parameters(unsigned num_entries, unsigned max_merged) { - assert(m_num_entries == num_entries && - "Change of MSHR parameters between kernels is not allowed"); - assert(m_max_merged == max_merged && - "Change of MSHR parameters between kernels is not allowed"); - } +private: - private: - // finite sized, fully associative table, with a finite maximum number of - // merged requests - const unsigned m_num_entries; - const unsigned m_max_merged; + // finite sized, fully associative table, with a finite maximum number of merged requests + const unsigned m_num_entries; + const unsigned m_max_merged; - struct mshr_entry { - std::list<mem_fetch *> m_list; - bool m_has_atomic; - mshr_entry() : m_has_atomic(false) {} - }; - typedef tr1_hash_map<new_addr_type, mshr_entry> table; - typedef tr1_hash_map<new_addr_type, mshr_entry> line_table; - table m_data; - line_table pending_lines; + struct mshr_entry { + std::list<mem_fetch*> m_list; + bool m_has_atomic; + mshr_entry() : m_has_atomic(false) { } + }; + typedef tr1_hash_map<new_addr_type,mshr_entry> table; + typedef tr1_hash_map<new_addr_type,mshr_entry> line_table; + table m_data; + line_table pending_lines; - // it may take several cycles to process the merged requests - bool m_current_response_ready; - std::list<new_addr_type> m_current_response; + // it may take several cycles to process the merged requests + bool m_current_response_ready; + std::list<new_addr_type> m_current_response; }; -/***************************************************************** Caches - * *****************************************************************/ + +/***************************************************************** Caches *****************************************************************/ /// -/// Simple struct to maintain cache accesses, misses, pending hits, and -/// reservation fails. +/// Simple struct to maintain cache accesses, misses, pending hits, and reservation fails. /// -struct cache_sub_stats { - unsigned long long accesses; - unsigned long long misses; - unsigned long long pending_hits; - unsigned long long res_fails; +struct cache_sub_stats{ + unsigned long long accesses; + unsigned long long misses; + unsigned long long pending_hits; + unsigned long long res_fails; - unsigned long long port_available_cycles; - unsigned long long data_port_busy_cycles; - unsigned long long fill_port_busy_cycles; + unsigned long long port_available_cycles; + unsigned long long data_port_busy_cycles; + unsigned long long fill_port_busy_cycles; - cache_sub_stats() { clear(); } - void clear() { - accesses = 0; - misses = 0; - pending_hits = 0; - res_fails = 0; - port_available_cycles = 0; - data_port_busy_cycles = 0; - fill_port_busy_cycles = 0; - } - cache_sub_stats &operator+=(const cache_sub_stats &css) { - /// - /// Overloading += operator to easily accumulate stats - /// - accesses += css.accesses; - misses += css.misses; - pending_hits += css.pending_hits; - res_fails += css.res_fails; - port_available_cycles += css.port_available_cycles; - data_port_busy_cycles += css.data_port_busy_cycles; - fill_port_busy_cycles += css.fill_port_busy_cycles; - return *this; - } + cache_sub_stats(){ + clear(); + } + void clear(){ + accesses = 0; + misses = 0; + pending_hits = 0; + res_fails = 0; + port_available_cycles = 0; + data_port_busy_cycles = 0; + fill_port_busy_cycles = 0; + } + cache_sub_stats &operator+=(const cache_sub_stats &css){ + /// + /// Overloading += operator to easily accumulate stats + /// + accesses += css.accesses; + misses += css.misses; + pending_hits += css.pending_hits; + res_fails += css.res_fails; + port_available_cycles += css.port_available_cycles; + data_port_busy_cycles += css.data_port_busy_cycles; + fill_port_busy_cycles += css.fill_port_busy_cycles; + return *this; + } - cache_sub_stats operator+(const cache_sub_stats &cs) { - /// - /// Overloading + operator to easily accumulate stats - /// - cache_sub_stats ret; - ret.accesses = accesses + cs.accesses; - ret.misses = misses + cs.misses; - ret.pending_hits = pending_hits + cs.pending_hits; - ret.res_fails = res_fails + cs.res_fails; - ret.port_available_cycles = - port_available_cycles + cs.port_available_cycles; - ret.data_port_busy_cycles = - data_port_busy_cycles + cs.data_port_busy_cycles; - ret.fill_port_busy_cycles = - fill_port_busy_cycles + cs.fill_port_busy_cycles; - return ret; - } + cache_sub_stats operator+(const cache_sub_stats &cs){ + /// + /// Overloading + operator to easily accumulate stats + /// + cache_sub_stats ret; + ret.accesses = accesses + cs.accesses; + ret.misses = misses + cs.misses; + ret.pending_hits = pending_hits + cs.pending_hits; + ret.res_fails = res_fails + cs.res_fails; + ret.port_available_cycles = port_available_cycles + cs.port_available_cycles; + ret.data_port_busy_cycles = data_port_busy_cycles + cs.data_port_busy_cycles; + ret.fill_port_busy_cycles = fill_port_busy_cycles + cs.fill_port_busy_cycles; + return ret; + } - void print_port_stats(FILE *fout, const char *cache_name) const; + void print_port_stats(FILE *fout, const char *cache_name) const; }; + // Used for collecting AerialVision per-window statistics -struct cache_sub_stats_pw { - unsigned accesses; - unsigned write_misses; - unsigned write_hits; - unsigned write_pending_hits; - unsigned write_res_fails; +struct cache_sub_stats_pw{ + unsigned accesses; + unsigned write_misses; + unsigned write_hits; + unsigned write_pending_hits; + unsigned write_res_fails; - unsigned read_misses; - unsigned read_hits; - unsigned read_pending_hits; - unsigned read_res_fails; + unsigned read_misses; + unsigned read_hits; + unsigned read_pending_hits; + unsigned read_res_fails; + + cache_sub_stats_pw(){ + clear(); + } + void clear(){ + accesses = 0; + write_misses = 0; + write_hits = 0; + write_pending_hits = 0; + write_res_fails = 0; + read_misses = 0; + read_hits = 0; + read_pending_hits = 0; + read_res_fails = 0; + } + cache_sub_stats_pw &operator+=(const cache_sub_stats_pw &css){ + /// + /// Overloading += operator to easily accumulate stats + /// + accesses += css.accesses; + write_misses += css.write_misses; + read_misses += css.read_misses; + write_pending_hits += css.write_pending_hits; + read_pending_hits += css.read_pending_hits; + write_res_fails += css.write_res_fails; + read_res_fails += css.read_res_fails; + return *this; + } - cache_sub_stats_pw() { clear(); } - void clear() { - accesses = 0; - write_misses = 0; - write_hits = 0; - write_pending_hits = 0; - write_res_fails = 0; - read_misses = 0; - read_hits = 0; - read_pending_hits = 0; - read_res_fails = 0; - } - cache_sub_stats_pw &operator+=(const cache_sub_stats_pw &css) { - /// - /// Overloading += operator to easily accumulate stats - /// - accesses += css.accesses; - write_misses += css.write_misses; - read_misses += css.read_misses; - write_pending_hits += css.write_pending_hits; - read_pending_hits += css.read_pending_hits; - write_res_fails += css.write_res_fails; - read_res_fails += css.read_res_fails; - return *this; - } + cache_sub_stats_pw operator+(const cache_sub_stats_pw &cs){ + /// + /// Overloading + operator to easily accumulate stats + /// + cache_sub_stats_pw ret; + ret.accesses = accesses + cs.accesses; + ret.write_misses = write_misses + cs.write_misses; + ret.read_misses = read_misses + cs.read_misses; + ret.write_pending_hits = write_pending_hits + cs.write_pending_hits; + ret.read_pending_hits = read_pending_hits + cs.read_pending_hits; + ret.write_res_fails = write_res_fails + cs.write_res_fails; + ret.read_res_fails = read_res_fails + cs.read_res_fails; + return ret; + } - cache_sub_stats_pw operator+(const cache_sub_stats_pw &cs) { - /// - /// Overloading + operator to easily accumulate stats - /// - cache_sub_stats_pw ret; - ret.accesses = accesses + cs.accesses; - ret.write_misses = write_misses + cs.write_misses; - ret.read_misses = read_misses + cs.read_misses; - ret.write_pending_hits = write_pending_hits + cs.write_pending_hits; - ret.read_pending_hits = read_pending_hits + cs.read_pending_hits; - ret.write_res_fails = write_res_fails + cs.write_res_fails; - ret.read_res_fails = read_res_fails + cs.read_res_fails; - return ret; - } }; + /// /// Cache_stats /// Used to record statistics for each cache. @@ -1067,469 +1039,484 @@ struct cache_sub_stats_pw { /// 'cache_request_status' : [mem_access_type][cache_request_status] /// class cache_stats { - public: - cache_stats(); - void clear(); - // Clear AerialVision cache stats after each window - void clear_pw(); - void inc_stats(int access_type, int access_outcome); - // Increment AerialVision cache stats - void inc_stats_pw(int access_type, int access_outcome); - void inc_fail_stats(int access_type, int fail_outcome); - enum cache_request_status select_stats_status( - enum cache_request_status probe, enum cache_request_status access) const; - unsigned long long &operator()(int access_type, int access_outcome, - bool fail_outcome); - unsigned long long operator()(int access_type, int access_outcome, - bool fail_outcome) const; - cache_stats operator+(const cache_stats &cs); - cache_stats &operator+=(const cache_stats &cs); - void print_stats(FILE *fout, const char *cache_name = "Cache_stats") const; - void print_fail_stats(FILE *fout, - const char *cache_name = "Cache_fail_stats") const; +public: + cache_stats(); + void clear(); + // Clear AerialVision cache stats after each window + void clear_pw(); + void inc_stats(int access_type, int access_outcome); + // Increment AerialVision cache stats + void inc_stats_pw(int access_type, int access_outcome); + void inc_fail_stats(int access_type, int fail_outcome); + enum cache_request_status select_stats_status(enum cache_request_status probe, enum cache_request_status access) const; + unsigned long long &operator()(int access_type, int access_outcome, bool fail_outcome); + unsigned long long operator()(int access_type, int access_outcome, bool fail_outcome) const; + cache_stats operator+(const cache_stats &cs); + cache_stats &operator+=(const cache_stats &cs); + void print_stats(FILE *fout, const char *cache_name = "Cache_stats") const; + void print_fail_stats(FILE *fout, const char *cache_name = "Cache_fail_stats") const; - unsigned long long get_stats(enum mem_access_type *access_type, - unsigned num_access_type, - enum cache_request_status *access_status, - unsigned num_access_status) const; - void get_sub_stats(struct cache_sub_stats &css) const; + unsigned long long get_stats(enum mem_access_type *access_type, unsigned num_access_type, enum cache_request_status *access_status, unsigned num_access_status) const; + void get_sub_stats(struct cache_sub_stats &css) const; - // Get per-window cache stats for AerialVision - void get_sub_stats_pw(struct cache_sub_stats_pw &css) const; + // Get per-window cache stats for AerialVision + void get_sub_stats_pw(struct cache_sub_stats_pw &css) const; - void sample_cache_port_utility(bool data_port_busy, bool fill_port_busy); + void sample_cache_port_utility(bool data_port_busy, bool fill_port_busy); +private: + bool check_valid(int type, int status) const; + bool check_fail_valid(int type, int fail) const; - private: - bool check_valid(int type, int status) const; - bool check_fail_valid(int type, int fail) const; - std::vector<std::vector<unsigned long long> > m_stats; - // AerialVision cache stats (per-window) - std::vector<std::vector<unsigned long long> > m_stats_pw; - std::vector<std::vector<unsigned long long> > m_fail_stats; + std::vector< std::vector<unsigned long long> > m_stats; + // AerialVision cache stats (per-window) + std::vector< std::vector<unsigned long long> > m_stats_pw; + std::vector< std::vector<unsigned long long> > m_fail_stats; - unsigned long long m_cache_port_available_cycles; - unsigned long long m_cache_data_port_busy_cycles; - unsigned long long m_cache_fill_port_busy_cycles; + unsigned long long m_cache_port_available_cycles; + unsigned long long m_cache_data_port_busy_cycles; + unsigned long long m_cache_fill_port_busy_cycles; }; class cache_t { - public: - virtual ~cache_t() {} - virtual enum cache_request_status access(new_addr_type addr, mem_fetch *mf, - unsigned time, - std::list<cache_event> &events) = 0; +public: + virtual ~cache_t() {} + virtual enum cache_request_status access( new_addr_type addr, mem_fetch *mf, unsigned time, std::list<cache_event> &events ) = 0; - // accessors for cache bandwidth availability - virtual bool data_port_free() const = 0; - virtual bool fill_port_free() const = 0; + // accessors for cache bandwidth availability + virtual bool data_port_free() const = 0; + virtual bool fill_port_free() const = 0; }; -bool was_write_sent(const std::list<cache_event> &events); -bool was_read_sent(const std::list<cache_event> &events); -bool was_writeallocate_sent(const std::list<cache_event> &events); +bool was_write_sent( const std::list<cache_event> &events ); +bool was_read_sent( const std::list<cache_event> &events ); +bool was_writeallocate_sent( const std::list<cache_event> &events ); /// Baseline cache /// Implements common functions for read_only_cache and data_cache /// Each subclass implements its own 'access' function class baseline_cache : public cache_t { - public: - baseline_cache(const char *name, cache_config &config, int core_id, - int type_id, mem_fetch_interface *memport, - enum mem_fetch_status status) - : m_config(config), - m_tag_array(new tag_array(config, core_id, type_id)), - m_mshrs(config.m_mshr_entries, config.m_mshr_max_merge), - m_bandwidth_management(config) { - init(name, config, memport, status); - } +public: + baseline_cache( const char *name, cache_config &config, int core_id, int type_id, mem_fetch_interface *memport, + enum mem_fetch_status status ) + : m_config(config), m_tag_array(new tag_array(config,core_id,type_id)), + m_mshrs(config.m_mshr_entries,config.m_mshr_max_merge), + m_bandwidth_management(config) + { + init( name, config, memport, status ); + } - void init(const char *name, const cache_config &config, - mem_fetch_interface *memport, enum mem_fetch_status status) { - m_name = name; - assert(config.m_mshr_type == ASSOC || config.m_mshr_type == SECTOR_ASSOC); - m_memport = memport; - m_miss_queue_status = status; - } + void init( const char *name, + const cache_config &config, + mem_fetch_interface *memport, + enum mem_fetch_status status ) + { + m_name = name; + assert(config.m_mshr_type == ASSOC || config.m_mshr_type == SECTOR_ASSOC); + m_memport=memport; + m_miss_queue_status = status; + } - virtual ~baseline_cache() { delete m_tag_array; } + virtual ~baseline_cache() + { + delete m_tag_array; + } - void update_cache_parameters(cache_config &config) { - m_config = config; - m_tag_array->update_cache_parameters(config); - m_mshrs.check_mshr_parameters(config.m_mshr_entries, - config.m_mshr_max_merge); - } + void update_cache_parameters(cache_config &config) + { + m_config=config; + m_tag_array->update_cache_parameters(config); + m_mshrs.check_mshr_parameters(config.m_mshr_entries,config.m_mshr_max_merge); + } - virtual enum cache_request_status access(new_addr_type addr, mem_fetch *mf, - unsigned time, - std::list<cache_event> &events) = 0; - /// Sends next request to lower level of memory - void cycle(); - /// Interface for response from lower memory level (model bandwidth - /// restictions in caller) - void fill(mem_fetch *mf, unsigned time); - /// Checks if mf is waiting to be filled by lower memory level - bool waiting_for_fill(mem_fetch *mf); - /// Are any (accepted) accesses that had to wait for memory now ready? (does - /// not include accesses that "HIT") - bool access_ready() const { return m_mshrs.access_ready(); } - /// Pop next ready access (does not include accesses that "HIT") - mem_fetch *next_access() { return m_mshrs.next_access(); } - // flash invalidate all entries in cache - void flush() { m_tag_array->flush(); } - void invalidate() { m_tag_array->invalidate(); } - void print(FILE *fp, unsigned &accesses, unsigned &misses) const; - void display_state(FILE *fp) const; + virtual enum cache_request_status access( new_addr_type addr, mem_fetch *mf, unsigned time, std::list<cache_event> &events ) = 0; + /// Sends next request to lower level of memory + void cycle(); + /// Interface for response from lower memory level (model bandwidth restictions in caller) + void fill( mem_fetch *mf, unsigned time ); + /// Checks if mf is waiting to be filled by lower memory level + bool waiting_for_fill( mem_fetch *mf ); + /// Are any (accepted) accesses that had to wait for memory now ready? (does not include accesses that "HIT") + bool access_ready() const {return m_mshrs.access_ready();} + /// Pop next ready access (does not include accesses that "HIT") + mem_fetch *next_access(){return m_mshrs.next_access();} + // flash invalidate all entries in cache + void flush(){m_tag_array->flush();} + void invalidate(){m_tag_array->invalidate();} + void print(FILE *fp, unsigned &accesses, unsigned &misses) const; + void display_state( FILE *fp ) const; - // Stat collection - const cache_stats &get_stats() const { return m_stats; } - unsigned get_stats(enum mem_access_type *access_type, - unsigned num_access_type, - enum cache_request_status *access_status, - unsigned num_access_status) const { - return m_stats.get_stats(access_type, num_access_type, access_status, - num_access_status); - } - void get_sub_stats(struct cache_sub_stats &css) const { - m_stats.get_sub_stats(css); - } - // Clear per-window stats for AerialVision support - void clear_pw() { m_stats.clear_pw(); } - // Per-window sub stats for AerialVision support - void get_sub_stats_pw(struct cache_sub_stats_pw &css) const { - m_stats.get_sub_stats_pw(css); - } + // Stat collection + const cache_stats &get_stats() const { + return m_stats; + } + unsigned get_stats(enum mem_access_type *access_type, unsigned num_access_type, enum cache_request_status *access_status, unsigned num_access_status) const{ + return m_stats.get_stats(access_type, num_access_type, access_status, num_access_status); + } + void get_sub_stats(struct cache_sub_stats &css) const { + m_stats.get_sub_stats(css); + } + // Clear per-window stats for AerialVision support + void clear_pw(){ + m_stats.clear_pw(); + } + // Per-window sub stats for AerialVision support + void get_sub_stats_pw(struct cache_sub_stats_pw &css) const { + m_stats.get_sub_stats_pw(css); + } - // accessors for cache bandwidth availability - bool data_port_free() const { - return m_bandwidth_management.data_port_free(); - } - bool fill_port_free() const { - return m_bandwidth_management.fill_port_free(); - } + // accessors for cache bandwidth availability + bool data_port_free() const { return m_bandwidth_management.data_port_free(); } + bool fill_port_free() const { return m_bandwidth_management.fill_port_free(); } - // This is a gapping hole we are poking in the system to quickly handle - // filling the cache on cudamemcopies. We don't care about anything other than - // L2 state after the memcopy - so just force the tag array to act as though - // something is read or written without doing anything else. - void force_tag_access(new_addr_type addr, unsigned time, - mem_access_sector_mask_t mask) { - m_tag_array->fill(addr, time, mask); - } + // This is a gapping hole we are poking in the system to quickly handle + // filling the cache on cudamemcopies. We don't care about anything other than + // L2 state after the memcopy - so just force the tag array to act as though + // something is read or written without doing anything else. + void force_tag_access( new_addr_type addr, unsigned time, mem_access_sector_mask_t mask ) + { + m_tag_array->fill( addr, time, mask ); + } - protected: - // Constructor that can be used by derived classes with custom tag arrays - baseline_cache(const char *name, cache_config &config, int core_id, - int type_id, mem_fetch_interface *memport, - enum mem_fetch_status status, tag_array *new_tag_array) - : m_config(config), - m_tag_array(new_tag_array), - m_mshrs(config.m_mshr_entries, config.m_mshr_max_merge), - m_bandwidth_management(config) { - init(name, config, memport, status); - } +protected: + // Constructor that can be used by derived classes with custom tag arrays + baseline_cache( const char *name, + cache_config &config, + int core_id, + int type_id, + mem_fetch_interface *memport, + enum mem_fetch_status status, + tag_array* new_tag_array ) + : m_config(config), + m_tag_array( new_tag_array ), + m_mshrs(config.m_mshr_entries,config.m_mshr_max_merge), + m_bandwidth_management(config) + { + init( name, config, memport, status ); + } - protected: - std::string m_name; - cache_config &m_config; - tag_array *m_tag_array; - mshr_table m_mshrs; - std::list<mem_fetch *> m_miss_queue; - enum mem_fetch_status m_miss_queue_status; - mem_fetch_interface *m_memport; +protected: + std::string m_name; + cache_config &m_config; + tag_array* m_tag_array; + mshr_table m_mshrs; + std::list<mem_fetch*> m_miss_queue; + enum mem_fetch_status m_miss_queue_status; + mem_fetch_interface *m_memport; - struct extra_mf_fields { - extra_mf_fields() { m_valid = false; } - extra_mf_fields(new_addr_type a, new_addr_type ad, unsigned i, unsigned d, - const cache_config &m_config) { - m_valid = true; - m_block_addr = a; - m_addr = ad; - m_cache_index = i; - m_data_size = d; - pending_read = m_config.m_mshr_type == SECTOR_ASSOC - ? m_config.m_line_sz / SECTOR_SIZE - : 0; - } - bool m_valid; - new_addr_type m_block_addr; - new_addr_type m_addr; - unsigned m_cache_index; - unsigned m_data_size; - // this variable is used when a load request generates multiple load - // transactions - // For example, a read request from non-sector L1 request sends a request to - // sector L2 - unsigned pending_read; - }; + struct extra_mf_fields { + extra_mf_fields() { m_valid = false;} + extra_mf_fields( new_addr_type a, new_addr_type ad, unsigned i, unsigned d, const cache_config& m_config) + { + m_valid = true; + m_block_addr = a; + m_addr = ad; + m_cache_index = i; + m_data_size = d; + pending_read = m_config.m_mshr_type == SECTOR_ASSOC? m_config.m_line_sz/SECTOR_SIZE : 0; - typedef std::map<mem_fetch *, extra_mf_fields> extra_mf_fields_lookup; + } + bool m_valid; + new_addr_type m_block_addr; + new_addr_type m_addr; + unsigned m_cache_index; + unsigned m_data_size; + //this variable is used when a load request generates multiple load transactions + //For example, a read request from non-sector L1 request sends a request to sector L2 + unsigned pending_read; + }; - extra_mf_fields_lookup m_extra_mf_fields; + typedef std::map<mem_fetch*,extra_mf_fields> extra_mf_fields_lookup; - cache_stats m_stats; + extra_mf_fields_lookup m_extra_mf_fields; - /// Checks whether this request can be handled on this cycle. num_miss equals - /// max # of misses to be handled on this cycle - bool miss_queue_full(unsigned num_miss) { - return ((m_miss_queue.size() + num_miss) >= m_config.m_miss_queue_size); - } - /// Read miss handler without writeback - void send_read_request(new_addr_type addr, new_addr_type block_addr, - unsigned cache_index, mem_fetch *mf, unsigned time, - bool &do_miss, std::list<cache_event> &events, - bool read_only, bool wa); - /// Read miss handler. Check MSHR hit or MSHR available - void send_read_request(new_addr_type addr, new_addr_type block_addr, - unsigned cache_index, mem_fetch *mf, unsigned time, - bool &do_miss, bool &wb, evicted_block_info &evicted, - std::list<cache_event> &events, bool read_only, - bool wa); + cache_stats m_stats; - /// Sub-class containing all metadata for port bandwidth management - class bandwidth_management { - public: - bandwidth_management(cache_config &config); + /// Checks whether this request can be handled on this cycle. num_miss equals max # of misses to be handled on this cycle + bool miss_queue_full(unsigned num_miss){ + return ( (m_miss_queue.size()+num_miss) >= m_config.m_miss_queue_size ); + } + /// Read miss handler without writeback + void send_read_request(new_addr_type addr, new_addr_type block_addr, unsigned cache_index, mem_fetch *mf, + unsigned time, bool &do_miss, std::list<cache_event> &events, bool read_only, bool wa); + /// Read miss handler. Check MSHR hit or MSHR available + void send_read_request(new_addr_type addr, new_addr_type block_addr, unsigned cache_index, mem_fetch *mf, + unsigned time, bool &do_miss, bool &wb, evicted_block_info &evicted, std::list<cache_event> &events, bool read_only, bool wa); - /// use the data port based on the outcome and events generated by the - /// mem_fetch request - void use_data_port(mem_fetch *mf, enum cache_request_status outcome, - const std::list<cache_event> &events); + /// Sub-class containing all metadata for port bandwidth management + class bandwidth_management + { + public: + bandwidth_management(cache_config &config); - /// use the fill port - void use_fill_port(mem_fetch *mf); + /// use the data port based on the outcome and events generated by the mem_fetch request + void use_data_port(mem_fetch *mf, enum cache_request_status outcome, const std::list<cache_event> &events); - /// called every cache cycle to free up the ports - void replenish_port_bandwidth(); + /// use the fill port + void use_fill_port(mem_fetch *mf); - /// query for data port availability - bool data_port_free() const; - /// query for fill port availability - bool fill_port_free() const; + /// called every cache cycle to free up the ports + void replenish_port_bandwidth(); - protected: - const cache_config &m_config; + /// query for data port availability + bool data_port_free() const; + /// query for fill port availability + bool fill_port_free() const; + protected: + const cache_config &m_config; - int m_data_port_occupied_cycles; //< Number of cycle that the data port - //remains used - int m_fill_port_occupied_cycles; //< Number of cycle that the fill port - //remains used - }; + int m_data_port_occupied_cycles; //< Number of cycle that the data port remains used + int m_fill_port_occupied_cycles; //< Number of cycle that the fill port remains used + }; - bandwidth_management m_bandwidth_management; + bandwidth_management m_bandwidth_management; }; /// Read only cache class read_only_cache : public baseline_cache { - public: - read_only_cache(const char *name, cache_config &config, int core_id, - int type_id, mem_fetch_interface *memport, - enum mem_fetch_status status) - : baseline_cache(name, config, core_id, type_id, memport, status) {} +public: + read_only_cache( const char *name, cache_config &config, int core_id, int type_id, mem_fetch_interface *memport, enum mem_fetch_status status ) + : baseline_cache(name,config,core_id,type_id,memport,status){} - /// Access cache for read_only_cache: returns RESERVATION_FAIL if request - /// could not be accepted (for any reason) - virtual enum cache_request_status access(new_addr_type addr, mem_fetch *mf, - unsigned time, - std::list<cache_event> &events); + /// Access cache for read_only_cache: returns RESERVATION_FAIL if request could not be accepted (for any reason) + virtual enum cache_request_status access( new_addr_type addr, mem_fetch *mf, unsigned time, std::list<cache_event> &events ); - virtual ~read_only_cache() {} + virtual ~read_only_cache(){} - protected: - read_only_cache(const char *name, cache_config &config, int core_id, - int type_id, mem_fetch_interface *memport, - enum mem_fetch_status status, tag_array *new_tag_array) - : baseline_cache(name, config, core_id, type_id, memport, status, - new_tag_array) {} +protected: + read_only_cache( const char *name, cache_config &config, int core_id, int type_id, mem_fetch_interface *memport, enum mem_fetch_status status, tag_array* new_tag_array ) + : baseline_cache(name,config,core_id,type_id,memport,status, new_tag_array){} }; /// Data cache - Implements common functions for L1 and L2 data cache class data_cache : public baseline_cache { - public: - data_cache(const char *name, cache_config &config, int core_id, int type_id, - mem_fetch_interface *memport, mem_fetch_allocator *mfcreator, - enum mem_fetch_status status, mem_access_type wr_alloc_type, - mem_access_type wrbk_type, class gpgpu_sim *gpu) - : baseline_cache(name, config, core_id, type_id, memport, status) { - init(mfcreator); - m_wr_alloc_type = wr_alloc_type; - m_wrbk_type = wrbk_type; - m_gpu = gpu; - } +public: + data_cache( const char *name, cache_config &config, + int core_id, int type_id, mem_fetch_interface *memport, + mem_fetch_allocator *mfcreator, enum mem_fetch_status status, + mem_access_type wr_alloc_type, mem_access_type wrbk_type, class gpgpu_sim* gpu ) + : baseline_cache(name,config,core_id,type_id,memport,status) + { + init( mfcreator ); + m_wr_alloc_type = wr_alloc_type; + m_wrbk_type = wrbk_type; + m_gpu=gpu; + } - virtual ~data_cache() {} + virtual ~data_cache() {} - virtual void init(mem_fetch_allocator *mfcreator) { - m_memfetch_creator = mfcreator; + virtual void init( mem_fetch_allocator *mfcreator ) + { + m_memfetch_creator=mfcreator; - // Set read hit function - m_rd_hit = &data_cache::rd_hit_base; + // Set read hit function + m_rd_hit = &data_cache::rd_hit_base; - // Set read miss function - m_rd_miss = &data_cache::rd_miss_base; + // Set read miss function + m_rd_miss = &data_cache::rd_miss_base; - // Set write hit function - switch (m_config.m_write_policy) { - // READ_ONLY is now a separate cache class, config is deprecated - case READ_ONLY: - assert(0 && "Error: Writable Data_cache set as READ_ONLY\n"); - break; - case WRITE_BACK: - m_wr_hit = &data_cache::wr_hit_wb; - break; - case WRITE_THROUGH: - m_wr_hit = &data_cache::wr_hit_wt; - break; - case WRITE_EVICT: - m_wr_hit = &data_cache::wr_hit_we; - break; - case LOCAL_WB_GLOBAL_WT: - m_wr_hit = &data_cache::wr_hit_global_we_local_wb; - break; - default: - assert(0 && "Error: Must set valid cache write policy\n"); - break; // Need to set a write hit function + // Set write hit function + switch(m_config.m_write_policy){ + // READ_ONLY is now a separate cache class, config is deprecated + case READ_ONLY: + assert(0 && "Error: Writable Data_cache set as READ_ONLY\n"); + break; + case WRITE_BACK: m_wr_hit = &data_cache::wr_hit_wb; break; + case WRITE_THROUGH: m_wr_hit = &data_cache::wr_hit_wt; break; + case WRITE_EVICT: m_wr_hit = &data_cache::wr_hit_we; break; + case LOCAL_WB_GLOBAL_WT: + m_wr_hit = &data_cache::wr_hit_global_we_local_wb; + break; + default: + assert(0 && "Error: Must set valid cache write policy\n"); + break; // Need to set a write hit function + } + + // Set write miss function + switch(m_config.m_write_alloc_policy){ + case NO_WRITE_ALLOCATE: m_wr_miss = &data_cache::wr_miss_no_wa; break; + case WRITE_ALLOCATE: m_wr_miss = &data_cache::wr_miss_wa_naive; break; + case FETCH_ON_WRITE: m_wr_miss = &data_cache::wr_miss_wa_fetch_on_write; break; + case LAZY_FETCH_ON_READ: m_wr_miss = &data_cache::wr_miss_wa_lazy_fetch_on_read; break; + default: + assert(0 && "Error: Must set valid cache write miss policy\n"); + break; // Need to set a write miss function + } } - // Set write miss function - switch (m_config.m_write_alloc_policy) { - case NO_WRITE_ALLOCATE: - m_wr_miss = &data_cache::wr_miss_no_wa; - break; - case WRITE_ALLOCATE: - m_wr_miss = &data_cache::wr_miss_wa_naive; - break; - case FETCH_ON_WRITE: - m_wr_miss = &data_cache::wr_miss_wa_fetch_on_write; - break; - case LAZY_FETCH_ON_READ: - m_wr_miss = &data_cache::wr_miss_wa_lazy_fetch_on_read; - break; - default: - assert(0 && "Error: Must set valid cache write miss policy\n"); - break; // Need to set a write miss function + virtual enum cache_request_status access( new_addr_type addr, + mem_fetch *mf, + unsigned time, + std::list<cache_event> &events ); +protected: + data_cache( const char *name, + cache_config &config, + int core_id, + int type_id, + mem_fetch_interface *memport, + mem_fetch_allocator *mfcreator, + enum mem_fetch_status status, + tag_array* new_tag_array, + mem_access_type wr_alloc_type, + mem_access_type wrbk_type, + class gpgpu_sim* gpu ) + : baseline_cache(name, config, core_id, type_id, memport,status, new_tag_array) + { + init( mfcreator ); + m_wr_alloc_type = wr_alloc_type; + m_wrbk_type = wrbk_type; + m_gpu=gpu; } - } - virtual enum cache_request_status access(new_addr_type addr, mem_fetch *mf, - unsigned time, - std::list<cache_event> &events); + mem_access_type m_wr_alloc_type; // Specifies type of write allocate request (e.g., L1 or L2) + mem_access_type m_wrbk_type; // Specifies type of writeback request (e.g., L1 or L2) + class gpgpu_sim* m_gpu; - protected: - data_cache(const char *name, cache_config &config, int core_id, int type_id, - mem_fetch_interface *memport, mem_fetch_allocator *mfcreator, - enum mem_fetch_status status, tag_array *new_tag_array, - mem_access_type wr_alloc_type, mem_access_type wrbk_type, - class gpgpu_sim *gpu) - : baseline_cache(name, config, core_id, type_id, memport, status, - new_tag_array) { - init(mfcreator); - m_wr_alloc_type = wr_alloc_type; - m_wrbk_type = wrbk_type; - m_gpu = gpu; - } + //! A general function that takes the result of a tag_array probe + // and performs the correspding functions based on the cache configuration + // The access fucntion calls this function + enum cache_request_status + process_tag_probe( bool wr, + enum cache_request_status status, + new_addr_type addr, + unsigned cache_index, + mem_fetch* mf, + unsigned time, + std::list<cache_event>& events ); - mem_access_type m_wr_alloc_type; // Specifies type of write allocate request - // (e.g., L1 or L2) - mem_access_type - m_wrbk_type; // Specifies type of writeback request (e.g., L1 or L2) - class gpgpu_sim *m_gpu; +protected: + mem_fetch_allocator *m_memfetch_creator; - //! A general function that takes the result of a tag_array probe - // and performs the correspding functions based on the cache configuration - // The access fucntion calls this function - enum cache_request_status process_tag_probe(bool wr, - enum cache_request_status status, - new_addr_type addr, - unsigned cache_index, - mem_fetch *mf, unsigned time, - std::list<cache_event> &events); + // Functions for data cache access + /// Sends write request to lower level memory (write or writeback) + void send_write_request( mem_fetch *mf, + cache_event request, + unsigned time, + std::list<cache_event> &events); - protected: - mem_fetch_allocator *m_memfetch_creator; + // Member Function pointers - Set by configuration options + // to the functions below each grouping + /******* Write-hit configs *******/ + enum cache_request_status + (data_cache::*m_wr_hit)( new_addr_type addr, + unsigned cache_index, + mem_fetch *mf, + unsigned time, + std::list<cache_event> &events, + enum cache_request_status status ); + /// Marks block as MODIFIED and updates block LRU + enum cache_request_status + wr_hit_wb( new_addr_type addr, + unsigned cache_index, + mem_fetch *mf, + unsigned time, + std::list<cache_event> &events, + enum cache_request_status status ); // write-back + enum cache_request_status + wr_hit_wt( new_addr_type addr, + unsigned cache_index, + mem_fetch *mf, + unsigned time, + std::list<cache_event> &events, + enum cache_request_status status ); // write-through - // Functions for data cache access - /// Sends write request to lower level memory (write or writeback) - void send_write_request(mem_fetch *mf, cache_event request, unsigned time, - std::list<cache_event> &events); + /// Marks block as INVALID and sends write request to lower level memory + enum cache_request_status + wr_hit_we( new_addr_type addr, + unsigned cache_index, + mem_fetch *mf, + unsigned time, + std::list<cache_event> &events, + enum cache_request_status status ); // write-evict + enum cache_request_status + wr_hit_global_we_local_wb( new_addr_type addr, + unsigned cache_index, + mem_fetch *mf, + unsigned time, + std::list<cache_event> &events, + enum cache_request_status status ); + // global write-evict, local write-back - // Member Function pointers - Set by configuration options - // to the functions below each grouping - /******* Write-hit configs *******/ - enum cache_request_status (data_cache::*m_wr_hit)( - new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, - std::list<cache_event> &events, enum cache_request_status status); - /// Marks block as MODIFIED and updates block LRU - enum cache_request_status wr_hit_wb( - new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, - std::list<cache_event> &events, - enum cache_request_status status); // write-back - enum cache_request_status wr_hit_wt( - new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, - std::list<cache_event> &events, - enum cache_request_status status); // write-through - /// Marks block as INVALID and sends write request to lower level memory - enum cache_request_status wr_hit_we( - new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, - std::list<cache_event> &events, - enum cache_request_status status); // write-evict - enum cache_request_status wr_hit_global_we_local_wb( - new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, - std::list<cache_event> &events, enum cache_request_status status); - // global write-evict, local write-back + /******* Write-miss configs *******/ + enum cache_request_status + (data_cache::*m_wr_miss)( new_addr_type addr, + unsigned cache_index, + mem_fetch *mf, + unsigned time, + std::list<cache_event> &events, + enum cache_request_status status ); + /// Sends read request, and possible write-back request, + // to lower level memory for a write miss with write-allocate + enum cache_request_status + wr_miss_wa_naive( new_addr_type addr, + unsigned cache_index, + mem_fetch *mf, + unsigned time, + std::list<cache_event> &events, + enum cache_request_status status ); // write-allocate-send-write-and-read-request + enum cache_request_status + wr_miss_wa_fetch_on_write( new_addr_type addr, + unsigned cache_index, + mem_fetch *mf, + unsigned time, + std::list<cache_event> &events, + enum cache_request_status status ); // write-allocate with fetch-on-every-write + enum cache_request_status + wr_miss_wa_lazy_fetch_on_read( new_addr_type addr, + unsigned cache_index, + mem_fetch *mf, + unsigned time, + std::list<cache_event> &events, + enum cache_request_status status ); // write-allocate with read-fetch-only + enum cache_request_status + wr_miss_wa_write_validate( new_addr_type addr, + unsigned cache_index, + mem_fetch *mf, + unsigned time, + std::list<cache_event> &events, + enum cache_request_status status ); // write-allocate that writes with no read fetch + enum cache_request_status + wr_miss_no_wa( new_addr_type addr, + unsigned cache_index, + mem_fetch *mf, + unsigned time, + std::list<cache_event> &events, + enum cache_request_status status ); // no write-allocate - /******* Write-miss configs *******/ - enum cache_request_status (data_cache::*m_wr_miss)( - new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, - std::list<cache_event> &events, enum cache_request_status status); - /// Sends read request, and possible write-back request, - // to lower level memory for a write miss with write-allocate - enum cache_request_status wr_miss_wa_naive( - new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, - std::list<cache_event> &events, - enum cache_request_status - status); // write-allocate-send-write-and-read-request - enum cache_request_status wr_miss_wa_fetch_on_write( - new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, - std::list<cache_event> &events, - enum cache_request_status - status); // write-allocate with fetch-on-every-write - enum cache_request_status wr_miss_wa_lazy_fetch_on_read( - new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, - std::list<cache_event> &events, - enum cache_request_status status); // write-allocate with read-fetch-only - enum cache_request_status wr_miss_wa_write_validate( - new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, - std::list<cache_event> &events, - enum cache_request_status - status); // write-allocate that writes with no read fetch - enum cache_request_status wr_miss_no_wa( - new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, - std::list<cache_event> &events, - enum cache_request_status status); // no write-allocate + // Currently no separate functions for reads + /******* Read-hit configs *******/ + enum cache_request_status + (data_cache::*m_rd_hit)( new_addr_type addr, + unsigned cache_index, + mem_fetch *mf, + unsigned time, + std::list<cache_event> &events, + enum cache_request_status status ); + enum cache_request_status + rd_hit_base( new_addr_type addr, + unsigned cache_index, + mem_fetch *mf, + unsigned time, + std::list<cache_event> &events, + enum cache_request_status status ); - // Currently no separate functions for reads - /******* Read-hit configs *******/ - enum cache_request_status (data_cache::*m_rd_hit)( - new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, - std::list<cache_event> &events, enum cache_request_status status); - enum cache_request_status rd_hit_base(new_addr_type addr, - unsigned cache_index, mem_fetch *mf, - unsigned time, - std::list<cache_event> &events, - enum cache_request_status status); + /******* Read-miss configs *******/ + enum cache_request_status + (data_cache::*m_rd_miss)( new_addr_type addr, + unsigned cache_index, + mem_fetch *mf, + unsigned time, + std::list<cache_event> &events, + enum cache_request_status status ); + enum cache_request_status + rd_miss_base( new_addr_type addr, + unsigned cache_index, + mem_fetch*mf, + unsigned time, + std::list<cache_event> &events, + enum cache_request_status status ); - /******* Read-miss configs *******/ - enum cache_request_status (data_cache::*m_rd_miss)( - new_addr_type addr, unsigned cache_index, mem_fetch *mf, unsigned time, - std::list<cache_event> &events, enum cache_request_status status); - enum cache_request_status rd_miss_base(new_addr_type addr, - unsigned cache_index, mem_fetch *mf, - unsigned time, - std::list<cache_event> &events, - enum cache_request_status status); }; /// This is meant to model the first level data cache in Fermi. @@ -1537,242 +1524,243 @@ class data_cache : public baseline_cache { /// the granularity of individual blocks /// (the policy used in fermi according to the CUDA manual) class l1_cache : public data_cache { - public: - l1_cache(const char *name, cache_config &config, int core_id, int type_id, - mem_fetch_interface *memport, mem_fetch_allocator *mfcreator, - enum mem_fetch_status status, class gpgpu_sim *gpu) - : data_cache(name, config, core_id, type_id, memport, mfcreator, status, - L1_WR_ALLOC_R, L1_WRBK_ACC, gpu) {} +public: + l1_cache(const char *name, cache_config &config, + int core_id, int type_id, mem_fetch_interface *memport, + mem_fetch_allocator *mfcreator, enum mem_fetch_status status, class gpgpu_sim* gpu ) + : data_cache(name,config,core_id,type_id,memport,mfcreator,status, L1_WR_ALLOC_R, L1_WRBK_ACC, gpu){} - virtual ~l1_cache() {} + virtual ~l1_cache(){} - virtual enum cache_request_status access(new_addr_type addr, mem_fetch *mf, - unsigned time, - std::list<cache_event> &events); + virtual enum cache_request_status + access( new_addr_type addr, + mem_fetch *mf, + unsigned time, + std::list<cache_event> &events ); + +protected: + l1_cache( const char *name, + cache_config &config, + int core_id, + int type_id, + mem_fetch_interface *memport, + mem_fetch_allocator *mfcreator, + enum mem_fetch_status status, + tag_array* new_tag_array, + class gpgpu_sim* gpu) + : data_cache( name, + config, + core_id,type_id,memport,mfcreator,status, new_tag_array, L1_WR_ALLOC_R, L1_WRBK_ACC, gpu ){} - protected: - l1_cache(const char *name, cache_config &config, int core_id, int type_id, - mem_fetch_interface *memport, mem_fetch_allocator *mfcreator, - enum mem_fetch_status status, tag_array *new_tag_array, - class gpgpu_sim *gpu) - : data_cache(name, config, core_id, type_id, memport, mfcreator, status, - new_tag_array, L1_WR_ALLOC_R, L1_WRBK_ACC, gpu) {} }; /// Models second level shared cache with global write-back /// and write-allocate policies class l2_cache : public data_cache { - public: - l2_cache(const char *name, cache_config &config, int core_id, int type_id, - mem_fetch_interface *memport, mem_fetch_allocator *mfcreator, - enum mem_fetch_status status, class gpgpu_sim *gpu) - : data_cache(name, config, core_id, type_id, memport, mfcreator, status, - L2_WR_ALLOC_R, L2_WRBK_ACC, gpu) {} +public: + l2_cache(const char *name, cache_config &config, + int core_id, int type_id, mem_fetch_interface *memport, + mem_fetch_allocator *mfcreator, enum mem_fetch_status status, class gpgpu_sim* gpu ) + : data_cache(name,config,core_id,type_id,memport,mfcreator,status, L2_WR_ALLOC_R, L2_WRBK_ACC, gpu){} - virtual ~l2_cache() {} + virtual ~l2_cache() {} - virtual enum cache_request_status access(new_addr_type addr, mem_fetch *mf, - unsigned time, - std::list<cache_event> &events); + virtual enum cache_request_status + access( new_addr_type addr, + mem_fetch *mf, + unsigned time, + std::list<cache_event> &events ); }; /*****************************************************************************/ // See the following paper to understand this cache model: -// -// Igehy, et al., Prefetching in a Texture Cache Architecture, +// +// Igehy, et al., Prefetching in a Texture Cache Architecture, // Proceedings of the 1998 Eurographics/SIGGRAPH Workshop on Graphics Hardware // http://www-graphics.stanford.edu/papers/texture_prefetch/ class tex_cache : public cache_t { - public: - tex_cache(const char *name, cache_config &config, int core_id, int type_id, - mem_fetch_interface *memport, enum mem_fetch_status request_status, - enum mem_fetch_status rob_status) - : m_config(config), - m_tags(config, core_id, type_id), - m_fragment_fifo(config.m_fragment_fifo_entries), - m_request_fifo(config.m_request_fifo_entries), - m_rob(config.m_rob_entries), - m_result_fifo(config.m_result_fifo_entries) { - m_name = name; - assert(config.m_mshr_type == TEX_FIFO || - config.m_mshr_type == SECTOR_TEX_FIFO); - assert(config.m_write_policy == READ_ONLY); - assert(config.m_alloc_policy == ON_MISS); - m_memport = memport; - m_cache = new data_block[config.get_num_lines()]; - m_request_queue_status = request_status; - m_rob_status = rob_status; - } - - /// Access function for tex_cache - /// return values: RESERVATION_FAIL if request could not be accepted - /// otherwise returns HIT_RESERVED or MISS; NOTE: *never* returns HIT - /// since unlike a normal CPU cache, a "HIT" in texture cache does not - /// mean the data is ready (still need to get through fragment fifo) - enum cache_request_status access(new_addr_type addr, mem_fetch *mf, - unsigned time, - std::list<cache_event> &events); - void cycle(); - /// Place returning cache block into reorder buffer - void fill(mem_fetch *mf, unsigned time); - /// Are any (accepted) accesses that had to wait for memory now ready? (does - /// not include accesses that "HIT") - bool access_ready() const { return !m_result_fifo.empty(); } - /// Pop next ready access (includes both accesses that "HIT" and those that - /// "MISS") - mem_fetch *next_access() { return m_result_fifo.pop(); } - void display_state(FILE *fp) const; - - // accessors for cache bandwidth availability - stubs for now - bool data_port_free() const { return true; } - bool fill_port_free() const { return true; } - - // Stat collection - const cache_stats &get_stats() const { return m_stats; } - unsigned get_stats(enum mem_access_type *access_type, - unsigned num_access_type, - enum cache_request_status *access_status, - unsigned num_access_status) const { - return m_stats.get_stats(access_type, num_access_type, access_status, - num_access_status); - } +public: + tex_cache( const char *name, cache_config &config, int core_id, int type_id, mem_fetch_interface *memport, + enum mem_fetch_status request_status, + enum mem_fetch_status rob_status ) + : m_config(config), + m_tags(config,core_id,type_id), + m_fragment_fifo(config.m_fragment_fifo_entries), + m_request_fifo(config.m_request_fifo_entries), + m_rob(config.m_rob_entries), + m_result_fifo(config.m_result_fifo_entries) + { + m_name = name; + assert(config.m_mshr_type == TEX_FIFO || config.m_mshr_type == SECTOR_TEX_FIFO ); + assert(config.m_write_policy == READ_ONLY); + assert(config.m_alloc_policy == ON_MISS); + m_memport=memport; + m_cache = new data_block[ config.get_num_lines() ]; + m_request_queue_status = request_status; + m_rob_status = rob_status; + } - void get_sub_stats(struct cache_sub_stats &css) const { - m_stats.get_sub_stats(css); - } + /// Access function for tex_cache + /// return values: RESERVATION_FAIL if request could not be accepted + /// otherwise returns HIT_RESERVED or MISS; NOTE: *never* returns HIT + /// since unlike a normal CPU cache, a "HIT" in texture cache does not + /// mean the data is ready (still need to get through fragment fifo) + enum cache_request_status access( new_addr_type addr, mem_fetch *mf, unsigned time, std::list<cache_event> &events ); + void cycle(); + /// Place returning cache block into reorder buffer + void fill( mem_fetch *mf, unsigned time ); + /// Are any (accepted) accesses that had to wait for memory now ready? (does not include accesses that "HIT") + bool access_ready() const{return !m_result_fifo.empty();} + /// Pop next ready access (includes both accesses that "HIT" and those that "MISS") + mem_fetch *next_access(){return m_result_fifo.pop();} + void display_state( FILE *fp ) const; - private: - std::string m_name; - const cache_config &m_config; + // accessors for cache bandwidth availability - stubs for now + bool data_port_free() const { return true; } + bool fill_port_free() const { return true; } - struct fragment_entry { - fragment_entry() {} - fragment_entry(mem_fetch *mf, unsigned idx, bool m, unsigned d) { - m_request = mf; - m_cache_index = idx; - m_miss = m; - m_data_size = d; + // Stat collection + const cache_stats &get_stats() const { + return m_stats; } - mem_fetch *m_request; // request information - unsigned m_cache_index; // where to look for data - bool m_miss; // true if sent memory request - unsigned m_data_size; - }; - - struct rob_entry { - rob_entry() { - m_ready = false; - m_time = 0; - m_request = NULL; + unsigned get_stats(enum mem_access_type *access_type, unsigned num_access_type, enum cache_request_status *access_status, unsigned num_access_status) const{ + return m_stats.get_stats(access_type, num_access_type, access_status, num_access_status); } - rob_entry(unsigned i, mem_fetch *mf, new_addr_type a) { - m_ready = false; - m_index = i; - m_time = 0; - m_request = mf; - m_block_addr = a; + + void get_sub_stats(struct cache_sub_stats &css) const{ + m_stats.get_sub_stats(css); } - bool m_ready; - unsigned m_time; // which cycle did this entry become ready? - unsigned m_index; // where in cache should block be placed? - mem_fetch *m_request; - new_addr_type m_block_addr; - }; +private: + std::string m_name; + const cache_config &m_config; - struct data_block { - data_block() { m_valid = false; } - bool m_valid; - new_addr_type m_block_addr; - }; + struct fragment_entry { + fragment_entry() {} + fragment_entry( mem_fetch *mf, unsigned idx, bool m, unsigned d ) + { + m_request=mf; + m_cache_index=idx; + m_miss=m; + m_data_size=d; + } + mem_fetch *m_request; // request information + unsigned m_cache_index; // where to look for data + bool m_miss; // true if sent memory request + unsigned m_data_size; + }; - // TODO: replace fifo_pipeline with this? - template <class T> - class fifo { - public: - fifo(unsigned size) { - m_size = size; - m_num = 0; - m_head = 0; - m_tail = 0; - m_data = new T[size]; - } - bool full() const { return m_num == m_size; } - bool empty() const { return m_num == 0; } - unsigned size() const { return m_num; } - unsigned capacity() const { return m_size; } - unsigned push(const T &e) { - assert(!full()); - m_data[m_head] = e; - unsigned result = m_head; - inc_head(); - return result; - } - T pop() { - assert(!empty()); - T result = m_data[m_tail]; - inc_tail(); - return result; - } - const T &peek(unsigned index) const { - assert(index < m_size); - return m_data[index]; - } - T &peek(unsigned index) { - assert(index < m_size); - return m_data[index]; - } - T &peek() const { return m_data[m_tail]; } - unsigned next_pop_index() const { return m_tail; } + struct rob_entry { + rob_entry() { m_ready = false; m_time=0; m_request=NULL;} + rob_entry( unsigned i, mem_fetch *mf, new_addr_type a ) + { + m_ready=false; + m_index=i; + m_time=0; + m_request=mf; + m_block_addr=a; + } + bool m_ready; + unsigned m_time; // which cycle did this entry become ready? + unsigned m_index; // where in cache should block be placed? + mem_fetch *m_request; + new_addr_type m_block_addr; + }; - private: - void inc_head() { - m_head = (m_head + 1) % m_size; - m_num++; - } - void inc_tail() { - assert(m_num > 0); - m_tail = (m_tail + 1) % m_size; - m_num--; - } + struct data_block { + data_block() { m_valid = false;} + bool m_valid; + new_addr_type m_block_addr; + }; - unsigned m_head; // next entry goes here - unsigned m_tail; // oldest entry found here - unsigned m_num; // how many in fifo? - unsigned m_size; // maximum number of entries in fifo - T *m_data; - }; + // TODO: replace fifo_pipeline with this? + template<class T> class fifo { + public: + fifo( unsigned size ) + { + m_size=size; + m_num=0; + m_head=0; + m_tail=0; + m_data = new T[size]; + } + bool full() const { return m_num == m_size;} + bool empty() const { return m_num == 0;} + unsigned size() const { return m_num;} + unsigned capacity() const { return m_size;} + unsigned push( const T &e ) + { + assert(!full()); + m_data[m_head] = e; + unsigned result = m_head; + inc_head(); + return result; + } + T pop() + { + assert(!empty()); + T result = m_data[m_tail]; + inc_tail(); + return result; + } + const T &peek( unsigned index ) const + { + assert( index < m_size ); + return m_data[index]; + } + T &peek( unsigned index ) + { + assert( index < m_size ); + return m_data[index]; + } + T &peek() const + { + return m_data[m_tail]; + } + unsigned next_pop_index() const + { + return m_tail; + } + private: + void inc_head() { m_head = (m_head+1)%m_size; m_num++;} + void inc_tail() { assert(m_num>0); m_tail = (m_tail+1)%m_size; m_num--;} - tag_array m_tags; - fifo<fragment_entry> m_fragment_fifo; - fifo<mem_fetch *> m_request_fifo; - fifo<rob_entry> m_rob; - data_block *m_cache; - fifo<mem_fetch *> m_result_fifo; // next completed texture fetch + unsigned m_head; // next entry goes here + unsigned m_tail; // oldest entry found here + unsigned m_num; // how many in fifo? + unsigned m_size; // maximum number of entries in fifo + T *m_data; + }; - mem_fetch_interface *m_memport; - enum mem_fetch_status m_request_queue_status; - enum mem_fetch_status m_rob_status; + tag_array m_tags; + fifo<fragment_entry> m_fragment_fifo; + fifo<mem_fetch*> m_request_fifo; + fifo<rob_entry> m_rob; + data_block *m_cache; + fifo<mem_fetch*> m_result_fifo; // next completed texture fetch - struct extra_mf_fields { - extra_mf_fields() { m_valid = false; } - extra_mf_fields(unsigned i, const cache_config &m_config) { - m_valid = true; - m_rob_index = i; - pending_read = m_config.m_mshr_type == SECTOR_TEX_FIFO - ? m_config.m_line_sz / SECTOR_SIZE - : 0; - } - bool m_valid; - unsigned m_rob_index; - unsigned pending_read; - }; + mem_fetch_interface *m_memport; + enum mem_fetch_status m_request_queue_status; + enum mem_fetch_status m_rob_status; + + struct extra_mf_fields { + extra_mf_fields() { m_valid = false;} + extra_mf_fields( unsigned i, const cache_config &m_config ) + { + m_valid = true; + m_rob_index = i; + pending_read = m_config.m_mshr_type == SECTOR_TEX_FIFO? m_config.m_line_sz/SECTOR_SIZE : 0; + } + bool m_valid; + unsigned m_rob_index; + unsigned pending_read; + }; - cache_stats m_stats; + cache_stats m_stats; - typedef std::map<mem_fetch *, extra_mf_fields> extra_mf_fields_lookup; + typedef std::map<mem_fetch*,extra_mf_fields> extra_mf_fields_lookup; - extra_mf_fields_lookup m_extra_mf_fields; + extra_mf_fields_lookup m_extra_mf_fields; }; #endif diff --git a/src/gpgpu-sim/gpu-misc.cc b/src/gpgpu-sim/gpu-misc.cc index e389df3..df042b1 100644 --- a/src/gpgpu-sim/gpu-misc.cc +++ b/src/gpgpu-sim/gpu-misc.cc @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -29,27 +27,17 @@ #include "gpu-misc.h" -unsigned int LOGB2(unsigned int v) { - unsigned int shift; - unsigned int r; +unsigned int LOGB2( unsigned int v ) { + unsigned int shift; + unsigned int r; - r = 0; + r = 0; - shift = ((v & 0xFFFF0000) != 0) << 4; - v >>= shift; - r |= shift; - shift = ((v & 0xFF00) != 0) << 3; - v >>= shift; - r |= shift; - shift = ((v & 0xF0) != 0) << 2; - v >>= shift; - r |= shift; - shift = ((v & 0xC) != 0) << 1; - v >>= shift; - r |= shift; - shift = ((v & 0x2) != 0) << 0; - v >>= shift; - r |= shift; + shift = (( v & 0xFFFF0000) != 0 ) << 4; v >>= shift; r |= shift; + shift = (( v & 0xFF00 ) != 0 ) << 3; v >>= shift; r |= shift; + shift = (( v & 0xF0 ) != 0 ) << 2; v >>= shift; r |= shift; + shift = (( v & 0xC ) != 0 ) << 1; v >>= shift; r |= shift; + shift = (( v & 0x2 ) != 0 ) << 0; v >>= shift; r |= shift; - return r; + return r; } diff --git a/src/gpgpu-sim/gpu-misc.h b/src/gpgpu-sim/gpu-misc.h index b0b4685..509cc3a 100644 --- a/src/gpgpu-sim/gpu-misc.h +++ b/src/gpgpu-sim/gpu-misc.h @@ -8,16 +8,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -31,13 +29,14 @@ #ifndef GPU_MISC_H #define GPU_MISC_H -// enables a verbose printout of all L1 cache misses and all MSHR status changes -// good for a single shader configuration +//enables a verbose printout of all L1 cache misses and all MSHR status changes +//good for a single shader configuration #define DEBUGL1MISS 0 -unsigned int LOGB2(unsigned int v); +unsigned int LOGB2( unsigned int v ); -#define gs_min2(a, b) (((a) < (b)) ? (a) : (b)) -#define min3(x, y, z) (((x) < (y) && (x) < (z)) ? (x) : (gs_min2((y), (z)))) +#define gs_min2(a,b) (((a)<(b))?(a):(b)) +#define min3(x,y,z) (((x)<(y) && (x)<(z))?(x):(gs_min2((y),(z)))) #endif + diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index ba64477..56ea8c4 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -8,16 +8,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -28,49 +26,51 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + #include "gpu-sim.h" -#include <math.h> -#include <signal.h> #include <stdio.h> #include <stdlib.h> +#include <math.h> +#include <signal.h> #include "zlib.h" -#include "dram.h" -#include "mem_fetch.h" + #include "shader.h" #include "shader_trace.h" +#include "dram.h" +#include "mem_fetch.h" #include <time.h> -#include "addrdec.h" -#include "delayqueue.h" -#include "dram.h" #include "gpu-cache.h" #include "gpu-misc.h" -#include "icnt_wrapper.h" -#include "l2cache.h" +#include "delayqueue.h" #include "shader.h" +#include "icnt_wrapper.h" +#include "dram.h" +#include "addrdec.h" #include "stat-tool.h" +#include "l2cache.h" -#include "../../libcuda/gpgpu_context.h" -#include "../abstract_hardware_model.h" -#include "../cuda-sim/cuda-sim.h" -#include "../cuda-sim/cuda_device_runtime.h" #include "../cuda-sim/ptx-stats.h" -#include "../cuda-sim/ptx_ir.h" +#include "../statwrapper.h" +#include "../abstract_hardware_model.h" #include "../debug.h" #include "../gpgpusim_entrypoint.h" -#include "../statwrapper.h" +#include "../cuda-sim/cuda-sim.h" +#include "../cuda-sim/ptx_ir.h" #include "../trace.h" #include "mem_latency_stat.h" #include "power_stat.h" -#include "stats.h" #include "visualizer.h" +#include "stats.h" +#include "../cuda-sim/cuda_device_runtime.h" +#include "../../libcuda/gpgpu_context.h" #ifdef GPGPUSIM_POWER_MODEL #include "power_interface.h" #else -class gpgpu_sim_wrapper {}; +class gpgpu_sim_wrapper {}; #endif #include <stdio.h> @@ -79,1915 +79,1781 @@ class gpgpu_sim_wrapper {}; #include <sstream> #include <string> -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + -bool g_interactive_debugger_enabled = false; +bool g_interactive_debugger_enabled=false; -tr1_hash_map<new_addr_type, unsigned> address_random_interleaving; +tr1_hash_map<new_addr_type,unsigned> address_random_interleaving; /* Clock Domains */ -#define CORE 0x01 -#define L2 0x02 -#define DRAM 0x04 -#define ICNT 0x08 +#define CORE 0x01 +#define L2 0x02 +#define DRAM 0x04 +#define ICNT 0x08 + #define MEM_LATENCY_STAT_IMPL + #include "mem_latency_stat.h" -void power_config::reg_options(class OptionParser *opp) { - option_parser_register(opp, "-gpuwattch_xml_file", OPT_CSTR, - &g_power_config_name, "GPUWattch XML file", - "gpuwattch.xml"); +void power_config::reg_options(class OptionParser * opp) +{ + + + option_parser_register(opp, "-gpuwattch_xml_file", OPT_CSTR, + &g_power_config_name,"GPUWattch XML file", + "gpuwattch.xml"); - option_parser_register(opp, "-power_simulation_enabled", OPT_BOOL, - &g_power_simulation_enabled, - "Turn on power simulator (1=On, 0=Off)", "0"); + option_parser_register(opp, "-power_simulation_enabled", OPT_BOOL, + &g_power_simulation_enabled, "Turn on power simulator (1=On, 0=Off)", + "0"); - option_parser_register(opp, "-power_per_cycle_dump", OPT_BOOL, - &g_power_per_cycle_dump, - "Dump detailed power output each cycle", "0"); + option_parser_register(opp, "-power_per_cycle_dump", OPT_BOOL, + &g_power_per_cycle_dump, "Dump detailed power output each cycle", + "0"); - // Output Data Formats - option_parser_register( - opp, "-power_trace_enabled", OPT_BOOL, &g_power_trace_enabled, - "produce a file for the power trace (1=On, 0=Off)", "0"); + // Output Data Formats + option_parser_register(opp, "-power_trace_enabled", OPT_BOOL, + &g_power_trace_enabled, "produce a file for the power trace (1=On, 0=Off)", + "0"); - option_parser_register( - opp, "-power_trace_zlevel", OPT_INT32, &g_power_trace_zlevel, - "Compression level of the power trace output log (0=no comp, 9=highest)", - "6"); + option_parser_register(opp, "-power_trace_zlevel", OPT_INT32, + &g_power_trace_zlevel, "Compression level of the power trace output log (0=no comp, 9=highest)", + "6"); - option_parser_register( - opp, "-steady_power_levels_enabled", OPT_BOOL, - &g_steady_power_levels_enabled, - "produce a file for the steady power levels (1=On, 0=Off)", "0"); + option_parser_register(opp, "-steady_power_levels_enabled", OPT_BOOL, + &g_steady_power_levels_enabled, "produce a file for the steady power levels (1=On, 0=Off)", + "0"); + + option_parser_register(opp, "-steady_state_definition", OPT_CSTR, + &gpu_steady_state_definition, "allowed deviation:number of samples", + "8:4"); - option_parser_register(opp, "-steady_state_definition", OPT_CSTR, - &gpu_steady_state_definition, - "allowed deviation:number of samples", "8:4"); } -void memory_config::reg_options(class OptionParser *opp) { - option_parser_register(opp, "-perf_sim_memcpy", OPT_BOOL, &m_perf_sim_memcpy, - "Fill the L2 cache on memcpy", "1"); - option_parser_register(opp, "-simple_dram_model", OPT_BOOL, - &simple_dram_model, - "simple_dram_model with fixed latency and BW", "0"); - option_parser_register(opp, "-gpgpu_dram_scheduler", OPT_INT32, - &scheduler_type, "0 = fifo, 1 = FR-FCFS (defaul)", - "1"); - option_parser_register(opp, "-gpgpu_dram_partition_queues", OPT_CSTR, - &gpgpu_L2_queue_config, "i2$:$2d:d2$:$2i", "8:8:8:8"); +void memory_config::reg_options(class OptionParser * opp) +{ + option_parser_register(opp, "-perf_sim_memcpy", OPT_BOOL, &m_perf_sim_memcpy, + "Fill the L2 cache on memcpy", "1"); + option_parser_register(opp, "-simple_dram_model", OPT_BOOL, &simple_dram_model, + "simple_dram_model with fixed latency and BW", "0"); + option_parser_register(opp, "-gpgpu_dram_scheduler", OPT_INT32, &scheduler_type, + "0 = fifo, 1 = FR-FCFS (defaul)", "1"); + option_parser_register(opp, "-gpgpu_dram_partition_queues", OPT_CSTR, &gpgpu_L2_queue_config, + "i2$:$2d:d2$:$2i", + "8:8:8:8"); - option_parser_register(opp, "-l2_ideal", OPT_BOOL, &l2_ideal, - "Use a ideal L2 cache that always hit", "0"); - option_parser_register(opp, "-gpgpu_cache:dl2", OPT_CSTR, - &m_L2_config.m_config_string, - "unified banked L2 data cache config " - " {<nsets>:<bsize>:<assoc>,<rep>:<wr>:<alloc>:<wr_" - "alloc>,<mshr>:<N>:<merge>,<mq>}", - "64:128:8,L:B:m:N,A:16:4,4"); - option_parser_register(opp, "-gpgpu_cache:dl2_texture_only", OPT_BOOL, - &m_L2_texure_only, "L2 cache used for texture only", - "1"); - option_parser_register( - opp, "-gpgpu_n_mem", OPT_UINT32, &m_n_mem, - "number of memory modules (e.g. memory controllers) in gpu", "8"); - option_parser_register(opp, "-gpgpu_n_sub_partition_per_mchannel", OPT_UINT32, - &m_n_sub_partition_per_memory_channel, - "number of memory subpartition in each memory module", - "1"); - option_parser_register(opp, "-gpgpu_n_mem_per_ctrlr", OPT_UINT32, - &gpu_n_mem_per_ctrlr, - "number of memory chips per memory controller", "1"); - option_parser_register(opp, "-gpgpu_memlatency_stat", OPT_INT32, - &gpgpu_memlatency_stat, - "track and display latency statistics 0x2 enables MC, " - "0x4 enables queue logs", - "0"); - option_parser_register(opp, "-gpgpu_frfcfs_dram_sched_queue_size", OPT_INT32, - &gpgpu_frfcfs_dram_sched_queue_size, - "0 = unlimited (default); # entries per chip", "0"); - option_parser_register(opp, "-gpgpu_dram_return_queue_size", OPT_INT32, - &gpgpu_dram_return_queue_size, - "0 = unlimited (default); # entries per chip", "0"); - option_parser_register(opp, "-gpgpu_dram_buswidth", OPT_UINT32, &busW, - "default = 4 bytes (8 bytes per cycle at DDR)", "4"); - option_parser_register( - opp, "-gpgpu_dram_burst_length", OPT_UINT32, &BL, - "Burst length of each DRAM request (default = 4 data bus cycle)", "4"); - option_parser_register(opp, "-dram_data_command_freq_ratio", OPT_UINT32, - &data_command_freq_ratio, - "Frequency ratio between DRAM data bus and command " - "bus (default = 2 times, i.e. DDR)", - "2"); - option_parser_register( - opp, "-gpgpu_dram_timing_opt", OPT_CSTR, &gpgpu_dram_timing_opt, - "DRAM timing parameters = " - "{nbk:tCCD:tRRD:tRCD:tRAS:tRP:tRC:CL:WL:tCDLR:tWR:nbkgrp:tCCDL:tRTPL}", - "4:2:8:12:21:13:34:9:4:5:13:1:0:0"); - option_parser_register(opp, "-rop_latency", OPT_UINT32, &rop_latency, - "ROP queue latency (default 85)", "85"); - option_parser_register(opp, "-dram_latency", OPT_UINT32, &dram_latency, - "DRAM latency (default 30)", "30"); - option_parser_register(opp, "-dual_bus_interface", OPT_UINT32, - &dual_bus_interface, - "dual_bus_interface (default = 0) ", "0"); - option_parser_register(opp, "-dram_bnk_indexing_policy", OPT_UINT32, - &dram_bnk_indexing_policy, - "dram_bnk_indexing_policy (0 = normal indexing, 1 = " - "Xoring with the higher bits) (Default = 0)", - "0"); - option_parser_register(opp, "-dram_bnkgrp_indexing_policy", OPT_UINT32, - &dram_bnkgrp_indexing_policy, - "dram_bnkgrp_indexing_policy (0 = take higher bits, 1 " - "= take lower bits) (Default = 0)", - "0"); - option_parser_register(opp, "-Seperate_Write_Queue_Enable", OPT_BOOL, - &seperate_write_queue_enabled, - "Seperate_Write_Queue_Enable", "0"); - option_parser_register(opp, "-Write_Queue_Size", OPT_CSTR, - &write_queue_size_opt, "Write_Queue_Size", "32:28:16"); - option_parser_register( - opp, "-Elimnate_rw_turnaround", OPT_BOOL, &elimnate_rw_turnaround, - "elimnate_rw_turnaround i.e set tWTR and tRTW = 0", "0"); - option_parser_register(opp, "-icnt_flit_size", OPT_UINT32, &icnt_flit_size, - "icnt_flit_size", "32"); - m_address_mapping.addrdec_setoption(opp); + option_parser_register(opp, "-l2_ideal", OPT_BOOL, &l2_ideal, + "Use a ideal L2 cache that always hit", + "0"); + option_parser_register(opp, "-gpgpu_cache:dl2", OPT_CSTR, &m_L2_config.m_config_string, + "unified banked L2 data cache config " + " {<nsets>:<bsize>:<assoc>,<rep>:<wr>:<alloc>:<wr_alloc>,<mshr>:<N>:<merge>,<mq>}", + "64:128:8,L:B:m:N,A:16:4,4"); + option_parser_register(opp, "-gpgpu_cache:dl2_texture_only", OPT_BOOL, &m_L2_texure_only, + "L2 cache used for texture only", + "1"); + option_parser_register(opp, "-gpgpu_n_mem", OPT_UINT32, &m_n_mem, + "number of memory modules (e.g. memory controllers) in gpu", + "8"); + option_parser_register(opp, "-gpgpu_n_sub_partition_per_mchannel", OPT_UINT32, &m_n_sub_partition_per_memory_channel, + "number of memory subpartition in each memory module", + "1"); + option_parser_register(opp, "-gpgpu_n_mem_per_ctrlr", OPT_UINT32, &gpu_n_mem_per_ctrlr, + "number of memory chips per memory controller", + "1"); + option_parser_register(opp, "-gpgpu_memlatency_stat", OPT_INT32, &gpgpu_memlatency_stat, + "track and display latency statistics 0x2 enables MC, 0x4 enables queue logs", + "0"); + option_parser_register(opp, "-gpgpu_frfcfs_dram_sched_queue_size", OPT_INT32, &gpgpu_frfcfs_dram_sched_queue_size, + "0 = unlimited (default); # entries per chip", + "0"); + option_parser_register(opp, "-gpgpu_dram_return_queue_size", OPT_INT32, &gpgpu_dram_return_queue_size, + "0 = unlimited (default); # entries per chip", + "0"); + option_parser_register(opp, "-gpgpu_dram_buswidth", OPT_UINT32, &busW, + "default = 4 bytes (8 bytes per cycle at DDR)", + "4"); + option_parser_register(opp, "-gpgpu_dram_burst_length", OPT_UINT32, &BL, + "Burst length of each DRAM request (default = 4 data bus cycle)", + "4"); + option_parser_register(opp, "-dram_data_command_freq_ratio", OPT_UINT32, &data_command_freq_ratio, + "Frequency ratio between DRAM data bus and command bus (default = 2 times, i.e. DDR)", + "2"); + option_parser_register(opp, "-gpgpu_dram_timing_opt", OPT_CSTR, &gpgpu_dram_timing_opt, + "DRAM timing parameters = {nbk:tCCD:tRRD:tRCD:tRAS:tRP:tRC:CL:WL:tCDLR:tWR:nbkgrp:tCCDL:tRTPL}", + "4:2:8:12:21:13:34:9:4:5:13:1:0:0"); + option_parser_register(opp, "-rop_latency", OPT_UINT32, &rop_latency, + "ROP queue latency (default 85)", + "85"); + option_parser_register(opp, "-dram_latency", OPT_UINT32, &dram_latency, + "DRAM latency (default 30)", + "30"); + option_parser_register(opp, "-dual_bus_interface", OPT_UINT32, &dual_bus_interface, + "dual_bus_interface (default = 0) ", + "0"); + option_parser_register(opp, "-dram_bnk_indexing_policy", OPT_UINT32, &dram_bnk_indexing_policy, + "dram_bnk_indexing_policy (0 = normal indexing, 1 = Xoring with the higher bits) (Default = 0)", + "0"); + option_parser_register(opp, "-dram_bnkgrp_indexing_policy", OPT_UINT32, &dram_bnkgrp_indexing_policy, + "dram_bnkgrp_indexing_policy (0 = take higher bits, 1 = take lower bits) (Default = 0)", + "0"); + option_parser_register(opp, "-Seperate_Write_Queue_Enable", OPT_BOOL, &seperate_write_queue_enabled, + "Seperate_Write_Queue_Enable", + "0"); + option_parser_register(opp, "-Write_Queue_Size", OPT_CSTR, &write_queue_size_opt, + "Write_Queue_Size", + "32:28:16"); + option_parser_register(opp, "-Elimnate_rw_turnaround", OPT_BOOL, &elimnate_rw_turnaround, + "elimnate_rw_turnaround i.e set tWTR and tRTW = 0", + "0"); + option_parser_register(opp, "-icnt_flit_size", OPT_UINT32, &icnt_flit_size, + "icnt_flit_size", + "32"); + m_address_mapping.addrdec_setoption(opp); } -void shader_core_config::reg_options(class OptionParser *opp) { - option_parser_register(opp, "-gpgpu_simd_model", OPT_INT32, &model, - "1 = post-dominator", "1"); - option_parser_register( - opp, "-gpgpu_shader_core_pipeline", OPT_CSTR, - &gpgpu_shader_core_pipeline_opt, - "shader core pipeline config, i.e., {<nthread>:<warpsize>}", "1024:32"); - option_parser_register(opp, "-gpgpu_tex_cache:l1", OPT_CSTR, - &m_L1T_config.m_config_string, - "per-shader L1 texture cache (READ-ONLY) config " - " {<nsets>:<bsize>:<assoc>,<rep>:<wr>:<alloc>:<wr_" - "alloc>,<mshr>:<N>:<merge>,<mq>:<rf>}", - "8:128:5,L:R:m:N,F:128:4,128:2"); - option_parser_register( - opp, "-gpgpu_const_cache:l1", OPT_CSTR, &m_L1C_config.m_config_string, - "per-shader L1 constant memory cache (READ-ONLY) config " - " {<nsets>:<bsize>:<assoc>,<rep>:<wr>:<alloc>:<wr_alloc>,<mshr>:<N>:<" - "merge>,<mq>} ", - "64:64:2,L:R:f:N,A:2:32,4"); - option_parser_register(opp, "-gpgpu_cache:il1", OPT_CSTR, - &m_L1I_config.m_config_string, - "shader L1 instruction cache config " - " {<nsets>:<bsize>:<assoc>,<rep>:<wr>:<alloc>:<wr_" - "alloc>,<mshr>:<N>:<merge>,<mq>} ", - "4:256:4,L:R:f:N,A:2:32,4"); - option_parser_register(opp, "-gpgpu_cache:dl1", OPT_CSTR, - &m_L1D_config.m_config_string, - "per-shader L1 data cache config " - " {<nsets>:<bsize>:<assoc>,<rep>:<wr>:<alloc>:<wr_" - "alloc>,<mshr>:<N>:<merge>,<mq> | none}", - "none"); - option_parser_register(opp, "-l1_banks", OPT_UINT32, &m_L1D_config.l1_banks, - "The number of L1 cache banks", "1"); - option_parser_register(opp, "-l1_latency", OPT_UINT32, - &m_L1D_config.l1_latency, "L1 Hit Latency", "1"); - option_parser_register(opp, "-smem_latency", OPT_UINT32, &smem_latency, - "smem Latency", "3"); - option_parser_register(opp, "-gpgpu_cache:dl1PrefL1", OPT_CSTR, - &m_L1D_config.m_config_stringPrefL1, - "per-shader L1 data cache config " - " {<nsets>:<bsize>:<assoc>,<rep>:<wr>:<alloc>:<wr_" - "alloc>,<mshr>:<N>:<merge>,<mq> | none}", - "none"); - option_parser_register(opp, "-gpgpu_cache:dl1PrefShared", OPT_CSTR, - &m_L1D_config.m_config_stringPrefShared, - "per-shader L1 data cache config " - " {<nsets>:<bsize>:<assoc>,<rep>:<wr>:<alloc>:<wr_" - "alloc>,<mshr>:<N>:<merge>,<mq> | none}", - "none"); - option_parser_register(opp, "-gmem_skip_L1D", OPT_BOOL, &gmem_skip_L1D, - "global memory access skip L1D cache (implements " - "-Xptxas -dlcm=cg, default=no skip)", - "0"); +void shader_core_config::reg_options(class OptionParser * opp) +{ + option_parser_register(opp, "-gpgpu_simd_model", OPT_INT32, &model, + "1 = post-dominator", "1"); + option_parser_register(opp, "-gpgpu_shader_core_pipeline", OPT_CSTR, &gpgpu_shader_core_pipeline_opt, + "shader core pipeline config, i.e., {<nthread>:<warpsize>}", + "1024:32"); + option_parser_register(opp, "-gpgpu_tex_cache:l1", OPT_CSTR, &m_L1T_config.m_config_string, + "per-shader L1 texture cache (READ-ONLY) config " + " {<nsets>:<bsize>:<assoc>,<rep>:<wr>:<alloc>:<wr_alloc>,<mshr>:<N>:<merge>,<mq>:<rf>}", + "8:128:5,L:R:m:N,F:128:4,128:2"); + option_parser_register(opp, "-gpgpu_const_cache:l1", OPT_CSTR, &m_L1C_config.m_config_string, + "per-shader L1 constant memory cache (READ-ONLY) config " + " {<nsets>:<bsize>:<assoc>,<rep>:<wr>:<alloc>:<wr_alloc>,<mshr>:<N>:<merge>,<mq>} ", + "64:64:2,L:R:f:N,A:2:32,4" ); + option_parser_register(opp, "-gpgpu_cache:il1", OPT_CSTR, &m_L1I_config.m_config_string, + "shader L1 instruction cache config " + " {<nsets>:<bsize>:<assoc>,<rep>:<wr>:<alloc>:<wr_alloc>,<mshr>:<N>:<merge>,<mq>} ", + "4:256:4,L:R:f:N,A:2:32,4" ); + option_parser_register(opp, "-gpgpu_cache:dl1", OPT_CSTR, &m_L1D_config.m_config_string, + "per-shader L1 data cache config " + " {<nsets>:<bsize>:<assoc>,<rep>:<wr>:<alloc>:<wr_alloc>,<mshr>:<N>:<merge>,<mq> | none}", + "none" ); + option_parser_register(opp, "-l1_banks", OPT_UINT32, &m_L1D_config.l1_banks, + "The number of L1 cache banks", + "1"); + option_parser_register(opp, "-l1_latency", OPT_UINT32, &m_L1D_config.l1_latency, + "L1 Hit Latency", + "1"); + option_parser_register(opp, "-smem_latency", OPT_UINT32, &smem_latency, + "smem Latency", + "3"); + option_parser_register(opp, "-gpgpu_cache:dl1PrefL1", OPT_CSTR, &m_L1D_config.m_config_stringPrefL1, + "per-shader L1 data cache config " + " {<nsets>:<bsize>:<assoc>,<rep>:<wr>:<alloc>:<wr_alloc>,<mshr>:<N>:<merge>,<mq> | none}", + "none" ); + option_parser_register(opp, "-gpgpu_cache:dl1PrefShared", OPT_CSTR, &m_L1D_config.m_config_stringPrefShared, + "per-shader L1 data cache config " + " {<nsets>:<bsize>:<assoc>,<rep>:<wr>:<alloc>:<wr_alloc>,<mshr>:<N>:<merge>,<mq> | none}", + "none" ); + option_parser_register(opp, "-gmem_skip_L1D", OPT_BOOL, &gmem_skip_L1D, + "global memory access skip L1D cache (implements -Xptxas -dlcm=cg, default=no skip)", + "0"); + + option_parser_register(opp, "-gpgpu_perfect_mem", OPT_BOOL, &gpgpu_perfect_mem, + "enable perfect memory mode (no cache miss)", + "0"); + option_parser_register(opp, "-n_regfile_gating_group", OPT_UINT32, &n_regfile_gating_group, + "group of lanes that should be read/written together)", + "4"); + option_parser_register(opp, "-gpgpu_clock_gated_reg_file", OPT_BOOL, &gpgpu_clock_gated_reg_file, + "enable clock gated reg file for power calculations", + "0"); + option_parser_register(opp, "-gpgpu_clock_gated_lanes", OPT_BOOL, &gpgpu_clock_gated_lanes, + "enable clock gated lanes for power calculations", + "0"); + option_parser_register(opp, "-gpgpu_shader_registers", OPT_UINT32, &gpgpu_shader_registers, + "Number of registers per shader core. Limits number of concurrent CTAs. (default 8192)", + "8192"); + option_parser_register(opp, "-gpgpu_registers_per_block", OPT_UINT32, &gpgpu_registers_per_block, + "Maximum number of registers per CTA. (default 8192)", + "8192"); + option_parser_register(opp, "-gpgpu_ignore_resources_limitation", OPT_BOOL, &gpgpu_ignore_resources_limitation, + "gpgpu_ignore_resources_limitation (default 0)", + "0"); + option_parser_register(opp, "-gpgpu_shader_cta", OPT_UINT32, &max_cta_per_core, + "Maximum number of concurrent CTAs in shader (default 8)", + "8"); + option_parser_register(opp, "-gpgpu_num_cta_barriers", OPT_UINT32, &max_barriers_per_cta, + "Maximum number of named barriers per CTA (default 16)", + "16"); + option_parser_register(opp, "-gpgpu_n_clusters", OPT_UINT32, &n_simt_clusters, + "number of processing clusters", + "10"); + option_parser_register(opp, "-gpgpu_n_cores_per_cluster", OPT_UINT32, &n_simt_cores_per_cluster, + "number of simd cores per cluster", + "3"); + option_parser_register(opp, "-gpgpu_n_cluster_ejection_buffer_size", OPT_UINT32, &n_simt_ejection_buffer_size, + "number of packets in ejection buffer", + "8"); + option_parser_register(opp, "-gpgpu_n_ldst_response_buffer_size", OPT_UINT32, &ldst_unit_response_queue_size, + "number of response packets in ld/st unit ejection buffer", + "2"); + option_parser_register(opp, "-gpgpu_shmem_per_block", OPT_UINT32, &gpgpu_shmem_per_block, + "Size of shared memory per thread block or CTA (default 48kB)", + "49152"); + option_parser_register(opp, "-gpgpu_shmem_size", OPT_UINT32, &gpgpu_shmem_size, + "Size of shared memory per shader core (default 16kB)", + "16384"); + option_parser_register(opp, "-adaptive_cache_config", OPT_BOOL, &adaptive_volta_cache_config, + "adaptive_cache_config", + "0"); + option_parser_register(opp, "-gpgpu_shmem_sizeDefault", OPT_UINT32, &gpgpu_shmem_sizeDefault, + "Size of shared memory per shader core (default 16kB)", + "16384"); + option_parser_register(opp, "-gpgpu_shmem_size_PrefL1", OPT_UINT32, &gpgpu_shmem_sizePrefL1, + "Size of shared memory per shader core (default 16kB)", + "16384"); + option_parser_register(opp, "-gpgpu_shmem_size_PrefShared", OPT_UINT32, &gpgpu_shmem_sizePrefShared, + "Size of shared memory per shader core (default 16kB)", + "16384"); + option_parser_register(opp, "-gpgpu_shmem_num_banks", OPT_UINT32, &num_shmem_bank, + "Number of banks in the shared memory in each shader core (default 16)", + "16"); + option_parser_register(opp, "-gpgpu_shmem_limited_broadcast", OPT_BOOL, &shmem_limited_broadcast, + "Limit shared memory to do one broadcast per cycle (default on)", + "1"); + option_parser_register(opp, "-gpgpu_shmem_warp_parts", OPT_INT32, &mem_warp_parts, + "Number of portions a warp is divided into for shared memory bank conflict check ", + "2"); + option_parser_register(opp, "-mem_unit_ports", OPT_INT32, &mem_unit_ports, + "The number of memory transactions allowed per core cycle", + "1"); + option_parser_register(opp, "-gpgpu_shmem_warp_parts", OPT_INT32, &mem_warp_parts, + "Number of portions a warp is divided into for shared memory bank conflict check ", + "2"); + option_parser_register(opp, "-gpgpu_warpdistro_shader", OPT_INT32, &gpgpu_warpdistro_shader, + "Specify which shader core to collect the warp size distribution from", + "-1"); + option_parser_register(opp, "-gpgpu_warp_issue_shader", OPT_INT32, &gpgpu_warp_issue_shader, + "Specify which shader core to collect the warp issue distribution from", + "0"); + option_parser_register(opp, "-gpgpu_local_mem_map", OPT_BOOL, &gpgpu_local_mem_map, + "Mapping from local memory space address to simulated GPU physical address space (default = enabled)", + "1"); + option_parser_register(opp, "-gpgpu_num_reg_banks", OPT_INT32, &gpgpu_num_reg_banks, + "Number of register banks (default = 8)", + "8"); + option_parser_register(opp, "-gpgpu_reg_bank_use_warp_id", OPT_BOOL, &gpgpu_reg_bank_use_warp_id, + "Use warp ID in mapping registers to banks (default = off)", + "0"); + option_parser_register(opp, "-sub_core_model", OPT_BOOL, &sub_core_model, + "Sub Core Volta/Pascal model (default = off)", + "0"); + option_parser_register(opp, "-enable_specialized_operand_collector", OPT_BOOL, &enable_specialized_operand_collector, + "enable_specialized_operand_collector", + "1"); + option_parser_register(opp, "-gpgpu_operand_collector_num_units_sp", OPT_INT32, &gpgpu_operand_collector_num_units_sp, + "number of collector units (default = 4)", + "4"); + option_parser_register(opp, "-gpgpu_operand_collector_num_units_dp", OPT_INT32, &gpgpu_operand_collector_num_units_dp, + "number of collector units (default = 0)", + "0"); + option_parser_register(opp, "-gpgpu_operand_collector_num_units_sfu", OPT_INT32, &gpgpu_operand_collector_num_units_sfu, + "number of collector units (default = 4)", + "4"); + option_parser_register(opp, "-gpgpu_operand_collector_num_units_int", OPT_INT32, &gpgpu_operand_collector_num_units_int, + "number of collector units (default = 0)", + "0"); + option_parser_register(opp, "-gpgpu_operand_collector_num_units_tensor_core", OPT_INT32, &gpgpu_operand_collector_num_units_tensor_core, + "number of collector units (default = 4)", + "4"); + option_parser_register(opp, "-gpgpu_operand_collector_num_units_mem", OPT_INT32, &gpgpu_operand_collector_num_units_mem, + "number of collector units (default = 2)", + "2"); + option_parser_register(opp, "-gpgpu_operand_collector_num_units_gen", OPT_INT32, &gpgpu_operand_collector_num_units_gen, + "number of collector units (default = 0)", + "0"); + option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_sp", OPT_INT32, &gpgpu_operand_collector_num_in_ports_sp, + "number of collector unit in ports (default = 1)", + "1"); + option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_dp", OPT_INT32, &gpgpu_operand_collector_num_in_ports_dp, + "number of collector unit in ports (default = 0)", + "0"); + option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_sfu", OPT_INT32, &gpgpu_operand_collector_num_in_ports_sfu, + "number of collector unit in ports (default = 1)", + "1"); + option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_int", OPT_INT32, &gpgpu_operand_collector_num_in_ports_int, + "number of collector unit in ports (default = 0)", + "0"); + option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_tensor_core", OPT_INT32, &gpgpu_operand_collector_num_in_ports_tensor_core, + "number of collector unit in ports (default = 1)", + "1"); + option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_mem", OPT_INT32, &gpgpu_operand_collector_num_in_ports_mem, + "number of collector unit in ports (default = 1)", + "1"); + option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_gen", OPT_INT32, &gpgpu_operand_collector_num_in_ports_gen, + "number of collector unit in ports (default = 0)", + "0"); + option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_sp", OPT_INT32, &gpgpu_operand_collector_num_out_ports_sp, + "number of collector unit in ports (default = 1)", + "1"); + option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_dp", OPT_INT32, &gpgpu_operand_collector_num_out_ports_dp, + "number of collector unit in ports (default = 0)", + "0"); + option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_sfu", OPT_INT32, &gpgpu_operand_collector_num_out_ports_sfu, + "number of collector unit in ports (default = 1)", + "1"); + option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_int", OPT_INT32, &gpgpu_operand_collector_num_out_ports_int, + "number of collector unit in ports (default = 0)", + "0"); + option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_tensor_core", OPT_INT32, &gpgpu_operand_collector_num_out_ports_tensor_core, + "number of collector unit in ports (default = 1)", + "1"); + option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_mem", OPT_INT32, &gpgpu_operand_collector_num_out_ports_mem, + "number of collector unit in ports (default = 1)", + "1"); + option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_gen", OPT_INT32, &gpgpu_operand_collector_num_out_ports_gen, + "number of collector unit in ports (default = 0)", + "0"); + option_parser_register(opp, "-gpgpu_coalesce_arch", OPT_INT32, &gpgpu_coalesce_arch, + "Coalescing arch (GT200 = 13, Fermi = 20)", + "13"); + option_parser_register(opp, "-gpgpu_num_sched_per_core", OPT_INT32, &gpgpu_num_sched_per_core, + "Number of warp schedulers per core", + "1"); + option_parser_register(opp, "-gpgpu_max_insn_issue_per_warp", OPT_INT32, &gpgpu_max_insn_issue_per_warp, + "Max number of instructions that can be issued per warp in one cycle by scheduler (either 1 or 2)", + "2"); + option_parser_register(opp, "-gpgpu_dual_issue_diff_exec_units", OPT_BOOL, &gpgpu_dual_issue_diff_exec_units, + "should dual issue use two different execution unit resources (Default = 1)", + "1"); + option_parser_register(opp, "-gpgpu_simt_core_sim_order", OPT_INT32, &simt_core_sim_order, + "Select the simulation order of cores in a cluster (0=Fix, 1=Round-Robin)", + "1"); + option_parser_register(opp, "-gpgpu_pipeline_widths", OPT_CSTR, &pipeline_widths_string, + "Pipeline widths " + "ID_OC_SP,ID_OC_DP,ID_OC_INT,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_DP,OC_EX_INT,OC_EX_SFU,OC_EX_MEM,EX_WB,ID_OC_TENSOR_CORE,OC_EX_TENSOR_CORE", + "1,1,1,1,1,1,1,1,1,1,1,1,1" ); + option_parser_register(opp, "-gpgpu_tensor_core_avail", OPT_INT32, &gpgpu_tensor_core_avail, + "Tensor Core Available (default=0)", + "0"); + option_parser_register(opp, "-gpgpu_num_sp_units", OPT_INT32, &gpgpu_num_sp_units, + "Number of SP units (default=1)", + "1"); + option_parser_register(opp, "-gpgpu_num_dp_units", OPT_INT32, &gpgpu_num_dp_units, + "Number of DP units (default=0)", + "0"); + option_parser_register(opp, "-gpgpu_num_int_units", OPT_INT32, &gpgpu_num_int_units, + "Number of INT units (default=0)", + "0"); + option_parser_register(opp, "-gpgpu_num_sfu_units", OPT_INT32, &gpgpu_num_sfu_units, + "Number of SF units (default=1)", + "1"); + option_parser_register(opp, "-gpgpu_num_tensor_core_units", OPT_INT32, &gpgpu_num_tensor_core_units, + "Number of tensor_core units (default=1)", + "1"); + option_parser_register(opp, "-gpgpu_num_mem_units", OPT_INT32, &gpgpu_num_mem_units, + "Number if ldst units (default=1) WARNING: not hooked up to anything", + "1"); + option_parser_register(opp, "-gpgpu_scheduler", OPT_CSTR, &gpgpu_scheduler_string, + "Scheduler configuration: < lrr | gto | two_level_active > " + "If two_level_active:<num_active_warps>:<inner_prioritization>:<outer_prioritization>" + "For complete list of prioritization values see shader.h enum scheduler_prioritization_type" + "Default: gto", + "gto"); - option_parser_register(opp, "-gpgpu_perfect_mem", OPT_BOOL, - &gpgpu_perfect_mem, - "enable perfect memory mode (no cache miss)", "0"); - option_parser_register( - opp, "-n_regfile_gating_group", OPT_UINT32, &n_regfile_gating_group, - "group of lanes that should be read/written together)", "4"); - option_parser_register( - opp, "-gpgpu_clock_gated_reg_file", OPT_BOOL, &gpgpu_clock_gated_reg_file, - "enable clock gated reg file for power calculations", "0"); - option_parser_register( - opp, "-gpgpu_clock_gated_lanes", OPT_BOOL, &gpgpu_clock_gated_lanes, - "enable clock gated lanes for power calculations", "0"); - option_parser_register(opp, "-gpgpu_shader_registers", OPT_UINT32, - &gpgpu_shader_registers, - "Number of registers per shader core. Limits number " - "of concurrent CTAs. (default 8192)", - "8192"); - option_parser_register( - opp, "-gpgpu_registers_per_block", OPT_UINT32, &gpgpu_registers_per_block, - "Maximum number of registers per CTA. (default 8192)", "8192"); - option_parser_register(opp, "-gpgpu_ignore_resources_limitation", OPT_BOOL, - &gpgpu_ignore_resources_limitation, - "gpgpu_ignore_resources_limitation (default 0)", "0"); - option_parser_register( - opp, "-gpgpu_shader_cta", OPT_UINT32, &max_cta_per_core, - "Maximum number of concurrent CTAs in shader (default 8)", "8"); - option_parser_register( - opp, "-gpgpu_num_cta_barriers", OPT_UINT32, &max_barriers_per_cta, - "Maximum number of named barriers per CTA (default 16)", "16"); - option_parser_register(opp, "-gpgpu_n_clusters", OPT_UINT32, &n_simt_clusters, - "number of processing clusters", "10"); - option_parser_register(opp, "-gpgpu_n_cores_per_cluster", OPT_UINT32, - &n_simt_cores_per_cluster, - "number of simd cores per cluster", "3"); - option_parser_register(opp, "-gpgpu_n_cluster_ejection_buffer_size", - OPT_UINT32, &n_simt_ejection_buffer_size, - "number of packets in ejection buffer", "8"); - option_parser_register( - opp, "-gpgpu_n_ldst_response_buffer_size", OPT_UINT32, - &ldst_unit_response_queue_size, - "number of response packets in ld/st unit ejection buffer", "2"); - option_parser_register( - opp, "-gpgpu_shmem_per_block", OPT_UINT32, &gpgpu_shmem_per_block, - "Size of shared memory per thread block or CTA (default 48kB)", "49152"); - option_parser_register( - opp, "-gpgpu_shmem_size", OPT_UINT32, &gpgpu_shmem_size, - "Size of shared memory per shader core (default 16kB)", "16384"); - option_parser_register(opp, "-adaptive_cache_config", OPT_BOOL, - &adaptive_volta_cache_config, "adaptive_cache_config", - "0"); - option_parser_register( - opp, "-gpgpu_shmem_sizeDefault", OPT_UINT32, &gpgpu_shmem_sizeDefault, - "Size of shared memory per shader core (default 16kB)", "16384"); - option_parser_register( - opp, "-gpgpu_shmem_size_PrefL1", OPT_UINT32, &gpgpu_shmem_sizePrefL1, - "Size of shared memory per shader core (default 16kB)", "16384"); - option_parser_register(opp, "-gpgpu_shmem_size_PrefShared", OPT_UINT32, - &gpgpu_shmem_sizePrefShared, - "Size of shared memory per shader core (default 16kB)", - "16384"); - option_parser_register( - opp, "-gpgpu_shmem_num_banks", OPT_UINT32, &num_shmem_bank, - "Number of banks in the shared memory in each shader core (default 16)", - "16"); - option_parser_register( - opp, "-gpgpu_shmem_limited_broadcast", OPT_BOOL, &shmem_limited_broadcast, - "Limit shared memory to do one broadcast per cycle (default on)", "1"); - option_parser_register(opp, "-gpgpu_shmem_warp_parts", OPT_INT32, - &mem_warp_parts, - "Number of portions a warp is divided into for shared " - "memory bank conflict check ", - "2"); - option_parser_register( - opp, "-mem_unit_ports", OPT_INT32, &mem_unit_ports, - "The number of memory transactions allowed per core cycle", "1"); - option_parser_register(opp, "-gpgpu_shmem_warp_parts", OPT_INT32, - &mem_warp_parts, - "Number of portions a warp is divided into for shared " - "memory bank conflict check ", - "2"); - option_parser_register( - opp, "-gpgpu_warpdistro_shader", OPT_INT32, &gpgpu_warpdistro_shader, - "Specify which shader core to collect the warp size distribution from", - "-1"); - option_parser_register( - opp, "-gpgpu_warp_issue_shader", OPT_INT32, &gpgpu_warp_issue_shader, - "Specify which shader core to collect the warp issue distribution from", - "0"); - option_parser_register(opp, "-gpgpu_local_mem_map", OPT_BOOL, - &gpgpu_local_mem_map, - "Mapping from local memory space address to simulated " - "GPU physical address space (default = enabled)", - "1"); - option_parser_register(opp, "-gpgpu_num_reg_banks", OPT_INT32, - &gpgpu_num_reg_banks, - "Number of register banks (default = 8)", "8"); - option_parser_register( - opp, "-gpgpu_reg_bank_use_warp_id", OPT_BOOL, &gpgpu_reg_bank_use_warp_id, - "Use warp ID in mapping registers to banks (default = off)", "0"); - option_parser_register(opp, "-sub_core_model", OPT_BOOL, &sub_core_model, - "Sub Core Volta/Pascal model (default = off)", "0"); - option_parser_register(opp, "-enable_specialized_operand_collector", OPT_BOOL, - &enable_specialized_operand_collector, - "enable_specialized_operand_collector", "1"); - option_parser_register(opp, "-gpgpu_operand_collector_num_units_sp", - OPT_INT32, &gpgpu_operand_collector_num_units_sp, - "number of collector units (default = 4)", "4"); - option_parser_register(opp, "-gpgpu_operand_collector_num_units_dp", - OPT_INT32, &gpgpu_operand_collector_num_units_dp, - "number of collector units (default = 0)", "0"); - option_parser_register(opp, "-gpgpu_operand_collector_num_units_sfu", - OPT_INT32, &gpgpu_operand_collector_num_units_sfu, - "number of collector units (default = 4)", "4"); - option_parser_register(opp, "-gpgpu_operand_collector_num_units_int", - OPT_INT32, &gpgpu_operand_collector_num_units_int, - "number of collector units (default = 0)", "0"); - option_parser_register(opp, "-gpgpu_operand_collector_num_units_tensor_core", - OPT_INT32, - &gpgpu_operand_collector_num_units_tensor_core, - "number of collector units (default = 4)", "4"); - option_parser_register(opp, "-gpgpu_operand_collector_num_units_mem", - OPT_INT32, &gpgpu_operand_collector_num_units_mem, - "number of collector units (default = 2)", "2"); - option_parser_register(opp, "-gpgpu_operand_collector_num_units_gen", - OPT_INT32, &gpgpu_operand_collector_num_units_gen, - "number of collector units (default = 0)", "0"); - option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_sp", - OPT_INT32, &gpgpu_operand_collector_num_in_ports_sp, - "number of collector unit in ports (default = 1)", - "1"); - option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_dp", - OPT_INT32, &gpgpu_operand_collector_num_in_ports_dp, - "number of collector unit in ports (default = 0)", - "0"); - option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_sfu", - OPT_INT32, &gpgpu_operand_collector_num_in_ports_sfu, - "number of collector unit in ports (default = 1)", - "1"); - option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_int", - OPT_INT32, &gpgpu_operand_collector_num_in_ports_int, - "number of collector unit in ports (default = 0)", - "0"); - option_parser_register( - opp, "-gpgpu_operand_collector_num_in_ports_tensor_core", OPT_INT32, - &gpgpu_operand_collector_num_in_ports_tensor_core, - "number of collector unit in ports (default = 1)", "1"); - option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_mem", - OPT_INT32, &gpgpu_operand_collector_num_in_ports_mem, - "number of collector unit in ports (default = 1)", - "1"); - option_parser_register(opp, "-gpgpu_operand_collector_num_in_ports_gen", - OPT_INT32, &gpgpu_operand_collector_num_in_ports_gen, - "number of collector unit in ports (default = 0)", - "0"); - option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_sp", - OPT_INT32, &gpgpu_operand_collector_num_out_ports_sp, - "number of collector unit in ports (default = 1)", - "1"); - option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_dp", - OPT_INT32, &gpgpu_operand_collector_num_out_ports_dp, - "number of collector unit in ports (default = 0)", - "0"); - option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_sfu", - OPT_INT32, &gpgpu_operand_collector_num_out_ports_sfu, - "number of collector unit in ports (default = 1)", - "1"); - option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_int", - OPT_INT32, &gpgpu_operand_collector_num_out_ports_int, - "number of collector unit in ports (default = 0)", - "0"); - option_parser_register( - opp, "-gpgpu_operand_collector_num_out_ports_tensor_core", OPT_INT32, - &gpgpu_operand_collector_num_out_ports_tensor_core, - "number of collector unit in ports (default = 1)", "1"); - option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_mem", - OPT_INT32, &gpgpu_operand_collector_num_out_ports_mem, - "number of collector unit in ports (default = 1)", - "1"); - option_parser_register(opp, "-gpgpu_operand_collector_num_out_ports_gen", - OPT_INT32, &gpgpu_operand_collector_num_out_ports_gen, - "number of collector unit in ports (default = 0)", - "0"); - option_parser_register(opp, "-gpgpu_coalesce_arch", OPT_INT32, - &gpgpu_coalesce_arch, - "Coalescing arch (GT200 = 13, Fermi = 20)", "13"); - option_parser_register(opp, "-gpgpu_num_sched_per_core", OPT_INT32, - &gpgpu_num_sched_per_core, - "Number of warp schedulers per core", "1"); - option_parser_register(opp, "-gpgpu_max_insn_issue_per_warp", OPT_INT32, - &gpgpu_max_insn_issue_per_warp, - "Max number of instructions that can be issued per " - "warp in one cycle by scheduler (either 1 or 2)", - "2"); - option_parser_register(opp, "-gpgpu_dual_issue_diff_exec_units", OPT_BOOL, - &gpgpu_dual_issue_diff_exec_units, - "should dual issue use two different execution unit " - "resources (Default = 1)", - "1"); - option_parser_register(opp, "-gpgpu_simt_core_sim_order", OPT_INT32, - &simt_core_sim_order, - "Select the simulation order of cores in a cluster " - "(0=Fix, 1=Round-Robin)", - "1"); - option_parser_register( - opp, "-gpgpu_pipeline_widths", OPT_CSTR, &pipeline_widths_string, - "Pipeline widths " - "ID_OC_SP,ID_OC_DP,ID_OC_INT,ID_OC_SFU,ID_OC_MEM,OC_EX_SP,OC_EX_DP,OC_EX_" - "INT,OC_EX_SFU,OC_EX_MEM,EX_WB,ID_OC_TENSOR_CORE,OC_EX_TENSOR_CORE", - "1,1,1,1,1,1,1,1,1,1,1,1,1"); - option_parser_register(opp, "-gpgpu_tensor_core_avail", OPT_INT32, - &gpgpu_tensor_core_avail, - "Tensor Core Available (default=0)", "0"); - option_parser_register(opp, "-gpgpu_num_sp_units", OPT_INT32, - &gpgpu_num_sp_units, "Number of SP units (default=1)", - "1"); - option_parser_register(opp, "-gpgpu_num_dp_units", OPT_INT32, - &gpgpu_num_dp_units, "Number of DP units (default=0)", - "0"); - option_parser_register(opp, "-gpgpu_num_int_units", OPT_INT32, - &gpgpu_num_int_units, - "Number of INT units (default=0)", "0"); - option_parser_register(opp, "-gpgpu_num_sfu_units", OPT_INT32, - &gpgpu_num_sfu_units, "Number of SF units (default=1)", - "1"); - option_parser_register(opp, "-gpgpu_num_tensor_core_units", OPT_INT32, - &gpgpu_num_tensor_core_units, - "Number of tensor_core units (default=1)", "1"); - option_parser_register( - opp, "-gpgpu_num_mem_units", OPT_INT32, &gpgpu_num_mem_units, - "Number if ldst units (default=1) WARNING: not hooked up to anything", - "1"); - option_parser_register( - opp, "-gpgpu_scheduler", OPT_CSTR, &gpgpu_scheduler_string, - "Scheduler configuration: < lrr | gto | two_level_active > " - "If " - "two_level_active:<num_active_warps>:<inner_prioritization>:<outer_" - "prioritization>" - "For complete list of prioritization values see shader.h enum " - "scheduler_prioritization_type" - "Default: gto", - "gto"); + option_parser_register(opp, "-gpgpu_concurrent_kernel_sm", OPT_BOOL, &gpgpu_concurrent_kernel_sm, + "Support concurrent kernels on a SM (default = disabled)", + "0"); - option_parser_register( - opp, "-gpgpu_concurrent_kernel_sm", OPT_BOOL, &gpgpu_concurrent_kernel_sm, - "Support concurrent kernels on a SM (default = disabled)", "0"); } -void gpgpu_sim_config::reg_options(option_parser_t opp) { - gpgpu_functional_sim_config::reg_options(opp); - m_shader_config.reg_options(opp); - m_memory_config.reg_options(opp); - power_config::reg_options(opp); - option_parser_register(opp, "-gpgpu_max_cycle", OPT_INT64, &gpu_max_cycle_opt, - "terminates gpu simulation early (0 = no limit)", "0"); - option_parser_register(opp, "-gpgpu_max_insn", OPT_INT64, &gpu_max_insn_opt, - "terminates gpu simulation early (0 = no limit)", "0"); - option_parser_register(opp, "-gpgpu_max_cta", OPT_INT32, &gpu_max_cta_opt, - "terminates gpu simulation early (0 = no limit)", "0"); - option_parser_register( - opp, "-gpgpu_runtime_stat", OPT_CSTR, &gpgpu_runtime_stat, - "display runtime statistics such as dram utilization {<freq>:<flag>}", - "10000:0"); - option_parser_register(opp, "-liveness_message_freq", OPT_INT64, - &liveness_message_freq, - "Minimum number of seconds between simulation " - "liveness messages (0 = always print)", - "1"); - option_parser_register(opp, "-gpgpu_compute_capability_major", OPT_UINT32, - &gpgpu_compute_capability_major, - "Major compute capability version number", "7"); - option_parser_register(opp, "-gpgpu_compute_capability_minor", OPT_UINT32, - &gpgpu_compute_capability_minor, - "Minor compute capability version number", "0"); - option_parser_register(opp, "-gpgpu_flush_l1_cache", OPT_BOOL, - &gpgpu_flush_l1_cache, - "Flush L1 cache at the end of each kernel call", "0"); - option_parser_register(opp, "-gpgpu_flush_l2_cache", OPT_BOOL, - &gpgpu_flush_l2_cache, - "Flush L2 cache at the end of each kernel call", "0"); - option_parser_register( - opp, "-gpgpu_deadlock_detect", OPT_BOOL, &gpu_deadlock_detect, - "Stop the simulation at deadlock (1=on (default), 0=off)", "1"); - option_parser_register( - opp, "-gpgpu_ptx_instruction_classification", OPT_INT32, - &(gpgpu_ctx->func_sim->gpgpu_ptx_instruction_classification), - "if enabled will classify ptx instruction types per kernel (Max 255 " - "kernels now)", - "0"); - option_parser_register( - opp, "-gpgpu_ptx_sim_mode", OPT_INT32, - &(gpgpu_ctx->func_sim->g_ptx_sim_mode), - "Select between Performance (default) or Functional simulation (1)", "0"); - option_parser_register(opp, "-gpgpu_clock_domains", OPT_CSTR, - &gpgpu_clock_domains, - "Clock Domain Frequencies in MhZ {<Core Clock>:<ICNT " - "Clock>:<L2 Clock>:<DRAM Clock>}", - "500.0:2000.0:2000.0:2000.0"); - option_parser_register( - opp, "-gpgpu_max_concurrent_kernel", OPT_INT32, &max_concurrent_kernel, - "maximum kernels that can run concurrently on GPU", "8"); - option_parser_register( - opp, "-gpgpu_cflog_interval", OPT_INT32, &gpgpu_cflog_interval, - "Interval between each snapshot in control flow logger", "0"); - option_parser_register(opp, "-visualizer_enabled", OPT_BOOL, - &g_visualizer_enabled, - "Turn on visualizer output (1=On, 0=Off)", "1"); - option_parser_register(opp, "-visualizer_outputfile", OPT_CSTR, - &g_visualizer_filename, - "Specifies the output log file for visualizer", NULL); - option_parser_register( - opp, "-visualizer_zlevel", OPT_INT32, &g_visualizer_zlevel, - "Compression level of the visualizer output log (0=no comp, 9=highest)", - "6"); - option_parser_register(opp, "-gpgpu_stack_size_limit", OPT_INT32, - &stack_size_limit, "GPU thread stack size", "1024"); - option_parser_register(opp, "-gpgpu_heap_size_limit", OPT_INT32, - &heap_size_limit, "GPU malloc heap size ", "8388608"); - option_parser_register(opp, "-gpgpu_runtime_sync_depth_limit", OPT_INT32, - &runtime_sync_depth_limit, - "GPU device runtime synchronize depth", "2"); - option_parser_register(opp, "-gpgpu_runtime_pending_launch_count_limit", - OPT_INT32, &runtime_pending_launch_count_limit, - "GPU device runtime pending launch count", "2048"); - option_parser_register(opp, "-trace_enabled", OPT_BOOL, &Trace::enabled, - "Turn on traces", "0"); - option_parser_register(opp, "-trace_components", OPT_CSTR, &Trace::config_str, - "comma seperated list of traces to enable. " - "Complete list found in trace_streams.tup. " - "Default none", - "none"); - option_parser_register( - opp, "-trace_sampling_core", OPT_INT32, &Trace::sampling_core, - "The core which is printed using CORE_DPRINTF. Default 0", "0"); - option_parser_register(opp, "-trace_sampling_memory_partition", OPT_INT32, - &Trace::sampling_memory_partition, - "The memory partition which is printed using " - "MEMPART_DPRINTF. Default -1 (i.e. all)", - "-1"); - gpgpu_ctx->stats->ptx_file_line_stats_options(opp); +void gpgpu_sim_config::reg_options(option_parser_t opp) +{ + gpgpu_functional_sim_config::reg_options(opp); + m_shader_config.reg_options(opp); + m_memory_config.reg_options(opp); + power_config::reg_options(opp); + option_parser_register(opp, "-gpgpu_max_cycle", OPT_INT64, &gpu_max_cycle_opt, + "terminates gpu simulation early (0 = no limit)", + "0"); + option_parser_register(opp, "-gpgpu_max_insn", OPT_INT64, &gpu_max_insn_opt, + "terminates gpu simulation early (0 = no limit)", + "0"); + option_parser_register(opp, "-gpgpu_max_cta", OPT_INT32, &gpu_max_cta_opt, + "terminates gpu simulation early (0 = no limit)", + "0"); + option_parser_register(opp, "-gpgpu_runtime_stat", OPT_CSTR, &gpgpu_runtime_stat, + "display runtime statistics such as dram utilization {<freq>:<flag>}", + "10000:0"); + option_parser_register(opp, "-liveness_message_freq", OPT_INT64, &liveness_message_freq, + "Minimum number of seconds between simulation liveness messages (0 = always print)", + "1"); + option_parser_register(opp, "-gpgpu_compute_capability_major", OPT_UINT32, &gpgpu_compute_capability_major, + "Major compute capability version number", + "7"); + option_parser_register(opp, "-gpgpu_compute_capability_minor", OPT_UINT32, &gpgpu_compute_capability_minor, + "Minor compute capability version number", + "0"); + option_parser_register(opp, "-gpgpu_flush_l1_cache", OPT_BOOL, &gpgpu_flush_l1_cache, + "Flush L1 cache at the end of each kernel call", + "0"); + option_parser_register(opp, "-gpgpu_flush_l2_cache", OPT_BOOL, &gpgpu_flush_l2_cache, + "Flush L2 cache at the end of each kernel call", + "0"); + option_parser_register(opp, "-gpgpu_deadlock_detect", OPT_BOOL, &gpu_deadlock_detect, + "Stop the simulation at deadlock (1=on (default), 0=off)", + "1"); + option_parser_register(opp, "-gpgpu_ptx_instruction_classification", OPT_INT32, + &(gpgpu_ctx->func_sim->gpgpu_ptx_instruction_classification), + "if enabled will classify ptx instruction types per kernel (Max 255 kernels now)", + "0"); + option_parser_register(opp, "-gpgpu_ptx_sim_mode", OPT_INT32, &(gpgpu_ctx->func_sim->g_ptx_sim_mode), + "Select between Performance (default) or Functional simulation (1)", + "0"); + option_parser_register(opp, "-gpgpu_clock_domains", OPT_CSTR, &gpgpu_clock_domains, + "Clock Domain Frequencies in MhZ {<Core Clock>:<ICNT Clock>:<L2 Clock>:<DRAM Clock>}", + "500.0:2000.0:2000.0:2000.0"); + option_parser_register(opp, "-gpgpu_max_concurrent_kernel", OPT_INT32, &max_concurrent_kernel, + "maximum kernels that can run concurrently on GPU", "8" ); + option_parser_register(opp, "-gpgpu_cflog_interval", OPT_INT32, &gpgpu_cflog_interval, + "Interval between each snapshot in control flow logger", + "0"); + option_parser_register(opp, "-visualizer_enabled", OPT_BOOL, + &g_visualizer_enabled, "Turn on visualizer output (1=On, 0=Off)", + "1"); + option_parser_register(opp, "-visualizer_outputfile", OPT_CSTR, + &g_visualizer_filename, "Specifies the output log file for visualizer", + NULL); + option_parser_register(opp, "-visualizer_zlevel", OPT_INT32, + &g_visualizer_zlevel, "Compression level of the visualizer output log (0=no comp, 9=highest)", + "6"); + option_parser_register(opp, "-gpgpu_stack_size_limit", OPT_INT32, &stack_size_limit, + "GPU thread stack size", "1024" ); + option_parser_register(opp, "-gpgpu_heap_size_limit", OPT_INT32, &heap_size_limit, + "GPU malloc heap size ", "8388608" ); + option_parser_register(opp, "-gpgpu_runtime_sync_depth_limit", OPT_INT32, &runtime_sync_depth_limit, + "GPU device runtime synchronize depth", "2" ); + option_parser_register(opp, "-gpgpu_runtime_pending_launch_count_limit", OPT_INT32, &runtime_pending_launch_count_limit, + "GPU device runtime pending launch count", "2048" ); + option_parser_register(opp, "-trace_enabled", OPT_BOOL, + &Trace::enabled, "Turn on traces", + "0"); + option_parser_register(opp, "-trace_components", OPT_CSTR, + &Trace::config_str, "comma seperated list of traces to enable. " + "Complete list found in trace_streams.tup. " + "Default none", + "none"); + option_parser_register(opp, "-trace_sampling_core", OPT_INT32, + &Trace::sampling_core, "The core which is printed using CORE_DPRINTF. Default 0", + "0"); + option_parser_register(opp, "-trace_sampling_memory_partition", OPT_INT32, + &Trace::sampling_memory_partition, "The memory partition which is printed using MEMPART_DPRINTF. Default -1 (i.e. all)", + "-1"); + gpgpu_ctx->stats->ptx_file_line_stats_options(opp); - // Jin: kernel launch latency - option_parser_register(opp, "-gpgpu_kernel_launch_latency", OPT_INT32, - &(gpgpu_ctx->device_runtime->g_kernel_launch_latency), - "Kernel launch latency in cycles. Default: 0", "0"); - option_parser_register(opp, "-gpgpu_cdp_enabled", OPT_BOOL, - &(gpgpu_ctx->device_runtime->g_cdp_enabled), - "Turn on CDP", "0"); + //Jin: kernel launch latency + option_parser_register(opp, "-gpgpu_kernel_launch_latency", OPT_INT32, + &(gpgpu_ctx->device_runtime->g_kernel_launch_latency), "Kernel launch latency in cycles. Default: 0", + "0"); + option_parser_register(opp, "-gpgpu_cdp_enabled", OPT_BOOL, + &(gpgpu_ctx->device_runtime->g_cdp_enabled), "Turn on CDP", + "0"); } ///////////////////////////////////////////////////////////////////////////// -void increment_x_then_y_then_z(dim3 &i, const dim3 &bound) { - i.x++; - if (i.x >= bound.x) { - i.x = 0; - i.y++; - if (i.y >= bound.y) { - i.y = 0; - if (i.z < bound.z) i.z++; - } - } +void increment_x_then_y_then_z( dim3 &i, const dim3 &bound) +{ + i.x++; + if ( i.x >= bound.x ) { + i.x = 0; + i.y++; + if ( i.y >= bound.y ) { + i.y = 0; + if( i.z < bound.z ) + i.z++; + } + } } -void gpgpu_sim::launch(kernel_info_t *kinfo) { - unsigned cta_size = kinfo->threads_per_cta(); - if (cta_size > m_shader_config->n_thread_per_shader) { - printf( - "Execution error: Shader kernel CTA (block) size is too large for " - "microarch config.\n"); - printf(" CTA size (x*y*z) = %u, max supported = %u\n", - cta_size, m_shader_config->n_thread_per_shader); - printf( - " => either change -gpgpu_shader argument in " - "gpgpusim.config file or\n"); - printf( - " modify the CUDA source to decrease the kernel block " - "size.\n"); - abort(); - } - unsigned n = 0; - for (n = 0; n < m_running_kernels.size(); n++) { - if ((NULL == m_running_kernels[n]) || m_running_kernels[n]->done()) { - m_running_kernels[n] = kinfo; - break; - } - } - assert(n < m_running_kernels.size()); +void gpgpu_sim::launch( kernel_info_t *kinfo ) +{ + unsigned cta_size = kinfo->threads_per_cta(); + if ( cta_size > m_shader_config->n_thread_per_shader ) { + printf("Execution error: Shader kernel CTA (block) size is too large for microarch config.\n"); + printf(" CTA size (x*y*z) = %u, max supported = %u\n", cta_size, + m_shader_config->n_thread_per_shader ); + printf(" => either change -gpgpu_shader argument in gpgpusim.config file or\n"); + printf(" modify the CUDA source to decrease the kernel block size.\n"); + abort(); + } + unsigned n=0; + for(n=0; n < m_running_kernels.size(); n++ ) { + if( (NULL==m_running_kernels[n]) || m_running_kernels[n]->done() ) { + m_running_kernels[n] = kinfo; + break; + } + } + assert(n < m_running_kernels.size()); } -bool gpgpu_sim::can_start_kernel() { - for (unsigned n = 0; n < m_running_kernels.size(); n++) { - if ((NULL == m_running_kernels[n]) || m_running_kernels[n]->done()) - return true; - } - return false; +bool gpgpu_sim::can_start_kernel() +{ + for(unsigned n=0; n < m_running_kernels.size(); n++ ) { + if( (NULL==m_running_kernels[n]) || m_running_kernels[n]->done() ) + return true; + } + return false; } bool gpgpu_sim::hit_max_cta_count() const { - if (m_config.gpu_max_cta_opt != 0) { - if ((gpu_tot_issued_cta + m_total_cta_launched) >= m_config.gpu_max_cta_opt) - return true; - } - return false; + if (m_config.gpu_max_cta_opt != 0) { + if( (gpu_tot_issued_cta + m_total_cta_launched) >= m_config.gpu_max_cta_opt ) + return true; + } + return false; } bool gpgpu_sim::kernel_more_cta_left(kernel_info_t *kernel) const { - if (hit_max_cta_count()) return false; + if(hit_max_cta_count()) + return false; - if (kernel && !kernel->no_more_ctas_to_run()) return true; + if(kernel && !kernel->no_more_ctas_to_run()) + return true; - return false; + return false; } -bool gpgpu_sim::get_more_cta_left() const { - if (hit_max_cta_count()) return false; +bool gpgpu_sim::get_more_cta_left() const +{ + if(hit_max_cta_count()) + return false; - for (unsigned n = 0; n < m_running_kernels.size(); n++) { - if (m_running_kernels[n] && !m_running_kernels[n]->no_more_ctas_to_run()) - return true; - } - return false; + for(unsigned n=0; n < m_running_kernels.size(); n++ ) { + if( m_running_kernels[n] && !m_running_kernels[n]->no_more_ctas_to_run() ) + return true; + } + return false; } -kernel_info_t *gpgpu_sim::select_kernel() { - if (m_running_kernels[m_last_issued_kernel] && - !m_running_kernels[m_last_issued_kernel]->no_more_ctas_to_run()) { - unsigned launch_uid = m_running_kernels[m_last_issued_kernel]->get_uid(); - if (std::find(m_executed_kernel_uids.begin(), m_executed_kernel_uids.end(), - launch_uid) == m_executed_kernel_uids.end()) { - m_running_kernels[m_last_issued_kernel]->start_cycle = - gpu_sim_cycle + gpu_tot_sim_cycle; - m_executed_kernel_uids.push_back(launch_uid); - m_executed_kernel_names.push_back( - m_running_kernels[m_last_issued_kernel]->name()); +kernel_info_t *gpgpu_sim::select_kernel() +{ + if(m_running_kernels[m_last_issued_kernel] && + !m_running_kernels[m_last_issued_kernel]->no_more_ctas_to_run()) { + unsigned launch_uid = m_running_kernels[m_last_issued_kernel]->get_uid(); + if(std::find(m_executed_kernel_uids.begin(), m_executed_kernel_uids.end(), launch_uid) == m_executed_kernel_uids.end()) { + m_running_kernels[m_last_issued_kernel]->start_cycle = gpu_sim_cycle + gpu_tot_sim_cycle; + m_executed_kernel_uids.push_back(launch_uid); + m_executed_kernel_names.push_back(m_running_kernels[m_last_issued_kernel]->name()); + } + return m_running_kernels[m_last_issued_kernel]; } - return m_running_kernels[m_last_issued_kernel]; - } - for (unsigned n = 0; n < m_running_kernels.size(); n++) { - unsigned idx = - (n + m_last_issued_kernel + 1) % m_config.max_concurrent_kernel; - if (kernel_more_cta_left(m_running_kernels[idx])) { - m_last_issued_kernel = idx; - m_running_kernels[idx]->start_cycle = gpu_sim_cycle + gpu_tot_sim_cycle; - // record this kernel for stat print if it is the first time this kernel - // is selected for execution - unsigned launch_uid = m_running_kernels[idx]->get_uid(); - assert(std::find(m_executed_kernel_uids.begin(), - m_executed_kernel_uids.end(), - launch_uid) == m_executed_kernel_uids.end()); - m_executed_kernel_uids.push_back(launch_uid); - m_executed_kernel_names.push_back(m_running_kernels[idx]->name()); + for(unsigned n=0; n < m_running_kernels.size(); n++ ) { + unsigned idx = (n+m_last_issued_kernel+1)%m_config.max_concurrent_kernel; + if( kernel_more_cta_left(m_running_kernels[idx]) ){ + m_last_issued_kernel=idx; + m_running_kernels[idx]->start_cycle = gpu_sim_cycle + gpu_tot_sim_cycle; + // record this kernel for stat print if it is the first time this kernel is selected for execution + unsigned launch_uid = m_running_kernels[idx]->get_uid(); + assert(std::find(m_executed_kernel_uids.begin(), m_executed_kernel_uids.end(), launch_uid) == m_executed_kernel_uids.end()); + m_executed_kernel_uids.push_back(launch_uid); + m_executed_kernel_names.push_back(m_running_kernels[idx]->name()); - return m_running_kernels[idx]; + return m_running_kernels[idx]; + } } - } - return NULL; + return NULL; } -unsigned gpgpu_sim::finished_kernel() { - if (m_finished_kernel.empty()) return 0; - unsigned result = m_finished_kernel.front(); - m_finished_kernel.pop_front(); - return result; +unsigned gpgpu_sim::finished_kernel() +{ + if( m_finished_kernel.empty() ) + return 0; + unsigned result = m_finished_kernel.front(); + m_finished_kernel.pop_front(); + return result; } -void gpgpu_sim::set_kernel_done(kernel_info_t *kernel) { - unsigned uid = kernel->get_uid(); - m_finished_kernel.push_back(uid); - std::vector<kernel_info_t *>::iterator k; - for (k = m_running_kernels.begin(); k != m_running_kernels.end(); k++) { - if (*k == kernel) { - kernel->end_cycle = gpu_sim_cycle + gpu_tot_sim_cycle; - *k = NULL; - break; +void gpgpu_sim::set_kernel_done( kernel_info_t *kernel ) +{ + unsigned uid = kernel->get_uid(); + m_finished_kernel.push_back(uid); + std::vector<kernel_info_t*>::iterator k; + for( k=m_running_kernels.begin(); k!=m_running_kernels.end(); k++ ) { + if( *k == kernel ) { + kernel->end_cycle = gpu_sim_cycle + gpu_tot_sim_cycle; + *k = NULL; + break; + } } - } - assert(k != m_running_kernels.end()); + assert( k != m_running_kernels.end() ); } -void gpgpu_sim::stop_all_running_kernels() { - std::vector<kernel_info_t *>::iterator k; - for (k = m_running_kernels.begin(); k != m_running_kernels.end(); ++k) { - if (*k != NULL) { // If a kernel is active - set_kernel_done(*k); // Stop the kernel - assert(*k == NULL); +void gpgpu_sim::stop_all_running_kernels(){ + std::vector<kernel_info_t *>::iterator k; + for(k = m_running_kernels.begin(); k != m_running_kernels.end(); ++k){ + if(*k != NULL){ // If a kernel is active + set_kernel_done(*k); // Stop the kernel + assert(*k==NULL); + } } - } } -gpgpu_sim::gpgpu_sim(const gpgpu_sim_config &config, gpgpu_context *ctx) - : gpgpu_t(config, ctx), m_config(config) { - gpgpu_ctx = ctx; - m_shader_config = &m_config.m_shader_config; - m_memory_config = &m_config.m_memory_config; - ctx->ptx_parser->set_ptx_warp_size(m_shader_config); - ptx_file_line_stats_create_exposed_latency_tracker(m_config.num_shader()); +gpgpu_sim::gpgpu_sim( const gpgpu_sim_config &config, gpgpu_context* ctx ) + : gpgpu_t(config, ctx), m_config(config) +{ + gpgpu_ctx = ctx; + m_shader_config = &m_config.m_shader_config; + m_memory_config = &m_config.m_memory_config; + ctx->ptx_parser->set_ptx_warp_size(m_shader_config); + ptx_file_line_stats_create_exposed_latency_tracker(m_config.num_shader()); #ifdef GPGPUSIM_POWER_MODEL - m_gpgpusim_wrapper = new gpgpu_sim_wrapper(config.g_power_simulation_enabled, - config.g_power_config_name); + m_gpgpusim_wrapper = new gpgpu_sim_wrapper(config.g_power_simulation_enabled,config.g_power_config_name); #endif - m_shader_stats = new shader_core_stats(m_shader_config); - m_memory_stats = new memory_stats_t(m_config.num_shader(), m_shader_config, - m_memory_config, this); - average_pipeline_duty_cycle = (float *)malloc(sizeof(float)); - active_sms = (float *)malloc(sizeof(float)); - m_power_stats = - new power_stat_t(m_shader_config, average_pipeline_duty_cycle, active_sms, - m_shader_stats, m_memory_config, m_memory_stats); + m_shader_stats = new shader_core_stats(m_shader_config); + m_memory_stats = new memory_stats_t(m_config.num_shader(),m_shader_config,m_memory_config,this); + average_pipeline_duty_cycle = (float *)malloc(sizeof(float)); + active_sms=(float *)malloc(sizeof(float)); + m_power_stats = new power_stat_t(m_shader_config,average_pipeline_duty_cycle,active_sms,m_shader_stats,m_memory_config,m_memory_stats); - gpu_sim_insn = 0; - gpu_tot_sim_insn = 0; - gpu_tot_issued_cta = 0; - m_total_cta_launched = 0; - gpu_deadlock = false; + gpu_sim_insn = 0; + gpu_tot_sim_insn = 0; + gpu_tot_issued_cta = 0; + m_total_cta_launched = 0; + gpu_deadlock = false; - gpu_stall_dramfull = 0; - gpu_stall_icnt2sh = 0; - partiton_reqs_in_parallel = 0; - partiton_reqs_in_parallel_total = 0; - partiton_reqs_in_parallel_util = 0; - partiton_reqs_in_parallel_util_total = 0; - gpu_sim_cycle_parition_util = 0; - gpu_tot_sim_cycle_parition_util = 0; - partiton_replys_in_parallel = 0; - partiton_replys_in_parallel_total = 0; + gpu_stall_dramfull = 0; + gpu_stall_icnt2sh = 0; + partiton_reqs_in_parallel = 0; + partiton_reqs_in_parallel_total = 0; + partiton_reqs_in_parallel_util = 0; + partiton_reqs_in_parallel_util_total = 0; + gpu_sim_cycle_parition_util = 0; + gpu_tot_sim_cycle_parition_util = 0; + partiton_replys_in_parallel = 0; + partiton_replys_in_parallel_total = 0; - m_cluster = new simt_core_cluster *[m_shader_config->n_simt_clusters]; - for (unsigned i = 0; i < m_shader_config->n_simt_clusters; i++) - m_cluster[i] = - new simt_core_cluster(this, i, m_shader_config, m_memory_config, - m_shader_stats, m_memory_stats); + m_cluster = new simt_core_cluster*[m_shader_config->n_simt_clusters]; + for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) + m_cluster[i] = new simt_core_cluster(this,i,m_shader_config,m_memory_config,m_shader_stats,m_memory_stats); - m_memory_partition_unit = - new memory_partition_unit *[m_memory_config->m_n_mem]; - m_memory_sub_partition = - new memory_sub_partition *[m_memory_config->m_n_mem_sub_partition]; - for (unsigned i = 0; i < m_memory_config->m_n_mem; i++) { - m_memory_partition_unit[i] = - new memory_partition_unit(i, m_memory_config, m_memory_stats, this); - for (unsigned p = 0; - p < m_memory_config->m_n_sub_partition_per_memory_channel; p++) { - unsigned submpid = - i * m_memory_config->m_n_sub_partition_per_memory_channel + p; - m_memory_sub_partition[submpid] = - m_memory_partition_unit[i]->get_sub_partition(p); + m_memory_partition_unit = new memory_partition_unit*[m_memory_config->m_n_mem]; + m_memory_sub_partition = new memory_sub_partition*[m_memory_config->m_n_mem_sub_partition]; + for (unsigned i=0;i<m_memory_config->m_n_mem;i++) { + m_memory_partition_unit[i] = new memory_partition_unit(i, m_memory_config, m_memory_stats, this); + for (unsigned p = 0; p < m_memory_config->m_n_sub_partition_per_memory_channel; p++) { + unsigned submpid = i * m_memory_config->m_n_sub_partition_per_memory_channel + p; + m_memory_sub_partition[submpid] = m_memory_partition_unit[i]->get_sub_partition(p); + } } - } - icnt_wrapper_init(); - icnt_create(m_shader_config->n_simt_clusters, - m_memory_config->m_n_mem_sub_partition); + icnt_wrapper_init(); + icnt_create(m_shader_config->n_simt_clusters,m_memory_config->m_n_mem_sub_partition); - time_vector_create(NUM_MEM_REQ_STAT); - fprintf(stdout, - "GPGPU-Sim uArch: performance model initialization complete.\n"); + time_vector_create(NUM_MEM_REQ_STAT); + fprintf(stdout, "GPGPU-Sim uArch: performance model initialization complete.\n"); - m_running_kernels.resize(config.max_concurrent_kernel, NULL); - m_last_issued_kernel = 0; - m_last_cluster_issue = m_shader_config->n_simt_clusters - - 1; // this causes first launch to use simt cluster 0 - *average_pipeline_duty_cycle = 0; - *active_sms = 0; + m_running_kernels.resize( config.max_concurrent_kernel, NULL ); + m_last_issued_kernel = 0; + m_last_cluster_issue = m_shader_config->n_simt_clusters-1; // this causes first launch to use simt cluster 0 + *average_pipeline_duty_cycle=0; + *active_sms=0; - last_liveness_message_time = 0; - - // Jin: functional simulation for CDP - m_functional_sim = false; - m_functional_sim_kernel = NULL; + last_liveness_message_time = 0; + + //Jin: functional simulation for CDP + m_functional_sim = false; + m_functional_sim_kernel = NULL; } -int gpgpu_sim::shared_mem_size() const { - return m_shader_config->gpgpu_shmem_size; +int gpgpu_sim::shared_mem_size() const +{ + return m_shader_config->gpgpu_shmem_size; } -int gpgpu_sim::shared_mem_per_block() const { - return m_shader_config->gpgpu_shmem_per_block; +int gpgpu_sim::shared_mem_per_block() const +{ + return m_shader_config->gpgpu_shmem_per_block; } -int gpgpu_sim::num_registers_per_core() const { - return m_shader_config->gpgpu_shader_registers; +int gpgpu_sim::num_registers_per_core() const +{ + return m_shader_config->gpgpu_shader_registers; } -int gpgpu_sim::num_registers_per_block() const { - return m_shader_config->gpgpu_registers_per_block; +int gpgpu_sim::num_registers_per_block() const +{ + return m_shader_config->gpgpu_registers_per_block; } -int gpgpu_sim::wrp_size() const { return m_shader_config->warp_size; } +int gpgpu_sim::wrp_size() const +{ + return m_shader_config->warp_size; +} -int gpgpu_sim::shader_clock() const { return m_config.core_freq / 1000; } +int gpgpu_sim::shader_clock() const +{ + return m_config.core_freq/1000; +} -int gpgpu_sim::max_cta_per_core() const { - return m_shader_config->max_cta_per_core; +int gpgpu_sim::max_cta_per_core() const +{ + return m_shader_config->max_cta_per_core; } -int gpgpu_sim::get_max_cta(const kernel_info_t &k) const { - return m_shader_config->max_cta(k); +int gpgpu_sim::get_max_cta( const kernel_info_t &k ) const +{ + return m_shader_config->max_cta(k); } -void gpgpu_sim::set_prop(cudaDeviceProp *prop) { m_cuda_properties = prop; } +void gpgpu_sim::set_prop( cudaDeviceProp *prop ) +{ + m_cuda_properties = prop; +} -int gpgpu_sim::compute_capability_major() const { - return m_config.gpgpu_compute_capability_major; +int gpgpu_sim::compute_capability_major() const +{ + return m_config.gpgpu_compute_capability_major; } -int gpgpu_sim::compute_capability_minor() const { - return m_config.gpgpu_compute_capability_minor; +int gpgpu_sim::compute_capability_minor() const +{ + return m_config.gpgpu_compute_capability_minor; } -const struct cudaDeviceProp *gpgpu_sim::get_prop() const { - return m_cuda_properties; +const struct cudaDeviceProp *gpgpu_sim::get_prop() const +{ + return m_cuda_properties; } -enum divergence_support_t gpgpu_sim::simd_model() const { - return m_shader_config->model; +enum divergence_support_t gpgpu_sim::simd_model() const +{ + return m_shader_config->model; } -void gpgpu_sim_config::init_clock_domains(void) { - sscanf(gpgpu_clock_domains, "%lf:%lf:%lf:%lf", &core_freq, &icnt_freq, - &l2_freq, &dram_freq); - core_freq = core_freq MhZ; - icnt_freq = icnt_freq MhZ; - l2_freq = l2_freq MhZ; - dram_freq = dram_freq MhZ; - core_period = 1 / core_freq; - icnt_period = 1 / icnt_freq; - dram_period = 1 / dram_freq; - l2_period = 1 / l2_freq; - printf("GPGPU-Sim uArch: clock freqs: %lf:%lf:%lf:%lf\n", core_freq, - icnt_freq, l2_freq, dram_freq); - printf("GPGPU-Sim uArch: clock periods: %.20lf:%.20lf:%.20lf:%.20lf\n", - core_period, icnt_period, l2_period, dram_period); +void gpgpu_sim_config::init_clock_domains(void ) +{ + sscanf(gpgpu_clock_domains,"%lf:%lf:%lf:%lf", + &core_freq, &icnt_freq, &l2_freq, &dram_freq); + core_freq = core_freq MhZ; + icnt_freq = icnt_freq MhZ; + l2_freq = l2_freq MhZ; + dram_freq = dram_freq MhZ; + core_period = 1/core_freq; + icnt_period = 1/icnt_freq; + dram_period = 1/dram_freq; + l2_period = 1/l2_freq; + printf("GPGPU-Sim uArch: clock freqs: %lf:%lf:%lf:%lf\n",core_freq,icnt_freq,l2_freq,dram_freq); + printf("GPGPU-Sim uArch: clock periods: %.20lf:%.20lf:%.20lf:%.20lf\n",core_period,icnt_period,l2_period,dram_period); } -void gpgpu_sim::reinit_clock_domains(void) { - core_time = 0; - dram_time = 0; - icnt_time = 0; - l2_time = 0; +void gpgpu_sim::reinit_clock_domains(void) +{ + core_time = 0; + dram_time = 0; + icnt_time = 0; + l2_time = 0; } -bool gpgpu_sim::active() { - if (m_config.gpu_max_cycle_opt && - (gpu_tot_sim_cycle + gpu_sim_cycle) >= m_config.gpu_max_cycle_opt) - return false; - if (m_config.gpu_max_insn_opt && - (gpu_tot_sim_insn + gpu_sim_insn) >= m_config.gpu_max_insn_opt) +bool gpgpu_sim::active() +{ + if (m_config.gpu_max_cycle_opt && (gpu_tot_sim_cycle + gpu_sim_cycle) >= m_config.gpu_max_cycle_opt) + return false; + if (m_config.gpu_max_insn_opt && (gpu_tot_sim_insn + gpu_sim_insn) >= m_config.gpu_max_insn_opt) + return false; + if (m_config.gpu_max_cta_opt && (gpu_tot_issued_cta >= m_config.gpu_max_cta_opt) ) + return false; + if (m_config.gpu_deadlock_detect && gpu_deadlock) + return false; + for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) + if( m_cluster[i]->get_not_completed()>0 ) + return true;; + for (unsigned i=0;i<m_memory_config->m_n_mem;i++) + if( m_memory_partition_unit[i]->busy()>0 ) + return true;; + if( icnt_busy() ) + return true; + if( get_more_cta_left() ) + return true; return false; - if (m_config.gpu_max_cta_opt && - (gpu_tot_issued_cta >= m_config.gpu_max_cta_opt)) - return false; - if (m_config.gpu_deadlock_detect && gpu_deadlock) return false; - for (unsigned i = 0; i < m_shader_config->n_simt_clusters; i++) - if (m_cluster[i]->get_not_completed() > 0) return true; - ; - for (unsigned i = 0; i < m_memory_config->m_n_mem; i++) - if (m_memory_partition_unit[i]->busy() > 0) return true; - ; - if (icnt_busy()) return true; - if (get_more_cta_left()) return true; - return false; } -void gpgpu_sim::init() { - // run a CUDA grid on the GPU microarchitecture simulator - gpu_sim_cycle = 0; - gpu_sim_insn = 0; - last_gpu_sim_insn = 0; - m_total_cta_launched = 0; - partiton_reqs_in_parallel = 0; - partiton_replys_in_parallel = 0; - partiton_reqs_in_parallel_util = 0; - gpu_sim_cycle_parition_util = 0; +void gpgpu_sim::init() +{ + // run a CUDA grid on the GPU microarchitecture simulator + gpu_sim_cycle = 0; + gpu_sim_insn = 0; + last_gpu_sim_insn = 0; + m_total_cta_launched=0; + partiton_reqs_in_parallel = 0; + partiton_replys_in_parallel = 0; + partiton_reqs_in_parallel_util = 0; + gpu_sim_cycle_parition_util = 0; - reinit_clock_domains(); - gpgpu_ctx->func_sim->set_param_gpgpu_num_shaders(m_config.num_shader()); - for (unsigned i = 0; i < m_shader_config->n_simt_clusters; i++) - m_cluster[i]->reinit(); - m_shader_stats->new_grid(); - // initialize the control-flow, memory access, memory latency logger - if (m_config.g_visualizer_enabled) { - create_thread_CFlogger(gpgpu_ctx, m_config.num_shader(), - m_shader_config->n_thread_per_shader, 0, - m_config.gpgpu_cflog_interval); - } - shader_CTA_count_create(m_config.num_shader(), m_config.gpgpu_cflog_interval); - if (m_config.gpgpu_cflog_interval != 0) { - insn_warp_occ_create(m_config.num_shader(), m_shader_config->warp_size); - shader_warp_occ_create(m_config.num_shader(), m_shader_config->warp_size, - m_config.gpgpu_cflog_interval); - shader_mem_acc_create(m_config.num_shader(), m_memory_config->m_n_mem, 4, - m_config.gpgpu_cflog_interval); - shader_mem_lat_create(m_config.num_shader(), m_config.gpgpu_cflog_interval); - shader_cache_access_create(m_config.num_shader(), 3, - m_config.gpgpu_cflog_interval); - set_spill_interval(m_config.gpgpu_cflog_interval * 40); - } + reinit_clock_domains(); + gpgpu_ctx->func_sim->set_param_gpgpu_num_shaders(m_config.num_shader()); + for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) + m_cluster[i]->reinit(); + m_shader_stats->new_grid(); + // initialize the control-flow, memory access, memory latency logger + if (m_config.g_visualizer_enabled) { + create_thread_CFlogger( gpgpu_ctx, m_config.num_shader(), m_shader_config->n_thread_per_shader, 0, m_config.gpgpu_cflog_interval ); + } + shader_CTA_count_create( m_config.num_shader(), m_config.gpgpu_cflog_interval); + if (m_config.gpgpu_cflog_interval != 0) { + insn_warp_occ_create( m_config.num_shader(), m_shader_config->warp_size ); + shader_warp_occ_create( m_config.num_shader(), m_shader_config->warp_size, m_config.gpgpu_cflog_interval); + shader_mem_acc_create( m_config.num_shader(), m_memory_config->m_n_mem, 4, m_config.gpgpu_cflog_interval); + shader_mem_lat_create( m_config.num_shader(), m_config.gpgpu_cflog_interval); + shader_cache_access_create( m_config.num_shader(), 3, m_config.gpgpu_cflog_interval); + set_spill_interval (m_config.gpgpu_cflog_interval * 40); + } - if (g_network_mode) icnt_init(); + if (g_network_mode) + icnt_init(); -// McPAT initialization function. Called on first launch of GPU + // McPAT initialization function. Called on first launch of GPU #ifdef GPGPUSIM_POWER_MODEL - if (m_config.g_power_simulation_enabled) { - init_mcpat(m_config, m_gpgpusim_wrapper, m_config.gpu_stat_sample_freq, - gpu_tot_sim_insn, gpu_sim_insn); - } + if(m_config.g_power_simulation_enabled){ + init_mcpat(m_config, m_gpgpusim_wrapper, m_config.gpu_stat_sample_freq, gpu_tot_sim_insn, gpu_sim_insn); + } #endif } void gpgpu_sim::update_stats() { - m_memory_stats->memlatstat_lat_pw(); - gpu_tot_sim_cycle += gpu_sim_cycle; - gpu_tot_sim_insn += gpu_sim_insn; - gpu_tot_issued_cta += m_total_cta_launched; - partiton_reqs_in_parallel_total += partiton_reqs_in_parallel; - partiton_replys_in_parallel_total += partiton_replys_in_parallel; - partiton_reqs_in_parallel_util_total += partiton_reqs_in_parallel_util; - gpu_tot_sim_cycle_parition_util += gpu_sim_cycle_parition_util; - gpu_tot_occupancy += gpu_occupancy; + m_memory_stats->memlatstat_lat_pw(); + gpu_tot_sim_cycle += gpu_sim_cycle; + gpu_tot_sim_insn += gpu_sim_insn; + gpu_tot_issued_cta += m_total_cta_launched; + partiton_reqs_in_parallel_total += partiton_reqs_in_parallel; + partiton_replys_in_parallel_total += partiton_replys_in_parallel; + partiton_reqs_in_parallel_util_total += partiton_reqs_in_parallel_util; + gpu_tot_sim_cycle_parition_util += gpu_sim_cycle_parition_util ; + gpu_tot_occupancy += gpu_occupancy; - gpu_sim_cycle = 0; - partiton_reqs_in_parallel = 0; - partiton_replys_in_parallel = 0; - partiton_reqs_in_parallel_util = 0; - gpu_sim_cycle_parition_util = 0; - gpu_sim_insn = 0; - m_total_cta_launched = 0; - gpu_occupancy = occupancy_stats(); + gpu_sim_cycle = 0; + partiton_reqs_in_parallel = 0; + partiton_replys_in_parallel = 0; + partiton_reqs_in_parallel_util = 0; + gpu_sim_cycle_parition_util = 0; + gpu_sim_insn = 0; + m_total_cta_launched = 0; + gpu_occupancy = occupancy_stats(); } -void gpgpu_sim::print_stats() { - gpgpu_ctx->stats->ptx_file_line_stats_write_file(); - gpu_print_stat(); +void gpgpu_sim::print_stats() +{ + gpgpu_ctx->stats->ptx_file_line_stats_write_file(); + gpu_print_stat(); - if (g_network_mode) { - printf( - "----------------------------Interconnect-DETAILS----------------------" - "----------\n"); - icnt_display_stats(); - icnt_display_overall_stats(); - printf( - "----------------------------END-of-Interconnect-DETAILS---------------" - "----------\n"); - } + if (g_network_mode) { + printf("----------------------------Interconnect-DETAILS--------------------------------\n" ); + icnt_display_stats(); + icnt_display_overall_stats(); + printf("----------------------------END-of-Interconnect-DETAILS-------------------------\n" ); + } } -void gpgpu_sim::deadlock_check() { - if (m_config.gpu_deadlock_detect && gpu_deadlock) { - fflush(stdout); - printf( - "\n\nGPGPU-Sim uArch: ERROR ** deadlock detected: last writeback core " - "%u @ gpu_sim_cycle %u (+ gpu_tot_sim_cycle %u) (%u cycles ago)\n", - gpu_sim_insn_last_update_sid, (unsigned)gpu_sim_insn_last_update, - (unsigned)(gpu_tot_sim_cycle - gpu_sim_cycle), - (unsigned)(gpu_sim_cycle - gpu_sim_insn_last_update)); - unsigned num_cores = 0; - for (unsigned i = 0; i < m_shader_config->n_simt_clusters; i++) { - unsigned not_completed = m_cluster[i]->get_not_completed(); - if (not_completed) { - if (!num_cores) { - printf( - "GPGPU-Sim uArch: DEADLOCK shader cores no longer committing " - "instructions [core(# threads)]:\n"); - printf("GPGPU-Sim uArch: DEADLOCK "); - m_cluster[i]->print_not_completed(stdout); - } else if (num_cores < 8) { - m_cluster[i]->print_not_completed(stdout); - } else if (num_cores >= 8) { - printf(" + others ... "); - } - num_cores += m_shader_config->n_simt_cores_per_cluster; +void gpgpu_sim::deadlock_check() +{ + if (m_config.gpu_deadlock_detect && gpu_deadlock) { + fflush(stdout); + printf("\n\nGPGPU-Sim uArch: ERROR ** deadlock detected: last writeback core %u @ gpu_sim_cycle %u (+ gpu_tot_sim_cycle %u) (%u cycles ago)\n", + gpu_sim_insn_last_update_sid, + (unsigned) gpu_sim_insn_last_update, (unsigned) (gpu_tot_sim_cycle-gpu_sim_cycle), + (unsigned) (gpu_sim_cycle - gpu_sim_insn_last_update )); + unsigned num_cores=0; + for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) { + unsigned not_completed = m_cluster[i]->get_not_completed(); + if( not_completed ) { + if ( !num_cores ) { + printf("GPGPU-Sim uArch: DEADLOCK shader cores no longer committing instructions [core(# threads)]:\n" ); + printf("GPGPU-Sim uArch: DEADLOCK "); + m_cluster[i]->print_not_completed(stdout); + } else if (num_cores < 8 ) { + m_cluster[i]->print_not_completed(stdout); + } else if (num_cores >= 8 ) { + printf(" + others ... "); + } + num_cores+=m_shader_config->n_simt_cores_per_cluster; + } } - } - printf("\n"); - for (unsigned i = 0; i < m_memory_config->m_n_mem; i++) { - bool busy = m_memory_partition_unit[i]->busy(); - if (busy) - printf("GPGPU-Sim uArch DEADLOCK: memory partition %u busy\n", i); - } - if (icnt_busy()) { - printf("GPGPU-Sim uArch DEADLOCK: iterconnect contains traffic\n"); - icnt_display_state(stdout); - } - printf( - "\nRe-run the simulator in gdb and use debug routines in .gdbinit to " - "debug this\n"); - fflush(stdout); - abort(); - } + printf("\n"); + for (unsigned i=0;i<m_memory_config->m_n_mem;i++) { + bool busy = m_memory_partition_unit[i]->busy(); + if( busy ) + printf("GPGPU-Sim uArch DEADLOCK: memory partition %u busy\n", i ); + } + if( icnt_busy() ) { + printf("GPGPU-Sim uArch DEADLOCK: iterconnect contains traffic\n"); + icnt_display_state( stdout ); + } + printf("\nRe-run the simulator in gdb and use debug routines in .gdbinit to debug this\n"); + fflush(stdout); + abort(); + } } -/// printing the names and uids of a set of executed kernels (usually there is -/// only one) -std::string gpgpu_sim::executed_kernel_info_string() { - std::stringstream statout; +/// printing the names and uids of a set of executed kernels (usually there is only one) +std::string gpgpu_sim::executed_kernel_info_string() +{ + std::stringstream statout; - statout << "kernel_name = "; - for (unsigned int k = 0; k < m_executed_kernel_names.size(); k++) { - statout << m_executed_kernel_names[k] << " "; - } - statout << std::endl; - statout << "kernel_launch_uid = "; - for (unsigned int k = 0; k < m_executed_kernel_uids.size(); k++) { - statout << m_executed_kernel_uids[k] << " "; - } - statout << std::endl; + statout << "kernel_name = "; + for (unsigned int k = 0; k < m_executed_kernel_names.size(); k++) { + statout << m_executed_kernel_names[k] << " "; + } + statout << std::endl; + statout << "kernel_launch_uid = "; + for (unsigned int k = 0; k < m_executed_kernel_uids.size(); k++) { + statout << m_executed_kernel_uids[k] << " "; + } + statout << std::endl; - return statout.str(); + return statout.str(); } -void gpgpu_sim::set_cache_config(std::string kernel_name, - FuncCache cacheConfig) { - m_special_cache_config[kernel_name] = cacheConfig; +void gpgpu_sim::set_cache_config(std::string kernel_name, FuncCache cacheConfig ) +{ + m_special_cache_config[kernel_name]=cacheConfig ; } -FuncCache gpgpu_sim::get_cache_config(std::string kernel_name) { - for (std::map<std::string, FuncCache>::iterator iter = - m_special_cache_config.begin(); - iter != m_special_cache_config.end(); iter++) { - std::string kernel = iter->first; - if (kernel_name.compare(kernel) == 0) { - return iter->second; - } - } - return (FuncCache)0; +FuncCache gpgpu_sim::get_cache_config(std::string kernel_name) +{ + for ( std::map<std::string, FuncCache>::iterator iter = m_special_cache_config.begin(); iter != m_special_cache_config.end(); iter++){ + std::string kernel= iter->first; + if (kernel_name.compare(kernel) == 0){ + return iter->second; + } + } + return (FuncCache)0; } -bool gpgpu_sim::has_special_cache_config(std::string kernel_name) { - for (std::map<std::string, FuncCache>::iterator iter = - m_special_cache_config.begin(); - iter != m_special_cache_config.end(); iter++) { - std::string kernel = iter->first; - if (kernel_name.compare(kernel) == 0) { - return true; - } - } - return false; +bool gpgpu_sim::has_special_cache_config(std::string kernel_name) +{ + for ( std::map<std::string, FuncCache>::iterator iter = m_special_cache_config.begin(); iter != m_special_cache_config.end(); iter++){ + std::string kernel= iter->first; + if (kernel_name.compare(kernel) == 0){ + return true; + } + } + return false; } -void gpgpu_sim::set_cache_config(std::string kernel_name) { - if (has_special_cache_config(kernel_name)) { - change_cache_config(get_cache_config(kernel_name)); - } else { - change_cache_config(FuncCachePreferNone); - } + +void gpgpu_sim::set_cache_config(std::string kernel_name) +{ + if(has_special_cache_config(kernel_name)){ + change_cache_config(get_cache_config(kernel_name)); + }else{ + change_cache_config(FuncCachePreferNone); + } } -void gpgpu_sim::change_cache_config(FuncCache cache_config) { - if (cache_config != m_shader_config->m_L1D_config.get_cache_status()) { - printf("FLUSH L1 Cache at configuration change between kernels\n"); - for (unsigned i = 0; i < m_shader_config->n_simt_clusters; i++) { - m_cluster[i]->cache_invalidate(); - } - } - switch (cache_config) { - case FuncCachePreferNone: - m_shader_config->m_L1D_config.init( - m_shader_config->m_L1D_config.m_config_string, FuncCachePreferNone); - m_shader_config->gpgpu_shmem_size = - m_shader_config->gpgpu_shmem_sizeDefault; - break; - case FuncCachePreferL1: - if ((m_shader_config->m_L1D_config.m_config_stringPrefL1 == NULL) || - (m_shader_config->gpgpu_shmem_sizePrefL1 == (unsigned)-1)) { - printf("WARNING: missing Preferred L1 configuration\n"); - m_shader_config->m_L1D_config.init( - m_shader_config->m_L1D_config.m_config_string, FuncCachePreferNone); - m_shader_config->gpgpu_shmem_size = - m_shader_config->gpgpu_shmem_sizeDefault; +void gpgpu_sim::change_cache_config(FuncCache cache_config) +{ + if(cache_config != m_shader_config->m_L1D_config.get_cache_status()){ + printf("FLUSH L1 Cache at configuration change between kernels\n"); + for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) { + m_cluster[i]->cache_invalidate(); + } + } - } else { - m_shader_config->m_L1D_config.init( - m_shader_config->m_L1D_config.m_config_stringPrefL1, - FuncCachePreferL1); - m_shader_config->gpgpu_shmem_size = - m_shader_config->gpgpu_shmem_sizePrefL1; - } - break; - case FuncCachePreferShared: - if ((m_shader_config->m_L1D_config.m_config_stringPrefShared == NULL) || - (m_shader_config->gpgpu_shmem_sizePrefShared == (unsigned)-1)) { - printf("WARNING: missing Preferred L1 configuration\n"); - m_shader_config->m_L1D_config.init( - m_shader_config->m_L1D_config.m_config_string, FuncCachePreferNone); - m_shader_config->gpgpu_shmem_size = - m_shader_config->gpgpu_shmem_sizeDefault; - } else { - m_shader_config->m_L1D_config.init( - m_shader_config->m_L1D_config.m_config_stringPrefShared, - FuncCachePreferShared); - m_shader_config->gpgpu_shmem_size = - m_shader_config->gpgpu_shmem_sizePrefShared; - } - break; - default: - break; - } + switch(cache_config){ + case FuncCachePreferNone: + m_shader_config->m_L1D_config.init(m_shader_config->m_L1D_config.m_config_string, FuncCachePreferNone); + m_shader_config->gpgpu_shmem_size=m_shader_config->gpgpu_shmem_sizeDefault; + break; + case FuncCachePreferL1: + if((m_shader_config->m_L1D_config.m_config_stringPrefL1 == NULL) || (m_shader_config->gpgpu_shmem_sizePrefL1 == (unsigned)-1)) + { + printf("WARNING: missing Preferred L1 configuration\n"); + m_shader_config->m_L1D_config.init(m_shader_config->m_L1D_config.m_config_string, FuncCachePreferNone); + m_shader_config->gpgpu_shmem_size=m_shader_config->gpgpu_shmem_sizeDefault; + + }else{ + m_shader_config->m_L1D_config.init(m_shader_config->m_L1D_config.m_config_stringPrefL1, FuncCachePreferL1); + m_shader_config->gpgpu_shmem_size=m_shader_config->gpgpu_shmem_sizePrefL1; + } + break; + case FuncCachePreferShared: + if((m_shader_config->m_L1D_config.m_config_stringPrefShared == NULL) || (m_shader_config->gpgpu_shmem_sizePrefShared == (unsigned)-1)) + { + printf("WARNING: missing Preferred L1 configuration\n"); + m_shader_config->m_L1D_config.init(m_shader_config->m_L1D_config.m_config_string, FuncCachePreferNone); + m_shader_config->gpgpu_shmem_size=m_shader_config->gpgpu_shmem_sizeDefault; + }else{ + m_shader_config->m_L1D_config.init(m_shader_config->m_L1D_config.m_config_stringPrefShared, FuncCachePreferShared); + m_shader_config->gpgpu_shmem_size=m_shader_config->gpgpu_shmem_sizePrefShared; + } + break; + default: + break; + } } -void gpgpu_sim::clear_executed_kernel_info() { - m_executed_kernel_names.clear(); - m_executed_kernel_uids.clear(); + +void gpgpu_sim::clear_executed_kernel_info() +{ + m_executed_kernel_names.clear(); + m_executed_kernel_uids.clear(); } -void gpgpu_sim::gpu_print_stat() { - FILE *statfout = stdout; +void gpgpu_sim::gpu_print_stat() +{ + FILE *statfout = stdout; - std::string kernel_info_str = executed_kernel_info_string(); - fprintf(statfout, "%s", kernel_info_str.c_str()); + std::string kernel_info_str = executed_kernel_info_string(); + fprintf(statfout, "%s", kernel_info_str.c_str()); - printf("gpu_sim_cycle = %lld\n", gpu_sim_cycle); - printf("gpu_sim_insn = %lld\n", gpu_sim_insn); - printf("gpu_ipc = %12.4f\n", (float)gpu_sim_insn / gpu_sim_cycle); - printf("gpu_tot_sim_cycle = %lld\n", gpu_tot_sim_cycle + gpu_sim_cycle); - printf("gpu_tot_sim_insn = %lld\n", gpu_tot_sim_insn + gpu_sim_insn); - printf("gpu_tot_ipc = %12.4f\n", (float)(gpu_tot_sim_insn + gpu_sim_insn) / - (gpu_tot_sim_cycle + gpu_sim_cycle)); - printf("gpu_tot_issued_cta = %lld\n", - gpu_tot_issued_cta + m_total_cta_launched); - printf("gpu_occupancy = %.4f%% \n", gpu_occupancy.get_occ_fraction() * 100); - printf("gpu_tot_occupancy = %.4f%% \n", - (gpu_occupancy + gpu_tot_occupancy).get_occ_fraction() * 100); + printf("gpu_sim_cycle = %lld\n", gpu_sim_cycle); + printf("gpu_sim_insn = %lld\n", gpu_sim_insn); + printf("gpu_ipc = %12.4f\n", (float)gpu_sim_insn / gpu_sim_cycle); + printf("gpu_tot_sim_cycle = %lld\n", gpu_tot_sim_cycle+gpu_sim_cycle); + printf("gpu_tot_sim_insn = %lld\n", gpu_tot_sim_insn+gpu_sim_insn); + printf("gpu_tot_ipc = %12.4f\n", (float)(gpu_tot_sim_insn+gpu_sim_insn) / (gpu_tot_sim_cycle+gpu_sim_cycle)); + printf("gpu_tot_issued_cta = %lld\n", gpu_tot_issued_cta + m_total_cta_launched); + printf("gpu_occupancy = %.4f%% \n", gpu_occupancy.get_occ_fraction() * 100); + printf("gpu_tot_occupancy = %.4f%% \n", (gpu_occupancy + gpu_tot_occupancy).get_occ_fraction() * 100); - fprintf(statfout, "max_total_param_size = %llu\n", - gpgpu_ctx->device_runtime->g_max_total_param_size); - // performance counter for stalls due to congestion. - printf("gpu_stall_dramfull = %d\n", gpu_stall_dramfull); - printf("gpu_stall_icnt2sh = %d\n", gpu_stall_icnt2sh); + fprintf(statfout, "max_total_param_size = %llu\n", gpgpu_ctx->device_runtime->g_max_total_param_size); - // printf("partiton_reqs_in_parallel = %lld\n", partiton_reqs_in_parallel); - // printf("partiton_reqs_in_parallel_total = %lld\n", - // partiton_reqs_in_parallel_total ); - printf("partiton_level_parallism = %12.4f\n", - (float)partiton_reqs_in_parallel / gpu_sim_cycle); - printf("partiton_level_parallism_total = %12.4f\n", - (float)(partiton_reqs_in_parallel + partiton_reqs_in_parallel_total) / - (gpu_tot_sim_cycle + gpu_sim_cycle)); - // printf("partiton_reqs_in_parallel_util = %lld\n", - // partiton_reqs_in_parallel_util); - // printf("partiton_reqs_in_parallel_util_total = %lld\n", - // partiton_reqs_in_parallel_util_total ); - // printf("gpu_sim_cycle_parition_util = %lld\n", - // gpu_sim_cycle_parition_util); - // printf("gpu_tot_sim_cycle_parition_util = %lld\n", - // gpu_tot_sim_cycle_parition_util ); - printf("partiton_level_parallism_util = %12.4f\n", - (float)partiton_reqs_in_parallel_util / gpu_sim_cycle_parition_util); - printf("partiton_level_parallism_util_total = %12.4f\n", - (float)(partiton_reqs_in_parallel_util + - partiton_reqs_in_parallel_util_total) / - (gpu_sim_cycle_parition_util + gpu_tot_sim_cycle_parition_util)); - // printf("partiton_replys_in_parallel = %lld\n", - // partiton_replys_in_parallel); - // printf("partiton_replys_in_parallel_total = %lld\n", - // partiton_replys_in_parallel_total ); - printf("L2_BW = %12.4f GB/Sec\n", - ((float)(partiton_replys_in_parallel * 32) / - (gpu_sim_cycle * m_config.icnt_period)) / - 1000000000); - printf("L2_BW_total = %12.4f GB/Sec\n", - ((float)((partiton_replys_in_parallel + - partiton_replys_in_parallel_total) * - 32) / - ((gpu_tot_sim_cycle + gpu_sim_cycle) * m_config.icnt_period)) / - 1000000000); + // performance counter for stalls due to congestion. + printf("gpu_stall_dramfull = %d\n", gpu_stall_dramfull); + printf("gpu_stall_icnt2sh = %d\n", gpu_stall_icnt2sh ); - time_t curr_time; - time(&curr_time); - unsigned long long elapsed_time = - MAX(curr_time - gpgpu_ctx->the_gpgpusim->g_simulation_starttime, 1); - printf("gpu_total_sim_rate=%u\n", - (unsigned)((gpu_tot_sim_insn + gpu_sim_insn) / elapsed_time)); + //printf("partiton_reqs_in_parallel = %lld\n", partiton_reqs_in_parallel); + //printf("partiton_reqs_in_parallel_total = %lld\n", partiton_reqs_in_parallel_total ); + printf("partiton_level_parallism = %12.4f\n", (float)partiton_reqs_in_parallel / gpu_sim_cycle); + printf("partiton_level_parallism_total = %12.4f\n", (float)(partiton_reqs_in_parallel+partiton_reqs_in_parallel_total) / (gpu_tot_sim_cycle+gpu_sim_cycle) ); + //printf("partiton_reqs_in_parallel_util = %lld\n", partiton_reqs_in_parallel_util); + //printf("partiton_reqs_in_parallel_util_total = %lld\n", partiton_reqs_in_parallel_util_total ); + //printf("gpu_sim_cycle_parition_util = %lld\n", gpu_sim_cycle_parition_util); + // printf("gpu_tot_sim_cycle_parition_util = %lld\n", gpu_tot_sim_cycle_parition_util ); + printf("partiton_level_parallism_util = %12.4f\n", (float)partiton_reqs_in_parallel_util / gpu_sim_cycle_parition_util); + printf("partiton_level_parallism_util_total = %12.4f\n", (float)(partiton_reqs_in_parallel_util+partiton_reqs_in_parallel_util_total) / (gpu_sim_cycle_parition_util+gpu_tot_sim_cycle_parition_util) ); + //printf("partiton_replys_in_parallel = %lld\n", partiton_replys_in_parallel); + //printf("partiton_replys_in_parallel_total = %lld\n", partiton_replys_in_parallel_total ); + printf("L2_BW = %12.4f GB/Sec\n", ((float)(partiton_replys_in_parallel * 32) / (gpu_sim_cycle * m_config.icnt_period)) / 1000000000); + printf("L2_BW_total = %12.4f GB/Sec\n", ((float)((partiton_replys_in_parallel+partiton_replys_in_parallel_total) * 32) / ((gpu_tot_sim_cycle+gpu_sim_cycle) * m_config.icnt_period)) / 1000000000 ); - // shader_print_l1_miss_stat( stdout ); - shader_print_cache_stats(stdout); + time_t curr_time; + time(&curr_time); + unsigned long long elapsed_time = MAX( curr_time - gpgpu_ctx->the_gpgpusim->g_simulation_starttime, 1 ); + printf( "gpu_total_sim_rate=%u\n", (unsigned)( ( gpu_tot_sim_insn + gpu_sim_insn ) / elapsed_time ) ); - cache_stats core_cache_stats; - core_cache_stats.clear(); - for (unsigned i = 0; i < m_config.num_cluster(); i++) { - m_cluster[i]->get_cache_stats(core_cache_stats); - } - printf("\nTotal_core_cache_stats:\n"); - core_cache_stats.print_stats(stdout, "Total_core_cache_stats_breakdown"); - printf("\nTotal_core_cache_fail_stats:\n"); - core_cache_stats.print_fail_stats(stdout, - "Total_core_cache_fail_stats_breakdown"); - shader_print_scheduler_stat(stdout, false); + //shader_print_l1_miss_stat( stdout ); + shader_print_cache_stats(stdout); - m_shader_stats->print(stdout); + cache_stats core_cache_stats; + core_cache_stats.clear(); + for(unsigned i=0; i<m_config.num_cluster(); i++){ + m_cluster[i]->get_cache_stats(core_cache_stats); + } + printf("\nTotal_core_cache_stats:\n"); + core_cache_stats.print_stats(stdout, "Total_core_cache_stats_breakdown"); + printf("\nTotal_core_cache_fail_stats:\n"); + core_cache_stats.print_fail_stats(stdout, "Total_core_cache_fail_stats_breakdown"); + shader_print_scheduler_stat( stdout, false ); + + m_shader_stats->print(stdout); #ifdef GPGPUSIM_POWER_MODEL - if (m_config.g_power_simulation_enabled) { - m_gpgpusim_wrapper->print_power_kernel_stats( - gpu_sim_cycle, gpu_tot_sim_cycle, gpu_tot_sim_insn + gpu_sim_insn, - kernel_info_str, true); - mcpat_reset_perf_count(m_gpgpusim_wrapper); - } + if(m_config.g_power_simulation_enabled){ + m_gpgpusim_wrapper->print_power_kernel_stats(gpu_sim_cycle, gpu_tot_sim_cycle, gpu_tot_sim_insn + gpu_sim_insn, kernel_info_str, true ); + mcpat_reset_perf_count(m_gpgpusim_wrapper); + } #endif - // performance counter that are not local to one shader - m_memory_stats->memlatstat_print(m_memory_config->m_n_mem, - m_memory_config->nbk); - for (unsigned i = 0; i < m_memory_config->m_n_mem; i++) - m_memory_partition_unit[i]->print(stdout); + // performance counter that are not local to one shader + m_memory_stats->memlatstat_print(m_memory_config->m_n_mem,m_memory_config->nbk); + for (unsigned i=0;i<m_memory_config->m_n_mem;i++) + m_memory_partition_unit[i]->print(stdout); - // L2 cache stats - if (!m_memory_config->m_L2_config.disabled()) { - cache_stats l2_stats; - struct cache_sub_stats l2_css; - struct cache_sub_stats total_l2_css; - l2_stats.clear(); - l2_css.clear(); - total_l2_css.clear(); + // L2 cache stats + if(!m_memory_config->m_L2_config.disabled()){ + cache_stats l2_stats; + struct cache_sub_stats l2_css; + struct cache_sub_stats total_l2_css; + l2_stats.clear(); + l2_css.clear(); + total_l2_css.clear(); - printf("\n========= L2 cache stats =========\n"); - for (unsigned i = 0; i < m_memory_config->m_n_mem_sub_partition; i++) { - m_memory_sub_partition[i]->accumulate_L2cache_stats(l2_stats); - m_memory_sub_partition[i]->get_L2cache_sub_stats(l2_css); + printf("\n========= L2 cache stats =========\n"); + for (unsigned i=0;i<m_memory_config->m_n_mem_sub_partition;i++){ + m_memory_sub_partition[i]->accumulate_L2cache_stats(l2_stats); + m_memory_sub_partition[i]->get_L2cache_sub_stats(l2_css); - fprintf(stdout, - "L2_cache_bank[%d]: Access = %llu, Miss = %llu, Miss_rate = " - "%.3lf, Pending_hits = %llu, Reservation_fails = %llu\n", - i, l2_css.accesses, l2_css.misses, - (double)l2_css.misses / (double)l2_css.accesses, - l2_css.pending_hits, l2_css.res_fails); + fprintf( stdout, "L2_cache_bank[%d]: Access = %llu, Miss = %llu, Miss_rate = %.3lf, Pending_hits = %llu, Reservation_fails = %llu\n", + i, l2_css.accesses, l2_css.misses, (double)l2_css.misses / (double)l2_css.accesses, l2_css.pending_hits, l2_css.res_fails); - total_l2_css += l2_css; - } - if (!m_memory_config->m_L2_config.disabled() && - m_memory_config->m_L2_config.get_num_lines()) { - // L2c_print_cache_stat(); - printf("L2_total_cache_accesses = %llu\n", total_l2_css.accesses); - printf("L2_total_cache_misses = %llu\n", total_l2_css.misses); - if (total_l2_css.accesses > 0) - printf("L2_total_cache_miss_rate = %.4lf\n", - (double)total_l2_css.misses / (double)total_l2_css.accesses); - printf("L2_total_cache_pending_hits = %llu\n", total_l2_css.pending_hits); - printf("L2_total_cache_reservation_fails = %llu\n", - total_l2_css.res_fails); - printf("L2_total_cache_breakdown:\n"); - l2_stats.print_stats(stdout, "L2_cache_stats_breakdown"); - printf("L2_total_cache_reservation_fail_breakdown:\n"); - l2_stats.print_fail_stats(stdout, "L2_cache_stats_fail_breakdown"); - total_l2_css.print_port_stats(stdout, "L2_cache"); - } - } + total_l2_css += l2_css; + } + if (!m_memory_config->m_L2_config.disabled() && m_memory_config->m_L2_config.get_num_lines()) { + //L2c_print_cache_stat(); + printf("L2_total_cache_accesses = %llu\n", total_l2_css.accesses); + printf("L2_total_cache_misses = %llu\n", total_l2_css.misses); + if(total_l2_css.accesses > 0) + printf("L2_total_cache_miss_rate = %.4lf\n", (double)total_l2_css.misses/(double)total_l2_css.accesses); + printf("L2_total_cache_pending_hits = %llu\n", total_l2_css.pending_hits); + printf("L2_total_cache_reservation_fails = %llu\n", total_l2_css.res_fails); + printf("L2_total_cache_breakdown:\n"); + l2_stats.print_stats(stdout, "L2_cache_stats_breakdown"); + printf("L2_total_cache_reservation_fail_breakdown:\n"); + l2_stats.print_fail_stats(stdout, "L2_cache_stats_fail_breakdown"); + total_l2_css.print_port_stats(stdout, "L2_cache"); + } + } - if (m_config.gpgpu_cflog_interval != 0) { - spill_log_to_file(stdout, 1, gpu_sim_cycle); - insn_warp_occ_print(stdout); - } - if (gpgpu_ctx->func_sim->gpgpu_ptx_instruction_classification) { - StatDisp(gpgpu_ctx->func_sim->g_inst_classification_stat - [gpgpu_ctx->func_sim->g_ptx_kernel_count]); - StatDisp(gpgpu_ctx->func_sim->g_inst_op_classification_stat - [gpgpu_ctx->func_sim->g_ptx_kernel_count]); - } + if (m_config.gpgpu_cflog_interval != 0) { + spill_log_to_file (stdout, 1, gpu_sim_cycle); + insn_warp_occ_print(stdout); + } + if ( gpgpu_ctx->func_sim->gpgpu_ptx_instruction_classification ) { + StatDisp( gpgpu_ctx->func_sim->g_inst_classification_stat[gpgpu_ctx->func_sim->g_ptx_kernel_count]); + StatDisp( gpgpu_ctx->func_sim->g_inst_op_classification_stat[gpgpu_ctx->func_sim->g_ptx_kernel_count]); + } #ifdef GPGPUSIM_POWER_MODEL - if (m_config.g_power_simulation_enabled) { - m_gpgpusim_wrapper->detect_print_steady_state( - 1, gpu_tot_sim_insn + gpu_sim_insn); - } + if(m_config.g_power_simulation_enabled){ + m_gpgpusim_wrapper->detect_print_steady_state(1,gpu_tot_sim_insn+gpu_sim_insn); + } #endif - // Interconnect power stat print - long total_simt_to_mem = 0; - long total_mem_to_simt = 0; - long temp_stm = 0; - long temp_mts = 0; - for (unsigned i = 0; i < m_config.num_cluster(); i++) { - m_cluster[i]->get_icnt_stats(temp_stm, temp_mts); - total_simt_to_mem += temp_stm; - total_mem_to_simt += temp_mts; - } - printf("\nicnt_total_pkts_mem_to_simt=%ld\n", total_mem_to_simt); - printf("icnt_total_pkts_simt_to_mem=%ld\n", total_simt_to_mem); - time_vector_print(); - fflush(stdout); + // Interconnect power stat print + long total_simt_to_mem=0; + long total_mem_to_simt=0; + long temp_stm=0; + long temp_mts = 0; + for(unsigned i=0; i<m_config.num_cluster(); i++){ + m_cluster[i]->get_icnt_stats(temp_stm, temp_mts); + total_simt_to_mem += temp_stm; + total_mem_to_simt += temp_mts; + } + printf("\nicnt_total_pkts_mem_to_simt=%ld\n", total_mem_to_simt); + printf("icnt_total_pkts_simt_to_mem=%ld\n", total_simt_to_mem); - clear_executed_kernel_info(); + time_vector_print(); + fflush(stdout); + + clear_executed_kernel_info(); } + // performance counter that are not local to one shader -unsigned gpgpu_sim::threads_per_core() const { - return m_shader_config->n_thread_per_shader; +unsigned gpgpu_sim::threads_per_core() const +{ + return m_shader_config->n_thread_per_shader; } -void shader_core_ctx::mem_instruction_stats(const warp_inst_t &inst) { - unsigned active_count = inst.active_count(); - // this breaks some encapsulation: the is_[space] functions, if you change - // those, change this. - switch (inst.space.get_type()) { +void shader_core_ctx::mem_instruction_stats(const warp_inst_t &inst) +{ + unsigned active_count = inst.active_count(); + //this breaks some encapsulation: the is_[space] functions, if you change those, change this. + switch (inst.space.get_type()) { case undefined_space: case reg_space: - break; + break; case shared_space: - m_stats->gpgpu_n_shmem_insn += active_count; - break; + m_stats->gpgpu_n_shmem_insn += active_count; + break; case sstarr_space: - m_stats->gpgpu_n_sstarr_insn += active_count; - break; + m_stats->gpgpu_n_sstarr_insn += active_count; + break; case const_space: - m_stats->gpgpu_n_const_insn += active_count; - break; + m_stats->gpgpu_n_const_insn += active_count; + break; case param_space_kernel: case param_space_local: - m_stats->gpgpu_n_param_insn += active_count; - break; + m_stats->gpgpu_n_param_insn += active_count; + break; case tex_space: - m_stats->gpgpu_n_tex_insn += active_count; - break; + m_stats->gpgpu_n_tex_insn += active_count; + break; case global_space: case local_space: - if (inst.is_store()) - m_stats->gpgpu_n_store_insn += active_count; - else - m_stats->gpgpu_n_load_insn += active_count; - break; + if( inst.is_store() ) + m_stats->gpgpu_n_store_insn += active_count; + else + m_stats->gpgpu_n_load_insn += active_count; + break; default: - abort(); - } + abort(); + } } -bool shader_core_ctx::can_issue_1block(kernel_info_t &kernel) { - // Jin: concurrent kernels on one SM - if (m_config->gpgpu_concurrent_kernel_sm) { - if (m_config->max_cta(kernel) < 1) return false; +bool shader_core_ctx::can_issue_1block(kernel_info_t & kernel) { - return occupy_shader_resource_1block(kernel, false); - } else { - return (get_n_active_cta() < m_config->max_cta(kernel)); - } + //Jin: concurrent kernels on one SM + if(m_config->gpgpu_concurrent_kernel_sm) { + if(m_config->max_cta(kernel) < 1) + return false; + + return occupy_shader_resource_1block(kernel, false); + } + else { + return (get_n_active_cta() < m_config->max_cta(kernel)); + } } int shader_core_ctx::find_available_hwtid(unsigned int cta_size, bool occupy) { - unsigned int step; - for (step = 0; step < m_config->n_thread_per_shader; step += cta_size) { - unsigned int hw_tid; - for (hw_tid = step; hw_tid < step + cta_size; hw_tid++) { - if (m_occupied_hwtid.test(hw_tid)) break; - } - if (hw_tid == step + cta_size) // consecutive non-active - break; - } - if (step >= m_config->n_thread_per_shader) // didn't find - return -1; - else { - if (occupy) { - for (unsigned hw_tid = step; hw_tid < step + cta_size; hw_tid++) - m_occupied_hwtid.set(hw_tid); - } - return step; - } + + unsigned int step; + for(step = 0; step < m_config->n_thread_per_shader; + step += cta_size) { + + unsigned int hw_tid; + for(hw_tid = step; hw_tid < step + cta_size; + hw_tid++) { + if(m_occupied_hwtid.test(hw_tid)) + break; + } + if(hw_tid == step + cta_size) //consecutive non-active + break; + } + if(step >= m_config->n_thread_per_shader) //didn't find + return -1; + else { + if(occupy) { + for(unsigned hw_tid = step; hw_tid < step + cta_size; + hw_tid++) + m_occupied_hwtid.set(hw_tid); + } + return step; + } } -bool shader_core_ctx::occupy_shader_resource_1block(kernel_info_t &k, - bool occupy) { - unsigned threads_per_cta = k.threads_per_cta(); - const class function_info *kernel = k.entry(); - unsigned int padded_cta_size = threads_per_cta; - unsigned int warp_size = m_config->warp_size; - if (padded_cta_size % warp_size) - padded_cta_size = ((padded_cta_size / warp_size) + 1) * (warp_size); +bool shader_core_ctx::occupy_shader_resource_1block(kernel_info_t & k, bool occupy) { + unsigned threads_per_cta = k.threads_per_cta(); + const class function_info *kernel = k.entry(); + unsigned int padded_cta_size = threads_per_cta; + unsigned int warp_size = m_config->warp_size; + if (padded_cta_size%warp_size) + padded_cta_size = ((padded_cta_size/warp_size)+1)*(warp_size); - if (m_occupied_n_threads + padded_cta_size > m_config->n_thread_per_shader) - return false; + if(m_occupied_n_threads + padded_cta_size > m_config->n_thread_per_shader) + return false; - if (find_available_hwtid(padded_cta_size, false) == -1) return false; + if(find_available_hwtid(padded_cta_size, false) == -1) + return false; - const struct gpgpu_ptx_sim_info *kernel_info = ptx_sim_kernel_info(kernel); + const struct gpgpu_ptx_sim_info *kernel_info = ptx_sim_kernel_info(kernel); - if (m_occupied_shmem + kernel_info->smem > m_config->gpgpu_shmem_size) - return false; - - unsigned int used_regs = padded_cta_size * ((kernel_info->regs + 3) & ~3); - if (m_occupied_regs + used_regs > m_config->gpgpu_shader_registers) - return false; + if(m_occupied_shmem + kernel_info->smem > m_config->gpgpu_shmem_size) + return false; - if (m_occupied_ctas + 1 > m_config->max_cta_per_core) return false; + unsigned int used_regs = padded_cta_size * ((kernel_info->regs+3)&~3); + if(m_occupied_regs + used_regs > m_config->gpgpu_shader_registers) + return false; - if (occupy) { - m_occupied_n_threads += padded_cta_size; - m_occupied_shmem += kernel_info->smem; - m_occupied_regs += (padded_cta_size * ((kernel_info->regs + 3) & ~3)); - m_occupied_ctas++; + if(m_occupied_ctas +1 > m_config->max_cta_per_core) + return false; + + if(occupy) { + m_occupied_n_threads += padded_cta_size; + m_occupied_shmem += kernel_info->smem; + m_occupied_regs += (padded_cta_size * ((kernel_info->regs+3)&~3)); + m_occupied_ctas++; - SHADER_DPRINTF(LIVENESS, - "GPGPU-Sim uArch: Occupied %u threads, %u shared mem, %u " - "registers, %u ctas\n", - m_occupied_n_threads, m_occupied_shmem, m_occupied_regs, - m_occupied_ctas); - } + SHADER_DPRINTF(LIVENESS, "GPGPU-Sim uArch: Occupied %u threads, %u shared mem, %u registers, %u ctas\n", + m_occupied_n_threads, m_occupied_shmem, m_occupied_regs, m_occupied_ctas); + } - return true; + return true; } -void shader_core_ctx::release_shader_resource_1block(unsigned hw_ctaid, - kernel_info_t &k) { - if (m_config->gpgpu_concurrent_kernel_sm) { - unsigned threads_per_cta = k.threads_per_cta(); - const class function_info *kernel = k.entry(); - unsigned int padded_cta_size = threads_per_cta; - unsigned int warp_size = m_config->warp_size; - if (padded_cta_size % warp_size) - padded_cta_size = ((padded_cta_size / warp_size) + 1) * (warp_size); - - assert(m_occupied_n_threads >= padded_cta_size); - m_occupied_n_threads -= padded_cta_size; - - int start_thread = m_occupied_cta_to_hwtid[hw_ctaid]; +void shader_core_ctx::release_shader_resource_1block(unsigned hw_ctaid, kernel_info_t & k) { - for (unsigned hwtid = start_thread; hwtid < start_thread + padded_cta_size; - hwtid++) - m_occupied_hwtid.reset(hwtid); - m_occupied_cta_to_hwtid.erase(hw_ctaid); - - const struct gpgpu_ptx_sim_info *kernel_info = ptx_sim_kernel_info(kernel); - - assert(m_occupied_shmem >= (unsigned int)kernel_info->smem); - m_occupied_shmem -= kernel_info->smem; - - unsigned int used_regs = padded_cta_size * ((kernel_info->regs + 3) & ~3); - assert(m_occupied_regs >= used_regs); - m_occupied_regs -= used_regs; - - assert(m_occupied_ctas >= 1); - m_occupied_ctas--; - } + if(m_config->gpgpu_concurrent_kernel_sm) { + unsigned threads_per_cta = k.threads_per_cta(); + const class function_info *kernel = k.entry(); + unsigned int padded_cta_size = threads_per_cta; + unsigned int warp_size = m_config->warp_size; + if (padded_cta_size%warp_size) + padded_cta_size = ((padded_cta_size/warp_size)+1)*(warp_size); + + assert(m_occupied_n_threads >= padded_cta_size); + m_occupied_n_threads -= padded_cta_size; + + int start_thread = m_occupied_cta_to_hwtid[hw_ctaid]; + + for(unsigned hwtid = start_thread; hwtid < start_thread + padded_cta_size; + hwtid++) + m_occupied_hwtid.reset(hwtid); + m_occupied_cta_to_hwtid.erase(hw_ctaid); + + const struct gpgpu_ptx_sim_info *kernel_info = ptx_sim_kernel_info(kernel); + + assert(m_occupied_shmem >= (unsigned int)kernel_info->smem); + m_occupied_shmem -= kernel_info->smem; + + unsigned int used_regs = padded_cta_size * ((kernel_info->regs+3)&~3); + assert(m_occupied_regs >= used_regs); + m_occupied_regs -= used_regs; + + assert(m_occupied_ctas >= 1); + m_occupied_ctas--; + } } //////////////////////////////////////////////////////////////////////////////////////////////// /** - * Launches a cooperative thread array (CTA). - * - * @param kernel - * object that tells us which kernel to ask for a CTA from + * Launches a cooperative thread array (CTA). + * + * @param kernel + * object that tells us which kernel to ask for a CTA from */ -void shader_core_ctx::issue_block2core(kernel_info_t &kernel) { - if (!m_config->gpgpu_concurrent_kernel_sm) - set_max_cta(kernel); - else - assert(occupy_shader_resource_1block(kernel, true)); +void shader_core_ctx::issue_block2core( kernel_info_t &kernel ) +{ - kernel.inc_running(); + if(!m_config->gpgpu_concurrent_kernel_sm) + set_max_cta(kernel); + else + assert(occupy_shader_resource_1block(kernel, true)); - // find a free CTA context - unsigned free_cta_hw_id = (unsigned)-1; + kernel.inc_running(); - unsigned max_cta_per_core; - if (!m_config->gpgpu_concurrent_kernel_sm) - max_cta_per_core = kernel_max_cta_per_shader; - else - max_cta_per_core = m_config->max_cta_per_core; - for (unsigned i = 0; i < max_cta_per_core; i++) { - if (m_cta_status[i] == 0) { - free_cta_hw_id = i; - break; - } - } - assert(free_cta_hw_id != (unsigned)-1); + // find a free CTA context + unsigned free_cta_hw_id=(unsigned)-1; - // determine hardware threads and warps that will be used for this CTA - int cta_size = kernel.threads_per_cta(); + unsigned max_cta_per_core; + if(!m_config->gpgpu_concurrent_kernel_sm) + max_cta_per_core = kernel_max_cta_per_shader; + else + max_cta_per_core = m_config->max_cta_per_core; + for (unsigned i=0;i<max_cta_per_core;i++ ) { + if( m_cta_status[i]==0 ) { + free_cta_hw_id=i; + break; + } + } + assert( free_cta_hw_id!=(unsigned)-1 ); - // hw warp id = hw thread id mod warp size, so we need to find a range - // of hardware thread ids corresponding to an integral number of hardware - // thread ids - int padded_cta_size = cta_size; - if (cta_size % m_config->warp_size) - padded_cta_size = - ((cta_size / m_config->warp_size) + 1) * (m_config->warp_size); + // determine hardware threads and warps that will be used for this CTA + int cta_size = kernel.threads_per_cta(); - unsigned int start_thread, end_thread; + // hw warp id = hw thread id mod warp size, so we need to find a range + // of hardware thread ids corresponding to an integral number of hardware + // thread ids + int padded_cta_size = cta_size; + if (cta_size%m_config->warp_size) + padded_cta_size = ((cta_size/m_config->warp_size)+1)*(m_config->warp_size); - if (!m_config->gpgpu_concurrent_kernel_sm) { - start_thread = free_cta_hw_id * padded_cta_size; - end_thread = start_thread + cta_size; - } else { - start_thread = find_available_hwtid(padded_cta_size, true); - assert((int)start_thread != -1); - end_thread = start_thread + cta_size; - assert(m_occupied_cta_to_hwtid.find(free_cta_hw_id) == - m_occupied_cta_to_hwtid.end()); - m_occupied_cta_to_hwtid[free_cta_hw_id] = start_thread; - } + unsigned int start_thread, end_thread; - // reset the microarchitecture state of the selected hardware thread and warp - // contexts - reinit(start_thread, end_thread, false); + if(!m_config->gpgpu_concurrent_kernel_sm) { + start_thread = free_cta_hw_id * padded_cta_size; + end_thread = start_thread + cta_size; + } + else { + start_thread = find_available_hwtid(padded_cta_size, true); + assert((int)start_thread != -1); + end_thread = start_thread + cta_size; + assert(m_occupied_cta_to_hwtid.find(free_cta_hw_id) == m_occupied_cta_to_hwtid.end()); + m_occupied_cta_to_hwtid[free_cta_hw_id]= start_thread; + } - // initalize scalar threads and determine which hardware warps they are - // allocated to - // bind functional simulation state of threads to hardware resources - // (simulation) - warp_set_t warps; - unsigned nthreads_in_block = 0; - function_info *kernel_func_info = kernel.entry(); - symbol_table *symtab = kernel_func_info->get_symtab(); - unsigned ctaid = kernel.get_next_cta_id_single(); - checkpoint *g_checkpoint = new checkpoint(); - for (unsigned i = start_thread; i < end_thread; i++) { - m_threadState[i].m_cta_id = free_cta_hw_id; - unsigned warp_id = i / m_config->warp_size; - nthreads_in_block += ptx_sim_init_thread( - kernel, &m_thread[i], m_sid, i, cta_size - (i - start_thread), - m_config->n_thread_per_shader, this, free_cta_hw_id, warp_id, - m_cluster->get_gpu()); - m_threadState[i].m_active = true; - // load thread local memory and register file - if (m_gpu->resume_option == 1 && kernel.get_uid() == m_gpu->resume_kernel && - ctaid >= m_gpu->resume_CTA && ctaid < m_gpu->checkpoint_CTA_t) { - char fname[2048]; - snprintf(fname, 2048, "checkpoint_files/thread_%d_%d_reg.txt", - i % cta_size, ctaid); - m_thread[i]->resume_reg_thread(fname, symtab); - char f1name[2048]; - snprintf(f1name, 2048, "checkpoint_files/local_mem_thread_%d_%d_reg.txt", - i % cta_size, ctaid); - g_checkpoint->load_global_mem(m_thread[i]->m_local_mem, f1name); + // reset the microarchitecture state of the selected hardware thread and warp contexts + reinit(start_thread, end_thread,false); + + // initalize scalar threads and determine which hardware warps they are allocated to + // bind functional simulation state of threads to hardware resources (simulation) + warp_set_t warps; + unsigned nthreads_in_block= 0; + function_info *kernel_func_info = kernel.entry(); + symbol_table * symtab= kernel_func_info->get_symtab(); + unsigned ctaid= kernel.get_next_cta_id_single(); + checkpoint *g_checkpoint= new checkpoint(); + for (unsigned i = start_thread; i<end_thread; i++) { + m_threadState[i].m_cta_id = free_cta_hw_id; + unsigned warp_id = i/m_config->warp_size; + nthreads_in_block += ptx_sim_init_thread(kernel,&m_thread[i],m_sid,i,cta_size-(i-start_thread),m_config->n_thread_per_shader,this,free_cta_hw_id,warp_id,m_cluster->get_gpu()); + m_threadState[i].m_active = true; + // load thread local memory and register file + if(m_gpu->resume_option == 1 && kernel.get_uid() == m_gpu->resume_kernel && ctaid >= m_gpu->resume_CTA && ctaid < m_gpu->checkpoint_CTA_t ) + { + char fname[2048]; + snprintf(fname,2048,"checkpoint_files/thread_%d_%d_reg.txt",i%cta_size,ctaid ); + m_thread[i]->resume_reg_thread(fname,symtab); + char f1name[2048]; + snprintf(f1name,2048,"checkpoint_files/local_mem_thread_%d_%d_reg.txt",i%cta_size,ctaid); + g_checkpoint->load_global_mem(m_thread[i]->m_local_mem, f1name); + } + // + warps.set( warp_id ); } - // - warps.set(warp_id); - } - assert(nthreads_in_block > 0 && - nthreads_in_block <= m_config->n_thread_per_shader); // should be at - // least one, but - // less than max - m_cta_status[free_cta_hw_id] = nthreads_in_block; + assert( nthreads_in_block > 0 && nthreads_in_block <= m_config->n_thread_per_shader); // should be at least one, but less than max + m_cta_status[free_cta_hw_id]=nthreads_in_block; - if (m_gpu->resume_option == 1 && kernel.get_uid() == m_gpu->resume_kernel && - ctaid >= m_gpu->resume_CTA && ctaid < m_gpu->checkpoint_CTA_t) { - char f1name[2048]; - snprintf(f1name, 2048, "checkpoint_files/shared_mem_%d.txt", ctaid); + if(m_gpu->resume_option == 1 && kernel.get_uid() == m_gpu->resume_kernel && ctaid >= m_gpu->resume_CTA && ctaid < m_gpu->checkpoint_CTA_t ) + { + char f1name[2048]; + snprintf(f1name,2048,"checkpoint_files/shared_mem_%d.txt", ctaid); + + g_checkpoint->load_global_mem(m_thread[start_thread]->m_shared_mem, f1name); + } + // now that we know which warps are used in this CTA, we can allocate + // resources for use in CTA-wide barrier operations + m_barriers.allocate_barrier(free_cta_hw_id,warps); - g_checkpoint->load_global_mem(m_thread[start_thread]->m_shared_mem, f1name); - } - // now that we know which warps are used in this CTA, we can allocate - // resources for use in CTA-wide barrier operations - m_barriers.allocate_barrier(free_cta_hw_id, warps); + // initialize the SIMT stacks and fetch hardware + init_warps( free_cta_hw_id, start_thread, end_thread, ctaid, cta_size, kernel.get_uid()); + m_n_active_cta++; - // initialize the SIMT stacks and fetch hardware - init_warps(free_cta_hw_id, start_thread, end_thread, ctaid, cta_size, - kernel.get_uid()); - m_n_active_cta++; + shader_CTA_count_log(m_sid, 1); + SHADER_DPRINTF(LIVENESS, "GPGPU-Sim uArch: cta:%2u, start_tid:%4u, end_tid:%4u, initialized @(%lld,%lld)\n", + free_cta_hw_id, start_thread, end_thread, m_gpu->gpu_sim_cycle, m_gpu->gpu_tot_sim_cycle ); - shader_CTA_count_log(m_sid, 1); - SHADER_DPRINTF(LIVENESS, - "GPGPU-Sim uArch: cta:%2u, start_tid:%4u, end_tid:%4u, " - "initialized @(%lld,%lld)\n", - free_cta_hw_id, start_thread, end_thread, m_gpu->gpu_sim_cycle, - m_gpu->gpu_tot_sim_cycle); } /////////////////////////////////////////////////////////////////////////////////////////// -void dram_t::dram_log(int task) { - if (task == SAMPLELOG) { - StatAddSample(mrqq_Dist, que_length()); - } else if (task == DUMPLOG) { - printf("Queue Length DRAM[%d] ", id); - StatDisp(mrqq_Dist); - } +void dram_t::dram_log( int task ) +{ + if (task == SAMPLELOG) { + StatAddSample(mrqq_Dist, que_length()); + } else if (task == DUMPLOG) { + printf ("Queue Length DRAM[%d] ",id);StatDisp(mrqq_Dist); + } } -// Find next clock domain and increment its time -int gpgpu_sim::next_clock_domain(void) { - double smallest = min3(core_time, icnt_time, dram_time); - int mask = 0x00; - if (l2_time <= smallest) { - smallest = l2_time; - mask |= L2; - l2_time += m_config.l2_period; - } - if (icnt_time <= smallest) { - mask |= ICNT; - icnt_time += m_config.icnt_period; - } - if (dram_time <= smallest) { - mask |= DRAM; - dram_time += m_config.dram_period; - } - if (core_time <= smallest) { - mask |= CORE; - core_time += m_config.core_period; - } - return mask; +//Find next clock domain and increment its time +int gpgpu_sim::next_clock_domain(void) +{ + double smallest = min3(core_time,icnt_time,dram_time); + int mask = 0x00; + if ( l2_time <= smallest ) { + smallest = l2_time; + mask |= L2 ; + l2_time += m_config.l2_period; + } + if ( icnt_time <= smallest ) { + mask |= ICNT; + icnt_time += m_config.icnt_period; + } + if ( dram_time <= smallest ) { + mask |= DRAM; + dram_time += m_config.dram_period; + } + if ( core_time <= smallest ) { + mask |= CORE; + core_time += m_config.core_period; + } + return mask; } -void gpgpu_sim::issue_block2core() { - unsigned last_issued = m_last_cluster_issue; - for (unsigned i = 0; i < m_shader_config->n_simt_clusters; i++) { - unsigned idx = (i + last_issued + 1) % m_shader_config->n_simt_clusters; - unsigned num = m_cluster[idx]->issue_block2core(); - if (num) { - m_last_cluster_issue = idx; - m_total_cta_launched += num; +void gpgpu_sim::issue_block2core() +{ + unsigned last_issued = m_last_cluster_issue; + for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) { + unsigned idx = (i + last_issued + 1) % m_shader_config->n_simt_clusters; + unsigned num = m_cluster[idx]->issue_block2core(); + if( num ) { + m_last_cluster_issue=idx; + m_total_cta_launched += num; + } } - } } -unsigned long long g_single_step = - 0; // set this in gdb to single step the pipeline +unsigned long long g_single_step=0; // set this in gdb to single step the pipeline -void gpgpu_sim::cycle() { - int clock_mask = next_clock_domain(); +void gpgpu_sim::cycle() +{ + int clock_mask = next_clock_domain(); - if (clock_mask & CORE) { - // shader core loading (pop from ICNT into core) follows CORE clock - for (unsigned i = 0; i < m_shader_config->n_simt_clusters; i++) - m_cluster[i]->icnt_cycle(); - } - unsigned partiton_replys_in_parallel_per_cycle = 0; - if (clock_mask & ICNT) { - // pop from memory controller to interconnect - for (unsigned i = 0; i < m_memory_config->m_n_mem_sub_partition; i++) { - mem_fetch *mf = m_memory_sub_partition[i]->top(); - if (mf) { - unsigned response_size = - mf->get_is_write() ? mf->get_ctrl_size() : mf->size(); - if (::icnt_has_buffer(m_shader_config->mem2device(i), response_size)) { - // if (!mf->get_is_write()) - mf->set_return_timestamp(gpu_sim_cycle + gpu_tot_sim_cycle); - mf->set_status(IN_ICNT_TO_SHADER, gpu_sim_cycle + gpu_tot_sim_cycle); - ::icnt_push(m_shader_config->mem2device(i), mf->get_tpc(), mf, - response_size); - m_memory_sub_partition[i]->pop(); - partiton_replys_in_parallel_per_cycle++; - } else { - gpu_stall_icnt2sh++; + if (clock_mask & CORE ) { + // shader core loading (pop from ICNT into core) follows CORE clock + for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) + m_cluster[i]->icnt_cycle(); + } + unsigned partiton_replys_in_parallel_per_cycle = 0; + if (clock_mask & ICNT) { + // pop from memory controller to interconnect + for (unsigned i=0;i<m_memory_config->m_n_mem_sub_partition;i++) { + mem_fetch* mf = m_memory_sub_partition[i]->top(); + if (mf) { + unsigned response_size = mf->get_is_write()?mf->get_ctrl_size():mf->size(); + if ( ::icnt_has_buffer( m_shader_config->mem2device(i), response_size ) ) { + //if (!mf->get_is_write()) + mf->set_return_timestamp(gpu_sim_cycle+gpu_tot_sim_cycle); + mf->set_status(IN_ICNT_TO_SHADER,gpu_sim_cycle+gpu_tot_sim_cycle); + ::icnt_push( m_shader_config->mem2device(i), mf->get_tpc(), mf, response_size ); + m_memory_sub_partition[i]->pop(); + partiton_replys_in_parallel_per_cycle++; + } else { + gpu_stall_icnt2sh++; + } + } else { + m_memory_sub_partition[i]->pop(); + } } - } else { - m_memory_sub_partition[i]->pop(); - } - } - } - partiton_replys_in_parallel += partiton_replys_in_parallel_per_cycle; - - if (clock_mask & DRAM) { - for (unsigned i = 0; i < m_memory_config->m_n_mem; i++) { - if (m_memory_config->simple_dram_model) - m_memory_partition_unit[i]->simple_dram_model_cycle(); - else - m_memory_partition_unit[i] - ->dram_cycle(); // Issue the dram command (scheduler + delay model) - // Update performance counters for DRAM - m_memory_partition_unit[i]->set_dram_power_stats( - m_power_stats->pwr_mem_stat->n_cmd[CURRENT_STAT_IDX][i], - m_power_stats->pwr_mem_stat->n_activity[CURRENT_STAT_IDX][i], - m_power_stats->pwr_mem_stat->n_nop[CURRENT_STAT_IDX][i], - m_power_stats->pwr_mem_stat->n_act[CURRENT_STAT_IDX][i], - m_power_stats->pwr_mem_stat->n_pre[CURRENT_STAT_IDX][i], - m_power_stats->pwr_mem_stat->n_rd[CURRENT_STAT_IDX][i], - m_power_stats->pwr_mem_stat->n_wr[CURRENT_STAT_IDX][i], - m_power_stats->pwr_mem_stat->n_req[CURRENT_STAT_IDX][i]); } - } + partiton_replys_in_parallel += partiton_replys_in_parallel_per_cycle; - // L2 operations follow L2 clock domain - unsigned partiton_reqs_in_parallel_per_cycle = 0; - if (clock_mask & L2) { - m_power_stats->pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX].clear(); - for (unsigned i = 0; i < m_memory_config->m_n_mem_sub_partition; i++) { - // move memory request from interconnect into memory partition (if not - // backed up) - // Note:This needs to be called in DRAM clock domain if there is no L2 - // cache in the system - // In the worst case, we may need to push SECTOR_CHUNCK_SIZE requests, so - // ensure you have enough buffer for them - if (m_memory_sub_partition[i]->full(SECTOR_CHUNCK_SIZE)) { - gpu_stall_dramfull++; - } else { - mem_fetch *mf = (mem_fetch *)icnt_pop(m_shader_config->mem2device(i)); - m_memory_sub_partition[i]->push(mf, gpu_sim_cycle + gpu_tot_sim_cycle); - if (mf) partiton_reqs_in_parallel_per_cycle++; + if (clock_mask & DRAM) { + for (unsigned i=0;i<m_memory_config->m_n_mem;i++){ + if(m_memory_config->simple_dram_model) + m_memory_partition_unit[i]->simple_dram_model_cycle(); + else + m_memory_partition_unit[i]->dram_cycle(); // Issue the dram command (scheduler + delay model) + // Update performance counters for DRAM + m_memory_partition_unit[i]->set_dram_power_stats(m_power_stats->pwr_mem_stat->n_cmd[CURRENT_STAT_IDX][i], m_power_stats->pwr_mem_stat->n_activity[CURRENT_STAT_IDX][i], + m_power_stats->pwr_mem_stat->n_nop[CURRENT_STAT_IDX][i], m_power_stats->pwr_mem_stat->n_act[CURRENT_STAT_IDX][i], m_power_stats->pwr_mem_stat->n_pre[CURRENT_STAT_IDX][i], + m_power_stats->pwr_mem_stat->n_rd[CURRENT_STAT_IDX][i], m_power_stats->pwr_mem_stat->n_wr[CURRENT_STAT_IDX][i], m_power_stats->pwr_mem_stat->n_req[CURRENT_STAT_IDX][i]); } - m_memory_sub_partition[i]->cache_cycle(gpu_sim_cycle + gpu_tot_sim_cycle); - m_memory_sub_partition[i]->accumulate_L2cache_stats( - m_power_stats->pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX]); - } - } - partiton_reqs_in_parallel += partiton_reqs_in_parallel_per_cycle; - if (partiton_reqs_in_parallel_per_cycle > 0) { - partiton_reqs_in_parallel_util += partiton_reqs_in_parallel_per_cycle; - gpu_sim_cycle_parition_util++; - } + } + + // L2 operations follow L2 clock domain + unsigned partiton_reqs_in_parallel_per_cycle = 0; + if (clock_mask & L2) { + m_power_stats->pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX].clear(); + for (unsigned i=0;i<m_memory_config->m_n_mem_sub_partition;i++) { + //move memory request from interconnect into memory partition (if not backed up) + //Note:This needs to be called in DRAM clock domain if there is no L2 cache in the system + //In the worst case, we may need to push SECTOR_CHUNCK_SIZE requests, so ensure you have enough buffer for them + if ( m_memory_sub_partition[i]->full(SECTOR_CHUNCK_SIZE) ) { + gpu_stall_dramfull++; + } else { + mem_fetch* mf = (mem_fetch*) icnt_pop( m_shader_config->mem2device(i) ); + m_memory_sub_partition[i]->push( mf, gpu_sim_cycle + gpu_tot_sim_cycle ); + if(mf) + partiton_reqs_in_parallel_per_cycle++; + } + m_memory_sub_partition[i]->cache_cycle(gpu_sim_cycle+gpu_tot_sim_cycle); + m_memory_sub_partition[i]->accumulate_L2cache_stats(m_power_stats->pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX]); + } + } + partiton_reqs_in_parallel += partiton_reqs_in_parallel_per_cycle; + if(partiton_reqs_in_parallel_per_cycle > 0){ + partiton_reqs_in_parallel_util += partiton_reqs_in_parallel_per_cycle; + gpu_sim_cycle_parition_util++; + } + + if (clock_mask & ICNT) { + icnt_transfer(); + } - if (clock_mask & ICNT) { - icnt_transfer(); - } + if (clock_mask & CORE) { + // L1 cache + shader core pipeline stages + m_power_stats->pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].clear(); + for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) { + if (m_cluster[i]->get_not_completed() || get_more_cta_left() ) { + m_cluster[i]->core_cycle(); + *active_sms+=m_cluster[i]->get_n_active_sms(); + } + // Update core icnt/cache stats for GPUWattch + m_cluster[i]->get_icnt_stats(m_power_stats->pwr_mem_stat->n_simt_to_mem[CURRENT_STAT_IDX][i], m_power_stats->pwr_mem_stat->n_mem_to_simt[CURRENT_STAT_IDX][i]); + m_cluster[i]->get_cache_stats(m_power_stats->pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX]); + m_cluster[i]->get_current_occupancy(gpu_occupancy.aggregate_warp_slot_filled, gpu_occupancy.aggregate_theoretical_warp_slots); - if (clock_mask & CORE) { - // L1 cache + shader core pipeline stages - m_power_stats->pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].clear(); - for (unsigned i = 0; i < m_shader_config->n_simt_clusters; i++) { - if (m_cluster[i]->get_not_completed() || get_more_cta_left()) { - m_cluster[i]->core_cycle(); - *active_sms += m_cluster[i]->get_n_active_sms(); } - // Update core icnt/cache stats for GPUWattch - m_cluster[i]->get_icnt_stats( - m_power_stats->pwr_mem_stat->n_simt_to_mem[CURRENT_STAT_IDX][i], - m_power_stats->pwr_mem_stat->n_mem_to_simt[CURRENT_STAT_IDX][i]); - m_cluster[i]->get_cache_stats( - m_power_stats->pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX]); - m_cluster[i]->get_current_occupancy( - gpu_occupancy.aggregate_warp_slot_filled, - gpu_occupancy.aggregate_theoretical_warp_slots); - } - float temp = 0; - for (unsigned i = 0; i < m_shader_config->num_shader(); i++) { - temp += m_shader_stats->m_pipeline_duty_cycle[i]; - } - temp = temp / m_shader_config->num_shader(); - *average_pipeline_duty_cycle = ((*average_pipeline_duty_cycle) + temp); - // cout<<"Average pipeline duty cycle: - // "<<*average_pipeline_duty_cycle<<endl; + float temp=0; + for (unsigned i=0;i<m_shader_config->num_shader();i++){ + temp+=m_shader_stats->m_pipeline_duty_cycle[i]; + } + temp=temp/m_shader_config->num_shader(); + *average_pipeline_duty_cycle=((*average_pipeline_duty_cycle)+temp); + //cout<<"Average pipeline duty cycle: "<<*average_pipeline_duty_cycle<<endl; - if (g_single_step && - ((gpu_sim_cycle + gpu_tot_sim_cycle) >= g_single_step)) { - raise(SIGTRAP); // Debug breakpoint - } - gpu_sim_cycle++; - if (g_interactive_debugger_enabled) gpgpu_debug(); + if( g_single_step && ((gpu_sim_cycle+gpu_tot_sim_cycle) >= g_single_step) ) { + raise(SIGTRAP); // Debug breakpoint + } + gpu_sim_cycle++; + + if( g_interactive_debugger_enabled ) + gpgpu_debug(); -// McPAT main cycle (interface with McPAT) + // McPAT main cycle (interface with McPAT) #ifdef GPGPUSIM_POWER_MODEL - if (m_config.g_power_simulation_enabled) { - mcpat_cycle(m_config, getShaderCoreConfig(), m_gpgpusim_wrapper, - m_power_stats, m_config.gpu_stat_sample_freq, - gpu_tot_sim_cycle, gpu_sim_cycle, gpu_tot_sim_insn, - gpu_sim_insn); - } + if(m_config.g_power_simulation_enabled){ + mcpat_cycle(m_config, getShaderCoreConfig(), m_gpgpusim_wrapper, m_power_stats, m_config.gpu_stat_sample_freq, gpu_tot_sim_cycle, gpu_sim_cycle, gpu_tot_sim_insn, gpu_sim_insn); + } #endif - issue_block2core(); - - // Depending on configuration, invalidate the caches once all of threads are - // completed. - int all_threads_complete = 1; - if (m_config.gpgpu_flush_l1_cache) { - for (unsigned i = 0; i < m_shader_config->n_simt_clusters; i++) { - if (m_cluster[i]->get_not_completed() == 0) - m_cluster[i]->cache_invalidate(); - else - all_threads_complete = 0; + issue_block2core(); + + // Depending on configuration, invalidate the caches once all of threads are completed. + int all_threads_complete = 1; + if (m_config.gpgpu_flush_l1_cache) { + for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) { + if (m_cluster[i]->get_not_completed() == 0) + m_cluster[i]->cache_invalidate(); + else + all_threads_complete = 0 ; + } } - } - if (m_config.gpgpu_flush_l2_cache) { - if (!m_config.gpgpu_flush_l1_cache) { - for (unsigned i = 0; i < m_shader_config->n_simt_clusters; i++) { - if (m_cluster[i]->get_not_completed() != 0) { - all_threads_complete = 0; - break; + if(m_config.gpgpu_flush_l2_cache){ + if(!m_config.gpgpu_flush_l1_cache){ + for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) { + if (m_cluster[i]->get_not_completed() != 0){ + all_threads_complete = 0 ; + break; + } + } } - } - } - if (all_threads_complete && !m_memory_config->m_L2_config.disabled()) { - printf("Flushed L2 caches...\n"); - if (m_memory_config->m_L2_config.get_num_lines()) { - int dlc = 0; - for (unsigned i = 0; i < m_memory_config->m_n_mem; i++) { - dlc = m_memory_sub_partition[i]->flushL2(); - assert(dlc == 0); // TODO: need to model actual writes to DRAM here - printf("Dirty lines flushed from L2 %d is %d\n", i, dlc); - } - } + if (all_threads_complete && !m_memory_config->m_L2_config.disabled() ) { + printf("Flushed L2 caches...\n"); + if (m_memory_config->m_L2_config.get_num_lines()) { + int dlc = 0; + for (unsigned i=0;i<m_memory_config->m_n_mem;i++) { + dlc = m_memory_sub_partition[i]->flushL2(); + assert (dlc == 0); // TODO: need to model actual writes to DRAM here + printf("Dirty lines flushed from L2 %d is %d\n", i, dlc ); + } + } + } } - } - if (!(gpu_sim_cycle % m_config.gpu_stat_sample_freq)) { - time_t days, hrs, minutes, sec; - time_t curr_time; - time(&curr_time); - unsigned long long elapsed_time = - MAX(curr_time - gpgpu_ctx->the_gpgpusim->g_simulation_starttime, 1); - if ((elapsed_time - last_liveness_message_time) >= - m_config.liveness_message_freq && - DTRACE(LIVENESS)) { - days = elapsed_time / (3600 * 24); - hrs = elapsed_time / 3600 - 24 * days; - minutes = elapsed_time / 60 - 60 * (hrs + 24 * days); - sec = elapsed_time - 60 * (minutes + 60 * (hrs + 24 * days)); - - unsigned long long active = 0, total = 0; - for (unsigned i = 0; i < m_shader_config->n_simt_clusters; i++) { - m_cluster[i]->get_current_occupancy(active, total); - } - DPRINTFG(LIVENESS, - "uArch: inst.: %lld (ipc=%4.1f, occ=%0.4f\% [%llu / %llu]) " - "sim_rate=%u (inst/sec) elapsed = %u:%u:%02u:%02u / %s", - gpu_tot_sim_insn + gpu_sim_insn, - (double)gpu_sim_insn / (double)gpu_sim_cycle, - float(active) / float(total) * 100, active, total, - (unsigned)((gpu_tot_sim_insn + gpu_sim_insn) / elapsed_time), - (unsigned)days, (unsigned)hrs, (unsigned)minutes, - (unsigned)sec, ctime(&curr_time)); - fflush(stdout); - last_liveness_message_time = elapsed_time; + if (!(gpu_sim_cycle % m_config.gpu_stat_sample_freq)) { + time_t days, hrs, minutes, sec; + time_t curr_time; + time(&curr_time); + unsigned long long elapsed_time = MAX(curr_time - gpgpu_ctx->the_gpgpusim->g_simulation_starttime, 1); + if ( (elapsed_time - last_liveness_message_time) >= m_config.liveness_message_freq && DTRACE(LIVENESS) ) { + days = elapsed_time/(3600*24); + hrs = elapsed_time/3600 - 24*days; + minutes = elapsed_time/60 - 60*(hrs + 24*days); + sec = elapsed_time - 60*(minutes + 60*(hrs + 24*days)); + + unsigned long long active = 0, total = 0; + for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) { + m_cluster[i]->get_current_occupancy(active, total); + } + DPRINTFG(LIVENESS, "uArch: inst.: %lld (ipc=%4.1f, occ=%0.4f\% [%llu / %llu]) sim_rate=%u (inst/sec) elapsed = %u:%u:%02u:%02u / %s", + gpu_tot_sim_insn + gpu_sim_insn, + (double)gpu_sim_insn/(double)gpu_sim_cycle, + float(active)/float(total) * 100, active, total, + (unsigned)((gpu_tot_sim_insn+gpu_sim_insn) / elapsed_time), + (unsigned)days,(unsigned)hrs,(unsigned)minutes,(unsigned)sec, + ctime(&curr_time)); + fflush(stdout); + last_liveness_message_time = elapsed_time; + } + visualizer_printstat(); + m_memory_stats->memlatstat_lat_pw(); + if (m_config.gpgpu_runtime_stat && (m_config.gpu_runtime_stat_flag != 0) ) { + if (m_config.gpu_runtime_stat_flag & GPU_RSTAT_BW_STAT) { + for (unsigned i=0;i<m_memory_config->m_n_mem;i++) + m_memory_partition_unit[i]->print_stat(stdout); + printf("maxmrqlatency = %d \n", m_memory_stats->max_mrq_latency); + printf("maxmflatency = %d \n", m_memory_stats->max_mf_latency); + } + if (m_config.gpu_runtime_stat_flag & GPU_RSTAT_SHD_INFO) + shader_print_runtime_stat( stdout ); + if (m_config.gpu_runtime_stat_flag & GPU_RSTAT_L1MISS) + shader_print_l1_miss_stat( stdout ); + if (m_config.gpu_runtime_stat_flag & GPU_RSTAT_SCHED) + shader_print_scheduler_stat( stdout, false ); + } } - visualizer_printstat(); - m_memory_stats->memlatstat_lat_pw(); - if (m_config.gpgpu_runtime_stat && - (m_config.gpu_runtime_stat_flag != 0)) { - if (m_config.gpu_runtime_stat_flag & GPU_RSTAT_BW_STAT) { - for (unsigned i = 0; i < m_memory_config->m_n_mem; i++) - m_memory_partition_unit[i]->print_stat(stdout); - printf("maxmrqlatency = %d \n", m_memory_stats->max_mrq_latency); - printf("maxmflatency = %d \n", m_memory_stats->max_mf_latency); - } - if (m_config.gpu_runtime_stat_flag & GPU_RSTAT_SHD_INFO) - shader_print_runtime_stat(stdout); - if (m_config.gpu_runtime_stat_flag & GPU_RSTAT_L1MISS) - shader_print_l1_miss_stat(stdout); - if (m_config.gpu_runtime_stat_flag & GPU_RSTAT_SCHED) - shader_print_scheduler_stat(stdout, false); - } - } - if (!(gpu_sim_cycle % 50000)) { - // deadlock detection - if (m_config.gpu_deadlock_detect && gpu_sim_insn == last_gpu_sim_insn) { - gpu_deadlock = true; - } else { - last_gpu_sim_insn = gpu_sim_insn; + if (!(gpu_sim_cycle % 50000)) { + // deadlock detection + if (m_config.gpu_deadlock_detect && gpu_sim_insn == last_gpu_sim_insn) { + gpu_deadlock = true; + } else { + last_gpu_sim_insn = gpu_sim_insn; + } } - } - try_snap_shot(gpu_sim_cycle); - spill_log_to_file(stdout, 0, gpu_sim_cycle); + try_snap_shot(gpu_sim_cycle); + spill_log_to_file (stdout, 0, gpu_sim_cycle); #if (CUDART_VERSION >= 5000) - // launch device kernel - gpgpu_ctx->device_runtime->launch_one_device_kernel(); + //launch device kernel + gpgpu_ctx->device_runtime->launch_one_device_kernel(); #endif - } + } } -void shader_core_ctx::dump_warp_state(FILE *fout) const { - fprintf(fout, "\n"); - fprintf(fout, "per warp functional simulation status:\n"); - for (unsigned w = 0; w < m_config->max_warps_per_shader; w++) - m_warp[w].print(fout); + +void shader_core_ctx::dump_warp_state( FILE *fout ) const +{ + fprintf(fout, "\n"); + fprintf(fout, "per warp functional simulation status:\n"); + for (unsigned w=0; w < m_config->max_warps_per_shader; w++ ) + m_warp[w].print(fout); } -void gpgpu_sim::perf_memcpy_to_gpu(size_t dst_start_addr, size_t count) { - if (m_memory_config->m_perf_sim_memcpy) { - assert(dst_start_addr % 32 == 0); - for (unsigned counter = 0; counter < count; counter += 32) { - const unsigned wr_addr = dst_start_addr + counter; - addrdec_t raw_addr; - mem_access_sector_mask_t mask; - mask.set(wr_addr % 128 / 32); - m_memory_config->m_address_mapping.addrdec_tlx(wr_addr, &raw_addr); - const unsigned partition_id = - raw_addr.sub_partition / - m_memory_config->m_n_sub_partition_per_memory_channel; - m_memory_partition_unit[partition_id]->handle_memcpy_to_gpu( - wr_addr, raw_addr.sub_partition, mask); +void gpgpu_sim::perf_memcpy_to_gpu( size_t dst_start_addr, size_t count ) +{ + if (m_memory_config->m_perf_sim_memcpy) { + assert (dst_start_addr % 32 == 0); + + for ( unsigned counter = 0; counter < count; counter += 32 ) { + const unsigned wr_addr = dst_start_addr + counter; + addrdec_t raw_addr; + mem_access_sector_mask_t mask; + mask.set(wr_addr % 128 / 32); + m_memory_config->m_address_mapping.addrdec_tlx( wr_addr, &raw_addr ); + const unsigned partition_id = raw_addr.sub_partition / m_memory_config->m_n_sub_partition_per_memory_channel; + m_memory_partition_unit[ partition_id ]->handle_memcpy_to_gpu( wr_addr, raw_addr.sub_partition, mask ); + } } - } } -void gpgpu_sim::dump_pipeline(int mask, int s, int m) const { - /* - You may want to use this function while running GPGPU-Sim in gdb. - One way to do that is add the following to your .gdbinit file: - - define dp - call g_the_gpu.dump_pipeline_impl((0x40|0x4|0x1),$arg0,0) - end - - Then, typing "dp 3" will show the contents of the pipeline for shader core - 3. - */ +void gpgpu_sim::dump_pipeline( int mask, int s, int m ) const +{ +/* + You may want to use this function while running GPGPU-Sim in gdb. + One way to do that is add the following to your .gdbinit file: + + define dp + call g_the_gpu.dump_pipeline_impl((0x40|0x4|0x1),$arg0,0) + end + + Then, typing "dp 3" will show the contents of the pipeline for shader core 3. +*/ - printf("Dumping pipeline state...\n"); - if (!mask) mask = 0xFFFFFFFF; - for (unsigned i = 0; i < m_shader_config->n_simt_clusters; i++) { - if (s != -1) { - i = s; - } - if (mask & 1) - m_cluster[m_shader_config->sid_to_cluster(i)]->display_pipeline( - i, stdout, 1, mask & 0x2E); - if (s != -1) { - break; - } - } - if (mask & 0x10000) { - for (unsigned i = 0; i < m_memory_config->m_n_mem; i++) { - if (m != -1) { - i = m; + printf("Dumping pipeline state...\n"); + if(!mask) mask = 0xFFFFFFFF; + for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++) { + if(s != -1) { + i = s; } - printf("DRAM / memory controller %u:\n", i); - if (mask & 0x100000) m_memory_partition_unit[i]->print_stat(stdout); - if (mask & 0x1000000) m_memory_partition_unit[i]->visualize(); - if (mask & 0x10000000) m_memory_partition_unit[i]->print(stdout); - if (m != -1) { - break; + if(mask&1) m_cluster[m_shader_config->sid_to_cluster(i)]->display_pipeline(i,stdout,1,mask & 0x2E); + if(s != -1) { + break; } - } - } - fflush(stdout); + } + if(mask&0x10000) { + for (unsigned i=0;i<m_memory_config->m_n_mem;i++) { + if(m != -1) { + i=m; + } + printf("DRAM / memory controller %u:\n", i); + if(mask&0x100000) m_memory_partition_unit[i]->print_stat(stdout); + if(mask&0x1000000) m_memory_partition_unit[i]->visualize(); + if(mask&0x10000000) m_memory_partition_unit[i]->print(stdout); + if(m != -1) { + break; + } + } + } + fflush(stdout); +} + +const shader_core_config * gpgpu_sim::getShaderCoreConfig() +{ + return m_shader_config; } -const shader_core_config *gpgpu_sim::getShaderCoreConfig() { - return m_shader_config; +const memory_config * gpgpu_sim::getMemoryConfig() +{ + return m_memory_config; } -const memory_config *gpgpu_sim::getMemoryConfig() { return m_memory_config; } +simt_core_cluster * gpgpu_sim::getSIMTCluster() +{ + return *m_cluster; +} -simt_core_cluster *gpgpu_sim::getSIMTCluster() { return *m_cluster; } diff --git a/src/gpgpu-sim/gpu-sim.h b/src/gpgpu-sim/gpu-sim.h index 40c4482..fba770d 100644 --- a/src/gpgpu-sim/gpu-sim.h +++ b/src/gpgpu-sim/gpu-sim.h @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -30,22 +28,24 @@ #ifndef GPU_SIM_H #define GPU_SIM_H -#include <stdio.h> -#include <fstream> -#include <iostream> -#include <list> -#include "../abstract_hardware_model.h" #include "../option_parser.h" +#include "../abstract_hardware_model.h" #include "../trace.h" #include "addrdec.h" -#include "gpu-cache.h" #include "shader.h" +#include "gpu-cache.h" +#include <iostream> +#include <fstream> +#include <list> +#include <stdio.h> + + // constants for statistics printouts #define GPU_RSTAT_SHD_INFO 0x1 -#define GPU_RSTAT_BW_STAT 0x2 +#define GPU_RSTAT_BW_STAT 0x2 #define GPU_RSTAT_WARP_DIS 0x4 -#define GPU_RSTAT_DWF_MAP 0x8 +#define GPU_RSTAT_DWF_MAP 0x8 #define GPU_RSTAT_L1MISS 0x10 #define GPU_RSTAT_PDOM 0x20 #define GPU_RSTAT_SCHED 0x40 @@ -65,618 +65,584 @@ class gpgpu_context; -extern tr1_hash_map<new_addr_type, unsigned> address_random_interleaving; +extern tr1_hash_map<new_addr_type,unsigned> address_random_interleaving; + +enum dram_ctrl_t { + DRAM_FIFO=0, + DRAM_FRFCFS=1 +}; + -enum dram_ctrl_t { DRAM_FIFO = 0, DRAM_FRFCFS = 1 }; struct power_config { - power_config() { m_valid = true; } - void init() { - // initialize file name if it is not set - time_t curr_time; - time(&curr_time); - char *date = ctime(&curr_time); - char *s = date; - while (*s) { - if (*s == ' ' || *s == '\t' || *s == ':') *s = '-'; - if (*s == '\n' || *s == '\r') *s = 0; - s++; - } - char buf1[1024]; - snprintf(buf1, 1024, "gpgpusim_power_report__%s.log", date); - g_power_filename = strdup(buf1); - char buf2[1024]; - snprintf(buf2, 1024, "gpgpusim_power_trace_report__%s.log.gz", date); - g_power_trace_filename = strdup(buf2); - char buf3[1024]; - snprintf(buf3, 1024, "gpgpusim_metric_trace_report__%s.log.gz", date); - g_metric_trace_filename = strdup(buf3); - char buf4[1024]; - snprintf(buf4, 1024, "gpgpusim_steady_state_tracking_report__%s.log.gz", - date); - g_steady_state_tracking_filename = strdup(buf4); + power_config() + { + m_valid = true; + } + void init() + { - if (g_steady_power_levels_enabled) { - sscanf(gpu_steady_state_definition, "%lf:%lf", - &gpu_steady_power_deviation, &gpu_steady_min_period); - } + // initialize file name if it is not set + time_t curr_time; + time(&curr_time); + char *date = ctime(&curr_time); + char *s = date; + while (*s) { + if (*s == ' ' || *s == '\t' || *s == ':') *s = '-'; + if (*s == '\n' || *s == '\r' ) *s = 0; + s++; + } + char buf1[1024]; + snprintf(buf1,1024,"gpgpusim_power_report__%s.log",date); + g_power_filename = strdup(buf1); + char buf2[1024]; + snprintf(buf2,1024,"gpgpusim_power_trace_report__%s.log.gz",date); + g_power_trace_filename = strdup(buf2); + char buf3[1024]; + snprintf(buf3,1024,"gpgpusim_metric_trace_report__%s.log.gz",date); + g_metric_trace_filename = strdup(buf3); + char buf4[1024]; + snprintf(buf4,1024,"gpgpusim_steady_state_tracking_report__%s.log.gz",date); + g_steady_state_tracking_filename = strdup(buf4); + + if(g_steady_power_levels_enabled){ + sscanf(gpu_steady_state_definition,"%lf:%lf", &gpu_steady_power_deviation,&gpu_steady_min_period); + } - // NOTE: After changing the nonlinear model to only scaling idle core, - // NOTE: The min_inc_per_active_sm is not used any more - if (g_use_nonlinear_model) - sscanf(gpu_nonlinear_model_config, "%lf:%lf", &gpu_idle_core_power, - &gpu_min_inc_per_active_sm); - } - void reg_options(class OptionParser *opp); + //NOTE: After changing the nonlinear model to only scaling idle core, + //NOTE: The min_inc_per_active_sm is not used any more + if (g_use_nonlinear_model) + sscanf(gpu_nonlinear_model_config,"%lf:%lf", &gpu_idle_core_power,&gpu_min_inc_per_active_sm); - char *g_power_config_name; + } + void reg_options(class OptionParser * opp); + + char *g_power_config_name; + + bool m_valid; + bool g_power_simulation_enabled; + bool g_power_trace_enabled; + bool g_steady_power_levels_enabled; + bool g_power_per_cycle_dump; + bool g_power_simulator_debug; + char *g_power_filename; + char *g_power_trace_filename; + char *g_metric_trace_filename; + char * g_steady_state_tracking_filename; + int g_power_trace_zlevel; + char * gpu_steady_state_definition; + double gpu_steady_power_deviation; + double gpu_steady_min_period; + + //Nonlinear power model + bool g_use_nonlinear_model; + char * gpu_nonlinear_model_config; + double gpu_idle_core_power; + double gpu_min_inc_per_active_sm; - bool m_valid; - bool g_power_simulation_enabled; - bool g_power_trace_enabled; - bool g_steady_power_levels_enabled; - bool g_power_per_cycle_dump; - bool g_power_simulator_debug; - char *g_power_filename; - char *g_power_trace_filename; - char *g_metric_trace_filename; - char *g_steady_state_tracking_filename; - int g_power_trace_zlevel; - char *gpu_steady_state_definition; - double gpu_steady_power_deviation; - double gpu_steady_min_period; - // Nonlinear power model - bool g_use_nonlinear_model; - char *gpu_nonlinear_model_config; - double gpu_idle_core_power; - double gpu_min_inc_per_active_sm; }; + class memory_config { - public: - memory_config(gpgpu_context *ctx) { - m_valid = false; - gpgpu_dram_timing_opt = NULL; - gpgpu_L2_queue_config = NULL; - gpgpu_ctx = ctx; - } - void init() { - assert(gpgpu_dram_timing_opt); - if (strchr(gpgpu_dram_timing_opt, '=') == NULL) { - // dram timing option in ordered variables (legacy) - // Disabling bank groups if their values are not specified - nbkgrp = 1; - tCCDL = 0; - tRTPL = 0; - sscanf(gpgpu_dram_timing_opt, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d", - &nbk, &tCCD, &tRRD, &tRCD, &tRAS, &tRP, &tRC, &CL, &WL, &tCDLR, - &tWR, &nbkgrp, &tCCDL, &tRTPL); - } else { - // named dram timing options (unordered) - option_parser_t dram_opp = option_parser_create(); + public: + memory_config(gpgpu_context* ctx) + { + m_valid = false; + gpgpu_dram_timing_opt=NULL; + gpgpu_L2_queue_config=NULL; + gpgpu_ctx = ctx; + } + void init() + { + assert(gpgpu_dram_timing_opt); + if (strchr(gpgpu_dram_timing_opt, '=') == NULL) { + // dram timing option in ordered variables (legacy) + // Disabling bank groups if their values are not specified + nbkgrp = 1; + tCCDL = 0; + tRTPL = 0; + sscanf(gpgpu_dram_timing_opt,"%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d", + &nbk,&tCCD,&tRRD,&tRCD,&tRAS,&tRP,&tRC,&CL,&WL,&tCDLR,&tWR,&nbkgrp,&tCCDL,&tRTPL); + } else { + // named dram timing options (unordered) + option_parser_t dram_opp = option_parser_create(); - option_parser_register(dram_opp, "nbk", OPT_UINT32, &nbk, - "number of banks", ""); - option_parser_register(dram_opp, "CCD", OPT_UINT32, &tCCD, - "column to column delay", ""); - option_parser_register( - dram_opp, "RRD", OPT_UINT32, &tRRD, - "minimal delay between activation of rows in different banks", ""); - option_parser_register(dram_opp, "RCD", OPT_UINT32, &tRCD, - "row to column delay", ""); - option_parser_register(dram_opp, "RAS", OPT_UINT32, &tRAS, - "time needed to activate row", ""); - option_parser_register(dram_opp, "RP", OPT_UINT32, &tRP, - "time needed to precharge (deactivate) row", ""); - option_parser_register(dram_opp, "RC", OPT_UINT32, &tRC, "row cycle time", - ""); - option_parser_register(dram_opp, "CDLR", OPT_UINT32, &tCDLR, - "switching from write to read (changes tWTR)", ""); - option_parser_register(dram_opp, "WR", OPT_UINT32, &tWR, - "last data-in to row precharge", ""); + option_parser_register(dram_opp, "nbk", OPT_UINT32, &nbk, "number of banks", ""); + option_parser_register(dram_opp, "CCD", OPT_UINT32, &tCCD, "column to column delay", ""); + option_parser_register(dram_opp, "RRD", OPT_UINT32, &tRRD, "minimal delay between activation of rows in different banks", ""); + option_parser_register(dram_opp, "RCD", OPT_UINT32, &tRCD, "row to column delay", ""); + option_parser_register(dram_opp, "RAS", OPT_UINT32, &tRAS, "time needed to activate row", ""); + option_parser_register(dram_opp, "RP", OPT_UINT32, &tRP, "time needed to precharge (deactivate) row", ""); + option_parser_register(dram_opp, "RC", OPT_UINT32, &tRC, "row cycle time", ""); + option_parser_register(dram_opp, "CDLR", OPT_UINT32, &tCDLR, "switching from write to read (changes tWTR)", ""); + option_parser_register(dram_opp, "WR", OPT_UINT32, &tWR, "last data-in to row precharge", ""); - option_parser_register(dram_opp, "CL", OPT_UINT32, &CL, "CAS latency", - ""); - option_parser_register(dram_opp, "WL", OPT_UINT32, &WL, "Write latency", - ""); + option_parser_register(dram_opp, "CL", OPT_UINT32, &CL, "CAS latency", ""); + option_parser_register(dram_opp, "WL", OPT_UINT32, &WL, "Write latency", ""); - // Disabling bank groups if their values are not specified - option_parser_register(dram_opp, "nbkgrp", OPT_UINT32, &nbkgrp, - "number of bank groups", "1"); - option_parser_register( - dram_opp, "CCDL", OPT_UINT32, &tCCDL, - "column to column delay between accesses to different bank groups", - "0"); - option_parser_register( - dram_opp, "RTPL", OPT_UINT32, &tRTPL, - "read to precharge delay between accesses to different bank groups", - "0"); + //Disabling bank groups if their values are not specified + option_parser_register(dram_opp, "nbkgrp", OPT_UINT32, &nbkgrp, "number of bank groups", "1"); + option_parser_register(dram_opp, "CCDL", OPT_UINT32, &tCCDL, "column to column delay between accesses to different bank groups", "0"); + option_parser_register(dram_opp, "RTPL", OPT_UINT32, &tRTPL, "read to precharge delay between accesses to different bank groups", "0"); - option_parser_delimited_string(dram_opp, gpgpu_dram_timing_opt, "=:;"); - fprintf(stdout, "DRAM Timing Options:\n"); - option_parser_print(dram_opp, stdout); - option_parser_destroy(dram_opp); - } + option_parser_delimited_string(dram_opp, gpgpu_dram_timing_opt, "=:;"); + fprintf(stdout, "DRAM Timing Options:\n"); + option_parser_print(dram_opp, stdout); + option_parser_destroy(dram_opp); + } - int nbkt = nbk / nbkgrp; - unsigned i; - for (i = 0; nbkt > 0; i++) { - nbkt = nbkt >> 1; - } - bk_tag_length = i - 1; - assert(nbkgrp > 0 && "Number of bank groups cannot be zero"); - tRCDWR = tRCD - (WL + 1); - if (elimnate_rw_turnaround) { - tRTW = 0; - tWTR = 0; - } else { - tRTW = (CL + (BL / data_command_freq_ratio) + 2 - WL); - tWTR = (WL + (BL / data_command_freq_ratio) + tCDLR); - } - tWTP = (WL + (BL / data_command_freq_ratio) + tWR); - dram_atom_size = BL * busW * gpu_n_mem_per_ctrlr; // burst length x bus - // width x # chips per - // partition + int nbkt = nbk/nbkgrp; + unsigned i; + for (i=0; nbkt>0; i++) { + nbkt = nbkt>>1; + } + bk_tag_length = i-1; + assert(nbkgrp>0 && "Number of bank groups cannot be zero"); + tRCDWR = tRCD-(WL+1); + if(elimnate_rw_turnaround) + { + tRTW = 0; + tWTR = 0; + } else { + tRTW = (CL+(BL/data_command_freq_ratio)+2-WL); + tWTR = (WL+(BL/data_command_freq_ratio)+tCDLR); + } + tWTP = (WL+(BL/data_command_freq_ratio)+tWR); + dram_atom_size = BL * busW * gpu_n_mem_per_ctrlr; // burst length x bus width x # chips per partition - assert(m_n_sub_partition_per_memory_channel > 0); - assert((nbk % m_n_sub_partition_per_memory_channel == 0) && - "Number of DRAM banks must be a perfect multiple of memory sub " - "partition"); - m_n_mem_sub_partition = m_n_mem * m_n_sub_partition_per_memory_channel; - fprintf(stdout, "Total number of memory sub partition = %u\n", - m_n_mem_sub_partition); + assert( m_n_sub_partition_per_memory_channel > 0 ); + assert( (nbk % m_n_sub_partition_per_memory_channel == 0) + && "Number of DRAM banks must be a perfect multiple of memory sub partition"); + m_n_mem_sub_partition = m_n_mem * m_n_sub_partition_per_memory_channel; + fprintf(stdout, "Total number of memory sub partition = %u\n", m_n_mem_sub_partition); - m_address_mapping.init(m_n_mem, m_n_sub_partition_per_memory_channel); - m_L2_config.init(&m_address_mapping); + m_address_mapping.init(m_n_mem, m_n_sub_partition_per_memory_channel); + m_L2_config.init(&m_address_mapping); - m_valid = true; + m_valid = true; - sscanf(write_queue_size_opt, "%d:%d:%d", - &gpgpu_frfcfs_dram_write_queue_size, &write_high_watermark, - &write_low_watermark); - } - void reg_options(class OptionParser *opp); + sscanf(write_queue_size_opt,"%d:%d:%d", + &gpgpu_frfcfs_dram_write_queue_size,&write_high_watermark,&write_low_watermark); + } + void reg_options(class OptionParser * opp); - bool m_valid; - mutable l2_cache_config m_L2_config; - bool m_L2_texure_only; + bool m_valid; + mutable l2_cache_config m_L2_config; + bool m_L2_texure_only; - char *gpgpu_dram_timing_opt; - char *gpgpu_L2_queue_config; - bool l2_ideal; - unsigned gpgpu_frfcfs_dram_sched_queue_size; - unsigned gpgpu_dram_return_queue_size; - enum dram_ctrl_t scheduler_type; - bool gpgpu_memlatency_stat; - unsigned m_n_mem; - unsigned m_n_sub_partition_per_memory_channel; - unsigned m_n_mem_sub_partition; - unsigned gpu_n_mem_per_ctrlr; + char *gpgpu_dram_timing_opt; + char *gpgpu_L2_queue_config; + bool l2_ideal; + unsigned gpgpu_frfcfs_dram_sched_queue_size; + unsigned gpgpu_dram_return_queue_size; + enum dram_ctrl_t scheduler_type; + bool gpgpu_memlatency_stat; + unsigned m_n_mem; + unsigned m_n_sub_partition_per_memory_channel; + unsigned m_n_mem_sub_partition; + unsigned gpu_n_mem_per_ctrlr; - unsigned rop_latency; - unsigned dram_latency; + unsigned rop_latency; + unsigned dram_latency; - // DRAM parameters + // DRAM parameters - unsigned tCCDL; // column to column delay when bank groups are enabled - unsigned tRTPL; // read to precharge delay when bank groups are enabled for - // GDDR5 this is identical to RTPS, if for other DRAM this is - // different, you will need to split them in two + unsigned tCCDL; //column to column delay when bank groups are enabled + unsigned tRTPL; //read to precharge delay when bank groups are enabled for GDDR5 this is identical to RTPS, if for other DRAM this is different, you will need to split them in two - unsigned tCCD; // column to column delay - unsigned tRRD; // minimal time required between activation of rows in - // different banks - unsigned tRCD; // row to column delay - time required to activate a row - // before a read - unsigned tRCDWR; // row to column delay for a write command - unsigned tRAS; // time needed to activate row - unsigned tRP; // row precharge ie. deactivate row - unsigned - tRC; // row cycle time ie. precharge current, then activate different row - unsigned tCDLR; // Last data-in to Read command (switching from write to - // read) - unsigned tWR; // Last data-in to Row precharge + unsigned tCCD; //column to column delay + unsigned tRRD; //minimal time required between activation of rows in different banks + unsigned tRCD; //row to column delay - time required to activate a row before a read + unsigned tRCDWR; //row to column delay for a write command + unsigned tRAS; //time needed to activate row + unsigned tRP; //row precharge ie. deactivate row + unsigned tRC; //row cycle time ie. precharge current, then activate different row + unsigned tCDLR; //Last data-in to Read command (switching from write to read) + unsigned tWR; //Last data-in to Row precharge - unsigned CL; // CAS latency - unsigned WL; // WRITE latency - unsigned BL; // Burst Length in bytes (4 in GDDR3, 8 in GDDR5) - unsigned tRTW; // time to switch from read to write - unsigned tWTR; // time to switch from write to read - unsigned tWTP; // time to switch from write to precharge in the same bank - unsigned busW; + unsigned CL; //CAS latency + unsigned WL; //WRITE latency + unsigned BL; //Burst Length in bytes (4 in GDDR3, 8 in GDDR5) + unsigned tRTW; //time to switch from read to write + unsigned tWTR; //time to switch from write to read + unsigned tWTP; //time to switch from write to precharge in the same bank + unsigned busW; - unsigned nbkgrp; // number of bank groups (has to be power of 2) - unsigned - bk_tag_length; // number of bits that define a bank inside a bank group + unsigned nbkgrp; // number of bank groups (has to be power of 2) + unsigned bk_tag_length; //number of bits that define a bank inside a bank group - unsigned nbk; + unsigned nbk; - bool elimnate_rw_turnaround; + bool elimnate_rw_turnaround; - unsigned data_command_freq_ratio; // frequency ratio between DRAM data bus - // and command bus (2 for GDDR3, 4 for - // GDDR5) - unsigned - dram_atom_size; // number of bytes transferred per read or write command + unsigned data_command_freq_ratio; // frequency ratio between DRAM data bus and command bus (2 for GDDR3, 4 for GDDR5) + unsigned dram_atom_size; // number of bytes transferred per read or write command - linear_to_raw_address_translation m_address_mapping; + linear_to_raw_address_translation m_address_mapping; - unsigned icnt_flit_size; + unsigned icnt_flit_size; - unsigned dram_bnk_indexing_policy; - unsigned dram_bnkgrp_indexing_policy; - bool dual_bus_interface; + unsigned dram_bnk_indexing_policy; + unsigned dram_bnkgrp_indexing_policy; + bool dual_bus_interface; - bool seperate_write_queue_enabled; - char *write_queue_size_opt; - unsigned gpgpu_frfcfs_dram_write_queue_size; - unsigned write_high_watermark; - unsigned write_low_watermark; - bool m_perf_sim_memcpy; - bool simple_dram_model; + bool seperate_write_queue_enabled; + char *write_queue_size_opt; + unsigned gpgpu_frfcfs_dram_write_queue_size; + unsigned write_high_watermark; + unsigned write_low_watermark; + bool m_perf_sim_memcpy; + bool simple_dram_model; - gpgpu_context *gpgpu_ctx; + gpgpu_context* gpgpu_ctx; }; + extern bool g_interactive_debugger_enabled; -class gpgpu_sim_config : public power_config, - public gpgpu_functional_sim_config { - public: - gpgpu_sim_config(gpgpu_context *ctx) - : m_shader_config(ctx), m_memory_config(ctx) { - m_valid = false; - gpgpu_ctx = ctx; - } - void reg_options(class OptionParser *opp); - void init() { - gpu_stat_sample_freq = 10000; - gpu_runtime_stat_flag = 0; - sscanf(gpgpu_runtime_stat, "%d:%x", &gpu_stat_sample_freq, - &gpu_runtime_stat_flag); - m_shader_config.init(); - ptx_set_tex_cache_linesize(m_shader_config.m_L1T_config.get_line_sz()); - m_memory_config.init(); - init_clock_domains(); - power_config::init(); - Trace::init(); +class gpgpu_sim_config : public power_config, public gpgpu_functional_sim_config { +public: + gpgpu_sim_config(gpgpu_context* ctx): m_shader_config(ctx), m_memory_config(ctx) { + m_valid = false; + gpgpu_ctx = ctx; + } + void reg_options(class OptionParser * opp); + void init() + { + gpu_stat_sample_freq = 10000; + gpu_runtime_stat_flag = 0; + sscanf(gpgpu_runtime_stat, "%d:%x", &gpu_stat_sample_freq, &gpu_runtime_stat_flag); + m_shader_config.init(); + ptx_set_tex_cache_linesize(m_shader_config.m_L1T_config.get_line_sz()); + m_memory_config.init(); + init_clock_domains(); + power_config::init(); + Trace::init(); + - // initialize file name if it is not set - time_t curr_time; - time(&curr_time); - char *date = ctime(&curr_time); - char *s = date; - while (*s) { - if (*s == ' ' || *s == '\t' || *s == ':') *s = '-'; - if (*s == '\n' || *s == '\r') *s = 0; - s++; + // initialize file name if it is not set + time_t curr_time; + time(&curr_time); + char *date = ctime(&curr_time); + char *s = date; + while (*s) { + if (*s == ' ' || *s == '\t' || *s == ':') *s = '-'; + if (*s == '\n' || *s == '\r' ) *s = 0; + s++; + } + char buf[1024]; + snprintf(buf,1024,"gpgpusim_visualizer__%s.log.gz",date); + g_visualizer_filename = strdup(buf); + + m_valid=true; } - char buf[1024]; - snprintf(buf, 1024, "gpgpusim_visualizer__%s.log.gz", date); - g_visualizer_filename = strdup(buf); - m_valid = true; - } + unsigned num_shader() const { return m_shader_config.num_shader(); } + unsigned num_cluster() const { return m_shader_config.n_simt_clusters; } + unsigned get_max_concurrent_kernel() const { return max_concurrent_kernel; } + unsigned checkpoint_option; + + size_t stack_limit() const {return stack_size_limit; } + size_t heap_limit() const {return heap_size_limit; } + size_t sync_depth_limit() const {return runtime_sync_depth_limit; } + size_t pending_launch_count_limit() const {return runtime_pending_launch_count_limit;} - unsigned num_shader() const { return m_shader_config.num_shader(); } - unsigned num_cluster() const { return m_shader_config.n_simt_clusters; } - unsigned get_max_concurrent_kernel() const { return max_concurrent_kernel; } - unsigned checkpoint_option; +private: + void init_clock_domains(void ); - size_t stack_limit() const { return stack_size_limit; } - size_t heap_limit() const { return heap_size_limit; } - size_t sync_depth_limit() const { return runtime_sync_depth_limit; } - size_t pending_launch_count_limit() const { - return runtime_pending_launch_count_limit; - } - private: - void init_clock_domains(void); + // backward pointer + class gpgpu_context* gpgpu_ctx; + bool m_valid; + shader_core_config m_shader_config; + memory_config m_memory_config; + // clock domains - frequency + double core_freq; + double icnt_freq; + double dram_freq; + double l2_freq; + double core_period; + double icnt_period; + double dram_period; + double l2_period; - // backward pointer - class gpgpu_context *gpgpu_ctx; - bool m_valid; - shader_core_config m_shader_config; - memory_config m_memory_config; - // clock domains - frequency - double core_freq; - double icnt_freq; - double dram_freq; - double l2_freq; - double core_period; - double icnt_period; - double dram_period; - double l2_period; + // GPGPU-Sim timing model options + unsigned long long gpu_max_cycle_opt; + unsigned long long gpu_max_insn_opt; + unsigned gpu_max_cta_opt; + char *gpgpu_runtime_stat; + bool gpgpu_flush_l1_cache; + bool gpgpu_flush_l2_cache; + bool gpu_deadlock_detect; + int gpgpu_frfcfs_dram_sched_queue_size; + int gpgpu_cflog_interval; + char * gpgpu_clock_domains; + unsigned max_concurrent_kernel; - // GPGPU-Sim timing model options - unsigned long long gpu_max_cycle_opt; - unsigned long long gpu_max_insn_opt; - unsigned gpu_max_cta_opt; - char *gpgpu_runtime_stat; - bool gpgpu_flush_l1_cache; - bool gpgpu_flush_l2_cache; - bool gpu_deadlock_detect; - int gpgpu_frfcfs_dram_sched_queue_size; - int gpgpu_cflog_interval; - char *gpgpu_clock_domains; - unsigned max_concurrent_kernel; + // visualizer + bool g_visualizer_enabled; + char *g_visualizer_filename; + int g_visualizer_zlevel; - // visualizer - bool g_visualizer_enabled; - char *g_visualizer_filename; - int g_visualizer_zlevel; - // statistics collection - int gpu_stat_sample_freq; - int gpu_runtime_stat_flag; + // statistics collection + int gpu_stat_sample_freq; + int gpu_runtime_stat_flag; - // Device Limits - size_t stack_size_limit; - size_t heap_size_limit; - size_t runtime_sync_depth_limit; - size_t runtime_pending_launch_count_limit; + // Device Limits + size_t stack_size_limit; + size_t heap_size_limit; + size_t runtime_sync_depth_limit; + size_t runtime_pending_launch_count_limit; - // gpu compute capability options - unsigned int gpgpu_compute_capability_major; - unsigned int gpgpu_compute_capability_minor; - unsigned long long liveness_message_freq; + //gpu compute capability options + unsigned int gpgpu_compute_capability_major; + unsigned int gpgpu_compute_capability_minor; + unsigned long long liveness_message_freq; - friend class gpgpu_sim; + friend class gpgpu_sim; }; struct occupancy_stats { - occupancy_stats() - : aggregate_warp_slot_filled(0), aggregate_theoretical_warp_slots(0) {} - occupancy_stats(unsigned long long wsf, unsigned long long tws) - : aggregate_warp_slot_filled(wsf), - aggregate_theoretical_warp_slots(tws) {} + occupancy_stats() : aggregate_warp_slot_filled(0), aggregate_theoretical_warp_slots(0){} + occupancy_stats( unsigned long long wsf, unsigned long long tws ) + : aggregate_warp_slot_filled(wsf), aggregate_theoretical_warp_slots(tws){} - unsigned long long aggregate_warp_slot_filled; - unsigned long long aggregate_theoretical_warp_slots; + unsigned long long aggregate_warp_slot_filled; + unsigned long long aggregate_theoretical_warp_slots; - float get_occ_fraction() const { - return float(aggregate_warp_slot_filled) / - float(aggregate_theoretical_warp_slots); - } + float get_occ_fraction() const { + return float(aggregate_warp_slot_filled) / float(aggregate_theoretical_warp_slots); + } - occupancy_stats &operator+=(const occupancy_stats &rhs) { - aggregate_warp_slot_filled += rhs.aggregate_warp_slot_filled; - aggregate_theoretical_warp_slots += rhs.aggregate_theoretical_warp_slots; - return *this; - } + occupancy_stats& operator+=(const occupancy_stats& rhs) { + aggregate_warp_slot_filled += rhs.aggregate_warp_slot_filled; + aggregate_theoretical_warp_slots += rhs.aggregate_theoretical_warp_slots; + return *this; + } - occupancy_stats operator+(const occupancy_stats &rhs) const { - return occupancy_stats( - aggregate_warp_slot_filled + rhs.aggregate_warp_slot_filled, - aggregate_theoretical_warp_slots + - rhs.aggregate_theoretical_warp_slots); - } + occupancy_stats operator+(const occupancy_stats& rhs) const{ + return occupancy_stats( aggregate_warp_slot_filled + rhs.aggregate_warp_slot_filled, + aggregate_theoretical_warp_slots + rhs.aggregate_theoretical_warp_slots + ); + } }; class gpgpu_context; class ptx_instruction; class watchpoint_event { - public: - watchpoint_event() { - m_thread = NULL; - m_inst = NULL; - } - watchpoint_event(const ptx_thread_info *thd, const ptx_instruction *pI) { - m_thread = thd; - m_inst = pI; - } - const ptx_thread_info *thread() const { return m_thread; } - const ptx_instruction *inst() const { return m_inst; } - - private: - const ptx_thread_info *m_thread; - const ptx_instruction *m_inst; +public: + watchpoint_event() + { + m_thread=NULL; + m_inst=NULL; + } + watchpoint_event(const ptx_thread_info *thd, const ptx_instruction *pI) + { + m_thread=thd; + m_inst = pI; + } + const ptx_thread_info *thread() const { return m_thread; } + const ptx_instruction *inst() const { return m_inst; } +private: + const ptx_thread_info *m_thread; + const ptx_instruction *m_inst; }; class gpgpu_sim : public gpgpu_t { - public: - gpgpu_sim(const gpgpu_sim_config &config, gpgpu_context *ctx); - - void set_prop(struct cudaDeviceProp *prop); +public: + gpgpu_sim( const gpgpu_sim_config &config, gpgpu_context* ctx ); - void launch(kernel_info_t *kinfo); - bool can_start_kernel(); - unsigned finished_kernel(); - void set_kernel_done(kernel_info_t *kernel); - void stop_all_running_kernels(); + void set_prop( struct cudaDeviceProp *prop ); - void init(); - void cycle(); - bool active(); - bool cycle_insn_cta_max_hit() { - return (m_config.gpu_max_cycle_opt && - (gpu_tot_sim_cycle + gpu_sim_cycle) >= - m_config.gpu_max_cycle_opt) || - (m_config.gpu_max_insn_opt && - (gpu_tot_sim_insn + gpu_sim_insn) >= m_config.gpu_max_insn_opt) || - (m_config.gpu_max_cta_opt && - (gpu_tot_issued_cta >= m_config.gpu_max_cta_opt)); - } - void print_stats(); - void update_stats(); - void deadlock_check(); + void launch( kernel_info_t *kinfo ); + bool can_start_kernel(); + unsigned finished_kernel(); + void set_kernel_done( kernel_info_t *kernel ); + void stop_all_running_kernels(); - void get_pdom_stack_top_info(unsigned sid, unsigned tid, unsigned *pc, - unsigned *rpc); + void init(); + void cycle(); + bool active(); + bool cycle_insn_cta_max_hit() { + return (m_config.gpu_max_cycle_opt && (gpu_tot_sim_cycle + gpu_sim_cycle) >= m_config.gpu_max_cycle_opt) || + (m_config.gpu_max_insn_opt && (gpu_tot_sim_insn + gpu_sim_insn) >= m_config.gpu_max_insn_opt) || + (m_config.gpu_max_cta_opt && (gpu_tot_issued_cta >= m_config.gpu_max_cta_opt) ); + } + void print_stats(); + void update_stats(); + void deadlock_check(); - int shared_mem_size() const; - int shared_mem_per_block() const; - int compute_capability_major() const; - int compute_capability_minor() const; - int num_registers_per_core() const; - int num_registers_per_block() const; - int wrp_size() const; - int shader_clock() const; - int max_cta_per_core() const; - int get_max_cta(const kernel_info_t &k) const; - const struct cudaDeviceProp *get_prop() const; - enum divergence_support_t simd_model() const; + void get_pdom_stack_top_info( unsigned sid, unsigned tid, unsigned *pc, unsigned *rpc ); - unsigned threads_per_core() const; - bool get_more_cta_left() const; - bool kernel_more_cta_left(kernel_info_t *kernel) const; - bool hit_max_cta_count() const; - kernel_info_t *select_kernel(); + int shared_mem_size() const; + int shared_mem_per_block() const; + int compute_capability_major() const; + int compute_capability_minor() const; + int num_registers_per_core() const; + int num_registers_per_block() const; + int wrp_size() const; + int shader_clock() const; + int max_cta_per_core() const; + int get_max_cta( const kernel_info_t &k ) const; + const struct cudaDeviceProp *get_prop() const; + enum divergence_support_t simd_model() const; - const gpgpu_sim_config &get_config() const { return m_config; } - void gpu_print_stat(); - void dump_pipeline(int mask, int s, int m) const; + unsigned threads_per_core() const; + bool get_more_cta_left() const; + bool kernel_more_cta_left(kernel_info_t *kernel) const; + bool hit_max_cta_count() const; + kernel_info_t *select_kernel(); - void perf_memcpy_to_gpu(size_t dst_start_addr, size_t count); + const gpgpu_sim_config &get_config() const { return m_config; } + void gpu_print_stat(); + void dump_pipeline( int mask, int s, int m ) const; - // The next three functions added to be used by the functional simulation - // function + void perf_memcpy_to_gpu( size_t dst_start_addr, size_t count ); - //! Get shader core configuration - /*! - * Returning the configuration of the shader core, used by the functional - * simulation only so far - */ - const shader_core_config *getShaderCoreConfig(); + //The next three functions added to be used by the functional simulation function + + //! Get shader core configuration + /*! + * Returning the configuration of the shader core, used by the functional simulation only so far + */ + const shader_core_config * getShaderCoreConfig(); + + + //! Get shader core Memory Configuration + /*! + * Returning the memory configuration of the shader core, used by the functional simulation only so far + */ + const memory_config * getMemoryConfig(); + + + //! Get shader core SIMT cluster + /*! + * Returning the cluster of of the shader core, used by the functional simulation so far + */ + simt_core_cluster * getSIMTCluster(); - //! Get shader core Memory Configuration - /*! - * Returning the memory configuration of the shader core, used by the - * functional simulation only so far - */ - const memory_config *getMemoryConfig(); + void hit_watchpoint( unsigned watchpoint_num, ptx_thread_info *thd, const ptx_instruction *pI ); - //! Get shader core SIMT cluster - /*! - * Returning the cluster of of the shader core, used by the functional - * simulation so far - */ - simt_core_cluster *getSIMTCluster(); + // backward pointer + class gpgpu_context* gpgpu_ctx; - void hit_watchpoint(unsigned watchpoint_num, ptx_thread_info *thd, - const ptx_instruction *pI); +private: + // clocks + void reinit_clock_domains(void); + int next_clock_domain(void); + void issue_block2core(); + void print_dram_stats(FILE *fout) const; + void shader_print_runtime_stat( FILE *fout ); + void shader_print_l1_miss_stat( FILE *fout ) const; + void shader_print_cache_stats( FILE *fout ) const; + void shader_print_scheduler_stat( FILE* fout, bool print_dynamic_info ) const; + void visualizer_printstat(); + void print_shader_cycle_distro( FILE *fout ) const; - // backward pointer - class gpgpu_context *gpgpu_ctx; + void gpgpu_debug(); - private: - // clocks - void reinit_clock_domains(void); - int next_clock_domain(void); - void issue_block2core(); - void print_dram_stats(FILE *fout) const; - void shader_print_runtime_stat(FILE *fout); - void shader_print_l1_miss_stat(FILE *fout) const; - void shader_print_cache_stats(FILE *fout) const; - void shader_print_scheduler_stat(FILE *fout, bool print_dynamic_info) const; - void visualizer_printstat(); - void print_shader_cycle_distro(FILE *fout) const; +///// data ///// - void gpgpu_debug(); + class simt_core_cluster **m_cluster; + class memory_partition_unit **m_memory_partition_unit; + class memory_sub_partition **m_memory_sub_partition; - ///// data ///// + std::vector<kernel_info_t*> m_running_kernels; + unsigned m_last_issued_kernel; - class simt_core_cluster **m_cluster; - class memory_partition_unit **m_memory_partition_unit; - class memory_sub_partition **m_memory_sub_partition; + std::list<unsigned> m_finished_kernel; + // m_total_cta_launched == per-kernel count. gpu_tot_issued_cta == global count. + unsigned long long m_total_cta_launched; + unsigned long long gpu_tot_issued_cta; - std::vector<kernel_info_t *> m_running_kernels; - unsigned m_last_issued_kernel; + unsigned m_last_cluster_issue; + float * average_pipeline_duty_cycle; + float * active_sms; + // time of next rising edge + double core_time; + double icnt_time; + double dram_time; + double l2_time; - std::list<unsigned> m_finished_kernel; - // m_total_cta_launched == per-kernel count. gpu_tot_issued_cta == global - // count. - unsigned long long m_total_cta_launched; - unsigned long long gpu_tot_issued_cta; + // debug + bool gpu_deadlock; - unsigned m_last_cluster_issue; - float *average_pipeline_duty_cycle; - float *active_sms; - // time of next rising edge - double core_time; - double icnt_time; - double dram_time; - double l2_time; + //// configuration parameters //// + const gpgpu_sim_config &m_config; + + const struct cudaDeviceProp *m_cuda_properties; + const shader_core_config *m_shader_config; + const memory_config *m_memory_config; - // debug - bool gpu_deadlock; + // stats + class shader_core_stats *m_shader_stats; + class memory_stats_t *m_memory_stats; + class power_stat_t *m_power_stats; + class gpgpu_sim_wrapper *m_gpgpusim_wrapper; + unsigned long long last_gpu_sim_insn; - //// configuration parameters //// - const gpgpu_sim_config &m_config; + unsigned long long last_liveness_message_time; - const struct cudaDeviceProp *m_cuda_properties; - const shader_core_config *m_shader_config; - const memory_config *m_memory_config; + std::map<std::string, FuncCache> m_special_cache_config; - // stats - class shader_core_stats *m_shader_stats; - class memory_stats_t *m_memory_stats; - class power_stat_t *m_power_stats; - class gpgpu_sim_wrapper *m_gpgpusim_wrapper; - unsigned long long last_gpu_sim_insn; + std::vector<std::string> m_executed_kernel_names; //< names of kernel for stat printout + std::vector<unsigned> m_executed_kernel_uids; //< uids of kernel launches for stat printout + std::map<unsigned,watchpoint_event> g_watchpoint_hits; - unsigned long long last_liveness_message_time; + std::string executed_kernel_info_string(); //< format the kernel information into a string for stat printout + void clear_executed_kernel_info(); //< clear the kernel information after stat printout - std::map<std::string, FuncCache> m_special_cache_config; - std::vector<std::string> - m_executed_kernel_names; //< names of kernel for stat printout - std::vector<unsigned> - m_executed_kernel_uids; //< uids of kernel launches for stat printout - std::map<unsigned, watchpoint_event> g_watchpoint_hits; +public: + unsigned long long gpu_sim_insn; + unsigned long long gpu_tot_sim_insn; + unsigned long long gpu_sim_insn_last_update; + unsigned gpu_sim_insn_last_update_sid; + occupancy_stats gpu_occupancy; + occupancy_stats gpu_tot_occupancy; - std::string executed_kernel_info_string(); //< format the kernel information - //into a string for stat printout - void clear_executed_kernel_info(); //< clear the kernel information after - //stat printout + // performance counter for stalls due to congestion. + unsigned int gpu_stall_dramfull; + unsigned int gpu_stall_icnt2sh; + unsigned long long partiton_reqs_in_parallel; + unsigned long long partiton_reqs_in_parallel_total; + unsigned long long partiton_reqs_in_parallel_util; + unsigned long long partiton_reqs_in_parallel_util_total; + unsigned long long gpu_sim_cycle_parition_util; + unsigned long long gpu_tot_sim_cycle_parition_util; + unsigned long long partiton_replys_in_parallel; + unsigned long long partiton_replys_in_parallel_total; - public: - unsigned long long gpu_sim_insn; - unsigned long long gpu_tot_sim_insn; - unsigned long long gpu_sim_insn_last_update; - unsigned gpu_sim_insn_last_update_sid; - occupancy_stats gpu_occupancy; - occupancy_stats gpu_tot_occupancy; - // performance counter for stalls due to congestion. - unsigned int gpu_stall_dramfull; - unsigned int gpu_stall_icnt2sh; - unsigned long long partiton_reqs_in_parallel; - unsigned long long partiton_reqs_in_parallel_total; - unsigned long long partiton_reqs_in_parallel_util; - unsigned long long partiton_reqs_in_parallel_util_total; - unsigned long long gpu_sim_cycle_parition_util; - unsigned long long gpu_tot_sim_cycle_parition_util; - unsigned long long partiton_replys_in_parallel; - unsigned long long partiton_replys_in_parallel_total; + FuncCache get_cache_config(std::string kernel_name); + void set_cache_config(std::string kernel_name, FuncCache cacheConfig ); + bool has_special_cache_config(std::string kernel_name); + void change_cache_config(FuncCache cache_config); + void set_cache_config(std::string kernel_name); - FuncCache get_cache_config(std::string kernel_name); - void set_cache_config(std::string kernel_name, FuncCache cacheConfig); - bool has_special_cache_config(std::string kernel_name); - void change_cache_config(FuncCache cache_config); - void set_cache_config(std::string kernel_name); + //Jin: functional simulation for CDP +private: + //set by stream operation every time a functoinal simulation is done + bool m_functional_sim; + kernel_info_t * m_functional_sim_kernel; - // Jin: functional simulation for CDP - private: - // set by stream operation every time a functoinal simulation is done - bool m_functional_sim; - kernel_info_t *m_functional_sim_kernel; - - public: - bool is_functional_sim() { return m_functional_sim; } - kernel_info_t *get_functional_kernel() { return m_functional_sim_kernel; } - void functional_launch(kernel_info_t *k) { - m_functional_sim = true; - m_functional_sim_kernel = k; - } - void finish_functional_sim(kernel_info_t *k) { - assert(m_functional_sim); - assert(m_functional_sim_kernel == k); - m_functional_sim = false; - m_functional_sim_kernel = NULL; - } +public: + bool is_functional_sim() { return m_functional_sim; } + kernel_info_t * get_functional_kernel() { return m_functional_sim_kernel; } + void functional_launch(kernel_info_t * k) { + m_functional_sim = true; + m_functional_sim_kernel = k; + } + void finish_functional_sim(kernel_info_t * k) { + assert(m_functional_sim); + assert(m_functional_sim_kernel == k); + m_functional_sim = false; + m_functional_sim_kernel = NULL; + } }; + #endif diff --git a/src/gpgpu-sim/histogram.cc b/src/gpgpu-sim/histogram.cc index 02c6c66..67f5c18 100644 --- a/src/gpgpu-sim/histogram.cc +++ b/src/gpgpu-sim/histogram.cc @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -31,108 +29,96 @@ #include <assert.h> -binned_histogram::binned_histogram(std::string name, int nbins, int* bins) - : m_name(name), - m_nbins(nbins), - m_bins(NULL), - m_bin_cnts(new int[m_nbins]), - m_maximum(0), - m_sum(0) { - if (bins) { - m_bins = new int[m_nbins]; - for (int i = 0; i < nbins; i++) { - m_bins[i] = bins[i]; - } - } +binned_histogram::binned_histogram (std::string name, int nbins, int* bins) + : m_name(name), m_nbins(nbins), m_bins(NULL), m_bin_cnts(new int[m_nbins]), m_maximum(0), m_sum(0) +{ + if (bins) { + m_bins = new int[m_nbins]; + for (int i = 0; i < nbins; i++) { + m_bins[i] = bins[i]; + } + } - reset_bins(); + reset_bins(); } -binned_histogram::binned_histogram(const binned_histogram& other) - : m_name(other.m_name), - m_nbins(other.m_nbins), - m_bins(NULL), - m_bin_cnts(new int[m_nbins]), - m_maximum(0), - m_sum(0) { - for (int i = 0; i < m_nbins; i++) { - m_bin_cnts[i] = other.m_bin_cnts[i]; - } +binned_histogram::binned_histogram (const binned_histogram& other) + : m_name(other.m_name), m_nbins(other.m_nbins), m_bins(NULL), + m_bin_cnts(new int[m_nbins]), m_maximum(0), m_sum(0) +{ + for (int i = 0; i < m_nbins; i++) { + m_bin_cnts[i] = other.m_bin_cnts[i]; + } } -void binned_histogram::reset_bins() { - for (int i = 0; i < m_nbins; i++) { - m_bin_cnts[i] = 0; - } +void binned_histogram::reset_bins () { + for (int i = 0; i < m_nbins; i++) { + m_bin_cnts[i] = 0; + } } -void binned_histogram::add2bin(int sample) { - assert(0); - m_maximum = (sample > m_maximum) ? sample : m_maximum; +void binned_histogram::add2bin (int sample) { + assert(0); + m_maximum = (sample > m_maximum)? sample : m_maximum; } -void binned_histogram::fprint(FILE* fout) const { - if (m_name.c_str() != NULL) fprintf(fout, "%s = ", m_name.c_str()); - int total_sample = 0; - for (int i = 0; i < m_nbins; i++) { - fprintf(fout, "%d ", m_bin_cnts[i]); - total_sample += m_bin_cnts[i]; - } - fprintf(fout, "max=%d ", m_maximum); - float avg = 0.0f; - if (total_sample > 0) { - avg = (float)m_sum / total_sample; - } - fprintf(fout, "avg=%0.2f ", avg); +void binned_histogram::fprint (FILE *fout) const +{ + if (m_name.c_str() != NULL) fprintf(fout, "%s = ", m_name.c_str()); + int total_sample = 0; + for (int i = 0; i < m_nbins; i++) { + fprintf(fout, "%d ", m_bin_cnts[i]); + total_sample += m_bin_cnts[i]; + } + fprintf(fout, "max=%d ", m_maximum); + float avg = 0.0f; + if (total_sample > 0) { + avg = (float)m_sum / total_sample; + } + fprintf(fout, "avg=%0.2f ", avg); } -binned_histogram::~binned_histogram() { - if (m_bins) delete[] m_bins; - delete[] m_bin_cnts; +binned_histogram::~binned_histogram () { + if (m_bins) delete[] m_bins; + delete[] m_bin_cnts; } -pow2_histogram::pow2_histogram(std::string name, int nbins, int* bins) - : binned_histogram(name, nbins, bins) {} +pow2_histogram::pow2_histogram (std::string name, int nbins, int* bins) + : binned_histogram (name, nbins, bins) {} -void pow2_histogram::add2bin(int sample) { - assert(sample >= 0); +void pow2_histogram::add2bin (int sample) { + assert(sample >= 0); + + int bin; + int v = sample; + register unsigned int shift; - int bin; - int v = sample; - register unsigned int shift; - - bin = (v > 0xFFFF) << 4; - v >>= bin; - shift = (v > 0xFF) << 3; - v >>= shift; - bin |= shift; - shift = (v > 0xF) << 2; - v >>= shift; - bin |= shift; - shift = (v > 0x3) << 1; - v >>= shift; - bin |= shift; - bin |= (v >> 1); - bin += (sample > 0) ? 1 : 0; - - m_bin_cnts[bin] += 1; - - m_maximum = (sample > m_maximum) ? sample : m_maximum; - m_sum += sample; + bin = (v > 0xFFFF) << 4; v >>= bin; + shift = (v > 0xFF ) << 3; v >>= shift; bin |= shift; + shift = (v > 0xF ) << 2; v >>= shift; bin |= shift; + shift = (v > 0x3 ) << 1; v >>= shift; bin |= shift; + bin |= (v >> 1); + bin += (sample > 0)? 1:0; + + m_bin_cnts[bin] += 1; + + m_maximum = (sample > m_maximum)? sample : m_maximum; + m_sum += sample; } -linear_histogram::linear_histogram(int stride, const char* name, int nbins, - int* bins) - : binned_histogram(name, nbins, bins), m_stride(stride) {} - -void linear_histogram::add2bin(int sample) { - assert(sample >= 0); - - int bin = sample / m_stride; - if (bin >= m_nbins) bin = m_nbins - 1; +linear_histogram::linear_histogram (int stride, const char *name, int nbins, int* bins) + : binned_histogram (name, nbins, bins), m_stride(stride) +{ +} - m_bin_cnts[bin] += 1; +void linear_histogram::add2bin (int sample) { + assert(sample >= 0); - m_maximum = (sample > m_maximum) ? sample : m_maximum; - m_sum += sample; + int bin = sample / m_stride; + if (bin >= m_nbins) bin = m_nbins - 1; + + m_bin_cnts[bin] += 1; + + m_maximum = (sample > m_maximum)? sample : m_maximum; + m_sum += sample; } diff --git a/src/gpgpu-sim/histogram.h b/src/gpgpu-sim/histogram.h index 03d43ce..e8fd375 100644 --- a/src/gpgpu-sim/histogram.h +++ b/src/gpgpu-sim/histogram.h @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -36,46 +34,44 @@ #include <string> class binned_histogram { - public: - // creators - binned_histogram(std::string name = "", int nbins = 32, int* bins = NULL); - binned_histogram(const binned_histogram& other); - virtual ~binned_histogram(); +public: + // creators + binned_histogram (std::string name = "", int nbins = 32, int* bins = NULL); + binned_histogram (const binned_histogram& other); + virtual ~binned_histogram (); - // modifiers: - void reset_bins(); - void add2bin(int sample); + // modifiers: + void reset_bins (); + void add2bin (int sample); - // accessors: - void fprint(FILE* fout) const; + // accessors: + void fprint (FILE *fout) const; - protected: - std::string m_name; - int m_nbins; - int* m_bins; // bin boundaries - int* m_bin_cnts; // counters - int m_maximum; // the maximum sample - signed long long int m_sum; // for calculating the average +protected: + std::string m_name; + int m_nbins; + int *m_bins; // bin boundaries + int *m_bin_cnts; // counters + int m_maximum; // the maximum sample + signed long long int m_sum; // for calculating the average }; class pow2_histogram : public binned_histogram { - public: - pow2_histogram(std::string name = "", int nbins = 32, int* bins = NULL); - ~pow2_histogram() {} +public: + pow2_histogram ( std::string name = "", int nbins = 32, int* bins = NULL); + ~pow2_histogram() {} - void add2bin(int sample); + void add2bin (int sample); }; class linear_histogram : public binned_histogram { - public: - linear_histogram(int stride = 1, const char* name = NULL, int nbins = 32, - int* bins = NULL); - ~linear_histogram() {} +public: + linear_histogram (int stride = 1, const char *name = NULL, int nbins = 32, int* bins = NULL); + ~linear_histogram() {} - void add2bin(int sample); - - private: - int m_stride; + void add2bin (int sample); +private: + int m_stride; }; #endif diff --git a/src/gpgpu-sim/icnt_wrapper.cc b/src/gpgpu-sim/icnt_wrapper.cc index bb44d4d..67724d0 100644 --- a/src/gpgpu-sim/icnt_wrapper.cc +++ b/src/gpgpu-sim/icnt_wrapper.cc @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -33,163 +31,196 @@ #include "../intersim2/interconnect_interface.hpp" #include "local_interconnect.h" -icnt_create_p icnt_create; -icnt_init_p icnt_init; -icnt_has_buffer_p icnt_has_buffer; -icnt_push_p icnt_push; -icnt_pop_p icnt_pop; -icnt_transfer_p icnt_transfer; -icnt_busy_p icnt_busy; -icnt_display_stats_p icnt_display_stats; + +icnt_create_p icnt_create; +icnt_init_p icnt_init; +icnt_has_buffer_p icnt_has_buffer; +icnt_push_p icnt_push; +icnt_pop_p icnt_pop; +icnt_transfer_p icnt_transfer; +icnt_busy_p icnt_busy; +icnt_display_stats_p icnt_display_stats; icnt_display_overall_stats_p icnt_display_overall_stats; -icnt_display_state_p icnt_display_state; -icnt_get_flit_size_p icnt_get_flit_size; +icnt_display_state_p icnt_display_state; +icnt_get_flit_size_p icnt_get_flit_size; -unsigned g_network_mode; +unsigned g_network_mode; char* g_network_config_filename; + struct inct_config g_inct_config; -LocalInterconnect* g_localicnt_interface; +LocalInterconnect *g_localicnt_interface; #include "../option_parser.h" // Wrapper to intersim2 to accompany old icnt_wrapper // TODO: use delegate/boost/c++11<funtion> instead -static void intersim2_create(unsigned int n_shader, unsigned int n_mem) { - g_icnt_interface->CreateInterconnect(n_shader, n_mem); +static void intersim2_create(unsigned int n_shader, unsigned int n_mem) +{ + g_icnt_interface->CreateInterconnect(n_shader, n_mem); } -static void intersim2_init() { g_icnt_interface->Init(); } +static void intersim2_init() +{ + g_icnt_interface->Init(); +} -static bool intersim2_has_buffer(unsigned input, unsigned int size) { - return g_icnt_interface->HasBuffer(input, size); +static bool intersim2_has_buffer(unsigned input, unsigned int size) +{ + return g_icnt_interface->HasBuffer(input, size); } -static void intersim2_push(unsigned input, unsigned output, void* data, - unsigned int size) { - g_icnt_interface->Push(input, output, data, size); +static void intersim2_push(unsigned input, unsigned output, void* data, unsigned int size) +{ + g_icnt_interface->Push(input, output, data, size); } -static void* intersim2_pop(unsigned output) { - return g_icnt_interface->Pop(output); +static void* intersim2_pop(unsigned output) +{ + return g_icnt_interface->Pop(output); } -static void intersim2_transfer() { g_icnt_interface->Advance(); } +static void intersim2_transfer() +{ + g_icnt_interface->Advance(); +} -static bool intersim2_busy() { return g_icnt_interface->Busy(); } +static bool intersim2_busy() +{ + return g_icnt_interface->Busy(); +} -static void intersim2_display_stats() { g_icnt_interface->DisplayStats(); } +static void intersim2_display_stats() +{ + g_icnt_interface->DisplayStats(); +} -static void intersim2_display_overall_stats() { - g_icnt_interface->DisplayOverallStats(); +static void intersim2_display_overall_stats() +{ + g_icnt_interface->DisplayOverallStats(); } -static void intersim2_display_state(FILE* fp) { - g_icnt_interface->DisplayState(fp); +static void intersim2_display_state(FILE *fp) +{ + g_icnt_interface->DisplayState(fp); } -static unsigned intersim2_get_flit_size() { - return g_icnt_interface->GetFlitSize(); +static unsigned intersim2_get_flit_size() +{ + return g_icnt_interface->GetFlitSize(); } + ////////////////////////////////////////////////////// -static void LocalInterconnect_create(unsigned int n_shader, - unsigned int n_mem) { - g_localicnt_interface->CreateInterconnect(n_shader, n_mem); +static void LocalInterconnect_create(unsigned int n_shader, unsigned int n_mem) +{ + g_localicnt_interface->CreateInterconnect(n_shader, n_mem); } -static void LocalInterconnect_init() { g_localicnt_interface->Init(); } +static void LocalInterconnect_init() +{ + g_localicnt_interface->Init(); +} -static bool LocalInterconnect_has_buffer(unsigned input, unsigned int size) { - return g_localicnt_interface->HasBuffer(input, size); +static bool LocalInterconnect_has_buffer(unsigned input, unsigned int size) +{ + return g_localicnt_interface->HasBuffer(input, size); } -static void LocalInterconnect_push(unsigned input, unsigned output, void* data, - unsigned int size) { - g_localicnt_interface->Push(input, output, data, size); +static void LocalInterconnect_push(unsigned input, unsigned output, void* data, unsigned int size) +{ + g_localicnt_interface->Push(input, output, data, size); } -static void* LocalInterconnect_pop(unsigned output) { - return g_localicnt_interface->Pop(output); +static void* LocalInterconnect_pop(unsigned output) +{ + return g_localicnt_interface->Pop(output); } -static void LocalInterconnect_transfer() { g_localicnt_interface->Advance(); } +static void LocalInterconnect_transfer() +{ + g_localicnt_interface->Advance(); +} -static bool LocalInterconnect_busy() { return g_localicnt_interface->Busy(); } +static bool LocalInterconnect_busy() +{ + return g_localicnt_interface->Busy(); +} -static void LocalInterconnect_display_stats() { - g_localicnt_interface->DisplayStats(); +static void LocalInterconnect_display_stats() +{ + g_localicnt_interface->DisplayStats(); } -static void LocalInterconnect_display_overall_stats() { - g_localicnt_interface->DisplayOverallStats(); +static void LocalInterconnect_display_overall_stats() +{ + g_localicnt_interface->DisplayOverallStats(); } -static void LocalInterconnect_display_state(FILE* fp) { - g_localicnt_interface->DisplayState(fp); +static void LocalInterconnect_display_state(FILE *fp) +{ + g_localicnt_interface->DisplayState(fp); } -static unsigned LocalInterconnect_get_flit_size() { - return g_localicnt_interface->GetFlitSize(); +static unsigned LocalInterconnect_get_flit_size() +{ + return g_localicnt_interface->GetFlitSize(); } + /////////////////////////// -void icnt_reg_options(class OptionParser* opp) { - option_parser_register(opp, "-network_mode", OPT_INT32, &g_network_mode, - "Interconnection network mode", "1"); - option_parser_register(opp, "-inter_config_file", OPT_CSTR, - &g_network_config_filename, - "Interconnection network config file", "mesh"); +void icnt_reg_options( class OptionParser * opp ) +{ + option_parser_register(opp, "-network_mode", OPT_INT32, &g_network_mode, "Interconnection network mode", "1"); + option_parser_register(opp, "-inter_config_file", OPT_CSTR, &g_network_config_filename, "Interconnection network config file", "mesh"); + + + //parameters for local xbar + option_parser_register(opp, "-inct_in_buffer_limit", OPT_UINT32, &g_inct_config.in_buffer_limit, "in_buffer_limit", "64"); + option_parser_register(opp, "-inct_out_buffer_limit", OPT_UINT32, &g_inct_config.out_buffer_limit, "out_buffer_limit", "64"); + option_parser_register(opp, "-inct_subnets", OPT_UINT32, &g_inct_config.subnets, "subnets", "2"); + option_parser_register(opp, "-arbiter_algo", OPT_UINT32, &g_inct_config.arbiter_algo, "arbiter_algo", "1"); + - // parameters for local xbar - option_parser_register(opp, "-inct_in_buffer_limit", OPT_UINT32, - &g_inct_config.in_buffer_limit, "in_buffer_limit", - "64"); - option_parser_register(opp, "-inct_out_buffer_limit", OPT_UINT32, - &g_inct_config.out_buffer_limit, "out_buffer_limit", - "64"); - option_parser_register(opp, "-inct_subnets", OPT_UINT32, - &g_inct_config.subnets, "subnets", "2"); - option_parser_register(opp, "-arbiter_algo", OPT_UINT32, - &g_inct_config.arbiter_algo, "arbiter_algo", "1"); } -void icnt_wrapper_init() { - switch (g_network_mode) { - case INTERSIM: - // FIXME: delete the object: may add icnt_done wrapper - g_icnt_interface = InterconnectInterface::New(g_network_config_filename); - icnt_create = intersim2_create; - icnt_init = intersim2_init; - icnt_has_buffer = intersim2_has_buffer; - icnt_push = intersim2_push; - icnt_pop = intersim2_pop; - icnt_transfer = intersim2_transfer; - icnt_busy = intersim2_busy; - icnt_display_stats = intersim2_display_stats; - icnt_display_overall_stats = intersim2_display_overall_stats; - icnt_display_state = intersim2_display_state; - icnt_get_flit_size = intersim2_get_flit_size; - break; - case LOCAL_XBAR: - g_localicnt_interface = LocalInterconnect::New(g_inct_config); - icnt_create = LocalInterconnect_create; - icnt_init = LocalInterconnect_init; - icnt_has_buffer = LocalInterconnect_has_buffer; - icnt_push = LocalInterconnect_push; - icnt_pop = LocalInterconnect_pop; - icnt_transfer = LocalInterconnect_transfer; - icnt_busy = LocalInterconnect_busy; - icnt_display_stats = LocalInterconnect_display_stats; - icnt_display_overall_stats = LocalInterconnect_display_overall_stats; - icnt_display_state = LocalInterconnect_display_state; - icnt_get_flit_size = LocalInterconnect_get_flit_size; - break; - default: - assert(0); - break; - } +void icnt_wrapper_init() +{ + switch (g_network_mode) { + case INTERSIM: + //FIXME: delete the object: may add icnt_done wrapper + g_icnt_interface = InterconnectInterface::New(g_network_config_filename); + icnt_create = intersim2_create; + icnt_init = intersim2_init; + icnt_has_buffer = intersim2_has_buffer; + icnt_push = intersim2_push; + icnt_pop = intersim2_pop; + icnt_transfer = intersim2_transfer; + icnt_busy = intersim2_busy; + icnt_display_stats = intersim2_display_stats; + icnt_display_overall_stats = intersim2_display_overall_stats; + icnt_display_state = intersim2_display_state; + icnt_get_flit_size = intersim2_get_flit_size; + break; + case LOCAL_XBAR: + g_localicnt_interface = LocalInterconnect::New(g_inct_config); + icnt_create = LocalInterconnect_create; + icnt_init = LocalInterconnect_init; + icnt_has_buffer = LocalInterconnect_has_buffer; + icnt_push = LocalInterconnect_push; + icnt_pop = LocalInterconnect_pop; + icnt_transfer = LocalInterconnect_transfer; + icnt_busy = LocalInterconnect_busy; + icnt_display_stats = LocalInterconnect_display_stats; + icnt_display_overall_stats = LocalInterconnect_display_overall_stats; + icnt_display_state = LocalInterconnect_display_state; + icnt_get_flit_size = LocalInterconnect_get_flit_size; + break; + default: + assert(0); + break; + } } diff --git a/src/gpgpu-sim/icnt_wrapper.h b/src/gpgpu-sim/icnt_wrapper.h index fbaeceb..e1086f9 100644 --- a/src/gpgpu-sim/icnt_wrapper.h +++ b/src/gpgpu-sim/icnt_wrapper.h @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -34,37 +32,42 @@ // functional interface to the interconnect -typedef void (*icnt_create_p)(unsigned n_shader, unsigned n_mem); -typedef void (*icnt_init_p)(); +typedef void (*icnt_create_p)(unsigned n_shader, unsigned n_mem); +typedef void (*icnt_init_p)( ); typedef bool (*icnt_has_buffer_p)(unsigned input, unsigned int size); -typedef void (*icnt_push_p)(unsigned input, unsigned output, void* data, - unsigned int size); +typedef void (*icnt_push_p)(unsigned input, unsigned output, void* data, unsigned int size); typedef void* (*icnt_pop_p)(unsigned output); -typedef void (*icnt_transfer_p)(); -typedef bool (*icnt_busy_p)(); -typedef void (*icnt_drain_p)(); -typedef void (*icnt_display_stats_p)(); -typedef void (*icnt_display_overall_stats_p)(); +typedef void (*icnt_transfer_p)( ); +typedef bool (*icnt_busy_p)( ); +typedef void (*icnt_drain_p)( ); +typedef void (*icnt_display_stats_p)( ); +typedef void (*icnt_display_overall_stats_p)( ); typedef void (*icnt_display_state_p)(FILE* fp); typedef unsigned (*icnt_get_flit_size_p)(); -extern icnt_create_p icnt_create; -extern icnt_init_p icnt_init; +extern icnt_create_p icnt_create; +extern icnt_init_p icnt_init; extern icnt_has_buffer_p icnt_has_buffer; -extern icnt_push_p icnt_push; -extern icnt_pop_p icnt_pop; -extern icnt_transfer_p icnt_transfer; -extern icnt_busy_p icnt_busy; -extern icnt_drain_p icnt_drain; +extern icnt_push_p icnt_push; +extern icnt_pop_p icnt_pop; +extern icnt_transfer_p icnt_transfer; +extern icnt_busy_p icnt_busy; +extern icnt_drain_p icnt_drain; extern icnt_display_stats_p icnt_display_stats; extern icnt_display_overall_stats_p icnt_display_overall_stats; extern icnt_display_state_p icnt_display_state; extern icnt_get_flit_size_p icnt_get_flit_size; extern unsigned g_network_mode; -enum network_mode { INTERSIM = 1, LOCAL_XBAR = 2, N_NETWORK_MODE }; +enum network_mode { + INTERSIM = 1, + LOCAL_XBAR = 2, + N_NETWORK_MODE +}; + + void icnt_wrapper_init(); -void icnt_reg_options(class OptionParser* opp); +void icnt_reg_options( class OptionParser * opp ); #endif diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc index 7fdb5a3..fb4ce32 100644 --- a/src/gpgpu-sim/l2cache.cc +++ b/src/gpgpu-sim/l2cache.cc @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -27,835 +25,797 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include <stdio.h> #include <stdlib.h> +#include <stdio.h> #include <string.h> #include <list> #include <set> -#include "../abstract_hardware_model.h" #include "../option_parser.h" -#include "../statwrapper.h" +#include "mem_fetch.h" #include "dram.h" #include "gpu-cache.h" -#include "gpu-sim.h" #include "histogram.h" #include "l2cache.h" -#include "l2cache_trace.h" -#include "mem_fetch.h" -#include "mem_latency_stat.h" +#include "../statwrapper.h" +#include "../abstract_hardware_model.h" +#include "gpu-sim.h" #include "shader.h" +#include "mem_latency_stat.h" +#include "l2cache_trace.h" + -mem_fetch *partition_mf_allocator::alloc(new_addr_type addr, - mem_access_type type, unsigned size, - bool wr, - unsigned long long cycle) const { - assert(wr); - mem_access_t access(type, addr, size, wr, m_memory_config->gpgpu_ctx); - mem_fetch *mf = new mem_fetch(access, NULL, WRITE_PACKET_SIZE, -1, -1, -1, - m_memory_config, cycle); - return mf; +mem_fetch * partition_mf_allocator::alloc(new_addr_type addr, mem_access_type type, unsigned size, bool wr, unsigned long long cycle ) const +{ + assert( wr ); + mem_access_t access( type, addr, size, wr, m_memory_config->gpgpu_ctx ); + mem_fetch *mf = new mem_fetch( access, + NULL, + WRITE_PACKET_SIZE, + -1, + -1, + -1, + m_memory_config, + cycle); + return mf; } -memory_partition_unit::memory_partition_unit(unsigned partition_id, - const memory_config *config, - class memory_stats_t *stats, - class gpgpu_sim *gpu) - : m_id(partition_id), - m_config(config), - m_stats(stats), - m_arbitration_metadata(config), - m_gpu(gpu) { - m_dram = new dram_t(m_id, m_config, m_stats, this, gpu); +memory_partition_unit::memory_partition_unit( unsigned partition_id, + const memory_config *config, + class memory_stats_t *stats, + class gpgpu_sim* gpu) +: m_id(partition_id), m_config(config), m_stats(stats), m_arbitration_metadata(config), m_gpu(gpu) +{ + m_dram = new dram_t(m_id,m_config,m_stats,this,gpu); + + m_sub_partition = new memory_sub_partition*[m_config->m_n_sub_partition_per_memory_channel]; + for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; p++) { + unsigned sub_partition_id = m_id * m_config->m_n_sub_partition_per_memory_channel + p; + m_sub_partition[p] = new memory_sub_partition(sub_partition_id, m_config, stats, gpu); + } - m_sub_partition = new memory_sub_partition - *[m_config->m_n_sub_partition_per_memory_channel]; - for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; - p++) { - unsigned sub_partition_id = - m_id * m_config->m_n_sub_partition_per_memory_channel + p; - m_sub_partition[p] = - new memory_sub_partition(sub_partition_id, m_config, stats, gpu); - } } -void memory_partition_unit::handle_memcpy_to_gpu( - size_t addr, unsigned global_subpart_id, mem_access_sector_mask_t mask) { - unsigned p = global_sub_partition_id_to_local_id(global_subpart_id); - std::string mystring = mask.to_string<char, std::string::traits_type, - std::string::allocator_type>(); - MEMPART_DPRINTF( - "Copy Engine Request Received For Address=%zx, local_subpart=%u, " - "global_subpart=%u, sector_mask=%s \n", - addr, p, global_subpart_id, mystring.c_str()); - m_sub_partition[p]->force_l2_tag_update( - addr, m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle, mask); +void memory_partition_unit::handle_memcpy_to_gpu( size_t addr, unsigned global_subpart_id, mem_access_sector_mask_t mask ) +{ + unsigned p = global_sub_partition_id_to_local_id(global_subpart_id); + std::string mystring = + mask.to_string<char,std::string::traits_type,std::string::allocator_type>(); + MEMPART_DPRINTF("Copy Engine Request Received For Address=%zx, local_subpart=%u, global_subpart=%u, sector_mask=%s \n", addr, p, global_subpart_id, mystring.c_str()); + m_sub_partition[p]->force_l2_tag_update(addr,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle, mask); } -memory_partition_unit::~memory_partition_unit() { - delete m_dram; - for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; - p++) { - delete m_sub_partition[p]; - } - delete[] m_sub_partition; +memory_partition_unit::~memory_partition_unit() +{ + delete m_dram; + for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; p++) { + delete m_sub_partition[p]; + } + delete[] m_sub_partition; } -memory_partition_unit::arbitration_metadata::arbitration_metadata( - const memory_config *config) - : m_last_borrower(config->m_n_sub_partition_per_memory_channel - 1), - m_private_credit(config->m_n_sub_partition_per_memory_channel, 0), - m_shared_credit(0) { - // each sub partition get at least 1 credit for forward progress - // the rest is shared among with other partitions - m_private_credit_limit = 1; - m_shared_credit_limit = config->gpgpu_frfcfs_dram_sched_queue_size + - config->gpgpu_dram_return_queue_size - - (config->m_n_sub_partition_per_memory_channel - 1); - if (config->seperate_write_queue_enabled) - m_shared_credit_limit += config->gpgpu_frfcfs_dram_write_queue_size; - if (config->gpgpu_frfcfs_dram_sched_queue_size == 0 or - config->gpgpu_dram_return_queue_size == 0) { - m_shared_credit_limit = - 0; // no limit if either of the queue has no limit in size - } - assert(m_shared_credit_limit >= 0); +memory_partition_unit::arbitration_metadata::arbitration_metadata(const memory_config *config) +: m_last_borrower(config->m_n_sub_partition_per_memory_channel - 1), + m_private_credit(config->m_n_sub_partition_per_memory_channel, 0), + m_shared_credit(0) +{ + // each sub partition get at least 1 credit for forward progress + // the rest is shared among with other partitions + m_private_credit_limit = 1; + m_shared_credit_limit = config->gpgpu_frfcfs_dram_sched_queue_size + + config->gpgpu_dram_return_queue_size + - (config->m_n_sub_partition_per_memory_channel - 1); + if(config->seperate_write_queue_enabled ) + m_shared_credit_limit += config->gpgpu_frfcfs_dram_write_queue_size; + if (config->gpgpu_frfcfs_dram_sched_queue_size == 0 + or config->gpgpu_dram_return_queue_size == 0) + { + m_shared_credit_limit = 0; // no limit if either of the queue has no limit in size + } + assert(m_shared_credit_limit >= 0); } -bool memory_partition_unit::arbitration_metadata::has_credits( - int inner_sub_partition_id) const { - int spid = inner_sub_partition_id; - if (m_private_credit[spid] < m_private_credit_limit) { - return true; - } else if (m_shared_credit_limit == 0 || - m_shared_credit < m_shared_credit_limit) { - return true; - } else { - return false; - } +bool memory_partition_unit::arbitration_metadata::has_credits(int inner_sub_partition_id) const +{ + int spid = inner_sub_partition_id; + if (m_private_credit[spid] < m_private_credit_limit) { + return true; + } else if (m_shared_credit_limit == 0 || m_shared_credit < m_shared_credit_limit) { + return true; + } else { + return false; + } } -void memory_partition_unit::arbitration_metadata::borrow_credit( - int inner_sub_partition_id) { - int spid = inner_sub_partition_id; - if (m_private_credit[spid] < m_private_credit_limit) { - m_private_credit[spid] += 1; - } else if (m_shared_credit_limit == 0 || - m_shared_credit < m_shared_credit_limit) { - m_shared_credit += 1; - } else { - assert(0 && "DRAM arbitration error: Borrowing from depleted credit!"); - } - m_last_borrower = spid; +void memory_partition_unit::arbitration_metadata::borrow_credit(int inner_sub_partition_id) +{ + int spid = inner_sub_partition_id; + if (m_private_credit[spid] < m_private_credit_limit) { + m_private_credit[spid] += 1; + } else if (m_shared_credit_limit == 0 || m_shared_credit < m_shared_credit_limit) { + m_shared_credit += 1; + } else { + assert(0 && "DRAM arbitration error: Borrowing from depleted credit!"); + } + m_last_borrower = spid; } -void memory_partition_unit::arbitration_metadata::return_credit( - int inner_sub_partition_id) { - int spid = inner_sub_partition_id; - if (m_private_credit[spid] > 0) { - m_private_credit[spid] -= 1; - } else { - m_shared_credit -= 1; - } - assert((m_shared_credit >= 0) && - "DRAM arbitration error: Returning more than available credits!"); +void memory_partition_unit::arbitration_metadata::return_credit(int inner_sub_partition_id) +{ + int spid = inner_sub_partition_id; + if (m_private_credit[spid] > 0) { + m_private_credit[spid] -= 1; + } else { + m_shared_credit -= 1; + } + assert((m_shared_credit >= 0) && "DRAM arbitration error: Returning more than available credits!"); } -void memory_partition_unit::arbitration_metadata::print(FILE *fp) const { - fprintf(fp, "private_credit = "); - for (unsigned p = 0; p < m_private_credit.size(); p++) { - fprintf(fp, "%d ", m_private_credit[p]); - } - fprintf(fp, "(limit = %d)\n", m_private_credit_limit); - fprintf(fp, "shared_credit = %d (limit = %d)\n", m_shared_credit, - m_shared_credit_limit); +void memory_partition_unit::arbitration_metadata::print( FILE *fp ) const +{ + fprintf(fp, "private_credit = "); + for (unsigned p = 0; p < m_private_credit.size(); p++) { + fprintf(fp, "%d ", m_private_credit[p]); + } + fprintf(fp, "(limit = %d)\n", m_private_credit_limit); + fprintf(fp, "shared_credit = %d (limit = %d)\n", m_shared_credit, m_shared_credit_limit); } -bool memory_partition_unit::busy() const { - bool busy = false; - for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; - p++) { - if (m_sub_partition[p]->busy()) { - busy = true; +bool memory_partition_unit::busy() const +{ + bool busy = false; + for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; p++) { + if (m_sub_partition[p]->busy()) { + busy = true; + } } - } - return busy; + return busy; } -void memory_partition_unit::cache_cycle(unsigned cycle) { - for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; - p++) { - m_sub_partition[p]->cache_cycle(cycle); - } +void memory_partition_unit::cache_cycle(unsigned cycle) +{ + for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; p++) { + m_sub_partition[p]->cache_cycle(cycle); + } } -void memory_partition_unit::visualizer_print(gzFile visualizer_file) const { - m_dram->visualizer_print(visualizer_file); - for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; - p++) { - m_sub_partition[p]->visualizer_print(visualizer_file); - } +void memory_partition_unit::visualizer_print( gzFile visualizer_file ) const +{ + m_dram->visualizer_print(visualizer_file); + for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; p++) { + m_sub_partition[p]->visualizer_print(visualizer_file); + } } -// determine whether a given subpartition can issue to DRAM -bool memory_partition_unit::can_issue_to_dram(int inner_sub_partition_id) { - int spid = inner_sub_partition_id; - bool sub_partition_contention = m_sub_partition[spid]->dram_L2_queue_full(); - bool has_dram_resource = m_arbitration_metadata.has_credits(spid); +// determine whether a given subpartition can issue to DRAM +bool memory_partition_unit::can_issue_to_dram(int inner_sub_partition_id) +{ + int spid = inner_sub_partition_id; + bool sub_partition_contention = m_sub_partition[spid]->dram_L2_queue_full(); + bool has_dram_resource = m_arbitration_metadata.has_credits(spid); - MEMPART_DPRINTF( - "sub partition %d sub_partition_contention=%c has_dram_resource=%c\n", - spid, (sub_partition_contention) ? 'T' : 'F', - (has_dram_resource) ? 'T' : 'F'); + MEMPART_DPRINTF("sub partition %d sub_partition_contention=%c has_dram_resource=%c\n", + spid, (sub_partition_contention)? 'T':'F', (has_dram_resource)? 'T':'F'); - return (has_dram_resource && !sub_partition_contention); + return (has_dram_resource && !sub_partition_contention); } -int memory_partition_unit::global_sub_partition_id_to_local_id( - int global_sub_partition_id) const { - return (global_sub_partition_id - - m_id * m_config->m_n_sub_partition_per_memory_channel); +int memory_partition_unit::global_sub_partition_id_to_local_id(int global_sub_partition_id) const +{ + return (global_sub_partition_id - m_id * m_config->m_n_sub_partition_per_memory_channel); } -void memory_partition_unit::simple_dram_model_cycle() { - // pop completed memory request from dram and push it to dram-to-L2 queue - // of the original sub partition - if (!m_dram_latency_queue.empty() && - ((m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle) >= - m_dram_latency_queue.front().ready_cycle)) { - mem_fetch *mf_return = m_dram_latency_queue.front().req; - if (mf_return->get_access_type() != L1_WRBK_ACC && - mf_return->get_access_type() != L2_WRBK_ACC) { - mf_return->set_reply(); +void memory_partition_unit::simple_dram_model_cycle() +{ - unsigned dest_global_spid = mf_return->get_sub_partition_id(); - int dest_spid = global_sub_partition_id_to_local_id(dest_global_spid); - assert(m_sub_partition[dest_spid]->get_id() == dest_global_spid); - if (!m_sub_partition[dest_spid]->dram_L2_queue_full()) { - if (mf_return->get_access_type() == L1_WRBK_ACC) { - m_sub_partition[dest_spid]->set_done(mf_return); - delete mf_return; - } else { - m_sub_partition[dest_spid]->dram_L2_queue_push(mf_return); - mf_return->set_status( - IN_PARTITION_DRAM_TO_L2_QUEUE, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - m_arbitration_metadata.return_credit(dest_spid); - MEMPART_DPRINTF( - "mem_fetch request %p return from dram to sub partition %d\n", - mf_return, dest_spid); - } - m_dram_latency_queue.pop_front(); - } + // pop completed memory request from dram and push it to dram-to-L2 queue + // of the original sub partition + if (!m_dram_latency_queue.empty() && ( (m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle) >= m_dram_latency_queue.front().ready_cycle )) { + mem_fetch* mf_return = m_dram_latency_queue.front().req; + if( mf_return->get_access_type() != L1_WRBK_ACC && mf_return->get_access_type() != L2_WRBK_ACC ) { + mf_return->set_reply(); - } else { - this->set_done(mf_return); - delete mf_return; - m_dram_latency_queue.pop_front(); - } - } + unsigned dest_global_spid = mf_return->get_sub_partition_id(); + int dest_spid = global_sub_partition_id_to_local_id(dest_global_spid); + assert(m_sub_partition[dest_spid]->get_id() == dest_global_spid); + if (!m_sub_partition[dest_spid]->dram_L2_queue_full()) { + if( mf_return->get_access_type() == L1_WRBK_ACC ) { + m_sub_partition[dest_spid]->set_done(mf_return); + delete mf_return; + } else { + m_sub_partition[dest_spid]->dram_L2_queue_push(mf_return); + mf_return->set_status(IN_PARTITION_DRAM_TO_L2_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); + m_arbitration_metadata.return_credit(dest_spid); + MEMPART_DPRINTF("mem_fetch request %p return from dram to sub partition %d\n", mf_return, dest_spid); + } + m_dram_latency_queue.pop_front(); + } - // mem_fetch *mf = m_sub_partition[spid]->L2_dram_queue_top(); - // if( !m_dram->full(mf->is_write()) ) { - // L2->DRAM queue to DRAM latency queue - // Arbitrate among multiple L2 subpartitions - int last_issued_partition = m_arbitration_metadata.last_borrower(); - for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; - p++) { - int spid = (p + last_issued_partition + 1) % - m_config->m_n_sub_partition_per_memory_channel; - if (!m_sub_partition[spid]->L2_dram_queue_empty() && - can_issue_to_dram(spid)) { - mem_fetch *mf = m_sub_partition[spid]->L2_dram_queue_top(); - if (m_dram->full(mf->is_write())) break; + } else { + this->set_done(mf_return); + delete mf_return; + m_dram_latency_queue.pop_front(); + } + } + + // mem_fetch *mf = m_sub_partition[spid]->L2_dram_queue_top(); + //if( !m_dram->full(mf->is_write()) ) { + // L2->DRAM queue to DRAM latency queue + // Arbitrate among multiple L2 subpartitions + int last_issued_partition = m_arbitration_metadata.last_borrower(); + for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; p++) { + int spid = (p + last_issued_partition + 1) % m_config->m_n_sub_partition_per_memory_channel; + if (!m_sub_partition[spid]->L2_dram_queue_empty() && can_issue_to_dram(spid)) { + mem_fetch *mf = m_sub_partition[spid]->L2_dram_queue_top(); + if(m_dram->full(mf->is_write()) ) + break; + + m_sub_partition[spid]->L2_dram_queue_pop(); + MEMPART_DPRINTF("Issue mem_fetch request %p from sub partition %d to dram\n", mf, spid); + dram_delay_t d; + d.req = mf; + d.ready_cycle = m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle + m_config->dram_latency; + m_dram_latency_queue.push_back(d); + mf->set_status(IN_PARTITION_DRAM_LATENCY_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); + m_arbitration_metadata.borrow_credit(spid); + break; // the DRAM should only accept one request per cycle + } + } + //} - m_sub_partition[spid]->L2_dram_queue_pop(); - MEMPART_DPRINTF( - "Issue mem_fetch request %p from sub partition %d to dram\n", mf, - spid); - dram_delay_t d; - d.req = mf; - d.ready_cycle = m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle + - m_config->dram_latency; - m_dram_latency_queue.push_back(d); - mf->set_status(IN_PARTITION_DRAM_LATENCY_QUEUE, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - m_arbitration_metadata.borrow_credit(spid); - break; // the DRAM should only accept one request per cycle - } - } - //} } -void memory_partition_unit::dram_cycle() { - // pop completed memory request from dram and push it to dram-to-L2 queue - // of the original sub partition - mem_fetch *mf_return = m_dram->return_queue_top(); - if (mf_return) { - unsigned dest_global_spid = mf_return->get_sub_partition_id(); - int dest_spid = global_sub_partition_id_to_local_id(dest_global_spid); - assert(m_sub_partition[dest_spid]->get_id() == dest_global_spid); - if (!m_sub_partition[dest_spid]->dram_L2_queue_full()) { - if (mf_return->get_access_type() == L1_WRBK_ACC) { - m_sub_partition[dest_spid]->set_done(mf_return); - delete mf_return; - } else { - m_sub_partition[dest_spid]->dram_L2_queue_push(mf_return); - mf_return->set_status(IN_PARTITION_DRAM_TO_L2_QUEUE, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - m_arbitration_metadata.return_credit(dest_spid); - MEMPART_DPRINTF( - "mem_fetch request %p return from dram to sub partition %d\n", - mf_return, dest_spid); - } - m_dram->return_queue_pop(); +void memory_partition_unit::dram_cycle() +{ + // pop completed memory request from dram and push it to dram-to-L2 queue + // of the original sub partition + mem_fetch* mf_return = m_dram->return_queue_top(); + if (mf_return) { + unsigned dest_global_spid = mf_return->get_sub_partition_id(); + int dest_spid = global_sub_partition_id_to_local_id(dest_global_spid); + assert(m_sub_partition[dest_spid]->get_id() == dest_global_spid); + if (!m_sub_partition[dest_spid]->dram_L2_queue_full()) { + if( mf_return->get_access_type() == L1_WRBK_ACC ) { + m_sub_partition[dest_spid]->set_done(mf_return); + delete mf_return; + } else { + m_sub_partition[dest_spid]->dram_L2_queue_push(mf_return); + mf_return->set_status(IN_PARTITION_DRAM_TO_L2_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); + m_arbitration_metadata.return_credit(dest_spid); + MEMPART_DPRINTF("mem_fetch request %p return from dram to sub partition %d\n", mf_return, dest_spid); + } + m_dram->return_queue_pop(); + } + } else { + m_dram->return_queue_pop(); } - } else { - m_dram->return_queue_pop(); - } + + m_dram->cycle(); + m_dram->dram_log(SAMPLELOG); - m_dram->cycle(); - m_dram->dram_log(SAMPLELOG); + // mem_fetch *mf = m_sub_partition[spid]->L2_dram_queue_top(); + //if( !m_dram->full(mf->is_write()) ) { + // L2->DRAM queue to DRAM latency queue + // Arbitrate among multiple L2 subpartitions + int last_issued_partition = m_arbitration_metadata.last_borrower(); + for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; p++) { + int spid = (p + last_issued_partition + 1) % m_config->m_n_sub_partition_per_memory_channel; + if (!m_sub_partition[spid]->L2_dram_queue_empty() && can_issue_to_dram(spid)) { + mem_fetch *mf = m_sub_partition[spid]->L2_dram_queue_top(); + if(m_dram->full(mf->is_write()) ) + break; - // mem_fetch *mf = m_sub_partition[spid]->L2_dram_queue_top(); - // if( !m_dram->full(mf->is_write()) ) { - // L2->DRAM queue to DRAM latency queue - // Arbitrate among multiple L2 subpartitions - int last_issued_partition = m_arbitration_metadata.last_borrower(); - for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; - p++) { - int spid = (p + last_issued_partition + 1) % - m_config->m_n_sub_partition_per_memory_channel; - if (!m_sub_partition[spid]->L2_dram_queue_empty() && - can_issue_to_dram(spid)) { - mem_fetch *mf = m_sub_partition[spid]->L2_dram_queue_top(); - if (m_dram->full(mf->is_write())) break; + m_sub_partition[spid]->L2_dram_queue_pop(); + MEMPART_DPRINTF("Issue mem_fetch request %p from sub partition %d to dram\n", mf, spid); + dram_delay_t d; + d.req = mf; + d.ready_cycle = m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle + m_config->dram_latency; + m_dram_latency_queue.push_back(d); + mf->set_status(IN_PARTITION_DRAM_LATENCY_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); + m_arbitration_metadata.borrow_credit(spid); + break; // the DRAM should only accept one request per cycle + } + } + //} - m_sub_partition[spid]->L2_dram_queue_pop(); - MEMPART_DPRINTF( - "Issue mem_fetch request %p from sub partition %d to dram\n", mf, - spid); - dram_delay_t d; - d.req = mf; - d.ready_cycle = m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle + - m_config->dram_latency; - m_dram_latency_queue.push_back(d); - mf->set_status(IN_PARTITION_DRAM_LATENCY_QUEUE, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - m_arbitration_metadata.borrow_credit(spid); - break; // the DRAM should only accept one request per cycle + // DRAM latency queue + if( !m_dram_latency_queue.empty() && ( (m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle) >= m_dram_latency_queue.front().ready_cycle ) && !m_dram->full(m_dram_latency_queue.front().req->is_write()) ) { + mem_fetch* mf = m_dram_latency_queue.front().req; + m_dram_latency_queue.pop_front(); + m_dram->push(mf); } - } - //} - - // DRAM latency queue - if (!m_dram_latency_queue.empty() && - ((m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle) >= - m_dram_latency_queue.front().ready_cycle) && - !m_dram->full(m_dram_latency_queue.front().req->is_write())) { - mem_fetch *mf = m_dram_latency_queue.front().req; - m_dram_latency_queue.pop_front(); - m_dram->push(mf); - } } -void memory_partition_unit::set_done(mem_fetch *mf) { - unsigned global_spid = mf->get_sub_partition_id(); - int spid = global_sub_partition_id_to_local_id(global_spid); - assert(m_sub_partition[spid]->get_id() == global_spid); - if (mf->get_access_type() == L1_WRBK_ACC || - mf->get_access_type() == L2_WRBK_ACC) { - m_arbitration_metadata.return_credit(spid); - MEMPART_DPRINTF( - "mem_fetch request %p return from dram to sub partition %d\n", mf, - spid); - } - m_sub_partition[spid]->set_done(mf); +void memory_partition_unit::set_done( mem_fetch *mf ) +{ + unsigned global_spid = mf->get_sub_partition_id(); + int spid = global_sub_partition_id_to_local_id(global_spid); + assert(m_sub_partition[spid]->get_id() == global_spid); + if (mf->get_access_type() == L1_WRBK_ACC || mf->get_access_type() == L2_WRBK_ACC) { + m_arbitration_metadata.return_credit(spid); + MEMPART_DPRINTF("mem_fetch request %p return from dram to sub partition %d\n", mf, spid); + } + m_sub_partition[spid]->set_done(mf); } -void memory_partition_unit::set_dram_power_stats( - unsigned &n_cmd, unsigned &n_activity, unsigned &n_nop, unsigned &n_act, - unsigned &n_pre, unsigned &n_rd, unsigned &n_wr, unsigned &n_req) const { - m_dram->set_dram_power_stats(n_cmd, n_activity, n_nop, n_act, n_pre, n_rd, - n_wr, n_req); +void memory_partition_unit::set_dram_power_stats(unsigned &n_cmd, + unsigned &n_activity, + unsigned &n_nop, + unsigned &n_act, + unsigned &n_pre, + unsigned &n_rd, + unsigned &n_wr, + unsigned &n_req) const +{ + m_dram->set_dram_power_stats(n_cmd, n_activity, n_nop, n_act, n_pre, n_rd, n_wr, n_req); } -void memory_partition_unit::print(FILE *fp) const { - fprintf(fp, "Memory Partition %u: \n", m_id); - for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; - p++) { - m_sub_partition[p]->print(fp); - } - fprintf(fp, "In Dram Latency Queue (total = %zd): \n", - m_dram_latency_queue.size()); - for (std::list<dram_delay_t>::const_iterator mf_dlq = - m_dram_latency_queue.begin(); - mf_dlq != m_dram_latency_queue.end(); ++mf_dlq) { - mem_fetch *mf = mf_dlq->req; - fprintf(fp, "Ready @ %llu - ", mf_dlq->ready_cycle); - if (mf) - mf->print(fp); - else - fprintf(fp, " <NULL mem_fetch?>\n"); - } - m_dram->print(fp); +void memory_partition_unit::print( FILE *fp ) const +{ + fprintf(fp, "Memory Partition %u: \n", m_id); + for (unsigned p = 0; p < m_config->m_n_sub_partition_per_memory_channel; p++) { + m_sub_partition[p]->print(fp); + } + fprintf(fp, "In Dram Latency Queue (total = %zd): \n", m_dram_latency_queue.size()); + for (std::list<dram_delay_t>::const_iterator mf_dlq = m_dram_latency_queue.begin(); + mf_dlq != m_dram_latency_queue.end(); ++mf_dlq) { + mem_fetch *mf = mf_dlq->req; + fprintf(fp, "Ready @ %llu - ", mf_dlq->ready_cycle); + if (mf) + mf->print(fp); + else + fprintf(fp, " <NULL mem_fetch?>\n"); + } + m_dram->print(fp); } -memory_sub_partition::memory_sub_partition(unsigned sub_partition_id, - const memory_config *config, - class memory_stats_t *stats, - class gpgpu_sim *gpu) { - m_id = sub_partition_id; - m_config = config; - m_stats = stats; - m_gpu = gpu; - m_memcpy_cycle_offset = 0; +memory_sub_partition::memory_sub_partition( unsigned sub_partition_id, + const memory_config *config, + class memory_stats_t *stats, + class gpgpu_sim* gpu) +{ + m_id = sub_partition_id; + m_config=config; + m_stats=stats; + m_gpu = gpu; + m_memcpy_cycle_offset = 0; - assert(m_id < m_config->m_n_mem_sub_partition); + assert(m_id < m_config->m_n_mem_sub_partition); - char L2c_name[32]; - snprintf(L2c_name, 32, "L2_bank_%03d", m_id); - m_L2interface = new L2interface(this); - m_mf_allocator = new partition_mf_allocator(config); + char L2c_name[32]; + snprintf(L2c_name, 32, "L2_bank_%03d", m_id); + m_L2interface = new L2interface(this); + m_mf_allocator = new partition_mf_allocator(config); - if (!m_config->m_L2_config.disabled()) - m_L2cache = - new l2_cache(L2c_name, m_config->m_L2_config, -1, -1, m_L2interface, - m_mf_allocator, IN_PARTITION_L2_MISS_QUEUE, gpu); + if(!m_config->m_L2_config.disabled()) + m_L2cache = new l2_cache(L2c_name,m_config->m_L2_config,-1,-1,m_L2interface,m_mf_allocator,IN_PARTITION_L2_MISS_QUEUE, gpu); - unsigned int icnt_L2; - unsigned int L2_dram; - unsigned int dram_L2; - unsigned int L2_icnt; - sscanf(m_config->gpgpu_L2_queue_config, "%u:%u:%u:%u", &icnt_L2, &L2_dram, - &dram_L2, &L2_icnt); - m_icnt_L2_queue = new fifo_pipeline<mem_fetch>("icnt-to-L2", 0, icnt_L2); - m_L2_dram_queue = new fifo_pipeline<mem_fetch>("L2-to-dram", 0, L2_dram); - m_dram_L2_queue = new fifo_pipeline<mem_fetch>("dram-to-L2", 0, dram_L2); - m_L2_icnt_queue = new fifo_pipeline<mem_fetch>("L2-to-icnt", 0, L2_icnt); - wb_addr = -1; + unsigned int icnt_L2; + unsigned int L2_dram; + unsigned int dram_L2; + unsigned int L2_icnt; + sscanf(m_config->gpgpu_L2_queue_config,"%u:%u:%u:%u", &icnt_L2,&L2_dram,&dram_L2,&L2_icnt ); + m_icnt_L2_queue = new fifo_pipeline<mem_fetch>("icnt-to-L2",0,icnt_L2); + m_L2_dram_queue = new fifo_pipeline<mem_fetch>("L2-to-dram",0,L2_dram); + m_dram_L2_queue = new fifo_pipeline<mem_fetch>("dram-to-L2",0,dram_L2); + m_L2_icnt_queue = new fifo_pipeline<mem_fetch>("L2-to-icnt",0,L2_icnt); + wb_addr=-1; } -memory_sub_partition::~memory_sub_partition() { - delete m_icnt_L2_queue; - delete m_L2_dram_queue; - delete m_dram_L2_queue; - delete m_L2_icnt_queue; - delete m_L2cache; - delete m_L2interface; +memory_sub_partition::~memory_sub_partition() +{ + delete m_icnt_L2_queue; + delete m_L2_dram_queue; + delete m_dram_L2_queue; + delete m_L2_icnt_queue; + delete m_L2cache; + delete m_L2interface; } -void memory_sub_partition::cache_cycle(unsigned cycle) { - // L2 fill responses - if (!m_config->m_L2_config.disabled()) { - if (m_L2cache->access_ready() && !m_L2_icnt_queue->full()) { - mem_fetch *mf = m_L2cache->next_access(); - if (mf->get_access_type() != - L2_WR_ALLOC_R) { // Don't pass write allocate read request back to - // upper level cache - mf->set_reply(); - mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - m_L2_icnt_queue->push(mf); - } else { - if (m_config->m_L2_config.m_write_alloc_policy == FETCH_ON_WRITE) { - mem_fetch *original_wr_mf = mf->get_original_wr_mf(); - assert(original_wr_mf); - original_wr_mf->set_reply(); - original_wr_mf->set_status( - IN_PARTITION_L2_TO_ICNT_QUEUE, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - m_L2_icnt_queue->push(original_wr_mf); - } - m_request_tracker.erase(mf); - delete mf; - } +void memory_sub_partition::cache_cycle( unsigned cycle ) +{ + // L2 fill responses + if( !m_config->m_L2_config.disabled()) { + if ( m_L2cache->access_ready() && !m_L2_icnt_queue->full() ) { + mem_fetch *mf = m_L2cache->next_access(); + if(mf->get_access_type() != L2_WR_ALLOC_R){ // Don't pass write allocate read request back to upper level cache + mf->set_reply(); + mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); + m_L2_icnt_queue->push(mf); + }else{ + if(m_config->m_L2_config.m_write_alloc_policy == FETCH_ON_WRITE) + { + mem_fetch* original_wr_mf = mf->get_original_wr_mf(); + assert(original_wr_mf); + original_wr_mf->set_reply(); + original_wr_mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); + m_L2_icnt_queue->push(original_wr_mf); + } + m_request_tracker.erase(mf); + delete mf; + } + } } - } - // DRAM to L2 (texture) and icnt (not texture) - if (!m_dram_L2_queue->empty()) { - mem_fetch *mf = m_dram_L2_queue->top(); - if (!m_config->m_L2_config.disabled() && m_L2cache->waiting_for_fill(mf)) { - if (m_L2cache->fill_port_free()) { - mf->set_status(IN_PARTITION_L2_FILL_QUEUE, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - m_L2cache->fill(mf, m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle + - m_memcpy_cycle_offset); - m_dram_L2_queue->pop(); - } - } else if (!m_L2_icnt_queue->full()) { - if (mf->is_write() && mf->get_type() == WRITE_ACK) - mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - m_L2_icnt_queue->push(mf); - m_dram_L2_queue->pop(); + // DRAM to L2 (texture) and icnt (not texture) + if ( !m_dram_L2_queue->empty() ) { + mem_fetch *mf = m_dram_L2_queue->top(); + if ( !m_config->m_L2_config.disabled() && m_L2cache->waiting_for_fill(mf) ) { + if (m_L2cache->fill_port_free()) { + mf->set_status(IN_PARTITION_L2_FILL_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); + m_L2cache->fill(mf,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle+m_memcpy_cycle_offset); + m_dram_L2_queue->pop(); + } + } else if ( !m_L2_icnt_queue->full() ) { + if(mf->is_write() && mf->get_type() == WRITE_ACK) + mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); + m_L2_icnt_queue->push(mf); + m_dram_L2_queue->pop(); + } } - } - // prior L2 misses inserted into m_L2_dram_queue here - if (!m_config->m_L2_config.disabled()) m_L2cache->cycle(); + // prior L2 misses inserted into m_L2_dram_queue here + if( !m_config->m_L2_config.disabled() ) + m_L2cache->cycle(); - // new L2 texture accesses and/or non-texture accesses - if (!m_L2_dram_queue->full() && !m_icnt_L2_queue->empty()) { - mem_fetch *mf = m_icnt_L2_queue->top(); - if (!m_config->m_L2_config.disabled() && - ((m_config->m_L2_texure_only && mf->istexture()) || - (!m_config->m_L2_texure_only))) { - // L2 is enabled and access is for L2 - bool output_full = m_L2_icnt_queue->full(); - bool port_free = m_L2cache->data_port_free(); - if (!output_full && port_free) { - std::list<cache_event> events; - enum cache_request_status status = - m_L2cache->access(mf->get_addr(), mf, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle + - m_memcpy_cycle_offset, - events); - bool write_sent = was_write_sent(events); - bool read_sent = was_read_sent(events); - MEM_SUBPART_DPRINTF("Probing L2 cache Address=%llx, status=%u\n", - mf->get_addr(), status); + // new L2 texture accesses and/or non-texture accesses + if ( !m_L2_dram_queue->full() && !m_icnt_L2_queue->empty() ) { + mem_fetch *mf = m_icnt_L2_queue->top(); + if ( !m_config->m_L2_config.disabled() && + ( (m_config->m_L2_texure_only && mf->istexture()) || (!m_config->m_L2_texure_only) ) + ) { + // L2 is enabled and access is for L2 + bool output_full = m_L2_icnt_queue->full(); + bool port_free = m_L2cache->data_port_free(); + if ( !output_full && port_free ) { + std::list<cache_event> events; + enum cache_request_status status = m_L2cache->access(mf->get_addr(),mf,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle+m_memcpy_cycle_offset,events); + bool write_sent = was_write_sent(events); + bool read_sent = was_read_sent(events); + MEM_SUBPART_DPRINTF("Probing L2 cache Address=%llx, status=%u\n", mf->get_addr(), status); - if (status == HIT) { - if (!write_sent) { - // L2 cache replies - assert(!read_sent); - if (mf->get_access_type() == L1_WRBK_ACC) { - m_request_tracker.erase(mf); - delete mf; - } else { - mf->set_reply(); - mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - m_L2_icnt_queue->push(mf); + if ( status == HIT ) { + if( !write_sent ) { + // L2 cache replies + assert(!read_sent); + if( mf->get_access_type() == L1_WRBK_ACC ) { + m_request_tracker.erase(mf); + delete mf; + } else { + mf->set_reply(); + mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); + m_L2_icnt_queue->push(mf); + } + m_icnt_L2_queue->pop(); + } else { + assert(write_sent); + m_icnt_L2_queue->pop(); + } + } else if ( status != RESERVATION_FAIL ) { + if(mf->is_write() && (m_config->m_L2_config.m_write_alloc_policy == FETCH_ON_WRITE || m_config->m_L2_config.m_write_alloc_policy == LAZY_FETCH_ON_READ) && !was_writeallocate_sent(events)) { + mf->set_reply(); + mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); + m_L2_icnt_queue->push(mf); + } + // L2 cache accepted request + m_icnt_L2_queue->pop(); + } else { + assert(!write_sent); + assert(!read_sent); + // L2 cache lock-up: will try again next cycle + } } - m_icnt_L2_queue->pop(); - } else { - assert(write_sent); - m_icnt_L2_queue->pop(); - } - } else if (status != RESERVATION_FAIL) { - if (mf->is_write() && - (m_config->m_L2_config.m_write_alloc_policy == FETCH_ON_WRITE || - m_config->m_L2_config.m_write_alloc_policy == - LAZY_FETCH_ON_READ) && - !was_writeallocate_sent(events)) { - mf->set_reply(); - mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - m_L2_icnt_queue->push(mf); - } - // L2 cache accepted request - m_icnt_L2_queue->pop(); } else { - assert(!write_sent); - assert(!read_sent); - // L2 cache lock-up: will try again next cycle + // L2 is disabled or non-texture access to texture-only L2 + mf->set_status(IN_PARTITION_L2_TO_DRAM_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); + m_L2_dram_queue->push(mf); + m_icnt_L2_queue->pop(); } - } - } else { - // L2 is disabled or non-texture access to texture-only L2 - mf->set_status(IN_PARTITION_L2_TO_DRAM_QUEUE, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - m_L2_dram_queue->push(mf); - m_icnt_L2_queue->pop(); } - } - // ROP delay queue - if (!m_rop.empty() && (cycle >= m_rop.front().ready_cycle) && - !m_icnt_L2_queue->full()) { - mem_fetch *mf = m_rop.front().req; - m_rop.pop(); - m_icnt_L2_queue->push(mf); - mf->set_status(IN_PARTITION_ICNT_TO_L2_QUEUE, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - } + // ROP delay queue + if( !m_rop.empty() && (cycle >= m_rop.front().ready_cycle) && !m_icnt_L2_queue->full() ) { + mem_fetch* mf = m_rop.front().req; + m_rop.pop(); + m_icnt_L2_queue->push(mf); + mf->set_status(IN_PARTITION_ICNT_TO_L2_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); + } } -bool memory_sub_partition::full() const { return m_icnt_L2_queue->full(); } +bool memory_sub_partition::full() const +{ + return m_icnt_L2_queue->full(); +} -bool memory_sub_partition::full(unsigned size) const { - return m_icnt_L2_queue->is_avilable_size(size); +bool memory_sub_partition::full(unsigned size) const +{ + return m_icnt_L2_queue->is_avilable_size(size); } -bool memory_sub_partition::L2_dram_queue_empty() const { - return m_L2_dram_queue->empty(); +bool memory_sub_partition::L2_dram_queue_empty() const +{ + return m_L2_dram_queue->empty(); } -class mem_fetch *memory_sub_partition::L2_dram_queue_top() const { - return m_L2_dram_queue->top(); +class mem_fetch* memory_sub_partition::L2_dram_queue_top() const +{ + return m_L2_dram_queue->top(); } -void memory_sub_partition::L2_dram_queue_pop() { m_L2_dram_queue->pop(); } +void memory_sub_partition::L2_dram_queue_pop() +{ + m_L2_dram_queue->pop(); +} -bool memory_sub_partition::dram_L2_queue_full() const { - return m_dram_L2_queue->full(); +bool memory_sub_partition::dram_L2_queue_full() const +{ + return m_dram_L2_queue->full(); } -void memory_sub_partition::dram_L2_queue_push(class mem_fetch *mf) { - m_dram_L2_queue->push(mf); +void memory_sub_partition::dram_L2_queue_push( class mem_fetch* mf ) +{ + m_dram_L2_queue->push(mf); } -void memory_sub_partition::print_cache_stat(unsigned &accesses, - unsigned &misses) const { - FILE *fp = stdout; - if (!m_config->m_L2_config.disabled()) m_L2cache->print(fp, accesses, misses); +void memory_sub_partition::print_cache_stat(unsigned &accesses, unsigned &misses) const +{ + FILE *fp = stdout; + if( !m_config->m_L2_config.disabled() ) + m_L2cache->print(fp,accesses,misses); } -void memory_sub_partition::print(FILE *fp) const { - if (!m_request_tracker.empty()) { - fprintf(fp, "Memory Sub Parition %u: pending memory requests:\n", m_id); - for (std::set<mem_fetch *>::const_iterator r = m_request_tracker.begin(); - r != m_request_tracker.end(); ++r) { - mem_fetch *mf = *r; - if (mf) - mf->print(fp); - else - fprintf(fp, " <NULL mem_fetch?>\n"); +void memory_sub_partition::print( FILE *fp ) const +{ + if ( !m_request_tracker.empty() ) { + fprintf(fp,"Memory Sub Parition %u: pending memory requests:\n", m_id); + for ( std::set<mem_fetch*>::const_iterator r=m_request_tracker.begin(); r != m_request_tracker.end(); ++r ) { + mem_fetch *mf = *r; + if ( mf ) + mf->print(fp); + else + fprintf(fp," <NULL mem_fetch?>\n"); + } } - } - if (!m_config->m_L2_config.disabled()) m_L2cache->display_state(fp); + if( !m_config->m_L2_config.disabled() ) + m_L2cache->display_state(fp); } -void memory_stats_t::visualizer_print(gzFile visualizer_file) { - gzprintf(visualizer_file, "Ltwowritemiss: %d\n", L2_write_miss); - gzprintf(visualizer_file, "Ltwowritehit: %d\n", L2_write_hit); - gzprintf(visualizer_file, "Ltworeadmiss: %d\n", L2_read_miss); - gzprintf(visualizer_file, "Ltworeadhit: %d\n", L2_read_hit); - clear_L2_stats_pw(); +void memory_stats_t::visualizer_print( gzFile visualizer_file ) +{ + gzprintf(visualizer_file, "Ltwowritemiss: %d\n", L2_write_miss); + gzprintf(visualizer_file, "Ltwowritehit: %d\n", L2_write_hit); + gzprintf(visualizer_file, "Ltworeadmiss: %d\n", L2_read_miss); + gzprintf(visualizer_file, "Ltworeadhit: %d\n", L2_read_hit); + clear_L2_stats_pw(); - if (num_mfs) - gzprintf(visualizer_file, "averagemflatency: %lld\n", - mf_total_lat / num_mfs); + if (num_mfs) + gzprintf(visualizer_file, "averagemflatency: %lld\n", mf_total_lat/num_mfs); } -void memory_stats_t::clear_L2_stats_pw() { - L2_write_miss = 0; - L2_write_hit = 0; - L2_read_miss = 0; - L2_read_hit = 0; +void memory_stats_t::clear_L2_stats_pw(){ + L2_write_miss = 0; + L2_write_hit = 0; + L2_read_miss = 0; + L2_read_hit = 0; } -void gpgpu_sim::print_dram_stats(FILE *fout) const { - unsigned cmd = 0; - unsigned activity = 0; - unsigned nop = 0; - unsigned act = 0; - unsigned pre = 0; - unsigned rd = 0; - unsigned wr = 0; - unsigned req = 0; - unsigned tot_cmd = 0; - unsigned tot_nop = 0; - unsigned tot_act = 0; - unsigned tot_pre = 0; - unsigned tot_rd = 0; - unsigned tot_wr = 0; - unsigned tot_req = 0; +void gpgpu_sim::print_dram_stats(FILE *fout) const +{ + unsigned cmd=0; + unsigned activity=0; + unsigned nop=0; + unsigned act=0; + unsigned pre=0; + unsigned rd=0; + unsigned wr=0; + unsigned req=0; + unsigned tot_cmd=0; + unsigned tot_nop=0; + unsigned tot_act=0; + unsigned tot_pre=0; + unsigned tot_rd=0; + unsigned tot_wr=0; + unsigned tot_req=0; - for (unsigned i = 0; i < m_memory_config->m_n_mem; i++) { - m_memory_partition_unit[i]->set_dram_power_stats(cmd, activity, nop, act, - pre, rd, wr, req); - tot_cmd += cmd; - tot_nop += nop; - tot_act += act; - tot_pre += pre; - tot_rd += rd; - tot_wr += wr; - tot_req += req; - } - fprintf(fout, "gpgpu_n_dram_reads = %d\n", tot_rd); - fprintf(fout, "gpgpu_n_dram_writes = %d\n", tot_wr); - fprintf(fout, "gpgpu_n_dram_activate = %d\n", tot_act); - fprintf(fout, "gpgpu_n_dram_commands = %d\n", tot_cmd); - fprintf(fout, "gpgpu_n_dram_noops = %d\n", tot_nop); - fprintf(fout, "gpgpu_n_dram_precharges = %d\n", tot_pre); - fprintf(fout, "gpgpu_n_dram_requests = %d\n", tot_req); + for (unsigned i=0;i<m_memory_config->m_n_mem;i++){ + m_memory_partition_unit[i]->set_dram_power_stats(cmd,activity,nop,act,pre,rd,wr,req); + tot_cmd+=cmd; + tot_nop+=nop; + tot_act+=act; + tot_pre+=pre; + tot_rd+=rd; + tot_wr+=wr; + tot_req+=req; + } + fprintf(fout,"gpgpu_n_dram_reads = %d\n",tot_rd ); + fprintf(fout,"gpgpu_n_dram_writes = %d\n",tot_wr ); + fprintf(fout,"gpgpu_n_dram_activate = %d\n",tot_act ); + fprintf(fout,"gpgpu_n_dram_commands = %d\n",tot_cmd); + fprintf(fout,"gpgpu_n_dram_noops = %d\n",tot_nop ); + fprintf(fout,"gpgpu_n_dram_precharges = %d\n",tot_pre ); + fprintf(fout,"gpgpu_n_dram_requests = %d\n",tot_req ); +} + +unsigned memory_sub_partition::flushL2() +{ + if (!m_config->m_L2_config.disabled()) { + m_L2cache->flush(); + } + return 0; //TODO: write the flushed data to the main memory } -unsigned memory_sub_partition::flushL2() { - if (!m_config->m_L2_config.disabled()) { - m_L2cache->flush(); - } - return 0; // TODO: write the flushed data to the main memory +unsigned memory_sub_partition::invalidateL2() +{ + if (!m_config->m_L2_config.disabled()) { + m_L2cache->invalidate(); + } + return 0; } -unsigned memory_sub_partition::invalidateL2() { - if (!m_config->m_L2_config.disabled()) { - m_L2cache->invalidate(); - } - return 0; +bool memory_sub_partition::busy() const +{ + return !m_request_tracker.empty(); } -bool memory_sub_partition::busy() const { return !m_request_tracker.empty(); } +std::vector<mem_fetch*> memory_sub_partition::breakdown_request_to_sector_requests(mem_fetch* mf) +{ + std::vector<mem_fetch*> result; -std::vector<mem_fetch *> -memory_sub_partition::breakdown_request_to_sector_requests(mem_fetch *mf) { - std::vector<mem_fetch *> result; + if(mf->get_data_size() == SECTOR_SIZE && mf->get_access_sector_mask().count() == 1) { + result.push_back(mf); + } else if (mf->get_data_size() == 128 || mf->get_data_size() == 64) { + //We only accept 32, 64 and 128 bytes reqs + unsigned start=0, end=0; + if(mf->get_data_size() == 128) { + start=0; end=3; + } else if (mf->get_data_size() == 64 && mf->get_access_sector_mask().to_string() == "1100") { + start=2; end=3; + } else if (mf->get_data_size() == 64 && mf->get_access_sector_mask().to_string() == "0011") { + start=0; end=1; + } else if (mf->get_data_size() == 64 && (mf->get_access_sector_mask().to_string() == "1111" || mf->get_access_sector_mask().to_string() == "0000")) { + if(mf->get_addr() % 128 == 0) { + start=0; end=1; + } else { + start=2; end=3; + } + } else + { + printf("Invalid sector received, address = 0x%06llx, sector mask = %s, data size = %d", + mf->get_addr(), mf->get_access_sector_mask(), mf->get_data_size()); + assert(0 && "Undefined sector mask is received"); + } - if (mf->get_data_size() == SECTOR_SIZE && - mf->get_access_sector_mask().count() == 1) { - result.push_back(mf); - } else if (mf->get_data_size() == 128 || mf->get_data_size() == 64) { - // We only accept 32, 64 and 128 bytes reqs - unsigned start = 0, end = 0; - if (mf->get_data_size() == 128) { - start = 0; - end = 3; - } else if (mf->get_data_size() == 64 && - mf->get_access_sector_mask().to_string() == "1100") { - start = 2; - end = 3; - } else if (mf->get_data_size() == 64 && - mf->get_access_sector_mask().to_string() == "0011") { - start = 0; - end = 1; - } else if (mf->get_data_size() == 64 && - (mf->get_access_sector_mask().to_string() == "1111" || - mf->get_access_sector_mask().to_string() == "0000")) { - if (mf->get_addr() % 128 == 0) { - start = 0; - end = 1; - } else { - start = 2; - end = 3; - } - } else { - printf( - "Invalid sector received, address = 0x%06llx, sector mask = %s, data " - "size = %d", - mf->get_addr(), mf->get_access_sector_mask(), mf->get_data_size()); - assert(0 && "Undefined sector mask is received"); - } + std::bitset<SECTOR_SIZE*SECTOR_CHUNCK_SIZE> byte_sector_mask; + byte_sector_mask.reset(); + for(unsigned k=start*SECTOR_SIZE; k< SECTOR_SIZE; ++k) + byte_sector_mask.set(k); - std::bitset<SECTOR_SIZE * SECTOR_CHUNCK_SIZE> byte_sector_mask; - byte_sector_mask.reset(); - for (unsigned k = start * SECTOR_SIZE; k < SECTOR_SIZE; ++k) - byte_sector_mask.set(k); + for(unsigned j=start, i=0; j<= end ; ++j, ++i){ - for (unsigned j = start, i = 0; j <= end; ++j, ++i) { - const mem_access_t *ma = new mem_access_t( - mf->get_access_type(), mf->get_addr() + SECTOR_SIZE * i, SECTOR_SIZE, - mf->is_write(), mf->get_access_warp_mask(), - mf->get_access_byte_mask() & byte_sector_mask, - std::bitset<SECTOR_CHUNCK_SIZE>().set(j), m_gpu->gpgpu_ctx); + const mem_access_t *ma = new mem_access_t( mf->get_access_type(), + mf->get_addr() + SECTOR_SIZE*i, + SECTOR_SIZE, + mf->is_write(), + mf->get_access_warp_mask(), + mf->get_access_byte_mask() & byte_sector_mask, + std::bitset<SECTOR_CHUNCK_SIZE>().set(j), + m_gpu->gpgpu_ctx); - mem_fetch *n_mf = - new mem_fetch(*ma, NULL, mf->get_ctrl_size(), mf->get_wid(), - mf->get_sid(), mf->get_tpc(), mf->get_mem_config(), - m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle, mf); + mem_fetch *n_mf = new mem_fetch( *ma, + NULL, + mf->get_ctrl_size(), + mf->get_wid(), + mf->get_sid(), + mf->get_tpc(), + mf->get_mem_config(), + m_gpu->gpu_tot_sim_cycle+m_gpu->gpu_sim_cycle, + mf); - result.push_back(n_mf); - byte_sector_mask <<= SECTOR_SIZE; - } - } else { - printf( - "Invalid sector received, address = 0x%06llx, sector mask = %d, byte " - "mask = , data size = %u", - mf->get_addr(), mf->get_access_sector_mask().count(), - mf->get_data_size()); - assert(0 && "Undefined data size is received"); - } + result.push_back(n_mf); + byte_sector_mask <<= SECTOR_SIZE; + } + } else { + printf("Invalid sector received, address = 0x%06llx, sector mask = %d, byte mask = , data size = %u", + mf->get_addr(), mf->get_access_sector_mask().count(), mf->get_data_size()); + assert(0 && "Undefined data size is received"); + } - return result; + return result; } -void memory_sub_partition::push(mem_fetch *m_req, unsigned long long cycle) { - if (m_req) { - m_stats->memlatstat_icnt2mem_pop(m_req); - std::vector<mem_fetch *> reqs; - if (m_config->m_L2_config.m_cache_type == SECTOR) - reqs = breakdown_request_to_sector_requests(m_req); - else - reqs.push_back(m_req); +void memory_sub_partition::push( mem_fetch* m_req, unsigned long long cycle ) +{ + if (m_req) { + m_stats->memlatstat_icnt2mem_pop(m_req); + std::vector<mem_fetch*> reqs; + if(m_config->m_L2_config.m_cache_type == SECTOR) + reqs = breakdown_request_to_sector_requests(m_req); + else + reqs.push_back(m_req); - for (unsigned i = 0; i < reqs.size(); ++i) { - mem_fetch *req = reqs[i]; - m_request_tracker.insert(req); - if (req->istexture()) { - m_icnt_L2_queue->push(req); - req->set_status(IN_PARTITION_ICNT_TO_L2_QUEUE, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - } else { - rop_delay_t r; - r.req = req; - r.ready_cycle = cycle + m_config->rop_latency; - m_rop.push(r); - req->set_status(IN_PARTITION_ROP_DELAY, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - } + for(unsigned i=0; i<reqs.size(); ++i) { + mem_fetch* req = reqs[i]; + m_request_tracker.insert(req); + if( req->istexture() ) { + m_icnt_L2_queue->push(req); + req->set_status(IN_PARTITION_ICNT_TO_L2_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); + } else { + rop_delay_t r; + r.req = req; + r.ready_cycle = cycle + m_config->rop_latency; + m_rop.push(r); + req->set_status(IN_PARTITION_ROP_DELAY,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); + } + } } - } } -mem_fetch *memory_sub_partition::pop() { - mem_fetch *mf = m_L2_icnt_queue->pop(); - m_request_tracker.erase(mf); - if (mf && mf->isatomic()) mf->do_atomic(); - if (mf && (mf->get_access_type() == L2_WRBK_ACC || - mf->get_access_type() == L1_WRBK_ACC)) { - delete mf; - mf = NULL; - } - return mf; +mem_fetch* memory_sub_partition::pop() +{ + mem_fetch* mf = m_L2_icnt_queue->pop(); + m_request_tracker.erase(mf); + if ( mf && mf->isatomic() ) + mf->do_atomic(); + if( mf && (mf->get_access_type() == L2_WRBK_ACC || mf->get_access_type() == L1_WRBK_ACC) ) { + delete mf; + mf = NULL; + } + return mf; } -mem_fetch *memory_sub_partition::top() { - mem_fetch *mf = m_L2_icnt_queue->top(); - if (mf && (mf->get_access_type() == L2_WRBK_ACC || - mf->get_access_type() == L1_WRBK_ACC)) { - m_L2_icnt_queue->pop(); - m_request_tracker.erase(mf); - delete mf; - mf = NULL; - } - return mf; +mem_fetch* memory_sub_partition::top() +{ + mem_fetch *mf = m_L2_icnt_queue->top(); + if( mf && (mf->get_access_type() == L2_WRBK_ACC || mf->get_access_type() == L1_WRBK_ACC) ) { + m_L2_icnt_queue->pop(); + m_request_tracker.erase(mf); + delete mf; + mf = NULL; + } + return mf; } -void memory_sub_partition::set_done(mem_fetch *mf) { - m_request_tracker.erase(mf); +void memory_sub_partition::set_done( mem_fetch *mf ) +{ + m_request_tracker.erase(mf); } -void memory_sub_partition::accumulate_L2cache_stats( - class cache_stats &l2_stats) const { - if (!m_config->m_L2_config.disabled()) { - l2_stats += m_L2cache->get_stats(); - } +void memory_sub_partition::accumulate_L2cache_stats(class cache_stats &l2_stats) const { + if (!m_config->m_L2_config.disabled()) { + l2_stats += m_L2cache->get_stats(); + } } -void memory_sub_partition::get_L2cache_sub_stats( - struct cache_sub_stats &css) const { - if (!m_config->m_L2_config.disabled()) { - m_L2cache->get_sub_stats(css); - } +void memory_sub_partition::get_L2cache_sub_stats(struct cache_sub_stats &css) const{ + if (!m_config->m_L2_config.disabled()) { + m_L2cache->get_sub_stats(css); + } } -void memory_sub_partition::get_L2cache_sub_stats_pw( - struct cache_sub_stats_pw &css) const { - if (!m_config->m_L2_config.disabled()) { - m_L2cache->get_sub_stats_pw(css); - } +void memory_sub_partition::get_L2cache_sub_stats_pw(struct cache_sub_stats_pw &css) const{ + if (!m_config->m_L2_config.disabled()) { + m_L2cache->get_sub_stats_pw(css); + } } void memory_sub_partition::clear_L2cache_stats_pw() { - if (!m_config->m_L2_config.disabled()) { - m_L2cache->clear_pw(); - } + if (!m_config->m_L2_config.disabled()) { + m_L2cache->clear_pw(); + } } -void memory_sub_partition::visualizer_print(gzFile visualizer_file) { - // Support for L2 AerialVision stats - // Per-sub-partition stats would be trivial to extend from this - cache_sub_stats_pw temp_sub_stats; - get_L2cache_sub_stats_pw(temp_sub_stats); +void memory_sub_partition::visualizer_print( gzFile visualizer_file ) +{ + // Support for L2 AerialVision stats + // Per-sub-partition stats would be trivial to extend from this + cache_sub_stats_pw temp_sub_stats; + get_L2cache_sub_stats_pw(temp_sub_stats); - m_stats->L2_read_miss += temp_sub_stats.read_misses; - m_stats->L2_write_miss += temp_sub_stats.write_misses; - m_stats->L2_read_hit += temp_sub_stats.read_hits; - m_stats->L2_write_hit += temp_sub_stats.write_hits; + m_stats->L2_read_miss += temp_sub_stats.read_misses; + m_stats->L2_write_miss += temp_sub_stats.write_misses; + m_stats->L2_read_hit += temp_sub_stats.read_hits; + m_stats->L2_write_hit += temp_sub_stats.write_hits; - clear_L2cache_stats_pw(); + clear_L2cache_stats_pw(); } diff --git a/src/gpgpu-sim/l2cache.h b/src/gpgpu-sim/l2cache.h index fda9a78..0f6fe32 100644 --- a/src/gpgpu-sim/l2cache.h +++ b/src/gpgpu-sim/l2cache.h @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -30,8 +28,8 @@ #ifndef MC_PARTITION_INCLUDED #define MC_PARTITION_INCLUDED -#include "../abstract_hardware_model.h" #include "dram.h" +#include "../abstract_hardware_model.h" #include <list> #include <queue> @@ -39,224 +37,222 @@ class mem_fetch; class partition_mf_allocator : public mem_fetch_allocator { - public: - partition_mf_allocator(const memory_config *config) { - m_memory_config = config; - } - virtual mem_fetch *alloc(const class warp_inst_t &inst, - const mem_access_t &access, - unsigned long long cycle) const { - abort(); - return NULL; - } - virtual mem_fetch *alloc(new_addr_type addr, mem_access_type type, - unsigned size, bool wr, - unsigned long long cycle) const; - - private: - const memory_config *m_memory_config; +public: + partition_mf_allocator( const memory_config *config ) + { + m_memory_config = config; + } + virtual mem_fetch * alloc(const class warp_inst_t &inst, const mem_access_t &access, unsigned long long cycle) const + { + abort(); + return NULL; + } + virtual mem_fetch * alloc(new_addr_type addr, mem_access_type type, unsigned size, bool wr, unsigned long long cycle) const; +private: + const memory_config *m_memory_config; }; -// Memory partition unit contains all the units assolcated with a single DRAM -// channel. -// - It arbitrates the DRAM channel among multiple sub partitions. -// - It does not connect directly with the interconnection network. -class memory_partition_unit { - public: - memory_partition_unit(unsigned partition_id, const memory_config *config, - class memory_stats_t *stats, class gpgpu_sim *gpu); - ~memory_partition_unit(); +// Memory partition unit contains all the units assolcated with a single DRAM channel. +// - It arbitrates the DRAM channel among multiple sub partitions. +// - It does not connect directly with the interconnection network. +class memory_partition_unit +{ +public: + memory_partition_unit( unsigned partition_id, const memory_config *config, class memory_stats_t *stats, class gpgpu_sim* gpu ); + ~memory_partition_unit(); - bool busy() const; + bool busy() const; - void cache_cycle(unsigned cycle); - void dram_cycle(); - void simple_dram_model_cycle(); + void cache_cycle( unsigned cycle ); + void dram_cycle(); + void simple_dram_model_cycle(); - void set_done(mem_fetch *mf); + void set_done( mem_fetch *mf ); - void visualizer_print(gzFile visualizer_file) const; - void print_stat(FILE *fp) { m_dram->print_stat(fp); } - void visualize() const { m_dram->visualize(); } - void print(FILE *fp) const; - void handle_memcpy_to_gpu(size_t dst_start_addr, unsigned subpart_id, - mem_access_sector_mask_t mask); + void visualizer_print( gzFile visualizer_file ) const; + void print_stat( FILE *fp ) { m_dram->print_stat(fp); } + void visualize() const { m_dram->visualize(); } + void print( FILE *fp ) const; + void handle_memcpy_to_gpu( size_t dst_start_addr, unsigned subpart_id, mem_access_sector_mask_t mask ); - class memory_sub_partition *get_sub_partition(int sub_partition_id) { - return m_sub_partition[sub_partition_id]; - } + class memory_sub_partition * get_sub_partition(int sub_partition_id) + { + return m_sub_partition[sub_partition_id]; + } - // Power model - void set_dram_power_stats(unsigned &n_cmd, unsigned &n_activity, - unsigned &n_nop, unsigned &n_act, unsigned &n_pre, - unsigned &n_rd, unsigned &n_wr, - unsigned &n_req) const; + // Power model + void set_dram_power_stats(unsigned &n_cmd, + unsigned &n_activity, + unsigned &n_nop, + unsigned &n_act, + unsigned &n_pre, + unsigned &n_rd, + unsigned &n_wr, + unsigned &n_req) const; - int global_sub_partition_id_to_local_id(int global_sub_partition_id) const; + int global_sub_partition_id_to_local_id(int global_sub_partition_id) const; - unsigned get_mpid() const { return m_id; } + unsigned get_mpid() const { return m_id; } - class gpgpu_sim *get_mgpu() const { - return m_gpu; - } + class gpgpu_sim* get_mgpu() const { return m_gpu; } - private: - unsigned m_id; - const memory_config *m_config; - class memory_stats_t *m_stats; - class memory_sub_partition **m_sub_partition; - class dram_t *m_dram; +private: - class arbitration_metadata { - public: - arbitration_metadata(const memory_config *config); + unsigned m_id; + const memory_config *m_config; + class memory_stats_t *m_stats; + class memory_sub_partition **m_sub_partition; + class dram_t *m_dram; - // check if a subpartition still has credit - bool has_credits(int inner_sub_partition_id) const; - // borrow a credit for a subpartition - void borrow_credit(int inner_sub_partition_id); - // return a credit from a subpartition - void return_credit(int inner_sub_partition_id); + class arbitration_metadata + { + public: + arbitration_metadata(const memory_config *config); - // return the last subpartition that borrowed credit - int last_borrower() const { return m_last_borrower; } + // check if a subpartition still has credit + bool has_credits(int inner_sub_partition_id) const; + // borrow a credit for a subpartition + void borrow_credit(int inner_sub_partition_id); + // return a credit from a subpartition + void return_credit(int inner_sub_partition_id); - void print(FILE *fp) const; + // return the last subpartition that borrowed credit + int last_borrower() const { return m_last_borrower; } - private: - // id of the last subpartition that borrowed credit - int m_last_borrower; + void print( FILE *fp ) const; + private: + // id of the last subpartition that borrowed credit + int m_last_borrower; - int m_shared_credit_limit; - int m_private_credit_limit; + int m_shared_credit_limit; + int m_private_credit_limit; - // credits borrowed by the subpartitions - std::vector<int> m_private_credit; - int m_shared_credit; - }; - arbitration_metadata m_arbitration_metadata; + // credits borrowed by the subpartitions + std::vector<int> m_private_credit; + int m_shared_credit; + }; + arbitration_metadata m_arbitration_metadata; - // determine wheither a given subpartition can issue to DRAM - bool can_issue_to_dram(int inner_sub_partition_id); + // determine wheither a given subpartition can issue to DRAM + bool can_issue_to_dram(int inner_sub_partition_id); - // model DRAM access scheduler latency (fixed latency between L2 and DRAM) - struct dram_delay_t { - unsigned long long ready_cycle; - class mem_fetch *req; - }; - std::list<dram_delay_t> m_dram_latency_queue; + // model DRAM access scheduler latency (fixed latency between L2 and DRAM) + struct dram_delay_t + { + unsigned long long ready_cycle; + class mem_fetch* req; + }; + std::list<dram_delay_t> m_dram_latency_queue; - class gpgpu_sim *m_gpu; + class gpgpu_sim* m_gpu; }; -class memory_sub_partition { - public: - memory_sub_partition(unsigned sub_partition_id, const memory_config *config, - class memory_stats_t *stats, class gpgpu_sim *gpu); - ~memory_sub_partition(); +class memory_sub_partition +{ +public: + memory_sub_partition( unsigned sub_partition_id, const memory_config *config, class memory_stats_t *stats, class gpgpu_sim* gpu ); + ~memory_sub_partition(); - unsigned get_id() const { return m_id; } + unsigned get_id() const { return m_id; } - bool busy() const; + bool busy() const; - void cache_cycle(unsigned cycle); + void cache_cycle( unsigned cycle ); - bool full() const; - bool full(unsigned size) const; - void push(class mem_fetch *mf, unsigned long long clock_cycle); - class mem_fetch *pop(); - class mem_fetch *top(); - void set_done(mem_fetch *mf); + bool full() const; + bool full(unsigned size) const; + void push( class mem_fetch* mf, unsigned long long clock_cycle ); + class mem_fetch* pop(); + class mem_fetch* top(); + void set_done( mem_fetch *mf ); - unsigned flushL2(); - unsigned invalidateL2(); + unsigned flushL2(); + unsigned invalidateL2(); - // interface to L2_dram_queue - bool L2_dram_queue_empty() const; - class mem_fetch *L2_dram_queue_top() const; - void L2_dram_queue_pop(); + // interface to L2_dram_queue + bool L2_dram_queue_empty() const; + class mem_fetch* L2_dram_queue_top() const; + void L2_dram_queue_pop(); - // interface to dram_L2_queue - bool dram_L2_queue_full() const; - void dram_L2_queue_push(class mem_fetch *mf); + // interface to dram_L2_queue + bool dram_L2_queue_full() const; + void dram_L2_queue_push( class mem_fetch* mf ); - void visualizer_print(gzFile visualizer_file); - void print_cache_stat(unsigned &accesses, unsigned &misses) const; - void print(FILE *fp) const; + void visualizer_print( gzFile visualizer_file ); + void print_cache_stat(unsigned &accesses, unsigned &misses) const; + void print( FILE *fp ) const; - void accumulate_L2cache_stats(class cache_stats &l2_stats) const; - void get_L2cache_sub_stats(struct cache_sub_stats &css) const; + void accumulate_L2cache_stats(class cache_stats &l2_stats) const; + void get_L2cache_sub_stats(struct cache_sub_stats &css) const; - // Support for getting per-window L2 stats for AerialVision - void get_L2cache_sub_stats_pw(struct cache_sub_stats_pw &css) const; - void clear_L2cache_stats_pw(); + // Support for getting per-window L2 stats for AerialVision + void get_L2cache_sub_stats_pw(struct cache_sub_stats_pw &css) const; + void clear_L2cache_stats_pw(); - void force_l2_tag_update(new_addr_type addr, unsigned time, - mem_access_sector_mask_t mask) { - m_L2cache->force_tag_access(addr, m_memcpy_cycle_offset + time, mask); - m_memcpy_cycle_offset += 1; - } + void force_l2_tag_update(new_addr_type addr, unsigned time, mem_access_sector_mask_t mask) + { + m_L2cache->force_tag_access( addr, m_memcpy_cycle_offset + time, mask ); + m_memcpy_cycle_offset += 1; + } - private: - // data - unsigned m_id; //< the global sub partition ID - const memory_config *m_config; - class l2_cache *m_L2cache; - class L2interface *m_L2interface; - class gpgpu_sim *m_gpu; - partition_mf_allocator *m_mf_allocator; +private: +// data + unsigned m_id; //< the global sub partition ID + const memory_config *m_config; + class l2_cache *m_L2cache; + class L2interface *m_L2interface; + class gpgpu_sim* m_gpu; + partition_mf_allocator *m_mf_allocator; - // model delay of ROP units with a fixed latency - struct rop_delay_t { - unsigned long long ready_cycle; - class mem_fetch *req; - }; - std::queue<rop_delay_t> m_rop; + // model delay of ROP units with a fixed latency + struct rop_delay_t + { + unsigned long long ready_cycle; + class mem_fetch* req; + }; + std::queue<rop_delay_t> m_rop; - // these are various FIFOs between units within a memory partition - fifo_pipeline<mem_fetch> *m_icnt_L2_queue; - fifo_pipeline<mem_fetch> *m_L2_dram_queue; - fifo_pipeline<mem_fetch> *m_dram_L2_queue; - fifo_pipeline<mem_fetch> *m_L2_icnt_queue; // L2 cache hit response queue + // these are various FIFOs between units within a memory partition + fifo_pipeline<mem_fetch> *m_icnt_L2_queue; + fifo_pipeline<mem_fetch> *m_L2_dram_queue; + fifo_pipeline<mem_fetch> *m_dram_L2_queue; + fifo_pipeline<mem_fetch> *m_L2_icnt_queue; // L2 cache hit response queue - class mem_fetch *L2dramout; - unsigned long long int wb_addr; + class mem_fetch *L2dramout; + unsigned long long int wb_addr; - class memory_stats_t *m_stats; + class memory_stats_t *m_stats; - std::set<mem_fetch *> m_request_tracker; + std::set<mem_fetch*> m_request_tracker; - friend class L2interface; + friend class L2interface; - std::vector<mem_fetch *> breakdown_request_to_sector_requests(mem_fetch *mf); + std::vector<mem_fetch*> breakdown_request_to_sector_requests(mem_fetch* mf); - // This is a cycle offset that has to be applied to the l2 accesses to account - // for - // the cudamemcpy read/writes. We want GPGPU-Sim to only count cycles for - // kernel execution - // but we want cudamemcpy to go through the L2. Everytime an access is made - // from cudamemcpy - // this counter is incremented, and when the l2 is accessed (in both - // cudamemcpyies and otherwise) - // this value is added to the gpgpu-sim cycle counters. - unsigned m_memcpy_cycle_offset; + // This is a cycle offset that has to be applied to the l2 accesses to account for + // the cudamemcpy read/writes. We want GPGPU-Sim to only count cycles for kernel execution + // but we want cudamemcpy to go through the L2. Everytime an access is made from cudamemcpy + // this counter is incremented, and when the l2 is accessed (in both cudamemcpyies and otherwise) + // this value is added to the gpgpu-sim cycle counters. + unsigned m_memcpy_cycle_offset; }; class L2interface : public mem_fetch_interface { - public: - L2interface(memory_sub_partition *unit) { m_unit = unit; } - virtual ~L2interface() {} - virtual bool full(unsigned size, bool write) const { - // assume read and write packets all same size - return m_unit->m_L2_dram_queue->full(); - } - virtual void push(mem_fetch *mf) { - mf->set_status(IN_PARTITION_L2_TO_DRAM_QUEUE, 0 /*FIXME*/); - m_unit->m_L2_dram_queue->push(mf); - } - - private: - memory_sub_partition *m_unit; +public: + L2interface( memory_sub_partition *unit ) { m_unit=unit; } + virtual ~L2interface() {} + virtual bool full( unsigned size, bool write) const + { + // assume read and write packets all same size + return m_unit->m_L2_dram_queue->full(); + } + virtual void push(mem_fetch *mf) + { + mf->set_status(IN_PARTITION_L2_TO_DRAM_QUEUE,0/*FIXME*/); + m_unit->m_L2_dram_queue->push(mf); + } +private: + memory_sub_partition *m_unit; }; #endif diff --git a/src/gpgpu-sim/l2cache_trace.h b/src/gpgpu-sim/l2cache_trace.h index e6b623d..d2dd948 100644 --- a/src/gpgpu-sim/l2cache_trace.h +++ b/src/gpgpu-sim/l2cache_trace.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2011, Tor M. Aamodt, Tim Rogers, Wilson W. L. Fung +// Copyright (c) 2009-2011, Tor M. Aamodt, Tim Rogers, Wilson W. L. Fung // The University of British Columbia // All rights reserved. // @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -27,54 +25,47 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#pragma once +#pragma once #include "../trace.h" #if TRACING_ON #define MEMPART_PRINT_STR SIM_PRINT_STR " %d - " -#define MEMPART_DTRACE(x) \ - (DTRACE(x) && (Trace::sampling_memory_partition == -1 || \ - Trace::sampling_memory_partition == (int)get_mpid())) +#define MEMPART_DTRACE(x) ( DTRACE(x) && (Trace::sampling_memory_partition == -1 || Trace::sampling_memory_partition == (int)get_mpid()) ) #define MEM_SUBPART_PRINT_STR SIM_PRINT_STR " %d - " -#define MEM_SUBPART_DTRACE(x) \ - (DTRACE(x) && (Trace::sampling_memory_partition == -1 || \ - Trace::sampling_memory_partition == (int)m_id)) +#define MEM_SUBPART_DTRACE(x) ( DTRACE(x) && (Trace::sampling_memory_partition == -1 || Trace::sampling_memory_partition == (int)m_id) ) // Intended to be called from inside components of a memory partition // Depends on a get_mpid() function -#define MEMPART_DPRINTF(...) \ - do { \ - if (MEMPART_DTRACE(MEMORY_PARTITION_UNIT)) { \ - printf( \ - MEMPART_PRINT_STR, m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle, \ - Trace::trace_streams_str[Trace::MEMORY_PARTITION_UNIT], get_mpid()); \ - printf(__VA_ARGS__); \ - } \ - } while (0) +#define MEMPART_DPRINTF(...) do {\ + if (MEMPART_DTRACE(MEMORY_PARTITION_UNIT)) {\ + printf( MEMPART_PRINT_STR,\ + m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle,\ + Trace::trace_streams_str[Trace::MEMORY_PARTITION_UNIT],\ + get_mpid() );\ + printf(__VA_ARGS__);\ + }\ +} while (0) -#define MEM_SUBPART_DPRINTF(...) \ - do { \ - if (MEM_SUBPART_DTRACE(MEMORY_PARTITION_UNIT)) { \ - printf(MEM_SUBPART_PRINT_STR, \ - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle, \ - Trace::trace_streams_str[Trace::MEMORY_SUBPARTITION_UNIT], m_id); \ - printf(__VA_ARGS__); \ - } \ - } while (0) +#define MEM_SUBPART_DPRINTF(...) do {\ + if (MEM_SUBPART_DTRACE(MEMORY_PARTITION_UNIT)) {\ + printf( MEM_SUBPART_PRINT_STR,\ + m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle,\ + Trace::trace_streams_str[Trace::MEMORY_SUBPARTITION_UNIT],\ + m_id );\ + printf(__VA_ARGS__);\ + }\ +} while (0) #else -#define MEMPART_DTRACE(x) (false) -#define MEMPART_DPRINTF(x, ...) \ - do { \ - } while (0) +#define MEMPART_DTRACE(x) (false) +#define MEMPART_DPRINTF(x, ...) do {} while (0) -#define MEM_SUBPART_DTRACE(x) (false) -#define MEM_SUBPART_DPRINTF(x, ...) \ - do { \ - } while (0) +#define MEM_SUBPART_DTRACE(x) (false) +#define MEM_SUBPART_DPRINTF(x, ...) do {} while (0) #endif + diff --git a/src/gpgpu-sim/local_interconnect.cc b/src/gpgpu-sim/local_interconnect.cc index 17a122c..c70477c 100644 --- a/src/gpgpu-sim/local_interconnect.cc +++ b/src/gpgpu-sim/local_interconnect.cc @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -27,343 +25,353 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include <algorithm> -#include <cmath> #include <fstream> -#include <iomanip> #include <iostream> #include <sstream> +#include <iomanip> +#include <cmath> #include <utility> +#include <algorithm> #include "local_interconnect.h" #include "mem_fetch.h" -xbar_router::xbar_router(unsigned router_id, enum Interconnect_type m_type, - unsigned n_shader, unsigned n_mem, - unsigned m_in_buffer_limit, - unsigned m_out_buffer_limit, - enum Arbiteration_type m_arbit_type) { - m_id = router_id; - router_type = m_type; - _n_mem = n_mem; - _n_shader = n_shader; - total_nodes = n_shader + n_mem; - in_buffers.resize(total_nodes); - out_buffers.resize(total_nodes); - next_node.resize(total_nodes, 0); - in_buffer_limit = m_in_buffer_limit; - out_buffer_limit = m_out_buffer_limit; - arbit_type = m_arbit_type; - next_node_id = 0; - if (m_type == REQ_NET) { - active_in_buffers = n_shader; - active_out_buffers = n_mem; - } else if (m_type == REPLY_NET) { - active_in_buffers = n_mem; - active_out_buffers = n_shader; - } +xbar_router::xbar_router(unsigned router_id, enum Interconnect_type m_type, unsigned n_shader, unsigned n_mem, unsigned m_in_buffer_limit, unsigned m_out_buffer_limit, enum Arbiteration_type m_arbit_type) +{ + m_id=router_id; + router_type=m_type; + _n_mem = n_mem; + _n_shader = n_shader; + total_nodes = n_shader+n_mem; + in_buffers.resize(total_nodes); + out_buffers.resize(total_nodes); + next_node.resize(total_nodes,0); + in_buffer_limit = m_in_buffer_limit; + out_buffer_limit = m_out_buffer_limit; + arbit_type = m_arbit_type; + next_node_id=0; + if(m_type == REQ_NET) { + active_in_buffers=n_shader; + active_out_buffers=n_mem; + } + else if(m_type == REPLY_NET) { + active_in_buffers=n_mem; + active_out_buffers=n_shader; + } - cycles = 0; - conflicts = 0; - out_buffer_full = 0; - in_buffer_full = 0; - out_buffer_util = 0; - in_buffer_util = 0; - packets_num = 0; + cycles = 0; + conflicts= 0; + out_buffer_full=0; + in_buffer_full=0; + out_buffer_util=0; + in_buffer_util=0; + packets_num=0; } -xbar_router::~xbar_router() {} -void xbar_router::Push(unsigned input_deviceID, unsigned output_deviceID, - void* data, unsigned int size) { - assert(input_deviceID < total_nodes); - in_buffers[input_deviceID].push(Packet(data, output_deviceID)); - packets_num++; +xbar_router::~xbar_router() +{ + +} + +void xbar_router::Push(unsigned input_deviceID, unsigned output_deviceID, void* data, unsigned int size) +{ + assert(input_deviceID < total_nodes); + in_buffers[input_deviceID].push(Packet(data, output_deviceID)); + packets_num++; } -void* xbar_router::Pop(unsigned ouput_deviceID) { - assert(ouput_deviceID < total_nodes); - void* data = NULL; +void* xbar_router::Pop(unsigned ouput_deviceID) +{ + assert(ouput_deviceID < total_nodes); + void* data = NULL; - if (!out_buffers[ouput_deviceID].empty()) { - data = out_buffers[ouput_deviceID].front().data; - out_buffers[ouput_deviceID].pop(); - } + if(!out_buffers[ouput_deviceID].empty()) { + data = out_buffers[ouput_deviceID].front().data; + out_buffers[ouput_deviceID].pop(); + } - return data; + return data; } -bool xbar_router::Has_Buffer_In(unsigned input_deviceID, unsigned size, - bool update_counter) { - assert(input_deviceID < total_nodes); - bool has_buffer = - (in_buffers[input_deviceID].size() + size <= in_buffer_limit); - if (update_counter && !has_buffer) in_buffer_full++; +bool xbar_router::Has_Buffer_In(unsigned input_deviceID, unsigned size, bool update_counter){ + + assert(input_deviceID < total_nodes); + + bool has_buffer = (in_buffers[input_deviceID].size() + size <= in_buffer_limit); + if(update_counter && !has_buffer) + in_buffer_full++; + + return has_buffer; - return has_buffer; } -bool xbar_router::Has_Buffer_Out(unsigned output_deviceID, unsigned size) { - return (out_buffers[output_deviceID].size() + size <= out_buffer_limit); +bool xbar_router::Has_Buffer_Out(unsigned output_deviceID, unsigned size){ + return (out_buffers[output_deviceID].size() + size <= out_buffer_limit); } void xbar_router::Advance() { - if (arbit_type == NAIVE_RR) - RR_Advance(); - else if (arbit_type == iSLIP) - iSLIP_Advance(); - else - assert(0); + + if(arbit_type == NAIVE_RR) + RR_Advance(); + else if(arbit_type == iSLIP) + iSLIP_Advance(); + else + assert(0); + } void xbar_router::RR_Advance() { - cycles++; + cycles++; - vector<bool> issued(total_nodes, false); + vector<bool> issued(total_nodes, false); - for (unsigned i = 0; i < total_nodes; ++i) { - unsigned node_id = (i + next_node_id) % total_nodes; + for(unsigned i=0; i<total_nodes; ++i){ + unsigned node_id = (i+next_node_id)%total_nodes; - if (!in_buffers[node_id].empty()) { - Packet _packet = in_buffers[node_id].front(); - // ensure that the outbuffer has space and not issued before in this cycle - if (Has_Buffer_Out(_packet.output_deviceID, 1)) { - if (!issued[_packet.output_deviceID]) { - out_buffers[_packet.output_deviceID].push(_packet); - in_buffers[node_id].pop(); - issued[_packet.output_deviceID] = true; - } else - conflicts++; - } else { - out_buffer_full++; + if(!in_buffers[node_id].empty()) { + Packet _packet = in_buffers[node_id].front(); + //ensure that the outbuffer has space and not issued before in this cycle + if(Has_Buffer_Out(_packet.output_deviceID, 1)){ + if(!issued[_packet.output_deviceID]) { + out_buffers[_packet.output_deviceID].push(_packet); + in_buffers[node_id].pop(); + issued[_packet.output_deviceID]=true; + } + else + conflicts++; + } + else { + out_buffer_full++; - if (issued[_packet.output_deviceID]) conflicts++; - } - } - } + if(issued[_packet.output_deviceID]) + conflicts++; + } + } + } - next_node_id = (++next_node_id % total_nodes); + next_node_id = (++next_node_id % total_nodes); - // collect some stats about buffer util - for (unsigned i = 0; i < total_nodes; ++i) { - in_buffer_util += in_buffers[i].size(); - out_buffer_util += out_buffers[i].size(); - } + //collect some stats about buffer util + for(unsigned i=0; i<total_nodes; ++i){ + in_buffer_util+=in_buffers[i].size(); + out_buffer_util+=out_buffers[i].size(); + } } -// iSLIP algorithm -// McKeown, Nick. "The iSLIP scheduling algorithm for input-queued switches." -// IEEE/ACM transactions on networking 2 (1999): 188-201. -// https://www.cs.rutgers.edu/~sn624/552-F18/papers/islip.pdf +//iSLIP algorithm +//McKeown, Nick. "The iSLIP scheduling algorithm for input-queued switches." IEEE/ACM transactions on networking 2 (1999): 188-201. +//https://www.cs.rutgers.edu/~sn624/552-F18/papers/islip.pdf void xbar_router::iSLIP_Advance() { - cycles++; + cycles++; + + vector<unsigned> node_tmp; + - vector<unsigned> node_tmp; + //calcaulte how many conflicts are there for stats + for (unsigned i=0; i<total_nodes; ++i){ + + if(!in_buffers[i].empty()){ + Packet _packet_tmp = in_buffers[i].front(); + if (!node_tmp.empty()){ + if (std::find(node_tmp.begin(), node_tmp.end(), _packet_tmp.output_deviceID)!=node_tmp.end()){ + conflicts++; + } + else + node_tmp.push_back(_packet_tmp.output_deviceID); + } + else{ + node_tmp.push_back(_packet_tmp.output_deviceID); + } + } + } - // calcaulte how many conflicts are there for stats - for (unsigned i = 0; i < total_nodes; ++i) { - if (!in_buffers[i].empty()) { - Packet _packet_tmp = in_buffers[i].front(); - if (!node_tmp.empty()) { - if (std::find(node_tmp.begin(), node_tmp.end(), - _packet_tmp.output_deviceID) != node_tmp.end()) { - conflicts++; - } else - node_tmp.push_back(_packet_tmp.output_deviceID); - } else { - node_tmp.push_back(_packet_tmp.output_deviceID); - } - } - } - // do iSLIP - for (unsigned i = 0; i < total_nodes; ++i) { - if (Has_Buffer_Out(i, 1)) { - for (unsigned j = 0; j < total_nodes; ++j) { - unsigned node_id = (j + next_node[i]) % total_nodes; + //do iSLIP + for(unsigned i=0; i<total_nodes; ++i){ - if (!in_buffers[node_id].empty()) { - Packet _packet = in_buffers[node_id].front(); - if (_packet.output_deviceID == i) { - out_buffers[_packet.output_deviceID].push(_packet); - in_buffers[node_id].pop(); - next_node[i] = (++node_id % total_nodes); - break; - } - } - } - } else - out_buffer_full++; - } + if(Has_Buffer_Out(i, 1)) { + for(unsigned j=0; j<total_nodes; ++j){ + unsigned node_id = (j+next_node[i])%total_nodes; - // collect some stats about buffer util - for (unsigned i = 0; i < total_nodes; ++i) { - in_buffer_util += in_buffers[i].size(); - out_buffer_util += out_buffers[i].size(); - } + if(!in_buffers[node_id].empty()) { + Packet _packet = in_buffers[node_id].front(); + if(_packet.output_deviceID==i){ + out_buffers[_packet.output_deviceID].push(_packet); + in_buffers[node_id].pop(); + next_node[i] = (++node_id % total_nodes); + break; + } + } + } + } + else + out_buffer_full++; + } + + //collect some stats about buffer util + for(unsigned i=0; i<total_nodes; ++i){ + in_buffer_util+=in_buffers[i].size(); + out_buffer_util+=out_buffers[i].size(); + } } + + bool xbar_router::Busy() const { - for (unsigned i = 0; i < total_nodes; ++i) { - if (!in_buffers[i].empty()) return true; - if (!out_buffers[i].empty()) return true; - } - return false; + for(unsigned i=0; i<total_nodes; ++i){ + if(!in_buffers[i].empty()) + return true; + + if(!out_buffers[i].empty()) + return true; + } + return false; } + //////////////////////////////////////////////////// /////////////LocalInterconnect///////////////////// -// assume all the packets are one flit +//assume all the packets are one flit #define LOCAL_INCT_FLIT_SIZE 40 -LocalInterconnect* LocalInterconnect::New( - const struct inct_config& m_localinct_config) { - LocalInterconnect* icnt_interface = new LocalInterconnect(m_localinct_config); +LocalInterconnect* LocalInterconnect::New(const struct inct_config& m_localinct_config) +{ - return icnt_interface; + LocalInterconnect* icnt_interface = new LocalInterconnect(m_localinct_config); + + return icnt_interface; } -LocalInterconnect::LocalInterconnect( - const struct inct_config& m_localinct_config) - : m_inct_config(m_localinct_config) { - n_shader = 0; - n_mem = 0; - n_subnets = m_localinct_config.subnets; +LocalInterconnect::LocalInterconnect(const struct inct_config& m_localinct_config): m_inct_config(m_localinct_config){ + n_shader=0; + n_mem=0; + n_subnets = m_localinct_config.subnets; } -LocalInterconnect::~LocalInterconnect() { - for (unsigned i = 0; i < m_inct_config.subnets; ++i) { - delete net[i]; - } +LocalInterconnect::~LocalInterconnect(){ + for (unsigned i = 0; i < m_inct_config.subnets; ++i) { + delete net[i]; + } } -void LocalInterconnect::CreateInterconnect(unsigned m_n_shader, - unsigned m_n_mem) { - n_shader = m_n_shader; - n_mem = m_n_mem; +void LocalInterconnect::CreateInterconnect(unsigned m_n_shader, unsigned m_n_mem){ + n_shader = m_n_shader; + n_mem = m_n_mem; + + net.resize(n_subnets); + for (unsigned i = 0; i < n_subnets; ++i) { + net[i] = new xbar_router( i, static_cast<Interconnect_type>(i), m_n_shader, m_n_mem, m_inct_config.in_buffer_limit, m_inct_config.out_buffer_limit,m_inct_config.arbiter_algo); + } - net.resize(n_subnets); - for (unsigned i = 0; i < n_subnets; ++i) { - net[i] = new xbar_router(i, static_cast<Interconnect_type>(i), m_n_shader, - m_n_mem, m_inct_config.in_buffer_limit, - m_inct_config.out_buffer_limit, - m_inct_config.arbiter_algo); - } } + void LocalInterconnect::Init() { - // empty - // there is nothing to do + //empty + //there is nothing to do + +} + +void LocalInterconnect::Push(unsigned input_deviceID, unsigned output_deviceID, void* data, unsigned int size){ + + unsigned subnet; + if (n_subnets == 1) { + subnet = 0; + } else { + if (input_deviceID < n_shader ) { + subnet = 0; + } else { + subnet = 1; + } + } + + // it should have free buffer + //assume all the packets have size of one + //no flits are implemented + assert(net[subnet]->Has_Buffer_In(input_deviceID, 1)); + + net[subnet]->Push(input_deviceID, output_deviceID, data, size); + } -void LocalInterconnect::Push(unsigned input_deviceID, unsigned output_deviceID, - void* data, unsigned int size) { - unsigned subnet; - if (n_subnets == 1) { - subnet = 0; - } else { - if (input_deviceID < n_shader) { - subnet = 0; - } else { - subnet = 1; - } - } +void* LocalInterconnect::Pop(unsigned ouput_deviceID){ - // it should have free buffer - // assume all the packets have size of one - // no flits are implemented - assert(net[subnet]->Has_Buffer_In(input_deviceID, 1)); + // 0-_n_shader-1 indicates reply(network 1), otherwise request(network 0) + int subnet = 0; + if (ouput_deviceID < n_shader) + subnet = 1; + + return net[subnet]->Pop(ouput_deviceID); - net[subnet]->Push(input_deviceID, output_deviceID, data, size); } -void* LocalInterconnect::Pop(unsigned ouput_deviceID) { - // 0-_n_shader-1 indicates reply(network 1), otherwise request(network 0) - int subnet = 0; - if (ouput_deviceID < n_shader) subnet = 1; +void LocalInterconnect::Advance(){ + + for (unsigned i = 0; i < n_subnets; ++i) { + net[i]->Advance(); + } - return net[subnet]->Pop(ouput_deviceID); } -void LocalInterconnect::Advance() { - for (unsigned i = 0; i < n_subnets; ++i) { - net[i]->Advance(); - } +bool LocalInterconnect::Busy() const{ + + for (unsigned i = 0; i < n_subnets; ++i) { + if(net[i]->Busy()) + return true; + } + return false; } -bool LocalInterconnect::Busy() const { - for (unsigned i = 0; i < n_subnets; ++i) { - if (net[i]->Busy()) return true; - } - return false; +bool LocalInterconnect::HasBuffer(unsigned deviceID, unsigned int size) const{ + + bool has_buffer = false; + + if ((n_subnets>1) && deviceID >= n_shader) // deviceID is memory node + has_buffer = net[REPLY_NET]->Has_Buffer_In(deviceID, 1, true); + else + has_buffer = net[REQ_NET]->Has_Buffer_In(deviceID, 1, true); + + return has_buffer; + } -bool LocalInterconnect::HasBuffer(unsigned deviceID, unsigned int size) const { - bool has_buffer = false; +void LocalInterconnect::DisplayStats() const{ + + cout<<"Req_Network_injected_packets_num = "<<net[REQ_NET]->packets_num<<endl; + cout<<"Req_Network_cycles = "<<net[REQ_NET]->cycles<<endl; + cout<<"Req_Network_injected_packets_per_cycle = "<<(float)(net[REQ_NET]->packets_num) / (net[REQ_NET]->cycles)<<endl; + cout<<"Req_Network_conflicts_per_cycle = "<<(float)(net[REQ_NET]->conflicts) / (net[REQ_NET]->cycles)<<endl; + cout<<"Req_Network_in_buffer_full_per_cycle = "<<(float)(net[REQ_NET]->in_buffer_full) / (net[REQ_NET]->cycles)<<endl; + cout<<"Req_Network_in_buffer_avg_util = "<<((float)(net[REQ_NET]->in_buffer_util) / (net[REQ_NET]->cycles) / net[REQ_NET]->active_in_buffers)<<endl; + cout<<"Req_Network_out_buffer_full_per_cycle = "<<(float)(net[REQ_NET]->out_buffer_full) / (net[REQ_NET]->cycles)<<endl; + cout<<"Req_Network_out_buffer_avg_util = "<<((float)(net[REQ_NET]->out_buffer_util) / (net[REQ_NET]->cycles) / net[REQ_NET]->active_out_buffers)<<endl; - if ((n_subnets > 1) && deviceID >= n_shader) // deviceID is memory node - has_buffer = net[REPLY_NET]->Has_Buffer_In(deviceID, 1, true); - else - has_buffer = net[REQ_NET]->Has_Buffer_In(deviceID, 1, true); + cout<<endl; + cout<<"Reply_Network_injected_packets_num = "<<net[REPLY_NET]->packets_num<<endl; + cout<<"Reply_Network_cycles = "<<net[REPLY_NET]->cycles<<endl; + cout<<"Reply_Network_injected_packets_per_cycle = "<<(float)(net[REPLY_NET]->packets_num) / (net[REPLY_NET]->cycles)<<endl; + cout<<"Reply_Network_conflicts_per_cycle = "<<(float)(net[REPLY_NET]->conflicts) / (net[REPLY_NET]->cycles)<<endl; + cout<<"Reply_Network_in_buffer_full_per_cycle = "<<(float)(net[REPLY_NET]->in_buffer_full) / (net[REPLY_NET]->cycles)<<endl; + cout<<"Reply_Network_in_buffer_avg_util = "<<((float)(net[REPLY_NET]->in_buffer_util) / (net[REPLY_NET]->cycles) / net[REPLY_NET]->active_in_buffers)<<endl; + cout<<"Reply_Network_out_buffer_full_per_cycle = "<<(float)(net[REPLY_NET]->out_buffer_full) / (net[REPLY_NET]->cycles)<<endl; + cout<<"Reply_Network_out_buffer_avg_util= "<<((float)(net[REPLY_NET]->out_buffer_util) / (net[REPLY_NET]->cycles) / net[REPLY_NET]->active_out_buffers)<<endl; - return has_buffer; } -void LocalInterconnect::DisplayStats() const { - cout << "Req_Network_injected_packets_num = " << net[REQ_NET]->packets_num - << endl; - cout << "Req_Network_cycles = " << net[REQ_NET]->cycles << endl; - cout << "Req_Network_injected_packets_per_cycle = " - << (float)(net[REQ_NET]->packets_num) / (net[REQ_NET]->cycles) << endl; - cout << "Req_Network_conflicts_per_cycle = " - << (float)(net[REQ_NET]->conflicts) / (net[REQ_NET]->cycles) << endl; - cout << "Req_Network_in_buffer_full_per_cycle = " - << (float)(net[REQ_NET]->in_buffer_full) / (net[REQ_NET]->cycles) - << endl; - cout << "Req_Network_in_buffer_avg_util = " - << ((float)(net[REQ_NET]->in_buffer_util) / (net[REQ_NET]->cycles) / - net[REQ_NET]->active_in_buffers) - << endl; - cout << "Req_Network_out_buffer_full_per_cycle = " - << (float)(net[REQ_NET]->out_buffer_full) / (net[REQ_NET]->cycles) - << endl; - cout << "Req_Network_out_buffer_avg_util = " - << ((float)(net[REQ_NET]->out_buffer_util) / (net[REQ_NET]->cycles) / - net[REQ_NET]->active_out_buffers) - << endl; +void LocalInterconnect::DisplayOverallStats() const{ - cout << endl; - cout << "Reply_Network_injected_packets_num = " << net[REPLY_NET]->packets_num - << endl; - cout << "Reply_Network_cycles = " << net[REPLY_NET]->cycles << endl; - cout << "Reply_Network_injected_packets_per_cycle = " - << (float)(net[REPLY_NET]->packets_num) / (net[REPLY_NET]->cycles) - << endl; - cout << "Reply_Network_conflicts_per_cycle = " - << (float)(net[REPLY_NET]->conflicts) / (net[REPLY_NET]->cycles) << endl; - cout << "Reply_Network_in_buffer_full_per_cycle = " - << (float)(net[REPLY_NET]->in_buffer_full) / (net[REPLY_NET]->cycles) - << endl; - cout << "Reply_Network_in_buffer_avg_util = " - << ((float)(net[REPLY_NET]->in_buffer_util) / (net[REPLY_NET]->cycles) / - net[REPLY_NET]->active_in_buffers) - << endl; - cout << "Reply_Network_out_buffer_full_per_cycle = " - << (float)(net[REPLY_NET]->out_buffer_full) / (net[REPLY_NET]->cycles) - << endl; - cout << "Reply_Network_out_buffer_avg_util= " - << ((float)(net[REPLY_NET]->out_buffer_util) / (net[REPLY_NET]->cycles) / - net[REPLY_NET]->active_out_buffers) - << endl; } -void LocalInterconnect::DisplayOverallStats() const {} +unsigned LocalInterconnect::GetFlitSize() const{ + return LOCAL_INCT_FLIT_SIZE; +} -unsigned LocalInterconnect::GetFlitSize() const { return LOCAL_INCT_FLIT_SIZE; } +void LocalInterconnect::DisplayState(FILE* fp) const{ -void LocalInterconnect::DisplayState(FILE* fp) const { - fprintf(fp, "GPGPU-Sim uArch: ICNT:Display State: Under implementation\n"); + fprintf(fp, "GPGPU-Sim uArch: ICNT:Display State: Under implementation\n"); } + diff --git a/src/gpgpu-sim/local_interconnect.h b/src/gpgpu-sim/local_interconnect.h index b569c50..a784da8 100644 --- a/src/gpgpu-sim/local_interconnect.h +++ b/src/gpgpu-sim/local_interconnect.h @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -30,102 +28,113 @@ #ifndef _LOCAL_INTERCONNECT_HPP_ #define _LOCAL_INTERCONNECT_HPP_ +#include <vector> +#include <queue> #include <iostream> #include <map> -#include <queue> -#include <vector> using namespace std; -enum Interconnect_type { REQ_NET = 0, REPLY_NET = 1 }; -enum Arbiteration_type { NAIVE_RR = 0, iSLIP = 1 }; +enum Interconnect_type { + REQ_NET=0, + REPLY_NET=1 +}; + +enum Arbiteration_type { + NAIVE_RR=0, + iSLIP=1 +}; -struct inct_config { - // config for local interconnect - unsigned in_buffer_limit; - unsigned out_buffer_limit; - unsigned subnets; - Arbiteration_type arbiter_algo; +struct inct_config +{ + //config for local interconnect + unsigned in_buffer_limit; + unsigned out_buffer_limit; + unsigned subnets; + Arbiteration_type arbiter_algo; }; class xbar_router { - public: - xbar_router(unsigned router_id, enum Interconnect_type m_type, - unsigned n_shader, unsigned n_mem, unsigned m_in_buffer_limit, - unsigned m_out_buffer_limit, enum Arbiteration_type m_arbit_type); - ~xbar_router(); - void Push(unsigned input_deviceID, unsigned output_deviceID, void* data, - unsigned int size); - void* Pop(unsigned ouput_deviceID); - void Advance(); - bool Busy() const; - bool Has_Buffer_In(unsigned input_deviceID, unsigned size, - bool update_counter = false); - bool Has_Buffer_Out(unsigned output_deviceID, unsigned size); +public: + xbar_router(unsigned router_id, enum Interconnect_type m_type, unsigned n_shader, unsigned n_mem, unsigned m_in_buffer_limit, unsigned m_out_buffer_limit, enum Arbiteration_type m_arbit_type); + ~xbar_router(); + void Push(unsigned input_deviceID, unsigned output_deviceID, void* data, unsigned int size); + void* Pop(unsigned ouput_deviceID); + void Advance( ); + - // some stats - unsigned long long cycles; - unsigned long long conflicts; - unsigned long long out_buffer_full; - unsigned long long out_buffer_util; - unsigned long long in_buffer_full; - unsigned long long in_buffer_util; - unsigned long long packets_num; + bool Busy() const; + bool Has_Buffer_In(unsigned input_deviceID, unsigned size, bool update_counter=false); + bool Has_Buffer_Out(unsigned output_deviceID, unsigned size); - private: - void iSLIP_Advance(); - void RR_Advance(); + //some stats + unsigned long long cycles; + unsigned long long conflicts; + unsigned long long out_buffer_full; + unsigned long long out_buffer_util; + unsigned long long in_buffer_full; + unsigned long long in_buffer_util; + unsigned long long packets_num; - struct Packet { - Packet(void* m_data, unsigned m_output_deviceID) { - data = m_data; - output_deviceID = m_output_deviceID; - } - void* data; - unsigned output_deviceID; - }; - vector<queue<Packet> > in_buffers; - vector<queue<Packet> > out_buffers; - unsigned _n_shader, _n_mem, total_nodes; - unsigned in_buffer_limit, out_buffer_limit; - vector<unsigned> next_node; // used for iSLIP arbit - unsigned next_node_id; // used for RR arbit - unsigned m_id; - enum Interconnect_type router_type; - unsigned active_in_buffers, active_out_buffers; - Arbiteration_type arbit_type; +private: + void iSLIP_Advance(); + void RR_Advance(); + + struct Packet{ + Packet(void* m_data, unsigned m_output_deviceID) { + data = m_data; + output_deviceID = m_output_deviceID; + } + void* data; + unsigned output_deviceID; + }; + vector<queue<Packet> > in_buffers; + vector<queue<Packet> > out_buffers; + unsigned _n_shader, _n_mem, total_nodes; + unsigned in_buffer_limit, out_buffer_limit; + vector<unsigned> next_node; //used for iSLIP arbit + unsigned next_node_id; //used for RR arbit + unsigned m_id; + enum Interconnect_type router_type; + unsigned active_in_buffers,active_out_buffers; + Arbiteration_type arbit_type; + + friend class LocalInterconnect; - friend class LocalInterconnect; }; class LocalInterconnect { - public: - LocalInterconnect(const struct inct_config& m_localinct_config); - ~LocalInterconnect(); - static LocalInterconnect* New(const struct inct_config& m_inct_config); - void CreateInterconnect(unsigned n_shader, unsigned n_mem); +public: + LocalInterconnect(const struct inct_config& m_localinct_config); + ~LocalInterconnect(); + static LocalInterconnect* New(const struct inct_config& m_inct_config); + void CreateInterconnect(unsigned n_shader, unsigned n_mem); + + //node side functions + void Init(); + void Push(unsigned input_deviceID, unsigned output_deviceID, void* data, unsigned int size); + void* Pop(unsigned ouput_deviceID); + void Advance(); + bool Busy() const; + bool HasBuffer(unsigned deviceID, unsigned int size) const; + void DisplayStats() const; + void DisplayOverallStats() const; + unsigned GetFlitSize() const; + + void DisplayState(FILE* fp) const; - // node side functions - void Init(); - void Push(unsigned input_deviceID, unsigned output_deviceID, void* data, - unsigned int size); - void* Pop(unsigned ouput_deviceID); - void Advance(); - bool Busy() const; - bool HasBuffer(unsigned deviceID, unsigned int size) const; - void DisplayStats() const; - void DisplayOverallStats() const; - unsigned GetFlitSize() const; - void DisplayState(FILE* fp) const; +protected: - protected: - const inct_config& m_inct_config; + const inct_config& m_inct_config; + + unsigned n_shader, n_mem; + unsigned n_subnets; + vector<xbar_router *> net; - unsigned n_shader, n_mem; - unsigned n_subnets; - vector<xbar_router*> net; }; #endif + + diff --git a/src/gpgpu-sim/mem_fetch.cc b/src/gpgpu-sim/mem_fetch.cc index b6126fc..6a00889 100644 --- a/src/gpgpu-sim/mem_fetch.cc +++ b/src/gpgpu-sim/mem_fetch.cc @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -28,111 +26,118 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "mem_fetch.h" -#include "gpu-sim.h" #include "mem_latency_stat.h" #include "shader.h" #include "visualizer.h" +#include "gpu-sim.h" -unsigned mem_fetch::sm_next_mf_request_uid = 1; +unsigned mem_fetch::sm_next_mf_request_uid=1; -mem_fetch::mem_fetch(const mem_access_t &access, const warp_inst_t *inst, - unsigned ctrl_size, unsigned wid, unsigned sid, - unsigned tpc, const memory_config *config, - unsigned long long cycle, mem_fetch *m_original_mf, - mem_fetch *m_original_wr_mf) - : m_access(access) +mem_fetch::mem_fetch( const mem_access_t &access, + const warp_inst_t *inst, + unsigned ctrl_size, + unsigned wid, + unsigned sid, + unsigned tpc, + const memory_config *config, + unsigned long long cycle, + mem_fetch *m_original_mf, + mem_fetch *m_original_wr_mf):m_access(access) { - m_request_uid = sm_next_mf_request_uid++; - m_access = access; - if (inst) { - m_inst = *inst; - assert(wid == m_inst.warp_id()); - } - m_data_size = access.get_size(); - m_ctrl_size = ctrl_size; - m_sid = sid; - m_tpc = tpc; - m_wid = wid; - config->m_address_mapping.addrdec_tlx(access.get_addr(), &m_raw_addr); - m_partition_addr = - config->m_address_mapping.partition_address(access.get_addr()); - m_type = m_access.is_write() ? WRITE_REQUEST : READ_REQUEST; - m_timestamp = cycle; - m_timestamp2 = 0; - m_status = MEM_FETCH_INITIALIZED; - m_status_change = cycle; - m_mem_config = config; - icnt_flit_size = config->icnt_flit_size; - original_mf = m_original_mf; - original_wr_mf = m_original_wr_mf; + m_request_uid = sm_next_mf_request_uid++; + m_access = access; + if( inst ) { + m_inst = *inst; + assert( wid == m_inst.warp_id() ); + } + m_data_size = access.get_size(); + m_ctrl_size = ctrl_size; + m_sid = sid; + m_tpc = tpc; + m_wid = wid; + config->m_address_mapping.addrdec_tlx(access.get_addr(),&m_raw_addr); + m_partition_addr = config->m_address_mapping.partition_address(access.get_addr()); + m_type = m_access.is_write()?WRITE_REQUEST:READ_REQUEST; + m_timestamp = cycle; + m_timestamp2 = 0; + m_status = MEM_FETCH_INITIALIZED; + m_status_change = cycle; + m_mem_config = config; + icnt_flit_size = config->icnt_flit_size; + original_mf = m_original_mf; + original_wr_mf = m_original_wr_mf; } -mem_fetch::~mem_fetch() { m_status = MEM_FETCH_DELETED; } +mem_fetch::~mem_fetch() +{ + m_status = MEM_FETCH_DELETED; +} -#define MF_TUP_BEGIN(X) static const char *Status_str[] = { +#define MF_TUP_BEGIN(X) static const char* Status_str[] = { #define MF_TUP(X) #X -#define MF_TUP_END(X) \ - } \ - ; +#define MF_TUP_END(X) }; #include "mem_fetch_status.tup" #undef MF_TUP_BEGIN #undef MF_TUP #undef MF_TUP_END -void mem_fetch::print(FILE *fp, bool print_inst) const { - if (this == NULL) { - fprintf(fp, " <NULL mem_fetch pointer>\n"); - return; - } - fprintf(fp, " mf: uid=%6u, sid%02u:w%02u, part=%u, ", m_request_uid, m_sid, - m_wid, m_raw_addr.chip); - m_access.print(fp); - if ((unsigned)m_status < NUM_MEM_REQ_STAT) - fprintf(fp, " status = %s (%llu), ", Status_str[m_status], m_status_change); - else - fprintf(fp, " status = %u??? (%llu), ", m_status, m_status_change); - if (!m_inst.empty() && print_inst) - m_inst.print(fp); - else - fprintf(fp, "\n"); +void mem_fetch::print( FILE *fp, bool print_inst ) const +{ + if( this == NULL ) { + fprintf(fp," <NULL mem_fetch pointer>\n"); + return; + } + fprintf(fp," mf: uid=%6u, sid%02u:w%02u, part=%u, ", m_request_uid, m_sid, m_wid, m_raw_addr.chip ); + m_access.print(fp); + if( (unsigned)m_status < NUM_MEM_REQ_STAT ) + fprintf(fp," status = %s (%llu), ", Status_str[m_status], m_status_change ); + else + fprintf(fp," status = %u??? (%llu), ", m_status, m_status_change ); + if( !m_inst.empty() && print_inst ) m_inst.print(fp); + else fprintf(fp,"\n"); } -void mem_fetch::set_status(enum mem_fetch_status status, - unsigned long long cycle) { - m_status = status; - m_status_change = cycle; +void mem_fetch::set_status( enum mem_fetch_status status, unsigned long long cycle ) +{ + m_status = status; + m_status_change = cycle; } -bool mem_fetch::isatomic() const { - if (m_inst.empty()) return false; - return m_inst.isatomic(); +bool mem_fetch::isatomic() const +{ + if( m_inst.empty() ) return false; + return m_inst.isatomic(); } -void mem_fetch::do_atomic() { m_inst.do_atomic(m_access.get_warp_mask()); } +void mem_fetch::do_atomic() +{ + m_inst.do_atomic( m_access.get_warp_mask() ); +} -bool mem_fetch::istexture() const { - if (m_inst.empty()) return false; - return m_inst.space.get_type() == tex_space; +bool mem_fetch::istexture() const +{ + if( m_inst.empty() ) return false; + return m_inst.space.get_type() == tex_space; } -bool mem_fetch::isconst() const { - if (m_inst.empty()) return false; - return (m_inst.space.get_type() == const_space) || - (m_inst.space.get_type() == param_space_kernel); +bool mem_fetch::isconst() const +{ + if( m_inst.empty() ) return false; + return (m_inst.space.get_type() == const_space) || (m_inst.space.get_type() == param_space_kernel); } -/// Returns number of flits traversing interconnect. simt_to_mem specifies the -/// direction -unsigned mem_fetch::get_num_flits(bool simt_to_mem) { - unsigned sz = 0; - // If atomic, write going to memory, or read coming back from memory, size = - // ctrl + data. Else, only ctrl - if (isatomic() || (simt_to_mem && get_is_write()) || - !(simt_to_mem || get_is_write())) - sz = size(); - else - sz = get_ctrl_size(); +/// Returns number of flits traversing interconnect. simt_to_mem specifies the direction +unsigned mem_fetch::get_num_flits(bool simt_to_mem){ + unsigned sz=0; + // If atomic, write going to memory, or read coming back from memory, size = ctrl + data. Else, only ctrl + if( isatomic() || (simt_to_mem && get_is_write()) || !(simt_to_mem || get_is_write()) ) + sz = size(); + else + sz = get_ctrl_size(); - return (sz / icnt_flit_size) + ((sz % icnt_flit_size) ? 1 : 0); + return (sz/icnt_flit_size) + ( (sz % icnt_flit_size)? 1:0); } + + + diff --git a/src/gpgpu-sim/mem_fetch.h b/src/gpgpu-sim/mem_fetch.h index aa548b7..1cab9f2 100644 --- a/src/gpgpu-sim/mem_fetch.h +++ b/src/gpgpu-sim/mem_fetch.h @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -30,22 +28,20 @@ #ifndef MEM_FETCH_H #define MEM_FETCH_H -#include <bitset> -#include "../abstract_hardware_model.h" #include "addrdec.h" +#include "../abstract_hardware_model.h" +#include <bitset> enum mf_type { - READ_REQUEST = 0, - WRITE_REQUEST, - READ_REPLY, // send to shader - WRITE_ACK + READ_REQUEST = 0, + WRITE_REQUEST, + READ_REPLY, // send to shader + WRITE_ACK }; #define MF_TUP_BEGIN(X) enum X { #define MF_TUP(X) X -#define MF_TUP_END(X) \ - } \ - ; +#define MF_TUP_END(X) }; #include "mem_fetch_status.tup" #undef MF_TUP_BEGIN #undef MF_TUP @@ -53,124 +49,113 @@ enum mf_type { class memory_config; class mem_fetch { - public: - mem_fetch(const mem_access_t &access, const warp_inst_t *inst, - unsigned ctrl_size, unsigned wid, unsigned sid, unsigned tpc, - const memory_config *config, unsigned long long cycle, - mem_fetch *original_mf = NULL, mem_fetch *original_wr_mf = NULL); - ~mem_fetch(); +public: + mem_fetch( const mem_access_t &access, + const warp_inst_t *inst, + unsigned ctrl_size, + unsigned wid, + unsigned sid, + unsigned tpc, + const memory_config *config, + unsigned long long cycle, + mem_fetch *original_mf = NULL, + mem_fetch *original_wr_mf = NULL); + ~mem_fetch(); + + void set_status( enum mem_fetch_status status, unsigned long long cycle ); + void set_reply() + { + assert( m_access.get_type() != L1_WRBK_ACC && m_access.get_type() != L2_WRBK_ACC ); + if( m_type==READ_REQUEST ) { + assert( !get_is_write() ); + m_type = READ_REPLY; + } else if( m_type == WRITE_REQUEST ) { + assert( get_is_write() ); + m_type = WRITE_ACK; + } + } + void do_atomic(); - void set_status(enum mem_fetch_status status, unsigned long long cycle); - void set_reply() { - assert(m_access.get_type() != L1_WRBK_ACC && - m_access.get_type() != L2_WRBK_ACC); - if (m_type == READ_REQUEST) { - assert(!get_is_write()); - m_type = READ_REPLY; - } else if (m_type == WRITE_REQUEST) { - assert(get_is_write()); - m_type = WRITE_ACK; - } - } - void do_atomic(); + void print( FILE *fp, bool print_inst = true ) const; - void print(FILE *fp, bool print_inst = true) const; + const addrdec_t &get_tlx_addr() const { return m_raw_addr; } + unsigned get_data_size() const { return m_data_size; } + void set_data_size( unsigned size ) { m_data_size=size; } + unsigned get_ctrl_size() const { return m_ctrl_size; } + unsigned size() const { return m_data_size+m_ctrl_size; } + bool is_write() {return m_access.is_write();} + void set_addr(new_addr_type addr) { m_access.set_addr(addr); } + new_addr_type get_addr() const { return m_access.get_addr(); } + unsigned get_access_size() const { return m_access.get_size(); } + new_addr_type get_partition_addr() const { return m_partition_addr; } + unsigned get_sub_partition_id() const { return m_raw_addr.sub_partition; } + bool get_is_write() const { return m_access.is_write(); } + unsigned get_request_uid() const { return m_request_uid; } + unsigned get_sid() const { return m_sid; } + unsigned get_tpc() const { return m_tpc; } + unsigned get_wid() const { return m_wid; } + bool istexture() const; + bool isconst() const; + enum mf_type get_type() const { return m_type; } + bool isatomic() const; - const addrdec_t &get_tlx_addr() const { return m_raw_addr; } - unsigned get_data_size() const { return m_data_size; } - void set_data_size(unsigned size) { m_data_size = size; } - unsigned get_ctrl_size() const { return m_ctrl_size; } - unsigned size() const { return m_data_size + m_ctrl_size; } - bool is_write() { return m_access.is_write(); } - void set_addr(new_addr_type addr) { m_access.set_addr(addr); } - new_addr_type get_addr() const { return m_access.get_addr(); } - unsigned get_access_size() const { return m_access.get_size(); } - new_addr_type get_partition_addr() const { return m_partition_addr; } - unsigned get_sub_partition_id() const { return m_raw_addr.sub_partition; } - bool get_is_write() const { return m_access.is_write(); } - unsigned get_request_uid() const { return m_request_uid; } - unsigned get_sid() const { return m_sid; } - unsigned get_tpc() const { return m_tpc; } - unsigned get_wid() const { return m_wid; } - bool istexture() const; - bool isconst() const; - enum mf_type get_type() const { return m_type; } - bool isatomic() const; + void set_return_timestamp( unsigned t ) { m_timestamp2=t; } + void set_icnt_receive_time( unsigned t ) { m_icnt_receive_time=t; } + unsigned get_timestamp() const { return m_timestamp; } + unsigned get_return_timestamp() const { return m_timestamp2; } + unsigned get_icnt_receive_time() const { return m_icnt_receive_time; } - void set_return_timestamp(unsigned t) { m_timestamp2 = t; } - void set_icnt_receive_time(unsigned t) { m_icnt_receive_time = t; } - unsigned get_timestamp() const { return m_timestamp; } - unsigned get_return_timestamp() const { return m_timestamp2; } - unsigned get_icnt_receive_time() const { return m_icnt_receive_time; } + enum mem_access_type get_access_type() const { return m_access.get_type(); } + const active_mask_t& get_access_warp_mask() const { return m_access.get_warp_mask(); } + mem_access_byte_mask_t get_access_byte_mask() const { return m_access.get_byte_mask(); } + mem_access_sector_mask_t get_access_sector_mask() const { return m_access.get_sector_mask(); } - enum mem_access_type get_access_type() const { return m_access.get_type(); } - const active_mask_t &get_access_warp_mask() const { - return m_access.get_warp_mask(); - } - mem_access_byte_mask_t get_access_byte_mask() const { - return m_access.get_byte_mask(); - } - mem_access_sector_mask_t get_access_sector_mask() const { - return m_access.get_sector_mask(); - } + address_type get_pc() const { return m_inst.empty()?-1:m_inst.pc; } + const warp_inst_t &get_inst() { return m_inst; } + enum mem_fetch_status get_status() const { return m_status; } - address_type get_pc() const { return m_inst.empty() ? -1 : m_inst.pc; } - const warp_inst_t &get_inst() { return m_inst; } - enum mem_fetch_status get_status() const { return m_status; } + const memory_config *get_mem_config(){return m_mem_config;} - const memory_config *get_mem_config() { return m_mem_config; } + unsigned get_num_flits(bool simt_to_mem); - unsigned get_num_flits(bool simt_to_mem); + mem_fetch* get_original_mf() { return original_mf; } + mem_fetch* get_original_wr_mf() { return original_wr_mf; } - mem_fetch *get_original_mf() { return original_mf; } - mem_fetch *get_original_wr_mf() { return original_wr_mf; } +private: + // request source information + unsigned m_request_uid; + unsigned m_sid; + unsigned m_tpc; + unsigned m_wid; - private: - // request source information - unsigned m_request_uid; - unsigned m_sid; - unsigned m_tpc; - unsigned m_wid; + // where is this request now? + enum mem_fetch_status m_status; + unsigned long long m_status_change; - // where is this request now? - enum mem_fetch_status m_status; - unsigned long long m_status_change; + // request type, address, size, mask + mem_access_t m_access; + unsigned m_data_size; // how much data is being written + unsigned m_ctrl_size; // how big would all this meta data be in hardware (does not necessarily match actual size of mem_fetch) + new_addr_type m_partition_addr; // linear physical address *within* dram partition (partition bank select bits squeezed out) + addrdec_t m_raw_addr; // raw physical address (i.e., decoded DRAM chip-row-bank-column address) + enum mf_type m_type; - // request type, address, size, mask - mem_access_t m_access; - unsigned m_data_size; // how much data is being written - unsigned m_ctrl_size; // how big would all this meta data be in hardware - // (does not necessarily match actual size of - // mem_fetch) - new_addr_type m_partition_addr; // linear physical address *within* dram - // partition (partition bank select bits - // squeezed out) - addrdec_t m_raw_addr; // raw physical address (i.e., decoded DRAM - // chip-row-bank-column address) - enum mf_type m_type; + // statistics + unsigned m_timestamp; // set to gpu_sim_cycle+gpu_tot_sim_cycle at struct creation + unsigned m_timestamp2; // set to gpu_sim_cycle+gpu_tot_sim_cycle when pushed onto icnt to shader; only used for reads + unsigned m_icnt_receive_time; // set to gpu_sim_cycle + interconnect_latency when fixed icnt latency mode is enabled - // statistics - unsigned - m_timestamp; // set to gpu_sim_cycle+gpu_tot_sim_cycle at struct creation - unsigned m_timestamp2; // set to gpu_sim_cycle+gpu_tot_sim_cycle when pushed - // onto icnt to shader; only used for reads - unsigned m_icnt_receive_time; // set to gpu_sim_cycle + interconnect_latency - // when fixed icnt latency mode is enabled + // requesting instruction (put last so mem_fetch prints nicer in gdb) + warp_inst_t m_inst; - // requesting instruction (put last so mem_fetch prints nicer in gdb) - warp_inst_t m_inst; + static unsigned sm_next_mf_request_uid; - static unsigned sm_next_mf_request_uid; + const memory_config *m_mem_config; + unsigned icnt_flit_size; - const memory_config *m_mem_config; - unsigned icnt_flit_size; + mem_fetch* original_mf; //this pointer is set up when a request is divided into sector requests at L2 cache (if the req size > L2 sector size), so the pointer refers to the original request + mem_fetch* original_wr_mf; //this pointer refers to the original write req, when fetch-on-write policy is used - mem_fetch *original_mf; // this pointer is set up when a request is divided - // into sector requests at L2 cache (if the req size - // > L2 sector size), so the pointer refers to the - // original request - mem_fetch *original_wr_mf; // this pointer refers to the original write req, - // when fetch-on-write policy is used }; #endif diff --git a/src/gpgpu-sim/mem_latency_stat.cc b/src/gpgpu-sim/mem_latency_stat.cc index b58a84f..a1b43a8 100644 --- a/src/gpgpu-sim/mem_latency_stat.cc +++ b/src/gpgpu-sim/mem_latency_stat.cc @@ -8,16 +8,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -28,494 +26,456 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include "mem_latency_stat.h" #include "../abstract_hardware_model.h" -#include "../cuda-sim/ptx-stats.h" -#include "dram.h" -#include "gpu-cache.h" -#include "gpu-misc.h" +#include "mem_latency_stat.h" #include "gpu-sim.h" -#include "mem_fetch.h" +#include "gpu-misc.h" +#include "gpu-cache.h" #include "shader.h" +#include "mem_fetch.h" #include "stat-tool.h" +#include "../cuda-sim/ptx-stats.h" #include "visualizer.h" +#include "dram.h" -#include <stdio.h> -#include <stdlib.h> #include <string.h> +#include <stdlib.h> +#include <stdio.h> #include "../../libcuda/gpgpu_context.h" -memory_stats_t::memory_stats_t(unsigned n_shader, - const shader_core_config *shader_config, - const memory_config *mem_config, - const class gpgpu_sim *gpu) { - assert(mem_config->m_valid); - assert(shader_config->m_valid); +memory_stats_t::memory_stats_t( unsigned n_shader, const shader_core_config *shader_config, const memory_config *mem_config, const class gpgpu_sim* gpu ) +{ + assert( mem_config->m_valid ); + assert( shader_config->m_valid ); - unsigned i, j; + unsigned i,j; - concurrent_row_access = - (unsigned int **)calloc(mem_config->m_n_mem, sizeof(unsigned int *)); - num_activates = - (unsigned int **)calloc(mem_config->m_n_mem, sizeof(unsigned int *)); - row_access = - (unsigned int **)calloc(mem_config->m_n_mem, sizeof(unsigned int *)); - max_conc_access2samerow = - (unsigned int **)calloc(mem_config->m_n_mem, sizeof(unsigned int *)); - max_servicetime2samerow = - (unsigned int **)calloc(mem_config->m_n_mem, sizeof(unsigned int *)); - for (unsigned i = 0; i < mem_config->m_n_mem; i++) { - concurrent_row_access[i] = - (unsigned int *)calloc(mem_config->nbk, sizeof(unsigned int)); - row_access[i] = - (unsigned int *)calloc(mem_config->nbk, sizeof(unsigned int)); - num_activates[i] = - (unsigned int *)calloc(mem_config->nbk, sizeof(unsigned int)); - max_conc_access2samerow[i] = - (unsigned int *)calloc(mem_config->nbk, sizeof(unsigned int)); - max_servicetime2samerow[i] = - (unsigned int *)calloc(mem_config->nbk, sizeof(unsigned int)); - } + concurrent_row_access = (unsigned int**) calloc(mem_config->m_n_mem, sizeof(unsigned int*)); + num_activates = (unsigned int**) calloc(mem_config->m_n_mem, sizeof(unsigned int*)); + row_access = (unsigned int**) calloc(mem_config->m_n_mem, sizeof(unsigned int*)); + max_conc_access2samerow = (unsigned int**) calloc(mem_config->m_n_mem, sizeof(unsigned int*)); + max_servicetime2samerow = (unsigned int**) calloc(mem_config->m_n_mem, sizeof(unsigned int*)); - m_n_shader = n_shader; - m_memory_config = mem_config; - m_gpu = gpu; - total_n_access = 0; - total_n_reads = 0; - total_n_writes = 0; - max_mrq_latency = 0; - max_dq_latency = 0; - max_mf_latency = 0; - max_icnt2mem_latency = 0; - max_icnt2sh_latency = 0; - tot_icnt2mem_latency = 0; - tot_icnt2sh_latency = 0; - tot_mrq_num = 0; - tot_mrq_latency = 0; - memset(mrq_lat_table, 0, sizeof(unsigned) * 32); - memset(dq_lat_table, 0, sizeof(unsigned) * 32); - memset(mf_lat_table, 0, sizeof(unsigned) * 32); - memset(icnt2mem_lat_table, 0, sizeof(unsigned) * 24); - memset(icnt2sh_lat_table, 0, sizeof(unsigned) * 24); - memset(mf_lat_pw_table, 0, sizeof(unsigned) * 32); - mf_num_lat_pw = 0; - max_warps = - n_shader * - (shader_config->n_thread_per_shader / shader_config->warp_size + 1); - mf_tot_lat_pw = 0; // total latency summed up per window. divide by - // mf_num_lat_pw to obtain average latency Per Window - mf_total_lat = 0; - num_mfs = 0; - printf("*** Initializing Memory Statistics ***\n"); - totalbankreads = - (unsigned int **)calloc(mem_config->m_n_mem, sizeof(unsigned int *)); - totalbankwrites = - (unsigned int **)calloc(mem_config->m_n_mem, sizeof(unsigned int *)); - totalbankaccesses = - (unsigned int **)calloc(mem_config->m_n_mem, sizeof(unsigned int *)); - mf_total_lat_table = (unsigned long long int **)calloc( - mem_config->m_n_mem, sizeof(unsigned long long *)); - mf_max_lat_table = - (unsigned **)calloc(mem_config->m_n_mem, sizeof(unsigned *)); - bankreads = (unsigned int ***)calloc(n_shader, sizeof(unsigned int **)); - bankwrites = (unsigned int ***)calloc(n_shader, sizeof(unsigned int **)); - num_MCBs_accessed = (unsigned int *)calloc( - mem_config->m_n_mem * mem_config->nbk, sizeof(unsigned int)); - if (mem_config->gpgpu_frfcfs_dram_sched_queue_size) { - position_of_mrq_chosen = (unsigned int *)calloc( - mem_config->gpgpu_frfcfs_dram_sched_queue_size, sizeof(unsigned int)); - } else - position_of_mrq_chosen = (unsigned int *)calloc(1024, sizeof(unsigned int)); - for (i = 0; i < n_shader; i++) { - bankreads[i] = - (unsigned int **)calloc(mem_config->m_n_mem, sizeof(unsigned int *)); - bankwrites[i] = - (unsigned int **)calloc(mem_config->m_n_mem, sizeof(unsigned int *)); - for (j = 0; j < mem_config->m_n_mem; j++) { - bankreads[i][j] = - (unsigned int *)calloc(mem_config->nbk, sizeof(unsigned int)); - bankwrites[i][j] = - (unsigned int *)calloc(mem_config->nbk, sizeof(unsigned int)); - } - } + for (unsigned i=0;i<mem_config->m_n_mem ;i++ ) { + concurrent_row_access[i] = (unsigned int*) calloc(mem_config->nbk, sizeof(unsigned int)); + row_access[i] = (unsigned int*) calloc(mem_config->nbk, sizeof(unsigned int)); + num_activates[i] = (unsigned int*) calloc(mem_config->nbk, sizeof(unsigned int)); + max_conc_access2samerow[i] = (unsigned int*) calloc(mem_config->nbk, sizeof(unsigned int)); + max_servicetime2samerow[i] = (unsigned int*) calloc(mem_config->nbk, sizeof(unsigned int)); + } - for (i = 0; i < mem_config->m_n_mem; i++) { - totalbankreads[i] = - (unsigned int *)calloc(mem_config->nbk, sizeof(unsigned int)); - totalbankwrites[i] = - (unsigned int *)calloc(mem_config->nbk, sizeof(unsigned int)); - totalbankaccesses[i] = - (unsigned int *)calloc(mem_config->nbk, sizeof(unsigned int)); - mf_total_lat_table[i] = (unsigned long long int *)calloc( - mem_config->nbk, sizeof(unsigned long long int)); - mf_max_lat_table[i] = (unsigned *)calloc(mem_config->nbk, sizeof(unsigned)); - } - mem_access_type_stats = - (unsigned ***)malloc(NUM_MEM_ACCESS_TYPE * sizeof(unsigned **)); - for (i = 0; i < NUM_MEM_ACCESS_TYPE; i++) { - int j; - mem_access_type_stats[i] = - (unsigned **)calloc(mem_config->m_n_mem, sizeof(unsigned *)); - for (j = 0; (unsigned)j < mem_config->m_n_mem; j++) { - mem_access_type_stats[i][j] = - (unsigned *)calloc((mem_config->nbk + 1), sizeof(unsigned *)); - } - } + m_n_shader=n_shader; + m_memory_config=mem_config; + m_gpu=gpu; + total_n_access=0; + total_n_reads=0; + total_n_writes=0; + max_mrq_latency = 0; + max_dq_latency = 0; + max_mf_latency = 0; + max_icnt2mem_latency = 0; + max_icnt2sh_latency = 0; + tot_icnt2mem_latency = 0; + tot_icnt2sh_latency = 0; + tot_mrq_num = 0; + tot_mrq_latency = 0; + memset(mrq_lat_table, 0, sizeof(unsigned)*32); + memset(dq_lat_table, 0, sizeof(unsigned)*32); + memset(mf_lat_table, 0, sizeof(unsigned)*32); + memset(icnt2mem_lat_table, 0, sizeof(unsigned)*24); + memset(icnt2sh_lat_table, 0, sizeof(unsigned)*24); + memset(mf_lat_pw_table, 0, sizeof(unsigned)*32); + mf_num_lat_pw = 0; + max_warps = n_shader * (shader_config->n_thread_per_shader / shader_config->warp_size+1); + mf_tot_lat_pw = 0; //total latency summed up per window. divide by mf_num_lat_pw to obtain average latency Per Window + mf_total_lat = 0; + num_mfs = 0; + printf("*** Initializing Memory Statistics ***\n"); + totalbankreads = (unsigned int**) calloc(mem_config->m_n_mem, sizeof(unsigned int*)); + totalbankwrites = (unsigned int**) calloc(mem_config->m_n_mem, sizeof(unsigned int*)); + totalbankaccesses = (unsigned int**) calloc(mem_config->m_n_mem, sizeof(unsigned int*)); + mf_total_lat_table = (unsigned long long int **) calloc(mem_config->m_n_mem, sizeof(unsigned long long *)); + mf_max_lat_table = (unsigned **) calloc(mem_config->m_n_mem, sizeof(unsigned *)); + bankreads = (unsigned int***) calloc(n_shader, sizeof(unsigned int**)); + bankwrites = (unsigned int***) calloc(n_shader, sizeof(unsigned int**)); + num_MCBs_accessed = (unsigned int*) calloc(mem_config->m_n_mem*mem_config->nbk, sizeof(unsigned int)); + if (mem_config->gpgpu_frfcfs_dram_sched_queue_size) { + position_of_mrq_chosen = (unsigned int*) calloc(mem_config->gpgpu_frfcfs_dram_sched_queue_size, sizeof(unsigned int)); + } else + position_of_mrq_chosen = (unsigned int*) calloc(1024, sizeof(unsigned int)); + for (i=0;i<n_shader ;i++ ) { + bankreads[i] = (unsigned int**) calloc(mem_config->m_n_mem, sizeof(unsigned int*)); + bankwrites[i] = (unsigned int**) calloc(mem_config->m_n_mem, sizeof(unsigned int*)); + for (j=0;j<mem_config->m_n_mem ;j++ ) { + bankreads[i][j] = (unsigned int*) calloc(mem_config->nbk, sizeof(unsigned int)); + bankwrites[i][j] = (unsigned int*) calloc(mem_config->nbk, sizeof(unsigned int)); + } + } - // AerialVision L2 stats - L2_read_miss = 0; - L2_write_miss = 0; - L2_read_hit = 0; - L2_write_hit = 0; + for (i=0;i<mem_config->m_n_mem ;i++ ) { + totalbankreads[i] = (unsigned int*) calloc(mem_config->nbk, sizeof(unsigned int)); + totalbankwrites[i] = (unsigned int*) calloc(mem_config->nbk, sizeof(unsigned int)); + totalbankaccesses[i] = (unsigned int*) calloc(mem_config->nbk, sizeof(unsigned int)); + mf_total_lat_table[i] = (unsigned long long int*) calloc(mem_config->nbk, sizeof(unsigned long long int)); + mf_max_lat_table[i] = (unsigned *) calloc(mem_config->nbk, sizeof(unsigned)); + } - L2_cbtoL2length = - (unsigned int *)calloc(mem_config->m_n_mem, sizeof(unsigned int)); - L2_cbtoL2writelength = - (unsigned int *)calloc(mem_config->m_n_mem, sizeof(unsigned int)); - L2_L2tocblength = - (unsigned int *)calloc(mem_config->m_n_mem, sizeof(unsigned int)); - L2_dramtoL2length = - (unsigned int *)calloc(mem_config->m_n_mem, sizeof(unsigned int)); - L2_dramtoL2writelength = - (unsigned int *)calloc(mem_config->m_n_mem, sizeof(unsigned int)); - L2_L2todramlength = - (unsigned int *)calloc(mem_config->m_n_mem, sizeof(unsigned int)); + mem_access_type_stats = (unsigned ***) malloc(NUM_MEM_ACCESS_TYPE * sizeof(unsigned **)); + for (i = 0; i < NUM_MEM_ACCESS_TYPE; i++) { + int j; + mem_access_type_stats[i] = (unsigned **) calloc(mem_config->m_n_mem, sizeof(unsigned*)); + for (j=0; (unsigned) j< mem_config->m_n_mem; j++) { + mem_access_type_stats[i][j] = (unsigned *) calloc((mem_config->nbk+1), sizeof(unsigned*)); + } + } + + // AerialVision L2 stats + L2_read_miss = 0; + L2_write_miss = 0; + L2_read_hit = 0; + L2_write_hit = 0; + + L2_cbtoL2length = (unsigned int*) calloc(mem_config->m_n_mem, sizeof(unsigned int)); + L2_cbtoL2writelength = (unsigned int*) calloc(mem_config->m_n_mem, sizeof(unsigned int)); + L2_L2tocblength = (unsigned int*) calloc(mem_config->m_n_mem, sizeof(unsigned int)); + L2_dramtoL2length = (unsigned int*) calloc(mem_config->m_n_mem, sizeof(unsigned int)); + L2_dramtoL2writelength = (unsigned int*) calloc(mem_config->m_n_mem, sizeof(unsigned int)); + L2_L2todramlength = (unsigned int*) calloc(mem_config->m_n_mem, sizeof(unsigned int)); } // record the total latency -unsigned memory_stats_t::memlatstat_done(mem_fetch *mf) { - unsigned mf_latency; - mf_latency = - (m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle) - mf->get_timestamp(); - mf_num_lat_pw++; - mf_tot_lat_pw += mf_latency; - unsigned idx = LOGB2(mf_latency); - assert(idx < 32); - mf_lat_table[idx]++; - shader_mem_lat_log(mf->get_sid(), mf_latency); - mf_total_lat_table[mf->get_tlx_addr().chip][mf->get_tlx_addr().bk] += - mf_latency; - if (mf_latency > max_mf_latency) max_mf_latency = mf_latency; - return mf_latency; +unsigned memory_stats_t::memlatstat_done(mem_fetch *mf ) +{ + unsigned mf_latency; + mf_latency = (m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle) - mf->get_timestamp(); + mf_num_lat_pw++; + mf_tot_lat_pw += mf_latency; + unsigned idx = LOGB2(mf_latency); + assert(idx<32); + mf_lat_table[idx]++; + shader_mem_lat_log(mf->get_sid(), mf_latency); + mf_total_lat_table[mf->get_tlx_addr().chip][mf->get_tlx_addr().bk] += mf_latency; + if (mf_latency > max_mf_latency) + max_mf_latency = mf_latency; + return mf_latency; } -void memory_stats_t::memlatstat_read_done(mem_fetch *mf) { - if (m_memory_config->gpgpu_memlatency_stat) { - unsigned mf_latency = memlatstat_done(mf); - if (mf_latency > - mf_max_lat_table[mf->get_tlx_addr().chip][mf->get_tlx_addr().bk]) - mf_max_lat_table[mf->get_tlx_addr().chip][mf->get_tlx_addr().bk] = - mf_latency; - unsigned icnt2sh_latency; - icnt2sh_latency = (m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle) - - mf->get_return_timestamp(); - tot_icnt2sh_latency += icnt2sh_latency; - icnt2sh_lat_table[LOGB2(icnt2sh_latency)]++; - if (icnt2sh_latency > max_icnt2sh_latency) - max_icnt2sh_latency = icnt2sh_latency; - } +void memory_stats_t::memlatstat_read_done(mem_fetch *mf) +{ + if (m_memory_config->gpgpu_memlatency_stat) { + unsigned mf_latency = memlatstat_done(mf); + if (mf_latency > mf_max_lat_table[mf->get_tlx_addr().chip][mf->get_tlx_addr().bk]) + mf_max_lat_table[mf->get_tlx_addr().chip][mf->get_tlx_addr().bk] = mf_latency; + unsigned icnt2sh_latency; + icnt2sh_latency = (m_gpu->gpu_tot_sim_cycle+m_gpu->gpu_sim_cycle) - mf->get_return_timestamp(); + tot_icnt2sh_latency += icnt2sh_latency; + icnt2sh_lat_table[LOGB2(icnt2sh_latency)]++; + if (icnt2sh_latency > max_icnt2sh_latency) + max_icnt2sh_latency = icnt2sh_latency; + } } -void memory_stats_t::memlatstat_dram_access(mem_fetch *mf) { - unsigned dram_id = mf->get_tlx_addr().chip; - unsigned bank = mf->get_tlx_addr().bk; - if (m_memory_config->gpgpu_memlatency_stat) { - if (mf->get_is_write()) { - if (mf->get_sid() < m_n_shader) { // do not count L2_writebacks here - bankwrites[mf->get_sid()][dram_id][bank]++; - shader_mem_acc_log(mf->get_sid(), dram_id, bank, 'w'); +void memory_stats_t::memlatstat_dram_access(mem_fetch *mf) +{ + unsigned dram_id = mf->get_tlx_addr().chip; + unsigned bank = mf->get_tlx_addr().bk; + if (m_memory_config->gpgpu_memlatency_stat) { + if (mf->get_is_write()) { + if ( mf->get_sid() < m_n_shader ) { //do not count L2_writebacks here + bankwrites[mf->get_sid()][dram_id][bank]++; + shader_mem_acc_log( mf->get_sid(), dram_id, bank, 'w'); + } + totalbankwrites[dram_id][bank]++; + } else { + bankreads[mf->get_sid()][dram_id][bank]++; + shader_mem_acc_log( mf->get_sid(), dram_id, bank, 'r'); + totalbankreads[dram_id][bank]++; } - totalbankwrites[dram_id][bank]++; - } else { - bankreads[mf->get_sid()][dram_id][bank]++; - shader_mem_acc_log(mf->get_sid(), dram_id, bank, 'r'); - totalbankreads[dram_id][bank]++; - } - mem_access_type_stats[mf->get_access_type()][dram_id][bank]++; - } - if (mf->get_pc() != (unsigned)-1) - m_gpu->gpgpu_ctx->stats->ptx_file_line_stats_add_dram_traffic( - mf->get_pc(), mf->get_data_size()); + mem_access_type_stats[mf->get_access_type()][dram_id][bank]++; + } + if (mf->get_pc() != (unsigned)-1) + m_gpu->gpgpu_ctx->stats->ptx_file_line_stats_add_dram_traffic(mf->get_pc(), mf->get_data_size()); } -void memory_stats_t::memlatstat_icnt2mem_pop(mem_fetch *mf) { - if (m_memory_config->gpgpu_memlatency_stat) { - unsigned icnt2mem_latency; - icnt2mem_latency = - (m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle) - mf->get_timestamp(); - tot_icnt2mem_latency += icnt2mem_latency; - icnt2mem_lat_table[LOGB2(icnt2mem_latency)]++; - if (icnt2mem_latency > max_icnt2mem_latency) - max_icnt2mem_latency = icnt2mem_latency; - } +void memory_stats_t::memlatstat_icnt2mem_pop(mem_fetch *mf) +{ + if (m_memory_config->gpgpu_memlatency_stat) { + unsigned icnt2mem_latency; + icnt2mem_latency = (m_gpu->gpu_tot_sim_cycle+m_gpu->gpu_sim_cycle) - mf->get_timestamp(); + tot_icnt2mem_latency += icnt2mem_latency; + icnt2mem_lat_table[LOGB2(icnt2mem_latency)]++; + if (icnt2mem_latency > max_icnt2mem_latency) + max_icnt2mem_latency = icnt2mem_latency; + } } -void memory_stats_t::memlatstat_lat_pw() { - if (mf_num_lat_pw && m_memory_config->gpgpu_memlatency_stat) { - assert(mf_tot_lat_pw); - mf_total_lat += mf_tot_lat_pw; - num_mfs += mf_num_lat_pw; - mf_lat_pw_table[LOGB2(mf_tot_lat_pw / mf_num_lat_pw)]++; - mf_tot_lat_pw = 0; - mf_num_lat_pw = 0; - } +void memory_stats_t::memlatstat_lat_pw() +{ + if (mf_num_lat_pw && m_memory_config->gpgpu_memlatency_stat) { + assert(mf_tot_lat_pw); + mf_total_lat += mf_tot_lat_pw; + num_mfs += mf_num_lat_pw; + mf_lat_pw_table[LOGB2(mf_tot_lat_pw/mf_num_lat_pw)]++; + mf_tot_lat_pw = 0; + mf_num_lat_pw = 0; + } } -void memory_stats_t::memlatstat_print(unsigned n_mem, unsigned gpu_mem_n_bk) { - unsigned i, j, k, l, m; - unsigned max_bank_accesses, min_bank_accesses, max_chip_accesses, - min_chip_accesses; - if (m_memory_config->gpgpu_memlatency_stat) { - printf("maxmflatency = %d \n", max_mf_latency); - printf("max_icnt2mem_latency = %d \n", max_icnt2mem_latency); - printf("maxmrqlatency = %d \n", max_mrq_latency); - // printf("maxdqlatency = %d \n", max_dq_latency); - printf("max_icnt2sh_latency = %d \n", max_icnt2sh_latency); - if (num_mfs) { - printf("averagemflatency = %lld \n", mf_total_lat / num_mfs); - printf("avg_icnt2mem_latency = %lld \n", tot_icnt2mem_latency / num_mfs); - if (tot_mrq_num) - printf("avg_mrq_latency = %lld \n", tot_mrq_latency / tot_mrq_num); +void memory_stats_t::memlatstat_print( unsigned n_mem, unsigned gpu_mem_n_bk ) +{ + unsigned i,j,k,l,m; + unsigned max_bank_accesses, min_bank_accesses, max_chip_accesses, min_chip_accesses; - printf("avg_icnt2sh_latency = %lld \n", tot_icnt2sh_latency / num_mfs); - } - printf("mrq_lat_table:"); - for (i = 0; i < 32; i++) { - printf("%d \t", mrq_lat_table[i]); - } - printf("\n"); - printf("dq_lat_table:"); - for (i = 0; i < 32; i++) { - printf("%d \t", dq_lat_table[i]); - } - printf("\n"); - printf("mf_lat_table:"); - for (i = 0; i < 32; i++) { - printf("%d \t", mf_lat_table[i]); - } - printf("\n"); - printf("icnt2mem_lat_table:"); - for (i = 0; i < 24; i++) { - printf("%d \t", icnt2mem_lat_table[i]); - } - printf("\n"); - printf("icnt2sh_lat_table:"); - for (i = 0; i < 24; i++) { - printf("%d \t", icnt2sh_lat_table[i]); - } - printf("\n"); - printf("mf_lat_pw_table:"); - for (i = 0; i < 32; i++) { - printf("%d \t", mf_lat_pw_table[i]); - } - printf("\n"); + if (m_memory_config->gpgpu_memlatency_stat) { + printf("maxmflatency = %d \n", max_mf_latency); + printf("max_icnt2mem_latency = %d \n", max_icnt2mem_latency); + printf("maxmrqlatency = %d \n", max_mrq_latency); + //printf("maxdqlatency = %d \n", max_dq_latency); + printf("max_icnt2sh_latency = %d \n", max_icnt2sh_latency); + if (num_mfs) { + printf("averagemflatency = %lld \n", mf_total_lat/num_mfs); + printf("avg_icnt2mem_latency = %lld \n", tot_icnt2mem_latency/num_mfs); + if(tot_mrq_num) + printf("avg_mrq_latency = %lld \n", tot_mrq_latency/tot_mrq_num); - /*MAXIMUM CONCURRENT ACCESSES TO SAME ROW*/ - printf("maximum concurrent accesses to same row:\n"); - for (i = 0; i < n_mem; i++) { - printf("dram[%d]: ", i); - for (j = 0; j < gpu_mem_n_bk; j++) { - printf("%9d ", max_conc_access2samerow[i][j]); + printf("avg_icnt2sh_latency = %lld \n", tot_icnt2sh_latency/num_mfs); + } + printf("mrq_lat_table:"); + for (i=0; i< 32; i++) { + printf("%d \t", mrq_lat_table[i]); } printf("\n"); - } - - /*MAXIMUM SERVICE TIME TO SAME ROW*/ - printf("maximum service time to same row:\n"); - for (i = 0; i < n_mem; i++) { - printf("dram[%d]: ", i); - for (j = 0; j < gpu_mem_n_bk; j++) { - printf("%9d ", max_servicetime2samerow[i][j]); + printf("dq_lat_table:"); + for (i=0; i< 32; i++) { + printf("%d \t", dq_lat_table[i]); } printf("\n"); - } - - /*AVERAGE ROW ACCESSES PER ACTIVATE*/ - int total_row_accesses = 0; - int total_num_activates = 0; - printf("average row accesses per activate:\n"); - for (i = 0; i < n_mem; i++) { - printf("dram[%d]: ", i); - for (j = 0; j < gpu_mem_n_bk; j++) { - total_row_accesses += row_access[i][j]; - total_num_activates += num_activates[i][j]; - printf("%9f ", (float)row_access[i][j] / num_activates[i][j]); + printf("mf_lat_table:"); + for (i=0; i< 32; i++) { + printf("%d \t", mf_lat_table[i]); } printf("\n"); - } - printf("average row locality = %d/%d = %f\n", total_row_accesses, - total_num_activates, - (float)total_row_accesses / total_num_activates); - /*MEMORY ACCESSES*/ - k = 0; - l = 0; - m = 0; - max_bank_accesses = 0; - max_chip_accesses = 0; - min_bank_accesses = 0xFFFFFFFF; - min_chip_accesses = 0xFFFFFFFF; - printf("number of total memory accesses made:\n"); - for (i = 0; i < n_mem; i++) { - printf("dram[%d]: ", i); - for (j = 0; j < gpu_mem_n_bk; j++) { - l = totalbankaccesses[i][j]; - if (l < min_bank_accesses) min_bank_accesses = l; - if (l > max_bank_accesses) max_bank_accesses = l; - k += l; - m += l; - printf("%9d ", l); + printf("icnt2mem_lat_table:"); + for (i=0; i< 24; i++) { + printf("%d \t", icnt2mem_lat_table[i]); + } + printf("\n"); + printf("icnt2sh_lat_table:"); + for (i=0; i< 24; i++) { + printf("%d \t", icnt2sh_lat_table[i]); + } + printf("\n"); + printf("mf_lat_pw_table:"); + for (i=0; i< 32; i++) { + printf("%d \t", mf_lat_pw_table[i]); } - if (m < min_chip_accesses) min_chip_accesses = m; - if (m > max_chip_accesses) max_chip_accesses = m; - m = 0; printf("\n"); - } - printf("total accesses: %d\n", k); - if (min_bank_accesses) - printf("bank skew: %d/%d = %4.2f\n", max_bank_accesses, min_bank_accesses, - (float)max_bank_accesses / min_bank_accesses); - else - printf("min_bank_accesses = 0!\n"); - if (min_chip_accesses) - printf("chip skew: %d/%d = %4.2f\n", max_chip_accesses, min_chip_accesses, - (float)max_chip_accesses / min_chip_accesses); - else - printf("min_chip_accesses = 0!\n"); - /*READ ACCESSES*/ - k = 0; - l = 0; - m = 0; - max_bank_accesses = 0; - max_chip_accesses = 0; - min_bank_accesses = 0xFFFFFFFF; - min_chip_accesses = 0xFFFFFFFF; - printf("number of total read accesses:\n"); - for (i = 0; i < n_mem; i++) { - printf("dram[%d]: ", i); - for (j = 0; j < gpu_mem_n_bk; j++) { - l = totalbankreads[i][j]; - if (l < min_bank_accesses) min_bank_accesses = l; - if (l > max_bank_accesses) max_bank_accesses = l; - k += l; - m += l; - printf("%9d ", l); + /*MAXIMUM CONCURRENT ACCESSES TO SAME ROW*/ + printf("maximum concurrent accesses to same row:\n"); + for (i=0;i<n_mem ;i++ ) { + printf("dram[%d]: ", i); + for (j=0;j<gpu_mem_n_bk;j++ ) { + printf("%9d ",max_conc_access2samerow[i][j]); + } + printf("\n"); } - if (m < min_chip_accesses) min_chip_accesses = m; - if (m > max_chip_accesses) max_chip_accesses = m; + + /*MAXIMUM SERVICE TIME TO SAME ROW*/ + printf("maximum service time to same row:\n"); + for (i=0;i<n_mem ;i++ ) { + printf("dram[%d]: ", i); + for (j=0;j<gpu_mem_n_bk;j++ ) { + printf("%9d ",max_servicetime2samerow[i][j]); + } + printf("\n"); + } + + /*AVERAGE ROW ACCESSES PER ACTIVATE*/ + int total_row_accesses = 0; + int total_num_activates = 0; + printf("average row accesses per activate:\n"); + for (i=0;i<n_mem ;i++ ) { + printf("dram[%d]: ", i); + for (j=0;j<gpu_mem_n_bk;j++ ) { + total_row_accesses += row_access[i][j]; + total_num_activates += num_activates[i][j]; + printf("%9f ",(float) row_access[i][j]/num_activates[i][j]); + } + printf("\n"); + } + printf("average row locality = %d/%d = %f\n", total_row_accesses, total_num_activates, (float)total_row_accesses/total_num_activates); + /*MEMORY ACCESSES*/ + k = 0; + l = 0; m = 0; - printf("\n"); - } - printf("total dram reads = %d\n", k); - if (min_bank_accesses) - printf("bank skew: %d/%d = %4.2f\n", max_bank_accesses, min_bank_accesses, - (float)max_bank_accesses / min_bank_accesses); - else - printf("min_bank_accesses = 0!\n"); - if (min_chip_accesses) - printf("chip skew: %d/%d = %4.2f\n", max_chip_accesses, min_chip_accesses, - (float)max_chip_accesses / min_chip_accesses); - else - printf("min_chip_accesses = 0!\n"); + max_bank_accesses = 0; + max_chip_accesses = 0; + min_bank_accesses = 0xFFFFFFFF; + min_chip_accesses = 0xFFFFFFFF; + printf("number of total memory accesses made:\n"); + for (i=0;i<n_mem ;i++ ) { + printf("dram[%d]: ", i); + for (j=0;j<gpu_mem_n_bk;j++ ) { + l = totalbankaccesses[i][j]; + if (l < min_bank_accesses) + min_bank_accesses = l; + if (l > max_bank_accesses) + max_bank_accesses = l; + k += l; + m += l; + printf("%9d ",l); + } + if (m < min_chip_accesses) + min_chip_accesses = m; + if (m > max_chip_accesses) + max_chip_accesses = m; + m = 0; + printf("\n"); + } + printf("total accesses: %d\n", k); + if (min_bank_accesses) + printf("bank skew: %d/%d = %4.2f\n", max_bank_accesses, min_bank_accesses, (float)max_bank_accesses/min_bank_accesses); + else + printf("min_bank_accesses = 0!\n"); + if (min_chip_accesses) + printf("chip skew: %d/%d = %4.2f\n", max_chip_accesses, min_chip_accesses, (float)max_chip_accesses/min_chip_accesses); + else + printf("min_chip_accesses = 0!\n"); - /*WRITE ACCESSES*/ - k = 0; - l = 0; - m = 0; - max_bank_accesses = 0; - max_chip_accesses = 0; - min_bank_accesses = 0xFFFFFFFF; - min_chip_accesses = 0xFFFFFFFF; - printf("number of total write accesses:\n"); - for (i = 0; i < n_mem; i++) { - printf("dram[%d]: ", i); - for (j = 0; j < gpu_mem_n_bk; j++) { - l = totalbankwrites[i][j]; - if (l < min_bank_accesses) min_bank_accesses = l; - if (l > max_bank_accesses) max_bank_accesses = l; - k += l; - m += l; - printf("%9d ", l); + /*READ ACCESSES*/ + k = 0; + l = 0; + m = 0; + max_bank_accesses = 0; + max_chip_accesses = 0; + min_bank_accesses = 0xFFFFFFFF; + min_chip_accesses = 0xFFFFFFFF; + printf("number of total read accesses:\n"); + for (i=0;i<n_mem ;i++ ) { + printf("dram[%d]: ", i); + for (j=0;j<gpu_mem_n_bk;j++ ) { + l = totalbankreads[i][j]; + if (l < min_bank_accesses) + min_bank_accesses = l; + if (l > max_bank_accesses) + max_bank_accesses = l; + k += l; + m += l; + printf("%9d ",l); + } + if (m < min_chip_accesses) + min_chip_accesses = m; + if (m > max_chip_accesses) + max_chip_accesses = m; + m = 0; + printf("\n"); } - if (m < min_chip_accesses) min_chip_accesses = m; - if (m > max_chip_accesses) max_chip_accesses = m; + printf("total dram reads = %d\n", k); + if (min_bank_accesses) + printf("bank skew: %d/%d = %4.2f\n", max_bank_accesses, min_bank_accesses, (float)max_bank_accesses/min_bank_accesses); + else + printf("min_bank_accesses = 0!\n"); + if (min_chip_accesses) + printf("chip skew: %d/%d = %4.2f\n", max_chip_accesses, min_chip_accesses, (float)max_chip_accesses/min_chip_accesses); + else + printf("min_chip_accesses = 0!\n"); + + /*WRITE ACCESSES*/ + k = 0; + l = 0; m = 0; - printf("\n"); - } - printf("total dram writes = %d\n", k); - if (min_bank_accesses) - printf("bank skew: %d/%d = %4.2f\n", max_bank_accesses, min_bank_accesses, - (float)max_bank_accesses / min_bank_accesses); - else - printf("min_bank_accesses = 0!\n"); - if (min_chip_accesses) - printf("chip skew: %d/%d = %4.2f\n", max_chip_accesses, min_chip_accesses, - (float)max_chip_accesses / min_chip_accesses); - else - printf("min_chip_accesses = 0!\n"); + max_bank_accesses = 0; + max_chip_accesses = 0; + min_bank_accesses = 0xFFFFFFFF; + min_chip_accesses = 0xFFFFFFFF; + printf("number of total write accesses:\n"); + for (i=0;i<n_mem ;i++ ) { + printf("dram[%d]: ", i); + for (j=0;j<gpu_mem_n_bk;j++ ) { + l = totalbankwrites[i][j]; + if (l < min_bank_accesses) + min_bank_accesses = l; + if (l > max_bank_accesses) + max_bank_accesses = l; + k += l; + m += l; + printf("%9d ",l); + } + if (m < min_chip_accesses) + min_chip_accesses = m; + if (m > max_chip_accesses) + max_chip_accesses = m; + m = 0; + printf("\n"); + } + printf("total dram writes = %d\n", k); + if (min_bank_accesses) + printf("bank skew: %d/%d = %4.2f\n", max_bank_accesses, min_bank_accesses, (float)max_bank_accesses/min_bank_accesses); + else + printf("min_bank_accesses = 0!\n"); + if (min_chip_accesses) + printf("chip skew: %d/%d = %4.2f\n", max_chip_accesses, min_chip_accesses, (float)max_chip_accesses/min_chip_accesses); + else + printf("min_chip_accesses = 0!\n"); + - /*AVERAGE MF LATENCY PER BANK*/ - printf("average mf latency per bank:\n"); - for (i = 0; i < n_mem; i++) { - printf("dram[%d]: ", i); - for (j = 0; j < gpu_mem_n_bk; j++) { - k = totalbankwrites[i][j] + totalbankreads[i][j]; - if (k) - printf("%10lld", mf_total_lat_table[i][j] / k); - else - printf(" none "); + /*AVERAGE MF LATENCY PER BANK*/ + printf("average mf latency per bank:\n"); + for (i=0;i<n_mem ;i++ ) { + printf("dram[%d]: ", i); + for (j=0;j<gpu_mem_n_bk;j++ ) { + k = totalbankwrites[i][j] + totalbankreads[i][j]; + if (k) + printf("%10lld", mf_total_lat_table[i][j] / k); + else + printf(" none "); + } + printf("\n"); } - printf("\n"); - } - /*MAXIMUM MF LATENCY PER BANK*/ - printf("maximum mf latency per bank:\n"); - for (i = 0; i < n_mem; i++) { - printf("dram[%d]: ", i); - for (j = 0; j < gpu_mem_n_bk; j++) { - printf("%10d", mf_max_lat_table[i][j]); + /*MAXIMUM MF LATENCY PER BANK*/ + printf("maximum mf latency per bank:\n"); + for (i=0;i<n_mem ;i++ ) { + printf("dram[%d]: ", i); + for (j=0;j<gpu_mem_n_bk;j++ ) { + printf("%10d", mf_max_lat_table[i][j]); + } + printf("\n"); + } + } + + if (m_memory_config->gpgpu_memlatency_stat & GPU_MEMLATSTAT_MC) { + printf("\nNumber of Memory Banks Accessed per Memory Operation per Warp (from 0):\n"); + unsigned long long accum_MCBs_accessed = 0; + unsigned long long tot_mem_ops_per_warp = 0; + for (i=0;i< n_mem*gpu_mem_n_bk ; i++ ) { + accum_MCBs_accessed += i*num_MCBs_accessed[i]; + tot_mem_ops_per_warp += num_MCBs_accessed[i]; + printf("%d\t", num_MCBs_accessed[i]); } - printf("\n"); - } - } - if (m_memory_config->gpgpu_memlatency_stat & GPU_MEMLATSTAT_MC) { - printf( - "\nNumber of Memory Banks Accessed per Memory Operation per Warp (from " - "0):\n"); - unsigned long long accum_MCBs_accessed = 0; - unsigned long long tot_mem_ops_per_warp = 0; - for (i = 0; i < n_mem * gpu_mem_n_bk; i++) { - accum_MCBs_accessed += i * num_MCBs_accessed[i]; - tot_mem_ops_per_warp += num_MCBs_accessed[i]; - printf("%d\t", num_MCBs_accessed[i]); - } + printf("\nAverage # of Memory Banks Accessed per Memory Operation per Warp=%f\n", (float)accum_MCBs_accessed/tot_mem_ops_per_warp); - printf( - "\nAverage # of Memory Banks Accessed per Memory Operation per " - "Warp=%f\n", - (float)accum_MCBs_accessed / tot_mem_ops_per_warp); + //printf("\nAverage Difference Between First and Last Response from Memory System per warp = "); - // printf("\nAverage Difference Between First and Last Response from Memory - // System per warp = "); - printf("\nposition of mrq chosen\n"); + printf("\nposition of mrq chosen\n"); - if (!m_memory_config->gpgpu_frfcfs_dram_sched_queue_size) - j = 1024; - else - j = m_memory_config->gpgpu_frfcfs_dram_sched_queue_size; - k = 0; - l = 0; - for (i = 0; i < j; i++) { - printf("%d\t", position_of_mrq_chosen[i]); - k += position_of_mrq_chosen[i]; - l += i * position_of_mrq_chosen[i]; - } - printf("\n"); - printf("\naverage position of mrq chosen = %f\n", (float)l / k); - } + if (!m_memory_config->gpgpu_frfcfs_dram_sched_queue_size) + j = 1024; + else + j = m_memory_config->gpgpu_frfcfs_dram_sched_queue_size; + k=0;l=0; + for (i=0;i< j; i++ ) { + printf("%d\t", position_of_mrq_chosen[i]); + k += position_of_mrq_chosen[i]; + l += i*position_of_mrq_chosen[i]; + } + printf("\n"); + printf("\naverage position of mrq chosen = %f\n", (float)l/k); + } } diff --git a/src/gpgpu-sim/mem_latency_stat.h b/src/gpgpu-sim/mem_latency_stat.h index 21c15ee..0c84972 100644 --- a/src/gpgpu-sim/mem_latency_stat.h +++ b/src/gpgpu-sim/mem_latency_stat.h @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -36,94 +34,87 @@ class memory_config; class memory_stats_t { - public: - memory_stats_t(unsigned n_shader, - const class shader_core_config *shader_config, - const memory_config *mem_config, const class gpgpu_sim *gpu); +public: + memory_stats_t( unsigned n_shader, + const class shader_core_config *shader_config, + const memory_config *mem_config, + const class gpgpu_sim* gpu); - unsigned memlatstat_done(class mem_fetch *mf); - void memlatstat_read_done(class mem_fetch *mf); - void memlatstat_dram_access(class mem_fetch *mf); - void memlatstat_icnt2mem_pop(class mem_fetch *mf); - void memlatstat_lat_pw(); - void memlatstat_print(unsigned n_mem, unsigned gpu_mem_n_bk); + unsigned memlatstat_done( class mem_fetch *mf ); + void memlatstat_read_done( class mem_fetch *mf ); + void memlatstat_dram_access( class mem_fetch *mf ); + void memlatstat_icnt2mem_pop( class mem_fetch *mf); + void memlatstat_lat_pw(); + void memlatstat_print(unsigned n_mem, unsigned gpu_mem_n_bk); - void visualizer_print(gzFile visualizer_file); + void visualizer_print( gzFile visualizer_file ); - // Reset local L2 stats that are aggregated each sampling window - void clear_L2_stats_pw(); + // Reset local L2 stats that are aggregated each sampling window + void clear_L2_stats_pw(); - unsigned m_n_shader; + unsigned m_n_shader; - const shader_core_config *m_shader_config; - const memory_config *m_memory_config; - const class gpgpu_sim *m_gpu; + const shader_core_config *m_shader_config; + const memory_config *m_memory_config; + const class gpgpu_sim* m_gpu; - unsigned max_mrq_latency; - unsigned max_dq_latency; - unsigned max_mf_latency; - unsigned max_icnt2mem_latency; - unsigned long long int tot_icnt2mem_latency; - unsigned long long int tot_icnt2sh_latency; - unsigned long long int tot_mrq_latency; - unsigned long long int tot_mrq_num; - unsigned max_icnt2sh_latency; - unsigned mrq_lat_table[32]; - unsigned dq_lat_table[32]; - unsigned mf_lat_table[32]; - unsigned icnt2mem_lat_table[24]; - unsigned icnt2sh_lat_table[24]; - unsigned mf_lat_pw_table[32]; // table storing values of mf latency Per - // Window - unsigned mf_num_lat_pw; - unsigned max_warps; - unsigned mf_tot_lat_pw; // total latency summed up per window. divide by - // mf_num_lat_pw to obtain average latency Per Window - unsigned long long int mf_total_lat; - unsigned long long int * - *mf_total_lat_table; // mf latency sums[dram chip id][bank id] - unsigned **mf_max_lat_table; // mf latency sums[dram chip id][bank id] - unsigned num_mfs; - unsigned int ***bankwrites; // bankwrites[shader id][dram chip id][bank id] - unsigned int ***bankreads; // bankreads[shader id][dram chip id][bank id] - unsigned int **totalbankwrites; // bankwrites[dram chip id][bank id] - unsigned int **totalbankreads; // bankreads[dram chip id][bank id] - unsigned int **totalbankaccesses; // bankaccesses[dram chip id][bank id] - unsigned int *num_MCBs_accessed; // tracks how many memory controllers are - // accessed whenever any thread in a warp - // misses in cache - unsigned int *position_of_mrq_chosen; // position of mrq in m_queue chosen + unsigned max_mrq_latency; + unsigned max_dq_latency; + unsigned max_mf_latency; + unsigned max_icnt2mem_latency; + unsigned long long int tot_icnt2mem_latency; + unsigned long long int tot_icnt2sh_latency; + unsigned long long int tot_mrq_latency; + unsigned long long int tot_mrq_num; + unsigned max_icnt2sh_latency; + unsigned mrq_lat_table[32]; + unsigned dq_lat_table[32]; + unsigned mf_lat_table[32]; + unsigned icnt2mem_lat_table[24]; + unsigned icnt2sh_lat_table[24]; + unsigned mf_lat_pw_table[32]; //table storing values of mf latency Per Window + unsigned mf_num_lat_pw; + unsigned max_warps; + unsigned mf_tot_lat_pw; //total latency summed up per window. divide by mf_num_lat_pw to obtain average latency Per Window + unsigned long long int mf_total_lat; + unsigned long long int ** mf_total_lat_table; //mf latency sums[dram chip id][bank id] + unsigned ** mf_max_lat_table; //mf latency sums[dram chip id][bank id] + unsigned num_mfs; + unsigned int ***bankwrites; //bankwrites[shader id][dram chip id][bank id] + unsigned int ***bankreads; //bankreads[shader id][dram chip id][bank id] + unsigned int **totalbankwrites; //bankwrites[dram chip id][bank id] + unsigned int **totalbankreads; //bankreads[dram chip id][bank id] + unsigned int **totalbankaccesses; //bankaccesses[dram chip id][bank id] + unsigned int *num_MCBs_accessed; //tracks how many memory controllers are accessed whenever any thread in a warp misses in cache + unsigned int *position_of_mrq_chosen; //position of mrq in m_queue chosen + + unsigned ***mem_access_type_stats; // dram access type classification - unsigned ***mem_access_type_stats; // dram access type classification + // AerialVision L2 stats + unsigned L2_read_miss; + unsigned L2_write_miss; + unsigned L2_read_hit; + unsigned L2_write_hit; - // AerialVision L2 stats - unsigned L2_read_miss; - unsigned L2_write_miss; - unsigned L2_read_hit; - unsigned L2_write_hit; + // L2 cache stats + unsigned int *L2_cbtoL2length; + unsigned int *L2_cbtoL2writelength; + unsigned int *L2_L2tocblength; + unsigned int *L2_dramtoL2length; + unsigned int *L2_dramtoL2writelength; + unsigned int *L2_L2todramlength; - // L2 cache stats - unsigned int *L2_cbtoL2length; - unsigned int *L2_cbtoL2writelength; - unsigned int *L2_L2tocblength; - unsigned int *L2_dramtoL2length; - unsigned int *L2_dramtoL2writelength; - unsigned int *L2_L2todramlength; + // DRAM access row locality stats + unsigned int **concurrent_row_access; //concurrent_row_access[dram chip id][bank id] + unsigned int **num_activates; //num_activates[dram chip id][bank id] + unsigned int **row_access; //row_access[dram chip id][bank id] + unsigned int **max_conc_access2samerow; //max_conc_access2samerow[dram chip id][bank id] + unsigned int **max_servicetime2samerow; //max_servicetime2samerow[dram chip id][bank id] - // DRAM access row locality stats - unsigned int * - *concurrent_row_access; // concurrent_row_access[dram chip id][bank id] - unsigned int **num_activates; // num_activates[dram chip id][bank id] - unsigned int **row_access; // row_access[dram chip id][bank id] - unsigned int **max_conc_access2samerow; // max_conc_access2samerow[dram chip - // id][bank id] - unsigned int **max_servicetime2samerow; // max_servicetime2samerow[dram chip - // id][bank id] - - // Power stats - unsigned total_n_access; - unsigned total_n_reads; - unsigned total_n_writes; + // Power stats + unsigned total_n_access; + unsigned total_n_reads; + unsigned total_n_writes; }; #endif /*MEM_LATENCY_STAT_H*/ diff --git a/src/gpgpu-sim/power_interface.cc b/src/gpgpu-sim/power_interface.cc index d3bb4e2..0272aa6 100644 --- a/src/gpgpu-sim/power_interface.cc +++ b/src/gpgpu-sim/power_interface.cc @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -29,127 +27,99 @@ #include "power_interface.h" -void init_mcpat(const gpgpu_sim_config &config, - class gpgpu_sim_wrapper *wrapper, unsigned stat_sample_freq, - unsigned tot_inst, unsigned inst) { - wrapper->init_mcpat( - config.g_power_config_name, config.g_power_filename, - config.g_power_trace_filename, config.g_metric_trace_filename, - config.g_steady_state_tracking_filename, - config.g_power_simulation_enabled, config.g_power_trace_enabled, - config.g_steady_power_levels_enabled, config.g_power_per_cycle_dump, - config.gpu_steady_power_deviation, config.gpu_steady_min_period, - config.g_power_trace_zlevel, tot_inst + inst, stat_sample_freq); +void init_mcpat(const gpgpu_sim_config &config, class gpgpu_sim_wrapper *wrapper, unsigned stat_sample_freq, unsigned tot_inst, unsigned inst){ + + wrapper->init_mcpat(config.g_power_config_name, config.g_power_filename, config.g_power_trace_filename, + config.g_metric_trace_filename,config.g_steady_state_tracking_filename,config.g_power_simulation_enabled, + config.g_power_trace_enabled,config.g_steady_power_levels_enabled,config.g_power_per_cycle_dump, + config.gpu_steady_power_deviation,config.gpu_steady_min_period,config.g_power_trace_zlevel, + tot_inst+inst,stat_sample_freq + ); + } -void mcpat_cycle(const gpgpu_sim_config &config, - const shader_core_config *shdr_config, - class gpgpu_sim_wrapper *wrapper, - class power_stat_t *power_stats, unsigned stat_sample_freq, - unsigned tot_cycle, unsigned cycle, unsigned tot_inst, - unsigned inst) { - static bool mcpat_init = true; +void mcpat_cycle(const gpgpu_sim_config &config, const shader_core_config *shdr_config, class gpgpu_sim_wrapper *wrapper, class power_stat_t *power_stats, unsigned stat_sample_freq, unsigned tot_cycle, unsigned cycle, unsigned tot_inst, unsigned inst){ + + static bool mcpat_init=true; + + if(mcpat_init){ // If first cycle, don't have any power numbers yet + mcpat_init=false; + return; + } + + if ((tot_cycle+cycle) % stat_sample_freq == 0) { + + wrapper->set_inst_power(shdr_config->gpgpu_clock_gated_lanes, + stat_sample_freq, stat_sample_freq, + power_stats->get_total_inst(), power_stats->get_total_int_inst(), + power_stats->get_total_fp_inst(), power_stats->get_l1d_read_accesses(), + power_stats->get_l1d_write_accesses(), power_stats->get_committed_inst()); + + // Single RF for both int and fp ops + wrapper->set_regfile_power(power_stats->get_regfile_reads(), power_stats->get_regfile_writes(), power_stats->get_non_regfile_operands()); + + //Instruction cache stats + wrapper->set_icache_power(power_stats->get_inst_c_hits(), power_stats->get_inst_c_misses()); + + //Constant Cache, shared memory, texture cache + wrapper->set_ccache_power(power_stats->get_constant_c_hits(), power_stats->get_constant_c_misses()); + wrapper->set_tcache_power(power_stats->get_texture_c_hits(), power_stats->get_texture_c_misses()); + wrapper->set_shrd_mem_power(power_stats->get_shmem_read_access()); - if (mcpat_init) { // If first cycle, don't have any power numbers yet - mcpat_init = false; - return; - } + wrapper->set_l1cache_power(power_stats->get_l1d_read_hits(), power_stats->get_l1d_read_misses(), + power_stats->get_l1d_write_hits(), power_stats->get_l1d_write_misses()); - if ((tot_cycle + cycle) % stat_sample_freq == 0) { - wrapper->set_inst_power( - shdr_config->gpgpu_clock_gated_lanes, stat_sample_freq, - stat_sample_freq, power_stats->get_total_inst(), - power_stats->get_total_int_inst(), power_stats->get_total_fp_inst(), - power_stats->get_l1d_read_accesses(), - power_stats->get_l1d_write_accesses(), - power_stats->get_committed_inst()); - // Single RF for both int and fp ops - wrapper->set_regfile_power(power_stats->get_regfile_reads(), - power_stats->get_regfile_writes(), - power_stats->get_non_regfile_operands()); + wrapper->set_l2cache_power(power_stats->get_l2_read_hits(), power_stats->get_l2_read_misses(), + power_stats->get_l2_write_hits(), power_stats->get_l2_write_misses()); - // Instruction cache stats - wrapper->set_icache_power(power_stats->get_inst_c_hits(), - power_stats->get_inst_c_misses()); - // Constant Cache, shared memory, texture cache - wrapper->set_ccache_power(power_stats->get_constant_c_hits(), - power_stats->get_constant_c_misses()); - wrapper->set_tcache_power(power_stats->get_texture_c_hits(), - power_stats->get_texture_c_misses()); - wrapper->set_shrd_mem_power(power_stats->get_shmem_read_access()); + float active_sms=(*power_stats->m_active_sms)/stat_sample_freq; + float num_cores = shdr_config->num_shader(); + float num_idle_core = num_cores - active_sms; + wrapper->set_idle_core_power(num_idle_core); - wrapper->set_l1cache_power( - power_stats->get_l1d_read_hits(), power_stats->get_l1d_read_misses(), - power_stats->get_l1d_write_hits(), power_stats->get_l1d_write_misses()); + //pipeline power - pipeline_duty_cycle *= percent_active_sms; + float pipeline_duty_cycle=((*power_stats->m_average_pipeline_duty_cycle/( stat_sample_freq)) < 0.8)?((*power_stats->m_average_pipeline_duty_cycle)/stat_sample_freq):0.8; + wrapper->set_duty_cycle_power(pipeline_duty_cycle); - wrapper->set_l2cache_power( - power_stats->get_l2_read_hits(), power_stats->get_l2_read_misses(), - power_stats->get_l2_write_hits(), power_stats->get_l2_write_misses()); + //Memory Controller + wrapper->set_mem_ctrl_power(power_stats->get_dram_rd(), power_stats->get_dram_wr(), power_stats->get_dram_pre()); - float active_sms = (*power_stats->m_active_sms) / stat_sample_freq; - float num_cores = shdr_config->num_shader(); - float num_idle_core = num_cores - active_sms; - wrapper->set_idle_core_power(num_idle_core); + //Execution pipeline accesses + //FPU (SP) accesses, Integer ALU (not present in Tesla), Sfu accesses + wrapper->set_exec_unit_power(power_stats->get_tot_fpu_accessess(), power_stats->get_ialu_accessess(), power_stats->get_tot_sfu_accessess()); - // pipeline power - pipeline_duty_cycle *= percent_active_sms; - float pipeline_duty_cycle = - ((*power_stats->m_average_pipeline_duty_cycle / (stat_sample_freq)) < - 0.8) - ? ((*power_stats->m_average_pipeline_duty_cycle) / stat_sample_freq) - : 0.8; - wrapper->set_duty_cycle_power(pipeline_duty_cycle); + //Average active lanes for sp and sfu pipelines + float avg_sp_active_lanes=(power_stats->get_sp_active_lanes())/stat_sample_freq; + float avg_sfu_active_lanes=(power_stats->get_sfu_active_lanes())/stat_sample_freq; + assert(avg_sp_active_lanes<=32); + assert(avg_sfu_active_lanes<=32); + wrapper->set_active_lanes_power((power_stats->get_sp_active_lanes())/stat_sample_freq, + (power_stats->get_sfu_active_lanes())/stat_sample_freq); - // Memory Controller - wrapper->set_mem_ctrl_power(power_stats->get_dram_rd(), - power_stats->get_dram_wr(), - power_stats->get_dram_pre()); - // Execution pipeline accesses - // FPU (SP) accesses, Integer ALU (not present in Tesla), Sfu accesses - wrapper->set_exec_unit_power(power_stats->get_tot_fpu_accessess(), - power_stats->get_ialu_accessess(), - power_stats->get_tot_sfu_accessess()); + double n_icnt_simt_to_mem = (double)power_stats->get_icnt_simt_to_mem(); // # flits from SIMT clusters to memory partitions + double n_icnt_mem_to_simt = (double)power_stats->get_icnt_mem_to_simt(); // # flits from memory partitions to SIMT clusters + wrapper->set_NoC_power(n_icnt_mem_to_simt, n_icnt_simt_to_mem); // Number of flits traversing the interconnect - // Average active lanes for sp and sfu pipelines - float avg_sp_active_lanes = - (power_stats->get_sp_active_lanes()) / stat_sample_freq; - float avg_sfu_active_lanes = - (power_stats->get_sfu_active_lanes()) / stat_sample_freq; - assert(avg_sp_active_lanes <= 32); - assert(avg_sfu_active_lanes <= 32); - wrapper->set_active_lanes_power( - (power_stats->get_sp_active_lanes()) / stat_sample_freq, - (power_stats->get_sfu_active_lanes()) / stat_sample_freq); + wrapper->compute(); - double n_icnt_simt_to_mem = - (double)power_stats->get_icnt_simt_to_mem(); // # flits from SIMT - // clusters to memory - // partitions - double n_icnt_mem_to_simt = - (double)power_stats->get_icnt_mem_to_simt(); // # flits from memory - // partitions to SIMT - // clusters - wrapper->set_NoC_power( - n_icnt_mem_to_simt, - n_icnt_simt_to_mem); // Number of flits traversing the interconnect - wrapper->compute(); + wrapper->update_components_power(); + wrapper->print_trace_files(); + power_stats->save_stats(); - wrapper->update_components_power(); - wrapper->print_trace_files(); - power_stats->save_stats(); + wrapper->detect_print_steady_state(0,tot_inst+inst); - wrapper->detect_print_steady_state(0, tot_inst + inst); + wrapper->power_metrics_calculations(); - wrapper->power_metrics_calculations(); - wrapper->dump(); - } - // wrapper->close_files(); + wrapper->dump(); + } + //wrapper->close_files(); } -void mcpat_reset_perf_count(class gpgpu_sim_wrapper *wrapper) { - wrapper->reset_counters(); +void mcpat_reset_perf_count(class gpgpu_sim_wrapper *wrapper){ + wrapper->reset_counters(); } diff --git a/src/gpgpu-sim/power_interface.h b/src/gpgpu-sim/power_interface.h index 654ca5a..a388c23 100644 --- a/src/gpgpu-sim/power_interface.h +++ b/src/gpgpu-sim/power_interface.h @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -34,17 +32,12 @@ #include "power_stat.h" #include "shader.h" + #include "gpgpu_sim_wrapper.h" -void init_mcpat(const gpgpu_sim_config &config, - class gpgpu_sim_wrapper *wrapper, unsigned stat_sample_freq, - unsigned tot_inst, unsigned inst); -void mcpat_cycle(const gpgpu_sim_config &config, - const shader_core_config *shdr_config, - class gpgpu_sim_wrapper *wrapper, - class power_stat_t *power_stats, unsigned stat_sample_freq, - unsigned tot_cycle, unsigned cycle, unsigned tot_inst, - unsigned inst); +void init_mcpat(const gpgpu_sim_config &config, class gpgpu_sim_wrapper *wrapper, unsigned stat_sample_freq, unsigned tot_inst, unsigned inst); +void mcpat_cycle(const gpgpu_sim_config &config, const shader_core_config *shdr_config, class gpgpu_sim_wrapper *wrapper, class power_stat_t *power_stats, + unsigned stat_sample_freq, unsigned tot_cycle, unsigned cycle, unsigned tot_inst, unsigned inst); void mcpat_reset_perf_count(class gpgpu_sim_wrapper *wrapper); #endif /* POWER_INTERFACE_H_ */ diff --git a/src/gpgpu-sim/power_stat.cc b/src/gpgpu-sim/power_stat.cc index 27e61db..2c02082 100644 --- a/src/gpgpu-sim/power_stat.cc +++ b/src/gpgpu-sim/power_stat.cc @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -27,346 +25,269 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include "power_stat.h" #include "../abstract_hardware_model.h" -#include "../cuda-sim/ptx-stats.h" -#include "dram.h" -#include "gpu-misc.h" +#include "power_stat.h" #include "gpu-sim.h" -#include "mem_fetch.h" +#include "gpu-misc.h" #include "shader.h" +#include "mem_fetch.h" #include "stat-tool.h" +#include "../cuda-sim/ptx-stats.h" #include "visualizer.h" +#include "dram.h" -#include <stdio.h> -#include <stdlib.h> #include <string.h> +#include <stdlib.h> +#include <stdio.h> + -power_mem_stat_t::power_mem_stat_t(const memory_config *mem_config, - const shader_core_config *shdr_config, - memory_stats_t *mem_stats, - shader_core_stats *shdr_stats) { - assert(mem_config->m_valid); - m_mem_stats = mem_stats; - m_config = mem_config; - m_core_stats = shdr_stats; - m_core_config = shdr_config; - init(); +power_mem_stat_t::power_mem_stat_t(const memory_config *mem_config, const shader_core_config *shdr_config, memory_stats_t *mem_stats, shader_core_stats *shdr_stats){ + assert( mem_config->m_valid ); + m_mem_stats = mem_stats; + m_config = mem_config; + m_core_stats = shdr_stats; + m_core_config = shdr_config; + + init(); } -void power_mem_stat_t::init() { - shmem_read_access[CURRENT_STAT_IDX] = - m_core_stats->gpgpu_n_shmem_bank_access; // Shared memory access - shmem_read_access[PREV_STAT_IDX] = - (unsigned *)calloc(m_core_config->num_shader(), sizeof(unsigned)); +void power_mem_stat_t::init(){ + + shmem_read_access[CURRENT_STAT_IDX] = m_core_stats->gpgpu_n_shmem_bank_access; // Shared memory access + shmem_read_access[PREV_STAT_IDX] = (unsigned *)calloc(m_core_config->num_shader(),sizeof(unsigned)); - for (unsigned i = 0; i < NUM_STAT_IDX; ++i) { - core_cache_stats[i].clear(); - l2_cache_stats[i].clear(); + for(unsigned i=0; i<NUM_STAT_IDX; ++i){ + core_cache_stats[i].clear(); + l2_cache_stats[i].clear(); - n_cmd[i] = (unsigned *)calloc(m_config->m_n_mem, sizeof(unsigned)); - n_activity[i] = (unsigned *)calloc(m_config->m_n_mem, sizeof(unsigned)); - n_nop[i] = (unsigned *)calloc(m_config->m_n_mem, sizeof(unsigned)); - n_act[i] = (unsigned *)calloc(m_config->m_n_mem, sizeof(unsigned)); - n_pre[i] = (unsigned *)calloc(m_config->m_n_mem, sizeof(unsigned)); - n_rd[i] = (unsigned *)calloc(m_config->m_n_mem, sizeof(unsigned)); - n_wr[i] = (unsigned *)calloc(m_config->m_n_mem, sizeof(unsigned)); - n_req[i] = (unsigned *)calloc(m_config->m_n_mem, sizeof(unsigned)); + n_cmd[i] = (unsigned *)calloc(m_config->m_n_mem,sizeof(unsigned)); + n_activity[i] = (unsigned *)calloc(m_config->m_n_mem,sizeof(unsigned)); + n_nop[i] = (unsigned *)calloc(m_config->m_n_mem,sizeof(unsigned)); + n_act[i] = (unsigned *)calloc(m_config->m_n_mem,sizeof(unsigned)); + n_pre[i] = (unsigned *)calloc(m_config->m_n_mem,sizeof(unsigned)); + n_rd[i] = (unsigned *)calloc(m_config->m_n_mem,sizeof(unsigned)); + n_wr[i] = (unsigned *)calloc(m_config->m_n_mem,sizeof(unsigned)); + n_req[i] = (unsigned *)calloc(m_config->m_n_mem,sizeof(unsigned)); - // Interconnect stats - n_mem_to_simt[i] = (long *)calloc(m_core_config->n_simt_clusters, - sizeof(long)); // Counted at SM - n_simt_to_mem[i] = (long *)calloc(m_core_config->n_simt_clusters, - sizeof(long)); // Counted at SM - } + // Interconnect stats + n_mem_to_simt[i] = (long *)calloc(m_core_config->n_simt_clusters,sizeof(long)); // Counted at SM + n_simt_to_mem[i] = (long *)calloc(m_core_config->n_simt_clusters,sizeof(long)); // Counted at SM + } } -void power_mem_stat_t::save_stats() { - core_cache_stats[PREV_STAT_IDX] = core_cache_stats[CURRENT_STAT_IDX]; - l2_cache_stats[PREV_STAT_IDX] = l2_cache_stats[CURRENT_STAT_IDX]; +void power_mem_stat_t::save_stats(){ - for (unsigned i = 0; i < m_core_config->num_shader(); ++i) { - shmem_read_access[PREV_STAT_IDX][i] = - shmem_read_access[CURRENT_STAT_IDX][i]; // Shared memory access - } + core_cache_stats[PREV_STAT_IDX] = core_cache_stats[CURRENT_STAT_IDX]; + l2_cache_stats[PREV_STAT_IDX] = l2_cache_stats[CURRENT_STAT_IDX]; - for (unsigned i = 0; i < m_config->m_n_mem; ++i) { - n_cmd[PREV_STAT_IDX][i] = n_cmd[CURRENT_STAT_IDX][i]; - n_activity[PREV_STAT_IDX][i] = n_activity[CURRENT_STAT_IDX][i]; - n_nop[PREV_STAT_IDX][i] = n_nop[CURRENT_STAT_IDX][i]; - n_act[PREV_STAT_IDX][i] = n_act[CURRENT_STAT_IDX][i]; - n_pre[PREV_STAT_IDX][i] = n_pre[CURRENT_STAT_IDX][i]; - n_rd[PREV_STAT_IDX][i] = n_rd[CURRENT_STAT_IDX][i]; - n_wr[PREV_STAT_IDX][i] = n_wr[CURRENT_STAT_IDX][i]; - n_req[PREV_STAT_IDX][i] = n_req[CURRENT_STAT_IDX][i]; - } + for(unsigned i=0; i<m_core_config->num_shader(); ++i){ + shmem_read_access[PREV_STAT_IDX][i] = shmem_read_access[CURRENT_STAT_IDX][i] ; // Shared memory access + } - for (unsigned i = 0; i < m_core_config->n_simt_clusters; i++) { - n_simt_to_mem[PREV_STAT_IDX][i] = - n_simt_to_mem[CURRENT_STAT_IDX][i]; // Interconnect - n_mem_to_simt[PREV_STAT_IDX][i] = - n_mem_to_simt[CURRENT_STAT_IDX][i]; // Interconnect - } + for(unsigned i=0; i<m_config->m_n_mem; ++i){ + n_cmd[PREV_STAT_IDX][i] = n_cmd[CURRENT_STAT_IDX][i]; + n_activity[PREV_STAT_IDX][i] = n_activity[CURRENT_STAT_IDX][i]; + n_nop[PREV_STAT_IDX][i] = n_nop[CURRENT_STAT_IDX][i]; + n_act[PREV_STAT_IDX][i] = n_act[CURRENT_STAT_IDX][i]; + n_pre[PREV_STAT_IDX][i] = n_pre[CURRENT_STAT_IDX][i]; + n_rd[PREV_STAT_IDX][i] = n_rd[CURRENT_STAT_IDX][i]; + n_wr[PREV_STAT_IDX][i] = n_wr[CURRENT_STAT_IDX][i]; + n_req[PREV_STAT_IDX][i] = n_req[CURRENT_STAT_IDX][i]; + } + + for(unsigned i=0; i<m_core_config->n_simt_clusters;i++){ + n_simt_to_mem[PREV_STAT_IDX][i] = n_simt_to_mem[CURRENT_STAT_IDX][i]; // Interconnect + n_mem_to_simt[PREV_STAT_IDX][i] = n_mem_to_simt[CURRENT_STAT_IDX][i]; // Interconnect + } } -void power_mem_stat_t::visualizer_print(gzFile power_visualizer_file) {} +void power_mem_stat_t::visualizer_print( gzFile power_visualizer_file ){ + +} -void power_mem_stat_t::print(FILE *fout) const { - fprintf(fout, "\n\n==========Power Metrics -- Memory==========\n"); - unsigned total_mem_reads = 0; - unsigned total_mem_writes = 0; - for (unsigned i = 0; i < m_config->m_n_mem; ++i) { - total_mem_reads += n_rd[CURRENT_STAT_IDX][i]; - total_mem_writes += n_wr[CURRENT_STAT_IDX][i]; - } - fprintf(fout, "Total memory controller accesses: %u\n", - total_mem_reads + total_mem_writes); - fprintf(fout, "Total memory controller reads: %u\n", total_mem_reads); - fprintf(fout, "Total memory controller writes: %u\n", total_mem_writes); +void power_mem_stat_t::print (FILE *fout) const { + fprintf(fout, "\n\n==========Power Metrics -- Memory==========\n"); + unsigned total_mem_reads=0; + unsigned total_mem_writes=0; + for(unsigned i=0; i<m_config->m_n_mem; ++i){ + total_mem_reads += n_rd[CURRENT_STAT_IDX][i]; + total_mem_writes += n_wr[CURRENT_STAT_IDX][i]; + } + fprintf(fout, "Total memory controller accesses: %u\n", total_mem_reads+total_mem_writes); + fprintf(fout, "Total memory controller reads: %u\n", total_mem_reads); + fprintf(fout, "Total memory controller writes: %u\n", total_mem_writes); - fprintf(fout, "Core cache stats:\n"); - core_cache_stats->print_stats(fout); - fprintf(fout, "L2 cache stats:\n"); - l2_cache_stats->print_stats(fout); + fprintf(fout, "Core cache stats:\n"); + core_cache_stats->print_stats(fout); + fprintf(fout, "L2 cache stats:\n"); + l2_cache_stats->print_stats(fout); } -power_core_stat_t::power_core_stat_t(const shader_core_config *shader_config, - shader_core_stats *core_stats) { - assert(shader_config->m_valid); - m_config = shader_config; - shader_core_power_stats_pod *pod = this; - memset(pod, 0, sizeof(shader_core_power_stats_pod)); - m_core_stats = core_stats; - init(); +power_core_stat_t::power_core_stat_t( const shader_core_config *shader_config, shader_core_stats *core_stats ) +{ + assert( shader_config->m_valid ); + m_config = shader_config; + shader_core_power_stats_pod *pod = this; + memset(pod,0,sizeof(shader_core_power_stats_pod)); + m_core_stats=core_stats; + + init(); + } -void power_core_stat_t::visualizer_print(gzFile visualizer_file) {} +void power_core_stat_t::visualizer_print( gzFile visualizer_file ) +{ + +} -void power_core_stat_t::print(FILE *fout) { - // per core statistics - fprintf(fout, "Power Metrics: \n"); - for (unsigned i = 0; i < m_config->num_shader(); i++) { - fprintf(fout, "core %u:\n", i); - fprintf(fout, "\tpipeline duty cycle =%f\n", - m_pipeline_duty_cycle[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal Deocded Instructions=%u\n", - m_num_decoded_insn[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal FP Deocded Instructions=%u\n", - m_num_FPdecoded_insn[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal INT Deocded Instructions=%u\n", - m_num_INTdecoded_insn[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal LOAD Queued Instructions=%u\n", - m_num_loadqueued_insn[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal STORE Queued Instructions=%u\n", - m_num_storequeued_insn[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal IALU Acesses=%u\n", - m_num_ialu_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal FP Acesses=%u\n", - m_num_fp_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal IMUL Acesses=%u\n", - m_num_imul_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal IMUL24 Acesses=%u\n", - m_num_imul24_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal IMUL32 Acesses=%u\n", - m_num_imul32_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal IDIV Acesses=%u\n", - m_num_idiv_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal FPMUL Acesses=%u\n", - m_num_fpmul_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal SFU Acesses=%u\n", - m_num_trans_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal FPDIV Acesses=%u\n", - m_num_fpdiv_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal SFU Acesses=%u\n", - m_num_sfu_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal SP Acesses=%u\n", - m_num_sp_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal MEM Acesses=%u\n", - m_num_mem_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal SFU Commissions=%u\n", - m_num_sfu_committed[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal SP Commissions=%u\n", - m_num_sp_committed[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal MEM Commissions=%u\n", - m_num_mem_committed[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal REG Reads=%u\n", - m_read_regfile_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal REG Writes=%u\n", - m_write_regfile_acesses[CURRENT_STAT_IDX][i]); - fprintf(fout, "\tTotal NON REG=%u\n", - m_non_rf_operands[CURRENT_STAT_IDX][i]); - } +void power_core_stat_t::print (FILE *fout) +{ + // per core statistics + fprintf(fout,"Power Metrics: \n"); + for(unsigned i=0; i<m_config->num_shader();i++){ + fprintf(fout,"core %u:\n",i); + fprintf(fout,"\tpipeline duty cycle =%f\n",m_pipeline_duty_cycle[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal Deocded Instructions=%u\n",m_num_decoded_insn[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal FP Deocded Instructions=%u\n",m_num_FPdecoded_insn[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal INT Deocded Instructions=%u\n",m_num_INTdecoded_insn[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal LOAD Queued Instructions=%u\n",m_num_loadqueued_insn[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal STORE Queued Instructions=%u\n",m_num_storequeued_insn[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal IALU Acesses=%u\n",m_num_ialu_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal FP Acesses=%u\n",m_num_fp_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal IMUL Acesses=%u\n",m_num_imul_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal IMUL24 Acesses=%u\n",m_num_imul24_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal IMUL32 Acesses=%u\n",m_num_imul32_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal IDIV Acesses=%u\n",m_num_idiv_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal FPMUL Acesses=%u\n",m_num_fpmul_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal SFU Acesses=%u\n",m_num_trans_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal FPDIV Acesses=%u\n",m_num_fpdiv_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal SFU Acesses=%u\n",m_num_sfu_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal SP Acesses=%u\n",m_num_sp_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal MEM Acesses=%u\n",m_num_mem_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal SFU Commissions=%u\n",m_num_sfu_committed[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal SP Commissions=%u\n",m_num_sp_committed[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal MEM Commissions=%u\n",m_num_mem_committed[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal REG Reads=%u\n",m_read_regfile_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal REG Writes=%u\n",m_write_regfile_acesses[CURRENT_STAT_IDX][i]); + fprintf(fout,"\tTotal NON REG=%u\n",m_non_rf_operands[CURRENT_STAT_IDX][i]); + } } -void power_core_stat_t::init() { - m_pipeline_duty_cycle[CURRENT_STAT_IDX] = m_core_stats->m_pipeline_duty_cycle; - m_num_decoded_insn[CURRENT_STAT_IDX] = m_core_stats->m_num_decoded_insn; - m_num_FPdecoded_insn[CURRENT_STAT_IDX] = m_core_stats->m_num_FPdecoded_insn; - m_num_INTdecoded_insn[CURRENT_STAT_IDX] = m_core_stats->m_num_INTdecoded_insn; - m_num_storequeued_insn[CURRENT_STAT_IDX] = - m_core_stats->m_num_storequeued_insn; - m_num_loadqueued_insn[CURRENT_STAT_IDX] = m_core_stats->m_num_loadqueued_insn; - m_num_ialu_acesses[CURRENT_STAT_IDX] = m_core_stats->m_num_ialu_acesses; - m_num_fp_acesses[CURRENT_STAT_IDX] = m_core_stats->m_num_fp_acesses; - m_num_imul_acesses[CURRENT_STAT_IDX] = m_core_stats->m_num_imul_acesses; - m_num_imul24_acesses[CURRENT_STAT_IDX] = m_core_stats->m_num_imul24_acesses; - m_num_imul32_acesses[CURRENT_STAT_IDX] = m_core_stats->m_num_imul32_acesses; - m_num_fpmul_acesses[CURRENT_STAT_IDX] = m_core_stats->m_num_fpmul_acesses; - m_num_idiv_acesses[CURRENT_STAT_IDX] = m_core_stats->m_num_idiv_acesses; - m_num_fpdiv_acesses[CURRENT_STAT_IDX] = m_core_stats->m_num_fpdiv_acesses; - m_num_sp_acesses[CURRENT_STAT_IDX] = m_core_stats->m_num_sp_acesses; - m_num_sfu_acesses[CURRENT_STAT_IDX] = m_core_stats->m_num_sfu_acesses; - m_num_trans_acesses[CURRENT_STAT_IDX] = m_core_stats->m_num_trans_acesses; - m_num_mem_acesses[CURRENT_STAT_IDX] = m_core_stats->m_num_mem_acesses; - m_num_sp_committed[CURRENT_STAT_IDX] = m_core_stats->m_num_sp_committed; - m_num_sfu_committed[CURRENT_STAT_IDX] = m_core_stats->m_num_sfu_committed; - m_num_mem_committed[CURRENT_STAT_IDX] = m_core_stats->m_num_mem_committed; - m_read_regfile_acesses[CURRENT_STAT_IDX] = - m_core_stats->m_read_regfile_acesses; - m_write_regfile_acesses[CURRENT_STAT_IDX] = - m_core_stats->m_write_regfile_acesses; - m_non_rf_operands[CURRENT_STAT_IDX] = m_core_stats->m_non_rf_operands; - m_active_sp_lanes[CURRENT_STAT_IDX] = m_core_stats->m_active_sp_lanes; - m_active_sfu_lanes[CURRENT_STAT_IDX] = m_core_stats->m_active_sfu_lanes; - m_num_tex_inst[CURRENT_STAT_IDX] = m_core_stats->m_num_tex_inst; +void power_core_stat_t::init() +{ + m_pipeline_duty_cycle[CURRENT_STAT_IDX]=m_core_stats->m_pipeline_duty_cycle; + m_num_decoded_insn[CURRENT_STAT_IDX]=m_core_stats->m_num_decoded_insn; + m_num_FPdecoded_insn[CURRENT_STAT_IDX]=m_core_stats->m_num_FPdecoded_insn; + m_num_INTdecoded_insn[CURRENT_STAT_IDX]=m_core_stats->m_num_INTdecoded_insn; + m_num_storequeued_insn[CURRENT_STAT_IDX]=m_core_stats->m_num_storequeued_insn; + m_num_loadqueued_insn[CURRENT_STAT_IDX]=m_core_stats->m_num_loadqueued_insn; + m_num_ialu_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_ialu_acesses; + m_num_fp_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_fp_acesses; + m_num_imul_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_imul_acesses; + m_num_imul24_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_imul24_acesses; + m_num_imul32_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_imul32_acesses; + m_num_fpmul_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_fpmul_acesses; + m_num_idiv_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_idiv_acesses; + m_num_fpdiv_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_fpdiv_acesses; + m_num_sp_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_sp_acesses; + m_num_sfu_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_sfu_acesses; + m_num_trans_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_trans_acesses; + m_num_mem_acesses[CURRENT_STAT_IDX]=m_core_stats->m_num_mem_acesses; + m_num_sp_committed[CURRENT_STAT_IDX]=m_core_stats->m_num_sp_committed; + m_num_sfu_committed[CURRENT_STAT_IDX]=m_core_stats->m_num_sfu_committed; + m_num_mem_committed[CURRENT_STAT_IDX]=m_core_stats->m_num_mem_committed; + m_read_regfile_acesses[CURRENT_STAT_IDX]=m_core_stats->m_read_regfile_acesses; + m_write_regfile_acesses[CURRENT_STAT_IDX]=m_core_stats->m_write_regfile_acesses; + m_non_rf_operands[CURRENT_STAT_IDX]=m_core_stats->m_non_rf_operands; + m_active_sp_lanes[CURRENT_STAT_IDX]=m_core_stats->m_active_sp_lanes; + m_active_sfu_lanes[CURRENT_STAT_IDX]=m_core_stats->m_active_sfu_lanes; + m_num_tex_inst[CURRENT_STAT_IDX]=m_core_stats->m_num_tex_inst; + - m_pipeline_duty_cycle[PREV_STAT_IDX] = - (float *)calloc(m_config->num_shader(), sizeof(float)); - m_num_decoded_insn[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_FPdecoded_insn[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_INTdecoded_insn[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_storequeued_insn[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_loadqueued_insn[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_ialu_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_fp_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_tex_inst[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_imul_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_imul24_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_imul32_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_fpmul_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_idiv_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_fpdiv_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_sp_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_sfu_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_trans_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_mem_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_sp_committed[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_sfu_committed[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_num_mem_committed[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_read_regfile_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_write_regfile_acesses[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_non_rf_operands[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_active_sp_lanes[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); - m_active_sfu_lanes[PREV_STAT_IDX] = - (unsigned *)calloc(m_config->num_shader(), sizeof(unsigned)); + m_pipeline_duty_cycle[PREV_STAT_IDX]=(float*)calloc(m_config->num_shader(),sizeof(float)); + m_num_decoded_insn[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_FPdecoded_insn[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_INTdecoded_insn[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_storequeued_insn[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_loadqueued_insn[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_ialu_acesses[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_fp_acesses[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_tex_inst[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_imul_acesses[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_imul24_acesses[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_imul32_acesses[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_fpmul_acesses[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_idiv_acesses[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_fpdiv_acesses[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_sp_acesses[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_sfu_acesses[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_trans_acesses[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_mem_acesses[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_sp_committed[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_sfu_committed[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_num_mem_committed[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_read_regfile_acesses[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_write_regfile_acesses[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_non_rf_operands[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_active_sp_lanes[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); + m_active_sfu_lanes[PREV_STAT_IDX]=(unsigned *)calloc(m_config->num_shader(),sizeof(unsigned)); } -void power_core_stat_t::save_stats() { - for (unsigned i = 0; i < m_config->num_shader(); ++i) { - m_pipeline_duty_cycle[PREV_STAT_IDX][i] = - m_pipeline_duty_cycle[CURRENT_STAT_IDX][i]; - m_num_decoded_insn[PREV_STAT_IDX][i] = - m_num_decoded_insn[CURRENT_STAT_IDX][i]; - m_num_FPdecoded_insn[PREV_STAT_IDX][i] = - m_num_FPdecoded_insn[CURRENT_STAT_IDX][i]; - m_num_INTdecoded_insn[PREV_STAT_IDX][i] = - m_num_INTdecoded_insn[CURRENT_STAT_IDX][i]; - m_num_storequeued_insn[PREV_STAT_IDX][i] = - m_num_storequeued_insn[CURRENT_STAT_IDX][i]; - m_num_loadqueued_insn[PREV_STAT_IDX][i] = - m_num_loadqueued_insn[CURRENT_STAT_IDX][i]; - m_num_ialu_acesses[PREV_STAT_IDX][i] = - m_num_ialu_acesses[CURRENT_STAT_IDX][i]; - m_num_fp_acesses[PREV_STAT_IDX][i] = m_num_fp_acesses[CURRENT_STAT_IDX][i]; - m_num_tex_inst[PREV_STAT_IDX][i] = m_num_tex_inst[CURRENT_STAT_IDX][i]; - m_num_imul_acesses[PREV_STAT_IDX][i] = - m_num_imul_acesses[CURRENT_STAT_IDX][i]; - m_num_imul24_acesses[PREV_STAT_IDX][i] = - m_num_imul24_acesses[CURRENT_STAT_IDX][i]; - m_num_imul32_acesses[PREV_STAT_IDX][i] = - m_num_imul32_acesses[CURRENT_STAT_IDX][i]; - m_num_fpmul_acesses[PREV_STAT_IDX][i] = - m_num_fpmul_acesses[CURRENT_STAT_IDX][i]; - m_num_idiv_acesses[PREV_STAT_IDX][i] = - m_num_idiv_acesses[CURRENT_STAT_IDX][i]; - m_num_fpdiv_acesses[PREV_STAT_IDX][i] = - m_num_fpdiv_acesses[CURRENT_STAT_IDX][i]; - m_num_sp_acesses[PREV_STAT_IDX][i] = m_num_sp_acesses[CURRENT_STAT_IDX][i]; - m_num_sfu_acesses[PREV_STAT_IDX][i] = - m_num_sfu_acesses[CURRENT_STAT_IDX][i]; - m_num_trans_acesses[PREV_STAT_IDX][i] = - m_num_trans_acesses[CURRENT_STAT_IDX][i]; - m_num_mem_acesses[PREV_STAT_IDX][i] = - m_num_mem_acesses[CURRENT_STAT_IDX][i]; - m_num_sp_committed[PREV_STAT_IDX][i] = - m_num_sp_committed[CURRENT_STAT_IDX][i]; - m_num_sfu_committed[PREV_STAT_IDX][i] = - m_num_sfu_committed[CURRENT_STAT_IDX][i]; - m_num_mem_committed[PREV_STAT_IDX][i] = - m_num_mem_committed[CURRENT_STAT_IDX][i]; - m_read_regfile_acesses[PREV_STAT_IDX][i] = - m_read_regfile_acesses[CURRENT_STAT_IDX][i]; - m_write_regfile_acesses[PREV_STAT_IDX][i] = - m_write_regfile_acesses[CURRENT_STAT_IDX][i]; - m_non_rf_operands[PREV_STAT_IDX][i] = - m_non_rf_operands[CURRENT_STAT_IDX][i]; - m_active_sp_lanes[PREV_STAT_IDX][i] = - m_active_sp_lanes[CURRENT_STAT_IDX][i]; - m_active_sfu_lanes[PREV_STAT_IDX][i] = - m_active_sfu_lanes[CURRENT_STAT_IDX][i]; - } +void power_core_stat_t::save_stats(){ +for(unsigned i=0; i<m_config->num_shader(); ++i){ + m_pipeline_duty_cycle[PREV_STAT_IDX][i]=m_pipeline_duty_cycle[CURRENT_STAT_IDX][i]; + m_num_decoded_insn[PREV_STAT_IDX][i]= m_num_decoded_insn[CURRENT_STAT_IDX][i]; + m_num_FPdecoded_insn[PREV_STAT_IDX][i]=m_num_FPdecoded_insn[CURRENT_STAT_IDX][i]; + m_num_INTdecoded_insn[PREV_STAT_IDX][i]=m_num_INTdecoded_insn[CURRENT_STAT_IDX][i]; + m_num_storequeued_insn[PREV_STAT_IDX][i]=m_num_storequeued_insn[CURRENT_STAT_IDX][i]; + m_num_loadqueued_insn[PREV_STAT_IDX][i]=m_num_loadqueued_insn[CURRENT_STAT_IDX][i]; + m_num_ialu_acesses[PREV_STAT_IDX][i]=m_num_ialu_acesses[CURRENT_STAT_IDX][i]; + m_num_fp_acesses[PREV_STAT_IDX][i]=m_num_fp_acesses[CURRENT_STAT_IDX][i]; + m_num_tex_inst[PREV_STAT_IDX][i]=m_num_tex_inst[CURRENT_STAT_IDX][i]; + m_num_imul_acesses[PREV_STAT_IDX][i]=m_num_imul_acesses[CURRENT_STAT_IDX][i]; + m_num_imul24_acesses[PREV_STAT_IDX][i]=m_num_imul24_acesses[CURRENT_STAT_IDX][i]; + m_num_imul32_acesses[PREV_STAT_IDX][i]=m_num_imul32_acesses[CURRENT_STAT_IDX][i]; + m_num_fpmul_acesses[PREV_STAT_IDX][i]=m_num_fpmul_acesses[CURRENT_STAT_IDX][i]; + m_num_idiv_acesses[PREV_STAT_IDX][i]=m_num_idiv_acesses[CURRENT_STAT_IDX][i]; + m_num_fpdiv_acesses[PREV_STAT_IDX][i]=m_num_fpdiv_acesses[CURRENT_STAT_IDX][i]; + m_num_sp_acesses[PREV_STAT_IDX][i]=m_num_sp_acesses[CURRENT_STAT_IDX][i]; + m_num_sfu_acesses[PREV_STAT_IDX][i]=m_num_sfu_acesses[CURRENT_STAT_IDX][i]; + m_num_trans_acesses[PREV_STAT_IDX][i]=m_num_trans_acesses[CURRENT_STAT_IDX][i]; + m_num_mem_acesses[PREV_STAT_IDX][i]=m_num_mem_acesses[CURRENT_STAT_IDX][i]; + m_num_sp_committed[PREV_STAT_IDX][i]=m_num_sp_committed[CURRENT_STAT_IDX][i]; + m_num_sfu_committed[PREV_STAT_IDX][i]=m_num_sfu_committed[CURRENT_STAT_IDX][i]; + m_num_mem_committed[PREV_STAT_IDX][i]=m_num_mem_committed[CURRENT_STAT_IDX][i]; + m_read_regfile_acesses[PREV_STAT_IDX][i]=m_read_regfile_acesses[CURRENT_STAT_IDX][i]; + m_write_regfile_acesses[PREV_STAT_IDX][i]=m_write_regfile_acesses[CURRENT_STAT_IDX][i]; + m_non_rf_operands[PREV_STAT_IDX][i]=m_non_rf_operands[CURRENT_STAT_IDX][i]; + m_active_sp_lanes[PREV_STAT_IDX][i]=m_active_sp_lanes[CURRENT_STAT_IDX][i]; + m_active_sfu_lanes[PREV_STAT_IDX][i]=m_active_sfu_lanes[CURRENT_STAT_IDX][i]; + } } -power_stat_t::power_stat_t(const shader_core_config *shader_config, - float *average_pipeline_duty_cycle, - float *active_sms, shader_core_stats *shader_stats, - const memory_config *mem_config, - memory_stats_t *memory_stats) { - assert(shader_config->m_valid); - assert(mem_config->m_valid); - pwr_core_stat = new power_core_stat_t(shader_config, shader_stats); - pwr_mem_stat = new power_mem_stat_t(mem_config, shader_config, memory_stats, - shader_stats); - m_average_pipeline_duty_cycle = average_pipeline_duty_cycle; - m_active_sms = active_sms; - m_config = shader_config; - m_mem_config = mem_config; +power_stat_t::power_stat_t( const shader_core_config *shader_config,float * average_pipeline_duty_cycle,float *active_sms,shader_core_stats * shader_stats, const memory_config *mem_config,memory_stats_t * memory_stats) +{ + assert( shader_config->m_valid ); + assert( mem_config->m_valid ); + pwr_core_stat= new power_core_stat_t(shader_config,shader_stats); + pwr_mem_stat= new power_mem_stat_t(mem_config,shader_config, memory_stats, shader_stats); + m_average_pipeline_duty_cycle=average_pipeline_duty_cycle; + m_active_sms=active_sms; + m_config = shader_config; + m_mem_config = mem_config; } -void power_stat_t::visualizer_print(gzFile visualizer_file) { - pwr_core_stat->visualizer_print(visualizer_file); - pwr_mem_stat->visualizer_print(visualizer_file); +void power_stat_t::visualizer_print( gzFile visualizer_file ) +{ + pwr_core_stat->visualizer_print(visualizer_file); + pwr_mem_stat->visualizer_print(visualizer_file); } -void power_stat_t::print(FILE *fout) const { - fprintf(fout, "average_pipeline_duty_cycle=%f\n", - *m_average_pipeline_duty_cycle); - pwr_core_stat->print(fout); - pwr_mem_stat->print(fout); +void power_stat_t::print (FILE *fout) const +{ + fprintf(fout,"average_pipeline_duty_cycle=%f\n",*m_average_pipeline_duty_cycle); + pwr_core_stat->print(fout); + pwr_mem_stat->print(fout); } + diff --git a/src/gpgpu-sim/power_stat.h b/src/gpgpu-sim/power_stat.h index d8dfe82..24ade99 100644 --- a/src/gpgpu-sim/power_stat.h +++ b/src/gpgpu-sim/power_stat.h @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -32,750 +30,599 @@ #include <stdio.h> #include <zlib.h> -#include "gpu-sim.h" #include "mem_latency_stat.h" +#include "gpu-sim.h" + +typedef enum _stat_idx{ + CURRENT_STAT_IDX = 0, // Current activity count + PREV_STAT_IDX, // Previous sample activity count + NUM_STAT_IDX // Total number of samples +}stat_idx; -typedef enum _stat_idx { - CURRENT_STAT_IDX = 0, // Current activity count - PREV_STAT_IDX, // Previous sample activity count - NUM_STAT_IDX // Total number of samples -} stat_idx; struct shader_core_power_stats_pod { - // [CURRENT_STAT_IDX] = CURRENT_STAT_IDX stat, [PREV_STAT_IDX] = last reading - float *m_pipeline_duty_cycle[NUM_STAT_IDX]; - unsigned *m_num_decoded_insn[NUM_STAT_IDX]; // number of instructions - // committed by this shader core - unsigned *m_num_FPdecoded_insn[NUM_STAT_IDX]; // number of instructions - // committed by this shader - // core - unsigned *m_num_INTdecoded_insn[NUM_STAT_IDX]; // number of instructions - // committed by this shader - // core - unsigned *m_num_storequeued_insn[NUM_STAT_IDX]; - unsigned *m_num_loadqueued_insn[NUM_STAT_IDX]; - unsigned *m_num_ialu_acesses[NUM_STAT_IDX]; - unsigned *m_num_fp_acesses[NUM_STAT_IDX]; - unsigned *m_num_tex_inst[NUM_STAT_IDX]; - unsigned *m_num_imul_acesses[NUM_STAT_IDX]; - unsigned *m_num_imul32_acesses[NUM_STAT_IDX]; - unsigned *m_num_imul24_acesses[NUM_STAT_IDX]; - unsigned *m_num_fpmul_acesses[NUM_STAT_IDX]; - unsigned *m_num_idiv_acesses[NUM_STAT_IDX]; - unsigned *m_num_fpdiv_acesses[NUM_STAT_IDX]; - unsigned *m_num_sp_acesses[NUM_STAT_IDX]; - unsigned *m_num_sfu_acesses[NUM_STAT_IDX]; - unsigned *m_num_trans_acesses[NUM_STAT_IDX]; - unsigned *m_num_mem_acesses[NUM_STAT_IDX]; - unsigned *m_num_sp_committed[NUM_STAT_IDX]; - unsigned *m_num_sfu_committed[NUM_STAT_IDX]; - unsigned *m_num_mem_committed[NUM_STAT_IDX]; - unsigned *m_active_sp_lanes[NUM_STAT_IDX]; - unsigned *m_active_sfu_lanes[NUM_STAT_IDX]; - unsigned *m_read_regfile_acesses[NUM_STAT_IDX]; - unsigned *m_write_regfile_acesses[NUM_STAT_IDX]; - unsigned *m_non_rf_operands[NUM_STAT_IDX]; + // [CURRENT_STAT_IDX] = CURRENT_STAT_IDX stat, [PREV_STAT_IDX] = last reading + float *m_pipeline_duty_cycle[NUM_STAT_IDX]; + unsigned *m_num_decoded_insn[NUM_STAT_IDX]; // number of instructions committed by this shader core + unsigned *m_num_FPdecoded_insn[NUM_STAT_IDX]; // number of instructions committed by this shader core + unsigned *m_num_INTdecoded_insn[NUM_STAT_IDX]; // number of instructions committed by this shader core + unsigned *m_num_storequeued_insn[NUM_STAT_IDX]; + unsigned *m_num_loadqueued_insn[NUM_STAT_IDX]; + unsigned *m_num_ialu_acesses[NUM_STAT_IDX]; + unsigned *m_num_fp_acesses[NUM_STAT_IDX]; + unsigned *m_num_tex_inst[NUM_STAT_IDX]; + unsigned *m_num_imul_acesses[NUM_STAT_IDX]; + unsigned *m_num_imul32_acesses[NUM_STAT_IDX]; + unsigned *m_num_imul24_acesses[NUM_STAT_IDX]; + unsigned *m_num_fpmul_acesses[NUM_STAT_IDX]; + unsigned *m_num_idiv_acesses[NUM_STAT_IDX]; + unsigned *m_num_fpdiv_acesses[NUM_STAT_IDX]; + unsigned *m_num_sp_acesses[NUM_STAT_IDX]; + unsigned *m_num_sfu_acesses[NUM_STAT_IDX]; + unsigned *m_num_trans_acesses[NUM_STAT_IDX]; + unsigned *m_num_mem_acesses[NUM_STAT_IDX]; + unsigned *m_num_sp_committed[NUM_STAT_IDX]; + unsigned *m_num_sfu_committed[NUM_STAT_IDX]; + unsigned *m_num_mem_committed[NUM_STAT_IDX]; + unsigned *m_active_sp_lanes[NUM_STAT_IDX]; + unsigned *m_active_sfu_lanes[NUM_STAT_IDX]; + unsigned *m_read_regfile_acesses[NUM_STAT_IDX]; + unsigned *m_write_regfile_acesses[NUM_STAT_IDX]; + unsigned *m_non_rf_operands[NUM_STAT_IDX]; }; class power_core_stat_t : public shader_core_power_stats_pod { - public: - power_core_stat_t(const shader_core_config *shader_config, - shader_core_stats *core_stats); - void visualizer_print(gzFile visualizer_file); - void print(FILE *fout); - void init(); - void save_stats(); +public: + power_core_stat_t(const shader_core_config *shader_config, shader_core_stats *core_stats); + void visualizer_print( gzFile visualizer_file ); + void print (FILE *fout); + void init(); + void save_stats(); + +private: + shader_core_stats * m_core_stats; + const shader_core_config *m_config; + float average_duty_cycle; + - private: - shader_core_stats *m_core_stats; - const shader_core_config *m_config; - float average_duty_cycle; }; -struct mem_power_stats_pod { - // [CURRENT_STAT_IDX] = CURRENT_STAT_IDX stat, [PREV_STAT_IDX] = last reading - class cache_stats core_cache_stats[NUM_STAT_IDX]; // Total core stats - class cache_stats l2_cache_stats[NUM_STAT_IDX]; // Total L2 partition stats +struct mem_power_stats_pod{ + // [CURRENT_STAT_IDX] = CURRENT_STAT_IDX stat, [PREV_STAT_IDX] = last reading + class cache_stats core_cache_stats[NUM_STAT_IDX]; // Total core stats + class cache_stats l2_cache_stats[NUM_STAT_IDX]; // Total L2 partition stats - unsigned *shmem_read_access[NUM_STAT_IDX]; // Shared memory access + unsigned *shmem_read_access[NUM_STAT_IDX]; // Shared memory access - // Low level DRAM stats - unsigned *n_cmd[NUM_STAT_IDX]; - unsigned *n_activity[NUM_STAT_IDX]; - unsigned *n_nop[NUM_STAT_IDX]; - unsigned *n_act[NUM_STAT_IDX]; - unsigned *n_pre[NUM_STAT_IDX]; - unsigned *n_rd[NUM_STAT_IDX]; - unsigned *n_wr[NUM_STAT_IDX]; - unsigned *n_req[NUM_STAT_IDX]; + // Low level DRAM stats + unsigned *n_cmd[NUM_STAT_IDX]; + unsigned *n_activity[NUM_STAT_IDX]; + unsigned *n_nop[NUM_STAT_IDX]; + unsigned *n_act[NUM_STAT_IDX]; + unsigned *n_pre[NUM_STAT_IDX]; + unsigned *n_rd[NUM_STAT_IDX]; + unsigned *n_wr[NUM_STAT_IDX]; + unsigned *n_req[NUM_STAT_IDX]; - // Interconnect stats - long *n_simt_to_mem[NUM_STAT_IDX]; - long *n_mem_to_simt[NUM_STAT_IDX]; + // Interconnect stats + long *n_simt_to_mem[NUM_STAT_IDX]; + long *n_mem_to_simt[NUM_STAT_IDX]; }; -class power_mem_stat_t : public mem_power_stats_pod { - public: - power_mem_stat_t(const memory_config *mem_config, - const shader_core_config *shdr_config, - memory_stats_t *mem_stats, shader_core_stats *shdr_stats); - void visualizer_print(gzFile visualizer_file); - void print(FILE *fout) const; - void init(); - void save_stats(); - private: - memory_stats_t *m_mem_stats; - shader_core_stats *m_core_stats; - const memory_config *m_config; - const shader_core_config *m_core_config; + +class power_mem_stat_t : public mem_power_stats_pod{ +public: + power_mem_stat_t(const memory_config *mem_config, const shader_core_config *shdr_config, memory_stats_t *mem_stats, shader_core_stats *shdr_stats); + void visualizer_print( gzFile visualizer_file ); + void print (FILE *fout) const; + void init(); + void save_stats(); +private: + memory_stats_t *m_mem_stats; + shader_core_stats * m_core_stats; + const memory_config *m_config; + const shader_core_config *m_core_config; }; + class power_stat_t { - public: - power_stat_t(const shader_core_config *shader_config, - float *average_pipeline_duty_cycle, float *active_sms, - shader_core_stats *shader_stats, const memory_config *mem_config, - memory_stats_t *memory_stats); - void visualizer_print(gzFile visualizer_file); - void print(FILE *fout) const; - void save_stats() { - pwr_core_stat->save_stats(); - pwr_mem_stat->save_stats(); - *m_average_pipeline_duty_cycle = 0; - *m_active_sms = 0; - } +public: + power_stat_t( const shader_core_config *shader_config,float * average_pipeline_duty_cycle,float * active_sms,shader_core_stats * shader_stats, const memory_config *mem_config,memory_stats_t * memory_stats); + void visualizer_print( gzFile visualizer_file ); + void print (FILE *fout) const; + void save_stats(){ + pwr_core_stat->save_stats(); + pwr_mem_stat->save_stats(); + *m_average_pipeline_duty_cycle=0; + *m_active_sms=0; + } - unsigned get_total_inst() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_decoded_insn[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_decoded_insn[PREV_STAT_IDX][i]); + unsigned get_total_inst(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_decoded_insn[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_decoded_insn[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - unsigned get_total_int_inst() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += - (pwr_core_stat->m_num_INTdecoded_insn[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_INTdecoded_insn[PREV_STAT_IDX][i]); + unsigned get_total_int_inst(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_INTdecoded_insn[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_INTdecoded_insn[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - unsigned get_total_fp_inst() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_FPdecoded_insn[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_FPdecoded_insn[PREV_STAT_IDX][i]); + unsigned get_total_fp_inst(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_FPdecoded_insn[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_FPdecoded_insn[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - unsigned get_total_load_inst() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += - (pwr_core_stat->m_num_loadqueued_insn[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_loadqueued_insn[PREV_STAT_IDX][i]); + unsigned get_total_load_inst(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_loadqueued_insn[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_loadqueued_insn[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - unsigned get_total_store_inst() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += - (pwr_core_stat->m_num_storequeued_insn[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_storequeued_insn[PREV_STAT_IDX][i]); + unsigned get_total_store_inst(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_storequeued_insn[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_storequeued_insn[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - unsigned get_sp_committed_inst() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_sp_committed[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_sp_committed[PREV_STAT_IDX][i]); + unsigned get_sp_committed_inst(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_sp_committed[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_sp_committed[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - unsigned get_sfu_committed_inst() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_sfu_committed[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_sfu_committed[PREV_STAT_IDX][i]); + unsigned get_sfu_committed_inst(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_sfu_committed[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_sfu_committed[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - unsigned get_mem_committed_inst() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_mem_committed[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_mem_committed[PREV_STAT_IDX][i]); + unsigned get_mem_committed_inst(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_mem_committed[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_mem_committed[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - unsigned get_committed_inst() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_mem_committed[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_mem_committed[PREV_STAT_IDX][i]) + - (pwr_core_stat->m_num_sfu_committed[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_sfu_committed[PREV_STAT_IDX][i]) + - (pwr_core_stat->m_num_sp_committed[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_sp_committed[PREV_STAT_IDX][i]); + unsigned get_committed_inst(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_mem_committed[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_mem_committed[PREV_STAT_IDX][i]) + +(pwr_core_stat->m_num_sfu_committed[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_sfu_committed[PREV_STAT_IDX][i]) + +(pwr_core_stat->m_num_sp_committed[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_sp_committed[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - unsigned get_regfile_reads() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += - (pwr_core_stat->m_read_regfile_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_read_regfile_acesses[PREV_STAT_IDX][i]); + unsigned get_regfile_reads(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_read_regfile_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_read_regfile_acesses[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - unsigned get_regfile_writes() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += - (pwr_core_stat->m_write_regfile_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_write_regfile_acesses[PREV_STAT_IDX][i]); + unsigned get_regfile_writes(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_write_regfile_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_write_regfile_acesses[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - float get_pipeline_duty() { - float total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += - (pwr_core_stat->m_pipeline_duty_cycle[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_pipeline_duty_cycle[PREV_STAT_IDX][i]); + float get_pipeline_duty(){ + float total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_pipeline_duty_cycle[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_pipeline_duty_cycle[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - unsigned get_non_regfile_operands() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_non_rf_operands[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_non_rf_operands[PREV_STAT_IDX][i]); + unsigned get_non_regfile_operands(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_non_rf_operands[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_non_rf_operands[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - unsigned get_sp_accessess() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_sp_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_sp_acesses[PREV_STAT_IDX][i]); + unsigned get_sp_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_sp_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_sp_acesses[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - unsigned get_sfu_accessess() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_sfu_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_sfu_acesses[PREV_STAT_IDX][i]); + unsigned get_sfu_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_sfu_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_sfu_acesses[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - unsigned get_trans_accessess() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_trans_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_trans_acesses[PREV_STAT_IDX][i]); - } - return total_inst; - } - - unsigned get_mem_accessess() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_mem_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_mem_acesses[PREV_STAT_IDX][i]); + unsigned get_trans_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_trans_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_trans_acesses[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - unsigned get_intdiv_accessess() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_idiv_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_idiv_acesses[PREV_STAT_IDX][i]); + unsigned get_mem_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_mem_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_mem_acesses[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - unsigned get_fpdiv_accessess() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_fpdiv_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_fpdiv_acesses[PREV_STAT_IDX][i]); + unsigned get_intdiv_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_idiv_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_idiv_acesses[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - unsigned get_intmul32_accessess() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_imul32_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_imul32_acesses[PREV_STAT_IDX][i]); + unsigned get_fpdiv_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_fpdiv_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_fpdiv_acesses[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - unsigned get_intmul24_accessess() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_imul24_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_imul24_acesses[PREV_STAT_IDX][i]); + unsigned get_intmul32_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_imul32_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_imul32_acesses[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - unsigned get_intmul_accessess() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_imul_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_imul_acesses[PREV_STAT_IDX][i]) + - (pwr_core_stat->m_num_imul24_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_imul24_acesses[PREV_STAT_IDX][i]) + - (pwr_core_stat->m_num_imul32_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_imul32_acesses[PREV_STAT_IDX][i]); + unsigned get_intmul24_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_imul24_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_imul24_acesses[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - unsigned get_fpmul_accessess() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_fp_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_fp_acesses[PREV_STAT_IDX][i]); + unsigned get_intmul_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_imul_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_imul_acesses[PREV_STAT_IDX][i])+ + (pwr_core_stat->m_num_imul24_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_imul24_acesses[PREV_STAT_IDX][i])+ + (pwr_core_stat->m_num_imul32_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_imul32_acesses[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - float get_sp_active_lanes() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_active_sp_lanes[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_active_sp_lanes[PREV_STAT_IDX][i]); + unsigned get_fpmul_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_fp_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_fp_acesses[PREV_STAT_IDX][i]); + } + return total_inst; } - return (total_inst / m_config->num_shader()) / m_config->gpgpu_num_sp_units; - } - float get_sfu_active_lanes() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_active_sfu_lanes[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_active_sfu_lanes[PREV_STAT_IDX][i]); + float get_sp_active_lanes(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_active_sp_lanes[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_active_sp_lanes[PREV_STAT_IDX][i]); + } + return (total_inst/m_config->num_shader())/m_config->gpgpu_num_sp_units; } - return (total_inst / m_config->num_shader()) / - m_config->gpgpu_num_sfu_units; - } + float get_sfu_active_lanes(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_active_sfu_lanes[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_active_sfu_lanes[PREV_STAT_IDX][i]); + } - unsigned get_tot_fpu_accessess() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_fp_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_fp_acesses[PREV_STAT_IDX][i]) + - (pwr_core_stat->m_num_fpdiv_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_fpdiv_acesses[PREV_STAT_IDX][i]) + - (pwr_core_stat->m_num_fpmul_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_fpmul_acesses[PREV_STAT_IDX][i]) + - (pwr_core_stat->m_num_imul24_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_imul24_acesses[PREV_STAT_IDX][i]) + - (pwr_core_stat->m_num_imul_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_imul_acesses[PREV_STAT_IDX][i]); + return (total_inst/m_config->num_shader())/m_config->gpgpu_num_sfu_units; } - total_inst += - get_total_load_inst() + get_total_store_inst() + get_tex_inst(); - return total_inst; - } - unsigned get_tot_sfu_accessess() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_idiv_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_idiv_acesses[PREV_STAT_IDX][i]) + - (pwr_core_stat->m_num_imul32_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_imul32_acesses[PREV_STAT_IDX][i]) + - (pwr_core_stat->m_num_trans_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_trans_acesses[PREV_STAT_IDX][i]); + unsigned get_tot_fpu_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_fp_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_fp_acesses[PREV_STAT_IDX][i])+ + (pwr_core_stat->m_num_fpdiv_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_fpdiv_acesses[PREV_STAT_IDX][i])+ + (pwr_core_stat->m_num_fpmul_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_fpmul_acesses[PREV_STAT_IDX][i])+ + (pwr_core_stat->m_num_imul24_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_imul24_acesses[PREV_STAT_IDX][i])+ + (pwr_core_stat->m_num_imul_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_imul_acesses[PREV_STAT_IDX][i]); + } + total_inst += get_total_load_inst()+get_total_store_inst()+get_tex_inst(); + return total_inst; } - return total_inst; - } - unsigned get_ialu_accessess() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_ialu_acesses[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_ialu_acesses[PREV_STAT_IDX][i]); + unsigned get_tot_sfu_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+= (pwr_core_stat->m_num_idiv_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_idiv_acesses[PREV_STAT_IDX][i])+ + (pwr_core_stat->m_num_imul32_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_imul32_acesses[PREV_STAT_IDX][i])+ + (pwr_core_stat->m_num_trans_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_trans_acesses[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - unsigned get_tex_inst() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_core_stat->m_num_tex_inst[CURRENT_STAT_IDX][i]) - - (pwr_core_stat->m_num_tex_inst[PREV_STAT_IDX][i]); + unsigned get_ialu_accessess(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_ialu_acesses[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_ialu_acesses[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - unsigned get_constant_c_accesses() { - enum mem_access_type access_type[] = {CONST_ACC_R}; - enum cache_request_status request_status[] = {HIT, MISS, HIT_RESERVED}; - unsigned num_access_type = - sizeof(access_type) / sizeof(enum mem_access_type); - unsigned num_request_status = - sizeof(request_status) / sizeof(enum cache_request_status); + unsigned get_tex_inst(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_core_stat->m_num_tex_inst[CURRENT_STAT_IDX][i]) - (pwr_core_stat->m_num_tex_inst[PREV_STAT_IDX][i]); + } + return total_inst; + } - return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)) - - (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)); - } - unsigned get_constant_c_misses() { - enum mem_access_type access_type[] = {CONST_ACC_R}; - enum cache_request_status request_status[] = {MISS}; - unsigned num_access_type = - sizeof(access_type) / sizeof(enum mem_access_type); - unsigned num_request_status = - sizeof(request_status) / sizeof(enum cache_request_status); + unsigned get_constant_c_accesses(){ + enum mem_access_type access_type[] = {CONST_ACC_R}; + enum cache_request_status request_status[] = {HIT, MISS, HIT_RESERVED}; + unsigned num_access_type = sizeof(access_type)/sizeof(enum mem_access_type); + unsigned num_request_status = sizeof(request_status)/sizeof(enum cache_request_status); - return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)) - - (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)); - } - unsigned get_constant_c_hits() { - return (get_constant_c_accesses() - get_constant_c_misses()); - } - unsigned get_texture_c_accesses() { - enum mem_access_type access_type[] = {TEXTURE_ACC_R}; - enum cache_request_status request_status[] = {HIT, MISS, HIT_RESERVED}; - unsigned num_access_type = - sizeof(access_type) / sizeof(enum mem_access_type); - unsigned num_request_status = - sizeof(request_status) / sizeof(enum cache_request_status); + return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)) - + (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)); + } + unsigned get_constant_c_misses(){ + enum mem_access_type access_type[] = {CONST_ACC_R}; + enum cache_request_status request_status[] = {MISS}; + unsigned num_access_type = sizeof(access_type)/sizeof(enum mem_access_type); + unsigned num_request_status = sizeof(request_status)/sizeof(enum cache_request_status); - return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)) - - (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)); - } - unsigned get_texture_c_misses() { - enum mem_access_type access_type[] = {TEXTURE_ACC_R}; - enum cache_request_status request_status[] = {MISS}; - unsigned num_access_type = - sizeof(access_type) / sizeof(enum mem_access_type); - unsigned num_request_status = - sizeof(request_status) / sizeof(enum cache_request_status); + return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)) - + (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)); + } + unsigned get_constant_c_hits(){ + return (get_constant_c_accesses()-get_constant_c_misses()); + } + unsigned get_texture_c_accesses(){ + enum mem_access_type access_type[] = {TEXTURE_ACC_R}; + enum cache_request_status request_status[] = {HIT, MISS, HIT_RESERVED}; + unsigned num_access_type = sizeof(access_type)/sizeof(enum mem_access_type); + unsigned num_request_status = sizeof(request_status)/sizeof(enum cache_request_status); - return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)) - - (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)); - } - unsigned get_texture_c_hits() { - return (get_texture_c_accesses() - get_texture_c_misses()); - } - unsigned get_inst_c_accesses() { - enum mem_access_type access_type[] = {INST_ACC_R}; - enum cache_request_status request_status[] = {HIT, MISS, HIT_RESERVED}; - unsigned num_access_type = - sizeof(access_type) / sizeof(enum mem_access_type); - unsigned num_request_status = - sizeof(request_status) / sizeof(enum cache_request_status); + return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)) - + (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)); + } + unsigned get_texture_c_misses(){ + enum mem_access_type access_type[] = {TEXTURE_ACC_R}; + enum cache_request_status request_status[] = {MISS}; + unsigned num_access_type = sizeof(access_type)/sizeof(enum mem_access_type); + unsigned num_request_status = sizeof(request_status)/sizeof(enum cache_request_status); - return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)) - - (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)); - } - unsigned get_inst_c_misses() { - enum mem_access_type access_type[] = {INST_ACC_R}; - enum cache_request_status request_status[] = {MISS}; - unsigned num_access_type = - sizeof(access_type) / sizeof(enum mem_access_type); - unsigned num_request_status = - sizeof(request_status) / sizeof(enum cache_request_status); + return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)) - + (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)); + } + unsigned get_texture_c_hits(){ + return ( get_texture_c_accesses()- get_texture_c_misses()); + } + unsigned get_inst_c_accesses(){ + enum mem_access_type access_type[] = {INST_ACC_R}; + enum cache_request_status request_status[] = {HIT, MISS, HIT_RESERVED}; + unsigned num_access_type = sizeof(access_type)/sizeof(enum mem_access_type); + unsigned num_request_status = sizeof(request_status)/sizeof(enum cache_request_status); - return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)) - - (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)); - } - unsigned get_inst_c_hits() { - return (get_inst_c_accesses() - get_inst_c_misses()); - } + return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)) - + (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)); + } + unsigned get_inst_c_misses(){ + enum mem_access_type access_type[] = {INST_ACC_R}; + enum cache_request_status request_status[] = {MISS}; + unsigned num_access_type = sizeof(access_type)/sizeof(enum mem_access_type); + unsigned num_request_status = sizeof(request_status)/sizeof(enum cache_request_status); - unsigned get_l1d_read_accesses() { - enum mem_access_type access_type[] = {GLOBAL_ACC_R, LOCAL_ACC_R}; - enum cache_request_status request_status[] = {HIT, MISS, HIT_RESERVED}; - unsigned num_access_type = - sizeof(access_type) / sizeof(enum mem_access_type); - unsigned num_request_status = - sizeof(request_status) / sizeof(enum cache_request_status); + return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)) - + (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)); + } + unsigned get_inst_c_hits(){ + return (get_inst_c_accesses()-get_inst_c_misses()); + } - return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)) - - (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)); - } - unsigned get_l1d_read_misses() { - enum mem_access_type access_type[] = {GLOBAL_ACC_R, LOCAL_ACC_R}; - enum cache_request_status request_status[] = {MISS}; - unsigned num_access_type = - sizeof(access_type) / sizeof(enum mem_access_type); - unsigned num_request_status = - sizeof(request_status) / sizeof(enum cache_request_status); + unsigned get_l1d_read_accesses(){ + enum mem_access_type access_type[] = {GLOBAL_ACC_R, LOCAL_ACC_R}; + enum cache_request_status request_status[] = {HIT, MISS, HIT_RESERVED}; + unsigned num_access_type = sizeof(access_type)/sizeof(enum mem_access_type); + unsigned num_request_status = sizeof(request_status)/sizeof(enum cache_request_status); - return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)) - - (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)); - } - unsigned get_l1d_read_hits() { - return (get_l1d_read_accesses() - get_l1d_read_misses()); - } - unsigned get_l1d_write_accesses() { - enum mem_access_type access_type[] = {GLOBAL_ACC_W, LOCAL_ACC_W}; - enum cache_request_status request_status[] = {HIT, MISS, HIT_RESERVED}; - unsigned num_access_type = - sizeof(access_type) / sizeof(enum mem_access_type); - unsigned num_request_status = - sizeof(request_status) / sizeof(enum cache_request_status); + return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)) - + (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)); + } + unsigned get_l1d_read_misses(){ + enum mem_access_type access_type[] = {GLOBAL_ACC_R, LOCAL_ACC_R}; + enum cache_request_status request_status[] = {MISS}; + unsigned num_access_type = sizeof(access_type)/sizeof(enum mem_access_type); + unsigned num_request_status = sizeof(request_status)/sizeof(enum cache_request_status); - return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)) - - (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)); - } - unsigned get_l1d_write_misses() { - enum mem_access_type access_type[] = {GLOBAL_ACC_W, LOCAL_ACC_W}; - enum cache_request_status request_status[] = {MISS}; - unsigned num_access_type = - sizeof(access_type) / sizeof(enum mem_access_type); - unsigned num_request_status = - sizeof(request_status) / sizeof(enum cache_request_status); + return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)) - + (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)); + } + unsigned get_l1d_read_hits(){ + return (get_l1d_read_accesses()-get_l1d_read_misses()); + } + unsigned get_l1d_write_accesses(){ + enum mem_access_type access_type[] = {GLOBAL_ACC_W, LOCAL_ACC_W}; + enum cache_request_status request_status[] = {HIT, MISS, HIT_RESERVED}; + unsigned num_access_type = sizeof(access_type)/sizeof(enum mem_access_type); + unsigned num_request_status = sizeof(request_status)/sizeof(enum cache_request_status); - return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)) - - (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)); - } - unsigned get_l1d_write_hits() { - return (get_l1d_write_accesses() - get_l1d_write_misses()); - } - unsigned get_cache_misses() { - return get_l1d_read_misses() + get_constant_c_misses() + - get_l1d_write_misses() + get_texture_c_misses(); - } + return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)) - + (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)); + } + unsigned get_l1d_write_misses(){ + enum mem_access_type access_type[] = {GLOBAL_ACC_W, LOCAL_ACC_W}; + enum cache_request_status request_status[] = {MISS}; + unsigned num_access_type = sizeof(access_type)/sizeof(enum mem_access_type); + unsigned num_request_status = sizeof(request_status)/sizeof(enum cache_request_status); - unsigned get_cache_read_misses() { - return get_l1d_read_misses() + get_constant_c_misses() + - get_texture_c_misses(); - } + return (pwr_mem_stat->core_cache_stats[CURRENT_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)) - + (pwr_mem_stat->core_cache_stats[PREV_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)); + } + unsigned get_l1d_write_hits(){ + return (get_l1d_write_accesses()-get_l1d_write_misses()); + } + unsigned get_cache_misses(){ + return get_l1d_read_misses()+get_constant_c_misses()+get_l1d_write_misses()+get_texture_c_misses(); + } + + unsigned get_cache_read_misses(){ + return get_l1d_read_misses()+get_constant_c_misses()+get_texture_c_misses(); + } - unsigned get_cache_write_misses() { return get_l1d_write_misses(); } + unsigned get_cache_write_misses(){ + return get_l1d_write_misses(); + } - unsigned get_shmem_read_access() { - unsigned total_inst = 0; - for (unsigned i = 0; i < m_config->num_shader(); i++) { - total_inst += (pwr_mem_stat->shmem_read_access[CURRENT_STAT_IDX][i]) - - (pwr_mem_stat->shmem_read_access[PREV_STAT_IDX][i]); + unsigned get_shmem_read_access(){ + unsigned total_inst=0; + for(unsigned i=0; i<m_config->num_shader();i++){ + total_inst+=(pwr_mem_stat->shmem_read_access[CURRENT_STAT_IDX][i]) - (pwr_mem_stat->shmem_read_access[PREV_STAT_IDX][i]); + } + return total_inst; } - return total_inst; - } - unsigned get_l2_read_accesses() { - enum mem_access_type access_type[] = { - GLOBAL_ACC_R, LOCAL_ACC_R, CONST_ACC_R, TEXTURE_ACC_R, INST_ACC_R}; - enum cache_request_status request_status[] = {HIT, MISS, HIT_RESERVED}; - unsigned num_access_type = - sizeof(access_type) / sizeof(enum mem_access_type); - unsigned num_request_status = - sizeof(request_status) / sizeof(enum cache_request_status); + unsigned get_l2_read_accesses(){ + enum mem_access_type access_type[] = {GLOBAL_ACC_R, LOCAL_ACC_R, CONST_ACC_R, TEXTURE_ACC_R, INST_ACC_R}; + enum cache_request_status request_status[] = {HIT, MISS, HIT_RESERVED}; + unsigned num_access_type = sizeof(access_type)/sizeof(enum mem_access_type); + unsigned num_request_status = sizeof(request_status)/sizeof(enum cache_request_status); - return (pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)) - - (pwr_mem_stat->l2_cache_stats[PREV_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)); - } + return (pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)) - + (pwr_mem_stat->l2_cache_stats[PREV_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)); + } - unsigned get_l2_read_misses() { - enum mem_access_type access_type[] = { - GLOBAL_ACC_R, LOCAL_ACC_R, CONST_ACC_R, TEXTURE_ACC_R, INST_ACC_R}; - enum cache_request_status request_status[] = {MISS}; - unsigned num_access_type = - sizeof(access_type) / sizeof(enum mem_access_type); - unsigned num_request_status = - sizeof(request_status) / sizeof(enum cache_request_status); + unsigned get_l2_read_misses(){ + enum mem_access_type access_type[] = {GLOBAL_ACC_R, LOCAL_ACC_R, CONST_ACC_R, TEXTURE_ACC_R, INST_ACC_R}; + enum cache_request_status request_status[] = {MISS}; + unsigned num_access_type = sizeof(access_type)/sizeof(enum mem_access_type); + unsigned num_request_status = sizeof(request_status)/sizeof(enum cache_request_status); - return (pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)) - - (pwr_mem_stat->l2_cache_stats[PREV_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)); - } + return (pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)) - + (pwr_mem_stat->l2_cache_stats[PREV_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)); + } - unsigned get_l2_read_hits() { - return (get_l2_read_accesses() - get_l2_read_misses()); - } + unsigned get_l2_read_hits(){ + return (get_l2_read_accesses()-get_l2_read_misses()); + } - unsigned get_l2_write_accesses() { - enum mem_access_type access_type[] = {GLOBAL_ACC_W, LOCAL_ACC_W, - L1_WRBK_ACC}; - enum cache_request_status request_status[] = {HIT, MISS, HIT_RESERVED}; - unsigned num_access_type = - sizeof(access_type) / sizeof(enum mem_access_type); - unsigned num_request_status = - sizeof(request_status) / sizeof(enum cache_request_status); + unsigned get_l2_write_accesses(){ + enum mem_access_type access_type[] = {GLOBAL_ACC_W, LOCAL_ACC_W, L1_WRBK_ACC}; + enum cache_request_status request_status[] = {HIT, MISS, HIT_RESERVED}; + unsigned num_access_type = sizeof(access_type)/sizeof(enum mem_access_type); + unsigned num_request_status = sizeof(request_status)/sizeof(enum cache_request_status); - return (pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)) - - (pwr_mem_stat->l2_cache_stats[PREV_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)); - } + return (pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)) - + (pwr_mem_stat->l2_cache_stats[PREV_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)); + } - unsigned get_l2_write_misses() { - enum mem_access_type access_type[] = {GLOBAL_ACC_W, LOCAL_ACC_W, - L1_WRBK_ACC}; - enum cache_request_status request_status[] = {MISS}; - unsigned num_access_type = - sizeof(access_type) / sizeof(enum mem_access_type); - unsigned num_request_status = - sizeof(request_status) / sizeof(enum cache_request_status); + unsigned get_l2_write_misses(){ + enum mem_access_type access_type[] = {GLOBAL_ACC_W, LOCAL_ACC_W, L1_WRBK_ACC}; + enum cache_request_status request_status[] = {MISS}; + unsigned num_access_type = sizeof(access_type)/sizeof(enum mem_access_type); + unsigned num_request_status = sizeof(request_status)/sizeof(enum cache_request_status); - return (pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)) - - (pwr_mem_stat->l2_cache_stats[PREV_STAT_IDX].get_stats( - access_type, num_access_type, request_status, - num_request_status)); - } - unsigned get_l2_write_hits() { - return (get_l2_write_accesses() - get_l2_write_misses()); - } - unsigned get_dram_cmd() { - unsigned total = 0; - for (unsigned i = 0; i < m_mem_config->m_n_mem; ++i) { - total += (pwr_mem_stat->n_cmd[CURRENT_STAT_IDX][i] - - pwr_mem_stat->n_cmd[PREV_STAT_IDX][i]); + return (pwr_mem_stat->l2_cache_stats[CURRENT_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)) - + (pwr_mem_stat->l2_cache_stats[PREV_STAT_IDX].get_stats(access_type, num_access_type, request_status, num_request_status)); + } + unsigned get_l2_write_hits(){ + return (get_l2_write_accesses()-get_l2_write_misses()); } - return total; - } - unsigned get_dram_activity() { - unsigned total = 0; - for (unsigned i = 0; i < m_mem_config->m_n_mem; ++i) { - total += (pwr_mem_stat->n_activity[CURRENT_STAT_IDX][i] - - pwr_mem_stat->n_activity[PREV_STAT_IDX][i]); + unsigned get_dram_cmd(){ + unsigned total=0; + for(unsigned i=0; i<m_mem_config->m_n_mem; ++i){ + total += (pwr_mem_stat->n_cmd[CURRENT_STAT_IDX][i] - pwr_mem_stat->n_cmd[PREV_STAT_IDX][i]); + } + return total; } - return total; - } - unsigned get_dram_nop() { - unsigned total = 0; - for (unsigned i = 0; i < m_mem_config->m_n_mem; ++i) { - total += (pwr_mem_stat->n_nop[CURRENT_STAT_IDX][i] - - pwr_mem_stat->n_nop[PREV_STAT_IDX][i]); + unsigned get_dram_activity(){ + unsigned total=0; + for(unsigned i=0; i<m_mem_config->m_n_mem; ++i){ + total += (pwr_mem_stat->n_activity[CURRENT_STAT_IDX][i] - pwr_mem_stat->n_activity[PREV_STAT_IDX][i]); + } + return total; } - return total; - } - unsigned get_dram_act() { - unsigned total = 0; - for (unsigned i = 0; i < m_mem_config->m_n_mem; ++i) { - total += (pwr_mem_stat->n_act[CURRENT_STAT_IDX][i] - - pwr_mem_stat->n_act[PREV_STAT_IDX][i]); + unsigned get_dram_nop(){ + unsigned total=0; + for(unsigned i=0; i<m_mem_config->m_n_mem; ++i){ + total += (pwr_mem_stat->n_nop[CURRENT_STAT_IDX][i] - pwr_mem_stat->n_nop[PREV_STAT_IDX][i]); + } + return total; } - return total; - } - unsigned get_dram_pre() { - unsigned total = 0; - for (unsigned i = 0; i < m_mem_config->m_n_mem; ++i) { - total += (pwr_mem_stat->n_pre[CURRENT_STAT_IDX][i] - - pwr_mem_stat->n_pre[PREV_STAT_IDX][i]); + unsigned get_dram_act(){ + unsigned total=0; + for(unsigned i=0; i<m_mem_config->m_n_mem; ++i){ + total += (pwr_mem_stat->n_act[CURRENT_STAT_IDX][i] - pwr_mem_stat->n_act[PREV_STAT_IDX][i]); + } + return total; } - return total; - } - unsigned get_dram_rd() { - unsigned total = 0; - for (unsigned i = 0; i < m_mem_config->m_n_mem; ++i) { - total += (pwr_mem_stat->n_rd[CURRENT_STAT_IDX][i] - - pwr_mem_stat->n_rd[PREV_STAT_IDX][i]); + unsigned get_dram_pre(){ + unsigned total=0; + for(unsigned i=0; i<m_mem_config->m_n_mem; ++i){ + total += (pwr_mem_stat->n_pre[CURRENT_STAT_IDX][i] - pwr_mem_stat->n_pre[PREV_STAT_IDX][i]); + } + return total; } - return total; - } - unsigned get_dram_wr() { - unsigned total = 0; - for (unsigned i = 0; i < m_mem_config->m_n_mem; ++i) { - total += (pwr_mem_stat->n_wr[CURRENT_STAT_IDX][i] - - pwr_mem_stat->n_wr[PREV_STAT_IDX][i]); + unsigned get_dram_rd(){ + unsigned total=0; + for(unsigned i=0; i<m_mem_config->m_n_mem; ++i){ + total += (pwr_mem_stat->n_rd[CURRENT_STAT_IDX][i] - pwr_mem_stat->n_rd[PREV_STAT_IDX][i]); + } + return total; } - return total; - } - unsigned get_dram_req() { - unsigned total = 0; - for (unsigned i = 0; i < m_mem_config->m_n_mem; ++i) { - total += (pwr_mem_stat->n_req[CURRENT_STAT_IDX][i] - - pwr_mem_stat->n_req[PREV_STAT_IDX][i]); + unsigned get_dram_wr(){ + unsigned total=0; + for(unsigned i=0; i<m_mem_config->m_n_mem; ++i){ + total += (pwr_mem_stat->n_wr[CURRENT_STAT_IDX][i] - pwr_mem_stat->n_wr[PREV_STAT_IDX][i]); + } + return total; + } + unsigned get_dram_req(){ + unsigned total=0; + for(unsigned i=0; i<m_mem_config->m_n_mem; ++i){ + total += (pwr_mem_stat->n_req[CURRENT_STAT_IDX][i] - pwr_mem_stat->n_req[PREV_STAT_IDX][i]); + } + return total; } - return total; - } - long get_icnt_simt_to_mem() { - long total = 0; - for (unsigned i = 0; i < m_config->n_simt_clusters; ++i) { - total += (pwr_mem_stat->n_simt_to_mem[CURRENT_STAT_IDX][i] - - pwr_mem_stat->n_simt_to_mem[PREV_STAT_IDX][i]); + long get_icnt_simt_to_mem(){ + long total=0; + for(unsigned i=0; i<m_config->n_simt_clusters; ++i){ + total += (pwr_mem_stat->n_simt_to_mem[CURRENT_STAT_IDX][i] - pwr_mem_stat->n_simt_to_mem[PREV_STAT_IDX][i]); + } + return total; } - return total; - } - long get_icnt_mem_to_simt() { - long total = 0; - for (unsigned i = 0; i < m_config->n_simt_clusters; ++i) { - total += (pwr_mem_stat->n_mem_to_simt[CURRENT_STAT_IDX][i] - - pwr_mem_stat->n_mem_to_simt[PREV_STAT_IDX][i]); + long get_icnt_mem_to_simt(){ + long total=0; + for(unsigned i=0; i<m_config->n_simt_clusters; ++i){ + total += (pwr_mem_stat->n_mem_to_simt[CURRENT_STAT_IDX][i] - pwr_mem_stat->n_mem_to_simt[PREV_STAT_IDX][i]); + } + return total; } - return total; - } - power_core_stat_t *pwr_core_stat; - power_mem_stat_t *pwr_mem_stat; - float *m_average_pipeline_duty_cycle; - float *m_active_sms; - const shader_core_config *m_config; - const memory_config *m_mem_config; + power_core_stat_t * pwr_core_stat; + power_mem_stat_t * pwr_mem_stat; + float * m_average_pipeline_duty_cycle; + float * m_active_sms; + const shader_core_config *m_config; + const memory_config *m_mem_config; }; + #endif /*POWER_LATENCY_STAT_H*/ diff --git a/src/gpgpu-sim/scoreboard.cc b/src/gpgpu-sim/scoreboard.cc index 7a207ec..1017e75 100644 --- a/src/gpgpu-sim/scoreboard.cc +++ b/src/gpgpu-sim/scoreboard.cc @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -28,128 +26,140 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "scoreboard.h" -#include "../cuda-sim/ptx_sim.h" #include "shader.h" +#include "../cuda-sim/ptx_sim.h" #include "shader_trace.h" -// Constructor -Scoreboard::Scoreboard(unsigned sid, unsigned n_warps, class gpgpu_t* gpu) - : longopregs() { - m_sid = sid; - // Initialize size of table - reg_table.resize(n_warps); - longopregs.resize(n_warps); - m_gpu = gpu; +//Constructor +Scoreboard::Scoreboard( unsigned sid, unsigned n_warps, class gpgpu_t* gpu ) +: longopregs() +{ + m_sid = sid; + //Initialize size of table + reg_table.resize(n_warps); + longopregs.resize(n_warps); + + m_gpu = gpu; } // Print scoreboard contents -void Scoreboard::printContents() const { - printf("scoreboard contents (sid=%d): \n", m_sid); - for (unsigned i = 0; i < reg_table.size(); i++) { - if (reg_table[i].size() == 0) continue; - printf(" wid = %2d: ", i); - std::set<unsigned>::const_iterator it; - for (it = reg_table[i].begin(); it != reg_table[i].end(); it++) - printf("%u ", *it); - printf("\n"); - } +void Scoreboard::printContents() const +{ + printf("scoreboard contents (sid=%d): \n", m_sid); + for(unsigned i=0; i<reg_table.size(); i++) { + if(reg_table[i].size() == 0 ) continue; + printf(" wid = %2d: ", i); + std::set<unsigned>::const_iterator it; + for( it=reg_table[i].begin() ; it != reg_table[i].end(); it++ ) + printf("%u ", *it); + printf("\n"); + } } -void Scoreboard::reserveRegister(unsigned wid, unsigned regnum) { - if (!(reg_table[wid].find(regnum) == reg_table[wid].end())) { - printf( - "Error: trying to reserve an already reserved register (sid=%d, " - "wid=%d, regnum=%d).", - m_sid, wid, regnum); - abort(); - } - SHADER_DPRINTF(SCOREBOARD, "Reserved Register - warp:%d, reg: %d\n", wid, - regnum); - reg_table[wid].insert(regnum); +void Scoreboard::reserveRegister(unsigned wid, unsigned regnum) +{ + if( !(reg_table[wid].find(regnum) == reg_table[wid].end()) ){ + printf("Error: trying to reserve an already reserved register (sid=%d, wid=%d, regnum=%d).", m_sid, wid, regnum); + abort(); + } + SHADER_DPRINTF( SCOREBOARD, + "Reserved Register - warp:%d, reg: %d\n", wid, regnum ); + reg_table[wid].insert(regnum); } // Unmark register as write-pending -void Scoreboard::releaseRegister(unsigned wid, unsigned regnum) { - if (!(reg_table[wid].find(regnum) != reg_table[wid].end())) return; - SHADER_DPRINTF(SCOREBOARD, "Release register - warp:%d, reg: %d\n", wid, - regnum); - reg_table[wid].erase(regnum); +void Scoreboard::releaseRegister(unsigned wid, unsigned regnum) +{ + if( !(reg_table[wid].find(regnum) != reg_table[wid].end()) ) + return; + SHADER_DPRINTF( SCOREBOARD, + "Release register - warp:%d, reg: %d\n", wid, regnum ); + reg_table[wid].erase(regnum); } -const bool Scoreboard::islongop(unsigned warp_id, unsigned regnum) { - return longopregs[warp_id].find(regnum) != longopregs[warp_id].end(); +const bool Scoreboard::islongop (unsigned warp_id,unsigned regnum) { + return longopregs[warp_id].find(regnum) != longopregs[warp_id].end(); } -void Scoreboard::reserveRegisters(const class warp_inst_t* inst) { - for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) { - if (inst->out[r] > 0) { - reserveRegister(inst->warp_id(), inst->out[r]); - SHADER_DPRINTF(SCOREBOARD, "Reserved register - warp:%d, reg: %d\n", - inst->warp_id(), inst->out[r]); +void Scoreboard::reserveRegisters(const class warp_inst_t* inst) +{ + for( unsigned r=0; r < MAX_OUTPUT_VALUES; r++) { + if(inst->out[r] > 0) { + reserveRegister(inst->warp_id(), inst->out[r]); + SHADER_DPRINTF( SCOREBOARD, + "Reserved register - warp:%d, reg: %d\n", + inst->warp_id(), + inst->out[r] ); + } } - } - // Keep track of long operations - if (inst->is_load() && (inst->space.get_type() == global_space || - inst->space.get_type() == local_space || - inst->space.get_type() == param_space_kernel || - inst->space.get_type() == param_space_local || - inst->space.get_type() == param_space_unclassified || - inst->space.get_type() == tex_space)) { - for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) { - if (inst->out[r] > 0) { - SHADER_DPRINTF(SCOREBOARD, "New longopreg marked - warp:%d, reg: %d\n", - inst->warp_id(), inst->out[r]); - longopregs[inst->warp_id()].insert(inst->out[r]); - } + //Keep track of long operations + if (inst->is_load() && + ( inst->space.get_type() == global_space || + inst->space.get_type() == local_space || + inst->space.get_type() == param_space_kernel || + inst->space.get_type() == param_space_local || + inst->space.get_type() == param_space_unclassified || + inst->space.get_type() == tex_space)){ + for ( unsigned r=0; r<MAX_OUTPUT_VALUES; r++) { + if(inst->out[r] > 0) { + SHADER_DPRINTF( SCOREBOARD, + "New longopreg marked - warp:%d, reg: %d\n", + inst->warp_id(), + inst->out[r] ); + longopregs[inst->warp_id()].insert(inst->out[r]); + } + } } - } } // Release registers for an instruction -void Scoreboard::releaseRegisters(const class warp_inst_t* inst) { - for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) { - if (inst->out[r] > 0) { - SHADER_DPRINTF(SCOREBOARD, "Register Released - warp:%d, reg: %d\n", - inst->warp_id(), inst->out[r]); - releaseRegister(inst->warp_id(), inst->out[r]); - longopregs[inst->warp_id()].erase(inst->out[r]); +void Scoreboard::releaseRegisters(const class warp_inst_t *inst) +{ + for( unsigned r=0; r < MAX_OUTPUT_VALUES; r++) { + if(inst->out[r] > 0) { + SHADER_DPRINTF( SCOREBOARD, + "Register Released - warp:%d, reg: %d\n", + inst->warp_id(), + inst->out[r] ); + releaseRegister(inst->warp_id(), inst->out[r]); + longopregs[inst->warp_id()].erase(inst->out[r]); + } } - } } -/** - * Checks to see if registers used by an instruction are reserved in the - *scoreboard - * - * @return +/** + * Checks to see if registers used by an instruction are reserved in the scoreboard + * + * @return * true if WAW or RAW hazard (no WAR since in-order issue) - **/ -bool Scoreboard::checkCollision(unsigned wid, const class inst_t* inst) const { - // Get list of all input and output registers - std::set<int> inst_regs; + **/ +bool Scoreboard::checkCollision( unsigned wid, const class inst_t *inst ) const +{ + // Get list of all input and output registers + std::set<int> inst_regs; - for (unsigned iii = 0; iii < inst->outcount; iii++) - inst_regs.insert(inst->out[iii]); + for(unsigned iii=0; iii < inst->outcount; iii++) + inst_regs.insert(inst->out[iii]); - for (unsigned jjj = 0; jjj < inst->incount; jjj++) - inst_regs.insert(inst->in[jjj]); + for(unsigned jjj=0;jjj<inst->incount;jjj++) + inst_regs.insert(inst->in[jjj]); - if (inst->pred > 0) inst_regs.insert(inst->pred); - if (inst->ar1 > 0) inst_regs.insert(inst->ar1); - if (inst->ar2 > 0) inst_regs.insert(inst->ar2); + if(inst->pred > 0) inst_regs.insert(inst->pred); + if(inst->ar1 > 0) inst_regs.insert(inst->ar1); + if(inst->ar2 > 0) inst_regs.insert(inst->ar2); - // Check for collision, get the intersection of reserved registers and - // instruction registers - std::set<int>::const_iterator it2; - for (it2 = inst_regs.begin(); it2 != inst_regs.end(); it2++) - if (reg_table[wid].find(*it2) != reg_table[wid].end()) { - return true; - } - return false; + // Check for collision, get the intersection of reserved registers and instruction registers + std::set<int>::const_iterator it2; + for ( it2=inst_regs.begin() ; it2 != inst_regs.end(); it2++ ) + if(reg_table[wid].find(*it2) != reg_table[wid].end()) { + return true; + } + return false; } -bool Scoreboard::pendingWrites(unsigned wid) const { - return !reg_table[wid].empty(); +bool Scoreboard::pendingWrites(unsigned wid) const +{ + return !reg_table[wid].empty(); } diff --git a/src/gpgpu-sim/scoreboard.h b/src/gpgpu-sim/scoreboard.h index 86deac7..a4baa19 100644 --- a/src/gpgpu-sim/scoreboard.h +++ b/src/gpgpu-sim/scoreboard.h @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -29,8 +27,8 @@ #include <stdio.h> #include <stdlib.h> -#include <set> #include <vector> +#include <set> #include "assert.h" #ifndef SCOREBOARD_H_ @@ -39,31 +37,31 @@ #include "../abstract_hardware_model.h" class Scoreboard { - public: - Scoreboard(unsigned sid, unsigned n_warps, class gpgpu_t *gpu); +public: + Scoreboard( unsigned sid, unsigned n_warps, class gpgpu_t* gpu ); - void reserveRegisters(const warp_inst_t *inst); - void releaseRegisters(const warp_inst_t *inst); - void releaseRegister(unsigned wid, unsigned regnum); + void reserveRegisters(const warp_inst_t *inst); + void releaseRegisters(const warp_inst_t *inst); + void releaseRegister(unsigned wid, unsigned regnum); - bool checkCollision(unsigned wid, const inst_t *inst) const; - bool pendingWrites(unsigned wid) const; - void printContents() const; - const bool islongop(unsigned warp_id, unsigned regnum); + bool checkCollision(unsigned wid, const inst_t *inst) const; + bool pendingWrites(unsigned wid) const; + void printContents() const; + const bool islongop(unsigned warp_id, unsigned regnum); +private: + void reserveRegister(unsigned wid, unsigned regnum); + int get_sid() const { return m_sid; } - private: - void reserveRegister(unsigned wid, unsigned regnum); - int get_sid() const { return m_sid; } + unsigned m_sid; - unsigned m_sid; + // keeps track of pending writes to registers + // indexed by warp id, reg_id => pending write count + std::vector< std::set<unsigned> > reg_table; + //Register that depend on a long operation (global, local or tex memory) + std::vector< std::set<unsigned> > longopregs; - // keeps track of pending writes to registers - // indexed by warp id, reg_id => pending write count - std::vector<std::set<unsigned> > reg_table; - // Register that depend on a long operation (global, local or tex memory) - std::vector<std::set<unsigned> > longopregs; - - class gpgpu_t *m_gpu; + class gpgpu_t* m_gpu; }; + #endif /* SCOREBOARD_H_ */ diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc index 73ea8b3..6a0e3d6 100644 --- a/src/gpgpu-sim/shader.cc +++ b/src/gpgpu-sim/shader.cc @@ -1,5 +1,5 @@ // Copyright (c) 2009-2011, Tor M. Aamodt, Wilson W.L. Fung, Ali Bakhoda, -// George L. Yuan, Andrew Turner, Inderpreet Singh +// George L. Yuan, Andrew Turner, Inderpreet Singh // The University of British Columbia // All rights reserved. // @@ -8,16 +8,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -28,2137 +26,2042 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include "shader.h" #include <float.h> -#include <limits.h> -#include <string.h> -#include "../../libcuda/gpgpu_context.h" -#include "../cuda-sim/cuda-sim.h" -#include "../cuda-sim/ptx-stats.h" -#include "../cuda-sim/ptx_sim.h" -#include "../statwrapper.h" +#include "shader.h" #include "addrdec.h" #include "dram.h" +#include "stat-tool.h" #include "gpu-misc.h" +#include "../cuda-sim/ptx_sim.h" +#include "../cuda-sim/ptx-stats.h" +#include "../cuda-sim/cuda-sim.h" #include "gpu-sim.h" -#include "icnt_wrapper.h" #include "mem_fetch.h" #include "mem_latency_stat.h" -#include "shader_trace.h" -#include "stat-tool.h" -#include "traffic_breakdown.h" #include "visualizer.h" +#include "../statwrapper.h" +#include "icnt_wrapper.h" +#include <string.h> +#include <limits.h> +#include "traffic_breakdown.h" +#include "shader_trace.h" +#include "../../libcuda/gpgpu_context.h" #define PRIORITIZE_MSHR_OVER_WB 1 -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) +#define MIN(a,b) (((a)<(b))?(a):(b)) + -mem_fetch *shader_core_mem_fetch_allocator::alloc( - new_addr_type addr, mem_access_type type, unsigned size, bool wr, - unsigned long long cycle) const { - mem_access_t access(type, addr, size, wr, m_memory_config->gpgpu_ctx); - mem_fetch *mf = - new mem_fetch(access, NULL, wr ? WRITE_PACKET_SIZE : READ_PACKET_SIZE, -1, - m_core_id, m_cluster_id, m_memory_config, cycle); - return mf; +mem_fetch *shader_core_mem_fetch_allocator::alloc( new_addr_type addr, mem_access_type type, unsigned size, bool wr, unsigned long long cycle ) const +{ + mem_access_t access( type, addr, size, wr, m_memory_config->gpgpu_ctx); + mem_fetch *mf = new mem_fetch( access, + NULL, + wr?WRITE_PACKET_SIZE:READ_PACKET_SIZE, + -1, + m_core_id, + m_cluster_id, + m_memory_config, + cycle); + return mf; } ///////////////////////////////////////////////////////////////////////////// -std::list<unsigned> shader_core_ctx::get_regs_written(const inst_t &fvt) const { - std::list<unsigned> result; - for (unsigned op = 0; op < MAX_REG_OPERANDS; op++) { - int reg_num = fvt.arch_reg.dst[op]; // this math needs to match that used - // in function_info::ptx_decode_inst - if (reg_num >= 0) // valid register - result.push_back(reg_num); - } - return result; +std::list<unsigned> shader_core_ctx::get_regs_written( const inst_t &fvt ) const +{ + std::list<unsigned> result; + for( unsigned op=0; op < MAX_REG_OPERANDS; op++ ) { + int reg_num = fvt.arch_reg.dst[op]; // this math needs to match that used in function_info::ptx_decode_inst + if( reg_num >= 0 ) // valid register + result.push_back(reg_num); + } + return result; } -shader_core_ctx::shader_core_ctx(class gpgpu_sim *gpu, - class simt_core_cluster *cluster, - unsigned shader_id, unsigned tpc_id, - const shader_core_config *config, - const memory_config *mem_config, - shader_core_stats *stats) - : core_t(gpu, NULL, config->warp_size, config->n_thread_per_shader), - m_barriers(this, config->max_warps_per_shader, config->max_cta_per_core, - config->max_barriers_per_cta, config->warp_size), - m_active_warps(0), - m_dynamic_warp_id(0) { - m_cluster = cluster; - m_config = config; - m_memory_config = mem_config; - m_stats = stats; - unsigned warp_size = config->warp_size; - Issue_Prio = 0; - - m_sid = shader_id; - m_tpc = tpc_id; - - m_pipeline_reg.reserve(N_PIPELINE_STAGES); - for (int j = 0; j < N_PIPELINE_STAGES; j++) { - m_pipeline_reg.push_back( - register_set(m_config->pipe_widths[j], pipeline_stage_name_decode[j])); - } - if (m_config->sub_core_model) { - // in subcore model, each scheduler should has its own issue register, so - // num scheduler = reg width - assert(m_config->gpgpu_num_sched_per_core == - m_pipeline_reg[ID_OC_SP].get_size()); - assert(m_config->gpgpu_num_sched_per_core == - m_pipeline_reg[ID_OC_SFU].get_size()); - assert(m_config->gpgpu_num_sched_per_core == - m_pipeline_reg[ID_OC_MEM].get_size()); - if (m_config->gpgpu_tensor_core_avail) - assert(m_config->gpgpu_num_sched_per_core == - m_pipeline_reg[ID_OC_TENSOR_CORE].get_size()); - if (m_config->gpgpu_num_dp_units > 0) - assert(m_config->gpgpu_num_sched_per_core == - m_pipeline_reg[ID_OC_DP].get_size()); - if (m_config->gpgpu_num_int_units > 0) - assert(m_config->gpgpu_num_sched_per_core == - m_pipeline_reg[ID_OC_INT].get_size()); - } - - m_threadState = - (thread_ctx_t *)calloc(sizeof(thread_ctx_t), config->n_thread_per_shader); - - m_not_completed = 0; - m_active_threads.reset(); - m_n_active_cta = 0; - for (unsigned i = 0; i < MAX_CTA_PER_SHADER; i++) m_cta_status[i] = 0; - for (unsigned i = 0; i < config->n_thread_per_shader; i++) { - m_thread[i] = NULL; - m_threadState[i].m_cta_id = -1; - m_threadState[i].m_active = false; - } - - // m_icnt = new shader_memory_interface(this,cluster); - if (m_config->gpgpu_perfect_mem) { - m_icnt = new perfect_memory_interface(this, cluster); - } else { - m_icnt = new shader_memory_interface(this, cluster); - } - m_mem_fetch_allocator = - new shader_core_mem_fetch_allocator(shader_id, tpc_id, mem_config); - - // fetch - m_last_warp_fetched = 0; - -#define STRSIZE 1024 - char name[STRSIZE]; - snprintf(name, STRSIZE, "L1I_%03d", m_sid); - m_L1I = new read_only_cache(name, m_config->m_L1I_config, m_sid, - get_shader_instruction_cache_id(), m_icnt, - IN_L1I_MISS_QUEUE); - - m_warp.resize(m_config->max_warps_per_shader, shd_warp_t(this, warp_size)); - m_scoreboard = new Scoreboard(m_sid, m_config->max_warps_per_shader, gpu); - - // scedulers - // must currently occur after all inputs have been initialized. - std::string sched_config = m_config->gpgpu_scheduler_string; - const concrete_scheduler scheduler = - sched_config.find("lrr") != std::string::npos - ? CONCRETE_SCHEDULER_LRR - : sched_config.find("two_level_active") != std::string::npos - ? CONCRETE_SCHEDULER_TWO_LEVEL_ACTIVE - : sched_config.find("gto") != std::string::npos - ? CONCRETE_SCHEDULER_GTO - : sched_config.find("old") != std::string::npos - ? CONCRETE_SCHEDULER_OLDEST_FIRST - : sched_config.find("warp_limiting") != - std::string::npos - ? CONCRETE_SCHEDULER_WARP_LIMITING - : NUM_CONCRETE_SCHEDULERS; - assert(scheduler != NUM_CONCRETE_SCHEDULERS); - - for (unsigned i = 0; i < m_config->gpgpu_num_sched_per_core; i++) { - switch (scheduler) { - case CONCRETE_SCHEDULER_LRR: - schedulers.push_back(new lrr_scheduler( - m_stats, this, m_scoreboard, m_simt_stack, &m_warp, - &m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_DP], - &m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_INT], - &m_pipeline_reg[ID_OC_TENSOR_CORE], &m_pipeline_reg[ID_OC_MEM], i)); - break; - case CONCRETE_SCHEDULER_TWO_LEVEL_ACTIVE: - schedulers.push_back(new two_level_active_scheduler( - m_stats, this, m_scoreboard, m_simt_stack, &m_warp, - &m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_DP], - &m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_INT], - &m_pipeline_reg[ID_OC_TENSOR_CORE], &m_pipeline_reg[ID_OC_MEM], i, - config->gpgpu_scheduler_string)); - break; - case CONCRETE_SCHEDULER_GTO: - schedulers.push_back(new gto_scheduler( - m_stats, this, m_scoreboard, m_simt_stack, &m_warp, - &m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_DP], - &m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_INT], - &m_pipeline_reg[ID_OC_TENSOR_CORE], &m_pipeline_reg[ID_OC_MEM], i)); - break; - case CONCRETE_SCHEDULER_OLDEST_FIRST: - schedulers.push_back(new oldest_scheduler( - m_stats, this, m_scoreboard, m_simt_stack, &m_warp, - &m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_DP], - &m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_INT], - &m_pipeline_reg[ID_OC_TENSOR_CORE], &m_pipeline_reg[ID_OC_MEM], i)); - break; - case CONCRETE_SCHEDULER_WARP_LIMITING: - schedulers.push_back(new swl_scheduler( - m_stats, this, m_scoreboard, m_simt_stack, &m_warp, - &m_pipeline_reg[ID_OC_SP], &m_pipeline_reg[ID_OC_DP], - &m_pipeline_reg[ID_OC_SFU], &m_pipeline_reg[ID_OC_INT], - &m_pipeline_reg[ID_OC_TENSOR_CORE], &m_pipeline_reg[ID_OC_MEM], i, - config->gpgpu_scheduler_string)); - break; - default: - abort(); - }; - } - - for (unsigned i = 0; i < m_warp.size(); i++) { - // distribute i's evenly though schedulers; - schedulers[i % m_config->gpgpu_num_sched_per_core]->add_supervised_warp_id( - i); - } - for (unsigned i = 0; i < m_config->gpgpu_num_sched_per_core; ++i) { - schedulers[i]->done_adding_supervised_warps(); - } - - // op collector configuration - - enum { SP_CUS, DP_CUS, SFU_CUS, TENSOR_CORE_CUS, INT_CUS, MEM_CUS, GEN_CUS }; - - opndcoll_rfu_t::port_vector_t in_ports; - opndcoll_rfu_t::port_vector_t out_ports; - opndcoll_rfu_t::uint_vector_t cu_sets; - - // configure generic collectors - m_operand_collector.add_cu_set( - GEN_CUS, m_config->gpgpu_operand_collector_num_units_gen, - m_config->gpgpu_operand_collector_num_out_ports_gen); - - for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_gen; - i++) { - in_ports.push_back(&m_pipeline_reg[ID_OC_SP]); - in_ports.push_back(&m_pipeline_reg[ID_OC_SFU]); - in_ports.push_back(&m_pipeline_reg[ID_OC_MEM]); - out_ports.push_back(&m_pipeline_reg[OC_EX_SP]); - out_ports.push_back(&m_pipeline_reg[OC_EX_SFU]); - out_ports.push_back(&m_pipeline_reg[OC_EX_MEM]); - if (m_config->gpgpu_tensor_core_avail) { - in_ports.push_back(&m_pipeline_reg[ID_OC_TENSOR_CORE]); - out_ports.push_back(&m_pipeline_reg[OC_EX_TENSOR_CORE]); - } - if (m_config->gpgpu_num_dp_units > 0) { - in_ports.push_back(&m_pipeline_reg[ID_OC_DP]); - out_ports.push_back(&m_pipeline_reg[OC_EX_DP]); - } - if (m_config->gpgpu_num_int_units > 0) { - in_ports.push_back(&m_pipeline_reg[ID_OC_INT]); - out_ports.push_back(&m_pipeline_reg[OC_EX_INT]); +shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu, + class simt_core_cluster *cluster, + unsigned shader_id, + unsigned tpc_id, + const shader_core_config *config, + const memory_config *mem_config, + shader_core_stats *stats ) + : core_t( gpu, NULL, config->warp_size, config->n_thread_per_shader ), + m_barriers( this, config->max_warps_per_shader, config->max_cta_per_core, config->max_barriers_per_cta, config->warp_size ), + m_active_warps(0), m_dynamic_warp_id(0) +{ + m_cluster = cluster; + m_config = config; + m_memory_config = mem_config; + m_stats = stats; + unsigned warp_size=config->warp_size; + Issue_Prio = 0; + + m_sid = shader_id; + m_tpc = tpc_id; + + m_pipeline_reg.reserve(N_PIPELINE_STAGES); + for (int j = 0; j<N_PIPELINE_STAGES; j++) { + m_pipeline_reg.push_back(register_set(m_config->pipe_widths[j],pipeline_stage_name_decode[j])); } - cu_sets.push_back((unsigned)GEN_CUS); - m_operand_collector.add_port(in_ports, out_ports, cu_sets); - in_ports.clear(), out_ports.clear(), cu_sets.clear(); - } - - if (m_config->enable_specialized_operand_collector) { - m_operand_collector.add_cu_set( - SP_CUS, m_config->gpgpu_operand_collector_num_units_sp, - m_config->gpgpu_operand_collector_num_out_ports_sp); - m_operand_collector.add_cu_set( - DP_CUS, m_config->gpgpu_operand_collector_num_units_dp, - m_config->gpgpu_operand_collector_num_out_ports_dp); - m_operand_collector.add_cu_set( - TENSOR_CORE_CUS, config->gpgpu_operand_collector_num_units_tensor_core, - config->gpgpu_operand_collector_num_out_ports_tensor_core); - m_operand_collector.add_cu_set( - SFU_CUS, m_config->gpgpu_operand_collector_num_units_sfu, - m_config->gpgpu_operand_collector_num_out_ports_sfu); - m_operand_collector.add_cu_set( - MEM_CUS, m_config->gpgpu_operand_collector_num_units_mem, - m_config->gpgpu_operand_collector_num_out_ports_mem); - m_operand_collector.add_cu_set( - INT_CUS, m_config->gpgpu_operand_collector_num_units_int, - m_config->gpgpu_operand_collector_num_out_ports_int); - - for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_sp; - i++) { - in_ports.push_back(&m_pipeline_reg[ID_OC_SP]); - out_ports.push_back(&m_pipeline_reg[OC_EX_SP]); - cu_sets.push_back((unsigned)SP_CUS); - cu_sets.push_back((unsigned)GEN_CUS); - m_operand_collector.add_port(in_ports, out_ports, cu_sets); - in_ports.clear(), out_ports.clear(), cu_sets.clear(); + if(m_config->sub_core_model) { + //in subcore model, each scheduler should has its own issue register, so num scheduler = reg width + assert(m_config->gpgpu_num_sched_per_core == m_pipeline_reg[ID_OC_SP].get_size() ); + assert(m_config->gpgpu_num_sched_per_core == m_pipeline_reg[ID_OC_SFU].get_size() ); + assert(m_config->gpgpu_num_sched_per_core == m_pipeline_reg[ID_OC_MEM].get_size() ); + if(m_config->gpgpu_tensor_core_avail) + assert(m_config->gpgpu_num_sched_per_core == m_pipeline_reg[ID_OC_TENSOR_CORE].get_size() ); + if(m_config->gpgpu_num_dp_units > 0) + assert(m_config->gpgpu_num_sched_per_core == m_pipeline_reg[ID_OC_DP].get_size() ); + if(m_config->gpgpu_num_int_units > 0) + assert(m_config->gpgpu_num_sched_per_core == m_pipeline_reg[ID_OC_INT].get_size() ); } - - for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_dp; - i++) { - in_ports.push_back(&m_pipeline_reg[ID_OC_DP]); - out_ports.push_back(&m_pipeline_reg[OC_EX_DP]); - cu_sets.push_back((unsigned)DP_CUS); - cu_sets.push_back((unsigned)GEN_CUS); - m_operand_collector.add_port(in_ports, out_ports, cu_sets); - in_ports.clear(), out_ports.clear(), cu_sets.clear(); + + m_threadState = (thread_ctx_t*) calloc(sizeof(thread_ctx_t), config->n_thread_per_shader); + + m_not_completed = 0; + m_active_threads.reset(); + m_n_active_cta = 0; + for ( unsigned i = 0; i<MAX_CTA_PER_SHADER; i++ ) + m_cta_status[i]=0; + for (unsigned i = 0; i<config->n_thread_per_shader; i++) { + m_thread[i]= NULL; + m_threadState[i].m_cta_id = -1; + m_threadState[i].m_active = false; } - - for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_sfu; - i++) { - in_ports.push_back(&m_pipeline_reg[ID_OC_SFU]); - out_ports.push_back(&m_pipeline_reg[OC_EX_SFU]); - cu_sets.push_back((unsigned)SFU_CUS); - cu_sets.push_back((unsigned)GEN_CUS); - m_operand_collector.add_port(in_ports, out_ports, cu_sets); - in_ports.clear(), out_ports.clear(), cu_sets.clear(); + + // m_icnt = new shader_memory_interface(this,cluster); + if ( m_config->gpgpu_perfect_mem ) { + m_icnt = new perfect_memory_interface(this,cluster); + } else { + m_icnt = new shader_memory_interface(this,cluster); } - - for (unsigned i = 0; - i < config->gpgpu_operand_collector_num_in_ports_tensor_core; i++) { - in_ports.push_back(&m_pipeline_reg[ID_OC_TENSOR_CORE]); - out_ports.push_back(&m_pipeline_reg[OC_EX_TENSOR_CORE]); - cu_sets.push_back((unsigned)TENSOR_CORE_CUS); - cu_sets.push_back((unsigned)GEN_CUS); - m_operand_collector.add_port(in_ports, out_ports, cu_sets); - in_ports.clear(), out_ports.clear(), cu_sets.clear(); + m_mem_fetch_allocator = new shader_core_mem_fetch_allocator(shader_id,tpc_id,mem_config); + + // fetch + m_last_warp_fetched = 0; + + #define STRSIZE 1024 + char name[STRSIZE]; + snprintf(name, STRSIZE, "L1I_%03d", m_sid); + m_L1I = new read_only_cache( name,m_config->m_L1I_config,m_sid,get_shader_instruction_cache_id(),m_icnt,IN_L1I_MISS_QUEUE); + + m_warp.resize(m_config->max_warps_per_shader, shd_warp_t(this, warp_size)); + m_scoreboard = new Scoreboard(m_sid, m_config->max_warps_per_shader, gpu); + + //scedulers + //must currently occur after all inputs have been initialized. + std::string sched_config = m_config->gpgpu_scheduler_string; + const concrete_scheduler scheduler = sched_config.find("lrr") != std::string::npos ? + CONCRETE_SCHEDULER_LRR : + sched_config.find("two_level_active") != std::string::npos ? + CONCRETE_SCHEDULER_TWO_LEVEL_ACTIVE : + sched_config.find("gto") != std::string::npos ? + CONCRETE_SCHEDULER_GTO : + sched_config.find("old") != std::string::npos ? + CONCRETE_SCHEDULER_OLDEST_FIRST : + sched_config.find("warp_limiting") != std::string::npos ? + CONCRETE_SCHEDULER_WARP_LIMITING: + NUM_CONCRETE_SCHEDULERS; + assert ( scheduler != NUM_CONCRETE_SCHEDULERS ); + + for (unsigned i = 0; i < m_config->gpgpu_num_sched_per_core; i++) { + switch( scheduler ) + { + case CONCRETE_SCHEDULER_LRR: + schedulers.push_back( + new lrr_scheduler( m_stats, + this, + m_scoreboard, + m_simt_stack, + &m_warp, + &m_pipeline_reg[ID_OC_SP], + &m_pipeline_reg[ID_OC_DP], + &m_pipeline_reg[ID_OC_SFU], + &m_pipeline_reg[ID_OC_INT], + &m_pipeline_reg[ID_OC_TENSOR_CORE], + &m_pipeline_reg[ID_OC_MEM], + i + ) + ); + break; + case CONCRETE_SCHEDULER_TWO_LEVEL_ACTIVE: + schedulers.push_back( + new two_level_active_scheduler( m_stats, + this, + m_scoreboard, + m_simt_stack, + &m_warp, + &m_pipeline_reg[ID_OC_SP], + &m_pipeline_reg[ID_OC_DP], + &m_pipeline_reg[ID_OC_SFU], + &m_pipeline_reg[ID_OC_INT], + &m_pipeline_reg[ID_OC_TENSOR_CORE], + &m_pipeline_reg[ID_OC_MEM], + i, + config->gpgpu_scheduler_string + ) + ); + break; + case CONCRETE_SCHEDULER_GTO: + schedulers.push_back( + new gto_scheduler( m_stats, + this, + m_scoreboard, + m_simt_stack, + &m_warp, + &m_pipeline_reg[ID_OC_SP], + &m_pipeline_reg[ID_OC_DP], + &m_pipeline_reg[ID_OC_SFU], + &m_pipeline_reg[ID_OC_INT], + &m_pipeline_reg[ID_OC_TENSOR_CORE], + &m_pipeline_reg[ID_OC_MEM], + i + ) + ); + break; + case CONCRETE_SCHEDULER_OLDEST_FIRST: + schedulers.push_back( + new oldest_scheduler( m_stats, + this, + m_scoreboard, + m_simt_stack, + &m_warp, + &m_pipeline_reg[ID_OC_SP], + &m_pipeline_reg[ID_OC_DP], + &m_pipeline_reg[ID_OC_SFU], + &m_pipeline_reg[ID_OC_INT], + &m_pipeline_reg[ID_OC_TENSOR_CORE], + &m_pipeline_reg[ID_OC_MEM], + i + ) + ); + break; + case CONCRETE_SCHEDULER_WARP_LIMITING: + schedulers.push_back( + new swl_scheduler( m_stats, + this, + m_scoreboard, + m_simt_stack, + &m_warp, + &m_pipeline_reg[ID_OC_SP], + &m_pipeline_reg[ID_OC_DP], + &m_pipeline_reg[ID_OC_SFU], + &m_pipeline_reg[ID_OC_INT], + &m_pipeline_reg[ID_OC_TENSOR_CORE], + &m_pipeline_reg[ID_OC_MEM], + i, + config->gpgpu_scheduler_string + ) + ); + break; + default: + abort(); + }; } - - for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_mem; - i++) { - in_ports.push_back(&m_pipeline_reg[ID_OC_MEM]); - out_ports.push_back(&m_pipeline_reg[OC_EX_MEM]); - cu_sets.push_back((unsigned)MEM_CUS); - cu_sets.push_back((unsigned)GEN_CUS); - m_operand_collector.add_port(in_ports, out_ports, cu_sets); - in_ports.clear(), out_ports.clear(), cu_sets.clear(); + + for (unsigned i = 0; i < m_warp.size(); i++) { + //distribute i's evenly though schedulers; + schedulers[i%m_config->gpgpu_num_sched_per_core]->add_supervised_warp_id(i); } - - for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_int; - i++) { - in_ports.push_back(&m_pipeline_reg[ID_OC_INT]); - out_ports.push_back(&m_pipeline_reg[OC_EX_INT]); - cu_sets.push_back((unsigned)INT_CUS); - cu_sets.push_back((unsigned)GEN_CUS); - m_operand_collector.add_port(in_ports, out_ports, cu_sets); - in_ports.clear(), out_ports.clear(), cu_sets.clear(); + for ( unsigned i = 0; i < m_config->gpgpu_num_sched_per_core; ++i ) { + schedulers[i]->done_adding_supervised_warps(); } - } + + //op collector configuration - m_operand_collector.init(m_config->gpgpu_num_reg_banks, this); + enum { SP_CUS, DP_CUS, SFU_CUS, TENSOR_CORE_CUS, INT_CUS, MEM_CUS, GEN_CUS }; - m_num_function_units = - m_config->gpgpu_num_sp_units + m_config->gpgpu_num_dp_units + - m_config->gpgpu_num_sfu_units + m_config->gpgpu_num_tensor_core_units + - m_config->gpgpu_num_int_units + - 1; // sp_unit, sfu, dp, tensor, int, ldst_unit - // m_dispatch_port = new enum pipeline_stage_name_t[ m_num_function_units ]; - // m_issue_port = new enum pipeline_stage_name_t[ m_num_function_units ]; + opndcoll_rfu_t::port_vector_t in_ports; + opndcoll_rfu_t::port_vector_t out_ports; + opndcoll_rfu_t::uint_vector_t cu_sets; - // m_fu = new simd_function_unit*[m_num_function_units]; + //configure generic collectors + m_operand_collector.add_cu_set(GEN_CUS, m_config->gpgpu_operand_collector_num_units_gen, m_config->gpgpu_operand_collector_num_out_ports_gen); - for (int k = 0; k < m_config->gpgpu_num_sp_units; k++) { - m_fu.push_back(new sp_unit(&m_pipeline_reg[EX_WB], m_config, this)); - m_dispatch_port.push_back(ID_OC_SP); - m_issue_port.push_back(OC_EX_SP); - } + for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_gen; i++) { + in_ports.push_back(&m_pipeline_reg[ID_OC_SP]); + in_ports.push_back(&m_pipeline_reg[ID_OC_SFU]); + in_ports.push_back(&m_pipeline_reg[ID_OC_MEM]); + out_ports.push_back(&m_pipeline_reg[OC_EX_SP]); + out_ports.push_back(&m_pipeline_reg[OC_EX_SFU]); + out_ports.push_back(&m_pipeline_reg[OC_EX_MEM]); + if(m_config->gpgpu_tensor_core_avail) { + in_ports.push_back(&m_pipeline_reg[ID_OC_TENSOR_CORE]); + out_ports.push_back(&m_pipeline_reg[OC_EX_TENSOR_CORE]); + } + if(m_config->gpgpu_num_dp_units > 0) { + in_ports.push_back(&m_pipeline_reg[ID_OC_DP]); + out_ports.push_back(&m_pipeline_reg[OC_EX_DP]); + } + if(m_config->gpgpu_num_int_units > 0) { + in_ports.push_back(&m_pipeline_reg[ID_OC_INT]); + out_ports.push_back(&m_pipeline_reg[OC_EX_INT]); + } + cu_sets.push_back((unsigned)GEN_CUS); + m_operand_collector.add_port(in_ports,out_ports,cu_sets); + in_ports.clear(),out_ports.clear(),cu_sets.clear(); + } - for (int k = 0; k < m_config->gpgpu_num_dp_units; k++) { - m_fu.push_back(new dp_unit(&m_pipeline_reg[EX_WB], m_config, this)); - m_dispatch_port.push_back(ID_OC_DP); - m_issue_port.push_back(OC_EX_DP); - } - for (int k = 0; k < m_config->gpgpu_num_int_units; k++) { - m_fu.push_back(new int_unit(&m_pipeline_reg[EX_WB], m_config, this)); - m_dispatch_port.push_back(ID_OC_INT); - m_issue_port.push_back(OC_EX_INT); - } + if(m_config->enable_specialized_operand_collector) { + m_operand_collector.add_cu_set(SP_CUS, m_config->gpgpu_operand_collector_num_units_sp, m_config->gpgpu_operand_collector_num_out_ports_sp); + m_operand_collector.add_cu_set(DP_CUS, m_config->gpgpu_operand_collector_num_units_dp, m_config->gpgpu_operand_collector_num_out_ports_dp); + m_operand_collector.add_cu_set(TENSOR_CORE_CUS, config->gpgpu_operand_collector_num_units_tensor_core, config->gpgpu_operand_collector_num_out_ports_tensor_core); + m_operand_collector.add_cu_set(SFU_CUS, m_config->gpgpu_operand_collector_num_units_sfu, m_config->gpgpu_operand_collector_num_out_ports_sfu); + m_operand_collector.add_cu_set(MEM_CUS, m_config->gpgpu_operand_collector_num_units_mem, m_config->gpgpu_operand_collector_num_out_ports_mem); + m_operand_collector.add_cu_set(INT_CUS, m_config->gpgpu_operand_collector_num_units_int, m_config->gpgpu_operand_collector_num_out_ports_int); - for (int k = 0; k < m_config->gpgpu_num_sfu_units; k++) { - m_fu.push_back(new sfu(&m_pipeline_reg[EX_WB], m_config, this)); - m_dispatch_port.push_back(ID_OC_SFU); - m_issue_port.push_back(OC_EX_SFU); - } + for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_sp; i++) { + in_ports.push_back(&m_pipeline_reg[ID_OC_SP]); + out_ports.push_back(&m_pipeline_reg[OC_EX_SP]); + cu_sets.push_back((unsigned)SP_CUS); + cu_sets.push_back((unsigned)GEN_CUS); + m_operand_collector.add_port(in_ports,out_ports,cu_sets); + in_ports.clear(),out_ports.clear(),cu_sets.clear(); + } - for (int k = 0; k < config->gpgpu_num_tensor_core_units; k++) { - m_fu.push_back(new tensor_core(&m_pipeline_reg[EX_WB], m_config, this)); - m_dispatch_port.push_back(ID_OC_TENSOR_CORE); - m_issue_port.push_back(OC_EX_TENSOR_CORE); - } + for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_dp; i++) { + in_ports.push_back(&m_pipeline_reg[ID_OC_DP]); + out_ports.push_back(&m_pipeline_reg[OC_EX_DP]); + cu_sets.push_back((unsigned)DP_CUS); + cu_sets.push_back((unsigned)GEN_CUS); + m_operand_collector.add_port(in_ports,out_ports,cu_sets); + in_ports.clear(),out_ports.clear(),cu_sets.clear(); + } - m_ldst_unit = - new ldst_unit(m_icnt, m_mem_fetch_allocator, this, &m_operand_collector, - m_scoreboard, config, mem_config, stats, shader_id, tpc_id); - m_fu.push_back(m_ldst_unit); - m_dispatch_port.push_back(ID_OC_MEM); - m_issue_port.push_back(OC_EX_MEM); + for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_sfu; i++) { + in_ports.push_back(&m_pipeline_reg[ID_OC_SFU]); + out_ports.push_back(&m_pipeline_reg[OC_EX_SFU]); + cu_sets.push_back((unsigned)SFU_CUS); + cu_sets.push_back((unsigned)GEN_CUS); + m_operand_collector.add_port(in_ports,out_ports,cu_sets); + in_ports.clear(),out_ports.clear(),cu_sets.clear(); + } - assert(m_num_function_units == m_fu.size() and - m_fu.size() == m_dispatch_port.size() and - m_fu.size() == m_issue_port.size()); + for (unsigned i = 0; i < config->gpgpu_operand_collector_num_in_ports_tensor_core; i++) { + in_ports.push_back(&m_pipeline_reg[ID_OC_TENSOR_CORE]); + out_ports.push_back(&m_pipeline_reg[OC_EX_TENSOR_CORE]); + cu_sets.push_back((unsigned)TENSOR_CORE_CUS); + cu_sets.push_back((unsigned)GEN_CUS); + m_operand_collector.add_port(in_ports,out_ports,cu_sets); + in_ports.clear(),out_ports.clear(),cu_sets.clear(); + } - // there are as many result buses as the width of the EX_WB stage - num_result_bus = config->pipe_widths[EX_WB]; - for (unsigned i = 0; i < num_result_bus; i++) { - this->m_result_bus.push_back(new std::bitset<MAX_ALU_LATENCY>()); - } + for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_mem; i++) { + in_ports.push_back(&m_pipeline_reg[ID_OC_MEM]); + out_ports.push_back(&m_pipeline_reg[OC_EX_MEM]); + cu_sets.push_back((unsigned)MEM_CUS); + cu_sets.push_back((unsigned)GEN_CUS); + m_operand_collector.add_port(in_ports,out_ports,cu_sets); + in_ports.clear(),out_ports.clear(),cu_sets.clear(); + } - m_last_inst_gpu_sim_cycle = 0; - m_last_inst_gpu_tot_sim_cycle = 0; + for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_int; i++) { + in_ports.push_back(&m_pipeline_reg[ID_OC_INT]); + out_ports.push_back(&m_pipeline_reg[OC_EX_INT]); + cu_sets.push_back((unsigned)INT_CUS); + cu_sets.push_back((unsigned)GEN_CUS); + m_operand_collector.add_port(in_ports,out_ports,cu_sets); + in_ports.clear(),out_ports.clear(),cu_sets.clear(); + } + } + + m_operand_collector.init( m_config->gpgpu_num_reg_banks, this ); + + m_num_function_units = m_config->gpgpu_num_sp_units + m_config->gpgpu_num_dp_units + m_config->gpgpu_num_sfu_units + m_config->gpgpu_num_tensor_core_units + m_config->gpgpu_num_int_units + 1; // sp_unit, sfu, dp, tensor, int, ldst_unit + //m_dispatch_port = new enum pipeline_stage_name_t[ m_num_function_units ]; + //m_issue_port = new enum pipeline_stage_name_t[ m_num_function_units ]; + + //m_fu = new simd_function_unit*[m_num_function_units]; + + for (int k = 0; k < m_config->gpgpu_num_sp_units; k++) { + m_fu.push_back(new sp_unit( &m_pipeline_reg[EX_WB], m_config, this )); + m_dispatch_port.push_back(ID_OC_SP); + m_issue_port.push_back(OC_EX_SP); + } + + for (int k = 0; k < m_config->gpgpu_num_dp_units; k++) { + m_fu.push_back(new dp_unit( &m_pipeline_reg[EX_WB], m_config, this )); + m_dispatch_port.push_back(ID_OC_DP); + m_issue_port.push_back(OC_EX_DP); + } + for (int k = 0; k < m_config->gpgpu_num_int_units; k++) { + m_fu.push_back(new int_unit( &m_pipeline_reg[EX_WB], m_config, this )); + m_dispatch_port.push_back(ID_OC_INT); + m_issue_port.push_back(OC_EX_INT); + } - // Jin: for concurrent kernels on a SM - m_occupied_n_threads = 0; - m_occupied_shmem = 0; - m_occupied_regs = 0; - m_occupied_ctas = 0; - m_occupied_hwtid.reset(); - m_occupied_cta_to_hwtid.clear(); -} + for (int k = 0; k < m_config->gpgpu_num_sfu_units; k++) { + m_fu.push_back(new sfu( &m_pipeline_reg[EX_WB], m_config, this )); + m_dispatch_port.push_back(ID_OC_SFU); + m_issue_port.push_back(OC_EX_SFU); + } + + for (int k = 0; k < config->gpgpu_num_tensor_core_units; k++) { + m_fu.push_back(new tensor_core( &m_pipeline_reg[EX_WB], m_config, this )); + m_dispatch_port.push_back(ID_OC_TENSOR_CORE); + m_issue_port.push_back(OC_EX_TENSOR_CORE); + } -void shader_core_ctx::reinit(unsigned start_thread, unsigned end_thread, - bool reset_not_completed) { - if (reset_not_completed) { - m_not_completed = 0; - m_active_threads.reset(); + m_ldst_unit = new ldst_unit( m_icnt, m_mem_fetch_allocator, this, &m_operand_collector, m_scoreboard, config, mem_config, stats, shader_id, tpc_id ); + m_fu.push_back(m_ldst_unit); + m_dispatch_port.push_back(ID_OC_MEM); + m_issue_port.push_back(OC_EX_MEM); + + assert(m_num_function_units == m_fu.size() and m_fu.size() == m_dispatch_port.size() and m_fu.size() == m_issue_port.size()); + + //there are as many result buses as the width of the EX_WB stage + num_result_bus = config->pipe_widths[EX_WB]; + for(unsigned i=0; i<num_result_bus; i++){ + this->m_result_bus.push_back(new std::bitset<MAX_ALU_LATENCY>()); + } + + m_last_inst_gpu_sim_cycle = 0; + m_last_inst_gpu_tot_sim_cycle = 0; - // Jin: for concurrent kernels on a SM + //Jin: for concurrent kernels on a SM m_occupied_n_threads = 0; m_occupied_shmem = 0; m_occupied_regs = 0; m_occupied_ctas = 0; m_occupied_hwtid.reset(); m_occupied_cta_to_hwtid.clear(); - m_active_warps = 0; - } - for (unsigned i = start_thread; i < end_thread; i++) { - m_threadState[i].n_insn = 0; - m_threadState[i].m_cta_id = -1; - } - for (unsigned i = start_thread / m_config->warp_size; - i < end_thread / m_config->warp_size; ++i) { - m_warp[i].reset(); - m_simt_stack[i]->reset(); - } } -void shader_core_ctx::init_warps(unsigned cta_id, unsigned start_thread, - unsigned end_thread, unsigned ctaid, - int cta_size, unsigned kernel_id) { - address_type start_pc = next_pc(start_thread); - if (m_config->model == POST_DOMINATOR) { - unsigned start_warp = start_thread / m_config->warp_size; - unsigned warp_per_cta = cta_size / m_config->warp_size; - unsigned end_warp = end_thread / m_config->warp_size + - ((end_thread % m_config->warp_size) ? 1 : 0); - for (unsigned i = start_warp; i < end_warp; ++i) { - unsigned n_active = 0; - simt_mask_t active_threads; - for (unsigned t = 0; t < m_config->warp_size; t++) { - unsigned hwtid = i * m_config->warp_size + t; - if (hwtid < end_thread) { - n_active++; - assert(!m_active_threads.test(hwtid)); - m_active_threads.set(hwtid); - active_threads.set(t); - } - } - m_simt_stack[i]->launch(start_pc, active_threads); +void shader_core_ctx::reinit(unsigned start_thread, unsigned end_thread, bool reset_not_completed ) +{ + if( reset_not_completed ) { + m_not_completed = 0; + m_active_threads.reset(); - if (m_gpu->resume_option == 1 && kernel_id == m_gpu->resume_kernel && - ctaid >= m_gpu->resume_CTA && ctaid < m_gpu->checkpoint_CTA_t) { - char fname[2048]; - snprintf(fname, 2048, "checkpoint_files/warp_%d_%d_simt.txt", - i % warp_per_cta, ctaid); - unsigned pc, rpc; - m_simt_stack[i]->resume(fname); - m_simt_stack[i]->get_pdom_stack_top_info(&pc, &rpc); - for (unsigned t = 0; t < m_config->warp_size; t++) { - m_thread[i * m_config->warp_size + t]->set_npc(pc); - m_thread[i * m_config->warp_size + t]->update_pc(); - } - start_pc = pc; - } + //Jin: for concurrent kernels on a SM + m_occupied_n_threads = 0; + m_occupied_shmem = 0; + m_occupied_regs = 0; + m_occupied_ctas = 0; + m_occupied_hwtid.reset(); + m_occupied_cta_to_hwtid.clear(); + m_active_warps = 0; - m_warp[i].init(start_pc, cta_id, i, active_threads, m_dynamic_warp_id); - ++m_dynamic_warp_id; - m_not_completed += n_active; - ++m_active_warps; - } - } + } + for (unsigned i = start_thread; i<end_thread; i++) { + m_threadState[i].n_insn = 0; + m_threadState[i].m_cta_id = -1; + } + for (unsigned i = start_thread / m_config->warp_size; i < end_thread / m_config->warp_size; ++i) { + m_warp[i].reset(); + m_simt_stack[i]->reset(); + } } -// return the next pc of a thread -address_type shader_core_ctx::next_pc(int tid) const { - if (tid == -1) return -1; - ptx_thread_info *the_thread = m_thread[tid]; - if (the_thread == NULL) return -1; - return the_thread->get_pc(); // PC should already be updatd to next PC at - // this point (was set in shader_decode() last - // time thread ran) +void shader_core_ctx::init_warps( unsigned cta_id, unsigned start_thread, unsigned end_thread, unsigned ctaid, int cta_size, unsigned kernel_id ) +{ + address_type start_pc = next_pc(start_thread); + if (m_config->model == POST_DOMINATOR) { + unsigned start_warp = start_thread / m_config->warp_size; + unsigned warp_per_cta = cta_size / m_config->warp_size; + unsigned end_warp = end_thread / m_config->warp_size + ((end_thread % m_config->warp_size)? 1 : 0); + for (unsigned i = start_warp; i < end_warp; ++i) { + unsigned n_active=0; + simt_mask_t active_threads; + for (unsigned t = 0; t < m_config->warp_size; t++) { + unsigned hwtid = i * m_config->warp_size + t; + if ( hwtid < end_thread ) { + n_active++; + assert( !m_active_threads.test(hwtid) ); + m_active_threads.set( hwtid ); + active_threads.set(t); + } + } + m_simt_stack[i]->launch(start_pc,active_threads); + + if(m_gpu->resume_option == 1 && kernel_id == m_gpu->resume_kernel && ctaid >= m_gpu->resume_CTA && ctaid < m_gpu->checkpoint_CTA_t ) + { + char fname[2048]; + snprintf(fname,2048,"checkpoint_files/warp_%d_%d_simt.txt",i%warp_per_cta,ctaid ); + unsigned pc,rpc; + m_simt_stack[i]->resume(fname); + m_simt_stack[i]->get_pdom_stack_top_info(&pc,&rpc); + for (unsigned t = 0; t < m_config->warp_size; t++) { + m_thread[i * m_config->warp_size + t]->set_npc(pc); + m_thread[i * m_config->warp_size + t]->update_pc(); + } + start_pc=pc; + } + + m_warp[i].init(start_pc,cta_id,i,active_threads, m_dynamic_warp_id); + ++m_dynamic_warp_id; + m_not_completed += n_active; + ++m_active_warps; + } + } } -void gpgpu_sim::get_pdom_stack_top_info(unsigned sid, unsigned tid, - unsigned *pc, unsigned *rpc) { - unsigned cluster_id = m_shader_config->sid_to_cluster(sid); - m_cluster[cluster_id]->get_pdom_stack_top_info(sid, tid, pc, rpc); +// return the next pc of a thread +address_type shader_core_ctx::next_pc( int tid ) const +{ + if( tid == -1 ) + return -1; + ptx_thread_info *the_thread = m_thread[tid]; + if ( the_thread == NULL ) + return -1; + return the_thread->get_pc(); // PC should already be updatd to next PC at this point (was set in shader_decode() last time thread ran) } -void shader_core_ctx::get_pdom_stack_top_info(unsigned tid, unsigned *pc, - unsigned *rpc) const { - unsigned warp_id = tid / m_config->warp_size; - m_simt_stack[warp_id]->get_pdom_stack_top_info(pc, rpc); +void gpgpu_sim::get_pdom_stack_top_info( unsigned sid, unsigned tid, unsigned *pc, unsigned *rpc ) +{ + unsigned cluster_id = m_shader_config->sid_to_cluster(sid); + m_cluster[cluster_id]->get_pdom_stack_top_info(sid,tid,pc,rpc); } -float shader_core_ctx::get_current_occupancy(unsigned long long &active, - unsigned long long &total) const { - // To match the achieved_occupancy in nvprof, only SMs that are active are - // counted toward the occupancy. - if (m_active_warps > 0) { - total += m_warp.size(); - active += m_active_warps; - return float(active) / float(total); - } else { - return 0; - } +void shader_core_ctx::get_pdom_stack_top_info( unsigned tid, unsigned *pc, unsigned *rpc ) const +{ + unsigned warp_id = tid/m_config->warp_size; + m_simt_stack[warp_id]->get_pdom_stack_top_info(pc,rpc); } -void shader_core_stats::print(FILE *fout) const { - unsigned long long thread_icount_uarch = 0; - unsigned long long warp_icount_uarch = 0; +float shader_core_ctx::get_current_occupancy( unsigned long long & active, unsigned long long & total ) const +{ + // To match the achieved_occupancy in nvprof, only SMs that are active are counted toward the occupancy. + if ( m_active_warps > 0 ) { + total += m_warp.size(); + active += m_active_warps; + return float(active) / float(total); + } else { + return 0; + } +} - for (unsigned i = 0; i < m_config->num_shader(); i++) { - thread_icount_uarch += m_num_sim_insn[i]; - warp_icount_uarch += m_num_sim_winsn[i]; - } - fprintf(fout, "gpgpu_n_tot_thrd_icount = %lld\n", thread_icount_uarch); - fprintf(fout, "gpgpu_n_tot_w_icount = %lld\n", warp_icount_uarch); +void shader_core_stats::print( FILE* fout ) const +{ + unsigned long long thread_icount_uarch=0; + unsigned long long warp_icount_uarch=0; - fprintf(fout, "gpgpu_n_stall_shd_mem = %d\n", gpgpu_n_stall_shd_mem); - fprintf(fout, "gpgpu_n_mem_read_local = %d\n", gpgpu_n_mem_read_local); - fprintf(fout, "gpgpu_n_mem_write_local = %d\n", gpgpu_n_mem_write_local); - fprintf(fout, "gpgpu_n_mem_read_global = %d\n", gpgpu_n_mem_read_global); - fprintf(fout, "gpgpu_n_mem_write_global = %d\n", gpgpu_n_mem_write_global); - fprintf(fout, "gpgpu_n_mem_texture = %d\n", gpgpu_n_mem_texture); - fprintf(fout, "gpgpu_n_mem_const = %d\n", gpgpu_n_mem_const); + for(unsigned i=0; i < m_config->num_shader(); i++) { + thread_icount_uarch += m_num_sim_insn[i]; + warp_icount_uarch += m_num_sim_winsn[i]; + } + fprintf(fout,"gpgpu_n_tot_thrd_icount = %lld\n", thread_icount_uarch); + fprintf(fout,"gpgpu_n_tot_w_icount = %lld\n", warp_icount_uarch); + + fprintf(fout,"gpgpu_n_stall_shd_mem = %d\n", gpgpu_n_stall_shd_mem ); + fprintf(fout,"gpgpu_n_mem_read_local = %d\n", gpgpu_n_mem_read_local); + fprintf(fout,"gpgpu_n_mem_write_local = %d\n", gpgpu_n_mem_write_local); + fprintf(fout,"gpgpu_n_mem_read_global = %d\n", gpgpu_n_mem_read_global); + fprintf(fout,"gpgpu_n_mem_write_global = %d\n", gpgpu_n_mem_write_global); + fprintf(fout,"gpgpu_n_mem_texture = %d\n", gpgpu_n_mem_texture); + fprintf(fout,"gpgpu_n_mem_const = %d\n", gpgpu_n_mem_const); - fprintf(fout, "gpgpu_n_load_insn = %d\n", gpgpu_n_load_insn); - fprintf(fout, "gpgpu_n_store_insn = %d\n", gpgpu_n_store_insn); - fprintf(fout, "gpgpu_n_shmem_insn = %d\n", gpgpu_n_shmem_insn); - fprintf(fout, "gpgpu_n_sstarr_insn = %d\n", gpgpu_n_sstarr_insn); - fprintf(fout, "gpgpu_n_tex_insn = %d\n", gpgpu_n_tex_insn); - fprintf(fout, "gpgpu_n_const_mem_insn = %d\n", gpgpu_n_const_insn); - fprintf(fout, "gpgpu_n_param_mem_insn = %d\n", gpgpu_n_param_insn); + fprintf(fout, "gpgpu_n_load_insn = %d\n", gpgpu_n_load_insn); + fprintf(fout, "gpgpu_n_store_insn = %d\n", gpgpu_n_store_insn); + fprintf(fout, "gpgpu_n_shmem_insn = %d\n", gpgpu_n_shmem_insn); + fprintf(fout, "gpgpu_n_sstarr_insn = %d\n", gpgpu_n_sstarr_insn); + fprintf(fout, "gpgpu_n_tex_insn = %d\n", gpgpu_n_tex_insn); + fprintf(fout, "gpgpu_n_const_mem_insn = %d\n", gpgpu_n_const_insn); + fprintf(fout, "gpgpu_n_param_mem_insn = %d\n", gpgpu_n_param_insn); - fprintf(fout, "gpgpu_n_shmem_bkconflict = %d\n", gpgpu_n_shmem_bkconflict); - fprintf(fout, "gpgpu_n_cache_bkconflict = %d\n", gpgpu_n_cache_bkconflict); + fprintf(fout, "gpgpu_n_shmem_bkconflict = %d\n", gpgpu_n_shmem_bkconflict); + fprintf(fout, "gpgpu_n_cache_bkconflict = %d\n", gpgpu_n_cache_bkconflict); - fprintf(fout, "gpgpu_n_intrawarp_mshr_merge = %d\n", - gpgpu_n_intrawarp_mshr_merge); - fprintf(fout, "gpgpu_n_cmem_portconflict = %d\n", gpgpu_n_cmem_portconflict); + fprintf(fout, "gpgpu_n_intrawarp_mshr_merge = %d\n", gpgpu_n_intrawarp_mshr_merge); + fprintf(fout, "gpgpu_n_cmem_portconflict = %d\n", gpgpu_n_cmem_portconflict); - fprintf(fout, "gpgpu_stall_shd_mem[c_mem][resource_stall] = %d\n", - gpu_stall_shd_mem_breakdown[C_MEM][BK_CONF]); - // fprintf(fout, "gpgpu_stall_shd_mem[c_mem][mshr_rc] = %d\n", - // gpu_stall_shd_mem_breakdown[C_MEM][MSHR_RC_FAIL]); - // fprintf(fout, "gpgpu_stall_shd_mem[c_mem][icnt_rc] = %d\n", - // gpu_stall_shd_mem_breakdown[C_MEM][ICNT_RC_FAIL]); - // fprintf(fout, "gpgpu_stall_shd_mem[c_mem][data_port_stall] = %d\n", - // gpu_stall_shd_mem_breakdown[C_MEM][DATA_PORT_STALL]); - // fprintf(fout, "gpgpu_stall_shd_mem[t_mem][mshr_rc] = %d\n", - // gpu_stall_shd_mem_breakdown[T_MEM][MSHR_RC_FAIL]); - // fprintf(fout, "gpgpu_stall_shd_mem[t_mem][icnt_rc] = %d\n", - // gpu_stall_shd_mem_breakdown[T_MEM][ICNT_RC_FAIL]); - // fprintf(fout, "gpgpu_stall_shd_mem[t_mem][data_port_stall] = %d\n", - // gpu_stall_shd_mem_breakdown[T_MEM][DATA_PORT_STALL]); - fprintf(fout, "gpgpu_stall_shd_mem[s_mem][bk_conf] = %d\n", - gpu_stall_shd_mem_breakdown[S_MEM][BK_CONF]); - fprintf(fout, "gpgpu_stall_shd_mem[gl_mem][resource_stall] = %d\n", - gpu_stall_shd_mem_breakdown[G_MEM_LD][BK_CONF] + - gpu_stall_shd_mem_breakdown[G_MEM_ST][BK_CONF] + - gpu_stall_shd_mem_breakdown[L_MEM_LD][BK_CONF] + - gpu_stall_shd_mem_breakdown[L_MEM_ST][BK_CONF]); // coalescing - // stall at data - // cache - fprintf(fout, "gpgpu_stall_shd_mem[gl_mem][coal_stall] = %d\n", - gpu_stall_shd_mem_breakdown[G_MEM_LD][COAL_STALL] + - gpu_stall_shd_mem_breakdown[G_MEM_ST][COAL_STALL] + - gpu_stall_shd_mem_breakdown[L_MEM_LD][COAL_STALL] + - gpu_stall_shd_mem_breakdown[L_MEM_ST][COAL_STALL]); // coalescing - // stall + - // bank - // conflict - // at data - // cache - fprintf(fout, "gpgpu_stall_shd_mem[gl_mem][data_port_stall] = %d\n", - gpu_stall_shd_mem_breakdown[G_MEM_LD][DATA_PORT_STALL] + - gpu_stall_shd_mem_breakdown[G_MEM_ST][DATA_PORT_STALL] + - gpu_stall_shd_mem_breakdown[L_MEM_LD][DATA_PORT_STALL] + - gpu_stall_shd_mem_breakdown[L_MEM_ST] - [DATA_PORT_STALL]); // data port stall - // at data cache - // fprintf(fout, "gpgpu_stall_shd_mem[g_mem_ld][mshr_rc] = %d\n", - // gpu_stall_shd_mem_breakdown[G_MEM_LD][MSHR_RC_FAIL]); - // fprintf(fout, "gpgpu_stall_shd_mem[g_mem_ld][icnt_rc] = %d\n", - // gpu_stall_shd_mem_breakdown[G_MEM_LD][ICNT_RC_FAIL]); - // fprintf(fout, "gpgpu_stall_shd_mem[g_mem_ld][wb_icnt_rc] = %d\n", - // gpu_stall_shd_mem_breakdown[G_MEM_LD][WB_ICNT_RC_FAIL]); - // fprintf(fout, "gpgpu_stall_shd_mem[g_mem_ld][wb_rsrv_fail] = %d\n", - // gpu_stall_shd_mem_breakdown[G_MEM_LD][WB_CACHE_RSRV_FAIL]); - // fprintf(fout, "gpgpu_stall_shd_mem[g_mem_st][mshr_rc] = %d\n", - // gpu_stall_shd_mem_breakdown[G_MEM_ST][MSHR_RC_FAIL]); - // fprintf(fout, "gpgpu_stall_shd_mem[g_mem_st][icnt_rc] = %d\n", - // gpu_stall_shd_mem_breakdown[G_MEM_ST][ICNT_RC_FAIL]); - // fprintf(fout, "gpgpu_stall_shd_mem[g_mem_st][wb_icnt_rc] = %d\n", - // gpu_stall_shd_mem_breakdown[G_MEM_ST][WB_ICNT_RC_FAIL]); - // fprintf(fout, "gpgpu_stall_shd_mem[g_mem_st][wb_rsrv_fail] = %d\n", - // gpu_stall_shd_mem_breakdown[G_MEM_ST][WB_CACHE_RSRV_FAIL]); - // fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][mshr_rc] = %d\n", - // gpu_stall_shd_mem_breakdown[L_MEM_LD][MSHR_RC_FAIL]); - // fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][icnt_rc] = %d\n", - // gpu_stall_shd_mem_breakdown[L_MEM_LD][ICNT_RC_FAIL]); - // fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][wb_icnt_rc] = %d\n", - // gpu_stall_shd_mem_breakdown[L_MEM_LD][WB_ICNT_RC_FAIL]); - // fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][wb_rsrv_fail] = %d\n", - // gpu_stall_shd_mem_breakdown[L_MEM_LD][WB_CACHE_RSRV_FAIL]); - // fprintf(fout, "gpgpu_stall_shd_mem[l_mem_st][mshr_rc] = %d\n", - // gpu_stall_shd_mem_breakdown[L_MEM_ST][MSHR_RC_FAIL]); - // fprintf(fout, "gpgpu_stall_shd_mem[l_mem_st][icnt_rc] = %d\n", - // gpu_stall_shd_mem_breakdown[L_MEM_ST][ICNT_RC_FAIL]); - // fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][wb_icnt_rc] = %d\n", - // gpu_stall_shd_mem_breakdown[L_MEM_ST][WB_ICNT_RC_FAIL]); - // fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][wb_rsrv_fail] = %d\n", - // gpu_stall_shd_mem_breakdown[L_MEM_ST][WB_CACHE_RSRV_FAIL]); + fprintf(fout, "gpgpu_stall_shd_mem[c_mem][resource_stall] = %d\n", gpu_stall_shd_mem_breakdown[C_MEM][BK_CONF]); + //fprintf(fout, "gpgpu_stall_shd_mem[c_mem][mshr_rc] = %d\n", gpu_stall_shd_mem_breakdown[C_MEM][MSHR_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[c_mem][icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[C_MEM][ICNT_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[c_mem][data_port_stall] = %d\n", gpu_stall_shd_mem_breakdown[C_MEM][DATA_PORT_STALL]); + //fprintf(fout, "gpgpu_stall_shd_mem[t_mem][mshr_rc] = %d\n", gpu_stall_shd_mem_breakdown[T_MEM][MSHR_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[t_mem][icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[T_MEM][ICNT_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[t_mem][data_port_stall] = %d\n", gpu_stall_shd_mem_breakdown[T_MEM][DATA_PORT_STALL]); + fprintf(fout, "gpgpu_stall_shd_mem[s_mem][bk_conf] = %d\n", gpu_stall_shd_mem_breakdown[S_MEM][BK_CONF]); + fprintf(fout, "gpgpu_stall_shd_mem[gl_mem][resource_stall] = %d\n", + gpu_stall_shd_mem_breakdown[G_MEM_LD][BK_CONF] + + gpu_stall_shd_mem_breakdown[G_MEM_ST][BK_CONF] + + gpu_stall_shd_mem_breakdown[L_MEM_LD][BK_CONF] + + gpu_stall_shd_mem_breakdown[L_MEM_ST][BK_CONF] + ); // coalescing stall at data cache + fprintf(fout, "gpgpu_stall_shd_mem[gl_mem][coal_stall] = %d\n", + gpu_stall_shd_mem_breakdown[G_MEM_LD][COAL_STALL] + + gpu_stall_shd_mem_breakdown[G_MEM_ST][COAL_STALL] + + gpu_stall_shd_mem_breakdown[L_MEM_LD][COAL_STALL] + + gpu_stall_shd_mem_breakdown[L_MEM_ST][COAL_STALL] + ); // coalescing stall + bank conflict at data cache + fprintf(fout, "gpgpu_stall_shd_mem[gl_mem][data_port_stall] = %d\n", + gpu_stall_shd_mem_breakdown[G_MEM_LD][DATA_PORT_STALL] + + gpu_stall_shd_mem_breakdown[G_MEM_ST][DATA_PORT_STALL] + + gpu_stall_shd_mem_breakdown[L_MEM_LD][DATA_PORT_STALL] + + gpu_stall_shd_mem_breakdown[L_MEM_ST][DATA_PORT_STALL] + ); // data port stall at data cache + //fprintf(fout, "gpgpu_stall_shd_mem[g_mem_ld][mshr_rc] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_LD][MSHR_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[g_mem_ld][icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_LD][ICNT_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[g_mem_ld][wb_icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_LD][WB_ICNT_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[g_mem_ld][wb_rsrv_fail] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_LD][WB_CACHE_RSRV_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[g_mem_st][mshr_rc] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_ST][MSHR_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[g_mem_st][icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_ST][ICNT_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[g_mem_st][wb_icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_ST][WB_ICNT_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[g_mem_st][wb_rsrv_fail] = %d\n", gpu_stall_shd_mem_breakdown[G_MEM_ST][WB_CACHE_RSRV_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][mshr_rc] = %d\n", gpu_stall_shd_mem_breakdown[L_MEM_LD][MSHR_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[L_MEM_LD][ICNT_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][wb_icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[L_MEM_LD][WB_ICNT_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][wb_rsrv_fail] = %d\n", gpu_stall_shd_mem_breakdown[L_MEM_LD][WB_CACHE_RSRV_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[l_mem_st][mshr_rc] = %d\n", gpu_stall_shd_mem_breakdown[L_MEM_ST][MSHR_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[l_mem_st][icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[L_MEM_ST][ICNT_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][wb_icnt_rc] = %d\n", gpu_stall_shd_mem_breakdown[L_MEM_ST][WB_ICNT_RC_FAIL]); + //fprintf(fout, "gpgpu_stall_shd_mem[l_mem_ld][wb_rsrv_fail] = %d\n", gpu_stall_shd_mem_breakdown[L_MEM_ST][WB_CACHE_RSRV_FAIL]); - fprintf(fout, "gpu_reg_bank_conflict_stalls = %d\n", - gpu_reg_bank_conflict_stalls); + fprintf(fout, "gpu_reg_bank_conflict_stalls = %d\n", gpu_reg_bank_conflict_stalls); - fprintf(fout, "Warp Occupancy Distribution:\n"); - fprintf(fout, "Stall:%d\t", shader_cycle_distro[2]); - fprintf(fout, "W0_Idle:%d\t", shader_cycle_distro[0]); - fprintf(fout, "W0_Scoreboard:%d", shader_cycle_distro[1]); - for (unsigned i = 3; i < m_config->warp_size + 3; i++) - fprintf(fout, "\tW%d:%d", i - 2, shader_cycle_distro[i]); - fprintf(fout, "\n"); - fprintf(fout, "single_issue_nums: "); - for (unsigned i = 0; i < m_config->gpgpu_num_sched_per_core; i++) - fprintf(fout, "WS%d:%d\t", i, single_issue_nums[i]); - fprintf(fout, "\n"); - fprintf(fout, "dual_issue_nums: "); - for (unsigned i = 0; i < m_config->gpgpu_num_sched_per_core; i++) - fprintf(fout, "WS%d:%d\t", i, dual_issue_nums[i]); - fprintf(fout, "\n"); + fprintf(fout, "Warp Occupancy Distribution:\n"); + fprintf(fout, "Stall:%d\t", shader_cycle_distro[2]); + fprintf(fout, "W0_Idle:%d\t", shader_cycle_distro[0]); + fprintf(fout, "W0_Scoreboard:%d", shader_cycle_distro[1]); + for (unsigned i = 3; i < m_config->warp_size + 3; i++) + fprintf(fout, "\tW%d:%d", i-2, shader_cycle_distro[i]); + fprintf(fout, "\n"); + fprintf(fout, "single_issue_nums: "); + for (unsigned i = 0; i < m_config->gpgpu_num_sched_per_core; i++) + fprintf(fout, "WS%d:%d\t", i, single_issue_nums[i]); + fprintf(fout, "\n"); + fprintf(fout, "dual_issue_nums: "); + for (unsigned i = 0; i < m_config->gpgpu_num_sched_per_core; i++) + fprintf(fout, "WS%d:%d\t", i, dual_issue_nums[i]); + fprintf(fout, "\n"); - m_outgoing_traffic_stats->print(fout); - m_incoming_traffic_stats->print(fout); + m_outgoing_traffic_stats->print(fout); + m_incoming_traffic_stats->print(fout); } -void shader_core_stats::event_warp_issued(unsigned s_id, unsigned warp_id, - unsigned num_issued, - unsigned dynamic_warp_id) { - assert(warp_id <= m_config->max_warps_per_shader); - for (unsigned i = 0; i < num_issued; ++i) { - if (m_shader_dynamic_warp_issue_distro[s_id].size() <= dynamic_warp_id) { - m_shader_dynamic_warp_issue_distro[s_id].resize(dynamic_warp_id + 1); - } - ++m_shader_dynamic_warp_issue_distro[s_id][dynamic_warp_id]; - if (m_shader_warp_slot_issue_distro[s_id].size() <= warp_id) { - m_shader_warp_slot_issue_distro[s_id].resize(warp_id + 1); +void shader_core_stats::event_warp_issued( unsigned s_id, unsigned warp_id, unsigned num_issued, unsigned dynamic_warp_id ) { + assert( warp_id <= m_config->max_warps_per_shader ); + for ( unsigned i = 0; i < num_issued; ++i ) { + if ( m_shader_dynamic_warp_issue_distro[ s_id ].size() <= dynamic_warp_id ) { + m_shader_dynamic_warp_issue_distro[ s_id ].resize(dynamic_warp_id + 1); + } + ++m_shader_dynamic_warp_issue_distro[ s_id ][ dynamic_warp_id ]; + if ( m_shader_warp_slot_issue_distro[ s_id ].size() <= warp_id ) { + m_shader_warp_slot_issue_distro[ s_id ].resize(warp_id + 1); + } + ++m_shader_warp_slot_issue_distro[ s_id ][ warp_id ]; } - ++m_shader_warp_slot_issue_distro[s_id][warp_id]; - } } -void shader_core_stats::visualizer_print(gzFile visualizer_file) { - // warp divergence breakdown - gzprintf(visualizer_file, "WarpDivergenceBreakdown:"); - unsigned int total = 0; - unsigned int cf = - (m_config->gpgpu_warpdistro_shader == -1) ? m_config->num_shader() : 1; - gzprintf(visualizer_file, " %d", - (shader_cycle_distro[0] - last_shader_cycle_distro[0]) / cf); - gzprintf(visualizer_file, " %d", - (shader_cycle_distro[1] - last_shader_cycle_distro[1]) / cf); - gzprintf(visualizer_file, " %d", - (shader_cycle_distro[2] - last_shader_cycle_distro[2]) / cf); - for (unsigned i = 0; i < m_config->warp_size + 3; i++) { - if (i >= 3) { - total += (shader_cycle_distro[i] - last_shader_cycle_distro[i]); - if (((i - 3) % (m_config->warp_size / 8)) == - ((m_config->warp_size / 8) - 1)) { - gzprintf(visualizer_file, " %d", total / cf); - total = 0; - } +void shader_core_stats::visualizer_print( gzFile visualizer_file ) +{ + // warp divergence breakdown + gzprintf(visualizer_file, "WarpDivergenceBreakdown:"); + unsigned int total=0; + unsigned int cf = (m_config->gpgpu_warpdistro_shader==-1)?m_config->num_shader():1; + gzprintf(visualizer_file, " %d", (shader_cycle_distro[0] - last_shader_cycle_distro[0]) / cf ); + gzprintf(visualizer_file, " %d", (shader_cycle_distro[1] - last_shader_cycle_distro[1]) / cf ); + gzprintf(visualizer_file, " %d", (shader_cycle_distro[2] - last_shader_cycle_distro[2]) / cf ); + for (unsigned i=0; i<m_config->warp_size+3; i++) { + if ( i>=3 ) { + total += (shader_cycle_distro[i] - last_shader_cycle_distro[i]); + if ( ((i-3) % (m_config->warp_size/8)) == ((m_config->warp_size/8)-1) ) { + gzprintf(visualizer_file, " %d", total / cf ); + total=0; + } + } + last_shader_cycle_distro[i] = shader_cycle_distro[i]; } - last_shader_cycle_distro[i] = shader_cycle_distro[i]; - } - gzprintf(visualizer_file, "\n"); + gzprintf(visualizer_file,"\n"); - // warp issue breakdown - unsigned sid = m_config->gpgpu_warp_issue_shader; - unsigned count = 0; - unsigned warp_id_issued_sum = 0; - gzprintf(visualizer_file, "WarpIssueSlotBreakdown:"); - if (m_shader_warp_slot_issue_distro[sid].size() > 0) { - for (std::vector<unsigned>::const_iterator - iter = m_shader_warp_slot_issue_distro[sid].begin(); - iter != m_shader_warp_slot_issue_distro[sid].end(); iter++, count++) { - unsigned diff = count < m_last_shader_warp_slot_issue_distro.size() - ? *iter - m_last_shader_warp_slot_issue_distro[count] - : *iter; - gzprintf(visualizer_file, " %d", diff); - warp_id_issued_sum += diff; + // warp issue breakdown + unsigned sid = m_config->gpgpu_warp_issue_shader; + unsigned count = 0; + unsigned warp_id_issued_sum = 0; + gzprintf(visualizer_file, "WarpIssueSlotBreakdown:"); + if(m_shader_warp_slot_issue_distro[sid].size() > 0){ + for ( std::vector<unsigned>::const_iterator iter = m_shader_warp_slot_issue_distro[ sid ].begin(); + iter != m_shader_warp_slot_issue_distro[ sid ].end(); iter++, count++ ) { + unsigned diff = count < m_last_shader_warp_slot_issue_distro.size() ? + *iter - m_last_shader_warp_slot_issue_distro[ count ] : + *iter; + gzprintf( visualizer_file, " %d", diff ); + warp_id_issued_sum += diff; + } + m_last_shader_warp_slot_issue_distro = m_shader_warp_slot_issue_distro[ sid ]; + }else{ + gzprintf( visualizer_file, " 0"); } - m_last_shader_warp_slot_issue_distro = m_shader_warp_slot_issue_distro[sid]; - } else { - gzprintf(visualizer_file, " 0"); - } - gzprintf(visualizer_file, "\n"); + gzprintf(visualizer_file,"\n"); -#define DYNAMIC_WARP_PRINT_RESOLUTION 32 - unsigned total_issued_this_resolution = 0; - unsigned dynamic_id_issued_sum = 0; - count = 0; - gzprintf(visualizer_file, "WarpIssueDynamicIdBreakdown:"); - if (m_shader_dynamic_warp_issue_distro[sid].size() > 0) { - for (std::vector<unsigned>::const_iterator - iter = m_shader_dynamic_warp_issue_distro[sid].begin(); - iter != m_shader_dynamic_warp_issue_distro[sid].end(); - iter++, count++) { - unsigned diff = - count < m_last_shader_dynamic_warp_issue_distro.size() - ? *iter - m_last_shader_dynamic_warp_issue_distro[count] - : *iter; - total_issued_this_resolution += diff; - if ((count + 1) % DYNAMIC_WARP_PRINT_RESOLUTION == 0) { - gzprintf(visualizer_file, " %d", total_issued_this_resolution); - dynamic_id_issued_sum += total_issued_this_resolution; - total_issued_this_resolution = 0; - } - } - if (count % DYNAMIC_WARP_PRINT_RESOLUTION != 0) { - gzprintf(visualizer_file, " %d", total_issued_this_resolution); - dynamic_id_issued_sum += total_issued_this_resolution; + #define DYNAMIC_WARP_PRINT_RESOLUTION 32 + unsigned total_issued_this_resolution = 0; + unsigned dynamic_id_issued_sum = 0; + count = 0; + gzprintf(visualizer_file, "WarpIssueDynamicIdBreakdown:"); + if(m_shader_dynamic_warp_issue_distro[sid].size() > 0){ + for ( std::vector<unsigned>::const_iterator iter = m_shader_dynamic_warp_issue_distro[ sid ].begin(); + iter != m_shader_dynamic_warp_issue_distro[ sid ].end(); iter++, count++ ) { + unsigned diff = count < m_last_shader_dynamic_warp_issue_distro.size() ? + *iter - m_last_shader_dynamic_warp_issue_distro[ count ] : + *iter; + total_issued_this_resolution += diff; + if ( ( count + 1 ) % DYNAMIC_WARP_PRINT_RESOLUTION == 0 ) { + gzprintf( visualizer_file, " %d", total_issued_this_resolution ); + dynamic_id_issued_sum += total_issued_this_resolution; + total_issued_this_resolution = 0; + } + } + if ( count % DYNAMIC_WARP_PRINT_RESOLUTION != 0 ) { + gzprintf( visualizer_file, " %d", total_issued_this_resolution ); + dynamic_id_issued_sum += total_issued_this_resolution; + } + m_last_shader_dynamic_warp_issue_distro = m_shader_dynamic_warp_issue_distro[ sid ]; + assert( warp_id_issued_sum == dynamic_id_issued_sum ); + }else{ + gzprintf( visualizer_file, " 0"); } - m_last_shader_dynamic_warp_issue_distro = - m_shader_dynamic_warp_issue_distro[sid]; - assert(warp_id_issued_sum == dynamic_id_issued_sum); - } else { - gzprintf(visualizer_file, " 0"); - } - gzprintf(visualizer_file, "\n"); + gzprintf(visualizer_file,"\n"); + + // overall cache miss rates + gzprintf(visualizer_file, "gpgpu_n_cache_bkconflict: %d\n", gpgpu_n_cache_bkconflict); + gzprintf(visualizer_file, "gpgpu_n_shmem_bkconflict: %d\n", gpgpu_n_shmem_bkconflict); - // overall cache miss rates - gzprintf(visualizer_file, "gpgpu_n_cache_bkconflict: %d\n", - gpgpu_n_cache_bkconflict); - gzprintf(visualizer_file, "gpgpu_n_shmem_bkconflict: %d\n", - gpgpu_n_shmem_bkconflict); - // instruction count per shader core - gzprintf(visualizer_file, "shaderinsncount: "); - for (unsigned i = 0; i < m_config->num_shader(); i++) - gzprintf(visualizer_file, "%u ", m_num_sim_insn[i]); - gzprintf(visualizer_file, "\n"); - // warp instruction count per shader core - gzprintf(visualizer_file, "shaderwarpinsncount: "); - for (unsigned i = 0; i < m_config->num_shader(); i++) - gzprintf(visualizer_file, "%u ", m_num_sim_winsn[i]); - gzprintf(visualizer_file, "\n"); - // warp divergence per shader core - gzprintf(visualizer_file, "shaderwarpdiv: "); - for (unsigned i = 0; i < m_config->num_shader(); i++) - gzprintf(visualizer_file, "%u ", m_n_diverge[i]); - gzprintf(visualizer_file, "\n"); + // instruction count per shader core + gzprintf(visualizer_file, "shaderinsncount: "); + for (unsigned i=0;i<m_config->num_shader();i++) + gzprintf(visualizer_file, "%u ", m_num_sim_insn[i] ); + gzprintf(visualizer_file, "\n"); + // warp instruction count per shader core + gzprintf(visualizer_file, "shaderwarpinsncount: "); + for (unsigned i=0;i<m_config->num_shader();i++) + gzprintf(visualizer_file, "%u ", m_num_sim_winsn[i] ); + gzprintf(visualizer_file, "\n"); + // warp divergence per shader core + gzprintf(visualizer_file, "shaderwarpdiv: "); + for (unsigned i=0;i<m_config->num_shader();i++) + gzprintf(visualizer_file, "%u ", m_n_diverge[i] ); + gzprintf(visualizer_file, "\n"); } -#define PROGRAM_MEM_START \ - 0xF0000000 /* should be distinct from other memory spaces... \ - check ptx_ir.h to verify this does not overlap \ - other memory spaces */ -void shader_core_ctx::decode() { - if (m_inst_fetch_buffer.m_valid) { - // decode 1 or 2 instructions and place them into ibuffer - address_type pc = m_inst_fetch_buffer.m_pc; - const warp_inst_t *pI1 = m_gpu->gpgpu_ctx->ptx_fetch_inst(pc); - m_warp[m_inst_fetch_buffer.m_warp_id].ibuffer_fill(0, pI1); - m_warp[m_inst_fetch_buffer.m_warp_id].inc_inst_in_pipeline(); - if (pI1) { - m_stats->m_num_decoded_insn[m_sid]++; - if (pI1->oprnd_type == INT_OP) { - m_stats->m_num_INTdecoded_insn[m_sid]++; - } else if (pI1->oprnd_type == FP_OP) { - m_stats->m_num_FPdecoded_insn[m_sid]++; - } - const warp_inst_t *pI2 = - m_gpu->gpgpu_ctx->ptx_fetch_inst(pc + pI1->isize); - if (pI2) { - m_warp[m_inst_fetch_buffer.m_warp_id].ibuffer_fill(1, pI2); +#define PROGRAM_MEM_START 0xF0000000 /* should be distinct from other memory spaces... + check ptx_ir.h to verify this does not overlap + other memory spaces */ +void shader_core_ctx::decode() +{ + if( m_inst_fetch_buffer.m_valid ) { + // decode 1 or 2 instructions and place them into ibuffer + address_type pc = m_inst_fetch_buffer.m_pc; + const warp_inst_t* pI1 = m_gpu->gpgpu_ctx->ptx_fetch_inst(pc); + m_warp[m_inst_fetch_buffer.m_warp_id].ibuffer_fill(0,pI1); m_warp[m_inst_fetch_buffer.m_warp_id].inc_inst_in_pipeline(); - m_stats->m_num_decoded_insn[m_sid]++; - if (pI2->oprnd_type == INT_OP) { - m_stats->m_num_INTdecoded_insn[m_sid]++; - } else if (pI2->oprnd_type == FP_OP) { - m_stats->m_num_FPdecoded_insn[m_sid]++; + if( pI1 ) { + m_stats->m_num_decoded_insn[m_sid]++; + if(pI1->oprnd_type==INT_OP){ + m_stats->m_num_INTdecoded_insn[m_sid]++; + }else if(pI1->oprnd_type==FP_OP) { + m_stats->m_num_FPdecoded_insn[m_sid]++; + } + const warp_inst_t* pI2 = m_gpu->gpgpu_ctx->ptx_fetch_inst(pc+pI1->isize); + if( pI2 ) { + m_warp[m_inst_fetch_buffer.m_warp_id].ibuffer_fill(1,pI2); + m_warp[m_inst_fetch_buffer.m_warp_id].inc_inst_in_pipeline(); + m_stats->m_num_decoded_insn[m_sid]++; + if(pI2->oprnd_type==INT_OP){ + m_stats->m_num_INTdecoded_insn[m_sid]++; + }else if(pI2->oprnd_type==FP_OP) { + m_stats->m_num_FPdecoded_insn[m_sid]++; + } + } } - } + m_inst_fetch_buffer.m_valid = false; } - m_inst_fetch_buffer.m_valid = false; - } } -void shader_core_ctx::fetch() { - if (!m_inst_fetch_buffer.m_valid) { - if (m_L1I->access_ready()) { - mem_fetch *mf = m_L1I->next_access(); - m_warp[mf->get_wid()].clear_imiss_pending(); - m_inst_fetch_buffer = ifetch_buffer_t( - m_warp[mf->get_wid()].get_pc(), mf->get_access_size(), mf->get_wid()); - assert(m_warp[mf->get_wid()].get_pc() == - (mf->get_addr() - PROGRAM_MEM_START)); // Verify that we got the - // instruction we were - // expecting. - m_inst_fetch_buffer.m_valid = true; - m_warp[mf->get_wid()].set_last_fetch(m_gpu->gpu_sim_cycle); - delete mf; - } else { - // find an active warp with space in instruction buffer that is not - // already waiting on a cache miss - // and get next 1-2 instructions from i-cache... - for (unsigned i = 0; i < m_config->max_warps_per_shader; i++) { - unsigned warp_id = - (m_last_warp_fetched + 1 + i) % m_config->max_warps_per_shader; +void shader_core_ctx::fetch() +{ - // this code checks if this warp has finished executing and can be - // reclaimed - if (m_warp[warp_id].hardware_done() && - !m_scoreboard->pendingWrites(warp_id) && - !m_warp[warp_id].done_exit()) { - bool did_exit = false; - for (unsigned t = 0; t < m_config->warp_size; t++) { - unsigned tid = warp_id * m_config->warp_size + t; - if (m_threadState[tid].m_active == true) { - m_threadState[tid].m_active = false; - unsigned cta_id = m_warp[warp_id].get_cta_id(); - register_cta_thread_exit(cta_id, &(m_thread[tid]->get_kernel())); - m_not_completed -= 1; - m_active_threads.reset(tid); - assert(m_thread[tid] != NULL); - did_exit = true; - } - } - if (did_exit) m_warp[warp_id].set_done_exit(); - --m_active_warps; - assert(m_active_warps >= 0); + if( !m_inst_fetch_buffer.m_valid ) { + if( m_L1I->access_ready() ) { + mem_fetch *mf = m_L1I->next_access(); + m_warp[mf->get_wid()].clear_imiss_pending(); + m_inst_fetch_buffer = ifetch_buffer_t(m_warp[mf->get_wid()].get_pc(), mf->get_access_size(), mf->get_wid()); + assert( m_warp[mf->get_wid()].get_pc() == (mf->get_addr()-PROGRAM_MEM_START)); // Verify that we got the instruction we were expecting. + m_inst_fetch_buffer.m_valid = true; + m_warp[mf->get_wid()].set_last_fetch(m_gpu->gpu_sim_cycle); + delete mf; } + else { + // find an active warp with space in instruction buffer that is not already waiting on a cache miss + // and get next 1-2 instructions from i-cache... + for( unsigned i=0; i < m_config->max_warps_per_shader; i++ ) { + unsigned warp_id = (m_last_warp_fetched+1+i) % m_config->max_warps_per_shader; - // this code fetches instructions from the i-cache or generates memory - // requests - if (!m_warp[warp_id].functional_done() && - !m_warp[warp_id].imiss_pending() && - m_warp[warp_id].ibuffer_empty()) { - address_type pc = m_warp[warp_id].get_pc(); - address_type ppc = pc + PROGRAM_MEM_START; - unsigned nbytes = 16; - unsigned offset_in_block = - pc & (m_config->m_L1I_config.get_line_sz() - 1); - if ((offset_in_block + nbytes) > m_config->m_L1I_config.get_line_sz()) - nbytes = (m_config->m_L1I_config.get_line_sz() - offset_in_block); + // this code checks if this warp has finished executing and can be reclaimed + if( m_warp[warp_id].hardware_done() && !m_scoreboard->pendingWrites(warp_id) && !m_warp[warp_id].done_exit() ) { + bool did_exit=false; + for( unsigned t=0; t<m_config->warp_size;t++) { + unsigned tid=warp_id*m_config->warp_size+t; + if( m_threadState[tid].m_active == true ) { + m_threadState[tid].m_active = false; + unsigned cta_id = m_warp[warp_id].get_cta_id(); + register_cta_thread_exit(cta_id, &(m_thread[tid]->get_kernel())); + m_not_completed -= 1; + m_active_threads.reset(tid); + assert( m_thread[tid]!= NULL ); + did_exit=true; + } + } + if( did_exit ) + m_warp[warp_id].set_done_exit(); + --m_active_warps; + assert(m_active_warps >= 0); + } - // TODO: replace with use of allocator - // mem_fetch *mf = m_mem_fetch_allocator->alloc() - mem_access_t acc(INST_ACC_R, ppc, nbytes, false, m_gpu->gpgpu_ctx); - mem_fetch *mf = new mem_fetch( - acc, NULL /*we don't have an instruction yet*/, READ_PACKET_SIZE, - warp_id, m_sid, m_tpc, m_memory_config, - m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle); - std::list<cache_event> events; - enum cache_request_status status = m_L1I->access( - (new_addr_type)ppc, mf, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle, events); - if (status == MISS) { - m_last_warp_fetched = warp_id; - m_warp[warp_id].set_imiss_pending(); - m_warp[warp_id].set_last_fetch(m_gpu->gpu_sim_cycle); - } else if (status == HIT) { - m_last_warp_fetched = warp_id; - m_inst_fetch_buffer = ifetch_buffer_t(pc, nbytes, warp_id); - m_warp[warp_id].set_last_fetch(m_gpu->gpu_sim_cycle); - delete mf; - } else { - m_last_warp_fetched = warp_id; - assert(status == RESERVATION_FAIL); - delete mf; - } - break; + // this code fetches instructions from the i-cache or generates memory requests + if( !m_warp[warp_id].functional_done() && !m_warp[warp_id].imiss_pending() && m_warp[warp_id].ibuffer_empty() ) { + address_type pc = m_warp[warp_id].get_pc(); + address_type ppc = pc + PROGRAM_MEM_START; + unsigned nbytes=16; + unsigned offset_in_block = pc & (m_config->m_L1I_config.get_line_sz()-1); + if( (offset_in_block+nbytes) > m_config->m_L1I_config.get_line_sz() ) + nbytes = (m_config->m_L1I_config.get_line_sz()-offset_in_block); + + // TODO: replace with use of allocator + // mem_fetch *mf = m_mem_fetch_allocator->alloc() + mem_access_t acc(INST_ACC_R,ppc,nbytes,false, m_gpu->gpgpu_ctx); + mem_fetch *mf = new mem_fetch(acc, + NULL/*we don't have an instruction yet*/, + READ_PACKET_SIZE, + warp_id, + m_sid, + m_tpc, + m_memory_config, + m_gpu->gpu_tot_sim_cycle+m_gpu->gpu_sim_cycle + ); + std::list<cache_event> events; + enum cache_request_status status = m_L1I->access( (new_addr_type)ppc, mf, m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle,events); + if( status == MISS ) { + m_last_warp_fetched=warp_id; + m_warp[warp_id].set_imiss_pending(); + m_warp[warp_id].set_last_fetch(m_gpu->gpu_sim_cycle); + } else if( status == HIT ) { + m_last_warp_fetched=warp_id; + m_inst_fetch_buffer = ifetch_buffer_t(pc,nbytes,warp_id); + m_warp[warp_id].set_last_fetch(m_gpu->gpu_sim_cycle); + delete mf; + } else { + m_last_warp_fetched=warp_id; + assert( status == RESERVATION_FAIL ); + delete mf; + } + break; + } + } } - } } - } - m_L1I->cycle(); + m_L1I->cycle(); } -void shader_core_ctx::func_exec_inst(warp_inst_t &inst) { - execute_warp_inst_t(inst); - if (inst.is_load() || inst.is_store()) { - inst.generate_mem_accesses(); - // inst.print_m_accessq(); - } +void shader_core_ctx::func_exec_inst( warp_inst_t &inst ) +{ + execute_warp_inst_t(inst); + if( inst.is_load() || inst.is_store() ) + { + inst.generate_mem_accesses(); + //inst.print_m_accessq(); + } } -void shader_core_ctx::issue_warp(register_set &pipe_reg_set, - const warp_inst_t *next_inst, - const active_mask_t &active_mask, - unsigned warp_id, unsigned sch_id) { - warp_inst_t **pipe_reg = - pipe_reg_set.get_free(m_config->sub_core_model, sch_id); - assert(pipe_reg); +void shader_core_ctx::issue_warp( register_set& pipe_reg_set, const warp_inst_t* next_inst, const active_mask_t &active_mask, unsigned warp_id, unsigned sch_id ) +{ + warp_inst_t** pipe_reg = pipe_reg_set.get_free(m_config->sub_core_model, sch_id); + assert(pipe_reg); - m_warp[warp_id].ibuffer_free(); - assert(next_inst->valid()); - **pipe_reg = *next_inst; // static instruction information - (*pipe_reg)->issue(active_mask, warp_id, - m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle, - m_warp[warp_id].get_dynamic_warp_id(), - sch_id); // dynamic instruction information - m_stats->shader_cycle_distro[2 + (*pipe_reg)->active_count()]++; - func_exec_inst(**pipe_reg); - if (next_inst->op == BARRIER_OP) { - m_warp[warp_id].store_info_of_last_inst_at_barrier(*pipe_reg); - m_barriers.warp_reaches_barrier(m_warp[warp_id].get_cta_id(), warp_id, - const_cast<warp_inst_t *>(next_inst)); + m_warp[warp_id].ibuffer_free(); + assert(next_inst->valid()); + **pipe_reg = *next_inst; // static instruction information + (*pipe_reg)->issue( active_mask, warp_id, m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle, m_warp[warp_id].get_dynamic_warp_id(), sch_id ); // dynamic instruction information + m_stats->shader_cycle_distro[2+(*pipe_reg)->active_count()]++; + func_exec_inst( **pipe_reg ); + if( next_inst->op == BARRIER_OP ){ + m_warp[warp_id].store_info_of_last_inst_at_barrier(*pipe_reg); + m_barriers.warp_reaches_barrier(m_warp[warp_id].get_cta_id(),warp_id,const_cast<warp_inst_t*> (next_inst)); - } else if (next_inst->op == MEMORY_BARRIER_OP) { - m_warp[warp_id].set_membar(); - } + }else if( next_inst->op == MEMORY_BARRIER_OP ){ + m_warp[warp_id].set_membar(); + } - updateSIMTStack(warp_id, *pipe_reg); - m_scoreboard->reserveRegisters(*pipe_reg); - m_warp[warp_id].set_next_pc(next_inst->pc + next_inst->isize); + updateSIMTStack(warp_id,*pipe_reg); + m_scoreboard->reserveRegisters(*pipe_reg); + m_warp[warp_id].set_next_pc(next_inst->pc + next_inst->isize); } -void shader_core_ctx::issue() { - // Ensure fair round robin issu between schedulers - unsigned j; - for (unsigned i = 0; i < schedulers.size(); i++) { - j = (Issue_Prio + i) % schedulers.size(); - schedulers[j]->cycle(); - } - Issue_Prio = (Issue_Prio + 1) % schedulers.size(); +void shader_core_ctx::issue(){ + + //Ensure fair round robin issu between schedulers + unsigned j; + for (unsigned i = 0; i < schedulers.size(); i++) { + j = (Issue_Prio + i) % schedulers.size(); + schedulers[j]->cycle(); + } + Issue_Prio = (Issue_Prio+1)% schedulers.size(); + + //really is issue; + //for (unsigned i = 0; i < schedulers.size(); i++) { + // schedulers[i]->cycle(); + //} +} - // really is issue; - // for (unsigned i = 0; i < schedulers.size(); i++) { - // schedulers[i]->cycle(); - //} +shd_warp_t& scheduler_unit::warp(int i){ + return (*m_warp)[i]; } -shd_warp_t &scheduler_unit::warp(int i) { return (*m_warp)[i]; } /** - * A general function to order things in a Loose Round Robin way. The simplist - * use of this - * function would be to implement a loose RR scheduler between all the warps - * assigned to this core. - * A more sophisticated usage would be to order a set of "fetch groups" in a RR - * fashion. - * In the first case, the templated class variable would be a simple unsigned - * int representing the - * warp_id. In the 2lvl case, T could be a struct or a list representing a set - * of warp_ids. - * @param result_list: The resultant list the caller wants returned. This list - * is cleared and then populated + * A general function to order things in a Loose Round Robin way. The simplist use of this + * function would be to implement a loose RR scheduler between all the warps assigned to this core. + * A more sophisticated usage would be to order a set of "fetch groups" in a RR fashion. + * In the first case, the templated class variable would be a simple unsigned int representing the + * warp_id. In the 2lvl case, T could be a struct or a list representing a set of warp_ids. + * @param result_list: The resultant list the caller wants returned. This list is cleared and then populated * in a loose round robin way - * @param input_list: The list of things that should be put into the - * result_list. For a simple scheduler + * @param input_list: The list of things that should be put into the result_list. For a simple scheduler * this can simply be the m_supervised_warps list. - * @param last_issued_from_input: An iterator pointing the last member in the - * input_list that issued. - * Since this function orders in a RR fashion, - * the object pointed - * to by this iterator will be last in the - * prioritization list - * @param num_warps_to_add: The number of warps you want the scheudler to pick - * between this cycle. - * Normally, this will be all the warps availible on - * the core, i.e. - * m_supervised_warps.size(). However, a more - * sophisticated scheduler may wish to - * limit this number. If the number if < - * m_supervised_warps.size(), then only - * the warps with highest RR priority will be placed in - * the result_list. + * @param last_issued_from_input: An iterator pointing the last member in the input_list that issued. + * Since this function orders in a RR fashion, the object pointed + * to by this iterator will be last in the prioritization list + * @param num_warps_to_add: The number of warps you want the scheudler to pick between this cycle. + * Normally, this will be all the warps availible on the core, i.e. + * m_supervised_warps.size(). However, a more sophisticated scheduler may wish to + * limit this number. If the number if < m_supervised_warps.size(), then only + * the warps with highest RR priority will be placed in the result_list. */ -template <class T> -void scheduler_unit::order_lrr( - std::vector<T> &result_list, const typename std::vector<T> &input_list, - const typename std::vector<T>::const_iterator &last_issued_from_input, - unsigned num_warps_to_add) { - assert(num_warps_to_add <= input_list.size()); - result_list.clear(); - typename std::vector<T>::const_iterator iter = - (last_issued_from_input == input_list.end()) ? input_list.begin() - : last_issued_from_input + 1; + template < class T > +void scheduler_unit::order_lrr( std::vector< T >& result_list, + const typename std::vector< T >& input_list, + const typename std::vector< T >::const_iterator& last_issued_from_input, + unsigned num_warps_to_add ) +{ + assert( num_warps_to_add <= input_list.size() ); + result_list.clear(); + typename std::vector< T >::const_iterator iter + = ( last_issued_from_input == input_list.end() ) ? input_list.begin() + : last_issued_from_input + 1; - for (unsigned count = 0; count < num_warps_to_add; ++iter, ++count) { - if (iter == input_list.end()) { - iter = input_list.begin(); + for ( unsigned count = 0; + count < num_warps_to_add; + ++iter, ++count) { + if ( iter == input_list.end() ) { + iter = input_list.begin(); + } + result_list.push_back( *iter ); } - result_list.push_back(*iter); - } } /** * A general function to order things in an priority-based way. * The core usage of the function is similar to order_lrr. - * The explanation of the additional parameters (beyond order_lrr) explains the - * further extensions. - * @param ordering: An enum that determines how the age function will be treated - * in prioritization + * The explanation of the additional parameters (beyond order_lrr) explains the further extensions. + * @param ordering: An enum that determines how the age function will be treated in prioritization * see the definition of OrderingType. - * @param priority_function: This function is used to sort the input_list. It - * is passed to stl::sort as - * the sorting fucntion. So, if you wanted to sort a - * list of integer warp_ids - * with the oldest warps having the most priority, - * then the priority_function + * @param priority_function: This function is used to sort the input_list. It is passed to stl::sort as + * the sorting fucntion. So, if you wanted to sort a list of integer warp_ids + * with the oldest warps having the most priority, then the priority_function * would compare the age of the two warps. */ -template <class T> -void scheduler_unit::order_by_priority( - std::vector<T> &result_list, const typename std::vector<T> &input_list, - const typename std::vector<T>::const_iterator &last_issued_from_input, - unsigned num_warps_to_add, OrderingType ordering, - bool (*priority_func)(T lhs, T rhs)) { - assert(num_warps_to_add <= input_list.size()); - result_list.clear(); - typename std::vector<T> temp = input_list; + template < class T > +void scheduler_unit::order_by_priority( std::vector< T >& result_list, + const typename std::vector< T >& input_list, + const typename std::vector< T >::const_iterator& last_issued_from_input, + unsigned num_warps_to_add, + OrderingType ordering, + bool (*priority_func)(T lhs, T rhs) ) +{ + assert( num_warps_to_add <= input_list.size() ); + result_list.clear(); + typename std::vector< T > temp = input_list; - if (ORDERING_GREEDY_THEN_PRIORITY_FUNC == ordering) { - T greedy_value = *last_issued_from_input; - result_list.push_back(greedy_value); + if ( ORDERING_GREEDY_THEN_PRIORITY_FUNC == ordering ) { + T greedy_value = *last_issued_from_input; + result_list.push_back( greedy_value ); - std::sort(temp.begin(), temp.end(), priority_func); - typename std::vector<T>::iterator iter = temp.begin(); - for (unsigned count = 0; count < num_warps_to_add; ++count, ++iter) { - if (*iter != greedy_value) { - result_list.push_back(*iter); - } - } - } else if (ORDERED_PRIORITY_FUNC_ONLY == ordering) { - std::sort(temp.begin(), temp.end(), priority_func); - typename std::vector<T>::iterator iter = temp.begin(); - for (unsigned count = 0; count < num_warps_to_add; ++count, ++iter) { - result_list.push_back(*iter); + std::sort( temp.begin(), temp.end(), priority_func ); + typename std::vector< T >::iterator iter = temp.begin(); + for ( unsigned count = 0; count < num_warps_to_add; ++count, ++iter ) { + if ( *iter != greedy_value ) { + result_list.push_back( *iter ); + } + } + } else if ( ORDERED_PRIORITY_FUNC_ONLY == ordering ) { + std::sort( temp.begin(), temp.end(), priority_func ); + typename std::vector< T >::iterator iter = temp.begin(); + for ( unsigned count = 0; count < num_warps_to_add; ++count, ++iter ) { + result_list.push_back( *iter ); + } + } else { + fprintf( stderr, "Unknown ordering - %d\n", ordering ); + abort(); } - } else { - fprintf(stderr, "Unknown ordering - %d\n", ordering); - abort(); - } } -void scheduler_unit::cycle() { - SCHED_DPRINTF("scheduler_unit::cycle()\n"); - bool valid_inst = false; // there was one warp with a valid instruction to - // issue (didn't require flush due to control - // hazard) - bool ready_inst = false; // of the valid instructions, there was one not - // waiting for pending register writes - bool issued_inst = false; // of these we issued one +void scheduler_unit::cycle() +{ + SCHED_DPRINTF( "scheduler_unit::cycle()\n" ); + bool valid_inst = false; // there was one warp with a valid instruction to issue (didn't require flush due to control hazard) + bool ready_inst = false; // of the valid instructions, there was one not waiting for pending register writes + bool issued_inst = false; // of these we issued one - order_warps(); - for (std::vector<shd_warp_t *>::const_iterator iter = - m_next_cycle_prioritized_warps.begin(); - iter != m_next_cycle_prioritized_warps.end(); iter++) { - // Don't consider warps that are not yet valid - if ((*iter) == NULL || (*iter)->done_exit()) { - continue; - } - SCHED_DPRINTF("Testing (warp_id %u, dynamic_warp_id %u)\n", - (*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id()); - unsigned warp_id = (*iter)->get_warp_id(); - unsigned checked = 0; - unsigned issued = 0; - exec_unit_type_t previous_issued_inst_exec_type = exec_unit_type_t::NONE; - unsigned max_issue = m_shader->m_config->gpgpu_max_insn_issue_per_warp; - bool diff_exec_units = - m_shader->m_config->gpgpu_dual_issue_diff_exec_units; // In tis mode, - // we only allow - // dual issue to - // diff execution - // units (as in - // Maxwell and - // Pascal) + order_warps(); + for ( std::vector< shd_warp_t* >::const_iterator iter = m_next_cycle_prioritized_warps.begin(); + iter != m_next_cycle_prioritized_warps.end(); + iter++ ) { + // Don't consider warps that are not yet valid + if ( (*iter) == NULL || (*iter)->done_exit() ) { + continue; + } + SCHED_DPRINTF( "Testing (warp_id %u, dynamic_warp_id %u)\n", + (*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id() ); + unsigned warp_id = (*iter)->get_warp_id(); + unsigned checked=0; + unsigned issued=0; + exec_unit_type_t previous_issued_inst_exec_type = exec_unit_type_t::NONE; + unsigned max_issue = m_shader->m_config->gpgpu_max_insn_issue_per_warp; + bool diff_exec_units = m_shader->m_config->gpgpu_dual_issue_diff_exec_units; //In tis mode, we only allow dual issue to diff execution units (as in Maxwell and Pascal) - while (!warp(warp_id).waiting() && !warp(warp_id).ibuffer_empty() && - (checked < max_issue) && (checked <= issued) && - (issued < max_issue)) { - const warp_inst_t *pI = warp(warp_id).ibuffer_next_inst(); - // Jin: handle cdp latency; - if (pI && pI->m_is_cdp && warp(warp_id).m_cdp_latency > 0) { - assert(warp(warp_id).m_cdp_dummy); - warp(warp_id).m_cdp_latency--; - break; - } + while( !warp(warp_id).waiting() && !warp(warp_id).ibuffer_empty() && (checked < max_issue) && (checked <= issued) && (issued < max_issue) ) { + const warp_inst_t *pI = warp(warp_id).ibuffer_next_inst(); + //Jin: handle cdp latency; + if(pI && pI->m_is_cdp && warp(warp_id).m_cdp_latency > 0) { + assert(warp(warp_id).m_cdp_dummy); + warp(warp_id).m_cdp_latency--; + break; + } - bool valid = warp(warp_id).ibuffer_next_valid(); - bool warp_inst_issued = false; - unsigned pc, rpc; - m_simt_stack[warp_id]->get_pdom_stack_top_info(&pc, &rpc); - SCHED_DPRINTF( - "Warp (warp_id %u, dynamic_warp_id %u) has valid instruction (%s)\n", - (*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id(), - m_shader->m_config->gpgpu_ctx->func_sim->ptx_get_insn_str(pc) - .c_str()); - if (pI) { - assert(valid); - if (pc != pI->pc) { - SCHED_DPRINTF( - "Warp (warp_id %u, dynamic_warp_id %u) control hazard " - "instruction flush\n", - (*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id()); - // control hazard - warp(warp_id).set_next_pc(pc); - warp(warp_id).ibuffer_flush(); - } else { - valid_inst = true; - if (!m_scoreboard->checkCollision(warp_id, pI)) { - SCHED_DPRINTF( - "Warp (warp_id %u, dynamic_warp_id %u) passes scoreboard\n", - (*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id()); - ready_inst = true; - const active_mask_t &active_mask = - m_simt_stack[warp_id]->get_active_mask(); - assert(warp(warp_id).inst_in_pipeline()); + bool valid = warp(warp_id).ibuffer_next_valid(); + bool warp_inst_issued = false; + unsigned pc,rpc; + m_simt_stack[warp_id]->get_pdom_stack_top_info(&pc,&rpc); + SCHED_DPRINTF( "Warp (warp_id %u, dynamic_warp_id %u) has valid instruction (%s)\n", + (*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id(), + m_shader->m_config->gpgpu_ctx->func_sim->ptx_get_insn_str( pc).c_str() ); + if( pI ) { + assert(valid); + if( pc != pI->pc ) { + SCHED_DPRINTF( "Warp (warp_id %u, dynamic_warp_id %u) control hazard instruction flush\n", + (*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id() ); + // control hazard + warp(warp_id).set_next_pc(pc); + warp(warp_id).ibuffer_flush(); + } else { + valid_inst = true; + if ( !m_scoreboard->checkCollision(warp_id, pI) ) { + SCHED_DPRINTF( "Warp (warp_id %u, dynamic_warp_id %u) passes scoreboard\n", + (*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id() ); + ready_inst = true; + const active_mask_t &active_mask = m_simt_stack[warp_id]->get_active_mask(); + assert( warp(warp_id).inst_in_pipeline() ); - if ((pI->op == LOAD_OP) || (pI->op == STORE_OP) || - (pI->op == MEMORY_BARRIER_OP) || - (pI->op == TENSOR_CORE_LOAD_OP) || - (pI->op == TENSOR_CORE_STORE_OP)) { - if (m_mem_out->has_free(m_shader->m_config->sub_core_model, - m_id) && - (!diff_exec_units || - previous_issued_inst_exec_type != exec_unit_type_t::MEM)) { - m_shader->issue_warp(*m_mem_out, pI, active_mask, warp_id, - m_id); - issued++; - issued_inst = true; - warp_inst_issued = true; - previous_issued_inst_exec_type = exec_unit_type_t::MEM; - } - } else { - bool sp_pipe_avail = - m_sp_out->has_free(m_shader->m_config->sub_core_model, m_id); - bool sfu_pipe_avail = - m_sfu_out->has_free(m_shader->m_config->sub_core_model, m_id); - bool tensor_core_pipe_avail = m_tensor_core_out->has_free( - m_shader->m_config->sub_core_model, m_id); - bool dp_pipe_avail = - m_dp_out->has_free(m_shader->m_config->sub_core_model, m_id); - bool int_pipe_avail = - m_int_out->has_free(m_shader->m_config->sub_core_model, m_id); + if ( (pI->op == LOAD_OP) || (pI->op == STORE_OP) || (pI->op == MEMORY_BARRIER_OP)||(pI->op==TENSOR_CORE_LOAD_OP)||(pI->op==TENSOR_CORE_STORE_OP) ) { + if( m_mem_out->has_free(m_shader->m_config->sub_core_model, m_id) && (!diff_exec_units || previous_issued_inst_exec_type != exec_unit_type_t::MEM)) { + m_shader->issue_warp(*m_mem_out,pI,active_mask,warp_id,m_id); + issued++; + issued_inst=true; + warp_inst_issued = true; + previous_issued_inst_exec_type = exec_unit_type_t::MEM; + } + } else { - // This code need to be refactored - if (pI->op != TENSOR_CORE_OP && pI->op != SFU_OP && - pI->op != DP_OP) { - bool execute_on_SP = false; - bool execute_on_INT = false; + bool sp_pipe_avail = m_sp_out->has_free(m_shader->m_config->sub_core_model, m_id); + bool sfu_pipe_avail = m_sfu_out->has_free(m_shader->m_config->sub_core_model, m_id); + bool tensor_core_pipe_avail = m_tensor_core_out->has_free(m_shader->m_config->sub_core_model, m_id); + bool dp_pipe_avail = m_dp_out->has_free(m_shader->m_config->sub_core_model, m_id); + bool int_pipe_avail = m_int_out->has_free(m_shader->m_config->sub_core_model, m_id); - // if INT unit pipline exist, then execute ALU and INT - // operations on INT unit and SP-FPU on SP unit (like in Volta) - // if INT unit pipline does not exist, then execute all ALU, INT - // and SP operations on SP unit (as in Fermi, Pascal GPUs) - if (m_shader->m_config->gpgpu_num_int_units > 0 && - int_pipe_avail && pI->op != SP_OP && - !(diff_exec_units && - previous_issued_inst_exec_type == exec_unit_type_t::INT)) - execute_on_INT = true; - else if (sp_pipe_avail && - (m_shader->m_config->gpgpu_num_int_units == 0 || - (m_shader->m_config->gpgpu_num_int_units > 0 && - pI->op == SP_OP)) && - !(diff_exec_units && - previous_issued_inst_exec_type == - exec_unit_type_t::SP)) - execute_on_SP = true; + //This code need to be refactored + if(pI->op != TENSOR_CORE_OP && pI->op != SFU_OP && pI->op != DP_OP) { + + bool execute_on_SP = false; + bool execute_on_INT = false; - if (execute_on_INT || execute_on_SP) { - // Jin: special for CDP api - if (pI->m_is_cdp && !warp(warp_id).m_cdp_dummy) { - assert(warp(warp_id).m_cdp_latency == 0); + //if INT unit pipline exist, then execute ALU and INT operations on INT unit and SP-FPU on SP unit (like in Volta) + //if INT unit pipline does not exist, then execute all ALU, INT and SP operations on SP unit (as in Fermi, Pascal GPUs) + if(m_shader->m_config->gpgpu_num_int_units > 0 && + int_pipe_avail && + pI->op != SP_OP && + !(diff_exec_units && previous_issued_inst_exec_type == exec_unit_type_t::INT)) + execute_on_INT = true; + else if (sp_pipe_avail && + (m_shader->m_config->gpgpu_num_int_units == 0 || + (m_shader->m_config->gpgpu_num_int_units > 0 && pI->op == SP_OP)) && + !(diff_exec_units && previous_issued_inst_exec_type == exec_unit_type_t::SP) ) + execute_on_SP = true; - if (pI->m_is_cdp == 1) - warp(warp_id).m_cdp_latency = - m_shader->m_config->gpgpu_ctx->func_sim - ->cdp_latency[pI->m_is_cdp - 1]; - else // cudaLaunchDeviceV2 and cudaGetParameterBufferV2 - warp(warp_id).m_cdp_latency = - m_shader->m_config->gpgpu_ctx->func_sim - ->cdp_latency[pI->m_is_cdp - 1] + - m_shader->m_config->gpgpu_ctx->func_sim - ->cdp_latency[pI->m_is_cdp] * - active_mask.count(); - warp(warp_id).m_cdp_dummy = true; - break; - } else if (pI->m_is_cdp && warp(warp_id).m_cdp_dummy) { - assert(warp(warp_id).m_cdp_latency == 0); - warp(warp_id).m_cdp_dummy = false; - } - } - if (execute_on_SP) { - m_shader->issue_warp(*m_sp_out, pI, active_mask, warp_id, - m_id); - issued++; - issued_inst = true; - warp_inst_issued = true; - previous_issued_inst_exec_type = exec_unit_type_t::SP; - } else if (execute_on_INT) { - m_shader->issue_warp(*m_int_out, pI, active_mask, warp_id, - m_id); - issued++; - issued_inst = true; - warp_inst_issued = true; - previous_issued_inst_exec_type = exec_unit_type_t::INT; - } - } else if ((m_shader->m_config->gpgpu_num_dp_units > 0) && - (pI->op == DP_OP) && - !(diff_exec_units && - previous_issued_inst_exec_type == - exec_unit_type_t::DP)) { - if (dp_pipe_avail) { - m_shader->issue_warp(*m_dp_out, pI, active_mask, warp_id, - m_id); - issued++; - issued_inst = true; - warp_inst_issued = true; - previous_issued_inst_exec_type = exec_unit_type_t::DP; - } - } // If the DP units = 0 (like in Fermi archi), then execute DP - // inst on SFU unit - else if (((m_shader->m_config->gpgpu_num_dp_units == 0 && - pI->op == DP_OP) || - (pI->op == SFU_OP) || (pI->op == ALU_SFU_OP)) && - !(diff_exec_units && - previous_issued_inst_exec_type == - exec_unit_type_t::SFU)) { - if (sfu_pipe_avail) { - m_shader->issue_warp(*m_sfu_out, pI, active_mask, warp_id, - m_id); - issued++; - issued_inst = true; - warp_inst_issued = true; - previous_issued_inst_exec_type = exec_unit_type_t::SFU; - } - } else if ((pI->op == TENSOR_CORE_OP) && - !(diff_exec_units && - previous_issued_inst_exec_type == - exec_unit_type_t::SP)) { - if (tensor_core_pipe_avail) { - m_shader->issue_warp(*m_tensor_core_out, pI, active_mask, - warp_id, m_id); - issued++; - issued_inst = true; - warp_inst_issued = true; - previous_issued_inst_exec_type = exec_unit_type_t::TENSOR; + if(execute_on_INT || execute_on_SP) { + //Jin: special for CDP api + if(pI->m_is_cdp && !warp(warp_id).m_cdp_dummy) { + assert(warp(warp_id).m_cdp_latency == 0); + + if(pI->m_is_cdp == 1) + warp(warp_id).m_cdp_latency = m_shader->m_config->gpgpu_ctx->func_sim->cdp_latency[pI->m_is_cdp - 1]; + else //cudaLaunchDeviceV2 and cudaGetParameterBufferV2 + warp(warp_id).m_cdp_latency = m_shader->m_config->gpgpu_ctx->func_sim->cdp_latency[pI->m_is_cdp - 1] + + m_shader->m_config->gpgpu_ctx->func_sim->cdp_latency[pI->m_is_cdp] * active_mask.count(); + warp(warp_id).m_cdp_dummy = true; + break; + } + else if(pI->m_is_cdp && warp(warp_id).m_cdp_dummy) { + assert(warp(warp_id).m_cdp_latency == 0); + warp(warp_id).m_cdp_dummy = false; + } + } + + if(execute_on_SP) { + m_shader->issue_warp(*m_sp_out,pI,active_mask,warp_id,m_id); + issued++; + issued_inst=true; + warp_inst_issued = true; + previous_issued_inst_exec_type = exec_unit_type_t::SP; + } else if (execute_on_INT) { + m_shader->issue_warp(*m_int_out,pI,active_mask,warp_id,m_id); + issued++; + issued_inst=true; + warp_inst_issued = true; + previous_issued_inst_exec_type = exec_unit_type_t::INT; + } + } else if ( (m_shader->m_config->gpgpu_num_dp_units > 0) && (pI->op == DP_OP) && !(diff_exec_units && previous_issued_inst_exec_type == exec_unit_type_t::DP)) { + if( dp_pipe_avail ) { + m_shader->issue_warp(*m_dp_out,pI,active_mask,warp_id,m_id); + issued++; + issued_inst=true; + warp_inst_issued = true; + previous_issued_inst_exec_type = exec_unit_type_t::DP; + } + } //If the DP units = 0 (like in Fermi archi), then execute DP inst on SFU unit + else if ( ((m_shader->m_config->gpgpu_num_dp_units == 0 && pI->op == DP_OP) || (pI->op == SFU_OP) || (pI->op == ALU_SFU_OP)) && !(diff_exec_units && previous_issued_inst_exec_type == exec_unit_type_t::SFU)) { + if( sfu_pipe_avail ) { + m_shader->issue_warp(*m_sfu_out,pI,active_mask,warp_id,m_id); + issued++; + issued_inst=true; + warp_inst_issued = true; + previous_issued_inst_exec_type = exec_unit_type_t::SFU; + } + } + else if ( (pI->op == TENSOR_CORE_OP) && !(diff_exec_units && previous_issued_inst_exec_type == exec_unit_type_t::SP) ) { + if( tensor_core_pipe_avail ) { + m_shader->issue_warp(*m_tensor_core_out,pI,active_mask,warp_id,m_id); + issued++; + issued_inst=true; + warp_inst_issued = true; + previous_issued_inst_exec_type = exec_unit_type_t::TENSOR; + } + } + }//end of else + } else { + + SCHED_DPRINTF( "Warp (warp_id %u, dynamic_warp_id %u) fails scoreboard\n", + (*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id() ); + } } - } - } // end of else - } else { - SCHED_DPRINTF( - "Warp (warp_id %u, dynamic_warp_id %u) fails scoreboard\n", - (*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id()); - } - } - } else if (valid) { - // this case can happen after a return instruction in diverged warp - SCHED_DPRINTF( - "Warp (warp_id %u, dynamic_warp_id %u) return from diverged warp " - "flush\n", - (*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id()); - warp(warp_id).set_next_pc(pc); - warp(warp_id).ibuffer_flush(); - } - if (warp_inst_issued) { - SCHED_DPRINTF( - "Warp (warp_id %u, dynamic_warp_id %u) issued %u instructions\n", - (*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id(), issued); - do_on_warp_issued(warp_id, issued, iter); - } - checked++; - } - if (issued) { - // This might be a bit inefficient, but we need to maintain - // two ordered list for proper scheduler execution. - // We could remove the need for this loop by associating a - // supervised_is index with each entry in the - // m_next_cycle_prioritized_warps - // vector. For now, just run through until you find the right warp_id - for (std::vector<shd_warp_t *>::const_iterator supervised_iter = - m_supervised_warps.begin(); - supervised_iter != m_supervised_warps.end(); ++supervised_iter) { - if (*iter == *supervised_iter) { - m_last_supervised_issued = supervised_iter; + } else if( valid ) { + // this case can happen after a return instruction in diverged warp + SCHED_DPRINTF( "Warp (warp_id %u, dynamic_warp_id %u) return from diverged warp flush\n", + (*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id() ); + warp(warp_id).set_next_pc(pc); + warp(warp_id).ibuffer_flush(); + } + if(warp_inst_issued) { + SCHED_DPRINTF( "Warp (warp_id %u, dynamic_warp_id %u) issued %u instructions\n", + (*iter)->get_warp_id(), + (*iter)->get_dynamic_warp_id(), + issued ); + do_on_warp_issued( warp_id, issued, iter ); + } + checked++; } - } + if ( issued ) { + // This might be a bit inefficient, but we need to maintain + // two ordered list for proper scheduler execution. + // We could remove the need for this loop by associating a + // supervised_is index with each entry in the m_next_cycle_prioritized_warps + // vector. For now, just run through until you find the right warp_id + for ( std::vector< shd_warp_t* >::const_iterator supervised_iter = m_supervised_warps.begin(); + supervised_iter != m_supervised_warps.end(); + ++supervised_iter ) { + if ( *iter == *supervised_iter ) { + m_last_supervised_issued = supervised_iter; + } + } - if (issued == 1) - m_stats->single_issue_nums[m_id]++; - else if (issued > 1) - m_stats->dual_issue_nums[m_id]++; - else - abort(); // issued should be > 0 + if(issued == 1) + m_stats->single_issue_nums[m_id]++; + else if(issued > 1) + m_stats->dual_issue_nums[m_id]++; + else + abort(); //issued should be > 0 - break; + break; + } } - } - // issue stall statistics: - if (!valid_inst) - m_stats->shader_cycle_distro[0]++; // idle or control hazard - else if (!ready_inst) - m_stats->shader_cycle_distro[1]++; // waiting for RAW hazards (possibly due - // to memory) - else if (!issued_inst) - m_stats->shader_cycle_distro[2]++; // pipeline stalled + // issue stall statistics: + if( !valid_inst ) + m_stats->shader_cycle_distro[0]++; // idle or control hazard + else if( !ready_inst ) + m_stats->shader_cycle_distro[1]++; // waiting for RAW hazards (possibly due to memory) + else if( !issued_inst ) + m_stats->shader_cycle_distro[2]++; // pipeline stalled } -void scheduler_unit::do_on_warp_issued( - unsigned warp_id, unsigned num_issued, - const std::vector<shd_warp_t *>::const_iterator &prioritized_iter) { - m_stats->event_warp_issued(m_shader->get_sid(), warp_id, num_issued, - warp(warp_id).get_dynamic_warp_id()); - warp(warp_id).ibuffer_step(); +void scheduler_unit::do_on_warp_issued( unsigned warp_id, + unsigned num_issued, + const std::vector< shd_warp_t* >::const_iterator& prioritized_iter ) +{ + m_stats->event_warp_issued( m_shader->get_sid(), + warp_id, + num_issued, + warp(warp_id).get_dynamic_warp_id() ); + warp(warp_id).ibuffer_step(); } -bool scheduler_unit::sort_warps_by_oldest_dynamic_id(shd_warp_t *lhs, - shd_warp_t *rhs) { - if (rhs && lhs) { - if (lhs->done_exit() || lhs->waiting()) { - return false; - } else if (rhs->done_exit() || rhs->waiting()) { - return true; +bool scheduler_unit::sort_warps_by_oldest_dynamic_id(shd_warp_t* lhs, shd_warp_t* rhs) +{ + if (rhs && lhs) { + if ( lhs->done_exit() || lhs->waiting() ) { + return false; + } else if ( rhs->done_exit() || rhs->waiting() ) { + return true; + } else { + return lhs->get_dynamic_warp_id() < rhs->get_dynamic_warp_id(); + } } else { - return lhs->get_dynamic_warp_id() < rhs->get_dynamic_warp_id(); + return lhs < rhs; } - } else { - return lhs < rhs; - } } -void lrr_scheduler::order_warps() { - order_lrr(m_next_cycle_prioritized_warps, m_supervised_warps, - m_last_supervised_issued, m_supervised_warps.size()); +void lrr_scheduler::order_warps() +{ + order_lrr( m_next_cycle_prioritized_warps, + m_supervised_warps, + m_last_supervised_issued, + m_supervised_warps.size() ); } -void gto_scheduler::order_warps() { - order_by_priority(m_next_cycle_prioritized_warps, m_supervised_warps, - m_last_supervised_issued, m_supervised_warps.size(), - ORDERING_GREEDY_THEN_PRIORITY_FUNC, - scheduler_unit::sort_warps_by_oldest_dynamic_id); +void gto_scheduler::order_warps() +{ + order_by_priority( m_next_cycle_prioritized_warps, + m_supervised_warps, + m_last_supervised_issued, + m_supervised_warps.size(), + ORDERING_GREEDY_THEN_PRIORITY_FUNC, + scheduler_unit::sort_warps_by_oldest_dynamic_id ); } -void oldest_scheduler::order_warps() { - order_by_priority(m_next_cycle_prioritized_warps, m_supervised_warps, - m_last_supervised_issued, m_supervised_warps.size(), - ORDERED_PRIORITY_FUNC_ONLY, - scheduler_unit::sort_warps_by_oldest_dynamic_id); +void oldest_scheduler::order_warps() +{ + order_by_priority( m_next_cycle_prioritized_warps, + m_supervised_warps, + m_last_supervised_issued, + m_supervised_warps.size(), + ORDERED_PRIORITY_FUNC_ONLY, + scheduler_unit::sort_warps_by_oldest_dynamic_id ); } -void two_level_active_scheduler::do_on_warp_issued( - unsigned warp_id, unsigned num_issued, - const std::vector<shd_warp_t *>::const_iterator &prioritized_iter) { - scheduler_unit::do_on_warp_issued(warp_id, num_issued, prioritized_iter); - if (SCHEDULER_PRIORITIZATION_LRR == m_inner_level_prioritization) { - std::vector<shd_warp_t *> new_active; - order_lrr(new_active, m_next_cycle_prioritized_warps, prioritized_iter, - m_next_cycle_prioritized_warps.size()); - m_next_cycle_prioritized_warps = new_active; - } else { - fprintf(stderr, "Unimplemented m_inner_level_prioritization: %d\n", - m_inner_level_prioritization); - abort(); - } +void +two_level_active_scheduler::do_on_warp_issued( unsigned warp_id, + unsigned num_issued, + const std::vector< shd_warp_t* >::const_iterator& prioritized_iter ) +{ + scheduler_unit::do_on_warp_issued( warp_id, num_issued, prioritized_iter ); + if ( SCHEDULER_PRIORITIZATION_LRR == m_inner_level_prioritization ) { + std::vector< shd_warp_t* > new_active; + order_lrr( new_active, + m_next_cycle_prioritized_warps, + prioritized_iter, + m_next_cycle_prioritized_warps.size() ); + m_next_cycle_prioritized_warps = new_active; + } else { + fprintf( stderr, + "Unimplemented m_inner_level_prioritization: %d\n", + m_inner_level_prioritization ); + abort(); + } } -void two_level_active_scheduler::order_warps() { - // Move waiting warps to m_pending_warps - unsigned num_demoted = 0; - for (std::vector<shd_warp_t *>::iterator iter = - m_next_cycle_prioritized_warps.begin(); - iter != m_next_cycle_prioritized_warps.end();) { - bool waiting = (*iter)->waiting(); - for (int i = 0; i < MAX_INPUT_VALUES; i++) { - const warp_inst_t *inst = (*iter)->ibuffer_next_inst(); - // Is the instruction waiting on a long operation? - if (inst && inst->in[i] > 0 && - this->m_scoreboard->islongop((*iter)->get_warp_id(), inst->in[i])) { - waiting = true; - } - } +void two_level_active_scheduler::order_warps() +{ + //Move waiting warps to m_pending_warps + unsigned num_demoted = 0; + for ( std::vector< shd_warp_t* >::iterator iter = m_next_cycle_prioritized_warps.begin(); + iter != m_next_cycle_prioritized_warps.end(); ) { + bool waiting = (*iter)->waiting(); + for (int i=0; i<MAX_INPUT_VALUES; i++){ + const warp_inst_t* inst = (*iter)->ibuffer_next_inst(); + //Is the instruction waiting on a long operation? + if ( inst && inst->in[i] > 0 && this->m_scoreboard->islongop((*iter)->get_warp_id(), inst->in[i])){ + waiting = true; + } + } - if (waiting) { - m_pending_warps.push_back(*iter); - iter = m_next_cycle_prioritized_warps.erase(iter); - SCHED_DPRINTF("DEMOTED warp_id=%d, dynamic_warp_id=%d\n", - (*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id()); - ++num_demoted; - } else { - ++iter; + if( waiting ) { + m_pending_warps.push_back(*iter); + iter = m_next_cycle_prioritized_warps.erase(iter); + SCHED_DPRINTF( "DEMOTED warp_id=%d, dynamic_warp_id=%d\n", + (*iter)->get_warp_id(), + (*iter)->get_dynamic_warp_id() ); + ++num_demoted; + } else { + ++iter; + } } - } - // If there is space in m_next_cycle_prioritized_warps, promote the next - // m_pending_warps - unsigned num_promoted = 0; - if (SCHEDULER_PRIORITIZATION_SRR == m_outer_level_prioritization) { - while (m_next_cycle_prioritized_warps.size() < m_max_active_warps) { - m_next_cycle_prioritized_warps.push_back(m_pending_warps.front()); - m_pending_warps.pop_front(); - SCHED_DPRINTF( - "PROMOTED warp_id=%d, dynamic_warp_id=%d\n", - (m_next_cycle_prioritized_warps.back())->get_warp_id(), - (m_next_cycle_prioritized_warps.back())->get_dynamic_warp_id()); - ++num_promoted; + //If there is space in m_next_cycle_prioritized_warps, promote the next m_pending_warps + unsigned num_promoted = 0; + if ( SCHEDULER_PRIORITIZATION_SRR == m_outer_level_prioritization ) { + while ( m_next_cycle_prioritized_warps.size() < m_max_active_warps ) { + m_next_cycle_prioritized_warps.push_back(m_pending_warps.front()); + m_pending_warps.pop_front(); + SCHED_DPRINTF( "PROMOTED warp_id=%d, dynamic_warp_id=%d\n", + (m_next_cycle_prioritized_warps.back())->get_warp_id(), + (m_next_cycle_prioritized_warps.back())->get_dynamic_warp_id() ); + ++num_promoted; + } + } else { + fprintf( stderr, + "Unimplemented m_outer_level_prioritization: %d\n", + m_outer_level_prioritization ); + abort(); } - } else { - fprintf(stderr, "Unimplemented m_outer_level_prioritization: %d\n", - m_outer_level_prioritization); - abort(); - } - assert(num_promoted == num_demoted); + assert( num_promoted == num_demoted ); } -swl_scheduler::swl_scheduler(shader_core_stats *stats, shader_core_ctx *shader, - Scoreboard *scoreboard, simt_stack **simt, - std::vector<shd_warp_t> *warp, - register_set *sp_out, register_set *dp_out, - register_set *sfu_out, register_set *int_out, - register_set *tensor_core_out, - register_set *mem_out, int id, char *config_string) - : scheduler_unit(stats, shader, scoreboard, simt, warp, sp_out, dp_out, - sfu_out, int_out, tensor_core_out, mem_out, id) { - unsigned m_prioritization_readin; - int ret = sscanf(config_string, "warp_limiting:%d:%d", - &m_prioritization_readin, &m_num_warps_to_limit); - assert(2 == ret); - m_prioritization = (scheduler_prioritization_type)m_prioritization_readin; - // Currently only GTO is implemented - assert(m_prioritization == SCHEDULER_PRIORITIZATION_GTO); - assert(m_num_warps_to_limit <= shader->get_config()->max_warps_per_shader); +swl_scheduler::swl_scheduler ( shader_core_stats* stats, shader_core_ctx* shader, + Scoreboard* scoreboard, simt_stack** simt, + std::vector<shd_warp_t>* warp, + register_set* sp_out, + register_set* dp_out, + register_set* sfu_out, + register_set* int_out, + register_set* tensor_core_out, + register_set* mem_out, + int id, + char* config_string ) + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out, int_out, tensor_core_out, mem_out, id ) +{ + unsigned m_prioritization_readin; + int ret = sscanf( config_string, + "warp_limiting:%d:%d", + &m_prioritization_readin, + &m_num_warps_to_limit + ); + assert( 2 == ret ); + m_prioritization = (scheduler_prioritization_type)m_prioritization_readin; + // Currently only GTO is implemented + assert( m_prioritization == SCHEDULER_PRIORITIZATION_GTO ); + assert( m_num_warps_to_limit <= shader->get_config()->max_warps_per_shader ); } -void swl_scheduler::order_warps() { - if (SCHEDULER_PRIORITIZATION_GTO == m_prioritization) { - order_by_priority(m_next_cycle_prioritized_warps, m_supervised_warps, - m_last_supervised_issued, - MIN(m_num_warps_to_limit, m_supervised_warps.size()), - ORDERING_GREEDY_THEN_PRIORITY_FUNC, - scheduler_unit::sort_warps_by_oldest_dynamic_id); - } else { - fprintf(stderr, "swl_scheduler m_prioritization = %d\n", m_prioritization); - abort(); - } +void swl_scheduler::order_warps() +{ + if ( SCHEDULER_PRIORITIZATION_GTO == m_prioritization ) { + order_by_priority( m_next_cycle_prioritized_warps, + m_supervised_warps, + m_last_supervised_issued, + MIN( m_num_warps_to_limit, m_supervised_warps.size() ), + ORDERING_GREEDY_THEN_PRIORITY_FUNC, + scheduler_unit::sort_warps_by_oldest_dynamic_id ); + } else { + fprintf(stderr, "swl_scheduler m_prioritization = %d\n", m_prioritization); + abort(); + } } -void shader_core_ctx::read_operands() {} +void shader_core_ctx::read_operands() +{ +} -address_type coalesced_segment(address_type addr, - unsigned segment_size_lg2bytes) { - return (addr >> segment_size_lg2bytes); +address_type coalesced_segment(address_type addr, unsigned segment_size_lg2bytes) +{ + return (addr >> segment_size_lg2bytes); } -// Returns numbers of addresses in translated_addrs, each addr points to a 4B -// (32-bit) word -unsigned shader_core_ctx::translate_local_memaddr( - address_type localaddr, unsigned tid, unsigned num_shader, - unsigned datasize, new_addr_type *translated_addrs) { - // During functional execution, each thread sees its own memory space for - // local memory, but these - // need to be mapped to a shared address space for timing simulation. We do - // that mapping here. +// Returns numbers of addresses in translated_addrs, each addr points to a 4B (32-bit) word +unsigned shader_core_ctx::translate_local_memaddr( address_type localaddr, unsigned tid, unsigned num_shader, unsigned datasize, new_addr_type* translated_addrs ) +{ + // During functional execution, each thread sees its own memory space for local memory, but these + // need to be mapped to a shared address space for timing simulation. We do that mapping here. - address_type thread_base = 0; - unsigned max_concurrent_threads = 0; - if (m_config->gpgpu_local_mem_map) { - // Dnew = D*N + T%nTpC + nTpC*C - // N = nTpC*nCpS*nS (max concurent threads) - // C = nS*K + S (hw cta number per gpu) - // K = T/nTpC (hw cta number per core) - // D = data index - // T = thread - // nTpC = number of threads per CTA - // nCpS = number of CTA per shader - // - // for a given local memory address threads in a CTA map to contiguous - // addresses, - // then distribute across memory space by CTAs from successive shader cores - // first, - // then by successive CTA in same shader core - thread_base = - 4 * (kernel_padded_threads_per_cta * - (m_sid + num_shader * (tid / kernel_padded_threads_per_cta)) + - tid % kernel_padded_threads_per_cta); - max_concurrent_threads = - kernel_padded_threads_per_cta * kernel_max_cta_per_shader * num_shader; - } else { - // legacy mapping that maps the same address in the local memory space of - // all threads - // to a single contiguous address region - thread_base = 4 * (m_config->n_thread_per_shader * m_sid + tid); - max_concurrent_threads = num_shader * m_config->n_thread_per_shader; - } - assert(thread_base < 4 /*word size*/ * max_concurrent_threads); + address_type thread_base = 0; + unsigned max_concurrent_threads=0; + if (m_config->gpgpu_local_mem_map) { + // Dnew = D*N + T%nTpC + nTpC*C + // N = nTpC*nCpS*nS (max concurent threads) + // C = nS*K + S (hw cta number per gpu) + // K = T/nTpC (hw cta number per core) + // D = data index + // T = thread + // nTpC = number of threads per CTA + // nCpS = number of CTA per shader + // + // for a given local memory address threads in a CTA map to contiguous addresses, + // then distribute across memory space by CTAs from successive shader cores first, + // then by successive CTA in same shader core + thread_base = 4*(kernel_padded_threads_per_cta * (m_sid + num_shader * (tid / kernel_padded_threads_per_cta)) + + tid % kernel_padded_threads_per_cta); + max_concurrent_threads = kernel_padded_threads_per_cta * kernel_max_cta_per_shader * num_shader; + } else { + // legacy mapping that maps the same address in the local memory space of all threads + // to a single contiguous address region + thread_base = 4*(m_config->n_thread_per_shader * m_sid + tid); + max_concurrent_threads = num_shader * m_config->n_thread_per_shader; + } + assert( thread_base < 4/*word size*/*max_concurrent_threads ); - // If requested datasize > 4B, split into multiple 4B accesses - // otherwise do one sub-4 byte memory access - unsigned num_accesses = 0; + // If requested datasize > 4B, split into multiple 4B accesses + // otherwise do one sub-4 byte memory access + unsigned num_accesses = 0; - if (datasize >= 4) { - // >4B access, split into 4B chunks - assert(datasize % 4 == 0); // Must be a multiple of 4B - num_accesses = datasize / 4; - assert(num_accesses <= MAX_ACCESSES_PER_INSN_PER_THREAD); // max 32B - assert(localaddr % 4 == 0); // Address must be 4B aligned - required if - // accessing 4B per request, otherwise access - // will overflow into next thread's space - for (unsigned i = 0; i < num_accesses; i++) { - address_type local_word = localaddr / 4 + i; - address_type linear_address = local_word * max_concurrent_threads * 4 + - thread_base + LOCAL_GENERIC_START; - translated_addrs[i] = linear_address; - } - } else { - // Sub-4B access, do only one access - assert(datasize > 0); - num_accesses = 1; - address_type local_word = localaddr / 4; - address_type local_word_offset = localaddr % 4; - assert((localaddr + datasize - 1) / 4 == - local_word); // Make sure access doesn't overflow into next 4B chunk - address_type linear_address = local_word * max_concurrent_threads * 4 + - local_word_offset + thread_base + - LOCAL_GENERIC_START; - translated_addrs[0] = linear_address; - } - return num_accesses; + if(datasize >= 4) { + // >4B access, split into 4B chunks + assert(datasize%4 == 0); // Must be a multiple of 4B + num_accesses = datasize/4; + assert(num_accesses <= MAX_ACCESSES_PER_INSN_PER_THREAD); // max 32B + assert(localaddr%4 == 0); // Address must be 4B aligned - required if accessing 4B per request, otherwise access will overflow into next thread's space + for(unsigned i=0; i<num_accesses; i++) { + address_type local_word = localaddr/4 + i; + address_type linear_address = local_word*max_concurrent_threads*4 + thread_base + LOCAL_GENERIC_START; + translated_addrs[i] = linear_address; + } + } else { + // Sub-4B access, do only one access + assert(datasize > 0); + num_accesses = 1; + address_type local_word = localaddr/4; + address_type local_word_offset = localaddr%4; + assert( (localaddr+datasize-1)/4 == local_word ); // Make sure access doesn't overflow into next 4B chunk + address_type linear_address = local_word*max_concurrent_threads*4 + local_word_offset + thread_base + LOCAL_GENERIC_START; + translated_addrs[0] = linear_address; + } + return num_accesses; } ///////////////////////////////////////////////////////////////////////////////////////// -int shader_core_ctx::test_res_bus(int latency) { - for (unsigned i = 0; i < num_result_bus; i++) { - if (!m_result_bus[i]->test(latency)) { - return i; - } - } - return -1; +int shader_core_ctx::test_res_bus(int latency){ + for(unsigned i=0; i<num_result_bus; i++){ + if(!m_result_bus[i]->test(latency)){return i;} + } + return -1; } -void shader_core_ctx::execute() { - for (unsigned i = 0; i < num_result_bus; i++) { - *(m_result_bus[i]) >>= 1; - } - for (unsigned n = 0; n < m_num_function_units; n++) { - unsigned multiplier = m_fu[n]->clock_multiplier(); - for (unsigned c = 0; c < multiplier; c++) m_fu[n]->cycle(); - m_fu[n]->active_lanes_in_pipeline(); - enum pipeline_stage_name_t issue_port = m_issue_port[n]; - register_set &issue_inst = m_pipeline_reg[issue_port]; - warp_inst_t **ready_reg = issue_inst.get_ready(); - if (issue_inst.has_ready() && m_fu[n]->can_issue(**ready_reg)) { - bool schedule_wb_now = !m_fu[n]->stallable(); - int resbus = -1; - if (schedule_wb_now && - (resbus = test_res_bus((*ready_reg)->latency)) != -1) { - assert((*ready_reg)->latency < MAX_ALU_LATENCY); - m_result_bus[resbus]->set((*ready_reg)->latency); - m_fu[n]->issue(issue_inst); - } else if (!schedule_wb_now) { - m_fu[n]->issue(issue_inst); - } else { - // stall issue (cannot reserve result bus) - } +void shader_core_ctx::execute() +{ + for(unsigned i=0; i<num_result_bus; i++){ + *(m_result_bus[i]) >>=1; + } + for( unsigned n=0; n < m_num_function_units; n++ ) { + unsigned multiplier = m_fu[n]->clock_multiplier(); + for( unsigned c=0; c < multiplier; c++ ) + m_fu[n]->cycle(); + m_fu[n]->active_lanes_in_pipeline(); + enum pipeline_stage_name_t issue_port = m_issue_port[n]; + register_set& issue_inst = m_pipeline_reg[ issue_port ]; + warp_inst_t** ready_reg = issue_inst.get_ready(); + if( issue_inst.has_ready() && m_fu[n]->can_issue( **ready_reg ) ) { + bool schedule_wb_now = !m_fu[n]->stallable(); + int resbus = -1; + if( schedule_wb_now && (resbus=test_res_bus( (*ready_reg)->latency ))!=-1 ) { + assert( (*ready_reg)->latency < MAX_ALU_LATENCY ); + m_result_bus[resbus]->set( (*ready_reg)->latency ); + m_fu[n]->issue( issue_inst ); + } else if( !schedule_wb_now ) { + m_fu[n]->issue( issue_inst ); + } else { + // stall issue (cannot reserve result bus) + } + } } - } } -void ldst_unit::print_cache_stats(FILE *fp, unsigned &dl1_accesses, - unsigned &dl1_misses) { - if (m_L1D) { - m_L1D->print(fp, dl1_accesses, dl1_misses); - } +void ldst_unit::print_cache_stats( FILE *fp, unsigned& dl1_accesses, unsigned& dl1_misses ) { + if( m_L1D ) { + m_L1D->print( fp, dl1_accesses, dl1_misses ); + } } void ldst_unit::get_cache_stats(cache_stats &cs) { - // Adds stats to 'cs' from each cache - if (m_L1D) cs += m_L1D->get_stats(); - if (m_L1C) cs += m_L1C->get_stats(); - if (m_L1T) cs += m_L1T->get_stats(); + // Adds stats to 'cs' from each cache + if(m_L1D) + cs += m_L1D->get_stats(); + if(m_L1C) + cs += m_L1C->get_stats(); + if(m_L1T) + cs += m_L1T->get_stats(); + } -void ldst_unit::get_L1D_sub_stats(struct cache_sub_stats &css) const { - if (m_L1D) m_L1D->get_sub_stats(css); +void ldst_unit::get_L1D_sub_stats(struct cache_sub_stats &css) const{ + if(m_L1D) + m_L1D->get_sub_stats(css); } -void ldst_unit::get_L1C_sub_stats(struct cache_sub_stats &css) const { - if (m_L1C) m_L1C->get_sub_stats(css); +void ldst_unit::get_L1C_sub_stats(struct cache_sub_stats &css) const{ + if(m_L1C) + m_L1C->get_sub_stats(css); } -void ldst_unit::get_L1T_sub_stats(struct cache_sub_stats &css) const { - if (m_L1T) m_L1T->get_sub_stats(css); +void ldst_unit::get_L1T_sub_stats(struct cache_sub_stats &css) const{ + if(m_L1T) + m_L1T->get_sub_stats(css); } -void shader_core_ctx::warp_inst_complete(const warp_inst_t &inst) { -#if 0 +void shader_core_ctx::warp_inst_complete(const warp_inst_t &inst) +{ + + #if 0 printf("[warp_inst_complete] uid=%u core=%u warp=%u pc=%#x @ time=%llu issued@%llu\n", inst.get_uid(), m_sid, inst.warp_id(), inst.pc, gpu_tot_sim_cycle + gpu_sim_cycle, inst.get_issue_cycle()); -#endif + #endif - if (inst.op_pipe == SP__OP) - m_stats->m_num_sp_committed[m_sid]++; - else if (inst.op_pipe == SFU__OP) - m_stats->m_num_sfu_committed[m_sid]++; - else if (inst.op_pipe == MEM__OP) - m_stats->m_num_mem_committed[m_sid]++; + if(inst.op_pipe==SP__OP) + m_stats->m_num_sp_committed[m_sid]++; + else if(inst.op_pipe==SFU__OP) + m_stats->m_num_sfu_committed[m_sid]++; + else if(inst.op_pipe==MEM__OP) + m_stats->m_num_mem_committed[m_sid]++; - if (m_config->gpgpu_clock_gated_lanes == false) - m_stats->m_num_sim_insn[m_sid] += m_config->warp_size; + if(m_config->gpgpu_clock_gated_lanes==false) + m_stats->m_num_sim_insn[m_sid] += m_config->warp_size; else - m_stats->m_num_sim_insn[m_sid] += inst.active_count(); + m_stats->m_num_sim_insn[m_sid] += inst.active_count(); m_stats->m_num_sim_winsn[m_sid]++; m_gpu->gpu_sim_insn += inst.active_count(); inst.completed(m_gpu->gpu_tot_sim_cycle + m_gpu->gpu_sim_cycle); } -void shader_core_ctx::writeback() { - unsigned max_committed_thread_instructions = - m_config->warp_size * - (m_config->pipe_widths[EX_WB]); // from the functional units - m_stats->m_pipeline_duty_cycle[m_sid] = - ((float)(m_stats->m_num_sim_insn[m_sid] - - m_stats->m_last_num_sim_insn[m_sid])) / - max_committed_thread_instructions; +void shader_core_ctx::writeback() +{ - m_stats->m_last_num_sim_insn[m_sid] = m_stats->m_num_sim_insn[m_sid]; - m_stats->m_last_num_sim_winsn[m_sid] = m_stats->m_num_sim_winsn[m_sid]; + unsigned max_committed_thread_instructions=m_config->warp_size * (m_config->pipe_widths[EX_WB]); //from the functional units + m_stats->m_pipeline_duty_cycle[m_sid]=((float)(m_stats->m_num_sim_insn[m_sid]-m_stats->m_last_num_sim_insn[m_sid]))/max_committed_thread_instructions; - warp_inst_t **preg = m_pipeline_reg[EX_WB].get_ready(); - warp_inst_t *pipe_reg = (preg == NULL) ? NULL : *preg; - while (preg and !pipe_reg->empty()) { - /* - * Right now, the writeback stage drains all waiting instructions - * assuming there are enough ports in the register file or the - * conflicts are resolved at issue. - */ - /* - * The operand collector writeback can generally generate a stall - * However, here, the pipelines should be un-stallable. This is - * guaranteed because this is the first time the writeback function - * is called after the operand collector's step function, which - * resets the allocations. There is one case which could result in - * the writeback function returning false (stall), which is when - * an instruction tries to modify two registers (GPR and predicate) - * To handle this case, we ignore the return value (thus allowing - * no stalling). - */ + m_stats->m_last_num_sim_insn[m_sid]=m_stats->m_num_sim_insn[m_sid]; + m_stats->m_last_num_sim_winsn[m_sid]=m_stats->m_num_sim_winsn[m_sid]; - m_operand_collector.writeback(*pipe_reg); - unsigned warp_id = pipe_reg->warp_id(); - m_scoreboard->releaseRegisters(pipe_reg); - m_warp[warp_id].dec_inst_in_pipeline(); - warp_inst_complete(*pipe_reg); - m_gpu->gpu_sim_insn_last_update_sid = m_sid; - m_gpu->gpu_sim_insn_last_update = m_gpu->gpu_sim_cycle; - m_last_inst_gpu_sim_cycle = m_gpu->gpu_sim_cycle; - m_last_inst_gpu_tot_sim_cycle = m_gpu->gpu_tot_sim_cycle; - pipe_reg->clear(); - preg = m_pipeline_reg[EX_WB].get_ready(); - pipe_reg = (preg == NULL) ? NULL : *preg; - } + warp_inst_t** preg = m_pipeline_reg[EX_WB].get_ready(); + warp_inst_t* pipe_reg = (preg==NULL)? NULL:*preg; + while( preg and !pipe_reg->empty()) { + /* + * Right now, the writeback stage drains all waiting instructions + * assuming there are enough ports in the register file or the + * conflicts are resolved at issue. + */ + /* + * The operand collector writeback can generally generate a stall + * However, here, the pipelines should be un-stallable. This is + * guaranteed because this is the first time the writeback function + * is called after the operand collector's step function, which + * resets the allocations. There is one case which could result in + * the writeback function returning false (stall), which is when + * an instruction tries to modify two registers (GPR and predicate) + * To handle this case, we ignore the return value (thus allowing + * no stalling). + */ + + m_operand_collector.writeback(*pipe_reg); + unsigned warp_id = pipe_reg->warp_id(); + m_scoreboard->releaseRegisters( pipe_reg ); + m_warp[warp_id].dec_inst_in_pipeline(); + warp_inst_complete(*pipe_reg); + m_gpu->gpu_sim_insn_last_update_sid = m_sid; + m_gpu->gpu_sim_insn_last_update = m_gpu->gpu_sim_cycle; + m_last_inst_gpu_sim_cycle = m_gpu->gpu_sim_cycle; + m_last_inst_gpu_tot_sim_cycle = m_gpu->gpu_tot_sim_cycle; + pipe_reg->clear(); + preg = m_pipeline_reg[EX_WB].get_ready(); + pipe_reg = (preg==NULL)? NULL:*preg; + } } -bool ldst_unit::shared_cycle(warp_inst_t &inst, mem_stage_stall_type &rc_fail, - mem_stage_access_type &fail_type) { - if (inst.space.get_type() != shared_space) return true; +bool ldst_unit::shared_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type) +{ + if( inst.space.get_type() != shared_space ) + return true; - if (inst.has_dispatch_delay()) { - m_stats->gpgpu_n_shmem_bank_access[m_sid]++; - } + if(inst.has_dispatch_delay()){ + m_stats->gpgpu_n_shmem_bank_access[m_sid]++; + } - bool stall = inst.dispatch_delay(); - if (stall) { - fail_type = S_MEM; - rc_fail = BK_CONF; - } else - rc_fail = NO_RC_FAIL; - return !stall; + bool stall = inst.dispatch_delay(); + if( stall ) { + fail_type = S_MEM; + rc_fail = BK_CONF; + } else + rc_fail = NO_RC_FAIL; + return !stall; } -mem_stage_stall_type ldst_unit::process_cache_access( - cache_t *cache, new_addr_type address, warp_inst_t &inst, - std::list<cache_event> &events, mem_fetch *mf, - enum cache_request_status status) { - mem_stage_stall_type result = NO_RC_FAIL; - bool write_sent = was_write_sent(events); - bool read_sent = was_read_sent(events); - if (write_sent) { - unsigned inc_ack = (m_config->m_L1D_config.get_mshr_type() == SECTOR_ASSOC) - ? (mf->get_data_size() / SECTOR_SIZE) - : 1; +mem_stage_stall_type +ldst_unit::process_cache_access( cache_t* cache, + new_addr_type address, + warp_inst_t &inst, + std::list<cache_event>& events, + mem_fetch *mf, + enum cache_request_status status ) +{ + mem_stage_stall_type result = NO_RC_FAIL; + bool write_sent = was_write_sent(events); + bool read_sent = was_read_sent(events); + if( write_sent ) { + unsigned inc_ack = (m_config->m_L1D_config.get_mshr_type() == SECTOR_ASSOC)? + (mf->get_data_size()/SECTOR_SIZE) : 1; + + for(unsigned i=0; i< inc_ack; ++i) + m_core->inc_store_req( inst.warp_id() ); - for (unsigned i = 0; i < inc_ack; ++i) - m_core->inc_store_req(inst.warp_id()); - } - if (status == HIT) { - assert(!read_sent); - inst.accessq_pop_back(); - if (inst.is_load()) { - for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) - if (inst.out[r] > 0) m_pending_writes[inst.warp_id()][inst.out[r]]--; } - if (!write_sent) delete mf; - } else if (status == RESERVATION_FAIL) { - result = BK_CONF; - assert(!read_sent); - assert(!write_sent); - delete mf; - } else { - assert(status == MISS || status == HIT_RESERVED); - // inst.clear_active( access.get_warp_mask() ); // threads in mf writeback - // when mf returns - inst.accessq_pop_back(); - } - if (!inst.accessq_empty() && result == NO_RC_FAIL) result = COAL_STALL; - return result; + if ( status == HIT ) { + assert( !read_sent ); + inst.accessq_pop_back(); + if ( inst.is_load() ) { + for ( unsigned r=0; r < MAX_OUTPUT_VALUES; r++) + if (inst.out[r] > 0) + m_pending_writes[inst.warp_id()][inst.out[r]]--; + } + if( !write_sent ) + delete mf; + } else if ( status == RESERVATION_FAIL ) { + result = BK_CONF; + assert( !read_sent ); + assert( !write_sent ); + delete mf; + } else { + assert( status == MISS || status == HIT_RESERVED ); + //inst.clear_active( access.get_warp_mask() ); // threads in mf writeback when mf returns + inst.accessq_pop_back(); + } + if( !inst.accessq_empty() && result == NO_RC_FAIL) + result = COAL_STALL; + return result; } -mem_stage_stall_type ldst_unit::process_memory_access_queue(cache_t *cache, - warp_inst_t &inst) { - mem_stage_stall_type result = NO_RC_FAIL; - if (inst.accessq_empty()) return result; +mem_stage_stall_type ldst_unit::process_memory_access_queue( cache_t *cache, warp_inst_t &inst ) +{ + mem_stage_stall_type result = NO_RC_FAIL; + if( inst.accessq_empty() ) + return result; - if (!cache->data_port_free()) return DATA_PORT_STALL; + if( !cache->data_port_free() ) + return DATA_PORT_STALL; - // const mem_access_t &access = inst.accessq_back(); - mem_fetch *mf = m_mf_allocator->alloc( - inst, inst.accessq_back(), - m_core->get_gpu()->gpu_sim_cycle + m_core->get_gpu()->gpu_tot_sim_cycle); - std::list<cache_event> events; - enum cache_request_status status = cache->access( - mf->get_addr(), mf, - m_core->get_gpu()->gpu_sim_cycle + m_core->get_gpu()->gpu_tot_sim_cycle, - events); - return process_cache_access(cache, mf->get_addr(), inst, events, mf, status); + //const mem_access_t &access = inst.accessq_back(); + mem_fetch *mf = m_mf_allocator->alloc(inst,inst.accessq_back(),m_core->get_gpu()->gpu_sim_cycle+m_core->get_gpu()->gpu_tot_sim_cycle); + std::list<cache_event> events; + enum cache_request_status status = cache->access(mf->get_addr(),mf,m_core->get_gpu()->gpu_sim_cycle+m_core->get_gpu()->gpu_tot_sim_cycle,events); + return process_cache_access( cache, mf->get_addr(), inst, events, mf, status ); } -mem_stage_stall_type ldst_unit::process_memory_access_queue_l1cache( - l1_cache *cache, warp_inst_t &inst) { - mem_stage_stall_type result = NO_RC_FAIL; - if (inst.accessq_empty()) return result; +mem_stage_stall_type ldst_unit::process_memory_access_queue_l1cache( l1_cache *cache, warp_inst_t &inst ) +{ + mem_stage_stall_type result = NO_RC_FAIL; + if( inst.accessq_empty() ) + return result; - if (m_config->m_L1D_config.l1_latency > 0) { - for (int j = 0; j < m_config->m_L1D_config.l1_banks; - j++) { // We can handle at max l1_banks reqs per cycle + if(m_config->m_L1D_config.l1_latency > 0) + { + for(int j=0; j<m_config->m_L1D_config.l1_banks; j++) { //We can handle at max l1_banks reqs per cycle - if (inst.accessq_empty()) return result; + if( inst.accessq_empty() ) + return result; - mem_fetch *mf = m_mf_allocator->alloc( - inst, inst.accessq_back(), m_core->get_gpu()->gpu_sim_cycle + - m_core->get_gpu()->gpu_tot_sim_cycle); - unsigned bank_id = m_config->m_L1D_config.set_bank(mf->get_addr()); - assert(bank_id < m_config->m_L1D_config.l1_banks); + mem_fetch *mf = m_mf_allocator->alloc(inst,inst.accessq_back(),m_core->get_gpu()->gpu_sim_cycle+m_core->get_gpu()->gpu_tot_sim_cycle); + unsigned bank_id = m_config->m_L1D_config.set_bank(mf->get_addr()); + assert(bank_id < m_config->m_L1D_config.l1_banks); - if ((l1_latency_queue[bank_id][m_config->m_L1D_config.l1_latency - 1]) == - NULL) { - l1_latency_queue[bank_id][m_config->m_L1D_config.l1_latency - 1] = mf; + if((l1_latency_queue[bank_id][m_config->m_L1D_config.l1_latency-1]) == NULL) + { + l1_latency_queue[bank_id][m_config->m_L1D_config.l1_latency-1] = mf; - if (mf->get_inst().is_store()) { - unsigned inc_ack = - (m_config->m_L1D_config.get_mshr_type() == SECTOR_ASSOC) - ? (mf->get_data_size() / SECTOR_SIZE) - : 1; + if( mf->get_inst().is_store() ) { + unsigned inc_ack = (m_config->m_L1D_config.get_mshr_type() == SECTOR_ASSOC)? + (mf->get_data_size()/SECTOR_SIZE) : 1; - for (unsigned i = 0; i < inc_ack; ++i) - m_core->inc_store_req(inst.warp_id()); - } + for(unsigned i=0; i< inc_ack; ++i) + m_core->inc_store_req( inst.warp_id() ); + } - inst.accessq_pop_back(); - } else { - result = BK_CONF; - delete mf; - break; // do not try again, just break from the loop and try the next - // cycle - } - } - if (!inst.accessq_empty() && result != BK_CONF) result = COAL_STALL; + inst.accessq_pop_back(); + } + else + { + result = BK_CONF; + delete mf; + break; //do not try again, just break from the loop and try the next cycle + } + } + if( !inst.accessq_empty() && result !=BK_CONF) + result = COAL_STALL; - return result; - } else { - mem_fetch *mf = m_mf_allocator->alloc( - inst, inst.accessq_back(), m_core->get_gpu()->gpu_sim_cycle + - m_core->get_gpu()->gpu_tot_sim_cycle); - std::list<cache_event> events; - enum cache_request_status status = cache->access( - mf->get_addr(), mf, - m_core->get_gpu()->gpu_sim_cycle + m_core->get_gpu()->gpu_tot_sim_cycle, - events); - return process_cache_access(cache, mf->get_addr(), inst, events, mf, - status); - } + return result; + } + else + { + mem_fetch *mf = m_mf_allocator->alloc(inst,inst.accessq_back(),m_core->get_gpu()->gpu_sim_cycle+m_core->get_gpu()->gpu_tot_sim_cycle); + std::list<cache_event> events; + enum cache_request_status status = cache->access(mf->get_addr(),mf,m_core->get_gpu()->gpu_sim_cycle+m_core->get_gpu()->gpu_tot_sim_cycle,events); + return process_cache_access( cache, mf->get_addr(), inst, events, mf, status ); + } } -void ldst_unit::L1_latency_queue_cycle() { - for (int j = 0; j < m_config->m_L1D_config.l1_banks; j++) { - if ((l1_latency_queue[j][0]) != NULL) { - mem_fetch *mf_next = l1_latency_queue[j][0]; - std::list<cache_event> events; - enum cache_request_status status = - m_L1D->access(mf_next->get_addr(), mf_next, - m_core->get_gpu()->gpu_sim_cycle + - m_core->get_gpu()->gpu_tot_sim_cycle, - events); +void ldst_unit::L1_latency_queue_cycle() +{ + for(int j=0; j<m_config->m_L1D_config.l1_banks; j++) { + if((l1_latency_queue[j][0]) != NULL) + { + mem_fetch* mf_next = l1_latency_queue[j][0]; + std::list<cache_event> events; + enum cache_request_status status = m_L1D->access(mf_next->get_addr(),mf_next,m_core->get_gpu()->gpu_sim_cycle+m_core->get_gpu()->gpu_tot_sim_cycle,events); - bool write_sent = was_write_sent(events); - bool read_sent = was_read_sent(events); + bool write_sent = was_write_sent(events); + bool read_sent = was_read_sent(events); - if (status == HIT) { - assert(!read_sent); - l1_latency_queue[j][0] = NULL; - if (mf_next->get_inst().is_load()) { - for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) - if (mf_next->get_inst().out[r] > 0) { - assert(m_pending_writes[mf_next->get_inst().warp_id()] - [mf_next->get_inst().out[r]] > 0); - unsigned still_pending = - --m_pending_writes[mf_next->get_inst().warp_id()] - [mf_next->get_inst().out[r]]; - if (!still_pending) { - m_pending_writes[mf_next->get_inst().warp_id()].erase( - mf_next->get_inst().out[r]); - m_scoreboard->releaseRegister(mf_next->get_inst().warp_id(), - mf_next->get_inst().out[r]); - m_core->warp_inst_complete(mf_next->get_inst()); - } - } - } + if ( status == HIT ) { + assert( !read_sent ); + l1_latency_queue[j][0] = NULL; + if ( mf_next->get_inst().is_load() ) { + for ( unsigned r=0; r < MAX_OUTPUT_VALUES; r++) + if (mf_next->get_inst().out[r] > 0) + { + assert(m_pending_writes[mf_next->get_inst().warp_id()][mf_next->get_inst().out[r]]>0); + unsigned still_pending = --m_pending_writes[mf_next->get_inst().warp_id()][mf_next->get_inst().out[r]]; + if(!still_pending) + { + m_pending_writes[mf_next->get_inst().warp_id()].erase(mf_next->get_inst().out[r]); + m_scoreboard->releaseRegister(mf_next->get_inst().warp_id(),mf_next->get_inst().out[r]); + m_core->warp_inst_complete(mf_next->get_inst()); + } + } + } - // For write hit in WB policy - if (mf_next->get_inst().is_store() && !write_sent) { - unsigned dec_ack = - (m_config->m_L1D_config.get_mshr_type() == SECTOR_ASSOC) - ? (mf_next->get_data_size() / SECTOR_SIZE) - : 1; + //For write hit in WB policy + if(mf_next->get_inst().is_store() && !write_sent) + { + unsigned dec_ack = (m_config->m_L1D_config.get_mshr_type() == SECTOR_ASSOC)? + (mf_next->get_data_size()/SECTOR_SIZE) : 1; - mf_next->set_reply(); + mf_next->set_reply(); - for (unsigned i = 0; i < dec_ack; ++i) m_core->store_ack(mf_next); - } + for(unsigned i=0; i< dec_ack; ++i) + m_core->store_ack(mf_next); + } - if (!write_sent) delete mf_next; + if( !write_sent ) + delete mf_next; - } else if (status == RESERVATION_FAIL) { - assert(!read_sent); - assert(!write_sent); - } else { - assert(status == MISS || status == HIT_RESERVED); - l1_latency_queue[j][0] = NULL; - } - } + } else if ( status == RESERVATION_FAIL ) { + assert( !read_sent ); + assert( !write_sent ); + } else { + assert( status == MISS || status == HIT_RESERVED ); + l1_latency_queue[j][0] = NULL; + } + } + + for( unsigned stage = 0; stage<m_config->m_L1D_config.l1_latency-1; ++stage) + if( l1_latency_queue[j][stage] == NULL) { + l1_latency_queue[j][stage] = l1_latency_queue[j][stage+1] ; + l1_latency_queue[j][stage+1] = NULL; + } + } - for (unsigned stage = 0; stage < m_config->m_L1D_config.l1_latency - 1; - ++stage) - if (l1_latency_queue[j][stage] == NULL) { - l1_latency_queue[j][stage] = l1_latency_queue[j][stage + 1]; - l1_latency_queue[j][stage + 1] = NULL; - } - } } -bool ldst_unit::constant_cycle(warp_inst_t &inst, mem_stage_stall_type &rc_fail, - mem_stage_access_type &fail_type) { - if (inst.empty() || ((inst.space.get_type() != const_space) && - (inst.space.get_type() != param_space_kernel))) - return true; - if (inst.active_count() == 0) return true; - mem_stage_stall_type fail = process_memory_access_queue(m_L1C, inst); - if (fail != NO_RC_FAIL) { - rc_fail = fail; // keep other fails if this didn't fail. - fail_type = C_MEM; - if (rc_fail == BK_CONF or rc_fail == COAL_STALL) { - m_stats->gpgpu_n_cmem_portconflict++; // coal stalls aren't really a bank - // conflict, but this maintains - // previous behavior. - } - } - return inst.accessq_empty(); // done if empty. + + +bool ldst_unit::constant_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type) +{ + if( inst.empty() || ((inst.space.get_type() != const_space) && (inst.space.get_type() != param_space_kernel)) ) + return true; + if( inst.active_count() == 0 ) + return true; + mem_stage_stall_type fail = process_memory_access_queue(m_L1C,inst); + if (fail != NO_RC_FAIL){ + rc_fail = fail; //keep other fails if this didn't fail. + fail_type = C_MEM; + if (rc_fail == BK_CONF or rc_fail == COAL_STALL) { + m_stats->gpgpu_n_cmem_portconflict++; //coal stalls aren't really a bank conflict, but this maintains previous behavior. + } + } + return inst.accessq_empty(); //done if empty. } -bool ldst_unit::texture_cycle(warp_inst_t &inst, mem_stage_stall_type &rc_fail, - mem_stage_access_type &fail_type) { - if (inst.empty() || inst.space.get_type() != tex_space) return true; - if (inst.active_count() == 0) return true; - mem_stage_stall_type fail = process_memory_access_queue(m_L1T, inst); - if (fail != NO_RC_FAIL) { - rc_fail = fail; // keep other fails if this didn't fail. - fail_type = T_MEM; - } - return inst.accessq_empty(); // done if empty. +bool ldst_unit::texture_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type) +{ + if( inst.empty() || inst.space.get_type() != tex_space ) + return true; + if( inst.active_count() == 0 ) + return true; + mem_stage_stall_type fail = process_memory_access_queue(m_L1T,inst); + if (fail != NO_RC_FAIL){ + rc_fail = fail; //keep other fails if this didn't fail. + fail_type = T_MEM; + } + return inst.accessq_empty(); //done if empty. } -bool ldst_unit::memory_cycle(warp_inst_t &inst, - mem_stage_stall_type &stall_reason, - mem_stage_access_type &access_type) { - if (inst.empty() || ((inst.space.get_type() != global_space) && - (inst.space.get_type() != local_space) && - (inst.space.get_type() != param_space_local))) - return true; - if (inst.active_count() == 0) return true; - assert(!inst.accessq_empty()); - mem_stage_stall_type stall_cond = NO_RC_FAIL; - const mem_access_t &access = inst.accessq_back(); +bool ldst_unit::memory_cycle( warp_inst_t &inst, mem_stage_stall_type &stall_reason, mem_stage_access_type &access_type ) +{ + if( inst.empty() || + ((inst.space.get_type() != global_space) && + (inst.space.get_type() != local_space) && + (inst.space.get_type() != param_space_local)) ) + return true; + if( inst.active_count() == 0 ) + return true; + assert( !inst.accessq_empty() ); + mem_stage_stall_type stall_cond = NO_RC_FAIL; + const mem_access_t &access = inst.accessq_back(); - bool bypassL1D = false; - if (CACHE_GLOBAL == inst.cache_op || (m_L1D == NULL)) { - bypassL1D = true; - } else if (inst.space.is_global()) { // global memory access - // skip L1 cache if the option is enabled - if (m_core->get_config()->gmem_skip_L1D && (CACHE_L1 != inst.cache_op)) - bypassL1D = true; - } - if (bypassL1D) { - // bypass L1 cache - unsigned control_size = - inst.is_store() ? WRITE_PACKET_SIZE : READ_PACKET_SIZE; - unsigned size = access.get_size() + control_size; - // printf("Interconnect:Addr: %x, size=%d\n",access.get_addr(),size); - if (m_icnt->full(size, inst.is_store() || inst.isatomic())) { - stall_cond = ICNT_RC_FAIL; - } else { - mem_fetch *mf = m_mf_allocator->alloc( - inst, access, m_core->get_gpu()->gpu_sim_cycle + - m_core->get_gpu()->gpu_tot_sim_cycle); - m_icnt->push(mf); - inst.accessq_pop_back(); - // inst.clear_active( access.get_warp_mask() ); - if (inst.is_load()) { - for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) - if (inst.out[r] > 0) - assert(m_pending_writes[inst.warp_id()][inst.out[r]] > 0); - } else if (inst.is_store()) - m_core->inc_store_req(inst.warp_id()); - } - } else { - assert(CACHE_UNDEFINED != inst.cache_op); - stall_cond = process_memory_access_queue_l1cache(m_L1D, inst); - } - if (!inst.accessq_empty() && stall_cond == NO_RC_FAIL) - stall_cond = COAL_STALL; - if (stall_cond != NO_RC_FAIL) { - stall_reason = stall_cond; - bool iswrite = inst.is_store(); - if (inst.space.is_local()) - access_type = (iswrite) ? L_MEM_ST : L_MEM_LD; - else - access_type = (iswrite) ? G_MEM_ST : G_MEM_LD; - } - return inst.accessq_empty(); + bool bypassL1D = false; + if ( CACHE_GLOBAL == inst.cache_op || (m_L1D == NULL) ) { + bypassL1D = true; + } else if (inst.space.is_global()) { // global memory access + // skip L1 cache if the option is enabled + if (m_core->get_config()->gmem_skip_L1D && (CACHE_L1 != inst.cache_op)) + bypassL1D = true; + } + if( bypassL1D ) { + // bypass L1 cache + unsigned control_size = inst.is_store() ? WRITE_PACKET_SIZE : READ_PACKET_SIZE; + unsigned size = access.get_size() + control_size; + //printf("Interconnect:Addr: %x, size=%d\n",access.get_addr(),size); + if( m_icnt->full(size, inst.is_store() || inst.isatomic()) ) { + stall_cond = ICNT_RC_FAIL; + } else { + mem_fetch *mf = m_mf_allocator->alloc(inst,access,m_core->get_gpu()->gpu_sim_cycle+m_core->get_gpu()->gpu_tot_sim_cycle); + m_icnt->push(mf); + inst.accessq_pop_back(); + //inst.clear_active( access.get_warp_mask() ); + if( inst.is_load() ) { + for( unsigned r=0; r < MAX_OUTPUT_VALUES; r++) + if(inst.out[r] > 0) + assert( m_pending_writes[inst.warp_id()][inst.out[r]] > 0 ); + } else if( inst.is_store() ) + m_core->inc_store_req( inst.warp_id() ); + } + } else { + assert( CACHE_UNDEFINED != inst.cache_op ); + stall_cond = process_memory_access_queue_l1cache(m_L1D,inst); + } + if( !inst.accessq_empty() && stall_cond == NO_RC_FAIL) + stall_cond = COAL_STALL; + if (stall_cond != NO_RC_FAIL) { + stall_reason = stall_cond; + bool iswrite = inst.is_store(); + if (inst.space.is_local()) + access_type = (iswrite)?L_MEM_ST:L_MEM_LD; + else + access_type = (iswrite)?G_MEM_ST:G_MEM_LD; + } + return inst.accessq_empty(); } -bool ldst_unit::response_buffer_full() const { - return m_response_fifo.size() >= m_config->ldst_unit_response_queue_size; + +bool ldst_unit::response_buffer_full() const +{ + return m_response_fifo.size() >= m_config->ldst_unit_response_queue_size; } -void ldst_unit::fill(mem_fetch *mf) { - mf->set_status( - IN_SHADER_LDST_RESPONSE_FIFO, - m_core->get_gpu()->gpu_sim_cycle + m_core->get_gpu()->gpu_tot_sim_cycle); - m_response_fifo.push_back(mf); +void ldst_unit::fill( mem_fetch *mf ) +{ + mf->set_status(IN_SHADER_LDST_RESPONSE_FIFO,m_core->get_gpu()->gpu_sim_cycle+m_core->get_gpu()->gpu_tot_sim_cycle); + m_response_fifo.push_back(mf); } -void ldst_unit::flush() { - // Flush L1D cache - m_L1D->flush(); +void ldst_unit::flush(){ + // Flush L1D cache + m_L1D->flush(); } -void ldst_unit::invalidate() { - // Flush L1D cache - m_L1D->invalidate(); +void ldst_unit::invalidate(){ + // Flush L1D cache + m_L1D->invalidate(); } -simd_function_unit::simd_function_unit(const shader_core_config *config) { - m_config = config; - m_dispatch_reg = new warp_inst_t(config); +simd_function_unit::simd_function_unit( const shader_core_config *config ) +{ + m_config=config; + m_dispatch_reg = new warp_inst_t(config); } -sfu::sfu(register_set *result_port, const shader_core_config *config, - shader_core_ctx *core) - : pipelined_simd_unit(result_port, config, config->max_sfu_latency, core) { - m_name = "SFU"; + +sfu:: sfu( register_set* result_port, const shader_core_config *config,shader_core_ctx *core ) + : pipelined_simd_unit(result_port,config,config->max_sfu_latency,core) +{ + m_name = "SFU"; } -tensor_core::tensor_core(register_set *result_port, - const shader_core_config *config, - shader_core_ctx *core) - : pipelined_simd_unit(result_port, config, config->max_tensor_core_latency, - core) { - m_name = "TENSOR_CORE"; +tensor_core:: tensor_core( register_set* result_port, const shader_core_config *config,shader_core_ctx *core ) + : pipelined_simd_unit(result_port,config,config->max_tensor_core_latency,core) +{ + m_name = "TENSOR_CORE"; } -void sfu::issue(register_set &source_reg) { - warp_inst_t **ready_reg = source_reg.get_ready(); - // m_core->incexecstat((*ready_reg)); +void sfu::issue( register_set& source_reg ) +{ + warp_inst_t** ready_reg = source_reg.get_ready(); + //m_core->incexecstat((*ready_reg)); - (*ready_reg)->op_pipe = SFU__OP; - m_core->incsfu_stat(m_core->get_config()->warp_size, (*ready_reg)->latency); - pipelined_simd_unit::issue(source_reg); + (*ready_reg)->op_pipe=SFU__OP; + m_core->incsfu_stat(m_core->get_config()->warp_size,(*ready_reg)->latency); + pipelined_simd_unit::issue(source_reg); } -void tensor_core::issue(register_set &source_reg) { - warp_inst_t **ready_reg = source_reg.get_ready(); - // m_core->incexecstat((*ready_reg)); +void tensor_core::issue( register_set& source_reg ) +{ + warp_inst_t** ready_reg = source_reg.get_ready(); + //m_core->incexecstat((*ready_reg)); - (*ready_reg)->op_pipe = TENSOR_CORE__OP; - m_core->incsfu_stat(m_core->get_config()->warp_size, (*ready_reg)->latency); - pipelined_simd_unit::issue(source_reg); + (*ready_reg)->op_pipe= TENSOR_CORE__OP; + m_core->incsfu_stat(m_core->get_config()->warp_size,(*ready_reg)->latency); + pipelined_simd_unit::issue(source_reg); } -unsigned pipelined_simd_unit::get_active_lanes_in_pipeline() { - active_mask_t active_lanes; - active_lanes.reset(); - if (m_core->get_gpu()->get_config().g_power_simulation_enabled) { - for (unsigned stage = 0; (stage + 1) < m_pipeline_depth; stage++) { - if (!m_pipeline_reg[stage]->empty()) - active_lanes |= m_pipeline_reg[stage]->get_active_mask(); - } - } - return active_lanes.count(); +unsigned pipelined_simd_unit::get_active_lanes_in_pipeline(){ + active_mask_t active_lanes; + active_lanes.reset(); + if(m_core->get_gpu()->get_config().g_power_simulation_enabled){ + for( unsigned stage=0; (stage+1)<m_pipeline_depth; stage++ ){ + if( !m_pipeline_reg[stage]->empty() ) + active_lanes|=m_pipeline_reg[stage]->get_active_mask(); + } + } + return active_lanes.count(); } -void ldst_unit::active_lanes_in_pipeline() { - unsigned active_count = pipelined_simd_unit::get_active_lanes_in_pipeline(); - assert(active_count <= m_core->get_config()->warp_size); - m_core->incfumemactivelanes_stat(active_count); +void ldst_unit::active_lanes_in_pipeline(){ + unsigned active_count=pipelined_simd_unit::get_active_lanes_in_pipeline(); + assert(active_count<=m_core->get_config()->warp_size); + m_core->incfumemactivelanes_stat(active_count); } -void sp_unit::active_lanes_in_pipeline() { - unsigned active_count = pipelined_simd_unit::get_active_lanes_in_pipeline(); - assert(active_count <= m_core->get_config()->warp_size); - m_core->incspactivelanes_stat(active_count); - m_core->incfuactivelanes_stat(active_count); - m_core->incfumemactivelanes_stat(active_count); +void sp_unit::active_lanes_in_pipeline(){ + unsigned active_count=pipelined_simd_unit::get_active_lanes_in_pipeline(); + assert(active_count<=m_core->get_config()->warp_size); + m_core->incspactivelanes_stat(active_count); + m_core->incfuactivelanes_stat(active_count); + m_core->incfumemactivelanes_stat(active_count); } -void dp_unit::active_lanes_in_pipeline() { - unsigned active_count = pipelined_simd_unit::get_active_lanes_in_pipeline(); - assert(active_count <= m_core->get_config()->warp_size); - m_core->incspactivelanes_stat(active_count); - m_core->incfuactivelanes_stat(active_count); - m_core->incfumemactivelanes_stat(active_count); +void dp_unit::active_lanes_in_pipeline(){ + unsigned active_count=pipelined_simd_unit::get_active_lanes_in_pipeline(); + assert(active_count<=m_core->get_config()->warp_size); + m_core->incspactivelanes_stat(active_count); + m_core->incfuactivelanes_stat(active_count); + m_core->incfumemactivelanes_stat(active_count); } -void int_unit::active_lanes_in_pipeline() { - unsigned active_count = pipelined_simd_unit::get_active_lanes_in_pipeline(); - assert(active_count <= m_core->get_config()->warp_size); - m_core->incspactivelanes_stat(active_count); - m_core->incfuactivelanes_stat(active_count); - m_core->incfumemactivelanes_stat(active_count); +void int_unit::active_lanes_in_pipeline(){ + unsigned active_count=pipelined_simd_unit::get_active_lanes_in_pipeline(); + assert(active_count<=m_core->get_config()->warp_size); + m_core->incspactivelanes_stat(active_count); + m_core->incfuactivelanes_stat(active_count); + m_core->incfumemactivelanes_stat(active_count); } -void sfu::active_lanes_in_pipeline() { - unsigned active_count = pipelined_simd_unit::get_active_lanes_in_pipeline(); - assert(active_count <= m_core->get_config()->warp_size); - m_core->incsfuactivelanes_stat(active_count); - m_core->incfuactivelanes_stat(active_count); - m_core->incfumemactivelanes_stat(active_count); +void sfu::active_lanes_in_pipeline(){ + unsigned active_count=pipelined_simd_unit::get_active_lanes_in_pipeline(); + assert(active_count<=m_core->get_config()->warp_size); + m_core->incsfuactivelanes_stat(active_count); + m_core->incfuactivelanes_stat(active_count); + m_core->incfumemactivelanes_stat(active_count); } -void tensor_core::active_lanes_in_pipeline() { - unsigned active_count = pipelined_simd_unit::get_active_lanes_in_pipeline(); - assert(active_count <= m_core->get_config()->warp_size); - m_core->incsfuactivelanes_stat(active_count); - m_core->incfuactivelanes_stat(active_count); - m_core->incfumemactivelanes_stat(active_count); +void tensor_core::active_lanes_in_pipeline(){ + unsigned active_count=pipelined_simd_unit::get_active_lanes_in_pipeline(); + assert(active_count<=m_core->get_config()->warp_size); + m_core->incsfuactivelanes_stat(active_count); + m_core->incfuactivelanes_stat(active_count); + m_core->incfumemactivelanes_stat(active_count); } -sp_unit::sp_unit(register_set *result_port, const shader_core_config *config, - shader_core_ctx *core) - : pipelined_simd_unit(result_port, config, config->max_sp_latency, core) { - m_name = "SP "; + +sp_unit::sp_unit( register_set* result_port, const shader_core_config *config,shader_core_ctx *core) + : pipelined_simd_unit(result_port,config,config->max_sp_latency,core) +{ + m_name = "SP "; } -dp_unit::dp_unit(register_set *result_port, const shader_core_config *config, - shader_core_ctx *core) - : pipelined_simd_unit(result_port, config, config->max_dp_latency, core) { - m_name = "DP "; +dp_unit::dp_unit( register_set* result_port, const shader_core_config *config,shader_core_ctx *core) + : pipelined_simd_unit(result_port,config,config->max_dp_latency,core) +{ + m_name = "DP "; } -int_unit::int_unit(register_set *result_port, const shader_core_config *config, - shader_core_ctx *core) - : pipelined_simd_unit(result_port, config, config->max_int_latency, core) { - m_name = "INT "; +int_unit::int_unit( register_set* result_port, const shader_core_config *config,shader_core_ctx *core) + : pipelined_simd_unit(result_port,config,config->max_int_latency,core) +{ + m_name = "INT "; } -void sp_unit::issue(register_set &source_reg) { - warp_inst_t **ready_reg = source_reg.get_ready(); - // m_core->incexecstat((*ready_reg)); - (*ready_reg)->op_pipe = SP__OP; - m_core->incsp_stat(m_core->get_config()->warp_size, (*ready_reg)->latency); - pipelined_simd_unit::issue(source_reg); +void sp_unit :: issue(register_set& source_reg) +{ + warp_inst_t** ready_reg = source_reg.get_ready(); + //m_core->incexecstat((*ready_reg)); + (*ready_reg)->op_pipe=SP__OP; + m_core->incsp_stat(m_core->get_config()->warp_size,(*ready_reg)->latency); + pipelined_simd_unit::issue(source_reg); } -void dp_unit::issue(register_set &source_reg) { - warp_inst_t **ready_reg = source_reg.get_ready(); - // m_core->incexecstat((*ready_reg)); - (*ready_reg)->op_pipe = DP__OP; - m_core->incsp_stat(m_core->get_config()->warp_size, (*ready_reg)->latency); - pipelined_simd_unit::issue(source_reg); +void dp_unit :: issue(register_set& source_reg) +{ + warp_inst_t** ready_reg = source_reg.get_ready(); + //m_core->incexecstat((*ready_reg)); + (*ready_reg)->op_pipe=DP__OP; + m_core->incsp_stat(m_core->get_config()->warp_size,(*ready_reg)->latency); + pipelined_simd_unit::issue(source_reg); } -void int_unit::issue(register_set &source_reg) { - warp_inst_t **ready_reg = source_reg.get_ready(); - // m_core->incexecstat((*ready_reg)); - (*ready_reg)->op_pipe = INTP__OP; - m_core->incsp_stat(m_core->get_config()->warp_size, (*ready_reg)->latency); - pipelined_simd_unit::issue(source_reg); +void int_unit :: issue(register_set& source_reg) +{ + warp_inst_t** ready_reg = source_reg.get_ready(); + //m_core->incexecstat((*ready_reg)); + (*ready_reg)->op_pipe=INTP__OP; + m_core->incsp_stat(m_core->get_config()->warp_size,(*ready_reg)->latency); + pipelined_simd_unit::issue(source_reg); } -pipelined_simd_unit::pipelined_simd_unit(register_set *result_port, - const shader_core_config *config, - unsigned max_latency, - shader_core_ctx *core) - : simd_function_unit(config) { - m_result_port = result_port; - m_pipeline_depth = max_latency; - m_pipeline_reg = new warp_inst_t *[m_pipeline_depth]; - for (unsigned i = 0; i < m_pipeline_depth; i++) - m_pipeline_reg[i] = new warp_inst_t(config); - m_core = core; - active_insts_in_pipeline = 0; +pipelined_simd_unit::pipelined_simd_unit( register_set* result_port, const shader_core_config *config, unsigned max_latency,shader_core_ctx *core ) + : simd_function_unit(config) +{ + m_result_port = result_port; + m_pipeline_depth = max_latency; + m_pipeline_reg = new warp_inst_t*[m_pipeline_depth]; + for( unsigned i=0; i < m_pipeline_depth; i++ ) + m_pipeline_reg[i] = new warp_inst_t( config ); + m_core=core; + active_insts_in_pipeline=0; } -void pipelined_simd_unit::cycle() { - if (!m_pipeline_reg[0]->empty()) { - m_result_port->move_in(m_pipeline_reg[0]); - assert(active_insts_in_pipeline > 0); - active_insts_in_pipeline--; - } - if (active_insts_in_pipeline) { - for (unsigned stage = 0; (stage + 1) < m_pipeline_depth; stage++) - move_warp(m_pipeline_reg[stage], m_pipeline_reg[stage + 1]); - } - if (!m_dispatch_reg->empty()) { - if (!m_dispatch_reg->dispatch_delay()) { - int start_stage = - m_dispatch_reg->latency - m_dispatch_reg->initiation_interval; - move_warp(m_pipeline_reg[start_stage], m_dispatch_reg); - active_insts_in_pipeline++; +void pipelined_simd_unit::cycle() +{ + if( !m_pipeline_reg[0]->empty() ){ + m_result_port->move_in(m_pipeline_reg[0]); + assert(active_insts_in_pipeline > 0); + active_insts_in_pipeline--; } - } - occupied >>= 1; + if(active_insts_in_pipeline){ + for( unsigned stage=0; (stage+1)<m_pipeline_depth; stage++ ) + move_warp(m_pipeline_reg[stage], m_pipeline_reg[stage+1]); + } + if( !m_dispatch_reg->empty() ) { + if( !m_dispatch_reg->dispatch_delay()){ + int start_stage = m_dispatch_reg->latency - m_dispatch_reg->initiation_interval; + move_warp(m_pipeline_reg[start_stage],m_dispatch_reg); + active_insts_in_pipeline++; + } + } + occupied >>=1; } -void pipelined_simd_unit::issue(register_set &source_reg) { - // move_warp(m_dispatch_reg,source_reg); - warp_inst_t **ready_reg = source_reg.get_ready(); - m_core->incexecstat((*ready_reg)); - // source_reg.move_out_to(m_dispatch_reg); - simd_function_unit::issue(source_reg); + +void pipelined_simd_unit::issue( register_set& source_reg ) +{ + //move_warp(m_dispatch_reg,source_reg); + warp_inst_t** ready_reg = source_reg.get_ready(); + m_core->incexecstat((*ready_reg)); + //source_reg.move_out_to(m_dispatch_reg); + simd_function_unit::issue(source_reg); } /* @@ -2170,230 +2073,253 @@ void pipelined_simd_unit::issue(register_set &source_reg) { } */ -void ldst_unit::init(mem_fetch_interface *icnt, - shader_core_mem_fetch_allocator *mf_allocator, - shader_core_ctx *core, opndcoll_rfu_t *operand_collector, - Scoreboard *scoreboard, const shader_core_config *config, - const memory_config *mem_config, shader_core_stats *stats, - unsigned sid, unsigned tpc) { - m_memory_config = mem_config; - m_icnt = icnt; - m_mf_allocator = mf_allocator; - m_core = core; - m_operand_collector = operand_collector; - m_scoreboard = scoreboard; - m_stats = stats; - m_sid = sid; - m_tpc = tpc; -#define STRSIZE 1024 - char L1T_name[STRSIZE]; - char L1C_name[STRSIZE]; - snprintf(L1T_name, STRSIZE, "L1T_%03d", m_sid); - snprintf(L1C_name, STRSIZE, "L1C_%03d", m_sid); - m_L1T = new tex_cache(L1T_name, m_config->m_L1T_config, m_sid, - get_shader_texture_cache_id(), icnt, IN_L1T_MISS_QUEUE, - IN_SHADER_L1T_ROB); - m_L1C = new read_only_cache(L1C_name, m_config->m_L1C_config, m_sid, - get_shader_constant_cache_id(), icnt, - IN_L1C_MISS_QUEUE); - m_L1D = NULL; - m_mem_rc = NO_RC_FAIL; - m_num_writeback_clients = - 5; // = shared memory, global/local (uncached), L1D, L1T, L1C - m_writeback_arb = 0; - m_next_global = NULL; - m_last_inst_gpu_sim_cycle = 0; - m_last_inst_gpu_tot_sim_cycle = 0; +void ldst_unit::init( mem_fetch_interface *icnt, + shader_core_mem_fetch_allocator *mf_allocator, + shader_core_ctx *core, + opndcoll_rfu_t *operand_collector, + Scoreboard *scoreboard, + const shader_core_config *config, + const memory_config *mem_config, + shader_core_stats *stats, + unsigned sid, + unsigned tpc ) +{ + m_memory_config = mem_config; + m_icnt = icnt; + m_mf_allocator=mf_allocator; + m_core = core; + m_operand_collector = operand_collector; + m_scoreboard = scoreboard; + m_stats = stats; + m_sid = sid; + m_tpc = tpc; + #define STRSIZE 1024 + char L1T_name[STRSIZE]; + char L1C_name[STRSIZE]; + snprintf(L1T_name, STRSIZE, "L1T_%03d", m_sid); + snprintf(L1C_name, STRSIZE, "L1C_%03d", m_sid); + m_L1T = new tex_cache(L1T_name,m_config->m_L1T_config,m_sid,get_shader_texture_cache_id(),icnt,IN_L1T_MISS_QUEUE,IN_SHADER_L1T_ROB); + m_L1C = new read_only_cache(L1C_name,m_config->m_L1C_config,m_sid,get_shader_constant_cache_id(),icnt,IN_L1C_MISS_QUEUE); + m_L1D = NULL; + m_mem_rc = NO_RC_FAIL; + m_num_writeback_clients=5; // = shared memory, global/local (uncached), L1D, L1T, L1C + m_writeback_arb = 0; + m_next_global=NULL; + m_last_inst_gpu_sim_cycle=0; + m_last_inst_gpu_tot_sim_cycle=0; } -ldst_unit::ldst_unit(mem_fetch_interface *icnt, - shader_core_mem_fetch_allocator *mf_allocator, - shader_core_ctx *core, opndcoll_rfu_t *operand_collector, - Scoreboard *scoreboard, const shader_core_config *config, - const memory_config *mem_config, shader_core_stats *stats, - unsigned sid, unsigned tpc) - : pipelined_simd_unit(NULL, config, config->smem_latency, core), - m_next_wb(config) { - assert(config->smem_latency > 1); - init(icnt, mf_allocator, core, operand_collector, scoreboard, config, - mem_config, stats, sid, tpc); - if (!m_config->m_L1D_config.disabled()) { - char L1D_name[STRSIZE]; - snprintf(L1D_name, STRSIZE, "L1D_%03d", m_sid); - m_L1D = new l1_cache(L1D_name, m_config->m_L1D_config, m_sid, - get_shader_normal_cache_id(), m_icnt, m_mf_allocator, - IN_L1D_MISS_QUEUE, core->get_gpu()); - l1_latency_queue.resize(m_config->m_L1D_config.l1_banks); - assert(m_config->m_L1D_config.l1_latency > 0); +ldst_unit::ldst_unit( mem_fetch_interface *icnt, + shader_core_mem_fetch_allocator *mf_allocator, + shader_core_ctx *core, + opndcoll_rfu_t *operand_collector, + Scoreboard *scoreboard, + const shader_core_config *config, + const memory_config *mem_config, + shader_core_stats *stats, + unsigned sid, + unsigned tpc ) : pipelined_simd_unit(NULL,config,config->smem_latency,core), m_next_wb(config) +{ + assert(config->smem_latency > 1); + init( icnt, + mf_allocator, + core, + operand_collector, + scoreboard, + config, + mem_config, + stats, + sid, + tpc ); + if( !m_config->m_L1D_config.disabled() ) { + char L1D_name[STRSIZE]; + snprintf(L1D_name, STRSIZE, "L1D_%03d", m_sid); + m_L1D = new l1_cache( L1D_name, + m_config->m_L1D_config, + m_sid, + get_shader_normal_cache_id(), + m_icnt, + m_mf_allocator, + IN_L1D_MISS_QUEUE, + core->get_gpu()); - for (unsigned j = 0; j < m_config->m_L1D_config.l1_banks; j++) - l1_latency_queue[j].resize(m_config->m_L1D_config.l1_latency, - (mem_fetch *)NULL); - } - m_name = "MEM "; + l1_latency_queue.resize(m_config->m_L1D_config.l1_banks); + assert(m_config->m_L1D_config.l1_latency > 0); + + for(unsigned j = 0; j < m_config->m_L1D_config.l1_banks; j++ ) + l1_latency_queue[j].resize(m_config->m_L1D_config.l1_latency,(mem_fetch*)NULL); + + } + m_name = "MEM "; } -ldst_unit::ldst_unit(mem_fetch_interface *icnt, - shader_core_mem_fetch_allocator *mf_allocator, - shader_core_ctx *core, opndcoll_rfu_t *operand_collector, - Scoreboard *scoreboard, const shader_core_config *config, - const memory_config *mem_config, shader_core_stats *stats, - unsigned sid, unsigned tpc, l1_cache *new_l1d_cache) - : pipelined_simd_unit(NULL, config, 3, core), - m_L1D(new_l1d_cache), - m_next_wb(config) { - init(icnt, mf_allocator, core, operand_collector, scoreboard, config, - mem_config, stats, sid, tpc); +ldst_unit::ldst_unit( mem_fetch_interface *icnt, + shader_core_mem_fetch_allocator *mf_allocator, + shader_core_ctx *core, + opndcoll_rfu_t *operand_collector, + Scoreboard *scoreboard, + const shader_core_config *config, + const memory_config *mem_config, + shader_core_stats *stats, + unsigned sid, + unsigned tpc, + l1_cache* new_l1d_cache ) + : pipelined_simd_unit(NULL,config,3,core), m_L1D(new_l1d_cache), m_next_wb(config) +{ + init( icnt, + mf_allocator, + core, + operand_collector, + scoreboard, + config, + mem_config, + stats, + sid, + tpc ); } -void ldst_unit::issue(register_set ®_set) { - warp_inst_t *inst = *(reg_set.get_ready()); +void ldst_unit:: issue( register_set ®_set ) +{ + warp_inst_t* inst = *(reg_set.get_ready()); - // record how many pending register writes/memory accesses there are for this - // instruction - assert(inst->empty() == false); - if (inst->is_load() and inst->space.get_type() != shared_space) { - unsigned warp_id = inst->warp_id(); - unsigned n_accesses = inst->accessq_count(); - for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) { - unsigned reg_id = inst->out[r]; - if (reg_id > 0) { - m_pending_writes[warp_id][reg_id] += n_accesses; + // record how many pending register writes/memory accesses there are for this instruction + assert(inst->empty() == false); + if (inst->is_load() and inst->space.get_type() != shared_space) { + unsigned warp_id = inst->warp_id(); + unsigned n_accesses = inst->accessq_count(); + for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) { + unsigned reg_id = inst->out[r]; + if (reg_id > 0) { + m_pending_writes[warp_id][reg_id] += n_accesses; + } } - } - } + } + - inst->op_pipe = MEM__OP; - // stat collection - m_core->mem_instruction_stats(*inst); - m_core->incmem_stat(m_core->get_config()->warp_size, 1); - pipelined_simd_unit::issue(reg_set); + inst->op_pipe=MEM__OP; + // stat collection + m_core->mem_instruction_stats(*inst); + m_core->incmem_stat(m_core->get_config()->warp_size,1); + pipelined_simd_unit::issue(reg_set); } -void ldst_unit::writeback() { - // process next instruction that is going to writeback - if (!m_next_wb.empty()) { - if (m_operand_collector->writeback(m_next_wb)) { - bool insn_completed = false; - for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) { - if (m_next_wb.out[r] > 0) { - if (m_next_wb.space.get_type() != shared_space) { - assert(m_pending_writes[m_next_wb.warp_id()][m_next_wb.out[r]] > 0); - unsigned still_pending = - --m_pending_writes[m_next_wb.warp_id()][m_next_wb.out[r]]; - if (!still_pending) { - m_pending_writes[m_next_wb.warp_id()].erase(m_next_wb.out[r]); - m_scoreboard->releaseRegister(m_next_wb.warp_id(), - m_next_wb.out[r]); - insn_completed = true; +void ldst_unit::writeback() +{ + // process next instruction that is going to writeback + if( !m_next_wb.empty() ) { + if( m_operand_collector->writeback(m_next_wb) ) { + bool insn_completed = false; + for( unsigned r=0; r < MAX_OUTPUT_VALUES; r++ ) { + if( m_next_wb.out[r] > 0 ) { + if( m_next_wb.space.get_type() != shared_space ) { + assert( m_pending_writes[m_next_wb.warp_id()][m_next_wb.out[r]] > 0 ); + unsigned still_pending = --m_pending_writes[m_next_wb.warp_id()][m_next_wb.out[r]]; + if( !still_pending ) { + m_pending_writes[m_next_wb.warp_id()].erase(m_next_wb.out[r]); + m_scoreboard->releaseRegister( m_next_wb.warp_id(), m_next_wb.out[r] ); + insn_completed = true; + } + } else { // shared + m_scoreboard->releaseRegister( m_next_wb.warp_id(), m_next_wb.out[r] ); + insn_completed = true; + } + } } - } else { // shared - m_scoreboard->releaseRegister(m_next_wb.warp_id(), - m_next_wb.out[r]); - insn_completed = true; - } + if( insn_completed ) { + m_core->warp_inst_complete(m_next_wb); + } + m_next_wb.clear(); + m_last_inst_gpu_sim_cycle = m_core->get_gpu()->gpu_sim_cycle; + m_last_inst_gpu_tot_sim_cycle = m_core->get_gpu()->gpu_tot_sim_cycle; } - } - if (insn_completed) { - m_core->warp_inst_complete(m_next_wb); - } - m_next_wb.clear(); - m_last_inst_gpu_sim_cycle = m_core->get_gpu()->gpu_sim_cycle; - m_last_inst_gpu_tot_sim_cycle = m_core->get_gpu()->gpu_tot_sim_cycle; } - } - unsigned serviced_client = -1; - for (unsigned c = 0; m_next_wb.empty() && (c < m_num_writeback_clients); - c++) { - unsigned next_client = (c + m_writeback_arb) % m_num_writeback_clients; - switch (next_client) { - case 0: // shared memory - if (!m_pipeline_reg[0]->empty()) { - m_next_wb = *m_pipeline_reg[0]; - if (m_next_wb.isatomic()) { - m_next_wb.do_atomic(); - m_core->decrement_atomic_count(m_next_wb.warp_id(), - m_next_wb.active_count()); - } - m_core->dec_inst_in_pipeline(m_pipeline_reg[0]->warp_id()); - m_pipeline_reg[0]->clear(); - serviced_client = next_client; - } - break; - case 1: // texture response - if (m_L1T->access_ready()) { - mem_fetch *mf = m_L1T->next_access(); - m_next_wb = mf->get_inst(); - delete mf; - serviced_client = next_client; - } - break; - case 2: // const cache response - if (m_L1C->access_ready()) { - mem_fetch *mf = m_L1C->next_access(); - m_next_wb = mf->get_inst(); - delete mf; - serviced_client = next_client; - } - break; - case 3: // global/local - if (m_next_global) { - m_next_wb = m_next_global->get_inst(); - if (m_next_global->isatomic()) - m_core->decrement_atomic_count( - m_next_global->get_wid(), - m_next_global->get_access_warp_mask().count()); - delete m_next_global; - m_next_global = NULL; - serviced_client = next_client; - } - break; - case 4: - if (m_L1D && m_L1D->access_ready()) { - mem_fetch *mf = m_L1D->next_access(); - m_next_wb = mf->get_inst(); - delete mf; - serviced_client = next_client; + unsigned serviced_client = -1; + for( unsigned c = 0; m_next_wb.empty() && (c < m_num_writeback_clients); c++ ) { + unsigned next_client = (c+m_writeback_arb)%m_num_writeback_clients; + switch( next_client ) { + case 0: // shared memory + if( !m_pipeline_reg[0]->empty() ) { + m_next_wb = *m_pipeline_reg[0]; + if(m_next_wb.isatomic()) { + m_next_wb.do_atomic(); + m_core->decrement_atomic_count(m_next_wb.warp_id(), m_next_wb.active_count()); + } + m_core->dec_inst_in_pipeline(m_pipeline_reg[0]->warp_id()); + m_pipeline_reg[0]->clear(); + serviced_client = next_client; + } + break; + case 1: // texture response + if( m_L1T->access_ready() ) { + mem_fetch *mf = m_L1T->next_access(); + m_next_wb = mf->get_inst(); + delete mf; + serviced_client = next_client; + } + break; + case 2: // const cache response + if( m_L1C->access_ready() ) { + mem_fetch *mf = m_L1C->next_access(); + m_next_wb = mf->get_inst(); + delete mf; + serviced_client = next_client; + } + break; + case 3: // global/local + if( m_next_global ) { + m_next_wb = m_next_global->get_inst(); + if( m_next_global->isatomic() ) + m_core->decrement_atomic_count(m_next_global->get_wid(),m_next_global->get_access_warp_mask().count()); + delete m_next_global; + m_next_global = NULL; + serviced_client = next_client; + } + break; + case 4: + if( m_L1D && m_L1D->access_ready() ) { + mem_fetch *mf = m_L1D->next_access(); + m_next_wb = mf->get_inst(); + delete mf; + serviced_client = next_client; + } + break; + default: abort(); } - break; - default: - abort(); } - } - // update arbitration priority only if: - // 1. the writeback buffer was available - // 2. a client was serviced - if (serviced_client != (unsigned)-1) { - m_writeback_arb = (serviced_client + 1) % m_num_writeback_clients; - } + // update arbitration priority only if: + // 1. the writeback buffer was available + // 2. a client was serviced + if (serviced_client != (unsigned)-1) { + m_writeback_arb = (serviced_client + 1) % m_num_writeback_clients; + } } -unsigned ldst_unit::clock_multiplier() const { - // to model multiple read port, we give multiple cycles for the memory units - if (m_config->mem_unit_ports) - return m_config->mem_unit_ports; - else - return m_config->mem_warp_parts; +unsigned ldst_unit::clock_multiplier() const +{ + //to model multiple read port, we give multiple cycles for the memory units + if(m_config->mem_unit_ports) + return m_config->mem_unit_ports; + else + return m_config->mem_warp_parts; } /* void ldst_unit::issue( register_set ®_set ) { - warp_inst_t* inst = *(reg_set.get_ready()); + warp_inst_t* inst = *(reg_set.get_ready()); // stat collection - m_core->mem_instruction_stats(*inst); + m_core->mem_instruction_stats(*inst); - // record how many pending register writes/memory accesses there are for this -instruction - assert(inst->empty() == false); + // record how many pending register writes/memory accesses there are for this instruction + assert(inst->empty() == false); if (inst->is_load() and inst->space.get_type() != shared_space) { - unsigned warp_id = inst->warp_id(); - unsigned n_accesses = inst->accessq_count(); + unsigned warp_id = inst->warp_id(); + unsigned n_accesses = inst->accessq_count(); for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) { - unsigned reg_id = inst->out[r]; + unsigned reg_id = inst->out[r]; if (reg_id > 0) { - m_pending_writes[warp_id][reg_id] += n_accesses; + m_pending_writes[warp_id][reg_id] += n_accesses; } } } @@ -2401,1881 +2327,1820 @@ instruction pipelined_simd_unit::issue(reg_set); } */ -void ldst_unit::cycle() { - writeback(); - m_operand_collector->step(); - for (unsigned stage = 0; (stage + 1) < m_pipeline_depth; stage++) - if (m_pipeline_reg[stage]->empty() && !m_pipeline_reg[stage + 1]->empty()) - move_warp(m_pipeline_reg[stage], m_pipeline_reg[stage + 1]); +void ldst_unit::cycle() +{ + writeback(); + m_operand_collector->step(); + for( unsigned stage=0; (stage+1)<m_pipeline_depth; stage++ ) + if( m_pipeline_reg[stage]->empty() && !m_pipeline_reg[stage+1]->empty() ) + move_warp(m_pipeline_reg[stage], m_pipeline_reg[stage+1]); - if (!m_response_fifo.empty()) { - mem_fetch *mf = m_response_fifo.front(); - if (mf->get_access_type() == TEXTURE_ACC_R) { - if (m_L1T->fill_port_free()) { - m_L1T->fill(mf, m_core->get_gpu()->gpu_sim_cycle + - m_core->get_gpu()->gpu_tot_sim_cycle); - m_response_fifo.pop_front(); - } - } else if (mf->get_access_type() == CONST_ACC_R) { - if (m_L1C->fill_port_free()) { - mf->set_status(IN_SHADER_FETCHED, - m_core->get_gpu()->gpu_sim_cycle + - m_core->get_gpu()->gpu_tot_sim_cycle); - m_L1C->fill(mf, m_core->get_gpu()->gpu_sim_cycle + - m_core->get_gpu()->gpu_tot_sim_cycle); - m_response_fifo.pop_front(); - } - } else { - if (mf->get_type() == WRITE_ACK || - (m_config->gpgpu_perfect_mem && mf->get_is_write())) { - m_core->store_ack(mf); - m_response_fifo.pop_front(); - delete mf; - } else { - assert(!mf->get_is_write()); // L1 cache is write evict, allocate line - // on load miss only + if( !m_response_fifo.empty() ) { + mem_fetch *mf = m_response_fifo.front(); + if (mf->get_access_type() == TEXTURE_ACC_R) { + if (m_L1T->fill_port_free()) { + m_L1T->fill(mf,m_core->get_gpu()->gpu_sim_cycle+m_core->get_gpu()->gpu_tot_sim_cycle); + m_response_fifo.pop_front(); + } + } else if (mf->get_access_type() == CONST_ACC_R) { + if (m_L1C->fill_port_free()) { + mf->set_status(IN_SHADER_FETCHED,m_core->get_gpu()->gpu_sim_cycle+m_core->get_gpu()->gpu_tot_sim_cycle); + m_L1C->fill(mf,m_core->get_gpu()->gpu_sim_cycle+m_core->get_gpu()->gpu_tot_sim_cycle); + m_response_fifo.pop_front(); + } + } else { + if( mf->get_type() == WRITE_ACK || ( m_config->gpgpu_perfect_mem && mf->get_is_write() )) { + m_core->store_ack(mf); + m_response_fifo.pop_front(); + delete mf; + } else { + assert( !mf->get_is_write() ); // L1 cache is write evict, allocate line on load miss only - bool bypassL1D = false; - if (CACHE_GLOBAL == mf->get_inst().cache_op || (m_L1D == NULL)) { - bypassL1D = true; - } else if (mf->get_access_type() == GLOBAL_ACC_R || - mf->get_access_type() == - GLOBAL_ACC_W) { // global memory access - if (m_core->get_config()->gmem_skip_L1D) bypassL1D = true; - } - if (bypassL1D) { - if (m_next_global == NULL) { - mf->set_status(IN_SHADER_FETCHED, - m_core->get_gpu()->gpu_sim_cycle + - m_core->get_gpu()->gpu_tot_sim_cycle); - m_response_fifo.pop_front(); - m_next_global = mf; - } - } else { - if (m_L1D->fill_port_free()) { - m_L1D->fill(mf, m_core->get_gpu()->gpu_sim_cycle + - m_core->get_gpu()->gpu_tot_sim_cycle); - m_response_fifo.pop_front(); - } - } - } - } - } + bool bypassL1D = false; + if ( CACHE_GLOBAL == mf->get_inst().cache_op || (m_L1D == NULL) ) { + bypassL1D = true; + } else if (mf->get_access_type() == GLOBAL_ACC_R || mf->get_access_type() == GLOBAL_ACC_W) { // global memory access + if (m_core->get_config()->gmem_skip_L1D) + bypassL1D = true; + } + if( bypassL1D ) { + if ( m_next_global == NULL ) { + mf->set_status(IN_SHADER_FETCHED,m_core->get_gpu()->gpu_sim_cycle+m_core->get_gpu()->gpu_tot_sim_cycle); + m_response_fifo.pop_front(); + m_next_global = mf; + } + } else { + if (m_L1D->fill_port_free()) { + m_L1D->fill(mf,m_core->get_gpu()->gpu_sim_cycle+m_core->get_gpu()->gpu_tot_sim_cycle); + m_response_fifo.pop_front(); + } + } + } + } + } - m_L1T->cycle(); - m_L1C->cycle(); - if (m_L1D) { - m_L1D->cycle(); - if (m_config->m_L1D_config.l1_latency > 0) L1_latency_queue_cycle(); - } + m_L1T->cycle(); + m_L1C->cycle(); + if( m_L1D ) { + m_L1D->cycle(); + if(m_config->m_L1D_config.l1_latency > 0) + L1_latency_queue_cycle(); + } - warp_inst_t &pipe_reg = *m_dispatch_reg; - enum mem_stage_stall_type rc_fail = NO_RC_FAIL; - mem_stage_access_type type; - bool done = true; - done &= shared_cycle(pipe_reg, rc_fail, type); - done &= constant_cycle(pipe_reg, rc_fail, type); - done &= texture_cycle(pipe_reg, rc_fail, type); - done &= memory_cycle(pipe_reg, rc_fail, type); - m_mem_rc = rc_fail; + warp_inst_t &pipe_reg = *m_dispatch_reg; + enum mem_stage_stall_type rc_fail = NO_RC_FAIL; + mem_stage_access_type type; + bool done = true; + done &= shared_cycle(pipe_reg, rc_fail, type); + done &= constant_cycle(pipe_reg, rc_fail, type); + done &= texture_cycle(pipe_reg, rc_fail, type); + done &= memory_cycle(pipe_reg, rc_fail, type); + m_mem_rc = rc_fail; - if (!done) { // log stall types and return - assert(rc_fail != NO_RC_FAIL); - m_stats->gpgpu_n_stall_shd_mem++; - m_stats->gpu_stall_shd_mem_breakdown[type][rc_fail]++; - return; - } + if (!done) { // log stall types and return + assert(rc_fail != NO_RC_FAIL); + m_stats->gpgpu_n_stall_shd_mem++; + m_stats->gpu_stall_shd_mem_breakdown[type][rc_fail]++; + return; + } - if (!pipe_reg.empty()) { - unsigned warp_id = pipe_reg.warp_id(); - if (pipe_reg.is_load()) { - if (pipe_reg.space.get_type() == shared_space) { - if (m_pipeline_reg[m_config->smem_latency - 1]->empty()) { - // new shared memory request - move_warp(m_pipeline_reg[m_config->smem_latency - 1], m_dispatch_reg); - m_dispatch_reg->clear(); - } - } else { - // if( pipe_reg.active_count() > 0 ) { - // if( !m_operand_collector->writeback(pipe_reg) ) - // return; - //} + if( !pipe_reg.empty() ) { + unsigned warp_id = pipe_reg.warp_id(); + if( pipe_reg.is_load() ) { + if( pipe_reg.space.get_type() == shared_space ) { + if( m_pipeline_reg[m_config->smem_latency-1]->empty() ) { + // new shared memory request + move_warp(m_pipeline_reg[m_config->smem_latency-1],m_dispatch_reg); + m_dispatch_reg->clear(); + } + } else { + //if( pipe_reg.active_count() > 0 ) { + // if( !m_operand_collector->writeback(pipe_reg) ) + // return; + //} - bool pending_requests = false; - for (unsigned r = 0; r < MAX_OUTPUT_VALUES; r++) { - unsigned reg_id = pipe_reg.out[r]; - if (reg_id > 0) { - if (m_pending_writes[warp_id].find(reg_id) != - m_pending_writes[warp_id].end()) { - if (m_pending_writes[warp_id][reg_id] > 0) { - pending_requests = true; - break; - } else { - // this instruction is done already - m_pending_writes[warp_id].erase(reg_id); - } - } - } - } - if (!pending_requests) { - m_core->warp_inst_complete(*m_dispatch_reg); - m_scoreboard->releaseRegisters(m_dispatch_reg); - } - m_core->dec_inst_in_pipeline(warp_id); - m_dispatch_reg->clear(); - } - } else { - // stores exit pipeline here - m_core->dec_inst_in_pipeline(warp_id); - m_core->warp_inst_complete(*m_dispatch_reg); - m_dispatch_reg->clear(); - } - } + bool pending_requests=false; + for( unsigned r=0; r<MAX_OUTPUT_VALUES; r++ ) { + unsigned reg_id = pipe_reg.out[r]; + if( reg_id > 0 ) { + if( m_pending_writes[warp_id].find(reg_id) != m_pending_writes[warp_id].end() ) { + if ( m_pending_writes[warp_id][reg_id] > 0 ) { + pending_requests=true; + break; + } else { + // this instruction is done already + m_pending_writes[warp_id].erase(reg_id); + } + } + } + } + if( !pending_requests ) { + m_core->warp_inst_complete(*m_dispatch_reg); + m_scoreboard->releaseRegisters(m_dispatch_reg); + } + m_core->dec_inst_in_pipeline(warp_id); + m_dispatch_reg->clear(); + } + } else { + // stores exit pipeline here + m_core->dec_inst_in_pipeline(warp_id); + m_core->warp_inst_complete(*m_dispatch_reg); + m_dispatch_reg->clear(); + } + } } -void shader_core_ctx::register_cta_thread_exit(unsigned cta_num, - kernel_info_t *kernel) { - assert(m_cta_status[cta_num] > 0); - m_cta_status[cta_num]--; - if (!m_cta_status[cta_num]) { - m_n_active_cta--; - m_barriers.deallocate_barrier(cta_num); - shader_CTA_count_unlog(m_sid, 1); +void shader_core_ctx::register_cta_thread_exit( unsigned cta_num, kernel_info_t * kernel) +{ + assert( m_cta_status[cta_num] > 0 ); + m_cta_status[cta_num]--; + if (!m_cta_status[cta_num]) { + m_n_active_cta--; + m_barriers.deallocate_barrier(cta_num); + shader_CTA_count_unlog(m_sid, 1); - SHADER_DPRINTF( - LIVENESS, - "GPGPU-Sim uArch: Finished CTA #%u (%lld,%lld), %u CTAs running\n", - cta_num, m_gpu->gpu_sim_cycle, m_gpu->gpu_tot_sim_cycle, - m_n_active_cta); + SHADER_DPRINTF(LIVENESS, "GPGPU-Sim uArch: Finished CTA #%u (%lld,%lld), %u CTAs running\n", + cta_num, m_gpu->gpu_sim_cycle, m_gpu->gpu_tot_sim_cycle, m_n_active_cta); - if (m_n_active_cta == 0) { - SHADER_DPRINTF( - LIVENESS, - "GPGPU-Sim uArch: Empty (last released kernel %u \'%s\').\n", - kernel->get_uid(), kernel->name().c_str()); - fflush(stdout); + if( m_n_active_cta == 0 ) { + SHADER_DPRINTF(LIVENESS, "GPGPU-Sim uArch: Empty (last released kernel %u \'%s\').\n", + kernel->get_uid(), kernel->name().c_str()); + fflush(stdout); - // Shader can only be empty when no more cta are dispatched - if (kernel != m_kernel) { - assert(m_kernel == NULL || !m_gpu->kernel_more_cta_left(m_kernel)); + //Shader can only be empty when no more cta are dispatched + if(kernel != m_kernel) { + assert(m_kernel == NULL || !m_gpu->kernel_more_cta_left(m_kernel)); + } + m_kernel = NULL; } - m_kernel = NULL; - } - // Jin: for concurrent kernels on sm - release_shader_resource_1block(cta_num, *kernel); - kernel->dec_running(); - if (!m_gpu->kernel_more_cta_left(kernel)) { - if (!kernel->running()) { - SHADER_DPRINTF(LIVENESS, - "GPGPU-Sim uArch: GPU detected kernel %u \'%s\' " - "finished on shader %u.\n", - kernel->get_uid(), kernel->name().c_str(), m_sid); + //Jin: for concurrent kernels on sm + release_shader_resource_1block(cta_num, *kernel); + kernel->dec_running(); + if( !m_gpu->kernel_more_cta_left(kernel) ) { + if( !kernel->running() ) { + SHADER_DPRINTF(LIVENESS, + "GPGPU-Sim uArch: GPU detected kernel %u \'%s\' finished on shader %u.\n", kernel->get_uid(), + kernel->name().c_str(), m_sid); - if (m_kernel == kernel) m_kernel = NULL; - m_gpu->set_kernel_done(kernel); + if(m_kernel == kernel) + m_kernel = NULL; + m_gpu->set_kernel_done( kernel ); + } } - } - } -} - -void gpgpu_sim::shader_print_runtime_stat(FILE *fout) { - /* - fprintf(fout, "SHD_INSN: "); - for (unsigned i=0;i<m_n_shader;i++) - fprintf(fout, "%u ",m_sc[i]->get_num_sim_insn()); - fprintf(fout, "\n"); - fprintf(fout, "SHD_THDS: "); - for (unsigned i=0;i<m_n_shader;i++) - fprintf(fout, "%u ",m_sc[i]->get_not_completed()); - fprintf(fout, "\n"); - fprintf(fout, "SHD_DIVG: "); - for (unsigned i=0;i<m_n_shader;i++) - fprintf(fout, "%u ",m_sc[i]->get_n_diverge()); - fprintf(fout, "\n"); - fprintf(fout, "THD_INSN: "); - for (unsigned i=0; i<m_shader_config->n_thread_per_shader; i++) - fprintf(fout, "%d ", m_sc[0]->get_thread_n_insn(i) ); - fprintf(fout, "\n"); - */ + } } -void gpgpu_sim::shader_print_scheduler_stat(FILE *fout, - bool print_dynamic_info) const { - // Print out the stats from the sampling shader core - const unsigned scheduler_sampling_core = - m_shader_config->gpgpu_warp_issue_shader; -#define STR_SIZE 55 - char name_buff[STR_SIZE]; - name_buff[STR_SIZE - 1] = '\0'; - const std::vector<unsigned> &distro = - print_dynamic_info - ? m_shader_stats->get_dynamic_warp_issue()[scheduler_sampling_core] - : m_shader_stats->get_warp_slot_issue()[scheduler_sampling_core]; - if (print_dynamic_info) { - snprintf(name_buff, STR_SIZE - 1, "dynamic_warp_id"); - } else { - snprintf(name_buff, STR_SIZE - 1, "warp_id"); - } - fprintf(fout, "Shader %d %s issue ditsribution:\n", scheduler_sampling_core, - name_buff); - const unsigned num_warp_ids = distro.size(); - // First print out the warp ids - fprintf(fout, "%s:\n", name_buff); - for (unsigned warp_id = 0; warp_id < num_warp_ids; ++warp_id) { - fprintf(fout, "%d, ", warp_id); - } +void gpgpu_sim::shader_print_runtime_stat( FILE *fout ) +{ + /* + fprintf(fout, "SHD_INSN: "); + for (unsigned i=0;i<m_n_shader;i++) + fprintf(fout, "%u ",m_sc[i]->get_num_sim_insn()); + fprintf(fout, "\n"); + fprintf(fout, "SHD_THDS: "); + for (unsigned i=0;i<m_n_shader;i++) + fprintf(fout, "%u ",m_sc[i]->get_not_completed()); + fprintf(fout, "\n"); + fprintf(fout, "SHD_DIVG: "); + for (unsigned i=0;i<m_n_shader;i++) + fprintf(fout, "%u ",m_sc[i]->get_n_diverge()); + fprintf(fout, "\n"); - fprintf(fout, "\ndistro:\n"); - // Then print out the distribution of instuctions issued - for (std::vector<unsigned>::const_iterator iter = distro.begin(); - iter != distro.end(); iter++) { - fprintf(fout, "%d, ", *iter); - } - fprintf(fout, "\n"); + fprintf(fout, "THD_INSN: "); + for (unsigned i=0; i<m_shader_config->n_thread_per_shader; i++) + fprintf(fout, "%d ", m_sc[0]->get_thread_n_insn(i) ); + fprintf(fout, "\n"); + */ } -void gpgpu_sim::shader_print_cache_stats(FILE *fout) const { - // L1I - struct cache_sub_stats total_css; - struct cache_sub_stats css; - if (!m_shader_config->m_L1I_config.disabled()) { - total_css.clear(); - css.clear(); - fprintf(fout, "\n========= Core cache stats =========\n"); - fprintf(fout, "L1I_cache:\n"); - for (unsigned i = 0; i < m_shader_config->n_simt_clusters; ++i) { - m_cluster[i]->get_L1I_sub_stats(css); - total_css += css; +void gpgpu_sim::shader_print_scheduler_stat( FILE* fout, bool print_dynamic_info ) const +{ + // Print out the stats from the sampling shader core + const unsigned scheduler_sampling_core = m_shader_config->gpgpu_warp_issue_shader; + #define STR_SIZE 55 + char name_buff[ STR_SIZE ]; + name_buff[ STR_SIZE - 1 ] = '\0'; + const std::vector< unsigned >& distro + = print_dynamic_info ? + m_shader_stats->get_dynamic_warp_issue()[ scheduler_sampling_core ] : + m_shader_stats->get_warp_slot_issue()[ scheduler_sampling_core ]; + if ( print_dynamic_info ) { + snprintf( name_buff, STR_SIZE - 1, "dynamic_warp_id" ); + } else { + snprintf( name_buff, STR_SIZE - 1, "warp_id" ); } - fprintf(fout, "\tL1I_total_cache_accesses = %llu\n", total_css.accesses); - fprintf(fout, "\tL1I_total_cache_misses = %llu\n", total_css.misses); - if (total_css.accesses > 0) { - fprintf(fout, "\tL1I_total_cache_miss_rate = %.4lf\n", - (double)total_css.misses / (double)total_css.accesses); + fprintf( fout, + "Shader %d %s issue ditsribution:\n", + scheduler_sampling_core, + name_buff ); + const unsigned num_warp_ids = distro.size(); + // First print out the warp ids + fprintf( fout, "%s:\n", name_buff ); + for ( unsigned warp_id = 0; + warp_id < num_warp_ids; + ++warp_id ) { + fprintf( fout, "%d, ", warp_id ); } - fprintf(fout, "\tL1I_total_cache_pending_hits = %llu\n", - total_css.pending_hits); - fprintf(fout, "\tL1I_total_cache_reservation_fails = %llu\n", - total_css.res_fails); - } - // L1D - if (!m_shader_config->m_L1D_config.disabled()) { - total_css.clear(); - css.clear(); - fprintf(fout, "L1D_cache:\n"); - for (unsigned i = 0; i < m_shader_config->n_simt_clusters; i++) { - m_cluster[i]->get_L1D_sub_stats(css); + fprintf( fout, "\ndistro:\n" ); + // Then print out the distribution of instuctions issued + for ( std::vector< unsigned >::const_iterator iter = distro.begin(); + iter != distro.end(); + iter++ ) { + fprintf( fout, "%d, ", *iter ); + } + fprintf( fout, "\n" ); +} - fprintf(stdout, - "\tL1D_cache_core[%d]: Access = %llu, Miss = %llu, Miss_rate = " - "%.3lf, Pending_hits = %llu, Reservation_fails = %llu\n", - i, css.accesses, css.misses, - (double)css.misses / (double)css.accesses, css.pending_hits, - css.res_fails); +void gpgpu_sim::shader_print_cache_stats( FILE *fout ) const{ - total_css += css; - } - fprintf(fout, "\tL1D_total_cache_accesses = %llu\n", total_css.accesses); - fprintf(fout, "\tL1D_total_cache_misses = %llu\n", total_css.misses); - if (total_css.accesses > 0) { - fprintf(fout, "\tL1D_total_cache_miss_rate = %.4lf\n", - (double)total_css.misses / (double)total_css.accesses); - } - fprintf(fout, "\tL1D_total_cache_pending_hits = %llu\n", - total_css.pending_hits); - fprintf(fout, "\tL1D_total_cache_reservation_fails = %llu\n", - total_css.res_fails); - total_css.print_port_stats(fout, "\tL1D_cache"); - } + // L1I + struct cache_sub_stats total_css; + struct cache_sub_stats css; - // L1C - if (!m_shader_config->m_L1C_config.disabled()) { - total_css.clear(); - css.clear(); - fprintf(fout, "L1C_cache:\n"); - for (unsigned i = 0; i < m_shader_config->n_simt_clusters; ++i) { - m_cluster[i]->get_L1C_sub_stats(css); - total_css += css; + if(!m_shader_config->m_L1I_config.disabled()){ + total_css.clear(); + css.clear(); + fprintf(fout, "\n========= Core cache stats =========\n"); + fprintf(fout, "L1I_cache:\n"); + for ( unsigned i = 0; i < m_shader_config->n_simt_clusters; ++i ) { + m_cluster[i]->get_L1I_sub_stats(css); + total_css += css; + } + fprintf(fout, "\tL1I_total_cache_accesses = %llu\n", total_css.accesses); + fprintf(fout, "\tL1I_total_cache_misses = %llu\n", total_css.misses); + if(total_css.accesses > 0){ + fprintf(fout, "\tL1I_total_cache_miss_rate = %.4lf\n", (double)total_css.misses / (double)total_css.accesses); + } + fprintf(fout, "\tL1I_total_cache_pending_hits = %llu\n", total_css.pending_hits); + fprintf(fout, "\tL1I_total_cache_reservation_fails = %llu\n", total_css.res_fails); } - fprintf(fout, "\tL1C_total_cache_accesses = %llu\n", total_css.accesses); - fprintf(fout, "\tL1C_total_cache_misses = %llu\n", total_css.misses); - if (total_css.accesses > 0) { - fprintf(fout, "\tL1C_total_cache_miss_rate = %.4lf\n", - (double)total_css.misses / (double)total_css.accesses); + + // L1D + if(!m_shader_config->m_L1D_config.disabled()){ + total_css.clear(); + css.clear(); + fprintf(fout, "L1D_cache:\n"); + for (unsigned i=0;i<m_shader_config->n_simt_clusters;i++){ + m_cluster[i]->get_L1D_sub_stats(css); + + fprintf( stdout, "\tL1D_cache_core[%d]: Access = %llu, Miss = %llu, Miss_rate = %.3lf, Pending_hits = %llu, Reservation_fails = %llu\n", + i, css.accesses, css.misses, (double)css.misses / (double)css.accesses, css.pending_hits, css.res_fails); + + total_css += css; + } + fprintf(fout, "\tL1D_total_cache_accesses = %llu\n", total_css.accesses); + fprintf(fout, "\tL1D_total_cache_misses = %llu\n", total_css.misses); + if(total_css.accesses > 0){ + fprintf(fout, "\tL1D_total_cache_miss_rate = %.4lf\n", (double)total_css.misses / (double)total_css.accesses); + } + fprintf(fout, "\tL1D_total_cache_pending_hits = %llu\n", total_css.pending_hits); + fprintf(fout, "\tL1D_total_cache_reservation_fails = %llu\n", total_css.res_fails); + total_css.print_port_stats(fout, "\tL1D_cache"); } - fprintf(fout, "\tL1C_total_cache_pending_hits = %llu\n", - total_css.pending_hits); - fprintf(fout, "\tL1C_total_cache_reservation_fails = %llu\n", - total_css.res_fails); - } - // L1T - if (!m_shader_config->m_L1T_config.disabled()) { - total_css.clear(); - css.clear(); - fprintf(fout, "L1T_cache:\n"); - for (unsigned i = 0; i < m_shader_config->n_simt_clusters; ++i) { - m_cluster[i]->get_L1T_sub_stats(css); - total_css += css; + // L1C + if(!m_shader_config->m_L1C_config.disabled()){ + total_css.clear(); + css.clear(); + fprintf(fout, "L1C_cache:\n"); + for ( unsigned i = 0; i < m_shader_config->n_simt_clusters; ++i ) { + m_cluster[i]->get_L1C_sub_stats(css); + total_css += css; + } + fprintf(fout, "\tL1C_total_cache_accesses = %llu\n", total_css.accesses); + fprintf(fout, "\tL1C_total_cache_misses = %llu\n", total_css.misses); + if(total_css.accesses > 0){ + fprintf(fout, "\tL1C_total_cache_miss_rate = %.4lf\n", (double)total_css.misses / (double)total_css.accesses); + } + fprintf(fout, "\tL1C_total_cache_pending_hits = %llu\n", total_css.pending_hits); + fprintf(fout, "\tL1C_total_cache_reservation_fails = %llu\n", total_css.res_fails); } - fprintf(fout, "\tL1T_total_cache_accesses = %llu\n", total_css.accesses); - fprintf(fout, "\tL1T_total_cache_misses = %llu\n", total_css.misses); - if (total_css.accesses > 0) { - fprintf(fout, "\tL1T_total_cache_miss_rate = %.4lf\n", - (double)total_css.misses / (double)total_css.accesses); + + // L1T + if(!m_shader_config->m_L1T_config.disabled()){ + total_css.clear(); + css.clear(); + fprintf(fout, "L1T_cache:\n"); + for ( unsigned i = 0; i < m_shader_config->n_simt_clusters; ++i ) { + m_cluster[i]->get_L1T_sub_stats(css); + total_css += css; + } + fprintf(fout, "\tL1T_total_cache_accesses = %llu\n", total_css.accesses); + fprintf(fout, "\tL1T_total_cache_misses = %llu\n", total_css.misses); + if(total_css.accesses > 0){ + fprintf(fout, "\tL1T_total_cache_miss_rate = %.4lf\n", (double)total_css.misses / (double)total_css.accesses); + } + fprintf(fout, "\tL1T_total_cache_pending_hits = %llu\n", total_css.pending_hits); + fprintf(fout, "\tL1T_total_cache_reservation_fails = %llu\n", total_css.res_fails); } - fprintf(fout, "\tL1T_total_cache_pending_hits = %llu\n", - total_css.pending_hits); - fprintf(fout, "\tL1T_total_cache_reservation_fails = %llu\n", - total_css.res_fails); - } } -void gpgpu_sim::shader_print_l1_miss_stat(FILE *fout) const { - unsigned total_d1_misses = 0, total_d1_accesses = 0; - for (unsigned i = 0; i < m_shader_config->n_simt_clusters; ++i) { - unsigned custer_d1_misses = 0, cluster_d1_accesses = 0; - m_cluster[i]->print_cache_stats(fout, cluster_d1_accesses, - custer_d1_misses); - total_d1_misses += custer_d1_misses; - total_d1_accesses += cluster_d1_accesses; - } - fprintf(fout, "total_dl1_misses=%d\n", total_d1_misses); - fprintf(fout, "total_dl1_accesses=%d\n", total_d1_accesses); - fprintf(fout, "total_dl1_miss_rate= %f\n", - (float)total_d1_misses / (float)total_d1_accesses); - /* - fprintf(fout, "THD_INSN_AC: "); - for (unsigned i=0; i<m_shader_config->n_thread_per_shader; i++) - fprintf(fout, "%d ", m_sc[0]->get_thread_n_insn_ac(i)); - fprintf(fout, "\n"); - fprintf(fout, "T_L1_Mss: "); //l1 miss rate per thread - for (unsigned i=0; i<m_shader_config->n_thread_per_shader; i++) - fprintf(fout, "%d ", m_sc[0]->get_thread_n_l1_mis_ac(i)); - fprintf(fout, "\n"); - fprintf(fout, "T_L1_Mgs: "); //l1 merged miss rate per thread - for (unsigned i=0; i<m_shader_config->n_thread_per_shader; i++) - fprintf(fout, "%d ", m_sc[0]->get_thread_n_l1_mis_ac(i) - - m_sc[0]->get_thread_n_l1_mrghit_ac(i)); - fprintf(fout, "\n"); - fprintf(fout, "T_L1_Acc: "); //l1 access per thread - for (unsigned i=0; i<m_shader_config->n_thread_per_shader; i++) - fprintf(fout, "%d ", m_sc[0]->get_thread_n_l1_access_ac(i)); - fprintf(fout, "\n"); +void gpgpu_sim::shader_print_l1_miss_stat( FILE *fout ) const +{ + unsigned total_d1_misses = 0, total_d1_accesses = 0; + for ( unsigned i = 0; i < m_shader_config->n_simt_clusters; ++i ) { + unsigned custer_d1_misses = 0, cluster_d1_accesses = 0; + m_cluster[ i ]->print_cache_stats( fout, cluster_d1_accesses, custer_d1_misses ); + total_d1_misses += custer_d1_misses; + total_d1_accesses += cluster_d1_accesses; + } + fprintf( fout, "total_dl1_misses=%d\n", total_d1_misses ); + fprintf( fout, "total_dl1_accesses=%d\n", total_d1_accesses ); + fprintf( fout, "total_dl1_miss_rate= %f\n", (float)total_d1_misses / (float)total_d1_accesses ); + /* + fprintf(fout, "THD_INSN_AC: "); + for (unsigned i=0; i<m_shader_config->n_thread_per_shader; i++) + fprintf(fout, "%d ", m_sc[0]->get_thread_n_insn_ac(i)); + fprintf(fout, "\n"); + fprintf(fout, "T_L1_Mss: "); //l1 miss rate per thread + for (unsigned i=0; i<m_shader_config->n_thread_per_shader; i++) + fprintf(fout, "%d ", m_sc[0]->get_thread_n_l1_mis_ac(i)); + fprintf(fout, "\n"); + fprintf(fout, "T_L1_Mgs: "); //l1 merged miss rate per thread + for (unsigned i=0; i<m_shader_config->n_thread_per_shader; i++) + fprintf(fout, "%d ", m_sc[0]->get_thread_n_l1_mis_ac(i) - m_sc[0]->get_thread_n_l1_mrghit_ac(i)); + fprintf(fout, "\n"); + fprintf(fout, "T_L1_Acc: "); //l1 access per thread + for (unsigned i=0; i<m_shader_config->n_thread_per_shader; i++) + fprintf(fout, "%d ", m_sc[0]->get_thread_n_l1_access_ac(i)); + fprintf(fout, "\n"); - //per warp - int temp =0; - fprintf(fout, "W_L1_Mss: "); //l1 miss rate per warp - for (unsigned i=0; i<m_shader_config->n_thread_per_shader; i++) { - temp += m_sc[0]->get_thread_n_l1_mis_ac(i); - if (i%m_shader_config->warp_size == - (unsigned)(m_shader_config->warp_size-1)) { - fprintf(fout, "%d ", temp); - temp = 0; - } - } - fprintf(fout, "\n"); - temp=0; - fprintf(fout, "W_L1_Mgs: "); //l1 merged miss rate per warp - for (unsigned i=0; i<m_shader_config->n_thread_per_shader; i++) { - temp += (m_sc[0]->get_thread_n_l1_mis_ac(i) - - m_sc[0]->get_thread_n_l1_mrghit_ac(i) ); - if (i%m_shader_config->warp_size == - (unsigned)(m_shader_config->warp_size-1)) { - fprintf(fout, "%d ", temp); - temp = 0; - } - } - fprintf(fout, "\n"); - temp =0; - fprintf(fout, "W_L1_Acc: "); //l1 access per warp - for (unsigned i=0; i<m_shader_config->n_thread_per_shader; i++) { - temp += m_sc[0]->get_thread_n_l1_access_ac(i); - if (i%m_shader_config->warp_size == - (unsigned)(m_shader_config->warp_size-1)) { - fprintf(fout, "%d ", temp); - temp = 0; - } - } - fprintf(fout, "\n"); - */ + //per warp + int temp =0; + fprintf(fout, "W_L1_Mss: "); //l1 miss rate per warp + for (unsigned i=0; i<m_shader_config->n_thread_per_shader; i++) { + temp += m_sc[0]->get_thread_n_l1_mis_ac(i); + if (i%m_shader_config->warp_size == (unsigned)(m_shader_config->warp_size-1)) { + fprintf(fout, "%d ", temp); + temp = 0; + } + } + fprintf(fout, "\n"); + temp=0; + fprintf(fout, "W_L1_Mgs: "); //l1 merged miss rate per warp + for (unsigned i=0; i<m_shader_config->n_thread_per_shader; i++) { + temp += (m_sc[0]->get_thread_n_l1_mis_ac(i) - m_sc[0]->get_thread_n_l1_mrghit_ac(i) ); + if (i%m_shader_config->warp_size == (unsigned)(m_shader_config->warp_size-1)) { + fprintf(fout, "%d ", temp); + temp = 0; + } + } + fprintf(fout, "\n"); + temp =0; + fprintf(fout, "W_L1_Acc: "); //l1 access per warp + for (unsigned i=0; i<m_shader_config->n_thread_per_shader; i++) { + temp += m_sc[0]->get_thread_n_l1_access_ac(i); + if (i%m_shader_config->warp_size == (unsigned)(m_shader_config->warp_size-1)) { + fprintf(fout, "%d ", temp); + temp = 0; + } + } + fprintf(fout, "\n"); + */ } -void warp_inst_t::print(FILE *fout) const { - if (empty()) { - fprintf(fout, "bubble\n"); - return; - } else - fprintf(fout, "0x%04x ", pc); - fprintf(fout, "w%02d[", m_warp_id); - for (unsigned j = 0; j < m_config->warp_size; j++) - fprintf(fout, "%c", (active(j) ? '1' : '0')); - fprintf(fout, "]: "); - m_config->gpgpu_ctx->func_sim->ptx_print_insn(pc, fout); - fprintf(fout, "\n"); +void warp_inst_t::print( FILE *fout ) const +{ + if (empty() ) { + fprintf(fout,"bubble\n" ); + return; + } else + fprintf(fout,"0x%04x ", pc ); + fprintf(fout, "w%02d[", m_warp_id); + for (unsigned j=0; j<m_config->warp_size; j++) + fprintf(fout, "%c", (active(j)?'1':'0') ); + fprintf(fout, "]: "); + m_config->gpgpu_ctx->func_sim->ptx_print_insn( pc, fout ); + fprintf(fout, "\n"); } -void shader_core_ctx::incexecstat(warp_inst_t *&inst) { - if (inst->mem_op == TEX) inctex_stat(inst->active_count(), 1); +void shader_core_ctx::incexecstat(warp_inst_t *&inst) +{ + if(inst->mem_op==TEX) + inctex_stat(inst->active_count(),1); - // Latency numbers for next operations are used to scale the power values - // for special operations, according observations from microbenchmarking - // TODO: put these numbers in the xml configuration + // Latency numbers for next operations are used to scale the power values + // for special operations, according observations from microbenchmarking + // TODO: put these numbers in the xml configuration - switch (inst->sp_op) { - case INT__OP: - incialu_stat(inst->active_count(), 32); - break; - case INT_MUL_OP: - incimul_stat(inst->active_count(), 7.2); - break; - case INT_MUL24_OP: - incimul24_stat(inst->active_count(), 4.2); - break; - case INT_MUL32_OP: - incimul32_stat(inst->active_count(), 4); - break; - case INT_DIV_OP: - incidiv_stat(inst->active_count(), 40); - break; - case FP__OP: - incfpalu_stat(inst->active_count(), 1); - break; - case FP_MUL_OP: - incfpmul_stat(inst->active_count(), 1.8); - break; - case FP_DIV_OP: - incfpdiv_stat(inst->active_count(), 48); - break; - case FP_SQRT_OP: - inctrans_stat(inst->active_count(), 25); - break; - case FP_LG_OP: - inctrans_stat(inst->active_count(), 35); - break; - case FP_SIN_OP: - inctrans_stat(inst->active_count(), 12); - break; - case FP_EXP_OP: - inctrans_stat(inst->active_count(), 35); - break; - default: - break; - } + switch(inst->sp_op){ + case INT__OP: + incialu_stat(inst->active_count(),32); + break; + case INT_MUL_OP: + incimul_stat(inst->active_count(),7.2); + break; + case INT_MUL24_OP: + incimul24_stat(inst->active_count(),4.2); + break; + case INT_MUL32_OP: + incimul32_stat(inst->active_count(),4); + break; + case INT_DIV_OP: + incidiv_stat(inst->active_count(),40); + break; + case FP__OP: + incfpalu_stat(inst->active_count(),1); + break; + case FP_MUL_OP: + incfpmul_stat(inst->active_count(),1.8); + break; + case FP_DIV_OP: + incfpdiv_stat(inst->active_count(),48); + break; + case FP_SQRT_OP: + inctrans_stat(inst->active_count(),25); + break; + case FP_LG_OP: + inctrans_stat(inst->active_count(),35); + break; + case FP_SIN_OP: + inctrans_stat(inst->active_count(),12); + break; + case FP_EXP_OP: + inctrans_stat(inst->active_count(),35); + break; + default: + break; + } } -void shader_core_ctx::print_stage(unsigned int stage, FILE *fout) const { - m_pipeline_reg[stage].print(fout); - // m_pipeline_reg[stage].print(fout); +void shader_core_ctx::print_stage(unsigned int stage, FILE *fout ) const +{ + m_pipeline_reg[stage].print(fout); + //m_pipeline_reg[stage].print(fout); } -void shader_core_ctx::display_simt_state(FILE *fout, int mask) const { - if ((mask & 4) && m_config->model == POST_DOMINATOR) { - fprintf(fout, "per warp SIMT control-flow state:\n"); - unsigned n = m_config->n_thread_per_shader / m_config->warp_size; - for (unsigned i = 0; i < n; i++) { - unsigned nactive = 0; - for (unsigned j = 0; j < m_config->warp_size; j++) { - unsigned tid = i * m_config->warp_size + j; - int done = ptx_thread_done(tid); - nactive += (ptx_thread_done(tid) ? 0 : 1); - if (done && (mask & 8)) { - unsigned done_cycle = m_thread[tid]->donecycle(); - if (done_cycle) { - printf("\n w%02u:t%03u: done @ cycle %u", i, tid, done_cycle); +void shader_core_ctx::display_simt_state(FILE *fout, int mask ) const +{ + if ( (mask & 4) && m_config->model == POST_DOMINATOR ) { + fprintf(fout,"per warp SIMT control-flow state:\n"); + unsigned n = m_config->n_thread_per_shader / m_config->warp_size; + for (unsigned i=0; i < n; i++) { + unsigned nactive = 0; + for (unsigned j=0; j<m_config->warp_size; j++ ) { + unsigned tid = i*m_config->warp_size + j; + int done = ptx_thread_done(tid); + nactive += (ptx_thread_done(tid)?0:1); + if ( done && (mask & 8) ) { + unsigned done_cycle = m_thread[tid]->donecycle(); + if ( done_cycle ) { + printf("\n w%02u:t%03u: done @ cycle %u", i, tid, done_cycle ); + } + } } - } - } - if (nactive == 0) { - continue; - } - m_simt_stack[i]->print(fout); + if ( nactive == 0 ) { + continue; + } + m_simt_stack[i]->print(fout); + } + fprintf(fout,"\n"); } - fprintf(fout, "\n"); - } } -void ldst_unit::print(FILE *fout) const { - fprintf(fout, "LD/ST unit = "); - m_dispatch_reg->print(fout); - if (m_mem_rc != NO_RC_FAIL) { - fprintf(fout, " LD/ST stall condition: "); - switch (m_mem_rc) { - case BK_CONF: - fprintf(fout, "BK_CONF"); - break; - case MSHR_RC_FAIL: - fprintf(fout, "MSHR_RC_FAIL"); - break; - case ICNT_RC_FAIL: - fprintf(fout, "ICNT_RC_FAIL"); - break; - case COAL_STALL: - fprintf(fout, "COAL_STALL"); - break; - case WB_ICNT_RC_FAIL: - fprintf(fout, "WB_ICNT_RC_FAIL"); - break; - case WB_CACHE_RSRV_FAIL: - fprintf(fout, "WB_CACHE_RSRV_FAIL"); - break; - case N_MEM_STAGE_STALL_TYPE: - fprintf(fout, "N_MEM_STAGE_STALL_TYPE"); - break; - default: - abort(); +void ldst_unit::print(FILE *fout) const +{ + fprintf(fout,"LD/ST unit = "); + m_dispatch_reg->print(fout); + if ( m_mem_rc != NO_RC_FAIL ) { + fprintf(fout," LD/ST stall condition: "); + switch ( m_mem_rc ) { + case BK_CONF: fprintf(fout,"BK_CONF"); break; + case MSHR_RC_FAIL: fprintf(fout,"MSHR_RC_FAIL"); break; + case ICNT_RC_FAIL: fprintf(fout,"ICNT_RC_FAIL"); break; + case COAL_STALL: fprintf(fout,"COAL_STALL"); break; + case WB_ICNT_RC_FAIL: fprintf(fout,"WB_ICNT_RC_FAIL"); break; + case WB_CACHE_RSRV_FAIL: fprintf(fout,"WB_CACHE_RSRV_FAIL"); break; + case N_MEM_STAGE_STALL_TYPE: fprintf(fout,"N_MEM_STAGE_STALL_TYPE"); break; + default: abort(); + } + fprintf(fout,"\n"); } - fprintf(fout, "\n"); - } - fprintf(fout, "LD/ST wb = "); - m_next_wb.print(fout); - fprintf( - fout, - "Last LD/ST writeback @ %llu + %llu (gpu_sim_cycle+gpu_tot_sim_cycle)\n", - m_last_inst_gpu_sim_cycle, m_last_inst_gpu_tot_sim_cycle); - fprintf(fout, "Pending register writes:\n"); - std::map<unsigned /*warp_id*/, - std::map<unsigned /*regnum*/, unsigned /*count*/> >::const_iterator - w; - for (w = m_pending_writes.begin(); w != m_pending_writes.end(); w++) { - unsigned warp_id = w->first; - const std::map<unsigned /*regnum*/, unsigned /*count*/> &warp_info = - w->second; - if (warp_info.empty()) continue; - fprintf(fout, " w%2u : ", warp_id); - std::map<unsigned /*regnum*/, unsigned /*count*/>::const_iterator r; - for (r = warp_info.begin(); r != warp_info.end(); ++r) { - fprintf(fout, " %u(%u)", r->first, r->second); + fprintf(fout,"LD/ST wb = "); + m_next_wb.print(fout); + fprintf(fout, "Last LD/ST writeback @ %llu + %llu (gpu_sim_cycle+gpu_tot_sim_cycle)\n", + m_last_inst_gpu_sim_cycle, m_last_inst_gpu_tot_sim_cycle ); + fprintf(fout,"Pending register writes:\n"); + std::map<unsigned/*warp_id*/, std::map<unsigned/*regnum*/,unsigned/*count*/> >::const_iterator w; + for( w=m_pending_writes.begin(); w!=m_pending_writes.end(); w++ ) { + unsigned warp_id = w->first; + const std::map<unsigned/*regnum*/,unsigned/*count*/> &warp_info = w->second; + if( warp_info.empty() ) + continue; + fprintf(fout," w%2u : ", warp_id ); + std::map<unsigned/*regnum*/,unsigned/*count*/>::const_iterator r; + for( r=warp_info.begin(); r!=warp_info.end(); ++r ) { + fprintf(fout," %u(%u)", r->first, r->second ); + } + fprintf(fout,"\n"); + } + m_L1C->display_state(fout); + m_L1T->display_state(fout); + if( !m_config->m_L1D_config.disabled() ) + m_L1D->display_state(fout); + fprintf(fout,"LD/ST response FIFO (occupancy = %zu):\n", m_response_fifo.size() ); + for( std::list<mem_fetch*>::const_iterator i=m_response_fifo.begin(); i != m_response_fifo.end(); i++ ) { + const mem_fetch *mf = *i; + mf->print(fout); } - fprintf(fout, "\n"); - } - m_L1C->display_state(fout); - m_L1T->display_state(fout); - if (!m_config->m_L1D_config.disabled()) m_L1D->display_state(fout); - fprintf(fout, "LD/ST response FIFO (occupancy = %zu):\n", - m_response_fifo.size()); - for (std::list<mem_fetch *>::const_iterator i = m_response_fifo.begin(); - i != m_response_fifo.end(); i++) { - const mem_fetch *mf = *i; - mf->print(fout); - } } -void shader_core_ctx::display_pipeline(FILE *fout, int print_mem, - int mask) const { - fprintf(fout, "=================================================\n"); - fprintf(fout, "shader %u at cycle %Lu+%Lu (%u threads running)\n", m_sid, - m_gpu->gpu_tot_sim_cycle, m_gpu->gpu_sim_cycle, m_not_completed); - fprintf(fout, "=================================================\n"); +void shader_core_ctx::display_pipeline(FILE *fout, int print_mem, int mask ) const +{ + fprintf(fout, "=================================================\n"); + fprintf(fout, "shader %u at cycle %Lu+%Lu (%u threads running)\n", m_sid, + m_gpu->gpu_tot_sim_cycle, m_gpu->gpu_sim_cycle, m_not_completed); + fprintf(fout, "=================================================\n"); - dump_warp_state(fout); - fprintf(fout, "\n"); + dump_warp_state(fout); + fprintf(fout,"\n"); - m_L1I->display_state(fout); + m_L1I->display_state(fout); - fprintf(fout, "IF/ID = "); - if (!m_inst_fetch_buffer.m_valid) - fprintf(fout, "bubble\n"); - else { - fprintf(fout, "w%2u : pc = 0x%x, nbytes = %u\n", - m_inst_fetch_buffer.m_warp_id, m_inst_fetch_buffer.m_pc, - m_inst_fetch_buffer.m_nbytes); - } - fprintf(fout, "\nibuffer status:\n"); - for (unsigned i = 0; i < m_config->max_warps_per_shader; i++) { - if (!m_warp[i].ibuffer_empty()) m_warp[i].print_ibuffer(fout); - } - fprintf(fout, "\n"); - display_simt_state(fout, mask); - fprintf(fout, "-------------------------- Scoreboard\n"); - m_scoreboard->printContents(); - /* - fprintf(fout,"ID/OC (SP) = "); - print_stage(ID_OC_SP, fout); - fprintf(fout,"ID/OC (SFU) = "); - print_stage(ID_OC_SFU, fout); - fprintf(fout,"ID/OC (MEM) = "); - print_stage(ID_OC_MEM, fout); - */ - fprintf(fout, "-------------------------- OP COL\n"); - m_operand_collector.dump(fout); - /* fprintf(fout, "OC/EX (SP) = "); - print_stage(OC_EX_SP, fout); - fprintf(fout, "OC/EX (SFU) = "); - print_stage(OC_EX_SFU, fout); - fprintf(fout, "OC/EX (MEM) = "); - print_stage(OC_EX_MEM, fout); - */ - fprintf(fout, "-------------------------- Pipe Regs\n"); + fprintf(fout, "IF/ID = "); + if( !m_inst_fetch_buffer.m_valid ) + fprintf(fout,"bubble\n"); + else { + fprintf(fout,"w%2u : pc = 0x%x, nbytes = %u\n", + m_inst_fetch_buffer.m_warp_id, + m_inst_fetch_buffer.m_pc, + m_inst_fetch_buffer.m_nbytes ); + } + fprintf(fout,"\nibuffer status:\n"); + for( unsigned i=0; i<m_config->max_warps_per_shader; i++) { + if( !m_warp[i].ibuffer_empty() ) + m_warp[i].print_ibuffer(fout); + } + fprintf(fout,"\n"); + display_simt_state(fout,mask); + fprintf(fout, "-------------------------- Scoreboard\n"); + m_scoreboard->printContents(); +/* + fprintf(fout,"ID/OC (SP) = "); + print_stage(ID_OC_SP, fout); + fprintf(fout,"ID/OC (SFU) = "); + print_stage(ID_OC_SFU, fout); + fprintf(fout,"ID/OC (MEM) = "); + print_stage(ID_OC_MEM, fout); +*/ + fprintf(fout, "-------------------------- OP COL\n"); + m_operand_collector.dump(fout); +/* fprintf(fout, "OC/EX (SP) = "); + print_stage(OC_EX_SP, fout); + fprintf(fout, "OC/EX (SFU) = "); + print_stage(OC_EX_SFU, fout); + fprintf(fout, "OC/EX (MEM) = "); + print_stage(OC_EX_MEM, fout); +*/ + fprintf(fout, "-------------------------- Pipe Regs\n"); - for (unsigned i = 0; i < N_PIPELINE_STAGES; i++) { - fprintf(fout, "--- %s ---\n", pipeline_stage_name_decode[i]); - print_stage(i, fout); - fprintf(fout, "\n"); - } + for (unsigned i = 0; i < N_PIPELINE_STAGES; i++) { + fprintf(fout,"--- %s ---\n",pipeline_stage_name_decode[i]); + print_stage(i,fout);fprintf(fout,"\n"); + } - fprintf(fout, "-------------------------- Fu\n"); - for (unsigned n = 0; n < m_num_function_units; n++) { - m_fu[n]->print(fout); - fprintf(fout, "---------------\n"); - } - fprintf(fout, "-------------------------- other:\n"); + fprintf(fout, "-------------------------- Fu\n"); + for( unsigned n=0; n < m_num_function_units; n++ ){ + m_fu[n]->print(fout); + fprintf(fout, "---------------\n"); + } + fprintf(fout, "-------------------------- other:\n"); - for (unsigned i = 0; i < num_result_bus; i++) { - std::string bits = m_result_bus[i]->to_string(); - fprintf(fout, "EX/WB sched[%d]= %s\n", i, bits.c_str()); - } - fprintf(fout, "EX/WB = "); - print_stage(EX_WB, fout); - fprintf(fout, "\n"); - fprintf( - fout, - "Last EX/WB writeback @ %llu + %llu (gpu_sim_cycle+gpu_tot_sim_cycle)\n", - m_last_inst_gpu_sim_cycle, m_last_inst_gpu_tot_sim_cycle); + for(unsigned i=0; i<num_result_bus; i++){ + std::string bits = m_result_bus[i]->to_string(); + fprintf(fout, "EX/WB sched[%d]= %s\n", i, bits.c_str() ); + } + fprintf(fout, "EX/WB = "); + print_stage(EX_WB, fout); + fprintf(fout, "\n"); + fprintf(fout, "Last EX/WB writeback @ %llu + %llu (gpu_sim_cycle+gpu_tot_sim_cycle)\n", + m_last_inst_gpu_sim_cycle, m_last_inst_gpu_tot_sim_cycle ); + + if( m_active_threads.count() <= 2*m_config->warp_size ) { + fprintf(fout,"Active Threads : "); + unsigned last_warp_id = -1; + for(unsigned tid=0; tid < m_active_threads.size(); tid++ ) { + unsigned warp_id = tid/m_config->warp_size; + if( m_active_threads.test(tid) ) { + if( warp_id != last_warp_id ) { + fprintf(fout,"\n warp %u : ", warp_id ); + last_warp_id=warp_id; + } + fprintf(fout,"%u ", tid ); + } + } + } - if (m_active_threads.count() <= 2 * m_config->warp_size) { - fprintf(fout, "Active Threads : "); - unsigned last_warp_id = -1; - for (unsigned tid = 0; tid < m_active_threads.size(); tid++) { - unsigned warp_id = tid / m_config->warp_size; - if (m_active_threads.test(tid)) { - if (warp_id != last_warp_id) { - fprintf(fout, "\n warp %u : ", warp_id); - last_warp_id = warp_id; - } - fprintf(fout, "%u ", tid); - } - } - } } -unsigned int shader_core_config::max_cta(const kernel_info_t &k) const { - unsigned threads_per_cta = k.threads_per_cta(); - const class function_info *kernel = k.entry(); - unsigned int padded_cta_size = threads_per_cta; - if (padded_cta_size % warp_size) - padded_cta_size = ((padded_cta_size / warp_size) + 1) * (warp_size); +unsigned int shader_core_config::max_cta( const kernel_info_t &k ) const +{ + unsigned threads_per_cta = k.threads_per_cta(); + const class function_info *kernel = k.entry(); + unsigned int padded_cta_size = threads_per_cta; + if (padded_cta_size%warp_size) + padded_cta_size = ((padded_cta_size/warp_size)+1)*(warp_size); - // Limit by n_threads/shader - unsigned int result_thread = n_thread_per_shader / padded_cta_size; + //Limit by n_threads/shader + unsigned int result_thread = n_thread_per_shader / padded_cta_size; - const struct gpgpu_ptx_sim_info *kernel_info = ptx_sim_kernel_info(kernel); + const struct gpgpu_ptx_sim_info *kernel_info = ptx_sim_kernel_info(kernel); - // Limit by shmem/shader - unsigned int result_shmem = (unsigned)-1; - if (kernel_info->smem > 0) - result_shmem = gpgpu_shmem_size / kernel_info->smem; + //Limit by shmem/shader + unsigned int result_shmem = (unsigned)-1; + if (kernel_info->smem > 0) + result_shmem = gpgpu_shmem_size / kernel_info->smem; - // Limit by register count, rounded up to multiple of 4. - unsigned int result_regs = (unsigned)-1; - if (kernel_info->regs > 0) - result_regs = gpgpu_shader_registers / - (padded_cta_size * ((kernel_info->regs + 3) & ~3)); + //Limit by register count, rounded up to multiple of 4. + unsigned int result_regs = (unsigned)-1; + if (kernel_info->regs > 0) + result_regs = gpgpu_shader_registers / (padded_cta_size * ((kernel_info->regs+3)&~3)); - // Limit by CTA - unsigned int result_cta = max_cta_per_core; + //Limit by CTA + unsigned int result_cta = max_cta_per_core; - unsigned result = result_thread; - result = gs_min2(result, result_shmem); - result = gs_min2(result, result_regs); - result = gs_min2(result, result_cta); + unsigned result = result_thread; + result = gs_min2(result, result_shmem); + result = gs_min2(result, result_regs); + result = gs_min2(result, result_cta); - static const struct gpgpu_ptx_sim_info *last_kinfo = NULL; - if (last_kinfo != - kernel_info) { // Only print out stats if kernel_info struct changes - last_kinfo = kernel_info; - printf("GPGPU-Sim uArch: CTA/core = %u, limited by:", result); - if (result == result_thread) printf(" threads"); - if (result == result_shmem) printf(" shmem"); - if (result == result_regs) printf(" regs"); - if (result == result_cta) printf(" cta_limit"); - printf("\n"); - } + static const struct gpgpu_ptx_sim_info* last_kinfo = NULL; + if (last_kinfo != kernel_info) { //Only print out stats if kernel_info struct changes + last_kinfo = kernel_info; + printf ("GPGPU-Sim uArch: CTA/core = %u, limited by:", result); + if (result == result_thread) printf (" threads"); + if (result == result_shmem) printf (" shmem"); + if (result == result_regs) printf (" regs"); + if (result == result_cta) printf (" cta_limit"); + printf ("\n"); + } - // gpu_max_cta_per_shader is limited by number of CTAs if not enough to keep - // all cores busy - if (k.num_blocks() < result * num_shader()) { - result = k.num_blocks() / num_shader(); - if (k.num_blocks() % num_shader()) result++; - } + //gpu_max_cta_per_shader is limited by number of CTAs if not enough to keep all cores busy + if( k.num_blocks() < result*num_shader() ) { + result = k.num_blocks() / num_shader(); + if (k.num_blocks() % num_shader()) + result++; + } - assert(result <= MAX_CTA_PER_SHADER); - if (result < 1) { - printf( - "GPGPU-Sim uArch: ERROR ** Kernel requires more resources than shader " - "has.\n"); - if (gpgpu_ignore_resources_limitation) { - printf( - "GPGPU-Sim uArch: gpgpu_ignore_resources_limitation is set, ignore " - "the ERROR!\n"); - return 1; + assert( result <= MAX_CTA_PER_SHADER ); + if (result < 1) { + printf ("GPGPU-Sim uArch: ERROR ** Kernel requires more resources than shader has.\n"); + if(gpgpu_ignore_resources_limitation) { + printf ("GPGPU-Sim uArch: gpgpu_ignore_resources_limitation is set, ignore the ERROR!\n"); + return 1; + } + abort(); } - abort(); - } - if (adaptive_volta_cache_config && !k.volta_cache_config_set) { - // For Volta, we assign the remaining shared memory to L1 cache - // For more info, see - // https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#shared-memory-7-x - unsigned total_shmed = kernel_info->smem * result; - assert(total_shmed >= 0 && total_shmed <= gpgpu_shmem_size); - assert(gpgpu_shmem_size == 98304); // Volta has 96 KB shared - assert(m_L1D_config.get_nset() == 4); // Volta L1 has four sets - if (total_shmed < gpgpu_shmem_size) { - if (total_shmed == 0) - m_L1D_config.set_assoc(256); // L1 is 128KB ans shd=0 - else if (total_shmed > 0 && total_shmed <= 8192) - m_L1D_config.set_assoc(240); // L1 is 120KB ans shd=8KB - else if (total_shmed > 8192 && total_shmed <= 16384) - m_L1D_config.set_assoc(224); // L1 is 112KB ans shd=16KB - else if (total_shmed > 16384 && total_shmed <= 32768) - m_L1D_config.set_assoc(192); // L1 is 96KB ans shd=32KB - else if (total_shmed > 32768 && total_shmed <= 65536) - m_L1D_config.set_assoc(128); // L1 is 64KB ans shd=64KB - else if (total_shmed > 65536 && total_shmed <= gpgpu_shmem_size) - m_L1D_config.set_assoc(64); // L1 is 32KB and shd=96KB - else - assert(0); + if(adaptive_volta_cache_config && !k.volta_cache_config_set) { + //For Volta, we assign the remaining shared memory to L1 cache + //For more info, see https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#shared-memory-7-x + unsigned total_shmed = kernel_info->smem * result; + assert(total_shmed >=0 && total_shmed <= gpgpu_shmem_size); + assert(gpgpu_shmem_size == 98304); //Volta has 96 KB shared + assert(m_L1D_config.get_nset() == 4); //Volta L1 has four sets + if(total_shmed < gpgpu_shmem_size){ + if(total_shmed == 0) + m_L1D_config.set_assoc(256); //L1 is 128KB ans shd=0 + else if(total_shmed > 0 && total_shmed <= 8192) + m_L1D_config.set_assoc(240); //L1 is 120KB ans shd=8KB + else if(total_shmed > 8192 && total_shmed <= 16384) + m_L1D_config.set_assoc(224); //L1 is 112KB ans shd=16KB + else if(total_shmed > 16384 && total_shmed <= 32768) + m_L1D_config.set_assoc(192); //L1 is 96KB ans shd=32KB + else if(total_shmed > 32768 && total_shmed <= 65536) + m_L1D_config.set_assoc(128); //L1 is 64KB ans shd=64KB + else if(total_shmed > 65536 && total_shmed <= gpgpu_shmem_size) + m_L1D_config.set_assoc(64); //L1 is 32KB and shd=96KB + else + assert(0); - printf("GPGPU-Sim: Reconfigure L1 cache in Volta Archi to %uKB\n", - m_L1D_config.get_total_size_inKB()); - } + printf ("GPGPU-Sim: Reconfigure L1 cache in Volta Archi to %uKB\n", m_L1D_config.get_total_size_inKB()); + } - k.volta_cache_config_set = true; - } + k.volta_cache_config_set = true; + } - return result; + return result; } void shader_core_config::set_pipeline_latency() { - // calculate the max latency based on the input - unsigned int_latency[5]; - unsigned fp_latency[5]; - unsigned dp_latency[5]; - unsigned sfu_latency; - unsigned tensor_latency; + //calculate the max latency based on the input - /* - * [0] ADD,SUB - * [1] MAX,Min - * [2] MUL - * [3] MAD - * [4] DIV - */ - sscanf(gpgpu_ctx->func_sim->opcode_latency_int, "%u,%u,%u,%u,%u", - &int_latency[0], &int_latency[1], &int_latency[2], &int_latency[3], - &int_latency[4]); - sscanf(gpgpu_ctx->func_sim->opcode_latency_fp, "%u,%u,%u,%u,%u", - &fp_latency[0], &fp_latency[1], &fp_latency[2], &fp_latency[3], - &fp_latency[4]); - sscanf(gpgpu_ctx->func_sim->opcode_latency_dp, "%u,%u,%u,%u,%u", - &dp_latency[0], &dp_latency[1], &dp_latency[2], &dp_latency[3], - &dp_latency[4]); - sscanf(gpgpu_ctx->func_sim->opcode_latency_sfu, "%u", &sfu_latency); - sscanf(gpgpu_ctx->func_sim->opcode_latency_tensor, "%u", &tensor_latency); + unsigned int_latency[5]; + unsigned fp_latency[5]; + unsigned dp_latency[5]; + unsigned sfu_latency; + unsigned tensor_latency; + + /* + * [0] ADD,SUB + * [1] MAX,Min + * [2] MUL + * [3] MAD + * [4] DIV + */ + sscanf(gpgpu_ctx->func_sim->opcode_latency_int, "%u,%u,%u,%u,%u", + &int_latency[0],&int_latency[1],&int_latency[2], + &int_latency[3],&int_latency[4]); + sscanf(gpgpu_ctx->func_sim->opcode_latency_fp, "%u,%u,%u,%u,%u", + &fp_latency[0],&fp_latency[1],&fp_latency[2], + &fp_latency[3],&fp_latency[4]); + sscanf(gpgpu_ctx->func_sim->opcode_latency_dp, "%u,%u,%u,%u,%u", + &dp_latency[0],&dp_latency[1],&dp_latency[2], + &dp_latency[3],&dp_latency[4]); + sscanf(gpgpu_ctx->func_sim->opcode_latency_sfu, "%u", + &sfu_latency); + sscanf(gpgpu_ctx->func_sim->opcode_latency_tensor, "%u", + &tensor_latency); + + //all div operation are executed on sfu + //assume that the max latency are dp div or normal sfu_latency + max_sfu_latency = std::max(dp_latency[4],sfu_latency); + //assume that the max operation has the max latency + max_sp_latency = fp_latency[1]; + max_int_latency = int_latency[1]; + max_dp_latency = dp_latency[1]; + max_tensor_core_latency = tensor_latency; - // all div operation are executed on sfu - // assume that the max latency are dp div or normal sfu_latency - max_sfu_latency = std::max(dp_latency[4], sfu_latency); - // assume that the max operation has the max latency - max_sp_latency = fp_latency[1]; - max_int_latency = int_latency[1]; - max_dp_latency = dp_latency[1]; - max_tensor_core_latency = tensor_latency; } -void shader_core_ctx::cycle() { - if (!isactive() && get_not_completed() == 0) return; +void shader_core_ctx::cycle() +{ + if(!isactive() && get_not_completed() == 0) + return; - m_stats->shader_cycles[m_sid]++; - writeback(); - execute(); - read_operands(); - issue(); - decode(); - fetch(); + m_stats->shader_cycles[m_sid]++; + writeback(); + execute(); + read_operands(); + issue(); + decode(); + fetch(); } // Flushes all content of the cache to memory -void shader_core_ctx::cache_flush() { m_ldst_unit->flush(); } +void shader_core_ctx::cache_flush() +{ + m_ldst_unit->flush(); +} -void shader_core_ctx::cache_invalidate() { m_ldst_unit->invalidate(); } +void shader_core_ctx::cache_invalidate() +{ + m_ldst_unit->invalidate(); +} // modifiers -std::list<opndcoll_rfu_t::op_t> opndcoll_rfu_t::arbiter_t::allocate_reads() { - std::list<op_t> result; // a list of registers that (a) are in different - // register banks, (b) do not go to the same operand - // collector +std::list<opndcoll_rfu_t::op_t> opndcoll_rfu_t::arbiter_t::allocate_reads() +{ + std::list<op_t> result; // a list of registers that (a) are in different register banks, (b) do not go to the same operand collector - int input; - int output; - int _inputs = m_num_banks; - int _outputs = m_num_collectors; - int _square = (_inputs > _outputs) ? _inputs : _outputs; - assert(_square > 0); - int _pri = (int)m_last_cu; + int input; + int output; + int _inputs = m_num_banks; + int _outputs = m_num_collectors; + int _square = ( _inputs > _outputs ) ? _inputs : _outputs; + assert(_square > 0); + int _pri = (int)m_last_cu; - // Clear matching - for (int i = 0; i < _inputs; ++i) _inmatch[i] = -1; - for (int j = 0; j < _outputs; ++j) _outmatch[j] = -1; + // Clear matching + for ( int i = 0; i < _inputs; ++i ) + _inmatch[i] = -1; + for ( int j = 0; j < _outputs; ++j ) + _outmatch[j] = -1; - for (unsigned i = 0; i < m_num_banks; i++) { - for (unsigned j = 0; j < m_num_collectors; j++) { - assert(i < (unsigned)_inputs); - assert(j < (unsigned)_outputs); - _request[i][j] = 0; - } - if (!m_queue[i].empty()) { - const op_t &op = m_queue[i].front(); - int oc_id = op.get_oc_id(); - assert(i < (unsigned)_inputs); - assert(oc_id < _outputs); - _request[i][oc_id] = 1; - } - if (m_allocated_bank[i].is_write()) { - assert(i < (unsigned)_inputs); - _inmatch[i] = 0; // write gets priority - } - } + for( unsigned i=0; i<m_num_banks; i++) { + for( unsigned j=0; j<m_num_collectors; j++) { + assert( i < (unsigned)_inputs ); + assert( j < (unsigned)_outputs ); + _request[i][j] = 0; + } + if( !m_queue[i].empty() ) { + const op_t &op = m_queue[i].front(); + int oc_id = op.get_oc_id(); + assert( i < (unsigned)_inputs ); + assert( oc_id < _outputs ); + _request[i][oc_id] = 1; + } + if( m_allocated_bank[i].is_write() ) { + assert( i < (unsigned)_inputs ); + _inmatch[i] = 0; // write gets priority + } + } - ///// wavefront allocator from booksim... ---> + ///// wavefront allocator from booksim... ---> + + // Loop through diagonals of request matrix - // Loop through diagonals of request matrix + for ( int p = 0; p < _square; ++p ) { + output = ( _pri + p ) % _square; - for (int p = 0; p < _square; ++p) { - output = (_pri + p) % _square; + // Step through the current diagonal + for ( input = 0; input < _inputs; ++input ) { + assert( input < _inputs ); + assert( output < _outputs ); + if ( ( output < _outputs ) && + ( _inmatch[input] == -1 ) && + ( _outmatch[output] == -1 ) && + ( _request[input][output]/*.label != -1*/ ) ) { + // Grant! + _inmatch[input] = output; + _outmatch[output] = input; + } - // Step through the current diagonal - for (input = 0; input < _inputs; ++input) { - assert(input < _inputs); - assert(output < _outputs); - if ((output < _outputs) && (_inmatch[input] == -1) && - (_outmatch[output] == -1) && - (_request[input][output] /*.label != -1*/)) { - // Grant! - _inmatch[input] = output; - _outmatch[output] = input; + output = ( output + 1 ) % _square; } + } - output = (output + 1) % _square; - } - } - - // Round-robin the priority diagonal - _pri = (_pri + 1) % _square; + // Round-robin the priority diagonal + _pri = ( _pri + 1 ) % _square; - /// <--- end code from booksim + /// <--- end code from booksim - m_last_cu = _pri; - for (unsigned i = 0; i < m_num_banks; i++) { - if (_inmatch[i] != -1) { - if (!m_allocated_bank[i].is_write()) { - unsigned bank = (unsigned)i; - op_t &op = m_queue[bank].front(); - result.push_back(op); - m_queue[bank].pop_front(); + m_last_cu = _pri; + for( unsigned i=0; i < m_num_banks; i++ ) { + if( _inmatch[i] != -1 ) { + if( !m_allocated_bank[i].is_write() ) { + unsigned bank = (unsigned)i; + op_t &op = m_queue[bank].front(); + result.push_back(op); + m_queue[bank].pop_front(); + } } - } - } + } - return result; + return result; } -barrier_set_t::barrier_set_t(shader_core_ctx *shader, - unsigned max_warps_per_core, - unsigned max_cta_per_core, - unsigned max_barriers_per_cta, - unsigned warp_size) { - m_max_warps_per_core = max_warps_per_core; - m_max_cta_per_core = max_cta_per_core; - m_max_barriers_per_cta = max_barriers_per_cta; - m_warp_size = warp_size; - m_shader = shader; - if (max_warps_per_core > WARP_PER_CTA_MAX) { - printf( - "ERROR ** increase WARP_PER_CTA_MAX in shader.h from %u to >= %u or " - "warps per cta in gpgpusim.config\n", - WARP_PER_CTA_MAX, max_warps_per_core); - exit(1); - } - if (max_barriers_per_cta > MAX_BARRIERS_PER_CTA) { - printf( - "ERROR ** increase MAX_BARRIERS_PER_CTA in abstract_hardware_model.h " - "from %u to >= %u or barriers per cta in gpgpusim.config\n", - MAX_BARRIERS_PER_CTA, max_barriers_per_cta); - exit(1); - } - m_warp_active.reset(); - m_warp_at_barrier.reset(); - for (unsigned i = 0; i < max_barriers_per_cta; i++) { - m_bar_id_to_warps[i].reset(); - } +barrier_set_t::barrier_set_t(shader_core_ctx *shader,unsigned max_warps_per_core, unsigned max_cta_per_core, unsigned max_barriers_per_cta, unsigned warp_size) +{ + m_max_warps_per_core = max_warps_per_core; + m_max_cta_per_core = max_cta_per_core; + m_max_barriers_per_cta = max_barriers_per_cta; + m_warp_size = warp_size; + m_shader = shader; + if( max_warps_per_core > WARP_PER_CTA_MAX ) { + printf("ERROR ** increase WARP_PER_CTA_MAX in shader.h from %u to >= %u or warps per cta in gpgpusim.config\n", + WARP_PER_CTA_MAX, max_warps_per_core ); + exit(1); + } + if(max_barriers_per_cta > MAX_BARRIERS_PER_CTA){ + printf("ERROR ** increase MAX_BARRIERS_PER_CTA in abstract_hardware_model.h from %u to >= %u or barriers per cta in gpgpusim.config\n", + MAX_BARRIERS_PER_CTA, max_barriers_per_cta ); + exit(1); + } + m_warp_active.reset(); + m_warp_at_barrier.reset(); + for(unsigned i=0; i<max_barriers_per_cta; i++){ + m_bar_id_to_warps[i].reset(); + } } // during cta allocation -void barrier_set_t::allocate_barrier(unsigned cta_id, warp_set_t warps) { - assert(cta_id < m_max_cta_per_core); - cta_to_warp_t::iterator w = m_cta_to_warps.find(cta_id); - assert(w == m_cta_to_warps.end()); // cta should not already be active or - // allocated barrier resources - m_cta_to_warps[cta_id] = warps; - assert(m_cta_to_warps.size() <= - m_max_cta_per_core); // catch cta's that were not properly deallocated +void barrier_set_t::allocate_barrier( unsigned cta_id, warp_set_t warps ) +{ + assert( cta_id < m_max_cta_per_core ); + cta_to_warp_t::iterator w=m_cta_to_warps.find(cta_id); + assert( w == m_cta_to_warps.end() ); // cta should not already be active or allocated barrier resources + m_cta_to_warps[cta_id] = warps; + assert( m_cta_to_warps.size() <= m_max_cta_per_core ); // catch cta's that were not properly deallocated + + m_warp_active |= warps; + m_warp_at_barrier &= ~warps; + for(unsigned i=0; i<m_max_barriers_per_cta; i++){ + m_bar_id_to_warps[i] &=~warps; + } - m_warp_active |= warps; - m_warp_at_barrier &= ~warps; - for (unsigned i = 0; i < m_max_barriers_per_cta; i++) { - m_bar_id_to_warps[i] &= ~warps; - } } // during cta deallocation -void barrier_set_t::deallocate_barrier(unsigned cta_id) { - cta_to_warp_t::iterator w = m_cta_to_warps.find(cta_id); - if (w == m_cta_to_warps.end()) return; - warp_set_t warps = w->second; - warp_set_t at_barrier = warps & m_warp_at_barrier; - assert(at_barrier.any() == false); // no warps stuck at barrier - warp_set_t active = warps & m_warp_active; - assert(active.any() == false); // no warps in CTA still running - m_warp_active &= ~warps; - m_warp_at_barrier &= ~warps; +void barrier_set_t::deallocate_barrier( unsigned cta_id ) +{ + cta_to_warp_t::iterator w=m_cta_to_warps.find(cta_id); + if( w == m_cta_to_warps.end() ) + return; + warp_set_t warps = w->second; + warp_set_t at_barrier = warps & m_warp_at_barrier; + assert( at_barrier.any() == false ); // no warps stuck at barrier + warp_set_t active = warps & m_warp_active; + assert( active.any() == false ); // no warps in CTA still running + m_warp_active &= ~warps; + m_warp_at_barrier &= ~warps; - for (unsigned i = 0; i < m_max_barriers_per_cta; i++) { - warp_set_t at_a_specific_barrier = warps & m_bar_id_to_warps[i]; - assert(at_a_specific_barrier.any() == false); // no warps stuck at barrier - m_bar_id_to_warps[i] &= ~warps; - } - m_cta_to_warps.erase(w); + for(unsigned i=0; i<m_max_barriers_per_cta; i++){ + warp_set_t at_a_specific_barrier = warps & m_bar_id_to_warps[i]; + assert( at_a_specific_barrier.any() == false ); // no warps stuck at barrier + m_bar_id_to_warps[i] &=~warps; + } + m_cta_to_warps.erase(w); } // individual warp hits barrier -void barrier_set_t::warp_reaches_barrier(unsigned cta_id, unsigned warp_id, - warp_inst_t *inst) { - barrier_type bar_type = inst->bar_type; - unsigned bar_id = inst->bar_id; - unsigned bar_count = inst->bar_count; - assert(bar_id != (unsigned)-1); - cta_to_warp_t::iterator w = m_cta_to_warps.find(cta_id); +void barrier_set_t::warp_reaches_barrier(unsigned cta_id,unsigned warp_id,warp_inst_t* inst) +{ + barrier_type bar_type = inst->bar_type; + unsigned bar_id = inst->bar_id; + unsigned bar_count = inst->bar_count; + assert(bar_id!=(unsigned)-1); + cta_to_warp_t::iterator w=m_cta_to_warps.find(cta_id); - if (w == m_cta_to_warps.end()) { // cta is active - printf( - "ERROR ** cta_id %u not found in barrier set on cycle %llu+%llu...\n", - cta_id, m_shader->get_gpu()->gpu_tot_sim_cycle, - m_shader->get_gpu()->gpu_sim_cycle); - dump(); - abort(); - } - assert(w->second.test(warp_id) == true); // warp is in cta + if( w == m_cta_to_warps.end() ) { // cta is active + printf("ERROR ** cta_id %u not found in barrier set on cycle %llu+%llu...\n", cta_id, m_shader->get_gpu()->gpu_tot_sim_cycle, m_shader->get_gpu()->gpu_sim_cycle ); + dump(); + abort(); + } + assert( w->second.test(warp_id) == true ); // warp is in cta - m_bar_id_to_warps[bar_id].set(warp_id); - if (bar_type == SYNC || bar_type == RED) { - m_warp_at_barrier.set(warp_id); - } - warp_set_t warps_in_cta = w->second; - warp_set_t at_barrier = warps_in_cta & m_bar_id_to_warps[bar_id]; - warp_set_t active = warps_in_cta & m_warp_active; - if (bar_count == (unsigned)-1) { - if (at_barrier == active) { - // all warps have reached barrier, so release waiting warps... - m_bar_id_to_warps[bar_id] &= ~at_barrier; - m_warp_at_barrier &= ~at_barrier; - if (bar_type == RED) { - m_shader->broadcast_barrier_reduction(cta_id, bar_id, at_barrier); - } - } - } else { - // TODO: check on the hardware if the count should include warp that exited - if ((at_barrier.count() * m_warp_size) == bar_count) { - // required number of warps have reached barrier, so release waiting - // warps... - m_bar_id_to_warps[bar_id] &= ~at_barrier; - m_warp_at_barrier &= ~at_barrier; - if (bar_type == RED) { - m_shader->broadcast_barrier_reduction(cta_id, bar_id, at_barrier); - } - } + m_bar_id_to_warps[bar_id].set(warp_id); + if(bar_type==SYNC || bar_type==RED){ + m_warp_at_barrier.set(warp_id); + } + warp_set_t warps_in_cta = w->second; + warp_set_t at_barrier = warps_in_cta & m_bar_id_to_warps[bar_id]; + warp_set_t active = warps_in_cta & m_warp_active; + if(bar_count==(unsigned)-1){ + if( at_barrier == active ) { + // all warps have reached barrier, so release waiting warps... + m_bar_id_to_warps[bar_id] &= ~at_barrier; + m_warp_at_barrier &= ~at_barrier; + if(bar_type==RED){ + m_shader->broadcast_barrier_reduction(cta_id, bar_id,at_barrier); + } + } + }else{ + // TODO: check on the hardware if the count should include warp that exited + if ((at_barrier.count() * m_warp_size) == bar_count){ + // required number of warps have reached barrier, so release waiting warps... + m_bar_id_to_warps[bar_id] &= ~at_barrier; + m_warp_at_barrier &= ~at_barrier; + if(bar_type==RED){ + m_shader->broadcast_barrier_reduction(cta_id, bar_id,at_barrier); + } + } } + + } -// warp reaches exit -void barrier_set_t::warp_exit(unsigned warp_id) { - // caller needs to verify all threads in warp are done, e.g., by checking PDOM - // stack to - // see it has only one entry during exit_impl() - m_warp_active.reset(warp_id); - // test for barrier release - cta_to_warp_t::iterator w = m_cta_to_warps.begin(); - for (; w != m_cta_to_warps.end(); ++w) { - if (w->second.test(warp_id) == true) break; - } - warp_set_t warps_in_cta = w->second; - warp_set_t active = warps_in_cta & m_warp_active; +// warp reaches exit +void barrier_set_t::warp_exit( unsigned warp_id ) +{ + // caller needs to verify all threads in warp are done, e.g., by checking PDOM stack to + // see it has only one entry during exit_impl() + m_warp_active.reset(warp_id); - for (unsigned i = 0; i < m_max_barriers_per_cta; i++) { - warp_set_t at_a_specific_barrier = warps_in_cta & m_bar_id_to_warps[i]; - if (at_a_specific_barrier == active) { - // all warps have reached barrier, so release waiting warps... - m_bar_id_to_warps[i] &= ~at_a_specific_barrier; - m_warp_at_barrier &= ~at_a_specific_barrier; - } - } + // test for barrier release + cta_to_warp_t::iterator w=m_cta_to_warps.begin(); + for (; w != m_cta_to_warps.end(); ++w) { + if (w->second.test(warp_id) == true) break; + } + warp_set_t warps_in_cta = w->second; + warp_set_t active = warps_in_cta & m_warp_active; + + for(unsigned i=0; i<m_max_barriers_per_cta; i++){ + warp_set_t at_a_specific_barrier = warps_in_cta & m_bar_id_to_warps[i]; + if( at_a_specific_barrier == active ) { + // all warps have reached barrier, so release waiting warps... + m_bar_id_to_warps[i] &= ~at_a_specific_barrier; + m_warp_at_barrier &= ~at_a_specific_barrier; + } + } } // assertions -bool barrier_set_t::warp_waiting_at_barrier(unsigned warp_id) const { - return m_warp_at_barrier.test(warp_id); +bool barrier_set_t::warp_waiting_at_barrier( unsigned warp_id ) const +{ + return m_warp_at_barrier.test(warp_id); } -void barrier_set_t::dump() { - printf("barrier set information\n"); - printf(" m_max_cta_per_core = %u\n", m_max_cta_per_core); - printf(" m_max_warps_per_core = %u\n", m_max_warps_per_core); - printf(" m_max_barriers_per_cta =%u\n", m_max_barriers_per_cta); - printf(" cta_to_warps:\n"); - - cta_to_warp_t::const_iterator i; - for (i = m_cta_to_warps.begin(); i != m_cta_to_warps.end(); i++) { - unsigned cta_id = i->first; - warp_set_t warps = i->second; - printf(" cta_id %u : %s\n", cta_id, warps.to_string().c_str()); - } - printf(" warp_active: %s\n", m_warp_active.to_string().c_str()); - printf(" warp_at_barrier: %s\n", m_warp_at_barrier.to_string().c_str()); - for (unsigned i = 0; i < m_max_barriers_per_cta; i++) { - warp_set_t warps_reached_barrier = m_bar_id_to_warps[i]; - printf(" warp_at_barrier %u: %s\n", i, - warps_reached_barrier.to_string().c_str()); - } - fflush(stdout); +void barrier_set_t::dump() +{ + printf( "barrier set information\n"); + printf( " m_max_cta_per_core = %u\n", m_max_cta_per_core ); + printf( " m_max_warps_per_core = %u\n", m_max_warps_per_core ); + printf( " m_max_barriers_per_cta =%u\n", m_max_barriers_per_cta); + printf( " cta_to_warps:\n"); + + cta_to_warp_t::const_iterator i; + for( i=m_cta_to_warps.begin(); i!=m_cta_to_warps.end(); i++ ) { + unsigned cta_id = i->first; + warp_set_t warps = i->second; + printf(" cta_id %u : %s\n", cta_id, warps.to_string().c_str() ); + } + printf(" warp_active: %s\n", m_warp_active.to_string().c_str() ); + printf(" warp_at_barrier: %s\n", m_warp_at_barrier.to_string().c_str() ); + for( unsigned i=0; i<m_max_barriers_per_cta; i++){ + warp_set_t warps_reached_barrier = m_bar_id_to_warps[i]; + printf(" warp_at_barrier %u: %s\n", i, warps_reached_barrier.to_string().c_str() ); + } + fflush(stdout); } -void shader_core_ctx::warp_exit(unsigned warp_id) { - bool done = true; - for (unsigned i = warp_id * get_config()->warp_size; - i < (warp_id + 1) * get_config()->warp_size; i++) { - // if(this->m_thread[i]->m_functional_model_thread_state && - //this->m_thread[i].m_functional_model_thread_state->donecycle()==0) { - // done = false; - // } +void shader_core_ctx::warp_exit( unsigned warp_id ) +{ + bool done = true; + for ( unsigned i = warp_id*get_config()->warp_size; + i < (warp_id+1)*get_config()->warp_size; + i++ ) { - if (m_thread[i] && !m_thread[i]->is_done()) done = false; - } - // if (m_warp[warp_id].get_n_completed() == get_config()->warp_size) - // if (this->m_simt_stack[warp_id]->get_num_entries() == 0) - if (done) m_barriers.warp_exit(warp_id); +// if(this->m_thread[i]->m_functional_model_thread_state && this->m_thread[i].m_functional_model_thread_state->donecycle()==0) { +// done = false; +// } + + + if (m_thread[i] && !m_thread[i]->is_done()) done = false; + } + //if (m_warp[warp_id].get_n_completed() == get_config()->warp_size) + //if (this->m_simt_stack[warp_id]->get_num_entries() == 0) + if (done) + m_barriers.warp_exit( warp_id ); } -bool shader_core_ctx::check_if_non_released_reduction_barrier( - warp_inst_t &inst) { - unsigned warp_id = inst.warp_id(); - bool bar_red_op = (inst.op == BARRIER_OP) && (inst.bar_type == RED); - bool non_released_barrier_reduction = false; - bool warp_stucked_at_barrier = warp_waiting_at_barrier(warp_id); - bool single_inst_in_pipeline = - (m_warp[warp_id].num_issued_inst_in_pipeline() == 1); - non_released_barrier_reduction = - single_inst_in_pipeline and warp_stucked_at_barrier and bar_red_op; - printf("non_released_barrier_reduction=%u\n", non_released_barrier_reduction); - return non_released_barrier_reduction; +bool shader_core_ctx::check_if_non_released_reduction_barrier(warp_inst_t &inst) +{ + unsigned warp_id = inst.warp_id(); + bool bar_red_op = (inst.op == BARRIER_OP) && (inst.bar_type == RED); + bool non_released_barrier_reduction = false; + bool warp_stucked_at_barrier = warp_waiting_at_barrier(warp_id); + bool single_inst_in_pipeline = (m_warp[warp_id].num_issued_inst_in_pipeline()==1); + non_released_barrier_reduction = single_inst_in_pipeline and warp_stucked_at_barrier and bar_red_op; + printf("non_released_barrier_reduction=%u\n",non_released_barrier_reduction); + return non_released_barrier_reduction; } -bool shader_core_ctx::warp_waiting_at_barrier(unsigned warp_id) const { - return m_barriers.warp_waiting_at_barrier(warp_id); +bool shader_core_ctx::warp_waiting_at_barrier( unsigned warp_id ) const +{ + return m_barriers.warp_waiting_at_barrier(warp_id); } -bool shader_core_ctx::warp_waiting_at_mem_barrier(unsigned warp_id) { - if (!m_warp[warp_id].get_membar()) return false; - if (!m_scoreboard->pendingWrites(warp_id)) { - m_warp[warp_id].clear_membar(); - return false; - } - return true; +bool shader_core_ctx::warp_waiting_at_mem_barrier( unsigned warp_id ) +{ + if( !m_warp[warp_id].get_membar() ) + return false; + if( !m_scoreboard->pendingWrites(warp_id) ) { + m_warp[warp_id].clear_membar(); + return false; + } + return true; } -void shader_core_ctx::set_max_cta(const kernel_info_t &kernel) { - // calculate the max cta count and cta size for local memory address mapping - kernel_max_cta_per_shader = m_config->max_cta(kernel); - unsigned int gpu_cta_size = kernel.threads_per_cta(); - kernel_padded_threads_per_cta = - (gpu_cta_size % m_config->warp_size) - ? m_config->warp_size * ((gpu_cta_size / m_config->warp_size) + 1) - : gpu_cta_size; +void shader_core_ctx::set_max_cta( const kernel_info_t &kernel ) +{ + // calculate the max cta count and cta size for local memory address mapping + kernel_max_cta_per_shader = m_config->max_cta(kernel); + unsigned int gpu_cta_size = kernel.threads_per_cta(); + kernel_padded_threads_per_cta = (gpu_cta_size%m_config->warp_size) ? + m_config->warp_size*((gpu_cta_size/m_config->warp_size)+1) : + gpu_cta_size; } -void shader_core_ctx::decrement_atomic_count(unsigned wid, unsigned n) { - assert(m_warp[wid].get_n_atomic() >= n); - m_warp[wid].dec_n_atomic(n); +void shader_core_ctx::decrement_atomic_count( unsigned wid, unsigned n ) +{ + assert( m_warp[wid].get_n_atomic() >= n ); + m_warp[wid].dec_n_atomic(n); } -void shader_core_ctx::broadcast_barrier_reduction(unsigned cta_id, - unsigned bar_id, - warp_set_t warps) { - for (unsigned i = 0; i < m_config->max_warps_per_shader; i++) { - if (warps.test(i)) { - const warp_inst_t *inst = - m_warp[i].restore_info_of_last_inst_at_barrier(); - const_cast<warp_inst_t *>(inst)->broadcast_barrier_reduction( - inst->get_active_mask()); - } - } +void shader_core_ctx::broadcast_barrier_reduction(unsigned cta_id,unsigned bar_id,warp_set_t warps) +{ + for(unsigned i=0; i<m_config->max_warps_per_shader;i++){ + if(warps.test(i)){ + const warp_inst_t * inst = m_warp[i].restore_info_of_last_inst_at_barrier(); + const_cast<warp_inst_t *> (inst)->broadcast_barrier_reduction(inst->get_active_mask()); + } + } } -bool shader_core_ctx::fetch_unit_response_buffer_full() const { return false; } +bool shader_core_ctx::fetch_unit_response_buffer_full() const +{ + return false; +} -void shader_core_ctx::accept_fetch_response(mem_fetch *mf) { - mf->set_status(IN_SHADER_FETCHED, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - m_L1I->fill(mf, m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); +void shader_core_ctx::accept_fetch_response( mem_fetch *mf ) +{ + mf->set_status(IN_SHADER_FETCHED,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); + m_L1I->fill(mf,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); } -bool shader_core_ctx::ldst_unit_response_buffer_full() const { - return m_ldst_unit->response_buffer_full(); +bool shader_core_ctx::ldst_unit_response_buffer_full() const +{ + return m_ldst_unit->response_buffer_full(); } -void shader_core_ctx::accept_ldst_unit_response(mem_fetch *mf) { - m_ldst_unit->fill(mf); +void shader_core_ctx::accept_ldst_unit_response(mem_fetch * mf) +{ + m_ldst_unit->fill(mf); } -void shader_core_ctx::store_ack(class mem_fetch *mf) { - assert(mf->get_type() == WRITE_ACK || - (m_config->gpgpu_perfect_mem && mf->get_is_write())); - unsigned warp_id = mf->get_wid(); - m_warp[warp_id].dec_store_req(); +void shader_core_ctx::store_ack( class mem_fetch *mf ) +{ + assert( mf->get_type() == WRITE_ACK || ( m_config->gpgpu_perfect_mem && mf->get_is_write() ) ); + unsigned warp_id = mf->get_wid(); + m_warp[warp_id].dec_store_req(); } -void shader_core_ctx::print_cache_stats(FILE *fp, unsigned &dl1_accesses, - unsigned &dl1_misses) { - m_ldst_unit->print_cache_stats(fp, dl1_accesses, dl1_misses); +void shader_core_ctx::print_cache_stats( FILE *fp, unsigned& dl1_accesses, unsigned& dl1_misses ) { + m_ldst_unit->print_cache_stats( fp, dl1_accesses, dl1_misses ); } -void shader_core_ctx::get_cache_stats(cache_stats &cs) { - // Adds stats from each cache to 'cs' - cs += m_L1I->get_stats(); // Get L1I stats - m_ldst_unit->get_cache_stats(cs); // Get L1D, L1C, L1T stats +void shader_core_ctx::get_cache_stats(cache_stats &cs){ + // Adds stats from each cache to 'cs' + cs += m_L1I->get_stats(); // Get L1I stats + m_ldst_unit->get_cache_stats(cs); // Get L1D, L1C, L1T stats } -void shader_core_ctx::get_L1I_sub_stats(struct cache_sub_stats &css) const { - if (m_L1I) m_L1I->get_sub_stats(css); +void shader_core_ctx::get_L1I_sub_stats(struct cache_sub_stats &css) const{ + if(m_L1I) + m_L1I->get_sub_stats(css); } -void shader_core_ctx::get_L1D_sub_stats(struct cache_sub_stats &css) const { - m_ldst_unit->get_L1D_sub_stats(css); +void shader_core_ctx::get_L1D_sub_stats(struct cache_sub_stats &css) const{ + m_ldst_unit->get_L1D_sub_stats(css); } -void shader_core_ctx::get_L1C_sub_stats(struct cache_sub_stats &css) const { - m_ldst_unit->get_L1C_sub_stats(css); +void shader_core_ctx::get_L1C_sub_stats(struct cache_sub_stats &css) const{ + m_ldst_unit->get_L1C_sub_stats(css); } -void shader_core_ctx::get_L1T_sub_stats(struct cache_sub_stats &css) const { - m_ldst_unit->get_L1T_sub_stats(css); +void shader_core_ctx::get_L1T_sub_stats(struct cache_sub_stats &css) const{ + m_ldst_unit->get_L1T_sub_stats(css); } -void shader_core_ctx::get_icnt_power_stats(long &n_simt_to_mem, - long &n_mem_to_simt) const { - n_simt_to_mem += m_stats->n_simt_to_mem[m_sid]; - n_mem_to_simt += m_stats->n_mem_to_simt[m_sid]; +void shader_core_ctx::get_icnt_power_stats(long &n_simt_to_mem, long &n_mem_to_simt) const{ + n_simt_to_mem += m_stats->n_simt_to_mem[m_sid]; + n_mem_to_simt += m_stats->n_mem_to_simt[m_sid]; } -bool shd_warp_t::functional_done() const { - return get_n_completed() == m_warp_size; +bool shd_warp_t::functional_done() const +{ + return get_n_completed() == m_warp_size; } -bool shd_warp_t::hardware_done() const { - return functional_done() && stores_done() && !inst_in_pipeline(); +bool shd_warp_t::hardware_done() const +{ + return functional_done() && stores_done() && !inst_in_pipeline(); } -bool shd_warp_t::waiting() { - if (functional_done()) { - // waiting to be initialized with a kernel - return true; - } else if (m_shader->warp_waiting_at_barrier(m_warp_id)) { - // waiting for other warps in CTA to reach barrier - return true; - } else if (m_shader->warp_waiting_at_mem_barrier(m_warp_id)) { - // waiting for memory barrier - return true; - } else if (m_n_atomic > 0) { - // waiting for atomic operation to complete at memory: - // this stall is not required for accurate timing model, but rather we - // stall here since if a call/return instruction occurs in the meantime - // the functional execution of the atomic when it hits DRAM can cause - // the wrong register to be read. - return true; - } - return false; +bool shd_warp_t::waiting() +{ + if ( functional_done() ) { + // waiting to be initialized with a kernel + return true; + } else if ( m_shader->warp_waiting_at_barrier(m_warp_id) ) { + // waiting for other warps in CTA to reach barrier + return true; + } else if ( m_shader->warp_waiting_at_mem_barrier(m_warp_id) ) { + // waiting for memory barrier + return true; + } else if ( m_n_atomic >0 ) { + // waiting for atomic operation to complete at memory: + // this stall is not required for accurate timing model, but rather we + // stall here since if a call/return instruction occurs in the meantime + // the functional execution of the atomic when it hits DRAM can cause + // the wrong register to be read. + return true; + } + return false; } -void shd_warp_t::print(FILE *fout) const { - if (!done_exit()) { - fprintf(fout, "w%02u npc: 0x%04x, done:%c%c%c%c:%2u i:%u s:%u a:%u (done: ", - m_warp_id, m_next_pc, (functional_done() ? 'f' : ' '), - (stores_done() ? 's' : ' '), (inst_in_pipeline() ? ' ' : 'i'), - (done_exit() ? 'e' : ' '), n_completed, m_inst_in_pipeline, - m_stores_outstanding, m_n_atomic); - for (unsigned i = m_warp_id * m_warp_size; - i < (m_warp_id + 1) * m_warp_size; i++) { - if (m_shader->ptx_thread_done(i)) - fprintf(fout, "1"); - else - fprintf(fout, "0"); - if ((((i + 1) % 4) == 0) && (i + 1) < (m_warp_id + 1) * m_warp_size) - fprintf(fout, ","); +void shd_warp_t::print( FILE *fout ) const +{ + if( !done_exit() ) { + fprintf( fout, "w%02u npc: 0x%04x, done:%c%c%c%c:%2u i:%u s:%u a:%u (done: ", + m_warp_id, + m_next_pc, + (functional_done()?'f':' '), + (stores_done()?'s':' '), + (inst_in_pipeline()?' ':'i'), + (done_exit()?'e':' '), + n_completed, + m_inst_in_pipeline, + m_stores_outstanding, + m_n_atomic ); + for (unsigned i = m_warp_id*m_warp_size; i < (m_warp_id+1)*m_warp_size; i++ ) { + if ( m_shader->ptx_thread_done(i) ) fprintf(fout,"1"); + else fprintf(fout,"0"); + if ( (((i+1)%4) == 0) && (i+1) < (m_warp_id+1)*m_warp_size ) + fprintf(fout,","); + } + fprintf(fout,") "); + fprintf(fout," active=%s", m_active_threads.to_string().c_str() ); + fprintf(fout," last fetched @ %5llu", m_last_fetch); + if( m_imiss_pending ) + fprintf(fout," i-miss pending"); + fprintf(fout,"\n"); } - fprintf(fout, ") "); - fprintf(fout, " active=%s", m_active_threads.to_string().c_str()); - fprintf(fout, " last fetched @ %5llu", m_last_fetch); - if (m_imiss_pending) fprintf(fout, " i-miss pending"); - fprintf(fout, "\n"); - } } -void shd_warp_t::print_ibuffer(FILE *fout) const { - fprintf(fout, " ibuffer[%2u] : ", m_warp_id); - for (unsigned i = 0; i < IBUFFER_SIZE; i++) { - const inst_t *inst = m_ibuffer[i].m_inst; - if (inst) - inst->print_insn(fout); - else if (m_ibuffer[i].m_valid) - fprintf(fout, " <invalid instruction> "); - else - fprintf(fout, " <empty> "); - } - fprintf(fout, "\n"); +void shd_warp_t::print_ibuffer( FILE *fout ) const +{ + fprintf(fout," ibuffer[%2u] : ", m_warp_id ); + for( unsigned i=0; i < IBUFFER_SIZE; i++) { + const inst_t *inst = m_ibuffer[i].m_inst; + if( inst ) inst->print_insn(fout); + else if( m_ibuffer[i].m_valid ) + fprintf(fout," <invalid instruction> "); + else fprintf(fout," <empty> "); + } + fprintf(fout,"\n"); } -void opndcoll_rfu_t::add_cu_set(unsigned set_id, unsigned num_cu, - unsigned num_dispatch) { - m_cus[set_id].reserve(num_cu); // this is necessary to stop pointers in m_cu - // from being invalid do to a resize; - for (unsigned i = 0; i < num_cu; i++) { - m_cus[set_id].push_back(collector_unit_t()); - m_cu.push_back(&m_cus[set_id].back()); - } - // for now each collector set gets dedicated dispatch units. - for (unsigned i = 0; i < num_dispatch; i++) { - m_dispatch_units.push_back(dispatch_unit_t(&m_cus[set_id])); - } +void opndcoll_rfu_t::add_cu_set(unsigned set_id, unsigned num_cu, unsigned num_dispatch){ + m_cus[set_id].reserve(num_cu); //this is necessary to stop pointers in m_cu from being invalid do to a resize; + for (unsigned i = 0; i < num_cu; i++) { + m_cus[set_id].push_back(collector_unit_t()); + m_cu.push_back(&m_cus[set_id].back()); + } + // for now each collector set gets dedicated dispatch units. + for (unsigned i = 0; i < num_dispatch; i++) { + m_dispatch_units.push_back(dispatch_unit_t(&m_cus[set_id])); + } } -void opndcoll_rfu_t::add_port(port_vector_t &input, port_vector_t &output, - uint_vector_t cu_sets) { - // m_num_ports++; - // m_num_collectors += num_collector_units; - // m_input.resize(m_num_ports); - // m_output.resize(m_num_ports); - // m_num_collector_units.resize(m_num_ports); - // m_input[m_num_ports-1]=input_port; - // m_output[m_num_ports-1]=output_port; - // m_num_collector_units[m_num_ports-1]=num_collector_units; - m_in_ports.push_back(input_port_t(input, output, cu_sets)); + +void opndcoll_rfu_t::add_port(port_vector_t & input, port_vector_t & output, uint_vector_t cu_sets) +{ + //m_num_ports++; + //m_num_collectors += num_collector_units; + //m_input.resize(m_num_ports); + //m_output.resize(m_num_ports); + //m_num_collector_units.resize(m_num_ports); + //m_input[m_num_ports-1]=input_port; + //m_output[m_num_ports-1]=output_port; + //m_num_collector_units[m_num_ports-1]=num_collector_units; + m_in_ports.push_back(input_port_t(input,output,cu_sets)); } -void opndcoll_rfu_t::init(unsigned num_banks, shader_core_ctx *shader) { - m_shader = shader; - m_arbiter.init(m_cu.size(), num_banks); - // for( unsigned n=0; n<m_num_ports;n++ ) - // m_dispatch_units[m_output[n]].init( m_num_collector_units[n] ); - m_num_banks = num_banks; - m_bank_warp_shift = 0; - m_warp_size = shader->get_config()->warp_size; - m_bank_warp_shift = (unsigned)(int)(log(m_warp_size + 0.5) / log(2.0)); - assert((m_bank_warp_shift == 5) || (m_warp_size != 32)); +void opndcoll_rfu_t::init( unsigned num_banks, shader_core_ctx *shader ) +{ + m_shader=shader; + m_arbiter.init(m_cu.size(),num_banks); + //for( unsigned n=0; n<m_num_ports;n++ ) + // m_dispatch_units[m_output[n]].init( m_num_collector_units[n] ); + m_num_banks = num_banks; + m_bank_warp_shift = 0; + m_warp_size = shader->get_config()->warp_size; + m_bank_warp_shift = (unsigned)(int) (log(m_warp_size+0.5) / log(2.0)); + assert( (m_bank_warp_shift == 5) || (m_warp_size != 32) ); + + sub_core_model = shader->get_config()->sub_core_model; + m_num_warp_sceds = shader->get_config()->gpgpu_num_sched_per_core; + if(sub_core_model) + assert(num_banks % shader->get_config()->gpgpu_num_sched_per_core == 0); + m_num_banks_per_sched = num_banks / shader->get_config()->gpgpu_num_sched_per_core; + + for( unsigned j=0; j<m_cu.size(); j++) { + m_cu[j]->init(j,num_banks,m_bank_warp_shift,shader->get_config(),this, sub_core_model, m_num_banks_per_sched ); + } + m_initialized=true; + + - sub_core_model = shader->get_config()->sub_core_model; - m_num_warp_sceds = shader->get_config()->gpgpu_num_sched_per_core; - if (sub_core_model) - assert(num_banks % shader->get_config()->gpgpu_num_sched_per_core == 0); - m_num_banks_per_sched = - num_banks / shader->get_config()->gpgpu_num_sched_per_core; - for (unsigned j = 0; j < m_cu.size(); j++) { - m_cu[j]->init(j, num_banks, m_bank_warp_shift, shader->get_config(), this, - sub_core_model, m_num_banks_per_sched); - } - m_initialized = true; } -int register_bank(int regnum, int wid, unsigned num_banks, - unsigned bank_warp_shift, bool sub_core_model, - unsigned banks_per_sched, unsigned sched_id) { - int bank = regnum; - if (bank_warp_shift) bank += wid; - if (sub_core_model) { - unsigned bank_num = (bank % banks_per_sched) + (sched_id * banks_per_sched); - assert(bank_num < num_banks); - return bank_num; - } else - return bank % num_banks; +int register_bank(int regnum, int wid, unsigned num_banks, unsigned bank_warp_shift, bool sub_core_model, unsigned banks_per_sched, unsigned sched_id) +{ + int bank = regnum; + if (bank_warp_shift) + bank += wid; + if(sub_core_model) { + unsigned bank_num = (bank % banks_per_sched) + (sched_id * banks_per_sched); + assert(bank_num < num_banks); + return bank_num; + } + else + return bank % num_banks; } -bool opndcoll_rfu_t::writeback(warp_inst_t &inst) { - assert(!inst.empty()); - std::list<unsigned> regs = m_shader->get_regs_written(inst); - for (unsigned op = 0; op < MAX_REG_OPERANDS; op++) { - int reg_num = inst.arch_reg.dst[op]; // this math needs to match that used - // in function_info::ptx_decode_inst - if (reg_num >= 0) { // valid register - unsigned bank = register_bank(reg_num, inst.warp_id(), m_num_banks, - m_bank_warp_shift, sub_core_model, - m_num_banks_per_sched, inst.get_schd_id()); - if (m_arbiter.bank_idle(bank)) { - m_arbiter.allocate_bank_for_write( - bank, - op_t(&inst, reg_num, m_num_banks, m_bank_warp_shift, sub_core_model, - m_num_banks_per_sched, inst.get_schd_id())); - inst.arch_reg.dst[op] = -1; - } else { - return false; +bool opndcoll_rfu_t::writeback( warp_inst_t &inst ) +{ + assert( !inst.empty() ); + std::list<unsigned> regs = m_shader->get_regs_written(inst); + for( unsigned op=0; op < MAX_REG_OPERANDS; op++ ) { + int reg_num = inst.arch_reg.dst[op]; // this math needs to match that used in function_info::ptx_decode_inst + if( reg_num >= 0 ){ // valid register + unsigned bank = register_bank(reg_num,inst.warp_id(),m_num_banks,m_bank_warp_shift, sub_core_model, m_num_banks_per_sched, inst.get_schd_id()); + if( m_arbiter.bank_idle(bank) ) { + m_arbiter.allocate_bank_for_write(bank,op_t(&inst,reg_num,m_num_banks,m_bank_warp_shift, sub_core_model, m_num_banks_per_sched, inst.get_schd_id())); + inst.arch_reg.dst[op] = -1; + } else { + return false; + } } - } - } - for (unsigned i = 0; i < (unsigned)regs.size(); i++) { - if (m_shader->get_config()->gpgpu_clock_gated_reg_file) { - unsigned active_count = 0; - for (unsigned i = 0; i < m_shader->get_config()->warp_size; - i = i + m_shader->get_config()->n_regfile_gating_group) { - for (unsigned j = 0; j < m_shader->get_config()->n_regfile_gating_group; - j++) { - if (inst.get_active_mask().test(i + j)) { - active_count += m_shader->get_config()->n_regfile_gating_group; - break; - } - } + } + for(unsigned i=0;i<(unsigned)regs.size();i++){ + if(m_shader->get_config()->gpgpu_clock_gated_reg_file){ + unsigned active_count=0; + for(unsigned i=0;i<m_shader->get_config()->warp_size;i=i+m_shader->get_config()->n_regfile_gating_group){ + for(unsigned j=0;j<m_shader->get_config()->n_regfile_gating_group;j++){ + if(inst.get_active_mask().test(i+j)){ + active_count+=m_shader->get_config()->n_regfile_gating_group; + break; + } + } + } + m_shader->incregfile_writes(active_count); + }else{ + m_shader->incregfile_writes(m_shader->get_config()->warp_size);//inst.active_count()); + } + } + return true; +} + +void opndcoll_rfu_t::dispatch_ready_cu() +{ + for( unsigned p=0; p < m_dispatch_units.size(); ++p ) { + dispatch_unit_t &du = m_dispatch_units[p]; + collector_unit_t *cu = du.find_ready(); + if( cu ) { + for(unsigned i=0;i<(cu->get_num_operands()-cu->get_num_regs());i++){ + if(m_shader->get_config()->gpgpu_clock_gated_reg_file){ + unsigned active_count=0; + for(unsigned i=0;i<m_shader->get_config()->warp_size;i=i+m_shader->get_config()->n_regfile_gating_group){ + for(unsigned j=0;j<m_shader->get_config()->n_regfile_gating_group;j++){ + if(cu->get_active_mask().test(i+j)){ + active_count+=m_shader->get_config()->n_regfile_gating_group; + break; + } + } + } + m_shader->incnon_rf_operands(active_count); + }else{ + m_shader->incnon_rf_operands(m_shader->get_config()->warp_size);//cu->get_active_count()); + } + } + cu->dispatch(); } - m_shader->incregfile_writes(active_count); - } else { - m_shader->incregfile_writes( - m_shader->get_config()->warp_size); // inst.active_count()); - } - } - return true; + } } -void opndcoll_rfu_t::dispatch_ready_cu() { - for (unsigned p = 0; p < m_dispatch_units.size(); ++p) { - dispatch_unit_t &du = m_dispatch_units[p]; - collector_unit_t *cu = du.find_ready(); - if (cu) { - for (unsigned i = 0; i < (cu->get_num_operands() - cu->get_num_regs()); - i++) { - if (m_shader->get_config()->gpgpu_clock_gated_reg_file) { - unsigned active_count = 0; - for (unsigned i = 0; i < m_shader->get_config()->warp_size; - i = i + m_shader->get_config()->n_regfile_gating_group) { - for (unsigned j = 0; - j < m_shader->get_config()->n_regfile_gating_group; j++) { - if (cu->get_active_mask().test(i + j)) { - active_count += m_shader->get_config()->n_regfile_gating_group; - break; +void opndcoll_rfu_t::allocate_cu( unsigned port_num ) +{ + input_port_t& inp = m_in_ports[port_num]; + for (unsigned i = 0; i < inp.m_in.size(); i++) { + if( (*inp.m_in[i]).has_ready() ) { + //find a free cu + for (unsigned j = 0; j < inp.m_cu_sets.size(); j++) { + std::vector<collector_unit_t> & cu_set = m_cus[inp.m_cu_sets[j]]; + bool allocated = false; + for (unsigned k = 0; k < cu_set.size(); k++) { + if(cu_set[k].is_free()) { + collector_unit_t *cu = &cu_set[k]; + allocated = cu->allocate(inp.m_in[i],inp.m_out[i]); + m_arbiter.add_read_requests(cu); + break; + } } - } + if (allocated) break; //cu has been allocated, no need to search more. } - m_shader->incnon_rf_operands(active_count); - } else { - m_shader->incnon_rf_operands( - m_shader->get_config()->warp_size); // cu->get_active_count()); - } - } - cu->dispatch(); - } - } + break; // can only service a single input, if it failed it will fail for others. + } + } } -void opndcoll_rfu_t::allocate_cu(unsigned port_num) { - input_port_t &inp = m_in_ports[port_num]; - for (unsigned i = 0; i < inp.m_in.size(); i++) { - if ((*inp.m_in[i]).has_ready()) { - // find a free cu - for (unsigned j = 0; j < inp.m_cu_sets.size(); j++) { - std::vector<collector_unit_t> &cu_set = m_cus[inp.m_cu_sets[j]]; - bool allocated = false; - for (unsigned k = 0; k < cu_set.size(); k++) { - if (cu_set[k].is_free()) { - collector_unit_t *cu = &cu_set[k]; - allocated = cu->allocate(inp.m_in[i], inp.m_out[i]); - m_arbiter.add_read_requests(cu); - break; - } - } - if (allocated) break; // cu has been allocated, no need to search more. +void opndcoll_rfu_t::allocate_reads() +{ + // process read requests that do not have conflicts + std::list<op_t> allocated = m_arbiter.allocate_reads(); + std::map<unsigned,op_t> read_ops; + for( std::list<op_t>::iterator r=allocated.begin(); r!=allocated.end(); r++ ) { + const op_t &rr = *r; + unsigned reg = rr.get_reg(); + unsigned wid = rr.get_wid(); + unsigned bank = register_bank(reg,wid,m_num_banks,m_bank_warp_shift,sub_core_model, m_num_banks_per_sched, rr.get_sid()); + m_arbiter.allocate_for_read(bank,rr); + read_ops[bank] = rr; + } + std::map<unsigned,op_t>::iterator r; + for(r=read_ops.begin();r!=read_ops.end();++r ) { + op_t &op = r->second; + unsigned cu = op.get_oc_id(); + unsigned operand = op.get_operand(); + m_cu[cu]->collect_operand(operand); + if(m_shader->get_config()->gpgpu_clock_gated_reg_file){ + unsigned active_count=0; + for(unsigned i=0;i<m_shader->get_config()->warp_size;i=i+m_shader->get_config()->n_regfile_gating_group){ + for(unsigned j=0;j<m_shader->get_config()->n_regfile_gating_group;j++){ + if(op.get_active_mask().test(i+j)){ + active_count+=m_shader->get_config()->n_regfile_gating_group; + break; + } + } + } + m_shader->incregfile_reads(active_count); + }else{ + m_shader->incregfile_reads(m_shader->get_config()->warp_size);//op.get_active_count()); } - break; // can only service a single input, if it failed it will fail for - // others. - } } +} + +bool opndcoll_rfu_t::collector_unit_t::ready() const +{ + return (!m_free) && m_not_ready.none() && (*m_output_register).has_free(); } -void opndcoll_rfu_t::allocate_reads() { - // process read requests that do not have conflicts - std::list<op_t> allocated = m_arbiter.allocate_reads(); - std::map<unsigned, op_t> read_ops; - for (std::list<op_t>::iterator r = allocated.begin(); r != allocated.end(); - r++) { - const op_t &rr = *r; - unsigned reg = rr.get_reg(); - unsigned wid = rr.get_wid(); - unsigned bank = - register_bank(reg, wid, m_num_banks, m_bank_warp_shift, sub_core_model, - m_num_banks_per_sched, rr.get_sid()); - m_arbiter.allocate_for_read(bank, rr); - read_ops[bank] = rr; - } - std::map<unsigned, op_t>::iterator r; - for (r = read_ops.begin(); r != read_ops.end(); ++r) { - op_t &op = r->second; - unsigned cu = op.get_oc_id(); - unsigned operand = op.get_operand(); - m_cu[cu]->collect_operand(operand); - if (m_shader->get_config()->gpgpu_clock_gated_reg_file) { - unsigned active_count = 0; - for (unsigned i = 0; i < m_shader->get_config()->warp_size; - i = i + m_shader->get_config()->n_regfile_gating_group) { - for (unsigned j = 0; j < m_shader->get_config()->n_regfile_gating_group; - j++) { - if (op.get_active_mask().test(i + j)) { - active_count += m_shader->get_config()->n_regfile_gating_group; - break; - } - } +void opndcoll_rfu_t::collector_unit_t::dump(FILE *fp, const shader_core_ctx *shader ) const +{ + if( m_free ) { + fprintf(fp," <free>\n"); + } else { + m_warp->print(fp); + for( unsigned i=0; i < MAX_REG_OPERANDS*2; i++ ) { + if( m_not_ready.test(i) ) { + std::string r = m_src_op[i].get_reg_string(); + fprintf(fp," '%s' not ready\n", r.c_str() ); + } } - m_shader->incregfile_reads(active_count); - } else { - m_shader->incregfile_reads( - m_shader->get_config()->warp_size); // op.get_active_count()); - } - } + } } -bool opndcoll_rfu_t::collector_unit_t::ready() const { - return (!m_free) && m_not_ready.none() && (*m_output_register).has_free(); +void opndcoll_rfu_t::collector_unit_t::init( unsigned n, + unsigned num_banks, + unsigned log2_warp_size, + const core_config *config, + opndcoll_rfu_t *rfu, + bool sub_core_model, + unsigned banks_per_sched) +{ + m_rfu=rfu; + m_cuid=n; + m_num_banks=num_banks; + assert(m_warp==NULL); + m_warp = new warp_inst_t(config); + m_bank_warp_shift=log2_warp_size; + m_sub_core_model = sub_core_model; + m_num_banks_per_sched = banks_per_sched; } -void opndcoll_rfu_t::collector_unit_t::dump( - FILE *fp, const shader_core_ctx *shader) const { - if (m_free) { - fprintf(fp, " <free>\n"); - } else { - m_warp->print(fp); - for (unsigned i = 0; i < MAX_REG_OPERANDS * 2; i++) { - if (m_not_ready.test(i)) { - std::string r = m_src_op[i].get_reg_string(); - fprintf(fp, " '%s' not ready\n", r.c_str()); +bool opndcoll_rfu_t::collector_unit_t::allocate( register_set* pipeline_reg_set, register_set* output_reg_set ) +{ + assert(m_free); + assert(m_not_ready.none()); + m_free = false; + m_output_register = output_reg_set; + warp_inst_t **pipeline_reg = pipeline_reg_set->get_ready(); + if( (pipeline_reg) and !((*pipeline_reg)->empty()) ) { + m_warp_id = (*pipeline_reg)->warp_id(); + for( unsigned op=0; op < MAX_REG_OPERANDS; op++ ) { + int reg_num = (*pipeline_reg)->arch_reg.src[op]; // this math needs to match that used in function_info::ptx_decode_inst + if( reg_num >= 0 ) { // valid register + m_src_op[op] = op_t( this, op, reg_num, m_num_banks, m_bank_warp_shift, m_sub_core_model, m_num_banks_per_sched, (*pipeline_reg)->get_schd_id() ); + m_not_ready.set(op); + } else + m_src_op[op] = op_t(); } - } - } + //move_warp(m_warp,*pipeline_reg); + pipeline_reg_set->move_out_to(m_warp); + return true; + } + return false; } -void opndcoll_rfu_t::collector_unit_t::init(unsigned n, unsigned num_banks, - unsigned log2_warp_size, - const core_config *config, - opndcoll_rfu_t *rfu, - bool sub_core_model, - unsigned banks_per_sched) { - m_rfu = rfu; - m_cuid = n; - m_num_banks = num_banks; - assert(m_warp == NULL); - m_warp = new warp_inst_t(config); - m_bank_warp_shift = log2_warp_size; - m_sub_core_model = sub_core_model; - m_num_banks_per_sched = banks_per_sched; +void opndcoll_rfu_t::collector_unit_t::dispatch() +{ + assert( m_not_ready.none() ); + //move_warp(*m_output_register,m_warp); + m_output_register->move_in(m_warp); + m_free=true; + m_output_register = NULL; + for( unsigned i=0; i<MAX_REG_OPERANDS*2;i++) + m_src_op[i].reset(); } -bool opndcoll_rfu_t::collector_unit_t::allocate(register_set *pipeline_reg_set, - register_set *output_reg_set) { - assert(m_free); - assert(m_not_ready.none()); - m_free = false; - m_output_register = output_reg_set; - warp_inst_t **pipeline_reg = pipeline_reg_set->get_ready(); - if ((pipeline_reg) and !((*pipeline_reg)->empty())) { - m_warp_id = (*pipeline_reg)->warp_id(); - for (unsigned op = 0; op < MAX_REG_OPERANDS; op++) { - int reg_num = - (*pipeline_reg)->arch_reg.src[op]; // this math needs to match that - // used in - // function_info::ptx_decode_inst - if (reg_num >= 0) { // valid register - m_src_op[op] = op_t(this, op, reg_num, m_num_banks, m_bank_warp_shift, - m_sub_core_model, m_num_banks_per_sched, - (*pipeline_reg)->get_schd_id()); - m_not_ready.set(op); - } else - m_src_op[op] = op_t(); +simt_core_cluster::simt_core_cluster( class gpgpu_sim *gpu, + unsigned cluster_id, + const shader_core_config *config, + const memory_config *mem_config, + shader_core_stats *stats, + class memory_stats_t *mstats ) +{ + m_config = config; + m_cta_issue_next_core=m_config->n_simt_cores_per_cluster-1; // this causes first launch to use hw cta 0 + m_cluster_id=cluster_id; + m_gpu = gpu; + m_stats = stats; + m_memory_stats = mstats; + m_core = new shader_core_ctx*[ config->n_simt_cores_per_cluster ]; + for( unsigned i=0; i < config->n_simt_cores_per_cluster; i++ ) { + unsigned sid = m_config->cid_to_sid(i,m_cluster_id); + m_core[i] = new shader_core_ctx(gpu,this,sid,m_cluster_id,config,mem_config,stats); + m_core_sim_order.push_back(i); } - // move_warp(m_warp,*pipeline_reg); - pipeline_reg_set->move_out_to(m_warp); - return true; - } - return false; } -void opndcoll_rfu_t::collector_unit_t::dispatch() { - assert(m_not_ready.none()); - // move_warp(*m_output_register,m_warp); - m_output_register->move_in(m_warp); - m_free = true; - m_output_register = NULL; - for (unsigned i = 0; i < MAX_REG_OPERANDS * 2; i++) m_src_op[i].reset(); -} +void simt_core_cluster::core_cycle() +{ + for( std::list<unsigned>::iterator it = m_core_sim_order.begin(); it != m_core_sim_order.end(); ++it ) { + m_core[*it]->cycle(); + } -simt_core_cluster::simt_core_cluster(class gpgpu_sim *gpu, unsigned cluster_id, - const shader_core_config *config, - const memory_config *mem_config, - shader_core_stats *stats, - class memory_stats_t *mstats) { - m_config = config; - m_cta_issue_next_core = m_config->n_simt_cores_per_cluster - - 1; // this causes first launch to use hw cta 0 - m_cluster_id = cluster_id; - m_gpu = gpu; - m_stats = stats; - m_memory_stats = mstats; - m_core = new shader_core_ctx *[config->n_simt_cores_per_cluster]; - for (unsigned i = 0; i < config->n_simt_cores_per_cluster; i++) { - unsigned sid = m_config->cid_to_sid(i, m_cluster_id); - m_core[i] = new shader_core_ctx(gpu, this, sid, m_cluster_id, config, - mem_config, stats); - m_core_sim_order.push_back(i); - } + if (m_config->simt_core_sim_order == 1) { + m_core_sim_order.splice(m_core_sim_order.end(), m_core_sim_order, m_core_sim_order.begin()); + } } -void simt_core_cluster::core_cycle() { - for (std::list<unsigned>::iterator it = m_core_sim_order.begin(); - it != m_core_sim_order.end(); ++it) { - m_core[*it]->cycle(); - } - - if (m_config->simt_core_sim_order == 1) { - m_core_sim_order.splice(m_core_sim_order.end(), m_core_sim_order, - m_core_sim_order.begin()); - } +void simt_core_cluster::reinit() +{ + for( unsigned i=0; i < m_config->n_simt_cores_per_cluster; i++ ) + m_core[i]->reinit(0,m_config->n_thread_per_shader,true); } -void simt_core_cluster::reinit() { - for (unsigned i = 0; i < m_config->n_simt_cores_per_cluster; i++) - m_core[i]->reinit(0, m_config->n_thread_per_shader, true); +unsigned simt_core_cluster::max_cta( const kernel_info_t &kernel ) +{ + return m_config->n_simt_cores_per_cluster * m_config->max_cta(kernel); } -unsigned simt_core_cluster::max_cta(const kernel_info_t &kernel) { - return m_config->n_simt_cores_per_cluster * m_config->max_cta(kernel); +unsigned simt_core_cluster::get_not_completed() const +{ + unsigned not_completed=0; + for( unsigned i=0; i < m_config->n_simt_cores_per_cluster; i++ ) + not_completed += m_core[i]->get_not_completed(); + return not_completed; } -unsigned simt_core_cluster::get_not_completed() const { - unsigned not_completed = 0; - for (unsigned i = 0; i < m_config->n_simt_cores_per_cluster; i++) - not_completed += m_core[i]->get_not_completed(); - return not_completed; +void simt_core_cluster::print_not_completed( FILE *fp ) const +{ + for( unsigned i=0; i < m_config->n_simt_cores_per_cluster; i++ ) { + unsigned not_completed=m_core[i]->get_not_completed(); + unsigned sid=m_config->cid_to_sid(i,m_cluster_id); + fprintf(fp,"%u(%u) ", sid, not_completed ); + } } -void simt_core_cluster::print_not_completed(FILE *fp) const { - for (unsigned i = 0; i < m_config->n_simt_cores_per_cluster; i++) { - unsigned not_completed = m_core[i]->get_not_completed(); - unsigned sid = m_config->cid_to_sid(i, m_cluster_id); - fprintf(fp, "%u(%u) ", sid, not_completed); - } -} -float simt_core_cluster::get_current_occupancy( - unsigned long long &active, unsigned long long &total) const { - float aggregate = 0.f; - for (unsigned i = 0; i < m_config->n_simt_cores_per_cluster; i++) { - aggregate += m_core[i]->get_current_occupancy(active, total); - } - return aggregate / m_config->n_simt_cores_per_cluster; +float simt_core_cluster::get_current_occupancy( unsigned long long& active, unsigned long long& total ) const { + float aggregate = 0.f; + for( unsigned i=0; i < m_config->n_simt_cores_per_cluster; i++ ) { + aggregate+=m_core[i]->get_current_occupancy( active, total ); + } + return aggregate / m_config->n_simt_cores_per_cluster; } -unsigned simt_core_cluster::get_n_active_cta() const { - unsigned n = 0; - for (unsigned i = 0; i < m_config->n_simt_cores_per_cluster; i++) - n += m_core[i]->get_n_active_cta(); - return n; +unsigned simt_core_cluster::get_n_active_cta() const +{ + unsigned n=0; + for( unsigned i=0; i < m_config->n_simt_cores_per_cluster; i++ ) + n += m_core[i]->get_n_active_cta(); + return n; } -unsigned simt_core_cluster::get_n_active_sms() const { - unsigned n = 0; - for (unsigned i = 0; i < m_config->n_simt_cores_per_cluster; i++) - n += m_core[i]->isactive(); - return n; +unsigned simt_core_cluster::get_n_active_sms() const +{ + unsigned n=0; + for( unsigned i=0; i < m_config->n_simt_cores_per_cluster; i++ ) + n += m_core[i]->isactive(); + return n; } -unsigned simt_core_cluster::issue_block2core() { - unsigned num_blocks_issued = 0; - for (unsigned i = 0; i < m_config->n_simt_cores_per_cluster; i++) { - unsigned core = - (i + m_cta_issue_next_core + 1) % m_config->n_simt_cores_per_cluster; +unsigned simt_core_cluster::issue_block2core() +{ + unsigned num_blocks_issued=0; + for( unsigned i=0; i < m_config->n_simt_cores_per_cluster; i++ ) { + unsigned core = (i+m_cta_issue_next_core+1)%m_config->n_simt_cores_per_cluster; - kernel_info_t *kernel; - // Jin: fetch kernel according to concurrent kernel setting - if (m_config->gpgpu_concurrent_kernel_sm) { // concurrent kernel on sm - // always select latest issued kernel - kernel_info_t *k = m_gpu->select_kernel(); - kernel = k; - } else { - // first select core kernel, if no more cta, get a new kernel - // only when core completes - kernel = m_core[core]->get_kernel(); - if (!m_gpu->kernel_more_cta_left(kernel)) { - // wait till current kernel finishes - if (m_core[core]->get_not_completed() == 0) { - kernel_info_t *k = m_gpu->select_kernel(); - if (k) m_core[core]->set_kernel(k); - kernel = k; + kernel_info_t * kernel; + //Jin: fetch kernel according to concurrent kernel setting + if(m_config->gpgpu_concurrent_kernel_sm) {//concurrent kernel on sm + //always select latest issued kernel + kernel_info_t *k = m_gpu->select_kernel(); + kernel = k; + } + else { + //first select core kernel, if no more cta, get a new kernel + //only when core completes + kernel = m_core[core]->get_kernel(); + if( !m_gpu->kernel_more_cta_left(kernel) ) { + //wait till current kernel finishes + if(m_core[core]->get_not_completed() == 0) + { + kernel_info_t *k = m_gpu->select_kernel(); + if( k ) + m_core[core]->set_kernel(k); + kernel = k; + } + } } - } - } - if (m_gpu->kernel_more_cta_left(kernel) && - // (m_core[core]->get_n_active_cta() < - // m_config->max_cta(*kernel)) ) { - m_core[core]->can_issue_1block(*kernel)) { - m_core[core]->issue_block2core(*kernel); - num_blocks_issued++; - m_cta_issue_next_core = core; - break; + if( m_gpu->kernel_more_cta_left(kernel) && +// (m_core[core]->get_n_active_cta() < m_config->max_cta(*kernel)) ) { + m_core[core]->can_issue_1block(*kernel)) { + m_core[core]->issue_block2core(*kernel); + num_blocks_issued++; + m_cta_issue_next_core=core; + break; + } } - } - return num_blocks_issued; + return num_blocks_issued; } -void simt_core_cluster::cache_flush() { - for (unsigned i = 0; i < m_config->n_simt_cores_per_cluster; i++) - m_core[i]->cache_flush(); +void simt_core_cluster::cache_flush() +{ + for( unsigned i=0; i < m_config->n_simt_cores_per_cluster; i++ ) + m_core[i]->cache_flush(); } -void simt_core_cluster::cache_invalidate() { - for (unsigned i = 0; i < m_config->n_simt_cores_per_cluster; i++) - m_core[i]->cache_invalidate(); +void simt_core_cluster::cache_invalidate() +{ + for( unsigned i=0; i < m_config->n_simt_cores_per_cluster; i++ ) + m_core[i]->cache_invalidate(); } -bool simt_core_cluster::icnt_injection_buffer_full(unsigned size, bool write) { - unsigned request_size = size; - if (!write) request_size = READ_PACKET_SIZE; - return !::icnt_has_buffer(m_cluster_id, request_size); +bool simt_core_cluster::icnt_injection_buffer_full(unsigned size, bool write) +{ + unsigned request_size = size; + if (!write) + request_size = READ_PACKET_SIZE; + return ! ::icnt_has_buffer(m_cluster_id, request_size); } -void simt_core_cluster::icnt_inject_request_packet(class mem_fetch *mf) { - // stats - if (mf->get_is_write()) - m_stats->made_write_mfs++; - else - m_stats->made_read_mfs++; - switch (mf->get_access_type()) { - case CONST_ACC_R: - m_stats->gpgpu_n_mem_const++; - break; - case TEXTURE_ACC_R: - m_stats->gpgpu_n_mem_texture++; - break; - case GLOBAL_ACC_R: - m_stats->gpgpu_n_mem_read_global++; - break; - // case GLOBAL_ACC_R: m_stats->gpgpu_n_mem_read_global++; - // printf("read_global%d\n",m_stats->gpgpu_n_mem_read_global); break; - case GLOBAL_ACC_W: - m_stats->gpgpu_n_mem_write_global++; - break; - case LOCAL_ACC_R: - m_stats->gpgpu_n_mem_read_local++; - break; - case LOCAL_ACC_W: - m_stats->gpgpu_n_mem_write_local++; - break; - case INST_ACC_R: - m_stats->gpgpu_n_mem_read_inst++; - break; - case L1_WRBK_ACC: - m_stats->gpgpu_n_mem_write_global++; - break; - case L2_WRBK_ACC: - m_stats->gpgpu_n_mem_l2_writeback++; - break; - case L1_WR_ALLOC_R: - m_stats->gpgpu_n_mem_l1_write_allocate++; - break; - case L2_WR_ALLOC_R: - m_stats->gpgpu_n_mem_l2_write_allocate++; - break; - default: - assert(0); - } +void simt_core_cluster::icnt_inject_request_packet(class mem_fetch *mf) +{ + // stats + if (mf->get_is_write()) m_stats->made_write_mfs++; + else m_stats->made_read_mfs++; + switch (mf->get_access_type()) { + case CONST_ACC_R: m_stats->gpgpu_n_mem_const++; break; + case TEXTURE_ACC_R: m_stats->gpgpu_n_mem_texture++; break; + case GLOBAL_ACC_R: m_stats->gpgpu_n_mem_read_global++; break; + //case GLOBAL_ACC_R: m_stats->gpgpu_n_mem_read_global++; printf("read_global%d\n",m_stats->gpgpu_n_mem_read_global); break; + case GLOBAL_ACC_W: m_stats->gpgpu_n_mem_write_global++; break; + case LOCAL_ACC_R: m_stats->gpgpu_n_mem_read_local++; break; + case LOCAL_ACC_W: m_stats->gpgpu_n_mem_write_local++; break; + case INST_ACC_R: m_stats->gpgpu_n_mem_read_inst++; break; + case L1_WRBK_ACC: m_stats->gpgpu_n_mem_write_global++; break; + case L2_WRBK_ACC: m_stats->gpgpu_n_mem_l2_writeback++; break; + case L1_WR_ALLOC_R: m_stats->gpgpu_n_mem_l1_write_allocate++; break; + case L2_WR_ALLOC_R: m_stats->gpgpu_n_mem_l2_write_allocate++; break; + default: assert(0); + } - // The packet size varies depending on the type of request: - // - For write request and atomic request, the packet contains the data - // - For read request (i.e. not write nor atomic), the packet only has control - // metadata - unsigned int packet_size = mf->size(); - if (!mf->get_is_write() && !mf->isatomic()) { - packet_size = mf->get_ctrl_size(); - } - m_stats->m_outgoing_traffic_stats->record_traffic(mf, packet_size); - unsigned destination = mf->get_sub_partition_id(); - mf->set_status(IN_ICNT_TO_MEM, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - if (!mf->get_is_write() && !mf->isatomic()) - ::icnt_push(m_cluster_id, m_config->mem2device(destination), (void *)mf, - mf->get_ctrl_size()); - else - ::icnt_push(m_cluster_id, m_config->mem2device(destination), (void *)mf, - mf->size()); + // The packet size varies depending on the type of request: + // - For write request and atomic request, the packet contains the data + // - For read request (i.e. not write nor atomic), the packet only has control metadata + unsigned int packet_size = mf->size(); + if (!mf->get_is_write() && !mf->isatomic()) { + packet_size = mf->get_ctrl_size(); + } + m_stats->m_outgoing_traffic_stats->record_traffic(mf, packet_size); + unsigned destination = mf->get_sub_partition_id(); + mf->set_status(IN_ICNT_TO_MEM,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); + if (!mf->get_is_write() && !mf->isatomic()) + ::icnt_push(m_cluster_id, m_config->mem2device(destination), (void*)mf, mf->get_ctrl_size() ); + else + ::icnt_push(m_cluster_id, m_config->mem2device(destination), (void*)mf, mf->size()); } -void simt_core_cluster::icnt_cycle() { - if (!m_response_fifo.empty()) { - mem_fetch *mf = m_response_fifo.front(); - unsigned cid = m_config->sid_to_cid(mf->get_sid()); - if (mf->get_access_type() == INST_ACC_R) { - // instruction fetch response - if (!m_core[cid]->fetch_unit_response_buffer_full()) { - m_response_fifo.pop_front(); - m_core[cid]->accept_fetch_response(mf); - } - } else { - // data response - if (!m_core[cid]->ldst_unit_response_buffer_full()) { - m_response_fifo.pop_front(); - m_memory_stats->memlatstat_read_done(mf); - m_core[cid]->accept_ldst_unit_response(mf); - } +void simt_core_cluster::icnt_cycle() +{ + if( !m_response_fifo.empty() ) { + mem_fetch *mf = m_response_fifo.front(); + unsigned cid = m_config->sid_to_cid(mf->get_sid()); + if( mf->get_access_type() == INST_ACC_R ) { + // instruction fetch response + if( !m_core[cid]->fetch_unit_response_buffer_full() ) { + m_response_fifo.pop_front(); + m_core[cid]->accept_fetch_response(mf); + } + } else { + // data response + if( !m_core[cid]->ldst_unit_response_buffer_full() ) { + m_response_fifo.pop_front(); + m_memory_stats->memlatstat_read_done(mf); + m_core[cid]->accept_ldst_unit_response(mf); + } + } } - } - if (m_response_fifo.size() < m_config->n_simt_ejection_buffer_size) { - mem_fetch *mf = (mem_fetch *)::icnt_pop(m_cluster_id); - if (!mf) return; - assert(mf->get_tpc() == m_cluster_id); - assert(mf->get_type() == READ_REPLY || mf->get_type() == WRITE_ACK); + if( m_response_fifo.size() < m_config->n_simt_ejection_buffer_size ) { + mem_fetch *mf = (mem_fetch*) ::icnt_pop(m_cluster_id); + if (!mf) + return; + assert(mf->get_tpc() == m_cluster_id); + assert(mf->get_type() == READ_REPLY || mf->get_type() == WRITE_ACK ); - // The packet size varies depending on the type of request: - // - For read request and atomic request, the packet contains the data - // - For write-ack, the packet only has control metadata - unsigned int packet_size = - (mf->get_is_write()) ? mf->get_ctrl_size() : mf->size(); - m_stats->m_incoming_traffic_stats->record_traffic(mf, packet_size); - mf->set_status(IN_CLUSTER_TO_SHADER_QUEUE, - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle); - // m_memory_stats->memlatstat_read_done(mf,m_shader_config->max_warps_per_shader); - m_response_fifo.push_back(mf); - m_stats->n_mem_to_simt[m_cluster_id] += mf->get_num_flits(false); - } + // The packet size varies depending on the type of request: + // - For read request and atomic request, the packet contains the data + // - For write-ack, the packet only has control metadata + unsigned int packet_size = (mf->get_is_write())? mf->get_ctrl_size() : mf->size(); + m_stats->m_incoming_traffic_stats->record_traffic(mf, packet_size); + mf->set_status(IN_CLUSTER_TO_SHADER_QUEUE,m_gpu->gpu_sim_cycle+m_gpu->gpu_tot_sim_cycle); + //m_memory_stats->memlatstat_read_done(mf,m_shader_config->max_warps_per_shader); + m_response_fifo.push_back(mf); + m_stats->n_mem_to_simt[m_cluster_id] += mf->get_num_flits(false); + } } -void simt_core_cluster::get_pdom_stack_top_info(unsigned sid, unsigned tid, - unsigned *pc, - unsigned *rpc) const { - unsigned cid = m_config->sid_to_cid(sid); - m_core[cid]->get_pdom_stack_top_info(tid, pc, rpc); +void simt_core_cluster::get_pdom_stack_top_info( unsigned sid, unsigned tid, unsigned *pc, unsigned *rpc ) const +{ + unsigned cid = m_config->sid_to_cid(sid); + m_core[cid]->get_pdom_stack_top_info(tid,pc,rpc); } -void simt_core_cluster::display_pipeline(unsigned sid, FILE *fout, - int print_mem, int mask) { - m_core[m_config->sid_to_cid(sid)]->display_pipeline(fout, print_mem, mask); +void simt_core_cluster::display_pipeline( unsigned sid, FILE *fout, int print_mem, int mask ) +{ + m_core[m_config->sid_to_cid(sid)]->display_pipeline(fout,print_mem,mask); - fprintf(fout, "\n"); - fprintf(fout, "Cluster %u pipeline state\n", m_cluster_id); - fprintf(fout, "Response FIFO (occupancy = %zu):\n", m_response_fifo.size()); - for (std::list<mem_fetch *>::const_iterator i = m_response_fifo.begin(); - i != m_response_fifo.end(); i++) { - const mem_fetch *mf = *i; - mf->print(fout); - } + fprintf(fout,"\n"); + fprintf(fout,"Cluster %u pipeline state\n", m_cluster_id ); + fprintf(fout,"Response FIFO (occupancy = %zu):\n", m_response_fifo.size() ); + for( std::list<mem_fetch*>::const_iterator i=m_response_fifo.begin(); i != m_response_fifo.end(); i++ ) { + const mem_fetch *mf = *i; + mf->print(fout); + } } -void simt_core_cluster::print_cache_stats(FILE *fp, unsigned &dl1_accesses, - unsigned &dl1_misses) const { - for (unsigned i = 0; i < m_config->n_simt_cores_per_cluster; ++i) { - m_core[i]->print_cache_stats(fp, dl1_accesses, dl1_misses); - } +void simt_core_cluster::print_cache_stats( FILE *fp, unsigned& dl1_accesses, unsigned& dl1_misses ) const { + for ( unsigned i = 0; i < m_config->n_simt_cores_per_cluster; ++i ) { + m_core[ i ]->print_cache_stats( fp, dl1_accesses, dl1_misses ); + } } -void simt_core_cluster::get_icnt_stats(long &n_simt_to_mem, - long &n_mem_to_simt) const { - long simt_to_mem = 0; - long mem_to_simt = 0; - for (unsigned i = 0; i < m_config->n_simt_cores_per_cluster; ++i) { - m_core[i]->get_icnt_power_stats(simt_to_mem, mem_to_simt); - } - n_simt_to_mem = simt_to_mem; - n_mem_to_simt = mem_to_simt; +void simt_core_cluster::get_icnt_stats(long &n_simt_to_mem, long &n_mem_to_simt) const { + long simt_to_mem=0; + long mem_to_simt=0; + for ( unsigned i = 0; i < m_config->n_simt_cores_per_cluster; ++i ) { + m_core[i]->get_icnt_power_stats(simt_to_mem, mem_to_simt); + } + n_simt_to_mem = simt_to_mem; + n_mem_to_simt = mem_to_simt; } -void simt_core_cluster::get_cache_stats(cache_stats &cs) const { - for (unsigned i = 0; i < m_config->n_simt_cores_per_cluster; ++i) { - m_core[i]->get_cache_stats(cs); - } +void simt_core_cluster::get_cache_stats(cache_stats &cs) const{ + for ( unsigned i = 0; i < m_config->n_simt_cores_per_cluster; ++i ) { + m_core[i]->get_cache_stats(cs); + } } -void simt_core_cluster::get_L1I_sub_stats(struct cache_sub_stats &css) const { - struct cache_sub_stats temp_css; - struct cache_sub_stats total_css; - temp_css.clear(); - total_css.clear(); - for (unsigned i = 0; i < m_config->n_simt_cores_per_cluster; ++i) { - m_core[i]->get_L1I_sub_stats(temp_css); - total_css += temp_css; - } - css = total_css; +void simt_core_cluster::get_L1I_sub_stats(struct cache_sub_stats &css) const{ + struct cache_sub_stats temp_css; + struct cache_sub_stats total_css; + temp_css.clear(); + total_css.clear(); + for ( unsigned i = 0; i < m_config->n_simt_cores_per_cluster; ++i ) { + m_core[i]->get_L1I_sub_stats(temp_css); + total_css += temp_css; + } + css = total_css; } -void simt_core_cluster::get_L1D_sub_stats(struct cache_sub_stats &css) const { - struct cache_sub_stats temp_css; - struct cache_sub_stats total_css; - temp_css.clear(); - total_css.clear(); - for (unsigned i = 0; i < m_config->n_simt_cores_per_cluster; ++i) { - m_core[i]->get_L1D_sub_stats(temp_css); - total_css += temp_css; - } - css = total_css; +void simt_core_cluster::get_L1D_sub_stats(struct cache_sub_stats &css) const{ + struct cache_sub_stats temp_css; + struct cache_sub_stats total_css; + temp_css.clear(); + total_css.clear(); + for ( unsigned i = 0; i < m_config->n_simt_cores_per_cluster; ++i ) { + m_core[i]->get_L1D_sub_stats(temp_css); + total_css += temp_css; + } + css = total_css; } -void simt_core_cluster::get_L1C_sub_stats(struct cache_sub_stats &css) const { - struct cache_sub_stats temp_css; - struct cache_sub_stats total_css; - temp_css.clear(); - total_css.clear(); - for (unsigned i = 0; i < m_config->n_simt_cores_per_cluster; ++i) { - m_core[i]->get_L1C_sub_stats(temp_css); - total_css += temp_css; - } - css = total_css; +void simt_core_cluster::get_L1C_sub_stats(struct cache_sub_stats &css) const{ + struct cache_sub_stats temp_css; + struct cache_sub_stats total_css; + temp_css.clear(); + total_css.clear(); + for ( unsigned i = 0; i < m_config->n_simt_cores_per_cluster; ++i ) { + m_core[i]->get_L1C_sub_stats(temp_css); + total_css += temp_css; + } + css = total_css; } -void simt_core_cluster::get_L1T_sub_stats(struct cache_sub_stats &css) const { - struct cache_sub_stats temp_css; - struct cache_sub_stats total_css; - temp_css.clear(); - total_css.clear(); - for (unsigned i = 0; i < m_config->n_simt_cores_per_cluster; ++i) { - m_core[i]->get_L1T_sub_stats(temp_css); - total_css += temp_css; - } - css = total_css; +void simt_core_cluster::get_L1T_sub_stats(struct cache_sub_stats &css) const{ + struct cache_sub_stats temp_css; + struct cache_sub_stats total_css; + temp_css.clear(); + total_css.clear(); + for ( unsigned i = 0; i < m_config->n_simt_cores_per_cluster; ++i ) { + m_core[i]->get_L1T_sub_stats(temp_css); + total_css += temp_css; + } + css = total_css; } -void shader_core_ctx::checkExecutionStatusAndUpdate(warp_inst_t &inst, - unsigned t, unsigned tid) { - if (inst.isatomic()) m_warp[inst.warp_id()].inc_n_atomic(); - if (inst.space.is_local() && (inst.is_load() || inst.is_store())) { - new_addr_type localaddrs[MAX_ACCESSES_PER_INSN_PER_THREAD]; - unsigned num_addrs; - num_addrs = translate_local_memaddr( - inst.get_addr(t), tid, - m_config->n_simt_clusters * m_config->n_simt_cores_per_cluster, - inst.data_size, (new_addr_type *)localaddrs); - inst.set_addr(t, (new_addr_type *)localaddrs, num_addrs); - } - if (ptx_thread_done(tid)) { - m_warp[inst.warp_id()].set_completed(t); - m_warp[inst.warp_id()].ibuffer_flush(); - } +void shader_core_ctx::checkExecutionStatusAndUpdate(warp_inst_t &inst, unsigned t, unsigned tid) +{ + if(inst.isatomic()) + m_warp[inst.warp_id()].inc_n_atomic(); + if (inst.space.is_local() && (inst.is_load() || inst.is_store())) { + new_addr_type localaddrs[MAX_ACCESSES_PER_INSN_PER_THREAD]; + unsigned num_addrs; + num_addrs = translate_local_memaddr(inst.get_addr(t), tid, m_config->n_simt_clusters*m_config->n_simt_cores_per_cluster, + inst.data_size, (new_addr_type*) localaddrs ); + inst.set_addr(t, (new_addr_type*) localaddrs, num_addrs); + } + if ( ptx_thread_done(tid) ) { + m_warp[inst.warp_id()].set_completed(t); + m_warp[inst.warp_id()].ibuffer_flush(); + } - // PC-Histogram Update - unsigned warp_id = inst.warp_id(); - unsigned pc = inst.pc; - for (unsigned t = 0; t < m_config->warp_size; t++) { - if (inst.active(t)) { - int tid = warp_id * m_config->warp_size + t; - cflog_update_thread_pc(m_sid, tid, pc); + // PC-Histogram Update + unsigned warp_id = inst.warp_id(); + unsigned pc = inst.pc; + for (unsigned t = 0; t < m_config->warp_size; t++) { + if (inst.active(t)) { + int tid = warp_id * m_config->warp_size + t; + cflog_update_thread_pc(m_sid, tid, pc); + } } - } } + diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index 24899ad..667cb2d 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2011, Tor M. Aamodt, Wilson W.L. Fung, Andrew Turner, -// Ali Bakhoda +// Ali Bakhoda // The University of British Columbia // All rights reserved. // @@ -8,16 +8,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -31,50 +29,50 @@ #ifndef SHADER_H #define SHADER_H -#include <assert.h> -#include <math.h> #include <stdio.h> #include <stdlib.h> -#include <algorithm> -#include <bitset> -#include <deque> -#include <list> +#include <math.h> +#include <assert.h> #include <map> #include <set> -#include <utility> #include <vector> +#include <list> +#include <bitset> +#include <utility> +#include <algorithm> +#include <deque> //#include "../cuda-sim/ptx.tab.h" -#include "../abstract_hardware_model.h" #include "delayqueue.h" +#include "stack.h" #include "dram.h" -#include "gpu-cache.h" -#include "mem_fetch.h" +#include "../abstract_hardware_model.h" #include "scoreboard.h" -#include "stack.h" +#include "mem_fetch.h" #include "stats.h" +#include "gpu-cache.h" #include "traffic_breakdown.h" -#define NO_OP_FLAG 0xFF + +#define NO_OP_FLAG 0xFF /* READ_PACKET_SIZE: - bytes: 6 address (flit can specify chanel so this gives up to ~2GB/channel, - so good for now), - 2 bytes [shaderid + mshrid](14 bits) + req_size(0-2 bits if req_size - variable) - so up to 2^14 = 16384 mshr total + bytes: 6 address (flit can specify chanel so this gives up to ~2GB/channel, so good for now), + 2 bytes [shaderid + mshrid](14 bits) + req_size(0-2 bits if req_size variable) - so up to 2^14 = 16384 mshr total */ #define READ_PACKET_SIZE 8 -// WRITE_PACKET_SIZE: bytes: 6 address, 2 miscelaneous. +//WRITE_PACKET_SIZE: bytes: 6 address, 2 miscelaneous. #define WRITE_PACKET_SIZE 8 #define WRITE_MASK_SIZE 8 class gpgpu_context; -enum exec_unit_type_t { +enum exec_unit_type_t +{ NONE = 0, SP = 1, SFU = 2, @@ -85,1134 +83,1127 @@ enum exec_unit_type_t { }; class thread_ctx_t { - public: - unsigned m_cta_id; // hardware CTA this thread belongs +public: + unsigned m_cta_id; // hardware CTA this thread belongs - // per thread stats (ac stands for accumulative). - unsigned n_insn; - unsigned n_insn_ac; - unsigned n_l1_mis_ac; - unsigned n_l1_mrghit_ac; - unsigned n_l1_access_ac; + // per thread stats (ac stands for accumulative). + unsigned n_insn; + unsigned n_insn_ac; + unsigned n_l1_mis_ac; + unsigned n_l1_mrghit_ac; + unsigned n_l1_access_ac; - bool m_active; + bool m_active; }; class shd_warp_t { - public: - shd_warp_t(class shader_core_ctx *shader, unsigned warp_size) - : m_shader(shader), m_warp_size(warp_size) { - m_stores_outstanding = 0; - m_inst_in_pipeline = 0; - reset(); - } - void reset() { - assert(m_stores_outstanding == 0); - assert(m_inst_in_pipeline == 0); - m_imiss_pending = false; - m_warp_id = (unsigned)-1; - m_dynamic_warp_id = (unsigned)-1; - n_completed = m_warp_size; - m_n_atomic = 0; - m_membar = false; - m_done_exit = true; - m_last_fetch = 0; - m_next = 0; +public: + shd_warp_t( class shader_core_ctx *shader, unsigned warp_size) + : m_shader(shader), m_warp_size(warp_size) + { + m_stores_outstanding=0; + m_inst_in_pipeline=0; + reset(); + } + void reset() + { + assert( m_stores_outstanding==0); + assert( m_inst_in_pipeline==0); + m_imiss_pending=false; + m_warp_id=(unsigned)-1; + m_dynamic_warp_id = (unsigned)-1; + n_completed = m_warp_size; + m_n_atomic=0; + m_membar=false; + m_done_exit=true; + m_last_fetch=0; + m_next=0; - // Jin: cdp support - m_cdp_latency = 0; - m_cdp_dummy = false; - } - void init(address_type start_pc, unsigned cta_id, unsigned wid, - const std::bitset<MAX_WARP_SIZE> &active, - unsigned dynamic_warp_id) { - m_cta_id = cta_id; - m_warp_id = wid; - m_dynamic_warp_id = dynamic_warp_id; - m_next_pc = start_pc; - assert(n_completed >= active.count()); - assert(n_completed <= m_warp_size); - n_completed -= active.count(); // active threads are not yet completed - m_active_threads = active; - m_done_exit = false; + //Jin: cdp support + m_cdp_latency = 0; + m_cdp_dummy = false; + } + void init( address_type start_pc, + unsigned cta_id, + unsigned wid, + const std::bitset<MAX_WARP_SIZE> &active, + unsigned dynamic_warp_id ) + { + m_cta_id=cta_id; + m_warp_id=wid; + m_dynamic_warp_id=dynamic_warp_id; + m_next_pc=start_pc; + assert( n_completed >= active.count() ); + assert( n_completed <= m_warp_size); + n_completed -= active.count(); // active threads are not yet completed + m_active_threads = active; + m_done_exit=false; - // Jin: cdp support - m_cdp_latency = 0; - m_cdp_dummy = false; - } + //Jin: cdp support + m_cdp_latency = 0; + m_cdp_dummy = false; + } - bool functional_done() const; - bool waiting(); // not const due to membar - bool hardware_done() const; + bool functional_done() const; + bool waiting(); // not const due to membar + bool hardware_done() const; - bool done_exit() const { return m_done_exit; } - void set_done_exit() { m_done_exit = true; } + bool done_exit() const { return m_done_exit; } + void set_done_exit() { m_done_exit=true; } - void print(FILE *fout) const; - void print_ibuffer(FILE *fout) const; + void print( FILE *fout ) const; + void print_ibuffer( FILE *fout ) const; - unsigned get_n_completed() const { return n_completed; } - void set_completed(unsigned lane) { - assert(m_active_threads.test(lane)); - m_active_threads.reset(lane); - n_completed++; - } + unsigned get_n_completed() const { return n_completed; } + void set_completed( unsigned lane ) + { + assert( m_active_threads.test(lane) ); + m_active_threads.reset(lane); + n_completed++; + } - void set_last_fetch(unsigned long long sim_cycle) { - m_last_fetch = sim_cycle; - } + void set_last_fetch( unsigned long long sim_cycle ) { m_last_fetch=sim_cycle; } - unsigned get_n_atomic() const { return m_n_atomic; } - void inc_n_atomic() { m_n_atomic++; } - void dec_n_atomic(unsigned n) { m_n_atomic -= n; } + unsigned get_n_atomic() const { return m_n_atomic; } + void inc_n_atomic() { m_n_atomic++; } + void dec_n_atomic(unsigned n) { m_n_atomic-=n; } - void set_membar() { m_membar = true; } - void clear_membar() { m_membar = false; } - bool get_membar() const { return m_membar; } - address_type get_pc() const { return m_next_pc; } - void set_next_pc(address_type pc) { m_next_pc = pc; } + void set_membar() { m_membar=true; } + void clear_membar() { m_membar=false; } + bool get_membar() const { return m_membar; } + address_type get_pc() const { return m_next_pc; } + void set_next_pc( address_type pc ) { m_next_pc = pc; } - void store_info_of_last_inst_at_barrier(const warp_inst_t *pI) { - m_inst_at_barrier = *pI; - } - warp_inst_t *restore_info_of_last_inst_at_barrier() { - return &m_inst_at_barrier; - } + void store_info_of_last_inst_at_barrier(const warp_inst_t *pI){ m_inst_at_barrier = *pI;} + warp_inst_t * restore_info_of_last_inst_at_barrier(){ return &m_inst_at_barrier;} - void ibuffer_fill(unsigned slot, const warp_inst_t *pI) { - assert(slot < IBUFFER_SIZE); - m_ibuffer[slot].m_inst = pI; - m_ibuffer[slot].m_valid = true; - m_next = 0; - } - bool ibuffer_empty() const { - for (unsigned i = 0; i < IBUFFER_SIZE; i++) - if (m_ibuffer[i].m_valid) return false; - return true; - } - void ibuffer_flush() { - for (unsigned i = 0; i < IBUFFER_SIZE; i++) { - if (m_ibuffer[i].m_valid) dec_inst_in_pipeline(); - m_ibuffer[i].m_inst = NULL; - m_ibuffer[i].m_valid = false; + void ibuffer_fill( unsigned slot, const warp_inst_t *pI ) + { + assert(slot < IBUFFER_SIZE ); + m_ibuffer[slot].m_inst=pI; + m_ibuffer[slot].m_valid=true; + m_next=0; } - } - const warp_inst_t *ibuffer_next_inst() { return m_ibuffer[m_next].m_inst; } - bool ibuffer_next_valid() { return m_ibuffer[m_next].m_valid; } - void ibuffer_free() { - m_ibuffer[m_next].m_inst = NULL; - m_ibuffer[m_next].m_valid = false; - } - void ibuffer_step() { m_next = (m_next + 1) % IBUFFER_SIZE; } + bool ibuffer_empty() const + { + for( unsigned i=0; i < IBUFFER_SIZE; i++) + if(m_ibuffer[i].m_valid) + return false; + return true; + } + void ibuffer_flush() + { + for(unsigned i=0;i<IBUFFER_SIZE;i++) { + if( m_ibuffer[i].m_valid ) + dec_inst_in_pipeline(); + m_ibuffer[i].m_inst=NULL; + m_ibuffer[i].m_valid=false; + } + } + const warp_inst_t *ibuffer_next_inst() { return m_ibuffer[m_next].m_inst; } + bool ibuffer_next_valid() { return m_ibuffer[m_next].m_valid; } + void ibuffer_free() + { + m_ibuffer[m_next].m_inst = NULL; + m_ibuffer[m_next].m_valid = false; + } + void ibuffer_step() { m_next = (m_next+1)%IBUFFER_SIZE; } - bool imiss_pending() const { return m_imiss_pending; } - void set_imiss_pending() { m_imiss_pending = true; } - void clear_imiss_pending() { m_imiss_pending = false; } + bool imiss_pending() const { return m_imiss_pending; } + void set_imiss_pending() { m_imiss_pending=true; } + void clear_imiss_pending() { m_imiss_pending=false; } - bool stores_done() const { return m_stores_outstanding == 0; } - void inc_store_req() { m_stores_outstanding++; } - void dec_store_req() { - assert(m_stores_outstanding > 0); - m_stores_outstanding--; - } + bool stores_done() const { return m_stores_outstanding == 0; } + void inc_store_req() { m_stores_outstanding++; } + void dec_store_req() + { + assert( m_stores_outstanding > 0 ); + m_stores_outstanding--; + } - unsigned num_inst_in_buffer() const { - unsigned count = 0; - for (unsigned i = 0; i < IBUFFER_SIZE; i++) { - if (m_ibuffer[i].m_valid) count++; + unsigned num_inst_in_buffer() const + { + unsigned count=0; + for(unsigned i=0;i<IBUFFER_SIZE;i++) { + if( m_ibuffer[i].m_valid ) + count++; + } + return count; + } + unsigned num_inst_in_pipeline() const { return m_inst_in_pipeline;} + unsigned num_issued_inst_in_pipeline() const {return (num_inst_in_pipeline()-num_inst_in_buffer());} + bool inst_in_pipeline() const { return m_inst_in_pipeline > 0; } + void inc_inst_in_pipeline() { m_inst_in_pipeline++; } + void dec_inst_in_pipeline() + { + assert( m_inst_in_pipeline > 0 ); + m_inst_in_pipeline--; } - return count; - } - unsigned num_inst_in_pipeline() const { return m_inst_in_pipeline; } - unsigned num_issued_inst_in_pipeline() const { - return (num_inst_in_pipeline() - num_inst_in_buffer()); - } - bool inst_in_pipeline() const { return m_inst_in_pipeline > 0; } - void inc_inst_in_pipeline() { m_inst_in_pipeline++; } - void dec_inst_in_pipeline() { - assert(m_inst_in_pipeline > 0); - m_inst_in_pipeline--; - } - unsigned get_cta_id() const { return m_cta_id; } + unsigned get_cta_id() const { return m_cta_id; } - unsigned get_dynamic_warp_id() const { return m_dynamic_warp_id; } - unsigned get_warp_id() const { return m_warp_id; } + unsigned get_dynamic_warp_id() const { return m_dynamic_warp_id; } + unsigned get_warp_id() const { return m_warp_id; } - private: - static const unsigned IBUFFER_SIZE = 2; - class shader_core_ctx *m_shader; - unsigned m_cta_id; - unsigned m_warp_id; - unsigned m_warp_size; - unsigned m_dynamic_warp_id; +private: + static const unsigned IBUFFER_SIZE=2; + class shader_core_ctx *m_shader; + unsigned m_cta_id; + unsigned m_warp_id; + unsigned m_warp_size; + unsigned m_dynamic_warp_id; - address_type m_next_pc; - unsigned n_completed; // number of threads in warp completed - std::bitset<MAX_WARP_SIZE> m_active_threads; + address_type m_next_pc; + unsigned n_completed; // number of threads in warp completed + std::bitset<MAX_WARP_SIZE> m_active_threads; - bool m_imiss_pending; + bool m_imiss_pending; + + struct ibuffer_entry { + ibuffer_entry() { m_valid = false; m_inst = NULL; } + const warp_inst_t *m_inst; + bool m_valid; + }; - struct ibuffer_entry { - ibuffer_entry() { - m_valid = false; - m_inst = NULL; - } - const warp_inst_t *m_inst; - bool m_valid; - }; + warp_inst_t m_inst_at_barrier; + ibuffer_entry m_ibuffer[IBUFFER_SIZE]; + unsigned m_next; + + unsigned m_n_atomic; // number of outstanding atomic operations + bool m_membar; // if true, warp is waiting at memory barrier - warp_inst_t m_inst_at_barrier; - ibuffer_entry m_ibuffer[IBUFFER_SIZE]; - unsigned m_next; + bool m_done_exit; // true once thread exit has been registered for threads in this warp - unsigned m_n_atomic; // number of outstanding atomic operations - bool m_membar; // if true, warp is waiting at memory barrier + unsigned long long m_last_fetch; - bool m_done_exit; // true once thread exit has been registered for threads in - // this warp + unsigned m_stores_outstanding; // number of store requests sent but not yet acknowledged + unsigned m_inst_in_pipeline; - unsigned long long m_last_fetch; + //Jin: cdp support +public: + unsigned int m_cdp_latency; + bool m_cdp_dummy; +}; - unsigned m_stores_outstanding; // number of store requests sent but not yet - // acknowledged - unsigned m_inst_in_pipeline; - // Jin: cdp support - public: - unsigned int m_cdp_latency; - bool m_cdp_dummy; -}; -inline unsigned hw_tid_from_wid(unsigned wid, unsigned warp_size, unsigned i) { - return wid * warp_size + i; -}; -inline unsigned wid_from_hw_tid(unsigned tid, unsigned warp_size) { - return tid / warp_size; -}; +inline unsigned hw_tid_from_wid(unsigned wid, unsigned warp_size, unsigned i){return wid * warp_size + i;}; +inline unsigned wid_from_hw_tid(unsigned tid, unsigned warp_size){return tid/warp_size;}; const unsigned WARP_PER_CTA_MAX = 64; typedef std::bitset<WARP_PER_CTA_MAX> warp_set_t; -int register_bank(int regnum, int wid, unsigned num_banks, - unsigned bank_warp_shift, bool sub_core_model, - unsigned banks_per_sched, unsigned sched_id); +int register_bank(int regnum, int wid, unsigned num_banks, unsigned bank_warp_shift, bool sub_core_model, unsigned banks_per_sched, unsigned sched_id ); class shader_core_ctx; class shader_core_config; class shader_core_stats; -enum scheduler_prioritization_type { - SCHEDULER_PRIORITIZATION_LRR = 0, // Loose Round Robin - SCHEDULER_PRIORITIZATION_SRR, // Strict Round Robin - SCHEDULER_PRIORITIZATION_GTO, // Greedy Then Oldest - SCHEDULER_PRIORITIZATION_GTLRR, // Greedy Then Loose Round Robin - SCHEDULER_PRIORITIZATION_GTY, // Greedy Then Youngest - SCHEDULER_PRIORITIZATION_OLDEST, // Oldest First - SCHEDULER_PRIORITIZATION_YOUNGEST, // Youngest First +enum scheduler_prioritization_type +{ + SCHEDULER_PRIORITIZATION_LRR = 0, // Loose Round Robin + SCHEDULER_PRIORITIZATION_SRR, // Strict Round Robin + SCHEDULER_PRIORITIZATION_GTO, // Greedy Then Oldest + SCHEDULER_PRIORITIZATION_GTLRR, // Greedy Then Loose Round Robin + SCHEDULER_PRIORITIZATION_GTY, // Greedy Then Youngest + SCHEDULER_PRIORITIZATION_OLDEST, // Oldest First + SCHEDULER_PRIORITIZATION_YOUNGEST, // Youngest First }; // Each of these corresponds to a string value in the gpgpsim.config file // For example - to specify the LRR scheudler the config must contain lrr -enum concrete_scheduler { - CONCRETE_SCHEDULER_LRR = 0, - CONCRETE_SCHEDULER_GTO, - CONCRETE_SCHEDULER_TWO_LEVEL_ACTIVE, - CONCRETE_SCHEDULER_WARP_LIMITING, - CONCRETE_SCHEDULER_OLDEST_FIRST, - NUM_CONCRETE_SCHEDULERS +enum concrete_scheduler +{ + CONCRETE_SCHEDULER_LRR = 0, + CONCRETE_SCHEDULER_GTO, + CONCRETE_SCHEDULER_TWO_LEVEL_ACTIVE, + CONCRETE_SCHEDULER_WARP_LIMITING, + CONCRETE_SCHEDULER_OLDEST_FIRST, + NUM_CONCRETE_SCHEDULERS }; -class scheduler_unit { // this can be copied freely, so can be used in std - // containers. - public: - scheduler_unit(shader_core_stats *stats, shader_core_ctx *shader, - Scoreboard *scoreboard, simt_stack **simt, - std::vector<shd_warp_t> *warp, register_set *sp_out, - register_set *dp_out, register_set *sfu_out, - register_set *int_out, register_set *tensor_core_out, - register_set *mem_out, int id) - : m_supervised_warps(), - m_stats(stats), - m_shader(shader), - m_scoreboard(scoreboard), - m_simt_stack(simt), - /*m_pipeline_reg(pipe_regs),*/ m_warp(warp), - m_sp_out(sp_out), - m_dp_out(dp_out), - m_sfu_out(sfu_out), - m_int_out(int_out), - m_tensor_core_out(tensor_core_out), - m_mem_out(mem_out), - m_id(id) {} - virtual ~scheduler_unit() {} - virtual void add_supervised_warp_id(int i) { - m_supervised_warps.push_back(&warp(i)); - } - virtual void done_adding_supervised_warps() { - m_last_supervised_issued = m_supervised_warps.end(); - } - - // The core scheduler cycle method is meant to be common between - // all the derived schedulers. The scheduler's behaviour can be - // modified by changing the contents of the m_next_cycle_prioritized_warps - // list. - void cycle(); +class scheduler_unit { //this can be copied freely, so can be used in std containers. +public: + scheduler_unit(shader_core_stats* stats, shader_core_ctx* shader, + Scoreboard* scoreboard, simt_stack** simt, + std::vector<shd_warp_t>* warp, + register_set* sp_out, + register_set* dp_out, + register_set* sfu_out, + register_set* int_out, + register_set* tensor_core_out, + register_set* mem_out, + int id) + : m_supervised_warps(), m_stats(stats), m_shader(shader), + m_scoreboard(scoreboard), m_simt_stack(simt), /*m_pipeline_reg(pipe_regs),*/ m_warp(warp), + m_sp_out(sp_out),m_dp_out(dp_out),m_sfu_out(sfu_out),m_int_out(int_out),m_tensor_core_out(tensor_core_out),m_mem_out(mem_out), m_id(id){} + virtual ~scheduler_unit(){} + virtual void add_supervised_warp_id(int i) { + m_supervised_warps.push_back(&warp(i)); + } + virtual void done_adding_supervised_warps() { + m_last_supervised_issued = m_supervised_warps.end(); + } - // These are some common ordering fucntions that the - // higher order schedulers can take advantage of - template <typename T> - void order_lrr( - typename std::vector<T> &result_list, - const typename std::vector<T> &input_list, - const typename std::vector<T>::const_iterator &last_issued_from_input, - unsigned num_warps_to_add); - enum OrderingType { - // The item that issued last is prioritized first then the sorted result - // of the priority_function - ORDERING_GREEDY_THEN_PRIORITY_FUNC = 0, - // No greedy scheduling based on last to issue. Only the priority function - // determines - // priority - ORDERED_PRIORITY_FUNC_ONLY, - NUM_ORDERING, - }; - template <typename U> - void order_by_priority( - std::vector<U> &result_list, const typename std::vector<U> &input_list, - const typename std::vector<U>::const_iterator &last_issued_from_input, - unsigned num_warps_to_add, OrderingType age_ordering, - bool (*priority_func)(U lhs, U rhs)); - static bool sort_warps_by_oldest_dynamic_id(shd_warp_t *lhs, shd_warp_t *rhs); + // The core scheduler cycle method is meant to be common between + // all the derived schedulers. The scheduler's behaviour can be + // modified by changing the contents of the m_next_cycle_prioritized_warps list. + void cycle(); - // Derived classes can override this function to populate - // m_supervised_warps with their scheduling policies - virtual void order_warps() = 0; + // These are some common ordering fucntions that the + // higher order schedulers can take advantage of + template < typename T > + void order_lrr( typename std::vector< T >& result_list, + const typename std::vector< T >& input_list, + const typename std::vector< T >::const_iterator& last_issued_from_input, + unsigned num_warps_to_add ); + + enum OrderingType + { + // The item that issued last is prioritized first then the sorted result + // of the priority_function + ORDERING_GREEDY_THEN_PRIORITY_FUNC = 0, + // No greedy scheduling based on last to issue. Only the priority function determines + // priority + ORDERED_PRIORITY_FUNC_ONLY, + NUM_ORDERING, + }; + template < typename U > + void order_by_priority( std::vector< U >& result_list, + const typename std::vector< U >& input_list, + const typename std::vector< U >::const_iterator& last_issued_from_input, + unsigned num_warps_to_add, + OrderingType age_ordering, + bool (*priority_func)(U lhs, U rhs) ); + static bool sort_warps_by_oldest_dynamic_id(shd_warp_t* lhs, shd_warp_t* rhs); - int get_schd_id() const { return m_id; } + // Derived classes can override this function to populate + // m_supervised_warps with their scheduling policies + virtual void order_warps() = 0; - protected: - virtual void do_on_warp_issued( - unsigned warp_id, unsigned num_issued, - const std::vector<shd_warp_t *>::const_iterator &prioritized_iter); - inline int get_sid() const; + int get_schd_id() const {return m_id;} - protected: - shd_warp_t &warp(int i); +protected: + virtual void do_on_warp_issued( unsigned warp_id, + unsigned num_issued, + const std::vector< shd_warp_t* >::const_iterator& prioritized_iter ); + inline int get_sid() const; +protected: + shd_warp_t& warp(int i); - // This is the prioritized warp list that is looped over each cycle to - // determine - // which warp gets to issue. - std::vector<shd_warp_t *> m_next_cycle_prioritized_warps; - // The m_supervised_warps list is all the warps this scheduler is supposed to - // arbitrate between. This is useful in systems where there is more than - // one warp scheduler. In a single scheduler system, this is simply all - // the warps assigned to this core. - std::vector<shd_warp_t *> m_supervised_warps; - // This is the iterator pointer to the last supervised warp you issued - std::vector<shd_warp_t *>::const_iterator m_last_supervised_issued; - shader_core_stats *m_stats; - shader_core_ctx *m_shader; - // these things should become accessors: but would need a bigger rearchitect - // of how shader_core_ctx interacts with its parts. - Scoreboard *m_scoreboard; - simt_stack **m_simt_stack; - // warp_inst_t** m_pipeline_reg; - std::vector<shd_warp_t> *m_warp; - register_set *m_sp_out; - register_set *m_dp_out; - register_set *m_sfu_out; - register_set *m_int_out; - register_set *m_tensor_core_out; - register_set *m_mem_out; + // This is the prioritized warp list that is looped over each cycle to determine + // which warp gets to issue. + std::vector< shd_warp_t* > m_next_cycle_prioritized_warps; + // The m_supervised_warps list is all the warps this scheduler is supposed to + // arbitrate between. This is useful in systems where there is more than + // one warp scheduler. In a single scheduler system, this is simply all + // the warps assigned to this core. + std::vector< shd_warp_t* > m_supervised_warps; + // This is the iterator pointer to the last supervised warp you issued + std::vector< shd_warp_t* >::const_iterator m_last_supervised_issued; + shader_core_stats *m_stats; + shader_core_ctx* m_shader; + // these things should become accessors: but would need a bigger rearchitect of how shader_core_ctx interacts with its parts. + Scoreboard* m_scoreboard; + simt_stack** m_simt_stack; + //warp_inst_t** m_pipeline_reg; + std::vector<shd_warp_t>* m_warp; + register_set* m_sp_out; + register_set* m_dp_out; + register_set* m_sfu_out; + register_set* m_int_out; + register_set* m_tensor_core_out; + register_set* m_mem_out; - int m_id; + int m_id; }; class lrr_scheduler : public scheduler_unit { - public: - lrr_scheduler(shader_core_stats *stats, shader_core_ctx *shader, - Scoreboard *scoreboard, simt_stack **simt, - std::vector<shd_warp_t> *warp, register_set *sp_out, - register_set *dp_out, register_set *sfu_out, - register_set *int_out, register_set *tensor_core_out, - register_set *mem_out, int id) - : scheduler_unit(stats, shader, scoreboard, simt, warp, sp_out, dp_out, - sfu_out, int_out, tensor_core_out, mem_out, id) {} - virtual ~lrr_scheduler() {} - virtual void order_warps(); - virtual void done_adding_supervised_warps() { - m_last_supervised_issued = m_supervised_warps.end(); - } +public: + lrr_scheduler ( shader_core_stats* stats, shader_core_ctx* shader, + Scoreboard* scoreboard, simt_stack** simt, + std::vector<shd_warp_t>* warp, + register_set* sp_out, + register_set* dp_out, + register_set* sfu_out, + register_set* int_out, + register_set* tensor_core_out, + register_set* mem_out, + int id ) + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out, int_out, tensor_core_out, mem_out, id ){} + virtual ~lrr_scheduler () {} + virtual void order_warps (); + virtual void done_adding_supervised_warps() { + m_last_supervised_issued = m_supervised_warps.end(); + } }; class gto_scheduler : public scheduler_unit { - public: - gto_scheduler(shader_core_stats *stats, shader_core_ctx *shader, - Scoreboard *scoreboard, simt_stack **simt, - std::vector<shd_warp_t> *warp, register_set *sp_out, - register_set *dp_out, register_set *sfu_out, - register_set *int_out, register_set *tensor_core_out, - register_set *mem_out, int id) - : scheduler_unit(stats, shader, scoreboard, simt, warp, sp_out, dp_out, - sfu_out, int_out, tensor_core_out, mem_out, id) {} - virtual ~gto_scheduler() {} - virtual void order_warps(); - virtual void done_adding_supervised_warps() { - m_last_supervised_issued = m_supervised_warps.begin(); - } +public: + gto_scheduler ( shader_core_stats* stats, shader_core_ctx* shader, + Scoreboard* scoreboard, simt_stack** simt, + std::vector<shd_warp_t>* warp, + register_set* sp_out, + register_set* dp_out, + register_set* sfu_out, + register_set* int_out, + register_set* tensor_core_out, + register_set* mem_out, + int id ) + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out, int_out, tensor_core_out, mem_out, id ){} + virtual ~gto_scheduler () {} + virtual void order_warps (); + virtual void done_adding_supervised_warps() { + m_last_supervised_issued = m_supervised_warps.begin(); + } + }; class oldest_scheduler : public scheduler_unit { - public: - oldest_scheduler(shader_core_stats *stats, shader_core_ctx *shader, - Scoreboard *scoreboard, simt_stack **simt, - std::vector<shd_warp_t> *warp, register_set *sp_out, - register_set *dp_out, register_set *sfu_out, - register_set *int_out, register_set *tensor_core_out, - register_set *mem_out, int id) - : scheduler_unit(stats, shader, scoreboard, simt, warp, sp_out, dp_out, - sfu_out, int_out, tensor_core_out, mem_out, id) {} - virtual ~oldest_scheduler() {} - virtual void order_warps(); - virtual void done_adding_supervised_warps() { - m_last_supervised_issued = m_supervised_warps.begin(); - } +public: + oldest_scheduler ( shader_core_stats* stats, shader_core_ctx* shader, + Scoreboard* scoreboard, simt_stack** simt, + std::vector<shd_warp_t>* warp, + register_set* sp_out, + register_set* dp_out, + register_set* sfu_out, + register_set* int_out, + register_set* tensor_core_out, + register_set* mem_out, + int id ) + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out, int_out, tensor_core_out, mem_out, id ){} + virtual ~oldest_scheduler () {} + virtual void order_warps (); + virtual void done_adding_supervised_warps() { + m_last_supervised_issued = m_supervised_warps.begin(); + } + }; class two_level_active_scheduler : public scheduler_unit { - public: - two_level_active_scheduler(shader_core_stats *stats, shader_core_ctx *shader, - Scoreboard *scoreboard, simt_stack **simt, - std::vector<shd_warp_t> *warp, - register_set *sp_out, register_set *dp_out, - register_set *sfu_out, register_set *int_out, - register_set *tensor_core_out, - register_set *mem_out, int id, char *config_str) - : scheduler_unit(stats, shader, scoreboard, simt, warp, sp_out, dp_out, - sfu_out, int_out, tensor_core_out, mem_out, id), - m_pending_warps() { - unsigned inner_level_readin; - unsigned outer_level_readin; - int ret = - sscanf(config_str, "two_level_active:%d:%d:%d", &m_max_active_warps, - &inner_level_readin, &outer_level_readin); - assert(3 == ret); - m_inner_level_prioritization = - (scheduler_prioritization_type)inner_level_readin; - m_outer_level_prioritization = - (scheduler_prioritization_type)outer_level_readin; - } - virtual ~two_level_active_scheduler() {} - virtual void order_warps(); - void add_supervised_warp_id(int i) { - if (m_next_cycle_prioritized_warps.size() < m_max_active_warps) { - m_next_cycle_prioritized_warps.push_back(&warp(i)); - } else { - m_pending_warps.push_back(&warp(i)); +public: + two_level_active_scheduler ( shader_core_stats* stats, shader_core_ctx* shader, + Scoreboard* scoreboard, simt_stack** simt, + std::vector<shd_warp_t>* warp, + register_set* sp_out, + register_set* dp_out, + register_set* sfu_out, + register_set* int_out, + register_set* tensor_core_out, + register_set* mem_out, + int id, + char* config_str ) + : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, dp_out, sfu_out, int_out, tensor_core_out, mem_out, id ), + m_pending_warps() + { + unsigned inner_level_readin; + unsigned outer_level_readin; + int ret = sscanf( config_str, + "two_level_active:%d:%d:%d", + &m_max_active_warps, + &inner_level_readin, + &outer_level_readin); + assert( 3 == ret ); + m_inner_level_prioritization=(scheduler_prioritization_type)inner_level_readin; + m_outer_level_prioritization=(scheduler_prioritization_type)outer_level_readin; + } + virtual ~two_level_active_scheduler () {} + virtual void order_warps(); + void add_supervised_warp_id(int i) { + if ( m_next_cycle_prioritized_warps.size() < m_max_active_warps ) { + m_next_cycle_prioritized_warps.push_back( &warp(i) ); + } else { + m_pending_warps.push_back(&warp(i)); + } + } + virtual void done_adding_supervised_warps() { + m_last_supervised_issued = m_supervised_warps.begin(); } - } - virtual void done_adding_supervised_warps() { - m_last_supervised_issued = m_supervised_warps.begin(); - } - protected: - virtual void do_on_warp_issued( - unsigned warp_id, unsigned num_issued, - const std::vector<shd_warp_t *>::const_iterator &prioritized_iter); +protected: + virtual void do_on_warp_issued( unsigned warp_id, + unsigned num_issued, + const std::vector< shd_warp_t* >::const_iterator& prioritized_iter ); - private: - std::deque<shd_warp_t *> m_pending_warps; - scheduler_prioritization_type m_inner_level_prioritization; - scheduler_prioritization_type m_outer_level_prioritization; - unsigned m_max_active_warps; +private: + std::deque< shd_warp_t* > m_pending_warps; + scheduler_prioritization_type m_inner_level_prioritization; + scheduler_prioritization_type m_outer_level_prioritization; + unsigned m_max_active_warps; }; // Static Warp Limiting Scheduler class swl_scheduler : public scheduler_unit { - public: - swl_scheduler(shader_core_stats *stats, shader_core_ctx *shader, - Scoreboard *scoreboard, simt_stack **simt, - std::vector<shd_warp_t> *warp, register_set *sp_out, - register_set *dp_out, register_set *sfu_out, - register_set *int_out, register_set *tensor_core_out, - register_set *mem_out, int id, char *config_string); - virtual ~swl_scheduler() {} - virtual void order_warps(); - virtual void done_adding_supervised_warps() { - m_last_supervised_issued = m_supervised_warps.begin(); - } +public: + swl_scheduler ( shader_core_stats* stats, shader_core_ctx* shader, + Scoreboard* scoreboard, simt_stack** simt, + std::vector<shd_warp_t>* warp, + register_set* sp_out, + register_set* dp_out, + register_set* sfu_out, + register_set* int_out, + register_set* tensor_core_out, + register_set* mem_out, + int id, + char* config_string ); + virtual ~swl_scheduler () {} + virtual void order_warps (); + virtual void done_adding_supervised_warps() { + m_last_supervised_issued = m_supervised_warps.begin(); + } - protected: - scheduler_prioritization_type m_prioritization; - unsigned m_num_warps_to_limit; +protected: + scheduler_prioritization_type m_prioritization; + unsigned m_num_warps_to_limit; }; -class opndcoll_rfu_t { // operand collector based register file unit - public: - // constructors - opndcoll_rfu_t() { - m_num_banks = 0; - m_shader = NULL; - m_initialized = false; - } - void add_cu_set(unsigned cu_set, unsigned num_cu, unsigned num_dispatch); - typedef std::vector<register_set *> port_vector_t; - typedef std::vector<unsigned int> uint_vector_t; - void add_port(port_vector_t &input, port_vector_t &ouput, - uint_vector_t cu_sets); - void init(unsigned num_banks, shader_core_ctx *shader); - // modifiers - bool writeback(warp_inst_t &warp); - void step() { - dispatch_ready_cu(); - allocate_reads(); - for (unsigned p = 0; p < m_in_ports.size(); p++) allocate_cu(p); - process_banks(); - } +class opndcoll_rfu_t { // operand collector based register file unit +public: + // constructors + opndcoll_rfu_t() + { + m_num_banks=0; + m_shader=NULL; + m_initialized=false; + } + void add_cu_set(unsigned cu_set, unsigned num_cu, unsigned num_dispatch); + typedef std::vector<register_set*> port_vector_t; + typedef std::vector<unsigned int> uint_vector_t; + void add_port( port_vector_t & input, port_vector_t & ouput, uint_vector_t cu_sets); + void init( unsigned num_banks, shader_core_ctx *shader ); - void dump(FILE *fp) const { - fprintf(fp, "\n"); - fprintf(fp, "Operand Collector State:\n"); - for (unsigned n = 0; n < m_cu.size(); n++) { - fprintf(fp, " CU-%2u: ", n); - m_cu[n]->dump(fp, m_shader); - } - m_arbiter.dump(fp); - } + // modifiers + bool writeback( warp_inst_t &warp ); - shader_core_ctx *shader_core() { return m_shader; } + void step() + { + dispatch_ready_cu(); + allocate_reads(); + for( unsigned p = 0 ; p < m_in_ports.size(); p++ ) + allocate_cu( p ); + process_banks(); + } - private: - void process_banks() { m_arbiter.reset_alloction(); } + void dump( FILE *fp ) const + { + fprintf(fp,"\n"); + fprintf(fp,"Operand Collector State:\n"); + for( unsigned n=0; n < m_cu.size(); n++ ) { + fprintf(fp," CU-%2u: ", n); + m_cu[n]->dump(fp,m_shader); + } + m_arbiter.dump(fp); + } + + shader_core_ctx *shader_core() { return m_shader; } + +private: + + void process_banks() + { + m_arbiter.reset_alloction(); + } - void dispatch_ready_cu(); - void allocate_cu(unsigned port); - void allocate_reads(); + void dispatch_ready_cu(); + void allocate_cu( unsigned port ); + void allocate_reads(); - // types + // types - class collector_unit_t; + class collector_unit_t; - class op_t { + class op_t { public: - op_t() { m_valid = false; } - op_t(collector_unit_t *cu, unsigned op, unsigned reg, unsigned num_banks, - unsigned bank_warp_shift, bool sub_core_model, - unsigned banks_per_sched, unsigned sched_id) { - m_valid = true; - m_warp = NULL; - m_cu = cu; - m_operand = op; - m_register = reg; - m_shced_id = sched_id; - m_bank = register_bank(reg, cu->get_warp_id(), num_banks, bank_warp_shift, - sub_core_model, banks_per_sched, sched_id); - } - op_t(const warp_inst_t *warp, unsigned reg, unsigned num_banks, - unsigned bank_warp_shift, bool sub_core_model, - unsigned banks_per_sched, unsigned sched_id) { - m_valid = true; - m_warp = warp; - m_register = reg; - m_cu = NULL; - m_operand = -1; - m_shced_id = sched_id; - m_bank = register_bank(reg, warp->warp_id(), num_banks, bank_warp_shift, - sub_core_model, banks_per_sched, sched_id); - } - // accessors - bool valid() const { return m_valid; } - unsigned get_reg() const { - assert(m_valid); - return m_register; - } - unsigned get_wid() const { - if (m_warp) - return m_warp->warp_id(); - else if (m_cu) - return m_cu->get_warp_id(); - else - abort(); - } - unsigned get_sid() const { return m_shced_id; } - unsigned get_active_count() const { - if (m_warp) - return m_warp->active_count(); - else if (m_cu) - return m_cu->get_active_count(); - else - abort(); - } - const active_mask_t &get_active_mask() { - if (m_warp) - return m_warp->get_active_mask(); - else if (m_cu) - return m_cu->get_active_mask(); - else - abort(); - } - unsigned get_sp_op() const { - if (m_warp) - return m_warp->sp_op; - else if (m_cu) - return m_cu->get_sp_op(); - else - abort(); - } - unsigned get_oc_id() const { return m_cu->get_id(); } - unsigned get_bank() const { return m_bank; } - unsigned get_operand() const { return m_operand; } - void dump(FILE *fp) const { - if (m_cu) - fprintf(fp, " <R%u, CU:%u, w:%02u> ", m_register, m_cu->get_id(), - m_cu->get_warp_id()); - else if (!m_warp->empty()) - fprintf(fp, " <R%u, wid:%02u> ", m_register, m_warp->warp_id()); - } - std::string get_reg_string() const { - char buffer[64]; - snprintf(buffer, 64, "R%u", m_register); - return std::string(buffer); - } + op_t() { m_valid = false; } + op_t( collector_unit_t *cu, unsigned op, unsigned reg, unsigned num_banks, unsigned bank_warp_shift, bool sub_core_model, unsigned banks_per_sched, unsigned sched_id ) + { + m_valid = true; + m_warp=NULL; + m_cu = cu; + m_operand = op; + m_register = reg; + m_shced_id = sched_id; + m_bank = register_bank(reg,cu->get_warp_id(),num_banks,bank_warp_shift, sub_core_model, banks_per_sched, sched_id); + } + op_t( const warp_inst_t *warp, unsigned reg, unsigned num_banks, unsigned bank_warp_shift, bool sub_core_model, unsigned banks_per_sched, unsigned sched_id ) + { + m_valid=true; + m_warp=warp; + m_register=reg; + m_cu=NULL; + m_operand = -1; + m_shced_id = sched_id; + m_bank = register_bank(reg,warp->warp_id(),num_banks,bank_warp_shift, sub_core_model, banks_per_sched, sched_id); + } - // modifiers - void reset() { m_valid = false; } + // accessors + bool valid() const { return m_valid; } + unsigned get_reg() const + { + assert( m_valid ); + return m_register; + } + unsigned get_wid() const + { + if( m_warp ) return m_warp->warp_id(); + else if( m_cu ) return m_cu->get_warp_id(); + else abort(); + } + unsigned get_sid() const + { + return m_shced_id; + } + unsigned get_active_count() const + { + if( m_warp ) return m_warp->active_count(); + else if( m_cu ) return m_cu->get_active_count(); + else abort(); + } + const active_mask_t & get_active_mask() + { + if( m_warp ) return m_warp->get_active_mask(); + else if( m_cu ) return m_cu->get_active_mask(); + else abort(); + } + unsigned get_sp_op() const + { + if( m_warp ) return m_warp->sp_op; + else if( m_cu ) return m_cu->get_sp_op(); + else abort(); + } + unsigned get_oc_id() const { return m_cu->get_id(); } + unsigned get_bank() const { return m_bank; } + unsigned get_operand() const { return m_operand; } + void dump(FILE *fp) const + { + if(m_cu) + fprintf(fp," <R%u, CU:%u, w:%02u> ", m_register,m_cu->get_id(),m_cu->get_warp_id()); + else if( !m_warp->empty() ) + fprintf(fp," <R%u, wid:%02u> ", m_register,m_warp->warp_id() ); + } + std::string get_reg_string() const + { + char buffer[64]; + snprintf(buffer,64,"R%u", m_register); + return std::string(buffer); + } + // modifiers + void reset() { m_valid = false; } private: - bool m_valid; - collector_unit_t *m_cu; - const warp_inst_t *m_warp; - unsigned m_operand; // operand offset in instruction. e.g., add r1,r2,r3; - // r2 is oprd 0, r3 is 1 (r1 is dst) - unsigned m_register; - unsigned m_bank; - unsigned m_shced_id; // scheduler id that has issued this inst - }; + bool m_valid; + collector_unit_t *m_cu; + const warp_inst_t *m_warp; + unsigned m_operand; // operand offset in instruction. e.g., add r1,r2,r3; r2 is oprd 0, r3 is 1 (r1 is dst) + unsigned m_register; + unsigned m_bank; + unsigned m_shced_id; //scheduler id that has issued this inst + }; - enum alloc_t { - NO_ALLOC, - READ_ALLOC, - WRITE_ALLOC, - }; + enum alloc_t { + NO_ALLOC, + READ_ALLOC, + WRITE_ALLOC, + }; - class allocation_t { + class allocation_t { public: - allocation_t() { m_allocation = NO_ALLOC; } - bool is_read() const { return m_allocation == READ_ALLOC; } - bool is_write() const { return m_allocation == WRITE_ALLOC; } - bool is_free() const { return m_allocation == NO_ALLOC; } - void dump(FILE *fp) const { - if (m_allocation == NO_ALLOC) { - fprintf(fp, "<free>"); - } else if (m_allocation == READ_ALLOC) { - fprintf(fp, "rd: "); - m_op.dump(fp); - } else if (m_allocation == WRITE_ALLOC) { - fprintf(fp, "wr: "); - m_op.dump(fp); + allocation_t() { m_allocation = NO_ALLOC; } + bool is_read() const { return m_allocation==READ_ALLOC; } + bool is_write() const {return m_allocation==WRITE_ALLOC; } + bool is_free() const {return m_allocation==NO_ALLOC; } + void dump(FILE *fp) const { + if( m_allocation == NO_ALLOC ) { fprintf(fp,"<free>"); } + else if( m_allocation == READ_ALLOC ) { fprintf(fp,"rd: "); m_op.dump(fp); } + else if( m_allocation == WRITE_ALLOC ) { fprintf(fp,"wr: "); m_op.dump(fp); } + fprintf(fp,"\n"); } - fprintf(fp, "\n"); - } - void alloc_read(const op_t &op) { - assert(is_free()); - m_allocation = READ_ALLOC; - m_op = op; - } - void alloc_write(const op_t &op) { - assert(is_free()); - m_allocation = WRITE_ALLOC; - m_op = op; - } - void reset() { m_allocation = NO_ALLOC; } - + void alloc_read( const op_t &op ) { assert(is_free()); m_allocation=READ_ALLOC; m_op=op; } + void alloc_write( const op_t &op ) { assert(is_free()); m_allocation=WRITE_ALLOC; m_op=op; } + void reset() { m_allocation = NO_ALLOC; } private: - enum alloc_t m_allocation; - op_t m_op; - }; + enum alloc_t m_allocation; + op_t m_op; + }; - class arbiter_t { + class arbiter_t { public: - // constructors - arbiter_t() { - m_queue = NULL; - m_allocated_bank = NULL; - m_allocator_rr_head = NULL; - _inmatch = NULL; - _outmatch = NULL; - _request = NULL; - m_last_cu = 0; - } - void init(unsigned num_cu, unsigned num_banks) { - assert(num_cu > 0); - assert(num_banks > 0); - m_num_collectors = num_cu; - m_num_banks = num_banks; - _inmatch = new int[m_num_banks]; - _outmatch = new int[m_num_collectors]; - _request = new int *[m_num_banks]; - for (unsigned i = 0; i < m_num_banks; i++) - _request[i] = new int[m_num_collectors]; - m_queue = new std::list<op_t>[num_banks]; - m_allocated_bank = new allocation_t[num_banks]; - m_allocator_rr_head = new unsigned[num_cu]; - for (unsigned n = 0; n < num_cu; n++) - m_allocator_rr_head[n] = n % num_banks; - reset_alloction(); - } - - // accessors - void dump(FILE *fp) const { - fprintf(fp, "\n"); - fprintf(fp, " Arbiter State:\n"); - fprintf(fp, " requests:\n"); - for (unsigned b = 0; b < m_num_banks; b++) { - fprintf(fp, " bank %u : ", b); - std::list<op_t>::const_iterator o = m_queue[b].begin(); - for (; o != m_queue[b].end(); o++) { - o->dump(fp); - } - fprintf(fp, "\n"); + // constructors + arbiter_t() + { + m_queue=NULL; + m_allocated_bank=NULL; + m_allocator_rr_head=NULL; + _inmatch=NULL; + _outmatch=NULL; + _request=NULL; + m_last_cu=0; } - fprintf(fp, " grants:\n"); - for (unsigned b = 0; b < m_num_banks; b++) { - fprintf(fp, " bank %u : ", b); - m_allocated_bank[b].dump(fp); + void init( unsigned num_cu, unsigned num_banks ) + { + assert(num_cu > 0); + assert(num_banks > 0); + m_num_collectors = num_cu; + m_num_banks = num_banks; + _inmatch = new int[ m_num_banks ]; + _outmatch = new int[ m_num_collectors ]; + _request = new int*[ m_num_banks ]; + for(unsigned i=0; i<m_num_banks;i++) + _request[i] = new int[m_num_collectors]; + m_queue = new std::list<op_t>[num_banks]; + m_allocated_bank = new allocation_t[num_banks]; + m_allocator_rr_head = new unsigned[num_cu]; + for( unsigned n=0; n<num_cu;n++ ) + m_allocator_rr_head[n] = n%num_banks; + reset_alloction(); } - fprintf(fp, "\n"); - } - // modifiers - std::list<op_t> allocate_reads(); + // accessors + void dump(FILE *fp) const + { + fprintf(fp,"\n"); + fprintf(fp," Arbiter State:\n"); + fprintf(fp," requests:\n"); + for( unsigned b=0; b<m_num_banks; b++ ) { + fprintf(fp," bank %u : ", b ); + std::list<op_t>::const_iterator o = m_queue[b].begin(); + for(; o != m_queue[b].end(); o++ ) { + o->dump(fp); + } + fprintf(fp,"\n"); + } + fprintf(fp," grants:\n"); + for(unsigned b=0;b<m_num_banks;b++) { + fprintf(fp," bank %u : ", b ); + m_allocated_bank[b].dump(fp); + } + fprintf(fp,"\n"); + } - void add_read_requests(collector_unit_t *cu) { - const op_t *src = cu->get_operands(); - for (unsigned i = 0; i < MAX_REG_OPERANDS * 2; i++) { - const op_t &op = src[i]; - if (op.valid()) { - unsigned bank = op.get_bank(); - m_queue[bank].push_back(op); - } + // modifiers + std::list<op_t> allocate_reads(); + + void add_read_requests( collector_unit_t *cu ) + { + const op_t *src = cu->get_operands(); + for( unsigned i=0; i<MAX_REG_OPERANDS*2; i++) { + const op_t &op = src[i]; + if( op.valid() ) { + unsigned bank = op.get_bank(); + m_queue[bank].push_back(op); + } + } + } + bool bank_idle( unsigned bank ) const + { + return m_allocated_bank[bank].is_free(); + } + void allocate_bank_for_write( unsigned bank, const op_t &op ) + { + assert( bank < m_num_banks ); + m_allocated_bank[bank].alloc_write(op); + } + void allocate_for_read( unsigned bank, const op_t &op ) + { + assert( bank < m_num_banks ); + m_allocated_bank[bank].alloc_read(op); + } + void reset_alloction() + { + for( unsigned b=0; b < m_num_banks; b++ ) + m_allocated_bank[b].reset(); } - } - bool bank_idle(unsigned bank) const { - return m_allocated_bank[bank].is_free(); - } - void allocate_bank_for_write(unsigned bank, const op_t &op) { - assert(bank < m_num_banks); - m_allocated_bank[bank].alloc_write(op); - } - void allocate_for_read(unsigned bank, const op_t &op) { - assert(bank < m_num_banks); - m_allocated_bank[bank].alloc_read(op); - } - void reset_alloction() { - for (unsigned b = 0; b < m_num_banks; b++) m_allocated_bank[b].reset(); - } private: - unsigned m_num_banks; - unsigned m_num_collectors; + unsigned m_num_banks; + unsigned m_num_collectors; - allocation_t *m_allocated_bank; // bank # -> register that wins - std::list<op_t> *m_queue; + allocation_t *m_allocated_bank; // bank # -> register that wins + std::list<op_t> *m_queue; - unsigned * - m_allocator_rr_head; // cu # -> next bank to check for request (rr-arb) - unsigned m_last_cu; // first cu to check while arb-ing banks (rr) + unsigned *m_allocator_rr_head; // cu # -> next bank to check for request (rr-arb) + unsigned m_last_cu; // first cu to check while arb-ing banks (rr) - int *_inmatch; - int *_outmatch; - int **_request; - }; + int *_inmatch; + int *_outmatch; + int **_request; + }; - class input_port_t { + class input_port_t { public: - input_port_t(port_vector_t &input, port_vector_t &output, - uint_vector_t cu_sets) - : m_in(input), m_out(output), m_cu_sets(cu_sets) { - assert(input.size() == output.size()); - assert(not m_cu_sets.empty()); - } - // private: - port_vector_t m_in, m_out; - uint_vector_t m_cu_sets; - }; + input_port_t(port_vector_t & input, port_vector_t & output, uint_vector_t cu_sets) + : m_in(input),m_out(output), m_cu_sets(cu_sets) + { + assert(input.size() == output.size()); + assert(not m_cu_sets.empty()); + } + //private: + port_vector_t m_in,m_out; + uint_vector_t m_cu_sets; + }; - class collector_unit_t { + class collector_unit_t { public: - // constructors - collector_unit_t() { - m_free = true; - m_warp = NULL; - m_output_register = NULL; - m_src_op = new op_t[MAX_REG_OPERANDS * 2]; - m_not_ready.reset(); - m_warp_id = -1; - m_num_banks = 0; - m_bank_warp_shift = 0; - } - // accessors - bool ready() const; - const op_t *get_operands() const { return m_src_op; } - void dump(FILE *fp, const shader_core_ctx *shader) const; + // constructors + collector_unit_t() + { + m_free = true; + m_warp = NULL; + m_output_register = NULL; + m_src_op = new op_t[MAX_REG_OPERANDS*2]; + m_not_ready.reset(); + m_warp_id = -1; + m_num_banks = 0; + m_bank_warp_shift = 0; + } + // accessors + bool ready() const; + const op_t *get_operands() const { return m_src_op; } + void dump(FILE *fp, const shader_core_ctx *shader ) const; - unsigned get_warp_id() const { return m_warp_id; } - unsigned get_active_count() const { return m_warp->active_count(); } - const active_mask_t &get_active_mask() const { - return m_warp->get_active_mask(); - } - unsigned get_sp_op() const { return m_warp->sp_op; } - unsigned get_id() const { return m_cuid; } // returns CU hw id + unsigned get_warp_id() const { return m_warp_id; } + unsigned get_active_count() const { return m_warp->active_count(); } + const active_mask_t & get_active_mask() const { return m_warp->get_active_mask(); } + unsigned get_sp_op() const { return m_warp->sp_op; } + unsigned get_id() const { return m_cuid; } // returns CU hw id - // modifiers - void init(unsigned n, unsigned num_banks, unsigned log2_warp_size, - const core_config *config, opndcoll_rfu_t *rfu, - bool m_sub_core_model, unsigned num_banks_per_sched); - bool allocate(register_set *pipeline_reg, register_set *output_reg); + // modifiers + void init(unsigned n, + unsigned num_banks, + unsigned log2_warp_size, + const core_config *config, + opndcoll_rfu_t *rfu, + bool m_sub_core_model, + unsigned num_banks_per_sched); + bool allocate( register_set* pipeline_reg, register_set* output_reg ); - void collect_operand(unsigned op) { m_not_ready.reset(op); } - unsigned get_num_operands() const { return m_warp->get_num_operands(); } - unsigned get_num_regs() const { return m_warp->get_num_regs(); } - void dispatch(); - bool is_free() { return m_free; } + void collect_operand( unsigned op ) + { + m_not_ready.reset(op); + } + unsigned get_num_operands() const{ + return m_warp->get_num_operands(); + } + unsigned get_num_regs() const{ + return m_warp->get_num_regs(); + } + void dispatch(); + bool is_free(){return m_free;} private: - bool m_free; - unsigned m_cuid; // collector unit hw id - unsigned m_warp_id; - warp_inst_t *m_warp; - register_set - *m_output_register; // pipeline register to issue to when ready - op_t *m_src_op; - std::bitset<MAX_REG_OPERANDS * 2> m_not_ready; - unsigned m_num_banks; - unsigned m_bank_warp_shift; - opndcoll_rfu_t *m_rfu; + bool m_free; + unsigned m_cuid; // collector unit hw id + unsigned m_warp_id; + warp_inst_t *m_warp; + register_set* m_output_register; // pipeline register to issue to when ready + op_t *m_src_op; + std::bitset<MAX_REG_OPERANDS*2> m_not_ready; + unsigned m_num_banks; + unsigned m_bank_warp_shift; + opndcoll_rfu_t *m_rfu; + + unsigned m_num_banks_per_sched; + bool m_sub_core_model; - unsigned m_num_banks_per_sched; - bool m_sub_core_model; - }; + }; - class dispatch_unit_t { + class dispatch_unit_t { public: - dispatch_unit_t(std::vector<collector_unit_t> *cus) { - m_last_cu = 0; - m_collector_units = cus; - m_num_collectors = (*cus).size(); - m_next_cu = 0; - } + dispatch_unit_t(std::vector<collector_unit_t>* cus) + { + m_last_cu=0; + m_collector_units=cus; + m_num_collectors = (*cus).size(); + m_next_cu=0; + } - collector_unit_t *find_ready() { - for (unsigned n = 0; n < m_num_collectors; n++) { - unsigned c = (m_last_cu + n + 1) % m_num_collectors; - if ((*m_collector_units)[c].ready()) { - m_last_cu = c; - return &((*m_collector_units)[c]); - } + collector_unit_t *find_ready() + { + for( unsigned n=0; n < m_num_collectors; n++ ) { + unsigned c=(m_last_cu+n+1)%m_num_collectors; + if( (*m_collector_units)[c].ready() ) { + m_last_cu=c; + return &((*m_collector_units)[c]); + } + } + return NULL; } - return NULL; - } private: - unsigned m_num_collectors; - std::vector<collector_unit_t> *m_collector_units; - unsigned m_last_cu; // dispatch ready cu's rr - unsigned m_next_cu; // for initialization - }; + unsigned m_num_collectors; + std::vector<collector_unit_t>* m_collector_units; + unsigned m_last_cu; // dispatch ready cu's rr + unsigned m_next_cu; // for initialization + }; - // opndcoll_rfu_t data members - bool m_initialized; + // opndcoll_rfu_t data members + bool m_initialized; - unsigned m_num_collector_sets; - // unsigned m_num_collectors; - unsigned m_num_banks; - unsigned m_bank_warp_shift; - unsigned m_warp_size; - std::vector<collector_unit_t *> m_cu; - arbiter_t m_arbiter; + unsigned m_num_collector_sets; + //unsigned m_num_collectors; + unsigned m_num_banks; + unsigned m_bank_warp_shift; + unsigned m_warp_size; + std::vector<collector_unit_t *> m_cu; + arbiter_t m_arbiter; - unsigned m_num_banks_per_sched; - unsigned m_num_warp_sceds; - bool sub_core_model; + unsigned m_num_banks_per_sched; + unsigned m_num_warp_sceds; + bool sub_core_model; - // unsigned m_num_ports; - // std::vector<warp_inst_t**> m_input; - // std::vector<warp_inst_t**> m_output; - // std::vector<unsigned> m_num_collector_units; - // warp_inst_t **m_alu_port; + //unsigned m_num_ports; + //std::vector<warp_inst_t**> m_input; + //std::vector<warp_inst_t**> m_output; + //std::vector<unsigned> m_num_collector_units; + //warp_inst_t **m_alu_port; - std::vector<input_port_t> m_in_ports; - typedef std::map<unsigned /* collector set */, - std::vector<collector_unit_t> /*collector sets*/> - cu_sets_t; - cu_sets_t m_cus; - std::vector<dispatch_unit_t> m_dispatch_units; + std::vector<input_port_t> m_in_ports; + typedef std::map<unsigned /* collector set */, std::vector<collector_unit_t> /*collector sets*/ > cu_sets_t; + cu_sets_t m_cus; + std::vector<dispatch_unit_t> m_dispatch_units; - // typedef std::map<warp_inst_t**/*port*/,dispatch_unit_t> port_to_du_t; - // port_to_du_t m_dispatch_units; - // std::map<warp_inst_t**,std::list<collector_unit_t*> > m_free_cu; - shader_core_ctx *m_shader; + //typedef std::map<warp_inst_t**/*port*/,dispatch_unit_t> port_to_du_t; + //port_to_du_t m_dispatch_units; + //std::map<warp_inst_t**,std::list<collector_unit_t*> > m_free_cu; + shader_core_ctx *m_shader; }; class barrier_set_t { - public: - barrier_set_t(shader_core_ctx *shader, unsigned max_warps_per_core, - unsigned max_cta_per_core, unsigned max_barriers_per_cta, - unsigned warp_size); +public: + barrier_set_t(shader_core_ctx * shader, unsigned max_warps_per_core, unsigned max_cta_per_core, unsigned max_barriers_per_cta, unsigned warp_size); + + // during cta allocation + void allocate_barrier( unsigned cta_id, warp_set_t warps ); + + // during cta deallocation + void deallocate_barrier( unsigned cta_id ); + + typedef std::map<unsigned, warp_set_t > cta_to_warp_t; + typedef std::map<unsigned, warp_set_t > bar_id_to_warp_t; /*set of warps reached a specific barrier id*/ - // during cta allocation - void allocate_barrier(unsigned cta_id, warp_set_t warps); - // during cta deallocation - void deallocate_barrier(unsigned cta_id); + // individual warp hits barrier + void warp_reaches_barrier( unsigned cta_id, unsigned warp_id, warp_inst_t* inst); - typedef std::map<unsigned, warp_set_t> cta_to_warp_t; - typedef std::map<unsigned, warp_set_t> - bar_id_to_warp_t; /*set of warps reached a specific barrier id*/ - // individual warp hits barrier - void warp_reaches_barrier(unsigned cta_id, unsigned warp_id, - warp_inst_t *inst); + // warp reaches exit + void warp_exit( unsigned warp_id ); - // warp reaches exit - void warp_exit(unsigned warp_id); + // assertions + bool warp_waiting_at_barrier( unsigned warp_id ) const; - // assertions - bool warp_waiting_at_barrier(unsigned warp_id) const; + // debug + void dump(); - // debug - void dump(); +private: + unsigned m_max_cta_per_core; + unsigned m_max_warps_per_core; + unsigned m_max_barriers_per_cta; + unsigned m_warp_size; + cta_to_warp_t m_cta_to_warps; + bar_id_to_warp_t m_bar_id_to_warps; + warp_set_t m_warp_active; + warp_set_t m_warp_at_barrier; + shader_core_ctx *m_shader; - private: - unsigned m_max_cta_per_core; - unsigned m_max_warps_per_core; - unsigned m_max_barriers_per_cta; - unsigned m_warp_size; - cta_to_warp_t m_cta_to_warps; - bar_id_to_warp_t m_bar_id_to_warps; - warp_set_t m_warp_active; - warp_set_t m_warp_at_barrier; - shader_core_ctx *m_shader; }; struct insn_latency_info { - unsigned pc; - unsigned long latency; + unsigned pc; + unsigned long latency; }; struct ifetch_buffer_t { - ifetch_buffer_t() { m_valid = false; } + ifetch_buffer_t() { m_valid=false; } - ifetch_buffer_t(address_type pc, unsigned nbytes, unsigned warp_id) { - m_valid = true; - m_pc = pc; - m_nbytes = nbytes; - m_warp_id = warp_id; - } + ifetch_buffer_t( address_type pc, unsigned nbytes, unsigned warp_id ) + { + m_valid=true; + m_pc=pc; + m_nbytes=nbytes; + m_warp_id=warp_id; + } - bool m_valid; - address_type m_pc; - unsigned m_nbytes; - unsigned m_warp_id; + bool m_valid; + address_type m_pc; + unsigned m_nbytes; + unsigned m_warp_id; }; class shader_core_config; class simd_function_unit { - public: - simd_function_unit(const shader_core_config *config); - ~simd_function_unit() { delete m_dispatch_reg; } +public: + simd_function_unit( const shader_core_config *config ); + ~simd_function_unit() { delete m_dispatch_reg; } - // modifiers - virtual void issue(register_set &source_reg) { - source_reg.move_out_to(m_dispatch_reg); - occupied.set(m_dispatch_reg->latency); - } - virtual void cycle() = 0; - virtual void active_lanes_in_pipeline() = 0; - - // accessors - virtual unsigned clock_multiplier() const { return 1; } - virtual bool can_issue(const warp_inst_t &inst) const { - return m_dispatch_reg->empty() && !occupied.test(inst.latency); - } - virtual bool stallable() const = 0; - virtual void print(FILE *fp) const { - fprintf(fp, "%s dispatch= ", m_name.c_str()); - m_dispatch_reg->print(fp); - } - const char *get_name() { return m_name.c_str(); } + // modifiers + virtual void issue( register_set& source_reg ) { source_reg.move_out_to(m_dispatch_reg); occupied.set(m_dispatch_reg->latency);} + virtual void cycle() = 0; + virtual void active_lanes_in_pipeline() = 0; - protected: - std::string m_name; - const shader_core_config *m_config; - warp_inst_t *m_dispatch_reg; - static const unsigned MAX_ALU_LATENCY = 512; - std::bitset<MAX_ALU_LATENCY> occupied; + // accessors + virtual unsigned clock_multiplier() const { return 1; } + virtual bool can_issue( const warp_inst_t &inst ) const { return m_dispatch_reg->empty() && !occupied.test(inst.latency); } + virtual bool stallable() const = 0; + virtual void print( FILE *fp ) const + { + fprintf(fp,"%s dispatch= ", m_name.c_str() ); + m_dispatch_reg->print(fp); + } + const char* get_name() { + return m_name.c_str(); + } +protected: + std::string m_name; + const shader_core_config *m_config; + warp_inst_t *m_dispatch_reg; + static const unsigned MAX_ALU_LATENCY = 512; + std::bitset<MAX_ALU_LATENCY> occupied; }; class pipelined_simd_unit : public simd_function_unit { - public: - pipelined_simd_unit(register_set *result_port, - const shader_core_config *config, unsigned max_latency, - shader_core_ctx *core); +public: + pipelined_simd_unit( register_set* result_port, const shader_core_config *config, unsigned max_latency, shader_core_ctx *core ); - // modifiers - virtual void cycle(); - virtual void issue(register_set &source_reg); - virtual unsigned get_active_lanes_in_pipeline(); + //modifiers + virtual void cycle(); + virtual void issue( register_set& source_reg ); + virtual unsigned get_active_lanes_in_pipeline(); - virtual void active_lanes_in_pipeline() = 0; - /* - virtual void issue( register_set& source_reg ) - { - //move_warp(m_dispatch_reg,source_reg); - //source_reg.move_out_to(m_dispatch_reg); - simd_function_unit::issue(source_reg); - } - */ - // accessors - virtual bool stallable() const { return false; } - virtual bool can_issue(const warp_inst_t &inst) const { - return simd_function_unit::can_issue(inst); - } - virtual void print(FILE *fp) const { - simd_function_unit::print(fp); - for (int s = m_pipeline_depth - 1; s >= 0; s--) { - if (!m_pipeline_reg[s]->empty()) { - fprintf(fp, " %s[%2d] ", m_name.c_str(), s); - m_pipeline_reg[s]->print(fp); - } + virtual void active_lanes_in_pipeline() = 0; +/* + virtual void issue( register_set& source_reg ) + { + //move_warp(m_dispatch_reg,source_reg); + //source_reg.move_out_to(m_dispatch_reg); + simd_function_unit::issue(source_reg); + } +*/ + // accessors + virtual bool stallable() const { return false; } + virtual bool can_issue( const warp_inst_t &inst ) const + { + return simd_function_unit::can_issue(inst); } - } + virtual void print(FILE *fp) const + { + simd_function_unit::print(fp); + for( int s=m_pipeline_depth-1; s>=0; s-- ) { + if( !m_pipeline_reg[s]->empty() ) { + fprintf(fp," %s[%2d] ", m_name.c_str(), s ); + m_pipeline_reg[s]->print(fp); + } + } + } +protected: + unsigned m_pipeline_depth; + warp_inst_t **m_pipeline_reg; + register_set *m_result_port; + class shader_core_ctx *m_core; - protected: - unsigned m_pipeline_depth; - warp_inst_t **m_pipeline_reg; - register_set *m_result_port; - class shader_core_ctx *m_core; + unsigned active_insts_in_pipeline; - unsigned active_insts_in_pipeline; }; -class sfu : public pipelined_simd_unit { - public: - sfu(register_set *result_port, const shader_core_config *config, - shader_core_ctx *core); - virtual bool can_issue(const warp_inst_t &inst) const { - switch (inst.op) { - case SFU_OP: - break; - case ALU_SFU_OP: - break; - case DP_OP: - break; // for compute <= 29 (i..e Fermi and GT200) - default: - return false; +class sfu : public pipelined_simd_unit +{ +public: + sfu( register_set* result_port, const shader_core_config *config, shader_core_ctx *core ); + virtual bool can_issue( const warp_inst_t &inst ) const + { + switch(inst.op) { + case SFU_OP: break; + case ALU_SFU_OP: break; + case DP_OP: break; //for compute <= 29 (i..e Fermi and GT200) + default: return false; + } + return pipelined_simd_unit::can_issue(inst); } - return pipelined_simd_unit::can_issue(inst); - } - virtual void active_lanes_in_pipeline(); - virtual void issue(register_set &source_reg); + virtual void active_lanes_in_pipeline(); + virtual void issue( register_set& source_reg ); }; -class dp_unit : public pipelined_simd_unit { - public: - dp_unit(register_set *result_port, const shader_core_config *config, - shader_core_ctx *core); - virtual bool can_issue(const warp_inst_t &inst) const { - switch (inst.op) { - case DP_OP: - break; - default: - return false; +class dp_unit : public pipelined_simd_unit +{ +public: + dp_unit( register_set* result_port, const shader_core_config *config, shader_core_ctx *core ); + virtual bool can_issue( const warp_inst_t &inst ) const + { + switch(inst.op) { + case DP_OP: break; + default: return false; + } + return pipelined_simd_unit::can_issue(inst); } - return pipelined_simd_unit::can_issue(inst); - } - virtual void active_lanes_in_pipeline(); - virtual void issue(register_set &source_reg); + virtual void active_lanes_in_pipeline(); + virtual void issue( register_set& source_reg ); }; -class tensor_core : public pipelined_simd_unit { - public: - tensor_core(register_set *result_port, const shader_core_config *config, - shader_core_ctx *core); - virtual bool can_issue(const warp_inst_t &inst) const { - switch (inst.op) { - case TENSOR_CORE_OP: - break; - default: - return false; +class tensor_core : public pipelined_simd_unit +{ +public: + tensor_core( register_set* result_port, const shader_core_config *config, shader_core_ctx *core ); + virtual bool can_issue( const warp_inst_t &inst ) const + { + switch(inst.op) { + case TENSOR_CORE_OP: break; + default: return false; + } + return pipelined_simd_unit::can_issue(inst); } - return pipelined_simd_unit::can_issue(inst); - } - virtual void active_lanes_in_pipeline(); - virtual void issue(register_set &source_reg); + virtual void active_lanes_in_pipeline(); + virtual void issue( register_set& source_reg ); }; -class int_unit : public pipelined_simd_unit { - public: - int_unit(register_set *result_port, const shader_core_config *config, - shader_core_ctx *core); - virtual bool can_issue(const warp_inst_t &inst) const { - switch (inst.op) { - case SFU_OP: - return false; - case LOAD_OP: - return false; - case TENSOR_CORE_LOAD_OP: - return false; - case STORE_OP: - return false; - case TENSOR_CORE_STORE_OP: - return false; - case MEMORY_BARRIER_OP: - return false; - case SP_OP: - return false; - case DP_OP: - return false; - default: - break; + +class int_unit : public pipelined_simd_unit +{ +public: + int_unit( register_set* result_port, const shader_core_config *config, shader_core_ctx *core ); + virtual bool can_issue( const warp_inst_t &inst ) const + { + switch(inst.op) { + case SFU_OP: return false; + case LOAD_OP: return false; + case TENSOR_CORE_LOAD_OP: return false; + case STORE_OP: return false; + case TENSOR_CORE_STORE_OP: return false; + case MEMORY_BARRIER_OP: return false; + case SP_OP: return false; + case DP_OP: return false; + default: break; + } + return pipelined_simd_unit::can_issue(inst); } - return pipelined_simd_unit::can_issue(inst); - } - virtual void active_lanes_in_pipeline(); - virtual void issue(register_set &source_reg); + virtual void active_lanes_in_pipeline(); + virtual void issue( register_set& source_reg ); }; -class sp_unit : public pipelined_simd_unit { - public: - sp_unit(register_set *result_port, const shader_core_config *config, - shader_core_ctx *core); - virtual bool can_issue(const warp_inst_t &inst) const { - switch (inst.op) { - case SFU_OP: - return false; - case LOAD_OP: - return false; - case TENSOR_CORE_LOAD_OP: - return false; - case STORE_OP: - return false; - case TENSOR_CORE_STORE_OP: - return false; - case MEMORY_BARRIER_OP: - return false; - case DP_OP: - return false; - default: - break; +class sp_unit : public pipelined_simd_unit +{ +public: + sp_unit( register_set* result_port, const shader_core_config *config, shader_core_ctx *core ); + virtual bool can_issue( const warp_inst_t &inst ) const + { + switch(inst.op) { + case SFU_OP: return false; + case LOAD_OP: return false; + case TENSOR_CORE_LOAD_OP: return false; + case STORE_OP: return false; + case TENSOR_CORE_STORE_OP: return false; + case MEMORY_BARRIER_OP: return false; + case DP_OP: return false; + default: break; + } + return pipelined_simd_unit::can_issue(inst); } - return pipelined_simd_unit::can_issue(inst); - } - virtual void active_lanes_in_pipeline(); - virtual void issue(register_set &source_reg); + virtual void active_lanes_in_pipeline(); + virtual void issue( register_set& source_reg ); }; class simt_core_cluster; @@ -1220,1062 +1211,948 @@ class shader_memory_interface; class shader_core_mem_fetch_allocator; class cache_t; -class ldst_unit : public pipelined_simd_unit { - public: - ldst_unit(mem_fetch_interface *icnt, - shader_core_mem_fetch_allocator *mf_allocator, - shader_core_ctx *core, opndcoll_rfu_t *operand_collector, - Scoreboard *scoreboard, const shader_core_config *config, - const memory_config *mem_config, class shader_core_stats *stats, - unsigned sid, unsigned tpc); - - // modifiers - virtual void issue(register_set &inst); - virtual void cycle(); +class ldst_unit: public pipelined_simd_unit { +public: + ldst_unit( mem_fetch_interface *icnt, + shader_core_mem_fetch_allocator *mf_allocator, + shader_core_ctx *core, + opndcoll_rfu_t *operand_collector, + Scoreboard *scoreboard, + const shader_core_config *config, + const memory_config *mem_config, + class shader_core_stats *stats, + unsigned sid, unsigned tpc ); - void fill(mem_fetch *mf); - void flush(); - void invalidate(); - void writeback(); + // modifiers + virtual void issue( register_set &inst ); + virtual void cycle(); + + void fill( mem_fetch *mf ); + void flush(); + void invalidate(); + void writeback(); - // accessors - virtual unsigned clock_multiplier() const; + // accessors + virtual unsigned clock_multiplier() const; - virtual bool can_issue(const warp_inst_t &inst) const { - switch (inst.op) { - case LOAD_OP: - break; - case TENSOR_CORE_LOAD_OP: - break; - case STORE_OP: - break; - case TENSOR_CORE_STORE_OP: - break; - case MEMORY_BARRIER_OP: - break; - default: - return false; + virtual bool can_issue( const warp_inst_t &inst ) const + { + switch(inst.op) { + case LOAD_OP: break; + case TENSOR_CORE_LOAD_OP: break; + case STORE_OP: break; + case TENSOR_CORE_STORE_OP: break; + case MEMORY_BARRIER_OP: break; + default: return false; + } + return m_dispatch_reg->empty(); } - return m_dispatch_reg->empty(); - } - virtual void active_lanes_in_pipeline(); - virtual bool stallable() const { return true; } - bool response_buffer_full() const; - void print(FILE *fout) const; - void print_cache_stats(FILE *fp, unsigned &dl1_accesses, - unsigned &dl1_misses); - void get_cache_stats(unsigned &read_accesses, unsigned &write_accesses, - unsigned &read_misses, unsigned &write_misses, - unsigned cache_type); - void get_cache_stats(cache_stats &cs); + virtual void active_lanes_in_pipeline(); + virtual bool stallable() const { return true; } + bool response_buffer_full() const; + void print(FILE *fout) const; + void print_cache_stats( FILE *fp, unsigned& dl1_accesses, unsigned& dl1_misses ); + void get_cache_stats(unsigned &read_accesses, unsigned &write_accesses, unsigned &read_misses, unsigned &write_misses, unsigned cache_type); + void get_cache_stats(cache_stats &cs); - void get_L1D_sub_stats(struct cache_sub_stats &css) const; - void get_L1C_sub_stats(struct cache_sub_stats &css) const; - void get_L1T_sub_stats(struct cache_sub_stats &css) const; + void get_L1D_sub_stats(struct cache_sub_stats &css) const; + void get_L1C_sub_stats(struct cache_sub_stats &css) const; + void get_L1T_sub_stats(struct cache_sub_stats &css) const; - protected: - ldst_unit(mem_fetch_interface *icnt, - shader_core_mem_fetch_allocator *mf_allocator, - shader_core_ctx *core, opndcoll_rfu_t *operand_collector, - Scoreboard *scoreboard, const shader_core_config *config, - const memory_config *mem_config, shader_core_stats *stats, - unsigned sid, unsigned tpc, l1_cache *new_l1d_cache); - void init(mem_fetch_interface *icnt, - shader_core_mem_fetch_allocator *mf_allocator, - shader_core_ctx *core, opndcoll_rfu_t *operand_collector, - Scoreboard *scoreboard, const shader_core_config *config, - const memory_config *mem_config, shader_core_stats *stats, - unsigned sid, unsigned tpc); +protected: + ldst_unit( mem_fetch_interface *icnt, + shader_core_mem_fetch_allocator *mf_allocator, + shader_core_ctx *core, + opndcoll_rfu_t *operand_collector, + Scoreboard *scoreboard, + const shader_core_config *config, + const memory_config *mem_config, + shader_core_stats *stats, + unsigned sid, + unsigned tpc, + l1_cache* new_l1d_cache ); + void init( mem_fetch_interface *icnt, + shader_core_mem_fetch_allocator *mf_allocator, + shader_core_ctx *core, + opndcoll_rfu_t *operand_collector, + Scoreboard *scoreboard, + const shader_core_config *config, + const memory_config *mem_config, + shader_core_stats *stats, + unsigned sid, + unsigned tpc ); - protected: - bool shared_cycle(warp_inst_t &inst, mem_stage_stall_type &rc_fail, - mem_stage_access_type &fail_type); - bool constant_cycle(warp_inst_t &inst, mem_stage_stall_type &rc_fail, - mem_stage_access_type &fail_type); - bool texture_cycle(warp_inst_t &inst, mem_stage_stall_type &rc_fail, - mem_stage_access_type &fail_type); - bool memory_cycle(warp_inst_t &inst, mem_stage_stall_type &rc_fail, - mem_stage_access_type &fail_type); +protected: + bool shared_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type); + bool constant_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type); + bool texture_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type); + bool memory_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type); - virtual mem_stage_stall_type process_cache_access( - cache_t *cache, new_addr_type address, warp_inst_t &inst, - std::list<cache_event> &events, mem_fetch *mf, - enum cache_request_status status); - mem_stage_stall_type process_memory_access_queue(cache_t *cache, - warp_inst_t &inst); - mem_stage_stall_type process_memory_access_queue_l1cache(l1_cache *cache, - warp_inst_t &inst); + virtual mem_stage_stall_type process_cache_access( cache_t* cache, + new_addr_type address, + warp_inst_t &inst, + std::list<cache_event>& events, + mem_fetch *mf, + enum cache_request_status status ); + mem_stage_stall_type process_memory_access_queue( cache_t *cache, warp_inst_t &inst ); + mem_stage_stall_type process_memory_access_queue_l1cache( l1_cache *cache, warp_inst_t &inst ); - const memory_config *m_memory_config; - class mem_fetch_interface *m_icnt; - shader_core_mem_fetch_allocator *m_mf_allocator; - class shader_core_ctx *m_core; - unsigned m_sid; - unsigned m_tpc; + const memory_config *m_memory_config; + class mem_fetch_interface *m_icnt; + shader_core_mem_fetch_allocator *m_mf_allocator; + class shader_core_ctx *m_core; + unsigned m_sid; + unsigned m_tpc; - tex_cache *m_L1T; // texture cache - read_only_cache *m_L1C; // constant cache - l1_cache *m_L1D; // data cache - std::map<unsigned /*warp_id*/, - std::map<unsigned /*regnum*/, unsigned /*count*/>> - m_pending_writes; - std::list<mem_fetch *> m_response_fifo; - opndcoll_rfu_t *m_operand_collector; - Scoreboard *m_scoreboard; + tex_cache *m_L1T; // texture cache + read_only_cache *m_L1C; // constant cache + l1_cache *m_L1D; // data cache + std::map<unsigned/*warp_id*/, std::map<unsigned/*regnum*/,unsigned/*count*/> > m_pending_writes; + std::list<mem_fetch*> m_response_fifo; + opndcoll_rfu_t *m_operand_collector; + Scoreboard *m_scoreboard; - mem_fetch *m_next_global; - warp_inst_t m_next_wb; - unsigned m_writeback_arb; // round-robin arbiter for writeback contention - // between L1T, L1C, shared - unsigned m_num_writeback_clients; + mem_fetch *m_next_global; + warp_inst_t m_next_wb; + unsigned m_writeback_arb; // round-robin arbiter for writeback contention between L1T, L1C, shared + unsigned m_num_writeback_clients; - enum mem_stage_stall_type m_mem_rc; + enum mem_stage_stall_type m_mem_rc; - shader_core_stats *m_stats; + shader_core_stats *m_stats; - // for debugging - unsigned long long m_last_inst_gpu_sim_cycle; - unsigned long long m_last_inst_gpu_tot_sim_cycle; + // for debugging + unsigned long long m_last_inst_gpu_sim_cycle; + unsigned long long m_last_inst_gpu_tot_sim_cycle; - std::vector<std::deque<mem_fetch *>> l1_latency_queue; - void L1_latency_queue_cycle(); + std::vector<std::deque<mem_fetch* >> l1_latency_queue; + void L1_latency_queue_cycle(); }; enum pipeline_stage_name_t { - ID_OC_SP = 0, - ID_OC_DP, - ID_OC_INT, - ID_OC_SFU, - ID_OC_MEM, - OC_EX_SP, - OC_EX_DP, - OC_EX_INT, - OC_EX_SFU, - OC_EX_MEM, - EX_WB, - ID_OC_TENSOR_CORE, - OC_EX_TENSOR_CORE, - N_PIPELINE_STAGES -}; - -const char *const pipeline_stage_name_decode[] = { - "ID_OC_SP", "ID_OC_DP", "ID_OC_INT", "ID_OC_SFU", - "ID_OC_MEM", "OC_EX_SP", "OC_EX_DP", "OC_EX_INT", - "OC_EX_SFU", "OC_EX_MEM", "EX_WB", "ID_OC_TENSOR_CORE", - "OC_EX_TENSOR_CORE", "N_PIPELINE_STAGES"}; + ID_OC_SP=0, + ID_OC_DP, + ID_OC_INT, + ID_OC_SFU, + ID_OC_MEM, + OC_EX_SP, + OC_EX_DP, + OC_EX_INT, + OC_EX_SFU, + OC_EX_MEM, + EX_WB, + ID_OC_TENSOR_CORE, + OC_EX_TENSOR_CORE, + N_PIPELINE_STAGES + }; -class shader_core_config : public core_config { - public: - shader_core_config(gpgpu_context *ctx) : core_config(ctx) { - pipeline_widths_string = NULL; - gpgpu_ctx = ctx; - } +const char* const pipeline_stage_name_decode[] = { + "ID_OC_SP", + "ID_OC_DP", + "ID_OC_INT", + "ID_OC_SFU", + "ID_OC_MEM", + "OC_EX_SP", + "OC_EX_DP", + "OC_EX_INT", + "OC_EX_SFU", + "OC_EX_MEM", + "EX_WB", + "ID_OC_TENSOR_CORE", + "OC_EX_TENSOR_CORE", + "N_PIPELINE_STAGES" +}; - void init() { - int ntok = sscanf(gpgpu_shader_core_pipeline_opt, "%d:%d", - &n_thread_per_shader, &warp_size); - if (ntok != 2) { - printf( - "GPGPU-Sim uArch: error while parsing configuration string " - "gpgpu_shader_core_pipeline_opt\n"); - abort(); +class shader_core_config : public core_config +{ + public: + shader_core_config(gpgpu_context* ctx):core_config(ctx){ + pipeline_widths_string = NULL; + gpgpu_ctx = ctx; } - char *toks = new char[100]; - char *tokd = toks; - strcpy(toks, pipeline_widths_string); + void init() + { + int ntok = sscanf(gpgpu_shader_core_pipeline_opt,"%d:%d", + &n_thread_per_shader, + &warp_size); + if(ntok != 2) { + printf("GPGPU-Sim uArch: error while parsing configuration string gpgpu_shader_core_pipeline_opt\n"); + abort(); + } - toks = strtok(toks, ","); + char* toks = new char[100]; + char* tokd = toks; + strcpy(toks,pipeline_widths_string); + + toks = strtok(toks,","); - /* Removing the tensorcore pipeline while reading the config files if the - tensor core is not available. - If we won't remove it, old regression will be broken. - So to support the legacy config files it's best to handle in this - way. - */ - int num_config_to_read = N_PIPELINE_STAGES - 2 * (!gpgpu_tensor_core_avail); + /* Removing the tensorcore pipeline while reading the config files if the tensor core is not available. + If we won't remove it, old regression will be broken. + So to support the legacy config files it's best to handle in this way. + */ + int num_config_to_read= N_PIPELINE_STAGES - 2 * (!gpgpu_tensor_core_avail); - for (int i = 0; i < num_config_to_read; i++) { - assert(toks); - ntok = sscanf(toks, "%d", &pipe_widths[i]); - assert(ntok == 1); - toks = strtok(NULL, ","); - } + for (int i = 0; i < num_config_to_read; i++) { + assert(toks); + ntok = sscanf(toks,"%d", &pipe_widths[i]); + assert(ntok == 1); + toks = strtok(NULL,","); + } - delete[] tokd; + delete[] tokd; + + if (n_thread_per_shader > MAX_THREAD_PER_SM) { + printf("GPGPU-Sim uArch: Error ** increase MAX_THREAD_PER_SM in abstract_hardware_model.h from %u to %u\n", + MAX_THREAD_PER_SM, n_thread_per_shader); + abort(); + } + max_warps_per_shader = n_thread_per_shader/warp_size; + assert( !(n_thread_per_shader % warp_size) ); - if (n_thread_per_shader > MAX_THREAD_PER_SM) { - printf( - "GPGPU-Sim uArch: Error ** increase MAX_THREAD_PER_SM in " - "abstract_hardware_model.h from %u to %u\n", - MAX_THREAD_PER_SM, n_thread_per_shader); - abort(); + set_pipeline_latency(); + + m_L1I_config.init(m_L1I_config.m_config_string,FuncCachePreferNone); + m_L1T_config.init(m_L1T_config.m_config_string,FuncCachePreferNone); + m_L1C_config.init(m_L1C_config.m_config_string,FuncCachePreferNone); + m_L1D_config.init(m_L1D_config.m_config_string,FuncCachePreferNone); + gpgpu_cache_texl1_linesize = m_L1T_config.get_line_sz(); + gpgpu_cache_constl1_linesize = m_L1C_config.get_line_sz(); + m_valid = true; } - max_warps_per_shader = n_thread_per_shader / warp_size; - assert(!(n_thread_per_shader % warp_size)); + void reg_options(class OptionParser * opp ); + unsigned max_cta( const kernel_info_t &k ) const; + unsigned num_shader() const { return n_simt_clusters*n_simt_cores_per_cluster; } + unsigned sid_to_cluster( unsigned sid ) const { return sid / n_simt_cores_per_cluster; } + unsigned sid_to_cid( unsigned sid ) const { return sid % n_simt_cores_per_cluster; } + unsigned cid_to_sid( unsigned cid, unsigned cluster_id ) const { return cluster_id*n_simt_cores_per_cluster + cid; } + void set_pipeline_latency(); - set_pipeline_latency(); + // backward pointer + class gpgpu_context* gpgpu_ctx; +// data + char *gpgpu_shader_core_pipeline_opt; + bool gpgpu_perfect_mem; + bool gpgpu_clock_gated_reg_file; + bool gpgpu_clock_gated_lanes; + enum divergence_support_t model; + unsigned n_thread_per_shader; + unsigned n_regfile_gating_group; + unsigned max_warps_per_shader; + unsigned max_cta_per_core; //Limit on number of concurrent CTAs in shader core + unsigned max_barriers_per_cta; + char * gpgpu_scheduler_string; + unsigned gpgpu_shmem_per_block; + unsigned gpgpu_registers_per_block; + char* pipeline_widths_string; + int pipe_widths[N_PIPELINE_STAGES]; - m_L1I_config.init(m_L1I_config.m_config_string, FuncCachePreferNone); - m_L1T_config.init(m_L1T_config.m_config_string, FuncCachePreferNone); - m_L1C_config.init(m_L1C_config.m_config_string, FuncCachePreferNone); - m_L1D_config.init(m_L1D_config.m_config_string, FuncCachePreferNone); - gpgpu_cache_texl1_linesize = m_L1T_config.get_line_sz(); - gpgpu_cache_constl1_linesize = m_L1C_config.get_line_sz(); - m_valid = true; - } - void reg_options(class OptionParser *opp); - unsigned max_cta(const kernel_info_t &k) const; - unsigned num_shader() const { - return n_simt_clusters * n_simt_cores_per_cluster; - } - unsigned sid_to_cluster(unsigned sid) const { - return sid / n_simt_cores_per_cluster; - } - unsigned sid_to_cid(unsigned sid) const { - return sid % n_simt_cores_per_cluster; - } - unsigned cid_to_sid(unsigned cid, unsigned cluster_id) const { - return cluster_id * n_simt_cores_per_cluster + cid; - } - void set_pipeline_latency(); + mutable cache_config m_L1I_config; + mutable cache_config m_L1T_config; + mutable cache_config m_L1C_config; + mutable l1d_cache_config m_L1D_config; - // backward pointer - class gpgpu_context *gpgpu_ctx; - // data - char *gpgpu_shader_core_pipeline_opt; - bool gpgpu_perfect_mem; - bool gpgpu_clock_gated_reg_file; - bool gpgpu_clock_gated_lanes; - enum divergence_support_t model; - unsigned n_thread_per_shader; - unsigned n_regfile_gating_group; - unsigned max_warps_per_shader; - unsigned - max_cta_per_core; // Limit on number of concurrent CTAs in shader core - unsigned max_barriers_per_cta; - char *gpgpu_scheduler_string; - unsigned gpgpu_shmem_per_block; - unsigned gpgpu_registers_per_block; - char *pipeline_widths_string; - int pipe_widths[N_PIPELINE_STAGES]; + bool gpgpu_dwf_reg_bankconflict; - mutable cache_config m_L1I_config; - mutable cache_config m_L1T_config; - mutable cache_config m_L1C_config; - mutable l1d_cache_config m_L1D_config; + unsigned gpgpu_num_sched_per_core; + int gpgpu_max_insn_issue_per_warp; + bool gpgpu_dual_issue_diff_exec_units; - bool gpgpu_dwf_reg_bankconflict; + //op collector + bool enable_specialized_operand_collector; + int gpgpu_operand_collector_num_units_sp; + int gpgpu_operand_collector_num_units_dp; + int gpgpu_operand_collector_num_units_sfu; + int gpgpu_operand_collector_num_units_tensor_core; + int gpgpu_operand_collector_num_units_mem; + int gpgpu_operand_collector_num_units_gen; + int gpgpu_operand_collector_num_units_int; - unsigned gpgpu_num_sched_per_core; - int gpgpu_max_insn_issue_per_warp; - bool gpgpu_dual_issue_diff_exec_units; + unsigned int gpgpu_operand_collector_num_in_ports_sp; + unsigned int gpgpu_operand_collector_num_in_ports_dp; + unsigned int gpgpu_operand_collector_num_in_ports_sfu; + unsigned int gpgpu_operand_collector_num_in_ports_tensor_core; + unsigned int gpgpu_operand_collector_num_in_ports_mem; + unsigned int gpgpu_operand_collector_num_in_ports_gen; + unsigned int gpgpu_operand_collector_num_in_ports_int; - // op collector - bool enable_specialized_operand_collector; - int gpgpu_operand_collector_num_units_sp; - int gpgpu_operand_collector_num_units_dp; - int gpgpu_operand_collector_num_units_sfu; - int gpgpu_operand_collector_num_units_tensor_core; - int gpgpu_operand_collector_num_units_mem; - int gpgpu_operand_collector_num_units_gen; - int gpgpu_operand_collector_num_units_int; + unsigned int gpgpu_operand_collector_num_out_ports_sp; + unsigned int gpgpu_operand_collector_num_out_ports_dp; + unsigned int gpgpu_operand_collector_num_out_ports_sfu; + unsigned int gpgpu_operand_collector_num_out_ports_tensor_core; + unsigned int gpgpu_operand_collector_num_out_ports_mem; + unsigned int gpgpu_operand_collector_num_out_ports_gen; + unsigned int gpgpu_operand_collector_num_out_ports_int; - unsigned int gpgpu_operand_collector_num_in_ports_sp; - unsigned int gpgpu_operand_collector_num_in_ports_dp; - unsigned int gpgpu_operand_collector_num_in_ports_sfu; - unsigned int gpgpu_operand_collector_num_in_ports_tensor_core; - unsigned int gpgpu_operand_collector_num_in_ports_mem; - unsigned int gpgpu_operand_collector_num_in_ports_gen; - unsigned int gpgpu_operand_collector_num_in_ports_int; + int gpgpu_num_sp_units; + int gpgpu_tensor_core_avail; + int gpgpu_num_dp_units; + int gpgpu_num_sfu_units; + int gpgpu_num_tensor_core_units; + int gpgpu_num_mem_units; + int gpgpu_num_int_units; - unsigned int gpgpu_operand_collector_num_out_ports_sp; - unsigned int gpgpu_operand_collector_num_out_ports_dp; - unsigned int gpgpu_operand_collector_num_out_ports_sfu; - unsigned int gpgpu_operand_collector_num_out_ports_tensor_core; - unsigned int gpgpu_operand_collector_num_out_ports_mem; - unsigned int gpgpu_operand_collector_num_out_ports_gen; - unsigned int gpgpu_operand_collector_num_out_ports_int; + //Shader core resources + unsigned gpgpu_shader_registers; + int gpgpu_warpdistro_shader; + int gpgpu_warp_issue_shader; + unsigned gpgpu_num_reg_banks; + bool gpgpu_reg_bank_use_warp_id; + bool gpgpu_local_mem_map; + bool gpgpu_ignore_resources_limitation; + bool sub_core_model; + + unsigned max_sp_latency; + unsigned max_int_latency; + unsigned max_sfu_latency; + unsigned max_dp_latency; + unsigned max_tensor_core_latency; + + unsigned n_simt_cores_per_cluster; + unsigned n_simt_clusters; + unsigned n_simt_ejection_buffer_size; + unsigned ldst_unit_response_queue_size; - int gpgpu_num_sp_units; - int gpgpu_tensor_core_avail; - int gpgpu_num_dp_units; - int gpgpu_num_sfu_units; - int gpgpu_num_tensor_core_units; - int gpgpu_num_mem_units; - int gpgpu_num_int_units; + int simt_core_sim_order; + + unsigned smem_latency; - // Shader core resources - unsigned gpgpu_shader_registers; - int gpgpu_warpdistro_shader; - int gpgpu_warp_issue_shader; - unsigned gpgpu_num_reg_banks; - bool gpgpu_reg_bank_use_warp_id; - bool gpgpu_local_mem_map; - bool gpgpu_ignore_resources_limitation; - bool sub_core_model; + unsigned mem2device(unsigned memid) const { return memid + n_simt_clusters; } - unsigned max_sp_latency; - unsigned max_int_latency; - unsigned max_sfu_latency; - unsigned max_dp_latency; - unsigned max_tensor_core_latency; + //Jin: concurrent kernel on sm + bool gpgpu_concurrent_kernel_sm; - unsigned n_simt_cores_per_cluster; - unsigned n_simt_clusters; - unsigned n_simt_ejection_buffer_size; - unsigned ldst_unit_response_queue_size; + bool adpative_volta_cache_config; - int simt_core_sim_order; - - unsigned smem_latency; - - unsigned mem2device(unsigned memid) const { return memid + n_simt_clusters; } - - // Jin: concurrent kernel on sm - bool gpgpu_concurrent_kernel_sm; - - bool adpative_volta_cache_config; }; struct shader_core_stats_pod { - void *shader_core_stats_pod_start[0]; // DO NOT MOVE FROM THE TOP - spaceless - // pointer to the start of this - // structure - unsigned long long *shader_cycles; - unsigned *m_num_sim_insn; // number of scalar thread instructions committed - // by this shader core - unsigned *m_num_sim_winsn; // number of warp instructions committed by this - // shader core - unsigned *m_last_num_sim_insn; - unsigned *m_last_num_sim_winsn; - unsigned * - m_num_decoded_insn; // number of instructions decoded by this shader core - float *m_pipeline_duty_cycle; - unsigned *m_num_FPdecoded_insn; - unsigned *m_num_INTdecoded_insn; - unsigned *m_num_storequeued_insn; - unsigned *m_num_loadqueued_insn; - unsigned *m_num_ialu_acesses; - unsigned *m_num_fp_acesses; - unsigned *m_num_imul_acesses; - unsigned *m_num_tex_inst; - unsigned *m_num_fpmul_acesses; - unsigned *m_num_idiv_acesses; - unsigned *m_num_fpdiv_acesses; - unsigned *m_num_sp_acesses; - unsigned *m_num_sfu_acesses; - unsigned *m_num_tensor_core_acesses; - unsigned *m_num_trans_acesses; - unsigned *m_num_mem_acesses; - unsigned *m_num_sp_committed; - unsigned *m_num_tlb_hits; - unsigned *m_num_tlb_accesses; - unsigned *m_num_sfu_committed; - unsigned *m_num_tensor_core_committed; - unsigned *m_num_mem_committed; - unsigned *m_read_regfile_acesses; - unsigned *m_write_regfile_acesses; - unsigned *m_non_rf_operands; - unsigned *m_num_imul24_acesses; - unsigned *m_num_imul32_acesses; - unsigned *m_active_sp_lanes; - unsigned *m_active_sfu_lanes; - unsigned *m_active_tensor_core_lanes; - unsigned *m_active_fu_lanes; - unsigned *m_active_fu_mem_lanes; - unsigned *m_n_diverge; // number of divergence occurring in this shader - unsigned gpgpu_n_load_insn; - unsigned gpgpu_n_store_insn; - unsigned gpgpu_n_shmem_insn; - unsigned gpgpu_n_sstarr_insn; - unsigned gpgpu_n_tex_insn; - unsigned gpgpu_n_const_insn; - unsigned gpgpu_n_param_insn; - unsigned gpgpu_n_shmem_bkconflict; - unsigned gpgpu_n_cache_bkconflict; - int gpgpu_n_intrawarp_mshr_merge; - unsigned gpgpu_n_cmem_portconflict; - unsigned gpu_stall_shd_mem_breakdown[N_MEM_STAGE_ACCESS_TYPE] - [N_MEM_STAGE_STALL_TYPE]; - unsigned gpu_reg_bank_conflict_stalls; - unsigned *shader_cycle_distro; - unsigned *last_shader_cycle_distro; - unsigned *num_warps_issuable; - unsigned gpgpu_n_stall_shd_mem; - unsigned *single_issue_nums; - unsigned *dual_issue_nums; - // memory access classification - int gpgpu_n_mem_read_local; - int gpgpu_n_mem_write_local; - int gpgpu_n_mem_texture; - int gpgpu_n_mem_const; - int gpgpu_n_mem_read_global; - int gpgpu_n_mem_write_global; - int gpgpu_n_mem_read_inst; + void* shader_core_stats_pod_start[0]; // DO NOT MOVE FROM THE TOP - spaceless pointer to the start of this structure + unsigned long long *shader_cycles; + unsigned *m_num_sim_insn; // number of scalar thread instructions committed by this shader core + unsigned *m_num_sim_winsn; // number of warp instructions committed by this shader core + unsigned *m_last_num_sim_insn; + unsigned *m_last_num_sim_winsn; + unsigned *m_num_decoded_insn; // number of instructions decoded by this shader core + float *m_pipeline_duty_cycle; + unsigned *m_num_FPdecoded_insn; + unsigned *m_num_INTdecoded_insn; + unsigned *m_num_storequeued_insn; + unsigned *m_num_loadqueued_insn; + unsigned *m_num_ialu_acesses; + unsigned *m_num_fp_acesses; + unsigned *m_num_imul_acesses; + unsigned *m_num_tex_inst; + unsigned *m_num_fpmul_acesses; + unsigned *m_num_idiv_acesses; + unsigned *m_num_fpdiv_acesses; + unsigned *m_num_sp_acesses; + unsigned *m_num_sfu_acesses; + unsigned *m_num_tensor_core_acesses; + unsigned *m_num_trans_acesses; + unsigned *m_num_mem_acesses; + unsigned *m_num_sp_committed; + unsigned *m_num_tlb_hits; + unsigned *m_num_tlb_accesses; + unsigned *m_num_sfu_committed; + unsigned *m_num_tensor_core_committed; + unsigned *m_num_mem_committed; + unsigned *m_read_regfile_acesses; + unsigned *m_write_regfile_acesses; + unsigned *m_non_rf_operands; + unsigned *m_num_imul24_acesses; + unsigned *m_num_imul32_acesses; + unsigned *m_active_sp_lanes; + unsigned *m_active_sfu_lanes; + unsigned *m_active_tensor_core_lanes; + unsigned *m_active_fu_lanes; + unsigned *m_active_fu_mem_lanes; + unsigned *m_n_diverge; // number of divergence occurring in this shader + unsigned gpgpu_n_load_insn; + unsigned gpgpu_n_store_insn; + unsigned gpgpu_n_shmem_insn; + unsigned gpgpu_n_sstarr_insn; + unsigned gpgpu_n_tex_insn; + unsigned gpgpu_n_const_insn; + unsigned gpgpu_n_param_insn; + unsigned gpgpu_n_shmem_bkconflict; + unsigned gpgpu_n_cache_bkconflict; + int gpgpu_n_intrawarp_mshr_merge; + unsigned gpgpu_n_cmem_portconflict; + unsigned gpu_stall_shd_mem_breakdown[N_MEM_STAGE_ACCESS_TYPE][N_MEM_STAGE_STALL_TYPE]; + unsigned gpu_reg_bank_conflict_stalls; + unsigned *shader_cycle_distro; + unsigned *last_shader_cycle_distro; + unsigned *num_warps_issuable; + unsigned gpgpu_n_stall_shd_mem; + unsigned* single_issue_nums; + unsigned* dual_issue_nums; - int gpgpu_n_mem_l2_writeback; - int gpgpu_n_mem_l1_write_allocate; - int gpgpu_n_mem_l2_write_allocate; + //memory access classification + int gpgpu_n_mem_read_local; + int gpgpu_n_mem_write_local; + int gpgpu_n_mem_texture; + int gpgpu_n_mem_const; + int gpgpu_n_mem_read_global; + int gpgpu_n_mem_write_global; + int gpgpu_n_mem_read_inst; + + int gpgpu_n_mem_l2_writeback; + int gpgpu_n_mem_l1_write_allocate; + int gpgpu_n_mem_l2_write_allocate; - unsigned made_write_mfs; - unsigned made_read_mfs; + unsigned made_write_mfs; + unsigned made_read_mfs; - unsigned *gpgpu_n_shmem_bank_access; - long *n_simt_to_mem; // Interconnect power stats - long *n_mem_to_simt; + unsigned *gpgpu_n_shmem_bank_access; + long *n_simt_to_mem; // Interconnect power stats + long *n_mem_to_simt; }; class shader_core_stats : public shader_core_stats_pod { - public: - shader_core_stats(const shader_core_config *config) { - m_config = config; - shader_core_stats_pod *pod = reinterpret_cast<shader_core_stats_pod *>( - this->shader_core_stats_pod_start); - memset(pod, 0, sizeof(shader_core_stats_pod)); - shader_cycles = (unsigned long long *)calloc(config->num_shader(), - sizeof(unsigned long long)); - m_num_sim_insn = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_sim_winsn = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_last_num_sim_winsn = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_last_num_sim_insn = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_pipeline_duty_cycle = - (float *)calloc(config->num_shader(), sizeof(float)); - m_num_decoded_insn = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_FPdecoded_insn = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_storequeued_insn = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_loadqueued_insn = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_INTdecoded_insn = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_ialu_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_fp_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_tex_inst = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_imul_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_imul24_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_imul32_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_fpmul_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_idiv_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_fpdiv_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_sp_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_sfu_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_tensor_core_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_trans_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_mem_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_sp_committed = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_tlb_hits = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_tlb_accesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_active_sp_lanes = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_active_sfu_lanes = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_active_tensor_core_lanes = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_active_fu_lanes = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_active_fu_mem_lanes = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_sfu_committed = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_tensor_core_committed = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_num_mem_committed = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_read_regfile_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_write_regfile_acesses = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_non_rf_operands = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_n_diverge = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - shader_cycle_distro = - (unsigned *)calloc(config->warp_size + 3, sizeof(unsigned)); - last_shader_cycle_distro = - (unsigned *)calloc(m_config->warp_size + 3, sizeof(unsigned)); - single_issue_nums = - (unsigned *)calloc(config->gpgpu_num_sched_per_core, sizeof(unsigned)); - dual_issue_nums = - (unsigned *)calloc(config->gpgpu_num_sched_per_core, sizeof(unsigned)); +public: + shader_core_stats( const shader_core_config *config ) + { + m_config = config; + shader_core_stats_pod *pod = reinterpret_cast< shader_core_stats_pod * > ( this->shader_core_stats_pod_start ); + memset(pod,0,sizeof(shader_core_stats_pod)); + shader_cycles=(unsigned long long *) calloc(config->num_shader(),sizeof(unsigned long long )); + m_num_sim_insn = (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_sim_winsn = (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_last_num_sim_winsn = (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_last_num_sim_insn = (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_pipeline_duty_cycle=(float*) calloc(config->num_shader(),sizeof(float)); + m_num_decoded_insn = (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_FPdecoded_insn = (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_storequeued_insn=(unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_loadqueued_insn=(unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_INTdecoded_insn = (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_ialu_acesses = (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_fp_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_tex_inst= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_imul_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_imul24_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_imul32_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_fpmul_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_idiv_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_fpdiv_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_sp_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_sfu_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_tensor_core_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_trans_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_mem_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_sp_committed= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_tlb_hits=(unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_tlb_accesses=(unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_active_sp_lanes= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_active_sfu_lanes= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_active_tensor_core_lanes= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_active_fu_lanes= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_active_fu_mem_lanes= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_sfu_committed= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_tensor_core_committed= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_num_mem_committed= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_read_regfile_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_write_regfile_acesses= (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_non_rf_operands=(unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + m_n_diverge = (unsigned*) calloc(config->num_shader(),sizeof(unsigned)); + shader_cycle_distro = (unsigned*) calloc(config->warp_size+3, sizeof(unsigned)); + last_shader_cycle_distro = (unsigned*) calloc(m_config->warp_size+3, sizeof(unsigned)); + single_issue_nums = (unsigned*) calloc(config->gpgpu_num_sched_per_core,sizeof(unsigned)); + dual_issue_nums = (unsigned*) calloc(config->gpgpu_num_sched_per_core, sizeof(unsigned)); - n_simt_to_mem = (long *)calloc(config->num_shader(), sizeof(long)); - n_mem_to_simt = (long *)calloc(config->num_shader(), sizeof(long)); + n_simt_to_mem = (long *)calloc(config->num_shader(), sizeof(long)); + n_mem_to_simt = (long *)calloc(config->num_shader(), sizeof(long)); - m_outgoing_traffic_stats = new traffic_breakdown("coretomem"); - m_incoming_traffic_stats = new traffic_breakdown("memtocore"); + m_outgoing_traffic_stats = new traffic_breakdown("coretomem"); + m_incoming_traffic_stats = new traffic_breakdown("memtocore"); - gpgpu_n_shmem_bank_access = - (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); + gpgpu_n_shmem_bank_access = (unsigned *)calloc(config->num_shader(), sizeof(unsigned)); - m_shader_dynamic_warp_issue_distro.resize(config->num_shader()); - m_shader_warp_slot_issue_distro.resize(config->num_shader()); - } + m_shader_dynamic_warp_issue_distro.resize( config->num_shader() ); + m_shader_warp_slot_issue_distro.resize( config->num_shader() ); + } - ~shader_core_stats() { - delete m_outgoing_traffic_stats; - delete m_incoming_traffic_stats; - free(m_num_sim_insn); - free(m_num_sim_winsn); - free(m_n_diverge); - free(shader_cycle_distro); - free(last_shader_cycle_distro); - } + ~shader_core_stats() + { + delete m_outgoing_traffic_stats; + delete m_incoming_traffic_stats; + free(m_num_sim_insn); + free(m_num_sim_winsn); + free(m_n_diverge); + free(shader_cycle_distro); + free(last_shader_cycle_distro); + } - void new_grid() {} + void new_grid() + { + } - void event_warp_issued(unsigned s_id, unsigned warp_id, unsigned num_issued, - unsigned dynamic_warp_id); + void event_warp_issued( unsigned s_id, unsigned warp_id, unsigned num_issued, unsigned dynamic_warp_id ); - void visualizer_print(gzFile visualizer_file); + void visualizer_print( gzFile visualizer_file ); - void print(FILE *fout) const; + void print( FILE *fout ) const; - const std::vector<std::vector<unsigned>> &get_dynamic_warp_issue() const { - return m_shader_dynamic_warp_issue_distro; - } + const std::vector< std::vector<unsigned> >& get_dynamic_warp_issue() const + { + return m_shader_dynamic_warp_issue_distro; + } - const std::vector<std::vector<unsigned>> &get_warp_slot_issue() const { - return m_shader_warp_slot_issue_distro; - } + const std::vector< std::vector<unsigned> >& get_warp_slot_issue() const + { + return m_shader_warp_slot_issue_distro; + } - private: - const shader_core_config *m_config; +private: + const shader_core_config *m_config; - traffic_breakdown *m_outgoing_traffic_stats; // core to memory partitions - traffic_breakdown *m_incoming_traffic_stats; // memory partition to core + traffic_breakdown *m_outgoing_traffic_stats; // core to memory partitions + traffic_breakdown *m_incoming_traffic_stats; // memory partition to core - // Counts the instructions issued for each dynamic warp. - std::vector<std::vector<unsigned>> m_shader_dynamic_warp_issue_distro; - std::vector<unsigned> m_last_shader_dynamic_warp_issue_distro; - std::vector<std::vector<unsigned>> m_shader_warp_slot_issue_distro; - std::vector<unsigned> m_last_shader_warp_slot_issue_distro; + // Counts the instructions issued for each dynamic warp. + std::vector< std::vector<unsigned> > m_shader_dynamic_warp_issue_distro; + std::vector<unsigned> m_last_shader_dynamic_warp_issue_distro; + std::vector< std::vector<unsigned> > m_shader_warp_slot_issue_distro; + std::vector<unsigned> m_last_shader_warp_slot_issue_distro; - friend class power_stat_t; - friend class shader_core_ctx; - friend class ldst_unit; - friend class simt_core_cluster; - friend class scheduler_unit; - friend class TwoLevelScheduler; - friend class LooseRoundRobbinScheduler; + friend class power_stat_t; + friend class shader_core_ctx; + friend class ldst_unit; + friend class simt_core_cluster; + friend class scheduler_unit; + friend class TwoLevelScheduler; + friend class LooseRoundRobbinScheduler; }; class memory_config; class shader_core_mem_fetch_allocator : public mem_fetch_allocator { - public: - shader_core_mem_fetch_allocator(unsigned core_id, unsigned cluster_id, - const memory_config *config) { - m_core_id = core_id; - m_cluster_id = cluster_id; - m_memory_config = config; - } - mem_fetch *alloc(new_addr_type addr, mem_access_type type, unsigned size, - bool wr, unsigned long long cycle) const; - mem_fetch *alloc(const warp_inst_t &inst, const mem_access_t &access, - unsigned long long cycle) const { - warp_inst_t inst_copy = inst; - mem_fetch *mf = new mem_fetch( - access, &inst_copy, - access.is_write() ? WRITE_PACKET_SIZE : READ_PACKET_SIZE, - inst.warp_id(), m_core_id, m_cluster_id, m_memory_config, cycle); - return mf; - } +public: + shader_core_mem_fetch_allocator( unsigned core_id, unsigned cluster_id, const memory_config *config ) + { + m_core_id = core_id; + m_cluster_id = cluster_id; + m_memory_config = config; + } + mem_fetch *alloc( new_addr_type addr, mem_access_type type, unsigned size, bool wr, unsigned long long cycle ) const; + mem_fetch *alloc( const warp_inst_t &inst, const mem_access_t &access, unsigned long long cycle ) const + { + warp_inst_t inst_copy = inst; + mem_fetch *mf = new mem_fetch(access, + &inst_copy, + access.is_write()?WRITE_PACKET_SIZE:READ_PACKET_SIZE, + inst.warp_id(), + m_core_id, + m_cluster_id, + m_memory_config, + cycle); + return mf; + } - private: - unsigned m_core_id; - unsigned m_cluster_id; - const memory_config *m_memory_config; +private: + unsigned m_core_id; + unsigned m_cluster_id; + const memory_config *m_memory_config; }; class shader_core_ctx : public core_t { - public: - // creator: - shader_core_ctx(class gpgpu_sim *gpu, class simt_core_cluster *cluster, - unsigned shader_id, unsigned tpc_id, - const shader_core_config *config, - const memory_config *mem_config, shader_core_stats *stats); - - // used by simt_core_cluster: - // modifiers - void cycle(); - void reinit(unsigned start_thread, unsigned end_thread, - bool reset_not_completed); - void issue_block2core(class kernel_info_t &kernel); - - void cache_flush(); - void cache_invalidate(); - void accept_fetch_response(mem_fetch *mf); - void accept_ldst_unit_response(class mem_fetch *mf); - void broadcast_barrier_reduction(unsigned cta_id, unsigned bar_id, - warp_set_t warps); - void set_kernel(kernel_info_t *k) { - assert(k); - m_kernel = k; - // k->inc_running(); - printf("GPGPU-Sim uArch: Shader %d bind to kernel %u \'%s\'\n", m_sid, - m_kernel->get_uid(), m_kernel->name().c_str()); - } - - // accessors - bool fetch_unit_response_buffer_full() const; - bool ldst_unit_response_buffer_full() const; - unsigned get_not_completed() const { return m_not_completed; } - unsigned get_n_active_cta() const { return m_n_active_cta; } - unsigned isactive() const { - if (m_n_active_cta > 0) - return 1; - else - return 0; - } - kernel_info_t *get_kernel() { return m_kernel; } - unsigned get_sid() const { return m_sid; } - - // used by functional simulation: - // modifiers - virtual void warp_exit(unsigned warp_id); - - // accessors - virtual bool warp_waiting_at_barrier(unsigned warp_id) const; - void get_pdom_stack_top_info(unsigned tid, unsigned *pc, unsigned *rpc) const; - float get_current_occupancy(unsigned long long &active, - unsigned long long &total) const; - - // used by pipeline timing model components: - // modifiers - void mem_instruction_stats(const warp_inst_t &inst); - void decrement_atomic_count(unsigned wid, unsigned n); - void inc_store_req(unsigned warp_id) { m_warp[warp_id].inc_store_req(); } - void dec_inst_in_pipeline(unsigned warp_id) { - m_warp[warp_id].dec_inst_in_pipeline(); - } // also used in writeback() - void store_ack(class mem_fetch *mf); - bool warp_waiting_at_mem_barrier(unsigned warp_id); - void set_max_cta(const kernel_info_t &kernel); - void warp_inst_complete(const warp_inst_t &inst); - - // accessors - std::list<unsigned> get_regs_written(const inst_t &fvt) const; - const shader_core_config *get_config() const { return m_config; } - void print_cache_stats(FILE *fp, unsigned &dl1_accesses, - unsigned &dl1_misses); - - void get_cache_stats(cache_stats &cs); - void get_L1I_sub_stats(struct cache_sub_stats &css) const; - void get_L1D_sub_stats(struct cache_sub_stats &css) const; - void get_L1C_sub_stats(struct cache_sub_stats &css) const; - void get_L1T_sub_stats(struct cache_sub_stats &css) const; - - void get_icnt_power_stats(long &n_simt_to_mem, long &n_mem_to_simt) const; +public: + // creator: + shader_core_ctx( class gpgpu_sim *gpu, + class simt_core_cluster *cluster, + unsigned shader_id, + unsigned tpc_id, + const shader_core_config *config, + const memory_config *mem_config, + shader_core_stats *stats ); - // debug: - void display_simt_state(FILE *fout, int mask) const; - void display_pipeline(FILE *fout, int print_mem, int mask3bit) const; +// used by simt_core_cluster: + // modifiers + void cycle(); + void reinit(unsigned start_thread, unsigned end_thread, bool reset_not_completed ); + void issue_block2core( class kernel_info_t &kernel ); - void incload_stat() { m_stats->m_num_loadqueued_insn[m_sid]++; } - void incstore_stat() { m_stats->m_num_storequeued_insn[m_sid]++; } - void incialu_stat(unsigned active_count, double latency) { - if (m_config->gpgpu_clock_gated_lanes == false) { - m_stats->m_num_ialu_acesses[m_sid] = - m_stats->m_num_ialu_acesses[m_sid] + active_count * latency + - inactive_lanes_accesses_nonsfu(active_count, latency); - } else { - m_stats->m_num_ialu_acesses[m_sid] = - m_stats->m_num_ialu_acesses[m_sid] + active_count * latency; - } - } - void inctex_stat(unsigned active_count, double latency) { - m_stats->m_num_tex_inst[m_sid] = - m_stats->m_num_tex_inst[m_sid] + active_count * latency; - } - void incimul_stat(unsigned active_count, double latency) { - if (m_config->gpgpu_clock_gated_lanes == false) { - m_stats->m_num_imul_acesses[m_sid] = - m_stats->m_num_imul_acesses[m_sid] + active_count * latency + - inactive_lanes_accesses_nonsfu(active_count, latency); - } else { - m_stats->m_num_imul_acesses[m_sid] = - m_stats->m_num_imul_acesses[m_sid] + active_count * latency; - } - } - void incimul24_stat(unsigned active_count, double latency) { - if (m_config->gpgpu_clock_gated_lanes == false) { - m_stats->m_num_imul24_acesses[m_sid] = - m_stats->m_num_imul24_acesses[m_sid] + active_count * latency + - inactive_lanes_accesses_nonsfu(active_count, latency); - } else { - m_stats->m_num_imul24_acesses[m_sid] = - m_stats->m_num_imul24_acesses[m_sid] + active_count * latency; - } - } - void incimul32_stat(unsigned active_count, double latency) { - if (m_config->gpgpu_clock_gated_lanes == false) { - m_stats->m_num_imul32_acesses[m_sid] = - m_stats->m_num_imul32_acesses[m_sid] + active_count * latency + - inactive_lanes_accesses_sfu(active_count, latency); - } else { - m_stats->m_num_imul32_acesses[m_sid] = - m_stats->m_num_imul32_acesses[m_sid] + active_count * latency; - } - // printf("Int_Mul -- Active_count: %d\n",active_count); - } - void incidiv_stat(unsigned active_count, double latency) { - if (m_config->gpgpu_clock_gated_lanes == false) { - m_stats->m_num_idiv_acesses[m_sid] = - m_stats->m_num_idiv_acesses[m_sid] + active_count * latency + - inactive_lanes_accesses_sfu(active_count, latency); - } else { - m_stats->m_num_idiv_acesses[m_sid] = - m_stats->m_num_idiv_acesses[m_sid] + active_count * latency; - } - } - void incfpalu_stat(unsigned active_count, double latency) { - if (m_config->gpgpu_clock_gated_lanes == false) { - m_stats->m_num_fp_acesses[m_sid] = - m_stats->m_num_fp_acesses[m_sid] + active_count * latency + - inactive_lanes_accesses_nonsfu(active_count, latency); - } else { - m_stats->m_num_fp_acesses[m_sid] = - m_stats->m_num_fp_acesses[m_sid] + active_count * latency; - } - } - void incfpmul_stat(unsigned active_count, double latency) { - // printf("FP MUL stat increament\n"); - if (m_config->gpgpu_clock_gated_lanes == false) { - m_stats->m_num_fpmul_acesses[m_sid] = - m_stats->m_num_fpmul_acesses[m_sid] + active_count * latency + - inactive_lanes_accesses_nonsfu(active_count, latency); - } else { - m_stats->m_num_fpmul_acesses[m_sid] = - m_stats->m_num_fpmul_acesses[m_sid] + active_count * latency; + void cache_flush(); + void cache_invalidate(); + void accept_fetch_response( mem_fetch *mf ); + void accept_ldst_unit_response( class mem_fetch * mf ); + void broadcast_barrier_reduction(unsigned cta_id, unsigned bar_id,warp_set_t warps); + void set_kernel( kernel_info_t *k ) + { + assert(k); + m_kernel=k; +// k->inc_running(); + printf("GPGPU-Sim uArch: Shader %d bind to kernel %u \'%s\'\n", m_sid, m_kernel->get_uid(), + m_kernel->name().c_str() ); } - } - void incfpdiv_stat(unsigned active_count, double latency) { - if (m_config->gpgpu_clock_gated_lanes == false) { - m_stats->m_num_fpdiv_acesses[m_sid] = - m_stats->m_num_fpdiv_acesses[m_sid] + active_count * latency + - inactive_lanes_accesses_sfu(active_count, latency); - } else { - m_stats->m_num_fpdiv_acesses[m_sid] = - m_stats->m_num_fpdiv_acesses[m_sid] + active_count * latency; - } - } - void inctrans_stat(unsigned active_count, double latency) { - if (m_config->gpgpu_clock_gated_lanes == false) { - m_stats->m_num_trans_acesses[m_sid] = - m_stats->m_num_trans_acesses[m_sid] + active_count * latency + - inactive_lanes_accesses_sfu(active_count, latency); - } else { - m_stats->m_num_trans_acesses[m_sid] = - m_stats->m_num_trans_acesses[m_sid] + active_count * latency; - } - } + + // accessors + bool fetch_unit_response_buffer_full() const; + bool ldst_unit_response_buffer_full() const; + unsigned get_not_completed() const { return m_not_completed; } + unsigned get_n_active_cta() const { return m_n_active_cta; } + unsigned isactive() const {if(m_n_active_cta>0) return 1; else return 0;} + kernel_info_t *get_kernel() { return m_kernel; } + unsigned get_sid() const {return m_sid;} - void incsfu_stat(unsigned active_count, double latency) { - m_stats->m_num_sfu_acesses[m_sid] = - m_stats->m_num_sfu_acesses[m_sid] + active_count * latency; - } - void incsp_stat(unsigned active_count, double latency) { - m_stats->m_num_sp_acesses[m_sid] = - m_stats->m_num_sp_acesses[m_sid] + active_count * latency; - } - void incmem_stat(unsigned active_count, double latency) { - if (m_config->gpgpu_clock_gated_lanes == false) { - m_stats->m_num_mem_acesses[m_sid] = - m_stats->m_num_mem_acesses[m_sid] + active_count * latency + - inactive_lanes_accesses_nonsfu(active_count, latency); - } else { - m_stats->m_num_mem_acesses[m_sid] = - m_stats->m_num_mem_acesses[m_sid] + active_count * latency; - } - } - void incexecstat(warp_inst_t *&inst); +// used by functional simulation: + // modifiers + virtual void warp_exit( unsigned warp_id ); + + // accessors + virtual bool warp_waiting_at_barrier( unsigned warp_id ) const; + void get_pdom_stack_top_info( unsigned tid, unsigned *pc, unsigned *rpc ) const; + float get_current_occupancy( unsigned long long & active, unsigned long long & total ) const; - void incregfile_reads(unsigned active_count) { - m_stats->m_read_regfile_acesses[m_sid] = - m_stats->m_read_regfile_acesses[m_sid] + active_count; - } - void incregfile_writes(unsigned active_count) { - m_stats->m_write_regfile_acesses[m_sid] = - m_stats->m_write_regfile_acesses[m_sid] + active_count; - } - void incnon_rf_operands(unsigned active_count) { - m_stats->m_non_rf_operands[m_sid] = - m_stats->m_non_rf_operands[m_sid] + active_count; - } +// used by pipeline timing model components: + // modifiers + void mem_instruction_stats(const warp_inst_t &inst); + void decrement_atomic_count( unsigned wid, unsigned n ); + void inc_store_req( unsigned warp_id) { m_warp[warp_id].inc_store_req(); } + void dec_inst_in_pipeline( unsigned warp_id ) { m_warp[warp_id].dec_inst_in_pipeline(); } // also used in writeback() + void store_ack( class mem_fetch *mf ); + bool warp_waiting_at_mem_barrier( unsigned warp_id ); + void set_max_cta( const kernel_info_t &kernel ); + void warp_inst_complete(const warp_inst_t &inst); + + // accessors + std::list<unsigned> get_regs_written( const inst_t &fvt ) const; + const shader_core_config *get_config() const { return m_config; } + void print_cache_stats( FILE *fp, unsigned& dl1_accesses, unsigned& dl1_misses ); - void incspactivelanes_stat(unsigned active_count) { - m_stats->m_active_sp_lanes[m_sid] = - m_stats->m_active_sp_lanes[m_sid] + active_count; - } - void incsfuactivelanes_stat(unsigned active_count) { - m_stats->m_active_sfu_lanes[m_sid] = - m_stats->m_active_sfu_lanes[m_sid] + active_count; - } - void incfuactivelanes_stat(unsigned active_count) { - m_stats->m_active_fu_lanes[m_sid] = - m_stats->m_active_fu_lanes[m_sid] + active_count; - } - void incfumemactivelanes_stat(unsigned active_count) { - m_stats->m_active_fu_mem_lanes[m_sid] = - m_stats->m_active_fu_mem_lanes[m_sid] + active_count; - } + void get_cache_stats(cache_stats &cs); + void get_L1I_sub_stats(struct cache_sub_stats &css) const; + void get_L1D_sub_stats(struct cache_sub_stats &css) const; + void get_L1C_sub_stats(struct cache_sub_stats &css) const; + void get_L1T_sub_stats(struct cache_sub_stats &css) const; - void inc_simt_to_mem(unsigned n_flits) { - m_stats->n_simt_to_mem[m_sid] += n_flits; - } - bool check_if_non_released_reduction_barrier(warp_inst_t &inst); + void get_icnt_power_stats(long &n_simt_to_mem, long &n_mem_to_simt) const; - private: - unsigned inactive_lanes_accesses_sfu(unsigned active_count, double latency) { - return (((32 - active_count) >> 1) * latency) + - (((32 - active_count) >> 3) * latency) + - (((32 - active_count) >> 3) * latency); - } - unsigned inactive_lanes_accesses_nonsfu(unsigned active_count, - double latency) { - return (((32 - active_count) >> 1) * latency); - } +// debug: + void display_simt_state(FILE *fout, int mask ) const; + void display_pipeline( FILE *fout, int print_mem, int mask3bit ) const; - int test_res_bus(int latency); - void init_warps(unsigned cta_id, unsigned start_thread, unsigned end_thread, - unsigned ctaid, int cta_size, unsigned kernel_id); - virtual void checkExecutionStatusAndUpdate(warp_inst_t &inst, unsigned t, - unsigned tid); - address_type next_pc(int tid) const; - void fetch(); - void register_cta_thread_exit(unsigned cta_num, kernel_info_t *kernel); + void incload_stat() {m_stats->m_num_loadqueued_insn[m_sid]++;} + void incstore_stat() {m_stats->m_num_storequeued_insn[m_sid]++;} + void incialu_stat(unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_ialu_acesses[m_sid]=m_stats->m_num_ialu_acesses[m_sid]+active_count*latency + + inactive_lanes_accesses_nonsfu(active_count, latency); + }else { + m_stats->m_num_ialu_acesses[m_sid]=m_stats->m_num_ialu_acesses[m_sid]+active_count*latency; + } + } + void inctex_stat(unsigned active_count,double latency){ + m_stats->m_num_tex_inst[m_sid]=m_stats->m_num_tex_inst[m_sid]+active_count*latency; + } + void incimul_stat(unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_imul_acesses[m_sid]=m_stats->m_num_imul_acesses[m_sid]+active_count*latency + + inactive_lanes_accesses_nonsfu(active_count, latency); + }else { + m_stats->m_num_imul_acesses[m_sid]=m_stats->m_num_imul_acesses[m_sid]+active_count*latency; + } + } + void incimul24_stat(unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_imul24_acesses[m_sid]=m_stats->m_num_imul24_acesses[m_sid]+active_count*latency + + inactive_lanes_accesses_nonsfu(active_count, latency); + }else { + m_stats->m_num_imul24_acesses[m_sid]=m_stats->m_num_imul24_acesses[m_sid]+active_count*latency; + } + } + void incimul32_stat(unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_imul32_acesses[m_sid]=m_stats->m_num_imul32_acesses[m_sid]+active_count*latency + + inactive_lanes_accesses_sfu(active_count, latency); + }else{ + m_stats->m_num_imul32_acesses[m_sid]=m_stats->m_num_imul32_acesses[m_sid]+active_count*latency; + } + //printf("Int_Mul -- Active_count: %d\n",active_count); + } + void incidiv_stat(unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_idiv_acesses[m_sid]=m_stats->m_num_idiv_acesses[m_sid]+active_count*latency + + inactive_lanes_accesses_sfu(active_count, latency); + }else { + m_stats->m_num_idiv_acesses[m_sid]=m_stats->m_num_idiv_acesses[m_sid]+active_count*latency; + } + } + void incfpalu_stat(unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_fp_acesses[m_sid]=m_stats->m_num_fp_acesses[m_sid]+active_count*latency + + inactive_lanes_accesses_nonsfu(active_count, latency); + }else { + m_stats->m_num_fp_acesses[m_sid]=m_stats->m_num_fp_acesses[m_sid]+active_count*latency; + } + } + void incfpmul_stat(unsigned active_count,double latency) { + // printf("FP MUL stat increament\n"); + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_fpmul_acesses[m_sid]=m_stats->m_num_fpmul_acesses[m_sid]+active_count*latency + + inactive_lanes_accesses_nonsfu(active_count, latency); + }else { + m_stats->m_num_fpmul_acesses[m_sid]=m_stats->m_num_fpmul_acesses[m_sid]+active_count*latency; + } + } + void incfpdiv_stat(unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_fpdiv_acesses[m_sid]=m_stats->m_num_fpdiv_acesses[m_sid]+active_count*latency + + inactive_lanes_accesses_sfu(active_count, latency); + }else { + m_stats->m_num_fpdiv_acesses[m_sid]=m_stats->m_num_fpdiv_acesses[m_sid]+active_count*latency; + } + } + void inctrans_stat(unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_trans_acesses[m_sid]=m_stats->m_num_trans_acesses[m_sid]+active_count*latency + + inactive_lanes_accesses_sfu(active_count, latency); + }else{ + m_stats->m_num_trans_acesses[m_sid]=m_stats->m_num_trans_acesses[m_sid]+active_count*latency; + } + } - void decode(); + void incsfu_stat(unsigned active_count,double latency) {m_stats->m_num_sfu_acesses[m_sid]=m_stats->m_num_sfu_acesses[m_sid]+active_count*latency;} + void incsp_stat(unsigned active_count,double latency) {m_stats->m_num_sp_acesses[m_sid]=m_stats->m_num_sp_acesses[m_sid]+active_count*latency;} + void incmem_stat(unsigned active_count,double latency) { + if(m_config->gpgpu_clock_gated_lanes==false){ + m_stats->m_num_mem_acesses[m_sid]=m_stats->m_num_mem_acesses[m_sid]+active_count*latency + + inactive_lanes_accesses_nonsfu(active_count, latency); + }else { + m_stats->m_num_mem_acesses[m_sid]=m_stats->m_num_mem_acesses[m_sid]+active_count*latency; + } + } + void incexecstat(warp_inst_t *&inst); - void issue(); - friend class scheduler_unit; // this is needed to use private issue warp. - friend class TwoLevelScheduler; - friend class LooseRoundRobbinScheduler; - void issue_warp(register_set &warp, const warp_inst_t *pI, - const active_mask_t &active_mask, unsigned warp_id, - unsigned sch_id); - void func_exec_inst(warp_inst_t &inst); + void incregfile_reads(unsigned active_count) {m_stats->m_read_regfile_acesses[m_sid]=m_stats->m_read_regfile_acesses[m_sid]+active_count;} + void incregfile_writes(unsigned active_count){m_stats->m_write_regfile_acesses[m_sid]=m_stats->m_write_regfile_acesses[m_sid]+active_count;} + void incnon_rf_operands(unsigned active_count){m_stats->m_non_rf_operands[m_sid]=m_stats->m_non_rf_operands[m_sid]+active_count;} - // Returns numbers of addresses in translated_addrs - unsigned translate_local_memaddr(address_type localaddr, unsigned tid, - unsigned num_shader, unsigned datasize, - new_addr_type *translated_addrs); + void incspactivelanes_stat(unsigned active_count) {m_stats->m_active_sp_lanes[m_sid]=m_stats->m_active_sp_lanes[m_sid]+active_count;} + void incsfuactivelanes_stat(unsigned active_count) {m_stats->m_active_sfu_lanes[m_sid]=m_stats->m_active_sfu_lanes[m_sid]+active_count;} + void incfuactivelanes_stat(unsigned active_count) {m_stats->m_active_fu_lanes[m_sid]=m_stats->m_active_fu_lanes[m_sid]+active_count;} + void incfumemactivelanes_stat(unsigned active_count) {m_stats->m_active_fu_mem_lanes[m_sid]=m_stats->m_active_fu_mem_lanes[m_sid]+active_count;} - void read_operands(); + void inc_simt_to_mem(unsigned n_flits){ m_stats->n_simt_to_mem[m_sid] += n_flits; } + bool check_if_non_released_reduction_barrier(warp_inst_t &inst); - void execute(); + private: + unsigned inactive_lanes_accesses_sfu(unsigned active_count,double latency){ + return ( ((32-active_count)>>1)*latency) + ( ((32-active_count)>>3)*latency) + ( ((32-active_count)>>3)*latency); + } + unsigned inactive_lanes_accesses_nonsfu(unsigned active_count,double latency){ + return ( ((32-active_count)>>1)*latency); + } - void writeback(); + int test_res_bus(int latency); + void init_warps(unsigned cta_id, unsigned start_thread, unsigned end_thread,unsigned ctaid, int cta_size, unsigned kernel_id); + virtual void checkExecutionStatusAndUpdate(warp_inst_t &inst, unsigned t, unsigned tid); + address_type next_pc( int tid ) const; + void fetch(); + void register_cta_thread_exit(unsigned cta_num, kernel_info_t * kernel ); - // used in display_pipeline(): - void dump_warp_state(FILE *fout) const; - void print_stage(unsigned int stage, FILE *fout) const; - unsigned long long m_last_inst_gpu_sim_cycle; - unsigned long long m_last_inst_gpu_tot_sim_cycle; + void decode(); + + void issue(); + friend class scheduler_unit; //this is needed to use private issue warp. + friend class TwoLevelScheduler; + friend class LooseRoundRobbinScheduler; + void issue_warp( register_set& warp, const warp_inst_t *pI, const active_mask_t &active_mask, unsigned warp_id, unsigned sch_id ); + void func_exec_inst( warp_inst_t &inst ); - // general information - unsigned m_sid; // shader id - unsigned m_tpc; // texture processor cluster id (aka, node id when using - // interconnect concentration) - const shader_core_config *m_config; - const memory_config *m_memory_config; - class simt_core_cluster *m_cluster; + // Returns numbers of addresses in translated_addrs + unsigned translate_local_memaddr( address_type localaddr, unsigned tid, unsigned num_shader, unsigned datasize, new_addr_type* translated_addrs ); - // statistics - shader_core_stats *m_stats; + void read_operands(); + + void execute(); + + void writeback(); + + // used in display_pipeline(): + void dump_warp_state( FILE *fout ) const; + void print_stage(unsigned int stage, FILE *fout) const; + unsigned long long m_last_inst_gpu_sim_cycle; + unsigned long long m_last_inst_gpu_tot_sim_cycle; - // CTA scheduling / hardware thread allocation - unsigned m_n_active_cta; // number of Cooperative Thread Arrays (blocks) - // currently running on this shader. - unsigned m_cta_status[MAX_CTA_PER_SHADER]; // CTAs status - unsigned m_not_completed; // number of threads to be completed (==0 when all - // thread on this core completed) - std::bitset<MAX_THREAD_PER_SM> m_active_threads; + // general information + unsigned m_sid; // shader id + unsigned m_tpc; // texture processor cluster id (aka, node id when using interconnect concentration) + const shader_core_config *m_config; + const memory_config *m_memory_config; + class simt_core_cluster *m_cluster; - // thread contexts - thread_ctx_t *m_threadState; + // statistics + shader_core_stats *m_stats; - // interconnect interface - mem_fetch_interface *m_icnt; - shader_core_mem_fetch_allocator *m_mem_fetch_allocator; + // CTA scheduling / hardware thread allocation + unsigned m_n_active_cta; // number of Cooperative Thread Arrays (blocks) currently running on this shader. + unsigned m_cta_status[MAX_CTA_PER_SHADER]; // CTAs status + unsigned m_not_completed; // number of threads to be completed (==0 when all thread on this core completed) + std::bitset<MAX_THREAD_PER_SM> m_active_threads; + + // thread contexts + thread_ctx_t *m_threadState; + + // interconnect interface + mem_fetch_interface *m_icnt; + shader_core_mem_fetch_allocator *m_mem_fetch_allocator; + + // fetch + read_only_cache *m_L1I; // instruction cache + int m_last_warp_fetched; - // fetch - read_only_cache *m_L1I; // instruction cache - int m_last_warp_fetched; + // decode/dispatch + std::vector<shd_warp_t> m_warp; // per warp information array + barrier_set_t m_barriers; + ifetch_buffer_t m_inst_fetch_buffer; + std::vector<register_set> m_pipeline_reg; + Scoreboard *m_scoreboard; + opndcoll_rfu_t m_operand_collector; + int m_active_warps; - // decode/dispatch - std::vector<shd_warp_t> m_warp; // per warp information array - barrier_set_t m_barriers; - ifetch_buffer_t m_inst_fetch_buffer; - std::vector<register_set> m_pipeline_reg; - Scoreboard *m_scoreboard; - opndcoll_rfu_t m_operand_collector; - int m_active_warps; + //schedule + std::vector<scheduler_unit*> schedulers; - // schedule - std::vector<scheduler_unit *> schedulers; + //issue + unsigned int Issue_Prio; - // issue - unsigned int Issue_Prio; + // execute + unsigned m_num_function_units; + std::vector<pipeline_stage_name_t> m_dispatch_port; + std::vector<pipeline_stage_name_t> m_issue_port; + std::vector<simd_function_unit*> m_fu; // stallable pipelines should be last in this array + ldst_unit *m_ldst_unit; + static const unsigned MAX_ALU_LATENCY = 512; + unsigned num_result_bus; + std::vector< std::bitset<MAX_ALU_LATENCY>* > m_result_bus; - // execute - unsigned m_num_function_units; - std::vector<pipeline_stage_name_t> m_dispatch_port; - std::vector<pipeline_stage_name_t> m_issue_port; - std::vector<simd_function_unit *> - m_fu; // stallable pipelines should be last in this array - ldst_unit *m_ldst_unit; - static const unsigned MAX_ALU_LATENCY = 512; - unsigned num_result_bus; - std::vector<std::bitset<MAX_ALU_LATENCY> *> m_result_bus; + // used for local address mapping with single kernel launch + unsigned kernel_max_cta_per_shader; + unsigned kernel_padded_threads_per_cta; + // Used for handing out dynamic warp_ids to new warps. + // the differnece between a warp_id and a dynamic_warp_id + // is that the dynamic_warp_id is a running number unique to every warp + // run on this shader, where the warp_id is the static warp slot. + unsigned m_dynamic_warp_id; - // used for local address mapping with single kernel launch - unsigned kernel_max_cta_per_shader; - unsigned kernel_padded_threads_per_cta; - // Used for handing out dynamic warp_ids to new warps. - // the differnece between a warp_id and a dynamic_warp_id - // is that the dynamic_warp_id is a running number unique to every warp - // run on this shader, where the warp_id is the static warp slot. - unsigned m_dynamic_warp_id; + //Jin: concurrent kernels on a sm +public: + bool can_issue_1block(kernel_info_t & kernel); + bool occupy_shader_resource_1block(kernel_info_t & kernel, bool occupy); + void release_shader_resource_1block(unsigned hw_ctaid, kernel_info_t & kernel); + int find_available_hwtid(unsigned int cta_size, bool occupy); +private: + unsigned int m_occupied_n_threads; + unsigned int m_occupied_shmem; + unsigned int m_occupied_regs; + unsigned int m_occupied_ctas; + std::bitset<MAX_THREAD_PER_SM> m_occupied_hwtid; + std::map<unsigned int, unsigned int> m_occupied_cta_to_hwtid; - // Jin: concurrent kernels on a sm - public: - bool can_issue_1block(kernel_info_t &kernel); - bool occupy_shader_resource_1block(kernel_info_t &kernel, bool occupy); - void release_shader_resource_1block(unsigned hw_ctaid, kernel_info_t &kernel); - int find_available_hwtid(unsigned int cta_size, bool occupy); - private: - unsigned int m_occupied_n_threads; - unsigned int m_occupied_shmem; - unsigned int m_occupied_regs; - unsigned int m_occupied_ctas; - std::bitset<MAX_THREAD_PER_SM> m_occupied_hwtid; - std::map<unsigned int, unsigned int> m_occupied_cta_to_hwtid; }; class simt_core_cluster { - public: - simt_core_cluster(class gpgpu_sim *gpu, unsigned cluster_id, - const shader_core_config *config, - const memory_config *mem_config, shader_core_stats *stats, - memory_stats_t *mstats); +public: + simt_core_cluster( class gpgpu_sim *gpu, + unsigned cluster_id, + const shader_core_config *config, + const memory_config *mem_config, + shader_core_stats *stats, + memory_stats_t *mstats ); - void core_cycle(); - void icnt_cycle(); + void core_cycle(); + void icnt_cycle(); - void reinit(); - unsigned issue_block2core(); - void cache_flush(); - void cache_invalidate(); - bool icnt_injection_buffer_full(unsigned size, bool write); - void icnt_inject_request_packet(class mem_fetch *mf); + void reinit(); + unsigned issue_block2core(); + void cache_flush(); + void cache_invalidate(); + bool icnt_injection_buffer_full(unsigned size, bool write); + void icnt_inject_request_packet(class mem_fetch *mf); - // for perfect memory interface - bool response_queue_full() { - return (m_response_fifo.size() >= m_config->n_simt_ejection_buffer_size); - } - void push_response_fifo(class mem_fetch *mf) { - m_response_fifo.push_back(mf); - } - void get_pdom_stack_top_info(unsigned sid, unsigned tid, unsigned *pc, - unsigned *rpc) const; - unsigned max_cta(const kernel_info_t &kernel); - unsigned get_not_completed() const; - void print_not_completed(FILE *fp) const; - unsigned get_n_active_cta() const; - unsigned get_n_active_sms() const; - gpgpu_sim *get_gpu() { return m_gpu; } + // for perfect memory interface + bool response_queue_full() { + return ( m_response_fifo.size() >= m_config->n_simt_ejection_buffer_size ); + } + void push_response_fifo(class mem_fetch *mf) { + m_response_fifo.push_back(mf); + } + + void get_pdom_stack_top_info( unsigned sid, unsigned tid, unsigned *pc, unsigned *rpc ) const; + unsigned max_cta( const kernel_info_t &kernel ); + unsigned get_not_completed() const; + void print_not_completed( FILE *fp ) const; + unsigned get_n_active_cta() const; + unsigned get_n_active_sms() const; + gpgpu_sim *get_gpu() { return m_gpu; } - void display_pipeline(unsigned sid, FILE *fout, int print_mem, int mask); - void print_cache_stats(FILE *fp, unsigned &dl1_accesses, - unsigned &dl1_misses) const; + void display_pipeline( unsigned sid, FILE *fout, int print_mem, int mask ); + void print_cache_stats( FILE *fp, unsigned& dl1_accesses, unsigned& dl1_misses ) const; - void get_cache_stats(cache_stats &cs) const; - void get_L1I_sub_stats(struct cache_sub_stats &css) const; - void get_L1D_sub_stats(struct cache_sub_stats &css) const; - void get_L1C_sub_stats(struct cache_sub_stats &css) const; - void get_L1T_sub_stats(struct cache_sub_stats &css) const; + void get_cache_stats(cache_stats &cs) const; + void get_L1I_sub_stats(struct cache_sub_stats &css) const; + void get_L1D_sub_stats(struct cache_sub_stats &css) const; + void get_L1C_sub_stats(struct cache_sub_stats &css) const; + void get_L1T_sub_stats(struct cache_sub_stats &css) const; - void get_icnt_stats(long &n_simt_to_mem, long &n_mem_to_simt) const; - float get_current_occupancy(unsigned long long &active, - unsigned long long &total) const; + void get_icnt_stats(long &n_simt_to_mem, long &n_mem_to_simt) const; + float get_current_occupancy( unsigned long long& active, unsigned long long & total ) const; - private: - unsigned m_cluster_id; - gpgpu_sim *m_gpu; - const shader_core_config *m_config; - shader_core_stats *m_stats; - memory_stats_t *m_memory_stats; - shader_core_ctx **m_core; +private: + unsigned m_cluster_id; + gpgpu_sim *m_gpu; + const shader_core_config *m_config; + shader_core_stats *m_stats; + memory_stats_t *m_memory_stats; + shader_core_ctx **m_core; - unsigned m_cta_issue_next_core; - std::list<unsigned> m_core_sim_order; - std::list<mem_fetch *> m_response_fifo; + unsigned m_cta_issue_next_core; + std::list<unsigned> m_core_sim_order; + std::list<mem_fetch*> m_response_fifo; }; class shader_memory_interface : public mem_fetch_interface { - public: - shader_memory_interface(shader_core_ctx *core, simt_core_cluster *cluster) { - m_core = core; - m_cluster = cluster; - } - virtual bool full(unsigned size, bool write) const { - return m_cluster->icnt_injection_buffer_full(size, write); - } - virtual void push(mem_fetch *mf) { - m_core->inc_simt_to_mem(mf->get_num_flits(true)); - m_cluster->icnt_inject_request_packet(mf); - } - - private: - shader_core_ctx *m_core; - simt_core_cluster *m_cluster; +public: + shader_memory_interface( shader_core_ctx *core, simt_core_cluster *cluster ) { m_core=core; m_cluster=cluster; } + virtual bool full( unsigned size, bool write ) const + { + return m_cluster->icnt_injection_buffer_full(size,write); + } + virtual void push(mem_fetch *mf) + { + m_core->inc_simt_to_mem(mf->get_num_flits(true)); + m_cluster->icnt_inject_request_packet(mf); + } +private: + shader_core_ctx *m_core; + simt_core_cluster *m_cluster; }; class perfect_memory_interface : public mem_fetch_interface { - public: - perfect_memory_interface(shader_core_ctx *core, simt_core_cluster *cluster) { - m_core = core; - m_cluster = cluster; - } - virtual bool full(unsigned size, bool write) const { - return m_cluster->response_queue_full(); - } - virtual void push(mem_fetch *mf) { - if (mf && mf->isatomic()) - mf->do_atomic(); // execute atomic inside the "memory subsystem" - m_core->inc_simt_to_mem(mf->get_num_flits(true)); - m_cluster->push_response_fifo(mf); - } - - private: - shader_core_ctx *m_core; - simt_core_cluster *m_cluster; +public: + perfect_memory_interface( shader_core_ctx *core, simt_core_cluster *cluster ) { m_core=core; m_cluster=cluster; } + virtual bool full( unsigned size, bool write) const + { + return m_cluster->response_queue_full(); + } + virtual void push(mem_fetch *mf) + { + if ( mf && mf->isatomic() ) + mf->do_atomic(); // execute atomic inside the "memory subsystem" + m_core->inc_simt_to_mem(mf->get_num_flits(true)); + m_cluster->push_response_fifo(mf); + } +private: + shader_core_ctx *m_core; + simt_core_cluster *m_cluster; }; + inline int scheduler_unit::get_sid() const { return m_shader->get_sid(); } #endif /* SHADER_H */ diff --git a/src/gpgpu-sim/shader_trace.h b/src/gpgpu-sim/shader_trace.h index 0b6c457..ac4e894 100644 --- a/src/gpgpu-sim/shader_trace.h +++ b/src/gpgpu-sim/shader_trace.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2011, Tor M. Aamodt, Tim Rogers -// George L. Yuan, Andrew Turner, Inderpreet Singh +// George L. Yuan, Andrew Turner, Inderpreet Singh // The University of British Columbia // All rights reserved. // @@ -8,16 +8,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -33,48 +31,44 @@ #include "../trace.h" + #if TRACING_ON #define SHADER_PRINT_STR SIM_PRINT_STR "Core %d - " #define SCHED_PRINT_STR SHADER_PRINT_STR "Scheduler %d - " -#define SHADER_DTRACE(x) \ - (DTRACE(x) && \ - (Trace::sampling_core == get_sid() || Trace::sampling_core == -1)) +#define SHADER_DTRACE(x) (DTRACE(x) && (Trace::sampling_core == get_sid()\ + || Trace::sampling_core == -1)) // Intended to be called from inside components of a shader core. // Depends on a get_sid() function -#define SHADER_DPRINTF(x, ...) \ - do { \ - if (SHADER_DTRACE(x)) { \ - printf(SHADER_PRINT_STR, \ - m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle, \ - Trace::trace_streams_str[Trace::x], get_sid()); \ - printf(__VA_ARGS__); \ - } \ - } while (0) +#define SHADER_DPRINTF(x, ...) do {\ + if (SHADER_DTRACE(x)) {\ + printf( SHADER_PRINT_STR,\ + m_gpu->gpu_sim_cycle + m_gpu->gpu_tot_sim_cycle,\ + Trace::trace_streams_str[Trace::x],\ + get_sid() );\ + printf(__VA_ARGS__);\ + }\ +} while (0) // Intended to be called from inside a scheduler_unit. // Depends on a m_id member -#define SCHED_DPRINTF(...) \ - do { \ - if (SHADER_DTRACE(WARP_SCHEDULER)) { \ - printf(SCHED_PRINT_STR, m_shader->get_gpu()->gpu_sim_cycle + \ - m_shader->get_gpu()->gpu_tot_sim_cycle, \ - Trace::trace_streams_str[Trace::WARP_SCHEDULER], get_sid(), \ - m_id); \ - printf(__VA_ARGS__); \ - } \ - } while (0) +#define SCHED_DPRINTF(...) do {\ + if (SHADER_DTRACE(WARP_SCHEDULER)) {\ + printf( SCHED_PRINT_STR,\ + m_shader->get_gpu()->gpu_sim_cycle + m_shader->get_gpu()->gpu_tot_sim_cycle,\ + Trace::trace_streams_str[Trace::WARP_SCHEDULER],\ + get_sid(),\ + m_id );\ + printf(__VA_ARGS__);\ + }\ +} while (0) #else -#define SHADER_DTRACE(x) (false) -#define SHADER_DPRINTF(x, ...) \ - do { \ - } while (0) -#define SCHED_DPRINTF(x, ...) \ - do { \ - } while (0) +#define SHADER_DTRACE(x) (false) +#define SHADER_DPRINTF(x, ...) do {} while (0) +#define SCHED_DPRINTF(x, ...) do {} while (0) #endif diff --git a/src/gpgpu-sim/stack.cc b/src/gpgpu-sim/stack.cc index c52cbc9..e77fc06 100644 --- a/src/gpgpu-sim/stack.cc +++ b/src/gpgpu-sim/stack.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2011, Tor M. Aamodt, Ali Bakhoda, Ivan Sham, +// Copyright (c) 2009-2011, Tor M. Aamodt, Ali Bakhoda, Ivan Sham, // Wilson W.L. Fung // All rights reserved. // @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -29,53 +27,62 @@ #include "stack.h" -#include <assert.h> #include <stdlib.h> +#include <assert.h> void push_stack(Stack *S, address_type val) { - assert(S->top < S->max_size); - S->v[S->top] = val; - (S->top)++; + assert(S->top < S->max_size); + S->v[S->top] = val; + (S->top)++; + } address_type pop_stack(Stack *S) { - (S->top)--; - return (S->v[S->top]); + (S->top)--; + return(S->v[S->top]); } address_type top_stack(Stack *S) { - assert(S->top >= 1); - return (S->v[S->top - 1]); + assert(S->top >= 1); + return(S->v[S->top - 1]); } -Stack *new_stack(int size) { - Stack *S; - S = (Stack *)malloc(sizeof(Stack)); - S->max_size = size; - S->top = 0; - S->v = (address_type *)calloc(size, sizeof(address_type)); - return S; +Stack* new_stack(int size) { + Stack* S; + S = (Stack*)malloc(sizeof(Stack)); + S->max_size = size; + S->top = 0; + S->v = (address_type*)calloc(size, sizeof(address_type)); + return S; } void free_stack(Stack *S) { - free(S->v); - free(S); + free(S->v); + free(S); } -int size_stack(Stack *S) { return S->top; } +int size_stack(Stack *S) { + return S->top; +} -int full_stack(Stack *S) { return S->top >= S->max_size; } +int full_stack(Stack *S) { + return S->top >= S->max_size; +} -int empty_stack(Stack *S) { return S->top == 0; } +int empty_stack(Stack *S) { + return S->top == 0; +} int element_exist_stack(Stack *S, address_type value) { - int i; - for (i = 0; i < S->top; ++i) { - if (value == S->v[i]) { - return 1; - } - } - return 0; + int i; + for (i = 0; i < S->top; ++i) { + if (value == S->v[i]) { + return 1; + } + } + return 0; } -void reset_stack(Stack *S) { S->top = 0; } +void reset_stack(Stack *S) { + S->top = 0; +} diff --git a/src/gpgpu-sim/stack.h b/src/gpgpu-sim/stack.h index dba7ed6..54b6621 100644 --- a/src/gpgpu-sim/stack.h +++ b/src/gpgpu-sim/stack.h @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -33,19 +31,19 @@ #include "../abstract_hardware_model.h" typedef struct { - address_type *v; - int max_size; - int top; + address_type *v; + int max_size; + int top; } Stack; void push_stack(Stack *S, address_type val); address_type pop_stack(Stack *S); address_type top_stack(Stack *S); -Stack *new_stack(int size); +Stack* new_stack(int size); void free_stack(Stack *S); int size_stack(Stack *S); int full_stack(Stack *S); int empty_stack(Stack *S); int element_exist_stack(Stack *S, address_type value); void reset_stack(Stack *S); -#endif // _MY_STACK_ +#endif // _MY_STACK_ diff --git a/src/gpgpu-sim/stat-tool.cc b/src/gpgpu-sim/stat-tool.cc index acbf763..35a4cc3 100644 --- a/src/gpgpu-sim/stat-tool.cc +++ b/src/gpgpu-sim/stat-tool.cc @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -29,159 +27,160 @@ #include "stat-tool.h" -#include <assert.h> #include <stdio.h> #include <stdlib.h> +#include <assert.h> #include <zlib.h> -#include <algorithm> +#include <string> #include <list> +#include <vector> #include <map> +#include <algorithm> #include <string> -#include <string> -#include <vector> #include "../../libcuda/gpgpu_context.h" //////////////////////////////////////////////////////////////////////////////// -static unsigned long long min_snap_shot_interval = 0; -static unsigned long long next_snap_shot_cycle = 0; -static std::list<snap_shot_trigger *> list_ss_trigger; +static unsigned long long min_snap_shot_interval = 0; +static unsigned long long next_snap_shot_cycle = 0; +static std::list<snap_shot_trigger*> list_ss_trigger; -void add_snap_shot_trigger(snap_shot_trigger *ss_trigger) { - // quick optimization assuming that all snap shot intervals are perfect - // multiples of each other - if (min_snap_shot_interval == 0 || - min_snap_shot_interval > ss_trigger->get_interval()) { - min_snap_shot_interval = ss_trigger->get_interval(); - next_snap_shot_cycle = - min_snap_shot_interval; // assume that snap shots haven't started yet - } - list_ss_trigger.push_back(ss_trigger); +void add_snap_shot_trigger (snap_shot_trigger* ss_trigger) +{ + // quick optimization assuming that all snap shot intervals are perfect multiples of each other + if (min_snap_shot_interval == 0 || min_snap_shot_interval > ss_trigger->get_interval()) { + min_snap_shot_interval = ss_trigger->get_interval(); + next_snap_shot_cycle = min_snap_shot_interval; // assume that snap shots haven't started yet + } + list_ss_trigger.push_back(ss_trigger); } -void remove_snap_shot_trigger(snap_shot_trigger *ss_trigger) { - list_ss_trigger.remove(ss_trigger); +void remove_snap_shot_trigger (snap_shot_trigger* ss_trigger) +{ + list_ss_trigger.remove(ss_trigger); } -void try_snap_shot(unsigned long long current_cycle) { - if (min_snap_shot_interval == 0) return; - if (current_cycle != next_snap_shot_cycle) return; - - std::list<snap_shot_trigger *>::iterator ss_trigger_iter = - list_ss_trigger.begin(); - for (; ss_trigger_iter != list_ss_trigger.end(); ++ss_trigger_iter) { - (*ss_trigger_iter) - ->snap_shot(current_cycle); // WF: should be try_snap_shot - } - next_snap_shot_cycle = - current_cycle + - min_snap_shot_interval; // WF: stateful testing, maybe bad +void try_snap_shot (unsigned long long current_cycle) +{ + if (min_snap_shot_interval == 0) return; + if (current_cycle != next_snap_shot_cycle) return; + + std::list<snap_shot_trigger*>::iterator ss_trigger_iter = list_ss_trigger.begin(); + for(; ss_trigger_iter != list_ss_trigger.end(); ++ss_trigger_iter) { + (*ss_trigger_iter)->snap_shot(current_cycle); // WF: should be try_snap_shot + } + next_snap_shot_cycle = current_cycle + min_snap_shot_interval; // WF: stateful testing, maybe bad } //////////////////////////////////////////////////////////////////////////////// + +static unsigned long long spill_interval = 0; +static unsigned long long next_spill_cycle = 0; +static std::list<spill_log_interface*> list_spill_log; -static unsigned long long spill_interval = 0; -static unsigned long long next_spill_cycle = 0; -static std::list<spill_log_interface *> list_spill_log; - -void add_spill_log(spill_log_interface *spill_log) { - list_spill_log.push_back(spill_log); +void add_spill_log (spill_log_interface* spill_log) +{ + list_spill_log.push_back(spill_log); } -void remove_spill_log(spill_log_interface *spill_log) { - list_spill_log.remove(spill_log); +void remove_spill_log (spill_log_interface* spill_log) +{ + list_spill_log.remove(spill_log); } -void set_spill_interval(unsigned long long interval) { - spill_interval = interval; - next_spill_cycle = spill_interval; +void set_spill_interval (unsigned long long interval) +{ + spill_interval = interval; + next_spill_cycle = spill_interval; } -void spill_log_to_file(FILE *fout, int final, - unsigned long long current_cycle) { - if (!final && spill_interval == 0) return; - if (!final && current_cycle <= next_spill_cycle) return; +void spill_log_to_file (FILE *fout, int final, unsigned long long current_cycle) +{ + if (!final && spill_interval == 0) return; + if (!final && current_cycle <= next_spill_cycle) return; - fprintf(fout, "\n"); // ensure that the spill occurs at a new line - std::list<spill_log_interface *>::iterator i_spill_log = - list_spill_log.begin(); - for (; i_spill_log != list_spill_log.end(); ++i_spill_log) { - (*i_spill_log)->spill(fout, final); - } - fflush(fout); + fprintf(fout, "\n"); // ensure that the spill occurs at a new line + std::list<spill_log_interface*>::iterator i_spill_log = list_spill_log.begin(); + for(; i_spill_log != list_spill_log.end(); ++i_spill_log) { + (*i_spill_log)->spill(fout, final); + } + fflush(fout); - next_spill_cycle = - current_cycle + spill_interval; // WF: stateful testing, maybe bad + next_spill_cycle = current_cycle + spill_interval; // WF: stateful testing, maybe bad } //////////////////////////////////////////////////////////////////////////////// static int n_thread_CFloggers = 0; -static thread_CFlocality **thread_CFlogger = NULL; - -void create_thread_CFlogger(gpgpu_context *ctx, int n_loggers, int n_threads, - address_type start_pc, - unsigned long long logging_interval) { - destroy_thread_CFlogger(); +static thread_CFlocality** thread_CFlogger = NULL; - n_thread_CFloggers = n_loggers; - thread_CFlogger = new thread_CFlocality *[n_loggers]; +void create_thread_CFlogger(gpgpu_context* ctx, int n_loggers, int n_threads, address_type start_pc, unsigned long long logging_interval) +{ + destroy_thread_CFlogger(); + + n_thread_CFloggers = n_loggers; + thread_CFlogger = new thread_CFlocality*[n_loggers]; - std::string name_tpl("CFLog"); - char buffer[32]; - for (int i = 0; i < n_thread_CFloggers; i++) { - snprintf(buffer, 32, "%02d", i); - thread_CFlogger[i] = new thread_CFlocality( - ctx, name_tpl + buffer, logging_interval, n_threads, start_pc); - if (logging_interval != 0) { - add_snap_shot_trigger(thread_CFlogger[i]); - add_spill_log(thread_CFlogger[i]); - } - } + std::string name_tpl("CFLog"); + char buffer[32]; + for (int i = 0; i < n_thread_CFloggers; i++) { + snprintf(buffer, 32, "%02d", i); + thread_CFlogger[i] = new thread_CFlocality( ctx, name_tpl + buffer, logging_interval, n_threads, start_pc); + if (logging_interval != 0) { + add_snap_shot_trigger(thread_CFlogger[i]); + add_spill_log(thread_CFlogger[i]); + } + } } -void destroy_thread_CFlogger() { - if (thread_CFlogger != NULL) { - for (int i = 0; i < n_thread_CFloggers; i++) { - remove_snap_shot_trigger(thread_CFlogger[i]); - remove_spill_log(thread_CFlogger[i]); - delete thread_CFlogger[i]; - } - delete[] thread_CFlogger; - thread_CFlogger = NULL; - } +void destroy_thread_CFlogger( ) +{ + if (thread_CFlogger != NULL) { + for (int i = 0; i < n_thread_CFloggers; i++) { + remove_snap_shot_trigger(thread_CFlogger[i]); + remove_spill_log(thread_CFlogger[i]); + delete thread_CFlogger[i]; + } + delete [] thread_CFlogger; + thread_CFlogger = NULL; + } } -void cflog_update_thread_pc(int logger_id, int thread_id, address_type pc) { - if (thread_CFlogger == NULL) return; // this means no visualizer output - if (thread_id < 0) return; - thread_CFlogger[logger_id]->update_thread_pc(thread_id, pc); +void cflog_update_thread_pc( int logger_id, int thread_id, address_type pc ) +{ + if (thread_CFlogger == NULL) return; // this means no visualizer output + if (thread_id < 0) return; + thread_CFlogger[logger_id]->update_thread_pc(thread_id, pc); } -// deprecated -void cflog_snapshot(int logger_id, unsigned long long cycle) { - thread_CFlogger[logger_id]->snap_shot(cycle); +// deprecated +void cflog_snapshot( int logger_id, unsigned long long cycle ) +{ + thread_CFlogger[logger_id]->snap_shot(cycle); } -void cflog_print(FILE *fout) { - if (thread_CFlogger == NULL) return; // this means no visualizer output - for (int i = 0; i < n_thread_CFloggers; i++) { - thread_CFlogger[i]->print_histo(fout); - } +void cflog_print(FILE *fout) +{ + if (thread_CFlogger == NULL) return; // this means no visualizer output + for (int i = 0; i < n_thread_CFloggers; i++) { + thread_CFlogger[i]->print_histo(fout); + } } -void cflog_visualizer_print(FILE *fout) { - if (thread_CFlogger == NULL) return; // this means no visualizer output - for (int i = 0; i < n_thread_CFloggers; i++) { - thread_CFlogger[i]->print_visualizer(fout); - } +void cflog_visualizer_print(FILE *fout) +{ + if (thread_CFlogger == NULL) return; // this means no visualizer output + for (int i = 0; i < n_thread_CFloggers; i++) { + thread_CFlogger[i]->print_visualizer(fout); + } } -void cflog_visualizer_gzprint(gzFile fout) { - if (thread_CFlogger == NULL) return; // this means no visualizer output - for (int i = 0; i < n_thread_CFloggers; i++) { - thread_CFlogger[i]->print_visualizer(fout); - } +void cflog_visualizer_gzprint(gzFile fout) +{ + if (thread_CFlogger == NULL) return; // this means no visualizer output + for (int i = 0; i < n_thread_CFloggers; i++) { + thread_CFlogger[i]->print_visualizer(fout); + } } //////////////////////////////////////////////////////////////////////////////// @@ -190,23 +189,26 @@ int insn_warp_occ_logger::s_ids = 0; static std::vector<insn_warp_occ_logger> iwo_logger; -void insn_warp_occ_create(int n_loggers, int simd_width) { - iwo_logger.clear(); - iwo_logger.assign(n_loggers, insn_warp_occ_logger(simd_width)); - for (unsigned i = 0; i < iwo_logger.size(); i++) { - iwo_logger[i].set_id(i); - } +void insn_warp_occ_create( int n_loggers, int simd_width ) +{ + iwo_logger.clear(); + iwo_logger.assign(n_loggers, insn_warp_occ_logger(simd_width)); + for (unsigned i = 0; i < iwo_logger.size(); i++) { + iwo_logger[i].set_id(i); + } } -void insn_warp_occ_log(int logger_id, address_type pc, int warp_occ) { - if (warp_occ <= 0) return; - iwo_logger[logger_id].log(pc, warp_occ); +void insn_warp_occ_log( int logger_id, address_type pc, int warp_occ) +{ + if (warp_occ <= 0) return; + iwo_logger[logger_id].log(pc, warp_occ); } -void insn_warp_occ_print(FILE *fout) { - for (unsigned i = 0; i < iwo_logger.size(); i++) { - iwo_logger[i].print(fout); - } +void insn_warp_occ_print( FILE *fout ) +{ + for (unsigned i = 0; i < iwo_logger.size(); i++) { + iwo_logger[i].print(fout); + } } //////////////////////////////////////////////////////////////////////////////// @@ -219,33 +221,36 @@ int linear_histogram_logger::s_ids = 0; static std::vector<linear_histogram_logger> s_warp_occ_logger; -void shader_warp_occ_create(int n_loggers, int simd_width, - unsigned long long logging_interval) { - // simd_width + 1 to include the case with full warp - s_warp_occ_logger.assign( - n_loggers, - linear_histogram_logger(simd_width + 1, logging_interval, "ShdrWarpOcc")); - for (unsigned i = 0; i < s_warp_occ_logger.size(); i++) { - s_warp_occ_logger[i].set_id(i); - add_snap_shot_trigger(&(s_warp_occ_logger[i])); - add_spill_log(&(s_warp_occ_logger[i])); - } +void shader_warp_occ_create( int n_loggers, int simd_width, unsigned long long logging_interval) +{ + // simd_width + 1 to include the case with full warp + s_warp_occ_logger.assign(n_loggers, + linear_histogram_logger(simd_width + 1, logging_interval, "ShdrWarpOcc")); + for (unsigned i = 0; i < s_warp_occ_logger.size(); i++) { + s_warp_occ_logger[i].set_id(i); + add_snap_shot_trigger(&(s_warp_occ_logger[i])); + add_spill_log(&(s_warp_occ_logger[i])); + } } -void shader_warp_occ_log(int logger_id, int warp_occ) { - s_warp_occ_logger[logger_id].log(warp_occ); +void shader_warp_occ_log( int logger_id, int warp_occ) +{ + s_warp_occ_logger[logger_id].log(warp_occ); } -void shader_warp_occ_snapshot(int logger_id, unsigned long long current_cycle) { - s_warp_occ_logger[logger_id].snap_shot(current_cycle); +void shader_warp_occ_snapshot( int logger_id, unsigned long long current_cycle) +{ + s_warp_occ_logger[logger_id].snap_shot(current_cycle); } -void shader_warp_occ_print(FILE *fout) { - for (unsigned i = 0; i < s_warp_occ_logger.size(); i++) { - s_warp_occ_logger[i].print(fout); - } +void shader_warp_occ_print( FILE *fout ) +{ + for (unsigned i = 0; i < s_warp_occ_logger.size(); i++) { + s_warp_occ_logger[i].print(fout); + } } + ///////////////////////////////////////////////////////////////////////////////////// // per-shadercore memory-access logger ///////////////////////////////////////////////////////////////////////////////////// @@ -254,116 +259,106 @@ static int s_mem_acc_logger_n_dram = 0; static int s_mem_acc_logger_n_bank = 0; static std::vector<linear_histogram_logger> s_mem_acc_logger; -void shader_mem_acc_create(int n_loggers, int n_dram, int n_bank, - unsigned long long logging_interval) { - // (n_bank + 1) to space data out; 2x to separate read and write - s_mem_acc_logger.assign( - n_loggers, linear_histogram_logger(2 * n_dram * (n_bank + 1), - logging_interval, "ShdrMemAcc")); +void shader_mem_acc_create( int n_loggers, int n_dram, int n_bank, unsigned long long logging_interval) +{ + // (n_bank + 1) to space data out; 2x to separate read and write + s_mem_acc_logger.assign(n_loggers, + linear_histogram_logger(2 * n_dram * (n_bank + 1), logging_interval, "ShdrMemAcc")); - s_mem_acc_logger_n_dram = n_dram; - s_mem_acc_logger_n_bank = n_bank; - for (unsigned i = 0; i < s_mem_acc_logger.size(); i++) { - s_mem_acc_logger[i].set_id(i); - add_snap_shot_trigger(&(s_mem_acc_logger[i])); - add_spill_log(&(s_mem_acc_logger[i])); - } + s_mem_acc_logger_n_dram = n_dram; + s_mem_acc_logger_n_bank = n_bank; + for (unsigned i = 0; i < s_mem_acc_logger.size(); i++) { + s_mem_acc_logger[i].set_id(i); + add_snap_shot_trigger(&(s_mem_acc_logger[i])); + add_spill_log(&(s_mem_acc_logger[i])); + } } -void shader_mem_acc_log(int logger_id, int dram_id, int bank, char rw) { - if (s_mem_acc_logger_n_dram == 0) return; - int write_offset = 0; - switch (rw) { - case 'r': - write_offset = 0; - break; - case 'w': - write_offset = (s_mem_acc_logger_n_bank + 1) * s_mem_acc_logger_n_dram; - break; - default: - assert(0); - break; - } - s_mem_acc_logger[logger_id].log(dram_id * s_mem_acc_logger_n_bank + bank + - write_offset); +void shader_mem_acc_log( int logger_id, int dram_id, int bank, char rw) +{ + if (s_mem_acc_logger_n_dram == 0) return; + int write_offset = 0; + switch(rw) { + case 'r': write_offset = 0; break; + case 'w': write_offset = (s_mem_acc_logger_n_bank + 1) * s_mem_acc_logger_n_dram; break; + default: assert(0); break; + } + s_mem_acc_logger[logger_id].log(dram_id * s_mem_acc_logger_n_bank + bank + write_offset); } -void shader_mem_acc_snapshot(int logger_id, unsigned long long current_cycle) { - s_mem_acc_logger[logger_id].snap_shot(current_cycle); +void shader_mem_acc_snapshot( int logger_id, unsigned long long current_cycle) +{ + s_mem_acc_logger[logger_id].snap_shot(current_cycle); } -void shader_mem_acc_print(FILE *fout) { - for (unsigned i = 0; i < s_mem_acc_logger.size(); i++) { - s_mem_acc_logger[i].print(fout); - } +void shader_mem_acc_print( FILE *fout ) +{ + for (unsigned i = 0; i < s_mem_acc_logger.size(); i++) { + s_mem_acc_logger[i].print(fout); + } } + ///////////////////////////////////////////////////////////////////////////////////// // per-shadercore memory-latency logger ///////////////////////////////////////////////////////////////////////////////////// static bool s_mem_lat_logger_used = false; -static int s_mem_lat_logger_nbins = 48; // up to 2^24 = 16M +static int s_mem_lat_logger_nbins = 48; // up to 2^24 = 16M static std::vector<linear_histogram_logger> s_mem_lat_logger; -void shader_mem_lat_create(int n_loggers, unsigned long long logging_interval) { - s_mem_lat_logger.assign( - n_loggers, linear_histogram_logger(s_mem_lat_logger_nbins, - logging_interval, "ShdrMemLat")); - - for (unsigned i = 0; i < s_mem_lat_logger.size(); i++) { - s_mem_lat_logger[i].set_id(i); - add_snap_shot_trigger(&(s_mem_lat_logger[i])); - add_spill_log(&(s_mem_lat_logger[i])); - } +void shader_mem_lat_create( int n_loggers, unsigned long long logging_interval) +{ + s_mem_lat_logger.assign(n_loggers, + linear_histogram_logger(s_mem_lat_logger_nbins, logging_interval, "ShdrMemLat")); - s_mem_lat_logger_used = true; + for (unsigned i = 0; i < s_mem_lat_logger.size(); i++) { + s_mem_lat_logger[i].set_id(i); + add_snap_shot_trigger(&(s_mem_lat_logger[i])); + add_spill_log(&(s_mem_lat_logger[i])); + } + + s_mem_lat_logger_used = true; } -void shader_mem_lat_log(int logger_id, int latency) { - if (s_mem_lat_logger_used == false) return; - if (latency > (1 << (s_mem_lat_logger_nbins / 2))) - assert(0); // guard for out of bound bin - assert(latency > 0); - - int latency_bin; - - int bin; // LOG_2(latency) - int v = latency; - register unsigned int shift; +void shader_mem_lat_log( int logger_id, int latency) +{ + if (s_mem_lat_logger_used == false) return; + if (latency > (1<<(s_mem_lat_logger_nbins/2))) assert(0); // guard for out of bound bin + assert(latency > 0); + + int latency_bin; + + int bin; // LOG_2(latency) + int v = latency; + register unsigned int shift; - bin = (v > 0xFFFF) << 4; - v >>= bin; - shift = (v > 0xFF) << 3; - v >>= shift; - bin |= shift; - shift = (v > 0xF) << 2; - v >>= shift; - bin |= shift; - shift = (v > 0x3) << 1; - v >>= shift; - bin |= shift; - bin |= (v >> 1); - latency_bin = 2 * bin; - if (bin > 0) { - latency_bin += ((latency & (1 << (bin - 1))) != 0) - ? 1 - : 0; // approx. for LOG_sqrt2(latency) - } + bin = (v > 0xFFFF) << 4; v >>= bin; + shift = (v > 0xFF ) << 3; v >>= shift; bin |= shift; + shift = (v > 0xF ) << 2; v >>= shift; bin |= shift; + shift = (v > 0x3 ) << 1; v >>= shift; bin |= shift; + bin |= (v >> 1); + latency_bin = 2 * bin; + if (bin > 0) { + latency_bin += ((latency & (1 << (bin - 1))) != 0)? 1 : 0; // approx. for LOG_sqrt2(latency) + } - s_mem_lat_logger[logger_id].log(latency_bin); + s_mem_lat_logger[logger_id].log(latency_bin); } -void shader_mem_lat_snapshot(int logger_id, unsigned long long current_cycle) { - s_mem_lat_logger[logger_id].snap_shot(current_cycle); +void shader_mem_lat_snapshot( int logger_id, unsigned long long current_cycle) +{ + s_mem_lat_logger[logger_id].snap_shot(current_cycle); } -void shader_mem_lat_print(FILE *fout) { - for (unsigned i = 0; i < s_mem_lat_logger.size(); i++) { - s_mem_lat_logger[i].print(fout); - } +void shader_mem_lat_print( FILE *fout ) +{ + for (unsigned i = 0; i < s_mem_lat_logger.size(); i++) { + s_mem_lat_logger[i].print(fout); + } } + ///////////////////////////////////////////////////////////////////////////////////// // per-shadercore cache-miss logger ///////////////////////////////////////////////////////////////////////////////////// @@ -371,393 +366,425 @@ void shader_mem_lat_print(FILE *fout) { static int s_cache_access_logger_n_types = 0; static std::vector<linear_histogram_logger> s_cache_access_logger; -enum cache_access_logger_types { NORMALS, TEXTURE, CONSTANT, INSTRUCTION }; +enum cache_access_logger_types { + NORMALS, TEXTURE, CONSTANT, INSTRUCTION +}; int get_shader_normal_cache_id() { return NORMALS; } int get_shader_texture_cache_id() { return TEXTURE; } int get_shader_constant_cache_id() { return CONSTANT; } int get_shader_instruction_cache_id() { return INSTRUCTION; } -void shader_cache_access_create(int n_loggers, int n_types, - unsigned long long logging_interval) { - // There are different type of cache (x2 for recording accesses and misses) - s_cache_access_logger.assign( - n_loggers, - linear_histogram_logger(n_types * 2, logging_interval, "ShdrCacheMiss")); +void shader_cache_access_create( int n_loggers, int n_types, unsigned long long logging_interval) +{ + // There are different type of cache (x2 for recording accesses and misses) + s_cache_access_logger.assign(n_loggers, + linear_histogram_logger(n_types * 2, logging_interval, "ShdrCacheMiss")); - s_cache_access_logger_n_types = n_types; - for (unsigned i = 0; i < s_cache_access_logger.size(); i++) { - s_cache_access_logger[i].set_id(i); - add_snap_shot_trigger(&(s_cache_access_logger[i])); - add_spill_log(&(s_cache_access_logger[i])); - } + s_cache_access_logger_n_types = n_types; + for (unsigned i = 0; i < s_cache_access_logger.size(); i++) { + s_cache_access_logger[i].set_id(i); + add_snap_shot_trigger(&(s_cache_access_logger[i])); + add_spill_log(&(s_cache_access_logger[i])); + } } -void shader_cache_access_log(int logger_id, int type, int miss) { - if (s_cache_access_logger_n_types == 0) return; - if (logger_id < 0) return; - assert(type == NORMALS || type == TEXTURE || type == CONSTANT || - type == INSTRUCTION); - assert(miss == 0 || miss == 1); - - s_cache_access_logger[logger_id].log(2 * type + miss); +void shader_cache_access_log( int logger_id, int type, int miss) +{ + if (s_cache_access_logger_n_types == 0) return; + if (logger_id < 0) return; + assert(type == NORMALS || type == TEXTURE || type == CONSTANT || type == INSTRUCTION); + assert(miss == 0 || miss == 1); + + s_cache_access_logger[logger_id].log(2 * type + miss); } -void shader_cache_access_unlog(int logger_id, int type, int miss) { - if (s_cache_access_logger_n_types == 0) return; - if (logger_id < 0) return; - assert(type == NORMALS || type == TEXTURE || type == CONSTANT || - type == INSTRUCTION); - assert(miss == 0 || miss == 1); - - s_cache_access_logger[logger_id].unlog(2 * type + miss); +void shader_cache_access_unlog( int logger_id, int type, int miss) +{ + if (s_cache_access_logger_n_types == 0) return; + if (logger_id < 0) return; + assert(type == NORMALS || type == TEXTURE || type == CONSTANT || type == INSTRUCTION); + assert(miss == 0 || miss == 1); + + s_cache_access_logger[logger_id].unlog(2 * type + miss); } -void shader_cache_access_print(FILE *fout) { - for (unsigned i = 0; i < s_cache_access_logger.size(); i++) { - s_cache_access_logger[i].print(fout); - } +void shader_cache_access_print( FILE *fout ) +{ + for (unsigned i = 0; i < s_cache_access_logger.size(); i++) { + s_cache_access_logger[i].print(fout); + } } + ///////////////////////////////////////////////////////////////////////////////////// -// per-shadercore CTA count logger (only make sense with -// gpgpu_spread_blocks_across_cores) +// per-shadercore CTA count logger (only make sense with gpgpu_spread_blocks_across_cores) ///////////////////////////////////////////////////////////////////////////////////// static linear_histogram_logger *s_CTA_count_logger = NULL; -void shader_CTA_count_create(int n_shaders, - unsigned long long logging_interval) { - // only need one logger to track all the shaders - if (s_CTA_count_logger != NULL) delete s_CTA_count_logger; - s_CTA_count_logger = new linear_histogram_logger(n_shaders, logging_interval, - "ShdrCTACount", false); +void shader_CTA_count_create( int n_shaders, unsigned long long logging_interval) +{ + // only need one logger to track all the shaders + if (s_CTA_count_logger != NULL) delete s_CTA_count_logger; + s_CTA_count_logger = new linear_histogram_logger(n_shaders, logging_interval, "ShdrCTACount", false); - s_CTA_count_logger->set_id(-1); - if (logging_interval != 0) { - add_snap_shot_trigger(s_CTA_count_logger); - add_spill_log(s_CTA_count_logger); - } + s_CTA_count_logger->set_id(-1); + if (logging_interval != 0) { + add_snap_shot_trigger(s_CTA_count_logger); + add_spill_log(s_CTA_count_logger); + } } -void shader_CTA_count_log(int shader_id, int nCTAadded) { - if (s_CTA_count_logger == NULL) return; - - for (int i = 0; i < nCTAadded; i++) { - s_CTA_count_logger->log(shader_id); - } +void shader_CTA_count_log( int shader_id, int nCTAadded ) +{ + if (s_CTA_count_logger == NULL) return; + + for (int i = 0; i < nCTAadded; i++) { + s_CTA_count_logger->log(shader_id); + } } -void shader_CTA_count_unlog(int shader_id, int nCTAdone) { - if (s_CTA_count_logger == NULL) return; - - for (int i = 0; i < nCTAdone; i++) { - s_CTA_count_logger->unlog(shader_id); - } +void shader_CTA_count_unlog( int shader_id, int nCTAdone ) +{ + if (s_CTA_count_logger == NULL) return; + + for (int i = 0; i < nCTAdone; i++) { + s_CTA_count_logger->unlog(shader_id); + } } -void shader_CTA_count_print(FILE *fout) { - if (s_CTA_count_logger == NULL) return; - s_CTA_count_logger->print(fout); +void shader_CTA_count_print( FILE *fout ) +{ + if (s_CTA_count_logger == NULL) return; + s_CTA_count_logger->print(fout); } -void shader_CTA_count_visualizer_print(FILE *fout) { - if (s_CTA_count_logger == NULL) return; - s_CTA_count_logger->print_visualizer(fout); +void shader_CTA_count_visualizer_print( FILE *fout ) +{ + if (s_CTA_count_logger == NULL) return; + s_CTA_count_logger->print_visualizer(fout); } -void shader_CTA_count_visualizer_gzprint(gzFile fout) { - if (s_CTA_count_logger == NULL) return; - s_CTA_count_logger->print_visualizer(fout); +void shader_CTA_count_visualizer_gzprint( gzFile fout ) +{ + if (s_CTA_count_logger == NULL) return; + s_CTA_count_logger->print_visualizer(fout); } + //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// -thread_insn_span::thread_insn_span(unsigned long long cycle, gpgpu_context *ctx) - : m_cycle(cycle), +thread_insn_span::thread_insn_span(unsigned long long cycle, gpgpu_context* ctx) + : m_cycle(cycle), #if (tr1_hash_map_ismap == 1) - m_insn_span_count() -#else - m_insn_span_count(32 * 1024) + m_insn_span_count() +#else + m_insn_span_count(32*1024) #endif { - gpgpu_ctx = ctx; + gpgpu_ctx = ctx; } -thread_insn_span::~thread_insn_span() {} - -thread_insn_span::thread_insn_span(const thread_insn_span &other, - gpgpu_context *ctx) - : m_cycle(other.m_cycle), m_insn_span_count(other.m_insn_span_count) { - gpgpu_ctx = ctx; +thread_insn_span::~thread_insn_span() { } + +thread_insn_span::thread_insn_span(const thread_insn_span& other, gpgpu_context* ctx) + : m_cycle(other.m_cycle), + m_insn_span_count(other.m_insn_span_count) +{ + gpgpu_ctx = ctx; } - -thread_insn_span &thread_insn_span::operator=(const thread_insn_span &other) { - printf("thread_insn_span& operator=\n"); - if (this != &other) { - m_insn_span_count = other.m_insn_span_count; - m_cycle = other.m_cycle; - } - return *this; + +thread_insn_span& thread_insn_span::operator=(const thread_insn_span& other) +{ + printf("thread_insn_span& operator=\n"); + if (this != &other) { + m_insn_span_count = other.m_insn_span_count; + m_cycle = other.m_cycle; + } + return *this; } - -thread_insn_span &thread_insn_span::operator+=(const thread_insn_span &other) { - span_count_map::const_iterator i_sc = other.m_insn_span_count.begin(); - for (; i_sc != other.m_insn_span_count.end(); ++i_sc) { - m_insn_span_count[i_sc->first] += i_sc->second; - } - return *this; + +thread_insn_span& thread_insn_span::operator+=(const thread_insn_span& other) +{ + span_count_map::const_iterator i_sc = other.m_insn_span_count.begin(); + for (; i_sc != other.m_insn_span_count.end(); ++i_sc) { + m_insn_span_count[i_sc->first] += i_sc->second; + } + return *this; } - -void thread_insn_span::set_span(address_type pc) { - if (((int)pc) >= 0) m_insn_span_count[pc] += 1; + +void thread_insn_span::set_span( address_type pc ) +{ + if( ((int)pc) >= 0 ) + m_insn_span_count[pc] += 1; } - -void thread_insn_span::reset(unsigned long long cycle) { - m_cycle = cycle; - m_insn_span_count.clear(); + +void thread_insn_span::reset(unsigned long long cycle) +{ + m_cycle = cycle; + m_insn_span_count.clear(); } - -void thread_insn_span::print_span(FILE *fout) const { - fprintf(fout, "%d: ", (int)m_cycle); - span_count_map::const_iterator i_sc = m_insn_span_count.begin(); - for (; i_sc != m_insn_span_count.end(); ++i_sc) { - fprintf(fout, "%d ", i_sc->first); - } - fprintf(fout, "\n"); + +void thread_insn_span::print_span(FILE *fout) const +{ + fprintf(fout, "%d: ", (int)m_cycle); + span_count_map::const_iterator i_sc = m_insn_span_count.begin(); + for (; i_sc != m_insn_span_count.end(); ++i_sc) { + fprintf(fout, "%d ", i_sc->first); + } + fprintf(fout, "\n"); } -void thread_insn_span::print_histo(FILE *fout) const { - fprintf(fout, "%d:", (int)m_cycle); - span_count_map::const_iterator i_sc = m_insn_span_count.begin(); - for (; i_sc != m_insn_span_count.end(); ++i_sc) { - fprintf(fout, "%d ", i_sc->second); - } - fprintf(fout, "\n"); +void thread_insn_span::print_histo(FILE *fout) const +{ + fprintf(fout, "%d:", (int)m_cycle); + span_count_map::const_iterator i_sc = m_insn_span_count.begin(); + for (; i_sc != m_insn_span_count.end(); ++i_sc) { + fprintf(fout, "%d ", i_sc->second); + } + fprintf(fout, "\n"); } -void thread_insn_span::print_sparse_histo(FILE *fout) const { - int n_printed_entries = 0; - span_count_map::const_iterator i_sc = m_insn_span_count.begin(); - for (; i_sc != m_insn_span_count.end(); ++i_sc) { - unsigned ptx_lineno = gpgpu_ctx->translate_pc_to_ptxlineno(i_sc->first); - fprintf(fout, "%u %d ", ptx_lineno, i_sc->second); - n_printed_entries++; - } - if (n_printed_entries == 0) { - fprintf(fout, "0 0 "); - } - fprintf(fout, "\n"); +void thread_insn_span::print_sparse_histo(FILE *fout) const +{ + int n_printed_entries = 0; + span_count_map::const_iterator i_sc = m_insn_span_count.begin(); + for (; i_sc != m_insn_span_count.end(); ++i_sc) { + unsigned ptx_lineno = gpgpu_ctx->translate_pc_to_ptxlineno(i_sc->first); + fprintf(fout, "%u %d ", ptx_lineno, i_sc->second); + n_printed_entries++; + } + if (n_printed_entries == 0) { + fprintf(fout, "0 0 "); + } + fprintf(fout, "\n"); } -void thread_insn_span::print_sparse_histo(gzFile fout) const { - int n_printed_entries = 0; - span_count_map::const_iterator i_sc = m_insn_span_count.begin(); - for (; i_sc != m_insn_span_count.end(); ++i_sc) { - unsigned ptx_lineno = gpgpu_ctx->translate_pc_to_ptxlineno(i_sc->first); - gzprintf(fout, "%u %d ", ptx_lineno, i_sc->second); - n_printed_entries++; - } - if (n_printed_entries == 0) { - gzprintf(fout, "0 0 "); - } - gzprintf(fout, "\n"); +void thread_insn_span::print_sparse_histo(gzFile fout) const +{ + int n_printed_entries = 0; + span_count_map::const_iterator i_sc = m_insn_span_count.begin(); + for (; i_sc != m_insn_span_count.end(); ++i_sc) { + unsigned ptx_lineno = gpgpu_ctx->translate_pc_to_ptxlineno(i_sc->first); + gzprintf(fout, "%u %d ", ptx_lineno, i_sc->second); + n_printed_entries++; + } + if (n_printed_entries == 0) { + gzprintf(fout, "0 0 "); + } + gzprintf(fout, "\n"); } //////////////////////////////////////////////////////////////////////////////// -thread_CFlocality::thread_CFlocality(gpgpu_context *ctx, std::string name, - unsigned long long snap_shot_interval, - int nthreads, address_type start_pc, - unsigned long long start_cycle) - : snap_shot_trigger(snap_shot_interval), - m_name(name), - m_nthreads(nthreads), - m_thread_pc(nthreads, start_pc), - m_cycle(start_cycle), - m_thd_span(start_cycle, ctx) { - std::fill( - m_thread_pc.begin(), m_thread_pc.end(), - -1); // so that hw thread with no work assigned will not clobber results +thread_CFlocality::thread_CFlocality( gpgpu_context* ctx, std::string name, + unsigned long long snap_shot_interval, + int nthreads, + address_type start_pc, + unsigned long long start_cycle) + : snap_shot_trigger(snap_shot_interval), m_name(name), + m_nthreads(nthreads), m_thread_pc(nthreads, start_pc), m_cycle(start_cycle), + m_thd_span(start_cycle, ctx) +{ + std::fill(m_thread_pc.begin(), m_thread_pc.end(), -1); // so that hw thread with no work assigned will not clobber results } - -thread_CFlocality::~thread_CFlocality() {} - -void thread_CFlocality::update_thread_pc(int thread_id, address_type pc) { - m_thread_pc[thread_id] = pc; - m_thd_span.set_span(pc); + +thread_CFlocality::~thread_CFlocality() +{ +} + +void thread_CFlocality::update_thread_pc( int thread_id, address_type pc ) +{ + m_thread_pc[thread_id] = pc; + m_thd_span.set_span(pc); } - -void thread_CFlocality::snap_shot(unsigned long long current_cycle) { - m_thd_span_archive.push_back(m_thd_span); - m_thd_span.reset(current_cycle); - for (int i = 0; i < (int)m_thread_pc.size(); i++) { - m_thd_span.set_span(m_thread_pc[i]); - } + +void thread_CFlocality::snap_shot(unsigned long long current_cycle) +{ + m_thd_span_archive.push_back(m_thd_span); + m_thd_span.reset(current_cycle); + for (int i = 0; i < (int)m_thread_pc.size(); i++) { + m_thd_span.set_span(m_thread_pc[i]); + } } - -void thread_CFlocality::spill(FILE *fout, bool final) { - std::list<thread_insn_span>::iterator lit = m_thd_span_archive.begin(); - for (; lit != m_thd_span_archive.end(); lit = m_thd_span_archive.erase(lit)) { - fprintf(fout, "%s-", m_name.c_str()); - lit->print_histo(fout); - } - assert(m_thd_span_archive.empty()); - if (final) { - fprintf(fout, "%s-", m_name.c_str()); - m_thd_span.print_histo(fout); - } + +void thread_CFlocality::spill(FILE *fout, bool final) +{ + std::list<thread_insn_span>::iterator lit = m_thd_span_archive.begin(); + for (; lit != m_thd_span_archive.end(); lit = m_thd_span_archive.erase(lit) ) { + fprintf(fout, "%s-", m_name.c_str()); + lit->print_histo(fout); + } + assert( m_thd_span_archive.empty() ); + if (final) { + fprintf(fout, "%s-", m_name.c_str()); + m_thd_span.print_histo(fout); + } } - -void thread_CFlocality::print_visualizer(FILE *fout) { - fprintf(fout, "%s: ", m_name.c_str()); - if (m_thd_span_archive.empty()) { - // visualizer do no require snap_shots - m_thd_span.print_sparse_histo(fout); - - // clean the thread span - m_thd_span.reset(0); - for (int i = 0; i < (int)m_thread_pc.size(); i++) - m_thd_span.set_span(m_thread_pc[i]); - } else { - assert(0); // TODO: implement fall back so that visualizer can work with - // snap shots - } + + +void thread_CFlocality::print_visualizer(FILE *fout) +{ + fprintf(fout, "%s: ", m_name.c_str()); + if (m_thd_span_archive.empty()) { + + // visualizer do no require snap_shots + m_thd_span.print_sparse_histo(fout); + + // clean the thread span + m_thd_span.reset(0); + for (int i = 0; i < (int)m_thread_pc.size(); i++) + m_thd_span.set_span(m_thread_pc[i]); + } else { + assert(0); // TODO: implement fall back so that visualizer can work with snap shots + } } - -void thread_CFlocality::print_visualizer(gzFile fout) { - gzprintf(fout, "%s: ", m_name.c_str()); - if (m_thd_span_archive.empty()) { - // visualizer do no require snap_shots - m_thd_span.print_sparse_histo(fout); - - // clean the thread span - m_thd_span.reset(0); - for (int i = 0; i < (int)m_thread_pc.size(); i++) { - m_thd_span.set_span(m_thread_pc[i]); - } - } else { - assert(0); // TODO: implement fall back so that visualizer can work with - // snap shots - } + +void thread_CFlocality::print_visualizer(gzFile fout) +{ + gzprintf(fout, "%s: ", m_name.c_str()); + if (m_thd_span_archive.empty()) { + + // visualizer do no require snap_shots + m_thd_span.print_sparse_histo(fout); + + // clean the thread span + m_thd_span.reset(0); + for (int i = 0; i < (int)m_thread_pc.size(); i++) { + m_thd_span.set_span(m_thread_pc[i]); + } + } else { + assert(0); // TODO: implement fall back so that visualizer can work with snap shots + } } - -void thread_CFlocality::print_span(FILE *fout) const { - std::list<thread_insn_span>::const_iterator lit = m_thd_span_archive.begin(); - for (; lit != m_thd_span_archive.end(); ++lit) { - fprintf(fout, "%s-", m_name.c_str()); - lit->print_span(fout); - } - fprintf(fout, "%s-", m_name.c_str()); - m_thd_span.print_span(fout); + +void thread_CFlocality::print_span(FILE *fout) const +{ + std::list<thread_insn_span>::const_iterator lit = m_thd_span_archive.begin(); + for (; lit != m_thd_span_archive.end(); ++lit) { + fprintf(fout, "%s-", m_name.c_str()); + lit->print_span(fout); + } + fprintf(fout, "%s-", m_name.c_str()); + m_thd_span.print_span(fout); } -void thread_CFlocality::print_histo(FILE *fout) const { - std::list<thread_insn_span>::const_iterator lit = m_thd_span_archive.begin(); - for (; lit != m_thd_span_archive.end(); ++lit) { - fprintf(fout, "%s-", m_name.c_str()); - lit->print_histo(fout); - } - fprintf(fout, "%s-", m_name.c_str()); - m_thd_span.print_histo(fout); +void thread_CFlocality::print_histo(FILE *fout) const +{ + std::list<thread_insn_span>::const_iterator lit = m_thd_span_archive.begin(); + for (; lit != m_thd_span_archive.end(); ++lit) { + fprintf(fout, "%s-", m_name.c_str()); + lit->print_histo(fout); + } + fprintf(fout, "%s-", m_name.c_str()); + m_thd_span.print_histo(fout); } //////////////////////////////////////////////////////////////////////////////// -linear_histogram_logger::linear_histogram_logger( - int n_bins, unsigned long long snap_shot_interval, const char *name, - bool reset_at_snap_shot, unsigned long long start_cycle) - : snap_shot_trigger(snap_shot_interval), - m_n_bins(n_bins), - m_curr_lin_hist(m_n_bins, start_cycle), - m_lin_hist_archive(), - m_cycle(start_cycle), - m_reset_at_snap_shot(reset_at_snap_shot), - m_name(name), - m_id(s_ids++) {} - -linear_histogram_logger::linear_histogram_logger( - const linear_histogram_logger &other) - : snap_shot_trigger(other.get_interval()), - m_n_bins(other.m_n_bins), - m_curr_lin_hist(m_n_bins, other.m_cycle), - m_lin_hist_archive(), - m_cycle(other.m_cycle), - m_reset_at_snap_shot(other.m_reset_at_snap_shot), - m_name(other.m_name), - m_id(s_ids++) {} - -linear_histogram_logger::~linear_histogram_logger() { - remove_snap_shot_trigger(this); - remove_spill_log(this); +linear_histogram_logger::linear_histogram_logger(int n_bins, + unsigned long long snap_shot_interval, + const char *name, + bool reset_at_snap_shot, + unsigned long long start_cycle ) + : snap_shot_trigger(snap_shot_interval), + m_n_bins(n_bins), + m_curr_lin_hist(m_n_bins, start_cycle), + m_lin_hist_archive(), + m_cycle(start_cycle), + m_reset_at_snap_shot(reset_at_snap_shot), + m_name(name), + m_id(s_ids++) +{ } -void linear_histogram_logger::snap_shot(unsigned long long current_cycle) { - m_lin_hist_archive.push_back(m_curr_lin_hist); - if (m_reset_at_snap_shot) { - m_curr_lin_hist.reset(current_cycle); - } else { - m_curr_lin_hist.set_cycle(current_cycle); - } +linear_histogram_logger::linear_histogram_logger(const linear_histogram_logger& other) + : snap_shot_trigger(other.get_interval()), + m_n_bins(other.m_n_bins), + m_curr_lin_hist(m_n_bins, other.m_cycle), + m_lin_hist_archive(), + m_cycle(other.m_cycle), + m_reset_at_snap_shot(other.m_reset_at_snap_shot), + m_name(other.m_name), + m_id(s_ids++) +{ } -void linear_histogram_logger::spill(FILE *fout, bool final) { - std::list<linear_histogram_snapshot>::iterator iter = - m_lin_hist_archive.begin(); - for (; iter != m_lin_hist_archive.end(); - iter = m_lin_hist_archive.erase(iter)) { - fprintf(fout, "%s%02d-", m_name.c_str(), (m_id >= 0) ? m_id : 0); - iter->print(fout); - fprintf(fout, "\n"); - } - assert(m_lin_hist_archive.empty()); - if (final) { - fprintf(fout, "%s%02d-", m_name.c_str(), (m_id >= 0) ? m_id : 0); - m_curr_lin_hist.print(fout); - fprintf(fout, "\n"); - } +linear_histogram_logger::~linear_histogram_logger() +{ + remove_snap_shot_trigger(this); + remove_spill_log(this); } - -void linear_histogram_logger::print(FILE *fout) const { - std::list<linear_histogram_snapshot>::const_iterator iter = - m_lin_hist_archive.begin(); - for (; iter != m_lin_hist_archive.end(); ++iter) { - fprintf(fout, "%s%02d-", m_name.c_str(), m_id); - iter->print(fout); - fprintf(fout, "\n"); - } - fprintf(fout, "%s%02d-", m_name.c_str(), m_id); - m_curr_lin_hist.print(fout); - fprintf(fout, "\n"); + +void linear_histogram_logger::snap_shot(unsigned long long current_cycle) { + m_lin_hist_archive.push_back(m_curr_lin_hist); + if (m_reset_at_snap_shot) { + m_curr_lin_hist.reset(current_cycle); + } else { + m_curr_lin_hist.set_cycle(current_cycle); + } +} + +void linear_histogram_logger::spill(FILE *fout, bool final) +{ + std::list<linear_histogram_snapshot>::iterator iter = m_lin_hist_archive.begin(); + for (; iter != m_lin_hist_archive.end(); iter = m_lin_hist_archive.erase(iter) ) { + fprintf(fout, "%s%02d-", m_name.c_str(), (m_id >= 0)? m_id : 0); + iter->print(fout); + fprintf(fout, "\n"); + } + assert( m_lin_hist_archive.empty() ); + if (final) { + fprintf(fout, "%s%02d-", m_name.c_str(), (m_id >= 0)? m_id : 0); + m_curr_lin_hist.print(fout); + fprintf(fout, "\n"); + } +} + +void linear_histogram_logger::print(FILE *fout) const +{ + std::list<linear_histogram_snapshot>::const_iterator iter = m_lin_hist_archive.begin(); + for (; iter != m_lin_hist_archive.end(); ++iter) { + fprintf(fout, "%s%02d-", m_name.c_str(), m_id); + iter->print(fout); + fprintf(fout, "\n"); + } + fprintf(fout, "%s%02d-", m_name.c_str(), m_id); + m_curr_lin_hist.print(fout); + fprintf(fout, "\n"); } -void linear_histogram_logger::print_visualizer(FILE *fout) { - assert(m_lin_hist_archive.empty()); // don't support snapshot for now - fprintf(fout, "%s", m_name.c_str()); - if (m_id >= 0) { - fprintf(fout, "%02d: ", m_id); - } else { - fprintf(fout, ": "); - } - m_curr_lin_hist.print_visualizer(fout); - fprintf(fout, "\n"); - if (m_reset_at_snap_shot) { - m_curr_lin_hist.reset(0); - } +void linear_histogram_logger::print_visualizer(FILE *fout) +{ + assert(m_lin_hist_archive.empty()); // don't support snapshot for now + fprintf(fout, "%s", m_name.c_str()); + if (m_id >= 0) { + fprintf(fout, "%02d: ", m_id); + } else { + fprintf(fout, ": "); + } + m_curr_lin_hist.print_visualizer(fout); + fprintf(fout, "\n"); + if (m_reset_at_snap_shot) { + m_curr_lin_hist.reset(0); + } } -void linear_histogram_logger::print_visualizer(gzFile fout) { - assert(m_lin_hist_archive.empty()); // don't support snapshot for now - gzprintf(fout, "%s", m_name.c_str()); - if (m_id >= 0) { - gzprintf(fout, "%02d: ", m_id); - } else { - gzprintf(fout, ": "); - } - m_curr_lin_hist.print_visualizer(fout); - gzprintf(fout, "\n"); - if (m_reset_at_snap_shot) { - m_curr_lin_hist.reset(0); - } +void linear_histogram_logger::print_visualizer(gzFile fout) +{ + assert(m_lin_hist_archive.empty()); // don't support snapshot for now + gzprintf(fout, "%s", m_name.c_str()); + if (m_id >= 0) { + gzprintf(fout, "%02d: ", m_id); + } else { + gzprintf(fout, ": "); + } + m_curr_lin_hist.print_visualizer(fout); + gzprintf(fout, "\n"); + if (m_reset_at_snap_shot) { + m_curr_lin_hist.reset(0); + } } + diff --git a/src/gpgpu-sim/stat-tool.h b/src/gpgpu-sim/stat-tool.h index 72d7b7d..67b3923 100644 --- a/src/gpgpu-sim/stat-tool.h +++ b/src/gpgpu-sim/stat-tool.h @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -31,54 +29,50 @@ #define STAT_TOOL_H #include "../abstract_hardware_model.h" -#include "../tr1_hash_map.h" #include "histogram.h" +#include "../tr1_hash_map.h" #include <stdio.h> #include <zlib.h> class gpgpu_context; ///////////////////////////////////////////////////////////////////////////////////// -// logger snapshot trigger: -// - automate the snap_shot part of loggers to avoid modifying simulation loop -// everytime +// logger snapshot trigger: +// - automate the snap_shot part of loggers to avoid modifying simulation loop everytime // a new time-dependent stat is added ///////////////////////////////////////////////////////////////////////////////////// class snap_shot_trigger { - public: - snap_shot_trigger(unsigned long long interval) - : m_snap_shot_interval(interval) {} - virtual ~snap_shot_trigger() {} - - void try_snap_shot(unsigned long long current_cycle) { - if ((current_cycle % m_snap_shot_interval == 0) && current_cycle != 0) { - snap_shot(current_cycle); - } - } - - virtual void snap_shot(unsigned long long current_cycle) = 0; +public: + snap_shot_trigger(unsigned long long interval) : m_snap_shot_interval(interval) {} + virtual ~snap_shot_trigger() {} + + void try_snap_shot(unsigned long long current_cycle) { + if ((current_cycle % m_snap_shot_interval == 0) && current_cycle != 0) { + snap_shot(current_cycle); + } + } + + virtual void snap_shot(unsigned long long current_cycle) = 0; - const unsigned long long &get_interval() const { - return m_snap_shot_interval; - } + const unsigned long long & get_interval() const { return m_snap_shot_interval;} - protected: - unsigned long long m_snap_shot_interval; +protected: + unsigned long long m_snap_shot_interval; }; + ///////////////////////////////////////////////////////////////////////////////////// -// spill log interface: -// - unified interface to spill log to file to avoid infinite memory usage for -// logging +// spill log interface: +// - unified interface to spill log to file to avoid infinite memory usage for logging ///////////////////////////////////////////////////////////////////////////////////// class spill_log_interface { - public: - spill_log_interface() {} - virtual ~spill_log_interface() {} - - virtual void spill(FILE *fout, bool final) = 0; +public: + spill_log_interface() {} + virtual ~spill_log_interface() {} + + virtual void spill(FILE *fout, bool final) = 0; }; ///////////////////////////////////////////////////////////////////////////////////// @@ -86,53 +80,51 @@ class spill_log_interface { ///////////////////////////////////////////////////////////////////////////////////// class thread_insn_span { - public: - thread_insn_span(unsigned long long cycle, gpgpu_context *ctx); - thread_insn_span(const thread_insn_span &other, gpgpu_context *ctx); - ~thread_insn_span(); - - thread_insn_span &operator=(const thread_insn_span &other); - thread_insn_span &operator+=(const thread_insn_span &other); - void set_span(address_type pc); - void reset(unsigned long long cycle); - - void print_span(FILE *fout) const; - void print_histo(FILE *fout) const; - void print_sparse_histo(FILE *fout) const; - void print_sparse_histo(gzFile fout) const; +public: + thread_insn_span(unsigned long long cycle, gpgpu_context* ctx); + thread_insn_span(const thread_insn_span& other, gpgpu_context* ctx); + ~thread_insn_span(); + + thread_insn_span& operator=(const thread_insn_span& other); + thread_insn_span& operator+=(const thread_insn_span& other); + void set_span( address_type pc ); + void reset(unsigned long long cycle); + + void print_span(FILE *fout) const; + void print_histo(FILE *fout) const; + void print_sparse_histo(FILE *fout) const; + void print_sparse_histo(gzFile fout) const; - private: - gpgpu_context *gpgpu_ctx; - typedef tr1_hash_map<address_type, int> span_count_map; - unsigned long long m_cycle; - span_count_map m_insn_span_count; +private: + gpgpu_context* gpgpu_ctx; + typedef tr1_hash_map<address_type, int> span_count_map; + unsigned long long m_cycle; + span_count_map m_insn_span_count; }; class thread_CFlocality : public snap_shot_trigger, public spill_log_interface { - public: - thread_CFlocality(gpgpu_context *ctx, std::string name, - unsigned long long snap_shot_interval, int nthreads, - address_type start_pc, unsigned long long start_cycle = 0); - ~thread_CFlocality(); +public: + thread_CFlocality(gpgpu_context* ctx, std::string name, unsigned long long snap_shot_interval, + int nthreads, address_type start_pc, unsigned long long start_cycle = 0); + ~thread_CFlocality(); + + void update_thread_pc( int thread_id, address_type pc ); + void snap_shot(unsigned long long current_cycle); + void spill(FILE *fout, bool final); + + void print_visualizer(FILE *fout); + void print_visualizer(gzFile fout); + void print_span(FILE *fout) const; + void print_histo(FILE *fout) const; +private: + std::string m_name; - void update_thread_pc(int thread_id, address_type pc); - void snap_shot(unsigned long long current_cycle); - void spill(FILE *fout, bool final); - - void print_visualizer(FILE *fout); - void print_visualizer(gzFile fout); - void print_span(FILE *fout) const; - void print_histo(FILE *fout) const; - - private: - std::string m_name; - - int m_nthreads; - std::vector<address_type> m_thread_pc; - - unsigned long long m_cycle; - thread_insn_span m_thd_span; - std::list<thread_insn_span> m_thd_span_archive; + int m_nthreads; + std::vector<address_type> m_thread_pc; + + unsigned long long m_cycle; + thread_insn_span m_thd_span; + std::list<thread_insn_span> m_thd_span_archive; }; ///////////////////////////////////////////////////////////////////////////////////// @@ -140,188 +132,194 @@ class thread_CFlocality : public snap_shot_trigger, public spill_log_interface { ///////////////////////////////////////////////////////////////////////////////////// class insn_warp_occ_logger { - public: - insn_warp_occ_logger(int simd_width) - : m_simd_width(simd_width), - m_insn_warp_occ(1, linear_histogram(1, "", m_simd_width)), +public: + insn_warp_occ_logger(int simd_width) + : m_simd_width(simd_width), + m_insn_warp_occ(1,linear_histogram(1, "", m_simd_width)), m_id(s_ids++) {} - - insn_warp_occ_logger(const insn_warp_occ_logger &other) - : m_simd_width(other.m_simd_width), - m_insn_warp_occ(other.m_insn_warp_occ.size(), - linear_histogram(1, "", m_simd_width)), + + insn_warp_occ_logger(const insn_warp_occ_logger& other) + : m_simd_width(other.m_simd_width), + m_insn_warp_occ(other.m_insn_warp_occ.size(), linear_histogram(1, "", m_simd_width)), m_id(s_ids++) {} + + ~insn_warp_occ_logger() {} - ~insn_warp_occ_logger() {} - - insn_warp_occ_logger &operator=(const insn_warp_occ_logger &p) { - printf("insn_warp_occ_logger Operator= called: %02d \n", m_id); - assert(0); - return *this; - } - - void set_id(int id) { m_id = id; } - - void log(address_type pc, int warp_occ) { - if (pc >= m_insn_warp_occ.size()) - m_insn_warp_occ.resize(2 * pc, linear_histogram(1, "", m_simd_width)); - m_insn_warp_occ[pc].add2bin(warp_occ - 1); - } + insn_warp_occ_logger& operator=(const insn_warp_occ_logger& p) { + printf("insn_warp_occ_logger Operator= called: %02d \n", m_id); + assert(0); + return *this; + } + + void set_id(int id) { m_id = id; } + + void log(address_type pc, int warp_occ) { + if( pc >= m_insn_warp_occ.size() ) + m_insn_warp_occ.resize(2*pc, linear_histogram(1, "", m_simd_width)); + m_insn_warp_occ[pc].add2bin(warp_occ - 1); + } + + void print(FILE *fout) const + { + for (unsigned i = 0; i < m_insn_warp_occ.size(); i++) { + fprintf(fout, "InsnWarpOcc%02d-%d", m_id, i); + m_insn_warp_occ[i].fprint(fout); + fprintf(fout, "\n"); + } + } - void print(FILE *fout) const { - for (unsigned i = 0; i < m_insn_warp_occ.size(); i++) { - fprintf(fout, "InsnWarpOcc%02d-%d", m_id, i); - m_insn_warp_occ[i].fprint(fout); - fprintf(fout, "\n"); - } - } +private: - private: - int m_simd_width; - std::vector<linear_histogram> m_insn_warp_occ; - int m_id; - static int s_ids; + int m_simd_width; + std::vector<linear_histogram> m_insn_warp_occ; + int m_id; + static int s_ids; }; + ///////////////////////////////////////////////////////////////////////////////////// // generic linear histogram logger ///////////////////////////////////////////////////////////////////////////////////// class linear_histogram_snapshot { - public: - linear_histogram_snapshot(int n_bins, unsigned long long cycle) - : m_cycle(cycle), m_linear_histogram(n_bins, 0) {} - - linear_histogram_snapshot(const linear_histogram_snapshot &other) - : m_cycle(other.m_cycle), m_linear_histogram(other.m_linear_histogram) {} - - ~linear_histogram_snapshot() {} - - void addsample(int pos) { - assert((size_t)pos < m_linear_histogram.size()); - m_linear_histogram[pos] += 1; - } - - void subsample(int pos) { - assert((size_t)pos < m_linear_histogram.size()); - m_linear_histogram[pos] -= 1; - } - - void reset(unsigned long long cycle) { - m_cycle = cycle; - m_linear_histogram.assign(m_linear_histogram.size(), 0); - } - - void set_cycle(unsigned long long cycle) { m_cycle = cycle; } - - void print(FILE *fout) const { - fprintf(fout, "%d = ", (int)m_cycle); - for (unsigned int i = 0; i < m_linear_histogram.size(); i++) { - fprintf(fout, "%d ", m_linear_histogram[i]); - } - } +public: + linear_histogram_snapshot(int n_bins, unsigned long long cycle) + : m_cycle(cycle), + m_linear_histogram(n_bins,0) + { } + + linear_histogram_snapshot(const linear_histogram_snapshot& other) + : m_cycle(other.m_cycle), + m_linear_histogram(other.m_linear_histogram) + { } + + ~linear_histogram_snapshot() { } + + void addsample(int pos) { + assert((size_t)pos < m_linear_histogram.size()); + m_linear_histogram[pos] += 1; + } + + void subsample(int pos) { + assert((size_t)pos < m_linear_histogram.size()); + m_linear_histogram[pos] -= 1; + } + + void reset(unsigned long long cycle) { + m_cycle = cycle; + m_linear_histogram.assign(m_linear_histogram.size(), 0); + } + + void set_cycle(unsigned long long cycle) { m_cycle = cycle; } + + void print(FILE *fout) const { + fprintf(fout, "%d = ", (int)m_cycle); + for (unsigned int i = 0; i < m_linear_histogram.size(); i++) { + fprintf(fout, "%d ", m_linear_histogram[i]); + } + } - void print_visualizer(FILE *fout) const { - for (unsigned int i = 0; i < m_linear_histogram.size(); i++) { - fprintf(fout, "%d ", m_linear_histogram[i]); - } - } + void print_visualizer(FILE *fout) const { + for (unsigned int i = 0; i < m_linear_histogram.size(); i++) { + fprintf(fout, "%d ", m_linear_histogram[i]); + } + } - void print_visualizer(gzFile fout) const { - for (unsigned int i = 0; i < m_linear_histogram.size(); i++) { - gzprintf(fout, "%d ", m_linear_histogram[i]); - } - } + void print_visualizer(gzFile fout) const { + for (unsigned int i = 0; i < m_linear_histogram.size(); i++) { + gzprintf(fout, "%d ", m_linear_histogram[i]); + } + } - private: - unsigned long long m_cycle; - std::vector<int> m_linear_histogram; +private: + unsigned long long m_cycle; + std::vector<int> m_linear_histogram; }; -class linear_histogram_logger : public snap_shot_trigger, - public spill_log_interface { - public: - linear_histogram_logger(int n_bins, unsigned long long snap_shot_interval, - const char *name, bool reset_at_snap_shot = true, - unsigned long long start_cycle = 0); - linear_histogram_logger(const linear_histogram_logger &other); +class linear_histogram_logger : public snap_shot_trigger, public spill_log_interface { +public: + linear_histogram_logger(int n_bins, + unsigned long long snap_shot_interval, + const char *name, + bool reset_at_snap_shot = true, + unsigned long long start_cycle = 0); + linear_histogram_logger(const linear_histogram_logger& other); + + ~linear_histogram_logger(); + + void set_id(int id) { m_id = id; } + void log(int pos) { m_curr_lin_hist.addsample(pos); } + void unlog(int pos) { m_curr_lin_hist.subsample(pos); } + void snap_shot(unsigned long long current_cycle); + void spill(FILE *fout, bool final); - ~linear_histogram_logger(); + void print(FILE *fout) const; + void print_visualizer(FILE *fout); + void print_visualizer(gzFile fout); - void set_id(int id) { m_id = id; } - void log(int pos) { m_curr_lin_hist.addsample(pos); } - void unlog(int pos) { m_curr_lin_hist.subsample(pos); } - void snap_shot(unsigned long long current_cycle); - void spill(FILE *fout, bool final); - - void print(FILE *fout) const; - void print_visualizer(FILE *fout); - void print_visualizer(gzFile fout); - - private: - int m_n_bins; - linear_histogram_snapshot m_curr_lin_hist; - std::list<linear_histogram_snapshot> m_lin_hist_archive; - unsigned long long m_cycle; - bool m_reset_at_snap_shot; - std::string m_name; - int m_id; - static int s_ids; +private: + int m_n_bins; + linear_histogram_snapshot m_curr_lin_hist; + std::list<linear_histogram_snapshot> m_lin_hist_archive; + unsigned long long m_cycle; + bool m_reset_at_snap_shot; + std::string m_name; + int m_id; + static int s_ids; }; -void try_snap_shot(unsigned long long current_cycle); -void set_spill_interval(unsigned long long interval); -void spill_log_to_file(FILE *fout, int final, unsigned long long current_cycle); +void try_snap_shot (unsigned long long current_cycle); +void set_spill_interval (unsigned long long interval); +void spill_log_to_file (FILE *fout, int final, unsigned long long current_cycle); -void create_thread_CFlogger(gpgpu_context *ctx, int n_loggers, int n_threads, - address_type start_pc, - unsigned long long logging_interval); -void destroy_thread_CFlogger(); -void cflog_update_thread_pc(int logger_id, int thread_id, address_type pc); -void cflog_snapshot(int logger_id, unsigned long long cycle); +void create_thread_CFlogger(gpgpu_context* ctx, int n_loggers, int n_threads, address_type start_pc, unsigned long long logging_interval); +void destroy_thread_CFlogger( ); +void cflog_update_thread_pc( int logger_id, int thread_id, address_type pc ); +void cflog_snapshot( int logger_id, unsigned long long cycle ); void cflog_print(FILE *fout); void cflog_print_path_expression(FILE *fout); void cflog_visualizer_print(FILE *fout); void cflog_visualizer_gzprint(gzFile fout); -void insn_warp_occ_create(int n_loggers, int simd_width); -void insn_warp_occ_log(int logger_id, address_type pc, int warp_occ); -void insn_warp_occ_print(FILE *fout); +void insn_warp_occ_create( int n_loggers, int simd_width ); +void insn_warp_occ_log( int logger_id, address_type pc, int warp_occ ); +void insn_warp_occ_print( FILE *fout ); + + +void shader_warp_occ_create( int n_loggers, int simd_width, unsigned long long logging_interval ); +void shader_warp_occ_log( int logger_id, int warp_occ ); +void shader_warp_occ_snapshot( int logger_id, unsigned long long current_cycle ); +void shader_warp_occ_print( FILE *fout ); -void shader_warp_occ_create(int n_loggers, int simd_width, - unsigned long long logging_interval); -void shader_warp_occ_log(int logger_id, int warp_occ); -void shader_warp_occ_snapshot(int logger_id, unsigned long long current_cycle); -void shader_warp_occ_print(FILE *fout); -void shader_mem_acc_create(int n_loggers, int n_dram, int n_bank, - unsigned long long logging_interval); -void shader_mem_acc_log(int logger_id, int dram_id, int bank, char rw); -void shader_mem_acc_snapshot(int logger_id, unsigned long long current_cycle); -void shader_mem_acc_print(FILE *fout); +void shader_mem_acc_create( int n_loggers, int n_dram, int n_bank, unsigned long long logging_interval ); +void shader_mem_acc_log( int logger_id, int dram_id, int bank, char rw ); +void shader_mem_acc_snapshot( int logger_id, unsigned long long current_cycle ); +void shader_mem_acc_print( FILE *fout ); + + +void shader_mem_lat_create( int n_loggers, unsigned long long logging_interval ); +void shader_mem_lat_log( int logger_id, int latency ); +void shader_mem_lat_snapshot( int logger_id, unsigned long long current_cycle ); +void shader_mem_lat_print( FILE *fout ); -void shader_mem_lat_create(int n_loggers, unsigned long long logging_interval); -void shader_mem_lat_log(int logger_id, int latency); -void shader_mem_lat_snapshot(int logger_id, unsigned long long current_cycle); -void shader_mem_lat_print(FILE *fout); int get_shader_normal_cache_id(); int get_shader_texture_cache_id(); int get_shader_constant_cache_id(); int get_shader_instruction_cache_id(); -void shader_cache_access_create(int n_loggers, int n_types, - unsigned long long logging_interval); -void shader_cache_access_log(int logger_id, int type, int miss); -void shader_cache_access_unlog(int logger_id, int type, int miss); -void shader_cache_access_print(FILE *fout); +void shader_cache_access_create( int n_loggers, int n_types, unsigned long long logging_interval ); +void shader_cache_access_log( int logger_id, int type, int miss); +void shader_cache_access_unlog( int logger_id, int type, int miss); +void shader_cache_access_print( FILE *fout ); + -void shader_CTA_count_create(int n_shaders, - unsigned long long logging_interval); -void shader_CTA_count_log(int shader_id, int nCTAadded); -void shader_CTA_count_unlog(int shader_id, int nCTAdone); -void shader_CTA_count_resetnow(); -void shader_CTA_count_print(FILE *fout); -void shader_CTA_count_visualizer_print(FILE *fout); +void shader_CTA_count_create( int n_shaders, unsigned long long logging_interval); +void shader_CTA_count_log( int shader_id, int nCTAadded ); +void shader_CTA_count_unlog( int shader_id, int nCTAdone ); +void shader_CTA_count_resetnow( ); +void shader_CTA_count_print( FILE *fout ); +void shader_CTA_count_visualizer_print( FILE *fout ); void shader_CTA_count_visualizer_gzprint(gzFile fout); #endif /* CFLOGGER_H */ diff --git a/src/gpgpu-sim/stats.h b/src/gpgpu-sim/stats.h index 06fd1e5..6a50f05 100644 --- a/src/gpgpu-sim/stats.h +++ b/src/gpgpu-sim/stats.h @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -31,27 +29,32 @@ #define STATS_INCLUDED enum mem_stage_access_type { - C_MEM, - T_MEM, - S_MEM, - G_MEM_LD, - L_MEM_LD, - G_MEM_ST, - L_MEM_ST, - N_MEM_STAGE_ACCESS_TYPE + C_MEM, + T_MEM, + S_MEM, + G_MEM_LD, + L_MEM_LD, + G_MEM_ST, + L_MEM_ST, + N_MEM_STAGE_ACCESS_TYPE +}; +enum tlb_request_status { + TLB_HIT = 0, + TLB_READY, + TLB_PENDING }; -enum tlb_request_status { TLB_HIT = 0, TLB_READY, TLB_PENDING }; enum mem_stage_stall_type { - NO_RC_FAIL = 0, - BK_CONF, - MSHR_RC_FAIL, - ICNT_RC_FAIL, - COAL_STALL, - TLB_STALL, - DATA_PORT_STALL, - WB_ICNT_RC_FAIL, - WB_CACHE_RSRV_FAIL, - N_MEM_STAGE_STALL_TYPE + NO_RC_FAIL = 0, + BK_CONF, + MSHR_RC_FAIL, + ICNT_RC_FAIL, + COAL_STALL, + TLB_STALL, + DATA_PORT_STALL, + WB_ICNT_RC_FAIL, + WB_CACHE_RSRV_FAIL, + N_MEM_STAGE_STALL_TYPE }; + #endif diff --git a/src/gpgpu-sim/traffic_breakdown.cc b/src/gpgpu-sim/traffic_breakdown.cc index 5cc7725..32f0d30 100644 --- a/src/gpgpu-sim/traffic_breakdown.cc +++ b/src/gpgpu-sim/traffic_breakdown.cc @@ -1,54 +1,51 @@ -#include "traffic_breakdown.h" -#include "mem_fetch.h" +#include "traffic_breakdown.h" +#include "mem_fetch.h" -void traffic_breakdown::print(FILE* fout) { - for (traffic_stat_t::const_iterator i_stat = m_stats.begin(); - i_stat != m_stats.end(); i_stat++) { - unsigned int byte_transferred = 0; - for (traffic_class_t::const_iterator i_class = i_stat->second.begin(); - i_class != i_stat->second.end(); i_class++) { - byte_transferred += - i_class->first * i_class->second; // byte/packet x #packets - } - fprintf(fout, "traffic_breakdown_%s[%s] = %u {", m_network_name.c_str(), - i_stat->first.c_str(), byte_transferred); - for (traffic_class_t::const_iterator i_class = i_stat->second.begin(); - i_class != i_stat->second.end(); i_class++) { - fprintf(fout, "%u:%u,", i_class->first, i_class->second); - } - fprintf(fout, "}\n"); - } +void traffic_breakdown::print(FILE* fout) +{ + for (traffic_stat_t::const_iterator i_stat = m_stats.begin(); i_stat != m_stats.end(); i_stat++) { + unsigned int byte_transferred = 0; + for (traffic_class_t::const_iterator i_class = i_stat->second.begin(); i_class != i_stat->second.end(); i_class++) { + byte_transferred += i_class->first * i_class->second; // byte/packet x #packets + } + fprintf(fout, "traffic_breakdown_%s[%s] = %u {", m_network_name.c_str(), i_stat->first.c_str(), byte_transferred); + for (traffic_class_t::const_iterator i_class = i_stat->second.begin(); i_class != i_stat->second.end(); i_class++) { + fprintf(fout, "%u:%u,", i_class->first, i_class->second); + } + fprintf(fout, "}\n"); + } } -void traffic_breakdown::record_traffic(class mem_fetch* mf, unsigned int size) { - m_stats[classify_memfetch(mf)][size] += 1; +void traffic_breakdown::record_traffic(class mem_fetch * mf, unsigned int size) +{ + m_stats[classify_memfetch(mf)][size] += 1; } -std::string traffic_breakdown::classify_memfetch(class mem_fetch* mf) { - std::string traffic_name; +std::string traffic_breakdown::classify_memfetch(class mem_fetch * mf) +{ + std::string traffic_name; - enum mem_access_type access_type = mf->get_access_type(); + enum mem_access_type access_type = mf->get_access_type(); - switch (access_type) { - case CONST_ACC_R: - case TEXTURE_ACC_R: - case GLOBAL_ACC_W: - case LOCAL_ACC_R: - case LOCAL_ACC_W: - case INST_ACC_R: - case L1_WRBK_ACC: - case L2_WRBK_ACC: - case L1_WR_ALLOC_R: - case L2_WR_ALLOC_R: - traffic_name = mem_access_type_str(access_type); - break; - case GLOBAL_ACC_R: - // check for global atomic operation - traffic_name = (mf->isatomic()) ? "GLOBAL_ATOMIC" - : mem_access_type_str(GLOBAL_ACC_R); - break; - default: - assert(0 && "Unknown traffic type"); - } - return traffic_name; + switch (access_type) { + case CONST_ACC_R: + case TEXTURE_ACC_R: + case GLOBAL_ACC_W: + case LOCAL_ACC_R: + case LOCAL_ACC_W: + case INST_ACC_R: + case L1_WRBK_ACC: + case L2_WRBK_ACC: + case L1_WR_ALLOC_R: + case L2_WR_ALLOC_R: + traffic_name = mem_access_type_str(access_type); + break; + case GLOBAL_ACC_R: + // check for global atomic operation + traffic_name = (mf->isatomic())? "GLOBAL_ATOMIC" : mem_access_type_str(GLOBAL_ACC_R); + break; + default: assert(0 && "Unknown traffic type"); + } + return traffic_name; } + diff --git a/src/gpgpu-sim/traffic_breakdown.h b/src/gpgpu-sim/traffic_breakdown.h index a898519..c9b8df5 100644 --- a/src/gpgpu-sim/traffic_breakdown.h +++ b/src/gpgpu-sim/traffic_breakdown.h @@ -1,35 +1,37 @@ -#pragma once +#pragma once #include <stdio.h> #include <map> -#include <string> +#include <string> // Breakdown traffic through the network according to category -class traffic_breakdown { - public: - traffic_breakdown(const std::string& network_name) - : m_network_name(network_name) {} +class traffic_breakdown +{ +public: + traffic_breakdown(const std::string &network_name) + : m_network_name(network_name) + { } - // print the stats - void print(FILE* fout); + // print the stats + void print(FILE* fout); - // record the amount and type of traffic introduced by this mem_fetch object - void record_traffic(class mem_fetch* mf, unsigned int size); + // record the amount and type of traffic introduced by this mem_fetch object + void record_traffic(class mem_fetch * mf, unsigned int size); - protected: - std::string m_network_name; +protected: - /// helper functions to identify the type of traffic sent - std::string classify_memfetch(class mem_fetch* mf); + std::string m_network_name; - /// helper functions to identify the size of traffic sent - unsigned int packet_size(class mem_fetch* mf); + /// helper functions to identify the type of traffic sent + std::string classify_memfetch(class mem_fetch * mf); - typedef std::string - mf_packet_type; // use string so that it remains extensible - typedef unsigned int mf_packet_size; - typedef std::map<mf_packet_size, unsigned int> traffic_class_t; - typedef std::map<mf_packet_type, traffic_class_t> traffic_stat_t; + /// helper functions to identify the size of traffic sent + unsigned int packet_size(class mem_fetch * mf); - traffic_stat_t m_stats; -}; + typedef std::string mf_packet_type; // use string so that it remains extensible + typedef unsigned int mf_packet_size; + typedef std::map < mf_packet_size, unsigned int > traffic_class_t; + typedef std::map < mf_packet_type, traffic_class_t > traffic_stat_t; + + traffic_stat_t m_stats; +}; diff --git a/src/gpgpu-sim/visualizer.cc b/src/gpgpu-sim/visualizer.cc index 6ba1a8a..dcb1175 100644 --- a/src/gpgpu-sim/visualizer.cc +++ b/src/gpgpu-sim/visualizer.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2011, Tor M. Aamodt, Wilson W.L. Fung, +// Copyright (c) 2009-2011, Tor M. Aamodt, Wilson W.L. Fung, // The University of British Columbia // All rights reserved. // @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -29,370 +27,358 @@ #include "visualizer.h" -#include "../option_parser.h" #include "gpu-sim.h" #include "l2cache.h" +#include "shader.h" +#include "../option_parser.h" #include "mem_latency_stat.h" #include "power_stat.h" -#include "shader.h" //#include "../../../mcpat/processor.h" -#include "gpu-cache.h" #include "stat-tool.h" +#include "gpu-cache.h" -#include <string.h> #include <time.h> +#include <string.h> #include <zlib.h> static void time_vector_print_interval2gzfile(gzFile outfile); -void gpgpu_sim::visualizer_printstat() { - gzFile visualizer_file = NULL; // gzFile is basically a pointer to a struct, - // so it is fine to initialize it as NULL - if (!m_config.g_visualizer_enabled) return; +void gpgpu_sim::visualizer_printstat() +{ + gzFile visualizer_file = NULL; // gzFile is basically a pointer to a struct, so it is fine to initialize it as NULL + if ( !m_config.g_visualizer_enabled ) + return; - // clean the content of the visualizer log if it is the first time, otherwise - // attach at the end - static bool visualizer_first_printstat = true; + // clean the content of the visualizer log if it is the first time, otherwise attach at the end + static bool visualizer_first_printstat = true; - visualizer_file = gzopen(m_config.g_visualizer_filename, - (visualizer_first_printstat) ? "w" : "a"); - if (visualizer_file == NULL) { - printf("error - could not open visualizer trace file.\n"); - exit(1); - } - gzsetparams(visualizer_file, m_config.g_visualizer_zlevel, - Z_DEFAULT_STRATEGY); - visualizer_first_printstat = false; + visualizer_file = gzopen(m_config.g_visualizer_filename, (visualizer_first_printstat)? "w" : "a"); + if (visualizer_file == NULL) { + printf("error - could not open visualizer trace file.\n"); + exit(1); + } + gzsetparams(visualizer_file, m_config.g_visualizer_zlevel, Z_DEFAULT_STRATEGY); + visualizer_first_printstat = false; + + cflog_visualizer_gzprint(visualizer_file); + shader_CTA_count_visualizer_gzprint(visualizer_file); - cflog_visualizer_gzprint(visualizer_file); - shader_CTA_count_visualizer_gzprint(visualizer_file); + for (unsigned i=0;i<m_memory_config->m_n_mem;i++) + m_memory_partition_unit[i]->visualizer_print(visualizer_file); + m_shader_stats->visualizer_print(visualizer_file); + m_memory_stats->visualizer_print(visualizer_file); + m_power_stats->visualizer_print(visualizer_file); + //proc->visualizer_print(visualizer_file); + // other parameters for graphing + gzprintf(visualizer_file, "globalcyclecount: %lld\n", gpu_sim_cycle); + gzprintf(visualizer_file, "globalinsncount: %lld\n", gpu_sim_insn); + gzprintf(visualizer_file, "globaltotinsncount: %lld\n", gpu_tot_sim_insn); - for (unsigned i = 0; i < m_memory_config->m_n_mem; i++) - m_memory_partition_unit[i]->visualizer_print(visualizer_file); - m_shader_stats->visualizer_print(visualizer_file); - m_memory_stats->visualizer_print(visualizer_file); - m_power_stats->visualizer_print(visualizer_file); - // proc->visualizer_print(visualizer_file); - // other parameters for graphing - gzprintf(visualizer_file, "globalcyclecount: %lld\n", gpu_sim_cycle); - gzprintf(visualizer_file, "globalinsncount: %lld\n", gpu_sim_insn); - gzprintf(visualizer_file, "globaltotinsncount: %lld\n", gpu_tot_sim_insn); + time_vector_print_interval2gzfile(visualizer_file); - time_vector_print_interval2gzfile(visualizer_file); - - gzclose(visualizer_file); - /* - gzprintf(visualizer_file, "CacheMissRate_GlobalLocalL1_All: "); - for (unsigned i=0;i<m_n_shader;i++) - gzprintf(visualizer_file, "%0.4f ", - m_sc[i]->L1_windowed_cache_miss_rate(0)); - gzprintf(visualizer_file, "\n"); - gzprintf(visualizer_file, "CacheMissRate_TextureL1_All: "); - for (unsigned i=0;i<m_n_shader;i++) - gzprintf(visualizer_file, "%0.4f ", - m_sc[i]->L1tex_windowed_cache_miss_rate(0)); - gzprintf(visualizer_file, "\n"); - gzprintf(visualizer_file, "CacheMissRate_ConstL1_All: "); - for (unsigned i=0;i<m_n_shader;i++) - gzprintf(visualizer_file, "%0.4f ", - m_sc[i]->L1const_windowed_cache_miss_rate(0)); - gzprintf(visualizer_file, "\n"); - gzprintf(visualizer_file, "CacheMissRate_GlobalLocalL1_noMgHt: "); - for (unsigned i=0;i<m_n_shader;i++) - gzprintf(visualizer_file, "%0.4f ", - m_sc[i]->L1_windowed_cache_miss_rate(1)); - gzprintf(visualizer_file, "\n"); - gzprintf(visualizer_file, "CacheMissRate_TextureL1_noMgHt: "); - for (unsigned i=0;i<m_n_shader;i++) - gzprintf(visualizer_file, "%0.4f ", - m_sc[i]->L1tex_windowed_cache_miss_rate(1)); - gzprintf(visualizer_file, "\n"); - gzprintf(visualizer_file, "CacheMissRate_ConstL1_noMgHt: "); - for (unsigned i=0;i<m_n_shader;i++) - gzprintf(visualizer_file, "%0.4f ", - m_sc[i]->L1const_windowed_cache_miss_rate(1)); - gzprintf(visualizer_file, "\n"); - // reset for next interval - for (unsigned i=0;i<m_n_shader;i++) - m_sc[i]->new_cache_window(); - */ + gzclose(visualizer_file); +/* + gzprintf(visualizer_file, "CacheMissRate_GlobalLocalL1_All: "); + for (unsigned i=0;i<m_n_shader;i++) + gzprintf(visualizer_file, "%0.4f ", m_sc[i]->L1_windowed_cache_miss_rate(0)); + gzprintf(visualizer_file, "\n"); + gzprintf(visualizer_file, "CacheMissRate_TextureL1_All: "); + for (unsigned i=0;i<m_n_shader;i++) + gzprintf(visualizer_file, "%0.4f ", m_sc[i]->L1tex_windowed_cache_miss_rate(0)); + gzprintf(visualizer_file, "\n"); + gzprintf(visualizer_file, "CacheMissRate_ConstL1_All: "); + for (unsigned i=0;i<m_n_shader;i++) + gzprintf(visualizer_file, "%0.4f ", m_sc[i]->L1const_windowed_cache_miss_rate(0)); + gzprintf(visualizer_file, "\n"); + gzprintf(visualizer_file, "CacheMissRate_GlobalLocalL1_noMgHt: "); + for (unsigned i=0;i<m_n_shader;i++) + gzprintf(visualizer_file, "%0.4f ", m_sc[i]->L1_windowed_cache_miss_rate(1)); + gzprintf(visualizer_file, "\n"); + gzprintf(visualizer_file, "CacheMissRate_TextureL1_noMgHt: "); + for (unsigned i=0;i<m_n_shader;i++) + gzprintf(visualizer_file, "%0.4f ", m_sc[i]->L1tex_windowed_cache_miss_rate(1)); + gzprintf(visualizer_file, "\n"); + gzprintf(visualizer_file, "CacheMissRate_ConstL1_noMgHt: "); + for (unsigned i=0;i<m_n_shader;i++) + gzprintf(visualizer_file, "%0.4f ", m_sc[i]->L1const_windowed_cache_miss_rate(1)); + gzprintf(visualizer_file, "\n"); + // reset for next interval + for (unsigned i=0;i<m_n_shader;i++) + m_sc[i]->new_cache_window(); +*/ } -#include <iostream> #include <list> -#include <map> #include <vector> -#include "../gpgpu-sim/shader.h" +#include <iostream> +#include <map> +#include"../gpgpu-sim/shader.h" class my_time_vector { - private: - std::map<unsigned int, std::vector<long int> > ld_time_map; - std::map<unsigned int, std::vector<long int> > st_time_map; - unsigned ld_vector_size; - unsigned st_vector_size; - std::vector<double> ld_time_dist; - std::vector<double> st_time_dist; - - std::vector<double> overal_ld_time_dist; - std::vector<double> overal_st_time_dist; - int overal_ld_count; - int overal_st_count; +private: + std::map< unsigned int, std::vector<long int> > ld_time_map; + std::map< unsigned int, std::vector<long int> > st_time_map; + unsigned ld_vector_size; + unsigned st_vector_size; + std::vector<double> ld_time_dist; + std::vector<double> st_time_dist; - public: - my_time_vector(int ld_size, int st_size) { - ld_vector_size = ld_size; - st_vector_size = st_size; - ld_time_dist.resize(ld_size); - st_time_dist.resize(st_size); - overal_ld_time_dist.resize(ld_size); - overal_st_time_dist.resize(st_size); - overal_ld_count = 0; - overal_st_count = 0; - } - void update_ld(unsigned int uid, unsigned int slot, long int time) { - if (ld_time_map.find(uid) != ld_time_map.end()) { - ld_time_map[uid][slot] = time; - } else if (slot < NUM_MEM_REQ_STAT) { - std::vector<long int> time_vec; - time_vec.resize(ld_vector_size); - time_vec[slot] = time; - ld_time_map[uid] = time_vec; - } else { - // It's a merged mshr! forget it - } - } - void update_st(unsigned int uid, unsigned int slot, long int time) { - if (st_time_map.find(uid) != st_time_map.end()) { - st_time_map[uid][slot] = time; - } else { - std::vector<long int> time_vec; - time_vec.resize(st_vector_size); - time_vec[slot] = time; - st_time_map[uid] = time_vec; - } - } - void check_ld_update(unsigned int uid, unsigned int slot, long int latency) { - if (ld_time_map.find(uid) != ld_time_map.end()) { - int our_latency = - ld_time_map[uid][slot] - ld_time_map[uid][IN_ICNT_TO_MEM]; - assert(our_latency == latency); - } else if (slot < NUM_MEM_REQ_STAT) { - abort(); - } - } - void check_st_update(unsigned int uid, unsigned int slot, long int latency) { - if (st_time_map.find(uid) != st_time_map.end()) { - int our_latency = - st_time_map[uid][slot] - st_time_map[uid][IN_ICNT_TO_MEM]; - assert(our_latency == latency); - } else { - abort(); - } - } + std::vector<double> overal_ld_time_dist; + std::vector<double> overal_st_time_dist; + int overal_ld_count; + int overal_st_count; - private: - void calculate_ld_dist(void) { - unsigned i, first; - long int last_update, diff; - int finished_count = 0; - ld_time_dist.clear(); - ld_time_dist.resize(ld_vector_size); - std::map<unsigned int, std::vector<long int> >::iterator iter, iter_temp; - iter = ld_time_map.begin(); - while (iter != ld_time_map.end()) { - last_update = 0; - first = -1; - if (!iter->second[IN_SHADER_FETCHED]) { - // this request is not done yet skip it! - ++iter; - continue; +public: + my_time_vector(int ld_size,int st_size){ + ld_vector_size = ld_size; + st_vector_size = st_size; + ld_time_dist.resize(ld_size); + st_time_dist.resize(st_size); + overal_ld_time_dist.resize(ld_size); + overal_st_time_dist.resize(st_size); + overal_ld_count = 0; + overal_st_count= 0; + } + void update_ld(unsigned int uid,unsigned int slot, long int time) { + if ( ld_time_map.find( uid )!=ld_time_map.end() ) { + ld_time_map[uid][slot]=time; + } else if (slot < NUM_MEM_REQ_STAT ) { + std::vector<long int> time_vec; + time_vec.resize(ld_vector_size); + time_vec[slot] = time; + ld_time_map[uid] = time_vec; + } else { + //It's a merged mshr! forget it } - while (!last_update) { - first++; - assert(first < iter->second.size()); - last_update = iter->second[first]; + } + void update_st(unsigned int uid,unsigned int slot, long int time) { + if ( st_time_map.find( uid )!=st_time_map.end() ) { + st_time_map[uid][slot]=time; + } else { + std::vector<long int> time_vec; + time_vec.resize(st_vector_size); + time_vec[slot] = time; + st_time_map[uid] = time_vec; + } + } + void check_ld_update(unsigned int uid,unsigned int slot, long int latency) { + if ( ld_time_map.find( uid )!=ld_time_map.end() ) { + int our_latency = ld_time_map[uid][slot] - ld_time_map[uid][IN_ICNT_TO_MEM]; + assert( our_latency == latency); + } else if (slot < NUM_MEM_REQ_STAT ) { + abort(); } + } + void check_st_update(unsigned int uid,unsigned int slot, long int latency) { + if ( st_time_map.find( uid )!=st_time_map.end() ) { + int our_latency = st_time_map[uid][slot] - st_time_map[uid][IN_ICNT_TO_MEM]; + assert( our_latency == latency); + } else { + abort(); + } + } +private: + void calculate_ld_dist(void) { + unsigned i,first; + long int last_update,diff; + int finished_count=0; + ld_time_dist.clear(); + ld_time_dist.resize(ld_vector_size); + std::map< unsigned int, std::vector<long int> >::iterator iter, iter_temp; + iter =ld_time_map.begin() ; + while (iter != ld_time_map.end()) { + last_update=0; + first=-1; + if (!iter->second[IN_SHADER_FETCHED]) { + //this request is not done yet skip it! + ++iter; + continue; + } + while ( !last_update ) { + first++; + assert( first < iter->second.size() ); + last_update = iter->second[first]; + } - for (i = first; i < ld_vector_size; i++) { - diff = iter->second[i] - last_update; - if (diff > 0) { - ld_time_dist[i] += diff; - last_update = iter->second[i]; - } - } - iter_temp = iter; - iter++; - ld_time_map.erase(iter_temp); - finished_count++; - } - if (finished_count) { - for (i = 0; i < ld_vector_size; i++) { - overal_ld_time_dist[i] = - (overal_ld_time_dist[i] * overal_ld_count + ld_time_dist[i]) / - (overal_ld_count + finished_count); + for ( i=first;i<ld_vector_size;i++ ) { + diff = iter->second[i] - last_update; + if ( diff>0 ) { + ld_time_dist[i]+=diff; + last_update = iter->second[i]; + } + } + iter_temp = iter; + iter++; + ld_time_map.erase(iter_temp); + finished_count++; } - overal_ld_count += finished_count; - for (i = 0; i < ld_vector_size; i++) { - ld_time_dist[i] /= finished_count; + if ( finished_count ) { + for ( i=0;i<ld_vector_size;i++ ) { + overal_ld_time_dist[i] = (overal_ld_time_dist[i]*overal_ld_count + ld_time_dist[i]) / (overal_ld_count + finished_count); + } + overal_ld_count += finished_count; + for ( i=0;i<ld_vector_size;i++ ) { + ld_time_dist[i]/=finished_count; + } } - } - } + } - void calculate_st_dist(void) { - unsigned i, first; - long int last_update, diff; - int finished_count = 0; - st_time_dist.clear(); - st_time_dist.resize(st_vector_size); - std::map<unsigned int, std::vector<long int> >::iterator iter, iter_temp; - iter = st_time_map.begin(); - while (iter != st_time_map.end()) { - last_update = 0; - first = -1; - if (!iter->second[IN_SHADER_FETCHED]) { - // this request is not done yet skip it! - ++iter; - continue; + void calculate_st_dist(void) { + unsigned i,first; + long int last_update,diff; + int finished_count=0; + st_time_dist.clear(); + st_time_dist.resize(st_vector_size); + std::map< unsigned int, std::vector<long int> >::iterator iter,iter_temp; + iter =st_time_map.begin() ; + while ( iter != st_time_map.end() ) { + last_update=0; + first=-1; + if (!iter->second[IN_SHADER_FETCHED]) { + //this request is not done yet skip it! + ++iter; + continue; + } + while ( !last_update ) { + first++; + assert( first < iter->second.size() ); + last_update = iter->second[first]; + } + + for ( i=first;i<st_vector_size;i++ ) { + diff = iter->second[i] - last_update; + if ( diff>0 ) { + st_time_dist[i]+=diff; + last_update = iter->second[i]; + } + } + iter_temp = iter; + iter++; + st_time_map.erase(iter_temp); + finished_count++; } - while (!last_update) { - first++; - assert(first < iter->second.size()); - last_update = iter->second[first]; + if ( finished_count ) { + for ( i=0;i<st_vector_size;i++ ) { + overal_st_time_dist[i] = (overal_st_time_dist[i]*overal_st_count + st_time_dist[i]) / (overal_st_count + finished_count); + } + overal_st_count += finished_count; + for ( i=0;i<st_vector_size;i++ ) { + st_time_dist[i]/=finished_count; + } } + } - for (i = first; i < st_vector_size; i++) { - diff = iter->second[i] - last_update; - if (diff > 0) { - st_time_dist[i] += diff; - last_update = iter->second[i]; - } - } - iter_temp = iter; - iter++; - st_time_map.erase(iter_temp); - finished_count++; - } - if (finished_count) { - for (i = 0; i < st_vector_size; i++) { - overal_st_time_dist[i] = - (overal_st_time_dist[i] * overal_st_count + st_time_dist[i]) / - (overal_st_count + finished_count); +public: + void clear_time_map_vectors(void) { + ld_time_map.clear(); + st_time_map.clear(); + } + void print_all_ld(void) { + unsigned i; + std::map< unsigned int, std::vector<long int> >::iterator iter; + for ( iter =ld_time_map.begin() ; iter != ld_time_map.end(); ++iter ) { + std::cout<<"ld_uid"<<iter->first; + for ( i=0;i<ld_vector_size;i++ ) { + std::cout<<" "<<iter->second[i]; + } + std::cout<< std::endl; } - overal_st_count += finished_count; - for (i = 0; i < st_vector_size; i++) { - st_time_dist[i] /= finished_count; + } + + void print_all_st(void) { + unsigned i; + std::map< unsigned int, std::vector<long int> >::iterator iter; + + for ( iter =st_time_map.begin() ; iter != st_time_map.end(); ++iter ) { + std::cout<<"st_uid"<<iter->first; + for ( i=0;i<st_vector_size;i++ ) { + std::cout<<" "<<iter->second[i]; + } + std::cout<<std::endl; } - } - } + } - public: - void clear_time_map_vectors(void) { - ld_time_map.clear(); - st_time_map.clear(); - } - void print_all_ld(void) { - unsigned i; - std::map<unsigned int, std::vector<long int> >::iterator iter; - for (iter = ld_time_map.begin(); iter != ld_time_map.end(); ++iter) { - std::cout << "ld_uid" << iter->first; - for (i = 0; i < ld_vector_size; i++) { - std::cout << " " << iter->second[i]; + void calculate_dist() { + calculate_ld_dist(); + calculate_st_dist(); + } + void print_dist(void) { + unsigned i; + calculate_dist(); + std::cout << "LD_mem_lat_dist " ; + for ( i=0;i<ld_vector_size;i++ ) { + std::cout <<" "<<(int)overal_ld_time_dist[i]; } std::cout << std::endl; - } - } - - void print_all_st(void) { - unsigned i; - std::map<unsigned int, std::vector<long int> >::iterator iter; - - for (iter = st_time_map.begin(); iter != st_time_map.end(); ++iter) { - std::cout << "st_uid" << iter->first; - for (i = 0; i < st_vector_size; i++) { - std::cout << " " << iter->second[i]; + std::cout << "ST_mem_lat_dist " ; + for ( i=0;i<st_vector_size;i++ ) { + std::cout <<" "<<(int)overal_st_time_dist[i]; } std::cout << std::endl; - } - } - - void calculate_dist() { - calculate_ld_dist(); - calculate_st_dist(); - } - void print_dist(void) { - unsigned i; - calculate_dist(); - std::cout << "LD_mem_lat_dist "; - for (i = 0; i < ld_vector_size; i++) { - std::cout << " " << (int)overal_ld_time_dist[i]; - } - std::cout << std::endl; - std::cout << "ST_mem_lat_dist "; - for (i = 0; i < st_vector_size; i++) { - std::cout << " " << (int)overal_st_time_dist[i]; - } - std::cout << std::endl; - } - void print_to_file(FILE* outfile) { - unsigned i; - calculate_dist(); - fprintf(outfile, "LDmemlatdist:"); - for (i = 0; i < ld_vector_size; i++) { - fprintf(outfile, " %d", (int)ld_time_dist[i]); - } - fprintf(outfile, "\n"); - fprintf(outfile, "STmemlatdist:"); - for (i = 0; i < st_vector_size; i++) { - fprintf(outfile, " %d", (int)st_time_dist[i]); - } - fprintf(outfile, "\n"); - } - void print_to_gzfile(gzFile outfile) { - unsigned i; - calculate_dist(); - gzprintf(outfile, "LDmemlatdist:"); - for (i = 0; i < ld_vector_size; i++) { - gzprintf(outfile, " %d", (int)ld_time_dist[i]); - } - gzprintf(outfile, "\n"); - gzprintf(outfile, "STmemlatdist:"); - for (i = 0; i < st_vector_size; i++) { - gzprintf(outfile, " %d", (int)st_time_dist[i]); - } - gzprintf(outfile, "\n"); - } + } + void print_to_file(FILE *outfile) { + unsigned i; + calculate_dist(); + fprintf (outfile,"LDmemlatdist:") ; + for ( i=0;i<ld_vector_size;i++ ) { + fprintf (outfile," %d", (int)ld_time_dist[i]); + } + fprintf (outfile,"\n") ; + fprintf (outfile,"STmemlatdist:") ; + for ( i=0;i<st_vector_size;i++ ) { + fprintf (outfile," %d", (int)st_time_dist[i]); + } + fprintf (outfile,"\n") ; + } + void print_to_gzfile(gzFile outfile) { + unsigned i; + calculate_dist(); + gzprintf (outfile,"LDmemlatdist:") ; + for ( i=0;i<ld_vector_size;i++ ) { + gzprintf (outfile," %d", (int)ld_time_dist[i]); + } + gzprintf (outfile,"\n") ; + gzprintf (outfile,"STmemlatdist:") ; + for ( i=0;i<st_vector_size;i++ ) { + gzprintf (outfile," %d", (int)st_time_dist[i]); + } + gzprintf (outfile,"\n") ; + } }; -my_time_vector* g_my_time_vector; +my_time_vector* g_my_time_vector; void time_vector_create(int size) { - g_my_time_vector = new my_time_vector(size, size); -} + g_my_time_vector = new my_time_vector(size,size); +} + -void time_vector_print(void) { g_my_time_vector->print_dist(); } +void time_vector_print(void) { + g_my_time_vector->print_dist(); +} void time_vector_print_interval2gzfile(gzFile outfile) { - g_my_time_vector->print_to_gzfile(outfile); + g_my_time_vector->print_to_gzfile(outfile); } #include "../gpgpu-sim/mem_fetch.h" -void time_vector_update(unsigned int uid, int slot, long int cycle, int type) { - if ((type == READ_REQUEST) || (type == READ_REPLY)) { - g_my_time_vector->update_ld(uid, slot, cycle); - } else if ((type == WRITE_REQUEST) || (type == WRITE_ACK)) { - g_my_time_vector->update_st(uid, slot, cycle); - } else { - abort(); - } +void time_vector_update(unsigned int uid,int slot ,long int cycle,int type) { + if ( (type == READ_REQUEST) || (type == READ_REPLY) ) { + g_my_time_vector->update_ld( uid, slot,cycle); + } else if ( (type == WRITE_REQUEST) || (type == WRITE_ACK) ) { + g_my_time_vector->update_st( uid, slot,cycle); + } else { + abort(); + } } -void check_time_vector_update(unsigned int uid, int slot, long int latency, - int type) { - if ((type == READ_REQUEST) || (type == READ_REPLY)) { - g_my_time_vector->check_ld_update(uid, slot, latency); - } else if ((type == WRITE_REQUEST) || (type == WRITE_ACK)) { - g_my_time_vector->check_st_update(uid, slot, latency); - } else { - abort(); - } +void check_time_vector_update(unsigned int uid,int slot ,long int latency,int type) +{ + if ( (type == READ_REQUEST) || (type == READ_REPLY) ) { + g_my_time_vector->check_ld_update( uid, slot, latency ); + } else if ( (type == WRITE_REQUEST) || (type == WRITE_ACK) ) { + g_my_time_vector->check_st_update( uid, slot, latency ); + } else { + abort(); + } } diff --git a/src/gpgpu-sim/visualizer.h b/src/gpgpu-sim/visualizer.h index b841f62..e8ab8bf 100644 --- a/src/gpgpu-sim/visualizer.h +++ b/src/gpgpu-sim/visualizer.h @@ -7,16 +7,14 @@ // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright notice, -// this +// Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -35,8 +33,7 @@ void time_vector_create(int size); void time_vector_print(void); -void time_vector_update(unsigned int uid, int slot, long int cycle, int type); -void check_time_vector_update(unsigned int uid, int slot, long int latency, - int type); +void time_vector_update(unsigned int uid,int slot ,long int cycle,int type); +void check_time_vector_update(unsigned int uid,int slot ,long int latency,int type); #endif |
