diff options
| author | Wilson Fung <[email protected]> | 2013-07-25 14:06:34 -0800 |
|---|---|---|
| committer | Andrew Boktor <[email protected]> | 2014-08-14 13:50:58 -0700 |
| commit | 84f63f6996db657fe1291b4cc6e08b66422918c4 (patch) | |
| tree | a11db8fb7ca10363ef512496130fd5e95a7f32af /src/gpgpu-sim/gpu-cache.h | |
| parent | b5e2e7003f5d628d1c9baef08e6f6ae8b43e2ee5 (diff) | |
Adding bandwidth modeling to the cache model.
[git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 16671]
Diffstat (limited to 'src/gpgpu-sim/gpu-cache.h')
| -rw-r--r-- | src/gpgpu-sim/gpu-cache.h | 81 |
1 files changed, 77 insertions, 4 deletions
diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index 594125e..9a0ea4b 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -133,6 +133,7 @@ public: m_config_string = NULL; // set by option parser m_config_stringPrefL1 = NULL; m_config_stringPrefShared = NULL; + m_data_port_width = 0; } void init(char * config, FuncCache status) { @@ -140,10 +141,11 @@ public: assert( config ); char rp, wp, ap, mshr_type, wap; - int ntok = sscanf(config,"%u:%u:%u,%c:%c:%c:%c,%c:%u:%u,%u:%u", + int ntok = sscanf(config,"%u:%u:%u,%c:%c:%c:%c,%c:%u:%u,%u:%u,%u", &m_nset, &m_line_sz, &m_assoc, &rp, &wp, &ap, &wap, &mshr_type, &m_mshr_entries,&m_mshr_max_merge, - &m_miss_queue_size,&m_result_fifo_entries); + &m_miss_queue_size,&m_result_fifo_entries, + &m_data_port_width); if ( ntok < 11 ) { if ( !strcmp(config,"none") ) { @@ -198,6 +200,12 @@ public: // are stalling each other. assert(0 && "Invalid cache configuration: Writeback cache cannot allocate new line on fill. "); } + + // 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); } bool disabled() const { return m_disabled;} unsigned get_line_sz() const @@ -278,6 +286,8 @@ protected: }; unsigned m_result_fifo_entries; + unsigned m_data_port_width; //< number of byte the cache can access per cycle + friend class tag_array; friend class baseline_cache; friend class read_only_cache; @@ -415,6 +425,10 @@ struct cache_sub_stats{ unsigned pending_hits; unsigned res_fails; + unsigned long long port_available_cycles; + unsigned long long data_port_busy_cycles; + unsigned long long fill_port_busy_cycles; + cache_sub_stats(){ clear(); } @@ -423,6 +437,9 @@ struct cache_sub_stats{ 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){ /// @@ -432,6 +449,9 @@ struct cache_sub_stats{ 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; } @@ -444,8 +464,13 @@ struct cache_sub_stats{ 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; }; /// @@ -469,16 +494,25 @@ public: unsigned 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; + void sample_cache_port_utility(bool data_port_busy, bool fill_port_busy); private: bool check_valid(int type, int status) const; std::vector< std::vector<unsigned> > m_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; }; 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; + + // 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 ); @@ -491,7 +525,9 @@ 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_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 ); } @@ -546,6 +582,10 @@ public: m_stats.get_sub_stats(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(); } + protected: // Constructor that can be used by derived classes with custom tag arrays baseline_cache( const char *name, @@ -557,7 +597,8 @@ protected: 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_mshrs(config.m_mshr_entries,config.m_mshr_max_merge), + m_bandwidth_management(config) { init( name, config, memport, status ); } @@ -602,6 +643,34 @@ protected: /// 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, cache_block_t &evicted, std::list<cache_event> &events, bool read_only, bool wa); + + /// Sub-class containing all metadata for port bandwidth management + class bandwidth_management + { + public: + bandwidth_management(cache_config &config); + + /// 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); + + /// use the fill port + void use_fill_port(mem_fetch *mf); + + /// called every cache cycle to free up the ports + void replenish_port_bandwidth(); + + /// 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 + }; + + bandwidth_management m_bandwidth_management; }; /// Read only cache @@ -909,6 +978,10 @@ public: 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; |
