/* * addrdec.cc * * Copyright (c) 2009 by Tor M. Aamodt, Wilson W. L. Fung, Ali Bakhoda, * George L. Yuan and the University of British Columbia * Vancouver, BC V6T 1Z4 * All Rights Reserved. * * THIS IS A LEGAL DOCUMENT BY DOWNLOADING GPGPU-SIM, YOU ARE AGREEING TO THESE * TERMS AND CONDITIONS. * * 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 OWNERS OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, 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. * * NOTE: The files libcuda/cuda_runtime_api.c and src/cuda-sim/cuda-math.h * are derived from the CUDA Toolset available from http://www.nvidia.com/cuda * (property of NVIDIA). The files benchmarks/BlackScholes/ and * benchmarks/template/ are derived from the CUDA SDK available from * http://www.nvidia.com/cuda (also property of NVIDIA). The files from * src/intersim/ are derived from Booksim (a simulator provided with the * textbook "Principles and Practices of Interconnection Networks" available * from http://cva.stanford.edu/books/ppin/). As such, those files are bound by * the corresponding legal terms and conditions set forth separately (original * copyright notices are left in files from these sources and where we have * modified a file our copyright notice appears before the original copyright * notice). * * Using this version of GPGPU-Sim requires a complete installation of CUDA * which is distributed seperately by NVIDIA under separate terms and * conditions. To use this version of GPGPU-Sim with OpenCL requires a * recent version of NVIDIA's drivers which support OpenCL. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. 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. * * 3. 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. * * 4. This version of GPGPU-SIM is distributed freely for non-commercial use only. * * 5. No nonprofit user may place any restrictions on the use of this software, * including as modified by the user, by any other authorized user. * * 6. GPGPU-SIM was developed primarily by Tor M. Aamodt, Wilson W. L. Fung, * Ali Bakhoda, George L. Yuan, at the University of British Columbia, * Vancouver, BC V6T 1Z4 */ #include #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; } 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@;}", NULL); } new_addr_type linear_to_raw_address_translation::partition_address( new_addr_type addr ) const { return addrdec_packbits( ~addrdec_mask[CHIP], addr, 64, 0 ); } 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 { addr_for_chip= ( (addr>>ADDR_CHIP_S) % Nchips) << ADDR_CHIP_S; rest_of_addr= ( (addr>>ADDR_CHIP_S) / Nchips) << ADDR_CHIP_S; tlx->chip = addrdec_packbits(addrdec_mask[CHIP], addr_for_chip, addrdec_mkhigh[CHIP], addrdec_mklow[CHIP]); if (addrdec_mask[BK] > addrdec_mask[CHIP]) { tlx->bk = addrdec_packbits(addrdec_mask[BK], rest_of_addr, addrdec_mkhigh[BK], addrdec_mklow[BK]); } else { tlx->bk = addrdec_packbits(addrdec_mask[BK], addr, addrdec_mkhigh[BK], addrdec_mklow[BK]); } if (addrdec_mask[ROW] > addrdec_mask[CHIP]) { tlx->row = addrdec_packbits(addrdec_mask[ROW], rest_of_addr, addrdec_mkhigh[ROW], addrdec_mklow[ROW]); } else { 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]); } } 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; 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); } } void linear_to_raw_address_translation::init(unsigned int nchips) { unsigned i; unsigned long long int mask; unsigned int nchipbits = ::LOGB2_32(nchips); Nchips = nchips; gap = (nchips - ::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; break; case 1: ADDR_CHIP_S = 13; addrdec_mask[CHIP] = 0x0000000000000000; addrdec_mask[BK] = 0x0000000000001800; addrdec_mask[ROW] = 0x0000000007FFE000; addrdec_mask[COL] = 0x00000000000007FF; break; case 2: ADDR_CHIP_S = 11; addrdec_mask[CHIP] = 0x0000000000000000; addrdec_mask[BK] = 0x0000000000001800; addrdec_mask[ROW] = 0x0000000007FFE000; addrdec_mask[COL] = 0x00000000000007FF; break; case 3: ADDR_CHIP_S = 11; addrdec_mask[CHIP] = 0x0000000000000000; addrdec_mask[BK] = 0x0000000000001800; addrdec_mask[ROW] = 0x000000000FFFE000; addrdec_mask[COL] = 0x00000000000007FF; break; case 14: ADDR_CHIP_S = 14; addrdec_mask[CHIP] = 0x0000000000000000; addrdec_mask[BK] = 0x0000000000001800; addrdec_mask[ROW] = 0x0000000007FFE000; addrdec_mask[COL] = 0x00000000000007FF; break; case 15: ADDR_CHIP_S = 15; addrdec_mask[CHIP] = 0x0000000000000000; addrdec_mask[BK] = 0x0000000000001800; addrdec_mask[ROW] = 0x0000000007FFE000; addrdec_mask[COL] = 0x00000000000007FF; break; case 16: ADDR_CHIP_S = 16; addrdec_mask[CHIP] = 0x0000000000000000; addrdec_mask[BK] = 0x0000000000001800; addrdec_mask[ROW] = 0x0000000007FFE000; addrdec_mask[COL] = 0x00000000000007FF; break; case 6: ADDR_CHIP_S = 6; addrdec_mask[CHIP] = 0x0000000000000000; addrdec_mask[BK] = 0x0000000000001800; addrdec_mask[ROW] = 0x0000000007FFE000; addrdec_mask[COL] = 0x00000000000007FF; break; 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: ADDR_CHIP_S = 1; addrdec_mask[CHIP] = 0x0000000000000000; addrdec_mask[BK] = 0x0000000000000003; addrdec_mask[ROW] = 0x0000000007FFE000; addrdec_mask[COL] = 0x0000000000001FFC; break; case 103: ADDR_CHIP_S = 3; addrdec_mask[CHIP] = 0x0000000000000000; addrdec_mask[BK] = 0x0000000000000003; addrdec_mask[ROW] = 0x0000000007FFE000; addrdec_mask[COL] = 0x0000000000001FFC; break; case 106: ADDR_CHIP_S = 6; addrdec_mask[CHIP] = 0x0000000000000000; 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 ADDR_CHIP_S = 6; addrdec_mask[CHIP] = 0x0000000000000000; addrdec_mask[BK] = 0x0000000000000300; addrdec_mask[ROW] = 0x0000000007FFE000; addrdec_mask[COL] = 0x0000000000001CFF; default: break; } if (addrdec_option != NULL) addrdec_parseoption(addrdec_option); if (ADDR_CHIP_S != -1) { 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; } } else { // make sure nchips is power of two when explicit dram id mask is used assert((nchips & (nchips - 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]); 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]); } void addrdec_t::print( FILE *fp ) const { if (chip) fprintf(fp,"\tchip:%x ", chip); if (row) fprintf(fp,"\trow:%x ", row); if (col) fprintf(fp,"\tcol:%x ", col); if (bk) fprintf(fp,"\tbk:%x ", bk); if (burst) fprintf(fp,"\tburst:%x ", burst); } 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; } static unsigned int LOGB2_32( unsigned int v ) { unsigned int shift; unsigned int r; 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; 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> 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; for (i=0;i<64;i++) { if ((mask & ((unsigned long long int)1<