summaryrefslogtreecommitdiff
path: root/src/gpgpu-sim/shader.h
diff options
context:
space:
mode:
authorTor Aamodt <[email protected]>2010-10-10 21:19:52 -0800
committerTor Aamodt <[email protected]>2010-10-10 21:19:52 -0800
commitb3ce70a797756285ea9b15b3e5cf515d8b6a2b63 (patch)
tree5b84d880e646f80611cc5b01931fdde622c5e06c /src/gpgpu-sim/shader.h
parent0151c5c566dcbcbb962acf35c86a8e0f4a4a6eb6 (diff)
1. create function unit classes for SP, SFU, LD/ST.
2. refactor memory stage into a ld/st function unit 3. refactor memory access generation (moved into warp_inst_t class) the above should make supporting fermi uarch much easier passing CUDA 3.1 regression still need to... (a) update scoreboard to keep count of outstanding memory requests and use operand collector for writebacks into register file (b) add back shared memory pipeline delay (c) remove use of MSHR's for non-cached global/local accesses (d) replace texture cache with a split tag/data array pipe (e) re-implement memory_partition stuff so it makes more sense [git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 7844]
Diffstat (limited to 'src/gpgpu-sim/shader.h')
-rw-r--r--src/gpgpu-sim/shader.h345
1 files changed, 236 insertions, 109 deletions
diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h
index 8e98749..d6ef552 100644
--- a/src/gpgpu-sim/shader.h
+++ b/src/gpgpu-sim/shader.h
@@ -107,8 +107,6 @@
#define WRITE_MASK_SIZE 8
#define NO_PARTIAL_WRITE (partial_write_mask_t())
-#define WORD_SIZE 4
-
//Set a hard limit of 32 CTAs per shader [cuda only has 8]
#define MAX_CTA_PER_SHADER 32
@@ -319,6 +317,7 @@ public:
void init( new_addr_type address, bool wr, memory_space_t space, unsigned warp_id );
void clear() { m_insts.clear(); }
void set_mf( class mem_fetch *mf ) { m_mf=mf; }
+ class mem_fetch *get_mf() { return m_mf; }
void add_inst( warp_inst_t inst ) { m_insts.push_back(inst); }
void set_status( enum mshr_status status );
void merge( mshr_entry *mshr )
@@ -346,7 +345,7 @@ public:
{
done_insts.insert(done_insts.end(),m_insts.begin(),m_insts.end());
}
- void add_to_queue( std::deque<mshr_entry*> &q )
+ void add_to_queue( std::list<mshr_entry*> &q )
{
// place all merged requests in return queue
mshr_entry *req = this;
@@ -380,7 +379,7 @@ public:
return m_insts[0].isatomic();
}
new_addr_type get_addr() const { return m_addr; }
- void print(FILE *fp, unsigned mask) const;
+ void print(FILE *fp) const;
private:
unsigned m_id;
@@ -416,25 +415,22 @@ public:
m_num_banks=0;
m_cu = NULL;
m_shader=NULL;
- m_sfu_port=NULL;
- m_alu_port=NULL;
+ m_num_ports=0;
}
- void init( unsigned num_collectors_alu,
- unsigned num_collectors_sfu,
- unsigned num_banks,
- shader_core_ctx *shader,
- warp_inst_t **alu_port,
- warp_inst_t **sfu_port );
+ void add_port( unsigned num_collector_units,
+ warp_inst_t **input_port,
+ warp_inst_t **output_port );
+ void init( unsigned num_banks, shader_core_ctx *shader );
// modifiers
bool writeback( const warp_inst_t &warp ); // might cause stall
- void step( warp_inst_t *&alu_issue_port, warp_inst_t *&sfu_issue_port )
+ void step()
{
dispatch_ready_cu();
allocate_reads();
- allocate_cu(alu_issue_port);
- allocate_cu(sfu_issue_port);
+ for( unsigned p=0; p < m_num_ports; p++ )
+ allocate_cu( p );
process_banks();
}
@@ -459,7 +455,7 @@ private:
}
void dispatch_ready_cu();
- void allocate_cu( warp_inst_t *&id_oc_reg );
+ void allocate_cu( unsigned port );
void allocate_reads();
// types
@@ -671,7 +667,7 @@ private:
warp_inst_t **port,
unsigned num_banks,
unsigned log2_warp_size,
- unsigned warp_size,
+ const shader_core_config *config,
opndcoll_rfu_t *rfu );
void allocate( warp_inst_t *&pipeline_reg );
@@ -747,8 +743,11 @@ private:
collector_unit_t *m_cu;
arbiter_t m_arbiter;
+ 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;
- warp_inst_t **m_sfu_port;
typedef std::map<warp_inst_t**/*port*/,dispatch_unit_t> port_to_du_t;
port_to_du_t m_dispatch_units;
@@ -825,7 +824,7 @@ public:
mshr_entry* add_mshr(mem_access_t &access, warp_inst_t* inst);
void mshr_return_from_mem(mshr_entry *mshr);
unsigned get_max_mshr_used() const {return m_max_mshr_used;}
- void print(FILE* fp, class shader_core_ctx* shader,unsigned mask);
+ void print(FILE* fp);
private:
mshr_entry *alloc_free_mshr(bool istexture);
@@ -836,15 +835,15 @@ private:
return (not m_mshr_return_queue.empty()) or
((not m_texture_mshr_pipeline.empty()) and m_texture_mshr_pipeline.front()->fetched());
}
- std::deque<mshr_entry*> &choose_return_queue();
+ std::list<mshr_entry*> &choose_return_queue();
const struct shader_core_config *m_shader_config;
typedef std::vector<mshr_entry> mshr_storage_type;
mshr_storage_type m_mshrs;
- std::deque<mshr_entry*> m_free_list;
- std::deque<mshr_entry*> m_mshr_return_queue;
- std::deque<mshr_entry*> m_texture_mshr_pipeline;
+ std::list<mshr_entry*> m_free_list;
+ std::list<mshr_entry*> m_mshr_return_queue;
+ std::list<mshr_entry*> m_texture_mshr_pipeline;
unsigned m_max_mshr_used;
mshr_lookup m_mshr_lookup;
};
@@ -871,7 +870,196 @@ struct ifetch_buffer_t {
unsigned m_warp_id;
};
-typedef address_type (*tag_func_t)(address_type add, unsigned line_size);
+class simd_function_unit {
+public:
+ simd_function_unit( warp_inst_t **result_port, const shader_core_config *config )
+ {
+ m_result_port = result_port;
+ m_config=config;
+ m_dispatch_reg = new warp_inst_t(config);
+ }
+ ~simd_function_unit() { delete m_dispatch_reg; }
+
+ // modifiers
+ virtual void issue( warp_inst_t *&inst ) { move_warp(m_dispatch_reg,inst); }
+ virtual void cycle() = 0;
+
+ // accessors
+ virtual bool can_issue( const warp_inst_t & ) const { return m_dispatch_reg->empty(); }
+ virtual bool stallable() const = 0;
+ virtual void print( FILE *fp ) const
+ {
+ fprintf(fp,"%s dispatch= ", m_name.c_str() );
+ m_dispatch_reg->print(fp);
+ }
+protected:
+ std::string m_name;
+ const shader_core_config *m_config;
+ warp_inst_t **m_result_port;
+ warp_inst_t *m_dispatch_reg;
+};
+
+class alu : public simd_function_unit {
+public:
+ alu( warp_inst_t **result_port, const shader_core_config *config, unsigned max_latency )
+ : simd_function_unit(result_port,config)
+ {
+ m_result_port = result_port;
+ m_pipeline_depth = max_latency;
+ m_pipeline_reg = new warp_inst_t*[m_pipeline_depth];
+ for( unsigned i=0; i < m_pipeline_depth; i++ )
+ m_pipeline_reg[i] = new warp_inst_t( config );
+ }
+
+ //modifiers
+ virtual void cycle()
+ {
+ if( !m_pipeline_reg[0]->empty() )
+ move_warp(*m_result_port,m_pipeline_reg[0]); // non-stallable pipeline
+ for( unsigned stage=0; (stage+1)<m_pipeline_depth; stage++ )
+ move_warp(m_pipeline_reg[stage], m_pipeline_reg[stage+1]);
+ if( !m_dispatch_reg->empty() ) {
+ if( !m_dispatch_reg->dispatch_delay() ) {
+ int start_stage = m_dispatch_reg->latency - m_dispatch_reg->initiation_interval;
+ move_warp(m_pipeline_reg[start_stage],m_dispatch_reg);
+ }
+ }
+ }
+ virtual void issue( warp_inst_t *&inst )
+ {
+ move_warp(m_dispatch_reg,inst);
+ }
+
+ // 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);
+ }
+ }
+ }
+private:
+ unsigned m_pipeline_depth;
+ warp_inst_t **m_pipeline_reg;
+};
+
+class sfu : public alu
+{
+public:
+ sfu( warp_inst_t **result_port, const shader_core_config *config )
+ : alu(result_port,config,config->max_sfu_latency) { m_name = "SFU"; }
+ virtual bool can_issue( const warp_inst_t &inst ) const
+ {
+ switch(inst.op) {
+ case SFU_OP: break;
+ case ALU_SFU_OP: break;
+ default: return false;
+ }
+ return alu::can_issue(inst);
+ }
+};
+
+class sp_unit : public alu
+{
+public:
+ sp_unit( warp_inst_t **result_port, const shader_core_config *config )
+ : alu(result_port,config,config->max_sp_latency) { m_name = "SP "; }
+ virtual bool can_issue( const warp_inst_t &inst ) const
+ {
+ switch(inst.op) {
+ case SFU_OP: return false;
+ case LOAD_OP: return false;
+ case STORE_OP: return false;
+ case MEMORY_BARRIER_OP: return false;
+ default: break;
+ }
+ return alu::can_issue(inst);
+ }
+};
+
+class ldst_unit : public simd_function_unit {
+public:
+ ldst_unit( gpgpu_sim *gpu,
+ shader_core_ctx *core,
+ warp_inst_t **result_port,
+ shader_core_config *config,
+ shader_core_stats *stats,
+ unsigned sid, unsigned tpc );
+
+ // modifiers
+ virtual void cycle();
+ void fill( mem_fetch *mf );
+ void flush();
+
+ // accessors
+ virtual bool can_issue( const warp_inst_t &inst ) const
+ {
+ switch(inst.op) {
+ case LOAD_OP: break;
+ case STORE_OP: break;
+ case MEMORY_BARRIER_OP: break;
+ default: return false;
+ }
+ return simd_function_unit::can_issue(inst);
+ }
+ virtual bool stallable() const { return true; }
+ void print(FILE *fout) const;
+
+private:
+ void generate_mem_accesses(warp_inst_t &pipe_reg);
+ void tex_cache_access(warp_inst_t &inst);
+ void const_cache_access(warp_inst_t &inst);
+
+ 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);
+
+ mem_stage_stall_type ccache_check(warp_inst_t &inst, mem_access_t& access){ return NO_RC_FAIL;}
+ mem_stage_stall_type tcache_check(warp_inst_t &inst, mem_access_t& access){ return NO_RC_FAIL;}
+ mem_stage_stall_type dcache_check(warp_inst_t &inst, mem_access_t& access);
+
+ typedef mem_stage_stall_type (ldst_unit::*cache_check_t)(warp_inst_t &,mem_access_t&);
+
+ mem_stage_stall_type process_memory_access_queue( ldst_unit::cache_check_t cache_check,
+ unsigned ports_per_bank,
+ unsigned memory_send_max,
+ warp_inst_t &inst );
+ mem_stage_stall_type send_mem_request(warp_inst_t &inst, mem_access_t &access);
+
+ gpgpu_sim *m_gpu;
+ shader_core_ctx *m_core;
+ unsigned m_sid;
+ unsigned m_tpc;
+
+ cache_t *m_L1D; // data cache (global/local memory accesses)
+ cache_t *m_L1T; // texture cache
+ cache_t *m_L1C; // constant cache
+ mshr_shader_unit *m_mshr_unit;
+
+ enum mem_stage_stall_type m_mem_rc;
+
+ shader_core_stats *m_stats;
+};
+
+enum pipeline_stage_name_t {
+ ID_OC_SP=0,
+ ID_OC_SFU,
+ ID_OC_MEM,
+ OC_EX_SP,
+ OC_EX_SFU,
+ OC_EX_MEM,
+ EX_WB,
+ N_PIPELINE_STAGES
+};
class shader_core_ctx : public core_t
{
@@ -880,12 +1068,11 @@ public:
const char *name,
unsigned shader_id,
unsigned tpc_id,
- const struct shader_core_config *config,
+ struct shader_core_config *config,
struct shader_core_stats *stats );
void issue_block2core( class kernel_info_t &kernel );
void get_pdom_stack_top_info( unsigned tid, unsigned *pc, unsigned *rpc );
- void new_cache_window();
bool ptx_thread_done( unsigned hw_thread_id ) const;
class ptx_thread_info *get_thread_state( unsigned hw_thread_id );
@@ -900,7 +1087,7 @@ public:
void deallocate_barrier( unsigned cta_id );
void decrement_atomic_count( unsigned wid );
- void cycle_gt200();
+ void cycle();
void reinit(unsigned start_thread, unsigned end_thread, bool reset_not_completed );
void init_warps(unsigned cta_id, unsigned start_thread, unsigned end_thread);
@@ -913,10 +1100,8 @@ public:
void fill_shd_L1_with_new_line( class mem_fetch * mf );
void store_ack( class mem_fetch *mf );
void dump_istream_state( FILE *fout );
- void mshr_print(FILE* fp, unsigned mask);
unsigned first_valid_thread( unsigned stage );
class ptx_thread_info* get_functional_thread( unsigned tid ) { return m_thread[tid].m_functional_model_thread_state; }
- void print_warp( warp_inst_t *warp, FILE *fout, int print_mem, int mask ) const;
std::list<unsigned> get_regs_written( const inst_t &fvt ) const;
const shader_core_config *get_config() const { return m_config; }
unsigned get_num_sim_insn() const { return m_num_sim_insn; }
@@ -927,14 +1112,8 @@ public:
unsigned get_thread_n_l1_mis_ac( unsigned tid ) const { return m_thread[tid].n_l1_mis_ac; }
unsigned get_thread_n_l1_mrghit_ac( unsigned tid ) const { return m_thread[tid].n_l1_mrghit_ac; }
unsigned get_thread_n_l1_access_ac( unsigned tid ) const { return m_thread[tid].n_l1_access_ac; }
- unsigned get_max_mshr_used() const { return m_mshr_unit->get_max_mshr_used(); }
- void L1cache_print( FILE *fp, unsigned &total_accesses, unsigned &total_misses) const;
- void L1texcache_print( FILE *fp, unsigned &total_accesses, unsigned &total_misses) const;
- void L1constcache_print( FILE *fp, unsigned &total_accesses, unsigned &total_misses) const;
unsigned get_n_active_cta() const { return m_n_active_cta; }
- float L1_windowed_cache_miss_rate( int x ) const { return m_L1D->shd_cache_windowed_cache_miss_rate(x); }
- float L1tex_windowed_cache_miss_rate( int x ) const { return m_L1T->shd_cache_windowed_cache_miss_rate(x); }
- float L1const_windowed_cache_miss_rate( int x ) const { return m_L1C->shd_cache_windowed_cache_miss_rate(x); }
+ void inc_store_req( unsigned warp_id) { m_warp[warp_id].inc_store_req(); }
private:
@@ -942,64 +1121,20 @@ private:
address_type next_pc( int tid ) const;
- void func_exec_inst( warp_inst_t &inst );
- void fetch_new();
+ void fetch();
+
+ void decode();
void issue_warp( warp_inst_t *&warp, const warp_inst_t *pI, unsigned active_mask, unsigned warp_id );
- void decode_new();
+ void func_exec_inst( warp_inst_t &inst );
+ address_type translate_local_memaddr(address_type localaddr, unsigned tid, unsigned num_shader );
void execute();
- void execute_pipe( unsigned pipeline, unsigned next_stage );
-
- void memory(); // advance memory pipeline stage
- void memory_queue(warp_inst_t &pipe_reg);
- void memory_shared_process_warp(warp_inst_t &inst);
- void memory_const_process_warp(warp_inst_t &inst);
- void memory_texture_process_warp(warp_inst_t &inst);
- void memory_global_process_warp(warp_inst_t &inst);
- bool memory_shared_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type);
- bool memory_constant_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type);
- bool memory_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);
- address_type translate_local_memaddr(address_type localaddr, int tid, unsigned num_shader );
-
- mem_stage_stall_type ccache_check(warp_inst_t &inst, mem_access_t& access){ return NO_RC_FAIL;}
- mem_stage_stall_type tcache_check(warp_inst_t &inst, mem_access_t& access){ return NO_RC_FAIL;}
- mem_stage_stall_type dcache_check(warp_inst_t &inst, mem_access_t& access);
-
- typedef mem_stage_stall_type (shader_core_ctx::*cache_check_t)(warp_inst_t &,mem_access_t&);
-
- mem_stage_stall_type process_memory_access_queue( shader_core_ctx::cache_check_t cache_check,
- unsigned ports_per_bank,
- unsigned memory_send_max,
- warp_inst_t &inst );
-
- typedef int (shader_core_ctx::*bank_func_t)(address_type add, unsigned line_size);
-
- int null_bank_func(address_type add, unsigned line_size);
- int shmem_bank_func(address_type add, unsigned line_size);
- int dcache_bank_func(address_type add, unsigned line_size);
-
- void get_memory_access_list( bank_func_t bank_func,
- tag_func_t tag_func,
- unsigned warp_parts,
- unsigned line_size,
- bool limit_broadcast,
- warp_inst_t &inst );
- mem_stage_stall_type send_mem_request(warp_inst_t &inst, mem_access_t &access);
void writeback();
- unsigned char fq_push( unsigned long long int addr,
- int bsize,
- unsigned char write,
- partial_write_mask_t partial_write_mask,
- int wid, mshr_entry* mshr,
- enum mem_access_type mem_acc,
- address_type pc );
-
void call_thread_done(inst_t &done_inst );
- void print_stage(unsigned int stage, FILE *fout, int print_mem, int mask );
+ void print_stage(unsigned int stage, FILE *fout) const;
// general information
unsigned m_sid; // shader id
@@ -1020,37 +1155,29 @@ private:
// thread contexts
thread_ctx_t *m_thread; // functional state, per thread fetch state
+
+ // fetch
+ cache_t *m_L1I; // instruction cache
+ int m_last_warp_fetched;
+
+ // decode/dispatch
+ int m_last_warp_issued;
std::vector<shd_warp_t> m_warp; // per warp information array
barrier_set_t m_barriers;
ifetch_buffer_t m_inst_fetch_buffer;
pdom_warp_ctx_t **m_pdom_warp; // pdom reconvergence context for each warp
-
warp_inst_t** m_pipeline_reg;
Scoreboard *m_scoreboard;
opndcoll_rfu_t m_operand_collector;
- mshr_shader_unit *m_mshr_unit;
- // fetch
- int m_last_warp_fetched;
- int m_last_warp_issued;
-
- cache_t *m_L1I; // instruction cache
- cache_t *m_L1D; // data cache (global/local memory accesses)
- cache_t *m_L1T; // texture cache
- cache_t *m_L1C; // constant cache
-
- enum mem_stage_stall_type m_mem_rc;
-};
-
-enum pipeline_stage_name_t {
- ID_OC_SP=0,
- ID_OC_SFU,
- OC_EX_SP,
- OC_EX_SFU,
- EX_MM,
- MM_WB,
- WB_RT,
- N_PIPELINE_STAGES
+ // execute
+ unsigned m_num_function_units;
+ enum pipeline_stage_name_t *m_dispatch_port;
+ enum pipeline_stage_name_t *m_issue_port;
+ simd_function_unit **m_fu; // stallable pipelines should be last in this array
+ ldst_unit *m_ldst_unit;
+ static const unsigned MAX_ALU_LATENCY = 64;
+ std::bitset<MAX_ALU_LATENCY> m_result_bus;
};
#endif /* SHADER_H */