summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWilson Fung <[email protected]>2012-03-02 02:09:25 -0800
committerAndrew Boktor <[email protected]>2014-08-14 13:19:04 -0700
commit9103b5e31822eec864b54717d70b007cd325ba3f (patch)
treea9e17993e3ac584f340a49f5def73b8f63ee7c5b /src
parent7ed81817628be2fe625a0794e8f5c1f39e258992 (diff)
Fixed bug 137. Now memory address mapping with non-power-of-two memory partitions will not lead to address aliasing.
[git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 11574]
Diffstat (limited to 'src')
-rw-r--r--src/gpgpu-sim/addrdec.cc102
-rw-r--r--src/gpgpu-sim/addrdec.h2
2 files changed, 94 insertions, 10 deletions
diff --git a/src/gpgpu-sim/addrdec.cc b/src/gpgpu-sim/addrdec.cc
index 1a07e10..3c5945e 100644
--- a/src/gpgpu-sim/addrdec.cc
+++ b/src/gpgpu-sim/addrdec.cc
@@ -56,6 +56,9 @@ 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");
@@ -63,7 +66,15 @@ void linear_to_raw_address_translation::addrdec_setoption(option_parser_t opp)
new_addr_type linear_to_raw_address_translation::partition_address( new_addr_type addr ) const
{
- return addrdec_packbits( ~addrdec_mask[CHIP], addr, 64, 0 );
+ if (!gap) {
+ // see addrdec_tlx for explanation
+ unsigned long long int partition_addr;
+ partition_addr = ( (addr>>ADDR_CHIP_S) / Nchips) << ADDR_CHIP_S;
+ partition_addr |= addr & ((1 << ADDR_CHIP_S) - 1);
+ return partition_addr;
+ } else {
+ 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
@@ -76,6 +87,7 @@ void linear_to_raw_address_translation::addrdec_tlx(new_addr_type addr, addrdec_
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 {
+ #if 0
addr_for_chip= ( (addr>>ADDR_CHIP_S) % Nchips) << ADDR_CHIP_S;
rest_of_addr= ( (addr>>ADDR_CHIP_S) / Nchips) << ADDR_CHIP_S;
@@ -92,6 +104,20 @@ void linear_to_raw_address_translation::addrdec_tlx(new_addr_type addr, addrdec_
}
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]);
+ #endif
+
+ // 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) % Nchips;
+ rest_of_addr = ( (addr>>ADDR_CHIP_S) / Nchips) << 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]);
}
}
@@ -258,16 +284,20 @@ void linear_to_raw_address_translation::init(unsigned int nchips)
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);
+ 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;
- }
+ 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 nchips is power of two when explicit dram id mask is used
assert((nchips & (nchips - 1)) == 0);
@@ -284,6 +314,58 @@ void linear_to_raw_address_translation::init(unsigned int nchips)
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]);
+
+ if (run_test) {
+ sweep_test();
+ }
+}
+
+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;
+}
+
+class hash_addrdec_t
+{
+public:
+ size_t operator()(const addrdec_t &x) const {
+ return (x.chip ^ x.bk ^ x.row ^ x.col ^ x.burst);
+ }
+};
+
+void linear_to_raw_address_translation::sweep_test() const
+{
+ new_addr_type sweep_range = 16 * 1024 * 1024;
+
+ typedef std::unordered_map<addrdec_t, new_addr_type, hash_addrdec_t> history_map_t;
+ 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);
+
+ 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 < Nchips);
+ history_map[tlx] = raw_addr;
+ }
+
+ if ((raw_addr & 0xffff) == 0) printf("%llu scaned\n", raw_addr);
+ }
}
void addrdec_t::print( FILE *fp ) const
diff --git a/src/gpgpu-sim/addrdec.h b/src/gpgpu-sim/addrdec.h
index 634981d..94b113a 100644
--- a/src/gpgpu-sim/addrdec.h
+++ b/src/gpgpu-sim/addrdec.h
@@ -57,6 +57,7 @@ public:
private:
void addrdec_parseoption(const char *option);
+ void sweep_test() const; // sanity check to ensure no overlapping
enum {
CHIP = 0,
@@ -69,6 +70,7 @@ private:
const char *addrdec_option;
int gpgpu_mem_address_mask;
+ bool run_test;
int ADDR_CHIP_S;
unsigned char addrdec_mklow[N_ADDRDEC];