summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gpgpu-sim/gpu-sim.cc3
-rw-r--r--src/gpgpu-sim/shader.cc63
-rw-r--r--src/gpgpu-sim/shader.h49
3 files changed, 93 insertions, 22 deletions
diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc
index d90d174..da8f508 100644
--- a/src/gpgpu-sim/gpu-sim.cc
+++ b/src/gpgpu-sim/gpu-sim.cc
@@ -267,6 +267,9 @@ void shader_core_config::reg_options(class OptionParser * opp)
option_parser_register(opp, "-gpgpu_coalesce_arch", OPT_INT32, &gpgpu_coalesce_arch,
"Coalescing arch (default = 13, anything else is off for now)",
"13");
+ option_parser_register(opp, "-gpgpu_num_sched_per_core", OPT_INT32, &gpgpu_num_sched_per_core,
+ "Number of warp schedulers per core",
+ "1");
}
void gpgpu_sim_config::reg_options(option_parser_t opp)
diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc
index 1f7ecb6..608b29c 100644
--- a/src/gpgpu-sim/shader.cc
+++ b/src/gpgpu-sim/shader.cc
@@ -143,7 +143,6 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu,
// fetch
m_last_warp_fetched = 0;
- m_last_warp_issued = 0;
#define STRSIZE 1024
char name[STRSIZE];
@@ -156,6 +155,18 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu,
m_simt_stack[i] = new simt_stack(i,this);
m_scoreboard = new Scoreboard(m_sid, m_config->max_warps_per_shader);
+ //scedulers
+ //must currently occur after all inputs have been initialized.
+ for (int i = 0; i < m_config->gpgpu_num_sched_per_core; i++) {
+ schedulers.push_back(scheduler_unit(m_stats,this,m_scoreboard,m_simt_stack,&m_warp,
+ &m_pipeline_reg[ID_OC_SP],
+ &m_pipeline_reg[ID_OC_SFU],
+ &m_pipeline_reg[ID_OC_MEM]));
+ }
+ for (unsigned i = 0; i < m_warp.size(); i++) {
+ //distribute i's evenly though schedulers;
+ schedulers[i%m_config->gpgpu_num_sched_per_core].add_supervised_warp_id(i);
+ }
//op collector configuration
enum { SP_CUS, SFU_CUS, MEM_CUS, GEN_CUS };
@@ -683,50 +694,62 @@ void shader_core_ctx::issue_warp( warp_inst_t *&pipe_reg, const warp_inst_t *nex
m_warp[warp_id].set_next_pc(next_inst->pc + next_inst->isize);
}
-void shader_core_ctx::decode()
+void shader_core_ctx::decode(){
+ //really is issue;
+ for (unsigned i = 0; i < schedulers.size(); i++) {
+ schedulers[i].cycle();
+ }
+}
+
+shd_warp_t& scheduler_unit::warp(int i){
+ return (*m_warp)[i];
+}
+
+void scheduler_unit::cycle()
{
bool valid_inst = false; // there was one warp with a valid instruction to issue (didn't require flush due to control hazard)
bool ready_inst = false; // of the valid instructions, there was one not waiting for pending register writes
bool issued_inst = false; // of these we issued one
- for ( unsigned i=0; i < m_config->max_warps_per_shader; i++ ) {
- unsigned warp_id = (m_last_warp_issued+1+i) % m_config->max_warps_per_shader;
+ for ( unsigned i=0; i < supervised_warps.size(); i++ ) {
+ unsigned supervised_id = (m_last_sup_id_issued+1+i) % supervised_warps.size();
+ unsigned warp_id = supervised_warps[supervised_id];
unsigned checked=0;
unsigned issued=0;
- while( !m_warp[warp_id].waiting() && !m_warp[warp_id].ibuffer_empty() && (checked < 2) && (issued < 2) ) {
- const warp_inst_t *pI = m_warp[warp_id].ibuffer_next_inst();
- bool valid = m_warp[warp_id].ibuffer_next_valid();
+ while( !warp(warp_id).waiting() && !warp(warp_id).ibuffer_empty() && (checked < 2) && (issued < 2) ) {
+ const warp_inst_t *pI = warp(warp_id).ibuffer_next_inst();
+ bool valid = warp(warp_id).ibuffer_next_valid();
unsigned pc,rpc;
m_simt_stack[warp_id]->get_pdom_stack_top_info(&pc,&rpc);
if( pI ) {
assert(valid);
if( pc != pI->pc ) {
// control hazard
- m_warp[warp_id].set_next_pc(pc);
- m_warp[warp_id].ibuffer_flush();
+ warp(warp_id).set_next_pc(pc);
+ warp(warp_id).ibuffer_flush();
} else {
valid_inst = true;
if ( !m_scoreboard->checkCollision(warp_id, pI) ) {
ready_inst = true;
const active_mask_t &active_mask = m_simt_stack[warp_id]->get_active_mask();
- assert( m_warp[warp_id].inst_in_pipeline() );
+ assert( warp(warp_id).inst_in_pipeline() );
if ( (pI->op == LOAD_OP) || (pI->op == STORE_OP) || (pI->op == MEMORY_BARRIER_OP) ) {
- if( m_pipeline_reg[ID_OC_MEM]->empty() ) {
- issue_warp(m_pipeline_reg[ID_OC_MEM],pI,active_mask,warp_id);
+ if( (*m_mem_out)->empty() ) {
+ m_shader->issue_warp(*m_mem_out,pI,active_mask,warp_id);
issued++;
issued_inst=true;
}
} else {
- bool sp_pipe_avail = m_pipeline_reg[ID_OC_SP]->empty();
- bool sfu_pipe_avail = m_pipeline_reg[ID_OC_SFU]->empty();
+ bool sp_pipe_avail = (*m_sp_out)->empty();
+ bool sfu_pipe_avail = (*m_sfu_out)->empty();
if( sp_pipe_avail && (pI->op != SFU_OP) ) {
// always prefer SP pipe for operations that can use both SP and SFU pipelines
- issue_warp(m_pipeline_reg[ID_OC_SP],pI,active_mask,warp_id);
+ m_shader->issue_warp(*m_sp_out,pI,active_mask,warp_id);
issued++;
issued_inst=true;
} else if ( (pI->op == SFU_OP) || (pI->op == ALU_SFU_OP) ) {
if( sfu_pipe_avail ) {
- issue_warp(m_pipeline_reg[ID_OC_SFU],pI,active_mask,warp_id);
+ m_shader->issue_warp(*m_sfu_out,pI,active_mask,warp_id);
issued++;
issued_inst=true;
}
@@ -736,14 +759,14 @@ void shader_core_ctx::decode()
}
} else if( valid ) {
// this case can happen after a return instruction in diverged warp
- m_warp[warp_id].set_next_pc(pc);
- m_warp[warp_id].ibuffer_flush();
+ warp(warp_id).set_next_pc(pc);
+ warp(warp_id).ibuffer_flush();
}
- m_warp[warp_id].ibuffer_step();
+ warp(warp_id).ibuffer_step();
checked++;
}
if ( issued ) {
- m_last_warp_issued=warp_id;
+ m_last_sup_id_issued=supervised_id;
break;
}
}
diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h
index 3f3a688..e3a4c62 100644
--- a/src/gpgpu-sim/shader.h
+++ b/src/gpgpu-sim/shader.h
@@ -319,6 +319,44 @@ typedef std::bitset<WARP_PER_CTA_MAX> warp_set_t;
int register_bank(int regnum, int wid, unsigned num_banks, unsigned bank_warp_shift);
class shader_core_ctx;
+class shader_core_config;
+class shader_core_stats;
+
+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,
+ warp_inst_t** sp_out,
+ warp_inst_t** sfu_out,
+ warp_inst_t** mem_out)
+ : supervised_warps(), m_last_sup_id_issued(0), 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_sfu_out(sfu_out),m_mem_out(mem_out){}
+ void add_supervised_warp_id(int i) {
+ supervised_warps.push_back(i);
+ }
+ void cycle();
+private:
+ shd_warp_t& warp(int i);
+
+ std::vector<int> supervised_warps;
+ int m_last_sup_id_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;
+ warp_inst_t** m_sp_out;
+ warp_inst_t** m_sfu_out;
+ warp_inst_t** m_mem_out;
+};
+
+
+
+
class opndcoll_rfu_t { // operand collector based register file unit
public:
@@ -985,6 +1023,9 @@ struct shader_core_config : public core_config
cache_config m_L1D_config;
bool gpgpu_dwf_reg_bankconflict;
+
+ int gpgpu_num_sched_per_core;
+
//op collector
int gpgpu_operand_collector_num_units_sp;
int gpgpu_operand_collector_num_units_sfu;
@@ -1079,6 +1120,7 @@ private:
friend class shader_core_ctx;
friend class ldst_unit;
friend class simt_core_cluster;
+ friend class scheduler_unit;
};
class shader_core_mem_fetch_allocator : public mem_fetch_allocator {
@@ -1195,6 +1237,7 @@ private:
void register_cta_thread_exit( unsigned cta_num );
void decode();
+ friend class scheduler_unit; //this is needed to use private issue warp.
void issue_warp( warp_inst_t *&warp, const warp_inst_t *pI, const active_mask_t &active_mask, unsigned warp_id );
void func_exec_inst( warp_inst_t &inst );
address_type translate_local_memaddr(address_type localaddr, unsigned tid, unsigned num_shader );
@@ -1241,7 +1284,6 @@ private:
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;
@@ -1249,7 +1291,10 @@ private:
warp_inst_t **m_pipeline_reg;
Scoreboard *m_scoreboard;
opndcoll_rfu_t m_operand_collector;
-
+
+ //schedule
+ std::vector<scheduler_unit> schedulers;
+
// execute
unsigned m_num_function_units;
enum pipeline_stage_name_t *m_dispatch_port;