summaryrefslogtreecommitdiff
path: root/src/gpgpu-sim/gpu-cache.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpgpu-sim/gpu-cache.h')
-rw-r--r--src/gpgpu-sim/gpu-cache.h120
1 files changed, 107 insertions, 13 deletions
diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h
index b2db1c5..75dce40 100644
--- a/src/gpgpu-sim/gpu-cache.h
+++ b/src/gpgpu-sim/gpu-cache.h
@@ -72,14 +72,26 @@ enum cache_event_type {
struct evicted_block_info {
new_addr_type m_block_addr;
unsigned m_modified_size;
+ mem_access_byte_mask_t m_byte_mask;
+ mem_access_sector_mask_t m_sector_mask;
evicted_block_info() {
m_block_addr = 0;
m_modified_size = 0;
+ m_byte_mask.reset();
+ m_sector_mask.reset();
}
void set_info(new_addr_type block_addr, unsigned modified_size) {
m_block_addr = block_addr;
m_modified_size = modified_size;
}
+ void set_info(new_addr_type block_addr, unsigned modified_size,
+ mem_access_byte_mask_t byte_mask,
+ mem_access_sector_mask_t sector_mask) {
+ m_block_addr = block_addr;
+ m_modified_size = modified_size;
+ m_byte_mask = byte_mask;
+ m_sector_mask = sector_mask;
+ }
};
struct cache_event {
@@ -109,7 +121,8 @@ struct cache_block_t {
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 fill(unsigned time, mem_access_sector_mask_t sector_mask,
+ mem_access_byte_mask_t byte_mask) = 0;
virtual bool is_invalid_line() = 0;
virtual bool is_valid_line() = 0;
@@ -120,7 +133,10 @@ struct cache_block_t {
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 void set_byte_mask(mem_fetch *mf) = 0;
+ virtual void set_byte_mask(mem_access_byte_mask_t byte_mask) = 0;
+ virtual mem_access_byte_mask_t get_dirty_byte_mask() = 0;
+ virtual mem_access_sector_mask_t get_dirty_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;
@@ -131,6 +147,7 @@ struct cache_block_t {
mem_access_sector_mask_t sector_mask) = 0;
virtual void set_readable_on_fill(bool readable,
mem_access_sector_mask_t sector_mask) = 0;
+ virtual void set_byte_mask_on_fill(bool m_modified) = 0;
virtual unsigned get_modified_size() = 0;
virtual void set_m_readable(bool readable,
mem_access_sector_mask_t sector_mask) = 0;
@@ -164,8 +181,10 @@ struct line_cache_block : public cache_block_t {
m_ignore_on_fill_status = false;
m_set_modified_on_fill = false;
m_set_readable_on_fill = false;
+ m_set_byte_mask_on_fill = false;
}
- void fill(unsigned time, mem_access_sector_mask_t sector_mask) {
+ virtual void fill(unsigned time, mem_access_sector_mask_t sector_mask,
+ mem_access_byte_mask_t byte_mask) {
// if(!m_ignore_on_fill_status)
// assert( m_status == RESERVED );
@@ -173,6 +192,7 @@ struct line_cache_block : public cache_block_t {
if (m_set_readable_on_fill)
m_readable = true;
+ if (m_set_byte_mask_on_fill) set_byte_mask(byte_mask);
m_fill_time = time;
}
@@ -189,6 +209,20 @@ struct line_cache_block : public cache_block_t {
mem_access_sector_mask_t sector_mask) {
m_status = status;
}
+ virtual void set_byte_mask(mem_fetch *mf) {
+ m_byte_mask = m_byte_mask | mf->get_access_byte_mask();
+ }
+ virtual void set_byte_mask(mem_access_byte_mask_t byte_mask) {
+ m_byte_mask = m_byte_mask | byte_mask;
+ }
+ virtual mem_access_byte_mask_t get_dirty_byte_mask() {
+ return m_byte_mask;
+ }
+ virtual mem_access_sector_mask_t get_dirty_sector_mask() {
+ mem_access_sector_mask_t sector_mask;
+ if (m_status == MODIFIED) sector_mask.set();
+ return sector_mask;
+ }
virtual unsigned long long get_last_access_time() {
return m_last_access_time;
}
@@ -209,6 +243,9 @@ struct line_cache_block : public cache_block_t {
mem_access_sector_mask_t sector_mask) {
m_set_readable_on_fill = readable;
}
+ virtual void set_byte_mask_on_fill(bool m_modified) {
+ m_set_byte_mask_on_fill = m_modified;
+ }
virtual unsigned get_modified_size() {
return SECTOR_CHUNCK_SIZE * SECTOR_SIZE; // i.e. cache line size
}
@@ -231,7 +268,9 @@ struct line_cache_block : public cache_block_t {
bool m_ignore_on_fill_status;
bool m_set_modified_on_fill;
bool m_set_readable_on_fill;
+ bool m_set_byte_mask_on_fill;
bool m_readable;
+ mem_access_byte_mask_t m_byte_mask;
};
struct sector_cache_block : public cache_block_t {
@@ -251,6 +290,7 @@ struct sector_cache_block : public cache_block_t {
m_line_alloc_time = 0;
m_line_last_access_time = 0;
m_line_fill_time = 0;
+ m_byte_mask.reset();
}
virtual void allocate(new_addr_type tag, new_addr_type block_addr,
@@ -276,6 +316,7 @@ struct sector_cache_block : public cache_block_t {
m_ignore_on_fill_status[sidx] = false;
m_set_modified_on_fill[sidx] = false;
m_set_readable_on_fill[sidx] = false;
+ m_set_byte_mask_on_fill = false;
// set line stats
m_line_alloc_time = time; // only set this for the first allocated sector
@@ -310,18 +351,19 @@ struct sector_cache_block : public cache_block_t {
m_line_fill_time = 0;
}
- virtual void fill(unsigned time, mem_access_sector_mask_t sector_mask) {
+ virtual void fill(unsigned time, mem_access_sector_mask_t sector_mask,
+ mem_access_byte_mask_t byte_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;
if (m_set_readable_on_fill[sidx]) {
m_readable[sidx] = true;
m_set_readable_on_fill[sidx] = false;
}
+ if (m_set_byte_mask_on_fill) set_byte_mask(byte_mask);
m_sector_fill_time[sidx] = time;
m_line_fill_time = time;
@@ -362,6 +404,23 @@ struct sector_cache_block : public cache_block_t {
m_status[sidx] = status;
}
+ virtual void set_byte_mask(mem_fetch *mf) {
+ m_byte_mask = m_byte_mask | mf->get_access_byte_mask();
+ }
+ virtual void set_byte_mask(mem_access_byte_mask_t byte_mask) {
+ m_byte_mask = m_byte_mask | byte_mask;
+ }
+ virtual mem_access_byte_mask_t get_dirty_byte_mask() {
+ return m_byte_mask;
+ }
+ virtual mem_access_sector_mask_t get_dirty_sector_mask() {
+ mem_access_sector_mask_t sector_mask;
+ for (unsigned i = 0; i < SECTOR_CHUNCK_SIZE; i++) {
+ if (m_status[i] == MODIFIED)
+ sector_mask.set(i);
+ }
+ return sector_mask;
+ }
virtual unsigned long long get_last_access_time() {
return m_line_last_access_time;
}
@@ -387,6 +446,9 @@ struct sector_cache_block : public cache_block_t {
unsigned sidx = get_sector_index(sector_mask);
m_set_modified_on_fill[sidx] = m_modified;
}
+ virtual void set_byte_mask_on_fill(bool m_modified) {
+ m_set_byte_mask_on_fill = m_modified;
+ }
virtual void set_readable_on_fill(bool readable,
mem_access_sector_mask_t sector_mask) {
@@ -428,7 +490,9 @@ struct sector_cache_block : public cache_block_t {
bool m_ignore_on_fill_status[SECTOR_CHUNCK_SIZE];
bool m_set_modified_on_fill[SECTOR_CHUNCK_SIZE];
bool m_set_readable_on_fill[SECTOR_CHUNCK_SIZE];
+ bool m_set_byte_mask_on_fill;
bool m_readable[SECTOR_CHUNCK_SIZE];
+ mem_access_byte_mask_t m_byte_mask;
unsigned get_sector_index(mem_access_sector_mask_t sector_mask) {
assert(sector_mask.count() == 1);
@@ -491,6 +555,7 @@ class cache_config {
m_data_port_width = 0;
m_set_index_function = LINEAR_SET_FUNCTION;
m_is_streaming = false;
+ m_wr_percent = 0;
}
void init(char *config, FuncCache status) {
cache_status = status;
@@ -498,10 +563,10 @@ class cache_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,
+ sscanf(config, "%c:%u:%u:%u,%c:%c:%c:%c:%c,%c:%u:%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);
+ &m_miss_queue_size, &m_result_fifo_entries, &m_data_port_width, &m_wr_percent);
if (ntok < 12) {
if (!strcmp(config, "none")) {
@@ -511,6 +576,14 @@ class cache_config {
exit_parse_error();
}
+ // set * assoc * cacheline size. Then convert Byte to KB
+ unsigned original_size = m_nset * m_assoc * m_line_sz / 1024;
+ if (m_unified_cache_size > 0) {
+ max_cache_multiplier = m_unified_cache_size / original_size;
+ } else {
+ max_cache_multiplier = MAX_DEFAULT_CACHE_SIZE_MULTIBLIER;
+ }
+
switch (ct) {
case 'N':
m_cache_type = NORMAL;
@@ -620,6 +693,7 @@ class cache_config {
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
@@ -711,11 +785,13 @@ class cache_config {
}
unsigned get_max_num_lines() const {
assert(m_valid);
- return MAX_DEFAULT_CACHE_SIZE_MULTIBLIER * m_nset * original_m_assoc;
+ // gpgpu_unified_cache_size is in KB while original_sz is in B
+ return max_cache_multiplier * m_nset * original_m_assoc;
}
unsigned get_max_assoc() const {
assert(m_valid);
- return MAX_DEFAULT_CACHE_SIZE_MULTIBLIER * original_m_assoc;
+ // gpgpu_unified_cache_size is in KB while original_sz is in B
+ return max_cache_multiplier * original_m_assoc;
}
void print(FILE *fp) const {
fprintf(fp, "Size = %d B (%d Set x %d-way x %d byte line)\n",
@@ -765,6 +841,14 @@ class cache_config {
char *m_config_stringPrefL1;
char *m_config_stringPrefShared;
FuncCache cache_status;
+ unsigned m_wr_percent;
+ unsigned m_unified_cache_size;
+ write_allocate_policy_t get_write_allocate_policy() {
+ return m_write_alloc_policy;
+ }
+ write_policy_t get_write_policy() {
+ return m_write_policy;
+ }
protected:
void exit_parse_error() {
@@ -784,6 +868,7 @@ class cache_config {
unsigned m_sector_sz_log2;
unsigned original_m_assoc;
bool m_is_streaming;
+ unsigned max_cache_multiplier;
enum replacement_policy_t m_replacement_policy; // 'L' = LRU, 'F' = FIFO
enum write_policy_t
@@ -812,6 +897,7 @@ class cache_config {
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
+ unsigned m_wr_percent;
friend class tag_array;
friend class baseline_cache;
@@ -857,9 +943,11 @@ class tag_array {
~tag_array();
enum cache_request_status probe(new_addr_type addr, unsigned &idx,
- mem_fetch *mf, bool probe_mode = false) const;
+ mem_fetch *mf, bool is_write,
+ bool probe_mode = false) const;
enum cache_request_status probe(new_addr_type addr, unsigned &idx,
mem_access_sector_mask_t mask,
+ bool is_write,
bool probe_mode = false,
mem_fetch *mf = NULL) const;
enum cache_request_status access(new_addr_type addr, unsigned time,
@@ -868,9 +956,10 @@ class tag_array {
unsigned &idx, bool &wb,
evicted_block_info &evicted, mem_fetch *mf);
- void fill(new_addr_type addr, unsigned time, mem_fetch *mf);
+ void fill(new_addr_type addr, unsigned time, mem_fetch *mf, bool is_write);
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_access_sector_mask_t mask,
+ mem_access_byte_mask_t byte_mask, bool is_write);
unsigned size() const { return m_config.get_num_lines(); }
cache_block_t *get_block(unsigned idx) { return m_lines[idx]; }
@@ -888,6 +977,9 @@ class tag_array {
void update_cache_parameters(cache_config &config);
void add_pending_line(mem_fetch *mf);
void remove_pending_line(mem_fetch *mf);
+ void inc_dirty() {
+ m_dirty++;
+ }
protected:
// This constructor is intended for use only from derived classes that wish to
@@ -908,6 +1000,7 @@ class tag_array {
// allocated but not filled
unsigned m_res_fail;
unsigned m_sector_miss;
+ unsigned m_dirty;
// performance counters for calculating the amount of misses within a time
// window
@@ -1253,7 +1346,8 @@ class baseline_cache : public cache_t {
// 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);
+ mem_access_byte_mask_t byte_mask;
+ m_tag_array->fill(addr, time, mask, byte_mask, true);
}
protected: