diff options
Diffstat (limited to 'src/gpgpu-sim/shader.h')
| -rw-r--r-- | src/gpgpu-sim/shader.h | 3697 |
1 files changed, 1907 insertions, 1790 deletions
diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index ca85903..7d8b77a 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,71 +8,71 @@ // // 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 -// 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. +// 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 -// 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 -// 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. +// 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 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. #ifndef SHADER_H #define SHADER_H +#include <assert.h> +#include <math.h> #include <stdio.h> #include <stdlib.h> -#include <math.h> -#include <assert.h> +#include <algorithm> +#include <bitset> +#include <deque> +#include <list> #include <map> #include <set> -#include <vector> -#include <list> -#include <bitset> #include <utility> -#include <algorithm> -#include <deque> +#include <vector> //#include "../cuda-sim/ptx.tab.h" +#include "../abstract_hardware_model.h" #include "delayqueue.h" -#include "stack.h" #include "dram.h" -#include "../abstract_hardware_model.h" -#include "scoreboard.h" +#include "gpu-cache.h" #include "mem_fetch.h" +#include "scoreboard.h" +#include "stack.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, @@ -83,1127 +83,1132 @@ 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_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_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; } + } + 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++; - } - 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 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--; + } - 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; - - struct ibuffer_entry { - ibuffer_entry() { m_valid = false; m_inst = NULL; } - const warp_inst_t *m_inst; - bool m_valid; - }; + bool m_imiss_pending; - 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 + struct ibuffer_entry { + ibuffer_entry() { + m_valid = false; + m_inst = NULL; + } + const warp_inst_t *m_inst; + bool m_valid; + }; - bool m_done_exit; // true once thread exit has been registered for threads in this warp + warp_inst_t m_inst_at_barrier; + ibuffer_entry m_ibuffer[IBUFFER_SIZE]; + unsigned m_next; - unsigned long long m_last_fetch; + unsigned m_n_atomic; // number of outstanding atomic operations + bool m_membar; // if true, warp is waiting at memory barrier - unsigned m_stores_outstanding; // number of store requests sent but not yet acknowledged - unsigned m_inst_in_pipeline; + bool m_done_exit; // true once thread exit has been registered for threads in + // this warp - //Jin: cdp support -public: - unsigned int m_cdp_latency; - bool m_cdp_dummy; -}; + unsigned long long m_last_fetch; + 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(); - } +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(); - // 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(); + // 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); - // 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); + 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); - // Derived classes can override this function to populate - // m_supervised_warps with their scheduling policies - virtual void order_warps() = 0; + // Derived classes can override this function to populate + // m_supervised_warps with their scheduling policies + virtual void order_warps() = 0; - int get_schd_id() const {return m_id;} + int get_schd_id() const { return m_id; } -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); + 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; - // 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; + protected: + shd_warp_t &warp(int i); - int m_id; + // 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; }; 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)); - } - } - virtual void done_adding_supervised_warps() { - m_last_supervised_issued = m_supervised_warps.begin(); + 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(); + } -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); -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(); - } + void step() { + dispatch_ready_cu(); + allocate_reads(); + for (unsigned p = 0; p < m_in_ports.size(); p++) allocate_cu(p); + process_banks(); + } - 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; } + 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); + } -private: + shader_core_ctx *shader_core() { return m_shader; } - void process_banks() - { - m_arbiter.reset_alloction(); - } + 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); + } - 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); + } - // 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; } - // 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); } - fprintf(fp,"\n"); + 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); } - 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; } + 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; } + 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(); - } + // 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"); - } - 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"); + // 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"); + } - // modifiers - std::list<op_t> allocate_reads(); + // 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(); + 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(); + } 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; - - unsigned m_num_banks_per_sched; - bool m_sub_core_model; + 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; + }; - 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]); - } - } - return NULL; + 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; + } 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); - - // during cta allocation - void allocate_barrier( unsigned cta_id, warp_set_t warps ); - - // during cta deallocation - void deallocate_barrier( unsigned cta_id ); + 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); - 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(); - -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; + // 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; }; 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; + // 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(); - } -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; + } - unsigned active_insts_in_pipeline; + 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; }; -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); +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; } - virtual void active_lanes_in_pipeline(); - virtual void issue( register_set& source_reg ); + return pipelined_simd_unit::can_issue(inst); + } + 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; - } - return pipelined_simd_unit::can_issue(inst); +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; } - virtual void active_lanes_in_pipeline(); - virtual void issue( register_set& source_reg ); + return pipelined_simd_unit::can_issue(inst); + } + 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; - } - return pipelined_simd_unit::can_issue(inst); +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; } - virtual void active_lanes_in_pipeline(); - virtual void issue( register_set& source_reg ); + return pipelined_simd_unit::can_issue(inst); + } + 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; - } - return pipelined_simd_unit::can_issue(inst); +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; } - virtual void active_lanes_in_pipeline(); - virtual void issue( register_set& source_reg ); + return pipelined_simd_unit::can_issue(inst); + } + 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; - } - return pipelined_simd_unit::can_issue(inst); +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; } - virtual void active_lanes_in_pipeline(); - virtual void issue( register_set& source_reg ); + return pipelined_simd_unit::can_issue(inst); + } + virtual void active_lanes_in_pipeline(); + virtual void issue(register_set &source_reg); }; class simt_core_cluster; @@ -1211,317 +1216,320 @@ 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 ); +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(); - - void fill( mem_fetch *mf ); - void flush(); - void invalidate(); - void writeback(); + // modifiers + virtual void issue(register_set &inst); + virtual void cycle(); - // accessors - virtual unsigned clock_multiplier() const; + void fill(mem_fetch *mf); + void flush(); + void invalidate(); + void writeback(); - 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(); + // 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; } + 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"}; + +class shader_core_config : public core_config { + public: + shader_core_config(gpgpu_context *ctx) : core_config(ctx) { + pipeline_widths_string = NULL; + gpgpu_ctx = ctx; + } + + 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(); } - 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(); - } + char *toks = new char[100]; + char *tokd = toks; + strcpy(toks, pipeline_widths_string); - char* toks = new char[100]; - char* tokd = toks; - strcpy(toks,pipeline_widths_string); - - toks = strtok(toks,","); + 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; - - 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) ); + delete[] tokd; - 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; + 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(); } - 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(); + max_warps_per_shader = n_thread_per_shader / warp_size; + assert(!(n_thread_per_shader % warp_size)); + + 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; + } + 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(); + + // 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]; - // 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]; + 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; - 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; + bool gpgpu_dwf_reg_bankconflict; - bool gpgpu_dwf_reg_bankconflict; + unsigned gpgpu_num_sched_per_core; + int gpgpu_max_insn_issue_per_warp; + bool gpgpu_dual_issue_diff_exec_units; - unsigned gpgpu_num_sched_per_core; - int gpgpu_max_insn_issue_per_warp; - bool gpgpu_dual_issue_diff_exec_units; + // 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; - //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_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; - 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; + 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_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; + 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 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; + // 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; - //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; + unsigned max_sp_latency; + unsigned max_int_latency; + unsigned max_sfu_latency; + unsigned max_dp_latency; + unsigned max_tensor_core_latency; - int simt_core_sim_order; - - unsigned smem_latency; + unsigned n_simt_cores_per_cluster; + unsigned n_simt_clusters; + unsigned n_simt_ejection_buffer_size; + unsigned ldst_unit_response_queue_size; - unsigned mem2device(unsigned memid) const { return memid + n_simt_clusters; } + int simt_core_sim_order; - //Jin: concurrent kernel on sm - bool gpgpu_concurrent_kernel_sm; + unsigned smem_latency; + + unsigned mem2device(unsigned memid) const { return memid + n_simt_clusters; } + + // Jin: concurrent kernel on sm + bool gpgpu_concurrent_kernel_sm; bool perfect_inst_const_cache; unsigned inst_fetch_throughput; @@ -1533,635 +1541,744 @@ class shader_core_config : public core_config char* trace_opcode_latency_initiation_sfu; char* trace_opcode_latency_initiation_tensor; - }; 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; - 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; - //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; + 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 ); + 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 ); + // 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;} + 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()); + } -// 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; + // 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 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 ); + // 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_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; + void get_icnt_power_stats(long &n_simt_to_mem, long &n_mem_to_simt) const; -// debug: - void display_simt_state(FILE *fout, int mask ) const; - void display_pipeline( FILE *fout, int print_mem, int mask3bit ) const; + // debug: + void display_simt_state(FILE *fout, int mask) const; + void display_pipeline(FILE *fout, int print_mem, int mask3bit) const; - 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 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 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 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 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 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 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;} + 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; + } - 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 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 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 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); - 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); - } + 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); + } - int test_res_bus(int latency); + int test_res_bus(int latency); void init_warps(unsigned cta_id, unsigned start_thread, unsigned end_thread,unsigned ctaid, int cta_size, kernel_info_t &kernel); 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 ); + address_type next_pc(int tid) const; + void fetch(); + void register_cta_thread_exit(unsigned cta_num, kernel_info_t *kernel); - 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 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); virtual void func_exec_inst( warp_inst_t &inst ); - // 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 ); + // 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 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; - 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; + // 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; - // 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; + // statistics + shader_core_stats *m_stats; - // statistics - shader_core_stats *m_stats; + // 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; - // 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; + // thread contexts + thread_ctx_t *m_threadState; - // 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; + // interconnect interface + mem_fetch_interface *m_icnt; + shader_core_mem_fetch_allocator *m_mem_fetch_allocator; - //schedule - std::vector<scheduler_unit*> schedulers; + // fetch + read_only_cache *m_L1I; // instruction cache + int m_last_warp_fetched; - //issue - unsigned int Issue_Prio; + // 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; - // 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; + // schedule + std::vector<scheduler_unit *> schedulers; - // 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; + // issue + unsigned int Issue_Prio; - //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; + // 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; + + // 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; - //Trace-driven simulation friend class trace_shader_core_ctx; }; 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); + } - // 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 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(); } |
