summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--aerialvision/guiclasses.py13
-rw-r--r--aerialvision/lexyacc.py2
-rw-r--r--aerialvision/organizedata.py9
-rw-r--r--configs/GTX480/gpgpusim.config13
-rw-r--r--configs/QuadroFX5800/gpgpusim.config5
-rw-r--r--configs/TeslaC2050/gpgpusim.config12
-rw-r--r--cuobjdump_to_ptxplus/ptx_parser.h103
-rw-r--r--src/Makefile5
-rw-r--r--src/cuda-sim/Makefile5
-rw-r--r--src/cuda-sim/cuda-sim.cc16
-rw-r--r--src/cuda-sim/cuda-sim.h1
-rw-r--r--src/cuda-sim/ptx_ir.cc51
-rw-r--r--src/cuda-sim/ptx_ir.h2
-rw-r--r--src/cuda-sim/ptx_parser.cc82
-rw-r--r--src/gpgpu-sim/Makefile5
-rw-r--r--src/gpgpu-sim/gpu-sim.cc25
-rw-r--r--src/gpgpu-sim/gpu-sim.h3
-rw-r--r--src/gpgpu-sim/scoreboard.cc40
-rw-r--r--src/gpgpu-sim/scoreboard.h1
-rw-r--r--src/gpgpu-sim/shader.cc806
-rw-r--r--src/gpgpu-sim/shader.h206
-rw-r--r--src/gpgpu-sim/shader_trace.h74
-rw-r--r--src/trace.cc55
-rw-r--r--src/trace.h79
-rw-r--r--src/trace_streams.tup32
26 files changed, 1202 insertions, 445 deletions
diff --git a/Makefile b/Makefile
index aa80c9f..7a9c9bd 100644
--- a/Makefile
+++ b/Makefile
@@ -37,6 +37,8 @@ else
export DEBUG=0
endif
+export TRACE?=1
+
NVCC_PATH=$(shellwhich nvcc)
ifneq ($(shell which nvcc), "")
ifeq ($(DEBUG), 1)
diff --git a/aerialvision/guiclasses.py b/aerialvision/guiclasses.py
index 7e2379b..0a7013b 100644
--- a/aerialvision/guiclasses.py
+++ b/aerialvision/guiclasses.py
@@ -1049,6 +1049,19 @@ class graphManager:
Legendname.append('W' + `4*(c-2)+1` + ':' + `4*(c-1)`)
BarSequence = range(0,numRows)
+ if yAxis == 'WarpIssueSlotBreakdown':
+ Legendname = []
+ for c in range(0, numRows):
+ Legendname.append('W' + `c`)
+ BarSequence = range(0,numRows)
+
+ dynamic_warp_resolution = 32
+ if yAxis == 'WarpIssueDynamicIdBreakdown':
+ Legendname = []
+ for c in range(0, numRows):
+ Legendname.append('W' + `dynamic_warp_resolution*c` + ":" + `dynamic_warp_resolution*(c+1)`)
+ BarSequence = range(0,numRows)
+
yoff_max = numpy.array([0.0] * numCols)
for row in range(numRows-1,-1,-1):
yoff_max += y[row]
diff --git a/aerialvision/lexyacc.py b/aerialvision/lexyacc.py
index c434619..de4e732 100644
--- a/aerialvision/lexyacc.py
+++ b/aerialvision/lexyacc.py
@@ -176,6 +176,8 @@ def parseMe(filename):
'LDmemlatdist':vc.variable('', 3, 0, 'stackbar'),
'STmemlatdist':vc.variable('', 3, 0, 'stackbar'),
'WarpDivergenceBreakdown':vc.variable('', 3, 0, 'stackbar'),
+ 'WarpIssueSlotBreakdown':vc.variable('', 3, 0, 'stackbar'),
+ 'WarpIssueDynamicIdBreakdown':vc.variable('', 3, 0, 'stackbar'),
'dram_writes_per_cycle':vc.variable('', 1, 0, 'scalar', float),
'dram_reads_per_cycle' :vc.variable('', 1, 0, 'scalar', float),
'gpu_stall_by_MSHRwb':vc.variable('', 1, 0, 'scalar'),
diff --git a/aerialvision/organizedata.py b/aerialvision/organizedata.py
index 0b547b3..090b90f 100644
--- a/aerialvision/organizedata.py
+++ b/aerialvision/organizedata.py
@@ -193,12 +193,12 @@ def nullOrganizedShader(nullVar, datatype_c):
organized = []
#determining how many shader cores are present
- for x in nullVar:
+ for x in reversed(nullVar):
if x != 'NULL':
count += 1
- else:
- numPlots = count
+ elif count != 0:
break
+ numPlots = count
count = 0
#initializing 2D list
@@ -208,6 +208,9 @@ def nullOrganizedShader(nullVar, datatype_c):
#filling up list appropriately
for x in range(0,(len(nullVar))):
if nullVar[x] == 'NULL':
+ while count < numPlots:
+ organized[count].append(0)
+ count += 1
count=0
else:
organized[count].append(nullVar[x])
diff --git a/configs/GTX480/gpgpusim.config b/configs/GTX480/gpgpusim.config
index 9a295a3..62dd078 100644
--- a/configs/GTX480/gpgpusim.config
+++ b/configs/GTX480/gpgpusim.config
@@ -103,10 +103,12 @@
# Fermi has two schedulers per core
-gpgpu_num_sched_per_core 2
-# Two Level Scheduler
-#-gpgpu_scheduler tl:16
+# Two Level Scheduler with active and pending pools
+#-gpgpu_scheduler two_level_active:6:0:1
# Loose round robbin scheduler
--gpgpu_scheduler lrr
+#-gpgpu_scheduler lrr
+# Greedy then oldest scheduler
+-gpgpu_scheduler gto
# stat collection
-gpgpu_memlatency_stat 14
@@ -117,3 +119,8 @@
# power model configs
-power_simulation_enabled 1
-gpuwattch_xml_file gpuwattch_gtx480.xml
+
+# tracing functionality
+#-trace_enabled 1
+#-trace_components WARP_SCHEDULER,SCOREBOARD
+#-trace_sampling_core 0
diff --git a/configs/QuadroFX5800/gpgpusim.config b/configs/QuadroFX5800/gpgpusim.config
index 7a2a151..81a5f1f 100644
--- a/configs/QuadroFX5800/gpgpusim.config
+++ b/configs/QuadroFX5800/gpgpusim.config
@@ -72,3 +72,8 @@
-gpgpu_operand_collector_num_units_sfu 8
-visualizer_enabled 0
+
+# tracing functionality
+#-trace_enabled 1
+#-trace_components WARP_SCHEDULER,SCOREBOARD
+#-trace_sampling_core 0
diff --git a/configs/TeslaC2050/gpgpusim.config b/configs/TeslaC2050/gpgpusim.config
index e161b43..3100cbc 100644
--- a/configs/TeslaC2050/gpgpusim.config
+++ b/configs/TeslaC2050/gpgpusim.config
@@ -106,10 +106,12 @@
# Fermi has two schedulers per core
-gpgpu_num_sched_per_core 2
-# Two Level Scheduler
-#-gpgpu_scheduler tl:16
+# Two Level Scheduler with active and pending pools
+#-gpgpu_scheduler two_level_active:6:0:1
# Loose round robbin scheduler
--gpgpu_scheduler lrr
+#-gpgpu_scheduler lrr
+# Greedy then oldest scheduler
+-gpgpu_scheduler gto
# stat collection
-gpgpu_memlatency_stat 14
@@ -117,3 +119,7 @@
-enable_ptx_file_line_stats 1
-visualizer_enabled 0
+# tracing functionality
+#-trace_enabled 1
+#-trace_components WARP_SCHEDULER,SCOREBOARD
+#-trace_sampling_core 0
diff --git a/cuobjdump_to_ptxplus/ptx_parser.h b/cuobjdump_to_ptxplus/ptx_parser.h
index f8b922b..1c96b46 100644
--- a/cuobjdump_to_ptxplus/ptx_parser.h
+++ b/cuobjdump_to_ptxplus/ptx_parser.h
@@ -45,7 +45,7 @@
#define ARRAY_IDENTIFIER_NO_DIM 2
#define ARRAY_IDENTIFIER 3
#define P_DEBUG 0
-#define DPRINTF(...) \
+#define PTX_PARSE_DPRINTF(...) \
if(P_DEBUG) { \
printf("(%s:%s:%u) ", __FILE__, __FUNCTION__, __LINE__); \
printf(__VA_ARGS__); \
@@ -53,7 +53,6 @@
fflush(stdout); \
}
-
enum _memory_space_t {
undefined_space=0,
reg_space,
@@ -73,43 +72,43 @@ int g_error_detected;
const char *g_filename = "";
int g_func_decl;
-void set_symtab( void* a ) {DPRINTF(" ");}
-void end_function() {DPRINTF(" ");}
-void add_directive() {DPRINTF(" ");}
-void add_function_arg() {DPRINTF(" ");}
-void add_instruction() {DPRINTF(" ");}
-void add_file( unsigned a, const char *b ) {DPRINTF(" ");}
-void add_variables() {DPRINTF(" ");}
-void set_variable_type() {DPRINTF(" ");}
-void add_option(int a ) {DPRINTF(" ");}
-void add_array_initializer() {DPRINTF(" ");}
-void add_label( const char *a ) {DPRINTF(" ");}
-void set_return() {DPRINTF(" ");}
-void add_opcode( int a ) {DPRINTF(" ");}
-void add_pred( const char *a, int b, int c ) {DPRINTF(" ");}
-void add_scalar_operand( const char *a ) {DPRINTF("%s", a);}
-void add_neg_pred_operand( const char *a ) {DPRINTF(" ");}
-void add_address_operand( const char *a, int b ) {DPRINTF("%s", a);}
-void add_address_operand2( int b ) {DPRINTF(" ");}
-void change_operand_lohi( int a ) {DPRINTF(" ");}
-void change_double_operand_type( int a ) {DPRINTF(" ");}
-void change_operand_neg( ) {DPRINTF(" ");}
-void add_double_operand( const char *a, const char *b ) {DPRINTF(" ");}
-void add_1vector_operand( const char *a ) {DPRINTF(" ");}
-void add_2vector_operand( const char *a, const char *b ) {DPRINTF(" ");}
-void add_3vector_operand( const char *a, const char *b, const char *c ) {DPRINTF(" ");}
-void add_4vector_operand( const char *a, const char *b, const char *c, const char *d ) {DPRINTF(" ");}
-void add_builtin_operand( int a, int b ) {DPRINTF(" ");}
-void add_memory_operand() {DPRINTF(" ");}
-void change_memory_addr_space( const char *a ) {DPRINTF(" ");}
-void add_literal_int( int a ) {DPRINTF(" ");}
-void add_literal_float( float a ) {DPRINTF(" ");}
-void add_literal_double( double a ) {DPRINTF(" ");}
-void add_ptr_spec( enum _memory_space_t spec ) {DPRINTF(" ");}
-void add_extern_spec() {DPRINTF(" ");}
-void add_alignment_spec( int ) {DPRINTF(" ");}
-void add_pragma( const char *a ) {DPRINTF(" ");}
-void add_constptr(const char* identifier1, const char* identifier2, int offset) {DPRINTF(" ");}
+void set_symtab( void* a ) {PTX_PARSE_DPRINTF(" ");}
+void end_function() {PTX_PARSE_DPRINTF(" ");}
+void add_directive() {PTX_PARSE_DPRINTF(" ");}
+void add_function_arg() {PTX_PARSE_DPRINTF(" ");}
+void add_instruction() {PTX_PARSE_DPRINTF(" ");}
+void add_file( unsigned a, const char *b ) {PTX_PARSE_DPRINTF(" ");}
+void add_variables() {PTX_PARSE_DPRINTF(" ");}
+void set_variable_type() {PTX_PARSE_DPRINTF(" ");}
+void add_option(int a ) {PTX_PARSE_DPRINTF(" ");}
+void add_array_initializer() {PTX_PARSE_DPRINTF(" ");}
+void add_label( const char *a ) {PTX_PARSE_DPRINTF(" ");}
+void set_return() {PTX_PARSE_DPRINTF(" ");}
+void add_opcode( int a ) {PTX_PARSE_DPRINTF(" ");}
+void add_pred( const char *a, int b, int c ) {PTX_PARSE_DPRINTF(" ");}
+void add_scalar_operand( const char *a ) {PTX_PARSE_DPRINTF("%s", a);}
+void add_neg_pred_operand( const char *a ) {PTX_PARSE_DPRINTF(" ");}
+void add_address_operand( const char *a, int b ) {PTX_PARSE_DPRINTF("%s", a);}
+void add_address_operand2( int b ) {PTX_PARSE_DPRINTF(" ");}
+void change_operand_lohi( int a ) {PTX_PARSE_DPRINTF(" ");}
+void change_double_operand_type( int a ) {PTX_PARSE_DPRINTF(" ");}
+void change_operand_neg( ) {PTX_PARSE_DPRINTF(" ");}
+void add_double_operand( const char *a, const char *b ) {PTX_PARSE_DPRINTF(" ");}
+void add_1vector_operand( const char *a ) {PTX_PARSE_DPRINTF(" ");}
+void add_2vector_operand( const char *a, const char *b ) {PTX_PARSE_DPRINTF(" ");}
+void add_3vector_operand( const char *a, const char *b, const char *c ) {PTX_PARSE_DPRINTF(" ");}
+void add_4vector_operand( const char *a, const char *b, const char *c, const char *d ) {PTX_PARSE_DPRINTF(" ");}
+void add_builtin_operand( int a, int b ) {PTX_PARSE_DPRINTF(" ");}
+void add_memory_operand() {PTX_PARSE_DPRINTF(" ");}
+void change_memory_addr_space( const char *a ) {PTX_PARSE_DPRINTF(" ");}
+void add_literal_int( int a ) {PTX_PARSE_DPRINTF(" ");}
+void add_literal_float( float a ) {PTX_PARSE_DPRINTF(" ");}
+void add_literal_double( double a ) {PTX_PARSE_DPRINTF(" ");}
+void add_ptr_spec( enum _memory_space_t spec ) {PTX_PARSE_DPRINTF(" ");}
+void add_extern_spec() {PTX_PARSE_DPRINTF(" ");}
+void add_alignment_spec( int ) {PTX_PARSE_DPRINTF(" ");}
+void add_pragma( const char *a ) {PTX_PARSE_DPRINTF(" ");}
+void add_constptr(const char* identifier1, const char* identifier2, int offset) {PTX_PARSE_DPRINTF(" ");}
/*non-dummy stuff below this point*/
@@ -127,7 +126,7 @@ bool inTexDirective = false;
void add_identifier( const char *a, int b, unsigned c ) {
- DPRINTF("name=%s", a);
+ PTX_PARSE_DPRINTF("name=%s", a);
if(inConstDirective){
//g_headerList->getListEnd()
}
@@ -135,7 +134,7 @@ void add_identifier( const char *a, int b, unsigned c ) {
void add_function_name( const char *headerInput )
{
- DPRINTF("name=%s", headerInput);
+ PTX_PARSE_DPRINTF("name=%s", headerInput);
char* headerInfo = (char*) headerInput;
std::string compareString = g_headerList->getListEnd().getBase();
@@ -149,7 +148,7 @@ void add_function_name( const char *headerInput )
//void add_space_spec(int headerInput)
void add_space_spec( enum _memory_space_t spec, int value )
{
- DPRINTF("spec=%u", spec);
+ PTX_PARSE_DPRINTF("spec=%u", spec);
cuobjdumpInst *instEntry;
//static int constmemindex=1;
switch(spec)
@@ -187,7 +186,7 @@ void add_space_spec( enum _memory_space_t spec, int value )
void add_scalar_type_spec( int headerInput )
{
- DPRINTF(" ");
+ PTX_PARSE_DPRINTF(" ");
//const char* compareString = g_headerList->getListEnd().getBase();
if( (inEntryDirective && inParamDirective) || inTexDirective || inConstDirective)
@@ -252,7 +251,7 @@ void add_scalar_type_spec( int headerInput )
//void version_header(double versionNumber)
void add_version_info( float versionNumber, unsigned ext)
{
- DPRINTF(" ");
+ PTX_PARSE_DPRINTF(" ");
cuobjdumpInst *instEntry = new cuobjdumpInst();
instEntry->setBase(".version");
g_headerList->add(instEntry);
@@ -269,7 +268,7 @@ void add_version_info( float versionNumber, unsigned ext)
void target_header(char* firstTarget)
{
- DPRINTF("%s", firstTarget);
+ PTX_PARSE_DPRINTF("%s", firstTarget);
cuobjdumpInst *instEntry = new cuobjdumpInst();
instEntry->setBase(".target");
g_headerList->add(instEntry);
@@ -279,7 +278,7 @@ void target_header(char* firstTarget)
void target_header2(char* firstTarget, char* secondTarget)
{
- DPRINTF("%s, %s", firstTarget, secondTarget);
+ PTX_PARSE_DPRINTF("%s, %s", firstTarget, secondTarget);
cuobjdumpInst *instEntry = new cuobjdumpInst();
instEntry->setBase(".target");
g_headerList->add(instEntry);
@@ -291,7 +290,7 @@ void target_header2(char* firstTarget, char* secondTarget)
void target_header3(char* firstTarget, char* secondTarget, char* thirdTarget)
{
- DPRINTF("%s, %s, %s", firstTarget, secondTarget, thirdTarget);
+ PTX_PARSE_DPRINTF("%s, %s, %s", firstTarget, secondTarget, thirdTarget);
cuobjdumpInst *instEntry = new cuobjdumpInst();
instEntry->setBase(".target");
g_headerList->add(instEntry);
@@ -305,20 +304,20 @@ void target_header3(char* firstTarget, char* secondTarget, char* thirdTarget)
void start_function( int a )
{
- DPRINTF(" ");
+ PTX_PARSE_DPRINTF(" ");
inEntryDirective = true;
}
void* reset_symtab()
{
- DPRINTF(" ");
+ PTX_PARSE_DPRINTF(" ");
inEntryDirective = false;
return (void*) NULL;
}
void func_header(const char* headerBase)
{
- DPRINTF("%s", headerBase);
+ PTX_PARSE_DPRINTF("%s", headerBase);
// If start of an entry
if((strcmp(headerBase, ".entry")==0)||(strcmp(headerBase, ".func")==0)) {
inEntryDirective = true;
@@ -332,7 +331,7 @@ void func_header(const char* headerBase)
void func_header_info(const char* headerInfo)
{
- DPRINTF("%s", headerInfo);
+ PTX_PARSE_DPRINTF("%s", headerInfo);
//const char* compareString = g_headerList->getListEnd().getBase();
if(inEntryDirective && !inTexDirective) {
@@ -360,7 +359,7 @@ void func_header_info(const char* headerInfo)
void func_header_info_int(const char* s, int i)
{
- DPRINTF("%s %d", s, i);
+ PTX_PARSE_DPRINTF("%s %d", s, i);
if(inEntryDirective && !inTexDirective) {
g_headerList->getListEnd().addOperand(s);
char *buff = (char*) malloc(30*sizeof(char));
diff --git a/src/Makefile b/src/Makefile
index b20186c..cc31764 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -30,6 +30,7 @@
# GPGPU-Sim Makefile
DEBUG?=0
+TRACE?=1
include ../version_detection.mk
@@ -40,6 +41,10 @@ ifeq ($(GNUC_CPP0X), 1)
CXXFLAGS += -std=c++0x
endif
+ifeq ($(TRACE),1)
+ CXXFLAGS += -DTRACING_ON=1
+endif
+
ifneq ($(DEBUG),1)
OPTFLAGS += -O3
else
diff --git a/src/cuda-sim/Makefile b/src/cuda-sim/Makefile
index 3062d99..9e37fe7 100644
--- a/src/cuda-sim/Makefile
+++ b/src/cuda-sim/Makefile
@@ -30,6 +30,7 @@ default: libgpgpu_ptx_sim.a
INTEL=0
DEBUG?=0
+TRACE?=0
CPP = g++ $(SNOW)
CC = gcc $(SNOW)
@@ -47,6 +48,10 @@ endif
OPT += -I$(CUDA_INSTALL_PATH)/include
OPT += -fPIC
+ifeq ($(TRACE),1)
+ OPT += -DTRACING_ON=1
+endif
+
CXX_OPT = $(OPT)
ifeq ($(INTEL),1)
CXX_OPT += -std=c++0x
diff --git a/src/cuda-sim/cuda-sim.cc b/src/cuda-sim/cuda-sim.cc
index cf64e82..1dbff50 100644
--- a/src/cuda-sim/cuda-sim.cc
+++ b/src/cuda-sim/cuda-sim.cc
@@ -450,6 +450,22 @@ void ptx_print_insn( address_type pc, FILE *fp )
assert( finfo );
finfo->print_insn(pc,fp);
}
+
+std::string ptx_get_insn_str( address_type pc )
+{
+ std::map<unsigned,function_info*>::iterator f = g_pc_to_finfo.find(pc);
+ if( f == g_pc_to_finfo.end() ) {
+ #define STR_SIZE 255
+ char buff[STR_SIZE];
+ buff[STR_SIZE - 1] = '\0';
+ snprintf(buff, STR_SIZE,"<no instruction at address 0x%x>", pc );
+ return std::string(buff);
+ }
+ function_info *finfo = f->second;
+ assert( finfo );
+ return finfo->get_insn_str(pc);
+}
+
void ptx_instruction::set_fp_or_int_archop(){
op2=UN_OP;
if((m_opcode == MEMBAR_OP)||(m_opcode == SSY_OP )||(m_opcode == BRA_OP) || (m_opcode == BAR_OP) || (m_opcode == RET_OP) || (m_opcode == RETP_OP) || (m_opcode == NOP_OP) || (m_opcode == EXIT_OP) || (m_opcode == CALLP_OP) || (m_opcode == CALL_OP)){
diff --git a/src/cuda-sim/cuda-sim.h b/src/cuda-sim/cuda-sim.h
index bcc36d1..261d458 100644
--- a/src/cuda-sim/cuda-sim.h
+++ b/src/cuda-sim/cuda-sim.h
@@ -75,6 +75,7 @@ unsigned ptx_sim_init_thread( kernel_info_t &kernel,
const warp_inst_t *ptx_fetch_inst( address_type pc );
const struct gpgpu_ptx_sim_kernel_info* ptx_sim_kernel_info(const class function_info *kernel);
void ptx_print_insn( address_type pc, FILE *fp );
+std::string ptx_get_insn_str( address_type pc );
void set_param_gpgpu_num_shaders(int num_shaders);
diff --git a/src/cuda-sim/ptx_ir.cc b/src/cuda-sim/ptx_ir.cc
index 29f6ff4..0dffe70 100644
--- a/src/cuda-sim/ptx_ir.cc
+++ b/src/cuda-sim/ptx_ir.cc
@@ -35,9 +35,12 @@
#include <list>
#include <assert.h>
#include <algorithm>
+#include "assert.h"
#include "cuda-sim.h"
+#define STR_SIZE 1024
+
unsigned symbol::sm_next_uid = 1;
unsigned symbol::get_uid()
@@ -1188,14 +1191,26 @@ void ptx_instruction::print_insn() const
void ptx_instruction::print_insn( FILE *fp ) const
{
- char buf[1024], *p;
- snprintf(buf,1024,"%s", m_source.c_str());
- p = strtok(buf,";");
- if( !is_label() )
- fprintf(fp," PC=0x%03x ", m_PC );
- else
- fprintf(fp," " );
- fprintf(fp,"(%s:%u) %s", m_source_file.c_str(), m_source_line, p );
+ fprintf( fp, to_string().c_str() );
+}
+
+std::string ptx_instruction::to_string() const
+{
+ std::string result( m_source );
+ unsigned semi_c_pos = result.find(";");
+ assert( semi_c_pos != std::string::npos );
+ if( !is_label() ) {
+ char buf[ STR_SIZE ];
+ buf[ STR_SIZE - 1 ] = '\0';
+ snprintf( buf, STR_SIZE, " PC=0x%03x ", m_PC );
+ result += std::string( buf );
+ } else
+ result += std::string(" ");
+ char buf[STR_SIZE];
+ buf[STR_SIZE - 1] = '\0';
+ snprintf( buf, STR_SIZE,
+ "(%s:%d) %s", m_source_file.c_str(), m_source_line, m_source.c_str() + semi_c_pos );
+ return result;
}
unsigned function_info::sm_next_uid = 1;
@@ -1240,6 +1255,26 @@ unsigned function_info::print_insn( unsigned pc, FILE * fp ) const
return inst_size;
}
+std::string function_info::get_insn_str( unsigned pc ) const
+{
+ unsigned index = pc - m_start_PC;
+ if ( index >= m_instr_mem_size ) {
+ char buff[STR_SIZE];
+ buff[STR_SIZE-1] = '\0';
+ snprintf(buff, STR_SIZE, "<past last instruction (max pc=%u)>", m_start_PC + m_instr_mem_size - 1 );
+ return std::string(buff);
+ } else {
+ if ( m_instr_mem[index] != NULL ) {
+ return m_instr_mem[index]->to_string();
+ } else {
+ char buff[STR_SIZE];
+ buff[STR_SIZE-1] = '\0';
+ snprintf(buff, STR_SIZE, "<no instruction at pc = %u>", pc );
+ return std::string(buff);
+ }
+ }
+}
+
void gpgpu_ptx_assemble( std::string kname, void *kinfo )
{
function_info *func_info = (function_info *)kinfo;
diff --git a/src/cuda-sim/ptx_ir.h b/src/cuda-sim/ptx_ir.h
index 547372d..9a24e47 100644
--- a/src/cuda-sim/ptx_ir.h
+++ b/src/cuda-sim/ptx_ir.h
@@ -786,6 +786,7 @@ public:
void print_insn() const;
virtual void print_insn( FILE *fp ) const;
+ std::string to_string() const;
unsigned inst_size() const { return m_inst_size; }
unsigned uid() const { return m_uid;}
int get_opcode() const { return m_opcode;}
@@ -1052,6 +1053,7 @@ public:
return m_name;
}
unsigned print_insn( unsigned pc, FILE * fp ) const;
+ std::string get_insn_str( unsigned pc ) const;
void add_inst( const std::list<ptx_instruction*> &instructions )
{
m_instructions = instructions;
diff --git a/src/cuda-sim/ptx_parser.cc b/src/cuda-sim/ptx_parser.cc
index d33007b..a02832d 100644
--- a/src/cuda-sim/ptx_parser.cc
+++ b/src/cuda-sim/ptx_parser.cc
@@ -74,7 +74,7 @@ std::list<operand_info> g_operands;
std::list<int> g_options;
std::list<int> g_scalar_type;
-#define DPRINTF(...) \
+#define PTX_PARSE_DPRINTF(...) \
if( g_debug_ir_generation ) { \
printf(" %s:%u => ",g_filename,ptx_lineno); \
printf(" (%s:%u) ", __FILE__, __LINE__); \
@@ -126,7 +126,7 @@ symbol_table *init_parser( const char *ptx_filename )
void init_directive_state()
{
- DPRINTF("init_directive_state");
+ PTX_PARSE_DPRINTF("init_directive_state");
g_space_spec=undefined_space;
g_ptr_spec=undefined_space;
g_scalar_type_spec=-1;
@@ -141,7 +141,7 @@ void init_directive_state()
void init_instruction_state()
{
- DPRINTF("init_instruction_state");
+ PTX_PARSE_DPRINTF("init_instruction_state");
g_pred = NULL;
g_neg_pred = 0;
g_pred_mod = -1;
@@ -156,7 +156,7 @@ static int g_entry_point;
void start_function( int entry_point )
{
- DPRINTF("start_function");
+ PTX_PARSE_DPRINTF("start_function");
init_directive_state();
init_instruction_state();
g_entry_point = entry_point;
@@ -170,7 +170,7 @@ int g_add_identifier_cached__array_ident;
void add_function_name( const char *name )
{
- DPRINTF("add_function_name %s %s", name, ((g_entry_point==1)?"(entrypoint)":((g_entry_point==2)?"(extern)":"")));
+ PTX_PARSE_DPRINTF("add_function_name %s %s", name, ((g_entry_point==1)?"(entrypoint)":((g_entry_point==2)?"(extern)":"")));
bool prior_decl = g_global_symbol_table->add_function_decl( name, g_entry_point, &g_func_info, &g_current_symbol_table );
if( g_add_identifier_cached__identifier ) {
add_identifier( g_add_identifier_cached__identifier,
@@ -189,7 +189,7 @@ void add_function_name( const char *name )
void add_directive()
{
- DPRINTF("add_directive");
+ PTX_PARSE_DPRINTF("add_directive");
init_directive_state();
}
@@ -197,7 +197,7 @@ void add_directive()
void end_function()
{
- DPRINTF("end_function");
+ PTX_PARSE_DPRINTF("end_function");
init_directive_state();
init_instruction_state();
@@ -207,7 +207,7 @@ void end_function()
gpgpu_ptx_assemble( g_func_info->get_name(), g_func_info );
g_current_symbol_table = g_global_symbol_table;
- DPRINTF("function %s, PC = %d\n", g_func_info->get_name().c_str(), g_func_info->get_start_PC());
+ PTX_PARSE_DPRINTF("function %s, PC = %d\n", g_func_info->get_name().c_str(), g_func_info->get_start_PC());
}
#define parse_error(msg, ...) parse_error_impl(__FILE__,__LINE__, msg, ##__VA_ARGS__)
@@ -265,7 +265,7 @@ const ptx_instruction *ptx_instruction_lookup( const char *filename, unsigned li
void add_instruction()
{
- DPRINTF("add_instruction: %s", ((g_opcode>0)?g_opcode_string[g_opcode]:"<label>") );
+ PTX_PARSE_DPRINTF("add_instruction: %s", ((g_opcode>0)?g_opcode_string[g_opcode]:"<label>") );
assert( g_shader_core_config != 0 );
ptx_instruction *i = new ptx_instruction( g_opcode,
g_pred,
@@ -288,7 +288,7 @@ void add_instruction()
void add_variables()
{
- DPRINTF("add_variables");
+ PTX_PARSE_DPRINTF("add_variables");
if ( !g_operands.empty() ) {
assert( g_last_symbol != NULL );
g_last_symbol->add_initializer(g_operands);
@@ -298,7 +298,7 @@ void add_variables()
void set_variable_type()
{
- DPRINTF("set_variable_type space_spec=%s scalar_type_spec=%s",
+ PTX_PARSE_DPRINTF("set_variable_type space_spec=%s scalar_type_spec=%s",
g_ptx_token_decode[g_space_spec.get_type()].c_str(),
g_ptx_token_decode[g_scalar_type_spec].c_str() );
parse_assert( g_space_spec != undefined_space, "variable has no space specification" );
@@ -333,7 +333,7 @@ void add_identifier( const char *identifier, int array_dim, unsigned array_ident
g_add_identifier_cached__array_ident = array_ident;
return;
}
- DPRINTF("add_identifier \"%s\" (%u)", identifier, g_ident_add_uid);
+ PTX_PARSE_DPRINTF("add_identifier \"%s\" (%u)", identifier, g_ident_add_uid);
g_ident_add_uid++;
type_info *type = g_var_type;
type_info_key ti = type->get_key();
@@ -501,27 +501,27 @@ void add_constptr(const char* identifier1, const char* identifier2, int offset)
void add_function_arg()
{
if( g_func_info ) {
- DPRINTF("add_function_arg \"%s\"", g_last_symbol->name().c_str() );
+ PTX_PARSE_DPRINTF("add_function_arg \"%s\"", g_last_symbol->name().c_str() );
g_func_info->add_arg(g_last_symbol);
}
}
void add_extern_spec()
{
- DPRINTF("add_extern_spec");
+ PTX_PARSE_DPRINTF("add_extern_spec");
g_extern_spec = 1;
}
void add_alignment_spec( int spec )
{
- DPRINTF("add_alignment_spec");
+ PTX_PARSE_DPRINTF("add_alignment_spec");
parse_assert( g_alignment_spec == -1, "multiple .align specifiers per variable declaration not allowed." );
g_alignment_spec = spec;
}
void add_ptr_spec( enum _memory_space_t spec )
{
- DPRINTF("add_ptr_spec \"%s\"", g_ptx_token_decode[spec].c_str() );
+ PTX_PARSE_DPRINTF("add_ptr_spec \"%s\"", g_ptx_token_decode[spec].c_str() );
parse_assert( g_ptr_spec == undefined_space, "multiple ptr space specifiers not allowed." );
parse_assert( spec == global_space or spec == local_space or spec == shared_space, "invalid space for ptr directive." );
g_ptr_spec = spec;
@@ -529,7 +529,7 @@ void add_ptr_spec( enum _memory_space_t spec )
void add_space_spec( enum _memory_space_t spec, int value )
{
- DPRINTF("add_space_spec \"%s\"", g_ptx_token_decode[spec].c_str() );
+ PTX_PARSE_DPRINTF("add_space_spec \"%s\"", g_ptx_token_decode[spec].c_str() );
parse_assert( g_space_spec == undefined_space, "multiple space specifiers not allowed." );
if( spec == param_space_unclassified ) {
if( g_func_decl ) {
@@ -548,14 +548,14 @@ void add_space_spec( enum _memory_space_t spec, int value )
void add_vector_spec(int spec )
{
- DPRINTF("add_vector_spec");
+ PTX_PARSE_DPRINTF("add_vector_spec");
parse_assert( g_vector_spec == -1, "multiple vector specifiers not allowed." );
g_vector_spec = spec;
}
void add_scalar_type_spec( int type_spec )
{
- DPRINTF("add_scalar_type_spec \"%s\"", g_ptx_token_decode[type_spec].c_str());
+ PTX_PARSE_DPRINTF("add_scalar_type_spec \"%s\"", g_ptx_token_decode[type_spec].c_str());
g_scalar_type.push_back( type_spec );
if ( g_scalar_type.size() > 1 ) {
parse_assert( (g_opcode == -1) || (g_opcode == CVT_OP) || (g_opcode == SET_OP) || (g_opcode == SLCT_OP)
@@ -567,7 +567,7 @@ void add_scalar_type_spec( int type_spec )
void add_label( const char *identifier )
{
- DPRINTF("add_label");
+ PTX_PARSE_DPRINTF("add_label");
symbol *s = g_current_symbol_table->lookup(identifier);
if ( s != NULL ) {
g_label = s;
@@ -583,7 +583,7 @@ void add_opcode( int opcode )
void add_pred( const char *identifier, int neg, int predModifier )
{
- DPRINTF("add_pred");
+ PTX_PARSE_DPRINTF("add_pred");
const symbol *s = g_current_symbol_table->lookup(identifier);
if ( s == NULL ) {
std::string msg = std::string("predicate \"") + identifier + "\" has no declaration.";
@@ -596,7 +596,7 @@ void add_pred( const char *identifier, int neg, int predModifier )
void add_option( int option )
{
- DPRINTF("add_option");
+ PTX_PARSE_DPRINTF("add_option");
g_options.push_back( option );
}
@@ -606,7 +606,7 @@ void add_double_operand( const char *d1, const char *d2 )
//eg. s[$ofs1+$r0], g[$ofs1+=$r0]
//TODO: Not sure if I'm going to use this for storing to two destinations or not.
- DPRINTF("add_double_operand");
+ PTX_PARSE_DPRINTF("add_double_operand");
const symbol *s1 = g_current_symbol_table->lookup(d1);
const symbol *s2 = g_current_symbol_table->lookup(d2);
parse_assert( s1 != NULL && s2 != NULL, "component(s) missing declarations.");
@@ -616,7 +616,7 @@ void add_double_operand( const char *d1, const char *d2 )
void add_1vector_operand( const char *d1 )
{
// handles the single element vector operand ({%v1}) found in tex.1d instructions
- DPRINTF("add_1vector_operand");
+ PTX_PARSE_DPRINTF("add_1vector_operand");
const symbol *s1 = g_current_symbol_table->lookup(d1);
parse_assert( s1 != NULL, "component(s) missing declarations.");
g_operands.push_back( operand_info(s1,NULL,NULL,NULL) );
@@ -624,7 +624,7 @@ void add_1vector_operand( const char *d1 )
void add_2vector_operand( const char *d1, const char *d2 )
{
- DPRINTF("add_2vector_operand");
+ PTX_PARSE_DPRINTF("add_2vector_operand");
const symbol *s1 = g_current_symbol_table->lookup(d1);
const symbol *s2 = g_current_symbol_table->lookup(d2);
parse_assert( s1 != NULL && s2 != NULL, "v2 component(s) missing declarations.");
@@ -633,7 +633,7 @@ void add_2vector_operand( const char *d1, const char *d2 )
void add_3vector_operand( const char *d1, const char *d2, const char *d3 )
{
- DPRINTF("add_3vector_operand");
+ PTX_PARSE_DPRINTF("add_3vector_operand");
const symbol *s1 = g_current_symbol_table->lookup(d1);
const symbol *s2 = g_current_symbol_table->lookup(d2);
const symbol *s3 = g_current_symbol_table->lookup(d3);
@@ -643,7 +643,7 @@ void add_3vector_operand( const char *d1, const char *d2, const char *d3 )
void add_4vector_operand( const char *d1, const char *d2, const char *d3, const char *d4 )
{
- DPRINTF("add_4vector_operand");
+ PTX_PARSE_DPRINTF("add_4vector_operand");
const symbol *s1 = g_current_symbol_table->lookup(d1);
const symbol *s2 = g_current_symbol_table->lookup(d2);
const symbol *s3 = g_current_symbol_table->lookup(d3);
@@ -658,13 +658,13 @@ void add_4vector_operand( const char *d1, const char *d2, const char *d3, const
void add_builtin_operand( int builtin, int dim_modifier )
{
- DPRINTF("add_builtin_operand");
+ PTX_PARSE_DPRINTF("add_builtin_operand");
g_operands.push_back( operand_info(builtin,dim_modifier) );
}
void add_memory_operand()
{
- DPRINTF("add_memory_operand");
+ PTX_PARSE_DPRINTF("add_memory_operand");
assert( !g_operands.empty() );
g_operands.back().make_memory_operand();
}
@@ -681,7 +681,7 @@ void change_memory_addr_space(const char *identifier)
bool recognizedType = false;
- DPRINTF("change_memory_addr_space");
+ PTX_PARSE_DPRINTF("change_memory_addr_space");
assert( !g_operands.empty() );
if(!strcmp(identifier, "g"))
{
@@ -724,7 +724,7 @@ void change_operand_lohi( int lohi )
*2 = hi, reading from highest bits
*/
- DPRINTF("change_operand_lohi");
+ PTX_PARSE_DPRINTF("change_operand_lohi");
assert( !g_operands.empty() );
g_operands.back().set_operand_lohi(lohi);
@@ -733,7 +733,7 @@ void change_operand_lohi( int lohi )
void set_immediate_operand_type ()
{
- DPRINTF("set_immediate_operand_type");
+ PTX_PARSE_DPRINTF("set_immediate_operand_type");
assert( !g_operands.empty() );
g_operands.back().set_immediate_addr();
}
@@ -750,7 +750,7 @@ void change_double_operand_type( int operand_type )
*3 = reg += immediate
*/
- DPRINTF("change_double_operand_type");
+ PTX_PARSE_DPRINTF("change_double_operand_type");
assert( !g_operands.empty() );
// For double destination operands, ensure valid instruction
@@ -772,7 +772,7 @@ void change_double_operand_type( int operand_type )
void change_operand_neg( )
{
- DPRINTF("change_operand_neg");
+ PTX_PARSE_DPRINTF("change_operand_neg");
assert( !g_operands.empty() );
g_operands.back().set_operand_neg();
@@ -781,25 +781,25 @@ void change_operand_neg( )
void add_literal_int( int value )
{
- DPRINTF("add_literal_int");
+ PTX_PARSE_DPRINTF("add_literal_int");
g_operands.push_back( operand_info(value) );
}
void add_literal_float( float value )
{
- DPRINTF("add_literal_float");
+ PTX_PARSE_DPRINTF("add_literal_float");
g_operands.push_back( operand_info(value) );
}
void add_literal_double( double value )
{
- DPRINTF("add_literal_double");
+ PTX_PARSE_DPRINTF("add_literal_double");
g_operands.push_back( operand_info(value) );
}
void add_scalar_operand( const char *identifier )
{
- DPRINTF("add_scalar_operand");
+ PTX_PARSE_DPRINTF("add_scalar_operand");
const symbol *s = g_current_symbol_table->lookup(identifier);
if ( s == NULL ) {
if ( g_opcode == BRA_OP || g_opcode == CALLP_OP) {
@@ -815,7 +815,7 @@ void add_scalar_operand( const char *identifier )
void add_neg_pred_operand( const char *identifier )
{
- DPRINTF("add_neg_pred_operand");
+ PTX_PARSE_DPRINTF("add_neg_pred_operand");
const symbol *s = g_current_symbol_table->lookup(identifier);
if ( s == NULL ) {
s = g_current_symbol_table->add_variable(identifier,NULL,1,g_filename,ptx_lineno);
@@ -827,7 +827,7 @@ void add_neg_pred_operand( const char *identifier )
void add_address_operand( const char *identifier, int offset )
{
- DPRINTF("add_address_operand");
+ PTX_PARSE_DPRINTF("add_address_operand");
const symbol *s = g_current_symbol_table->lookup(identifier);
if ( s == NULL ) {
std::string msg = std::string("operand \"") + identifier + "\" has no declaration.";
@@ -838,7 +838,7 @@ void add_address_operand( const char *identifier, int offset )
void add_address_operand2( int offset )
{
- DPRINTF("add_address_operand");
+ PTX_PARSE_DPRINTF("add_address_operand");
g_operands.push_back( operand_info((unsigned)offset) );
}
diff --git a/src/gpgpu-sim/Makefile b/src/gpgpu-sim/Makefile
index 04659aa..b9749e5 100644
--- a/src/gpgpu-sim/Makefile
+++ b/src/gpgpu-sim/Makefile
@@ -29,6 +29,7 @@
# GPGPU-Sim Makefile
DEBUG?=0
+TRACE?=0
ifeq ($(DEBUG),1)
CXXFLAGS = -Wall -DDEBUG
@@ -38,6 +39,10 @@ else
CXXFLAGS_L2CACHE = -Wall
endif
+ifeq ($(TRACE),1)
+ CXXFLAGS += -DTRACING_ON=1
+endif
+
include ../../version_detection.mk
ifeq ($(GNUC_CPP0X), 1)
diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc
index 3fa1d75..3a8cdea 100644
--- a/src/gpgpu-sim/gpu-sim.cc
+++ b/src/gpgpu-sim/gpu-sim.cc
@@ -57,6 +57,7 @@
#include "../debug.h"
#include "../gpgpusim_entrypoint.h"
#include "../cuda-sim/cuda-sim.h"
+#include "../trace.h"
#include "mem_latency_stat.h"
#include "power_stat.h"
#include "visualizer.h"
@@ -260,6 +261,9 @@ void shader_core_config::reg_options(class OptionParser * opp)
option_parser_register(opp, "-gpgpu_warpdistro_shader", OPT_INT32, &gpgpu_warpdistro_shader,
"Specify which shader core to collect the warp size distribution from",
"-1");
+ option_parser_register(opp, "-gpgpu_warp_issue_shader", OPT_INT32, &gpgpu_warp_issue_shader,
+ "Specify which shader core to collect the warp issue distribution from",
+ "0");
option_parser_register(opp, "-gpgpu_local_mem_map", OPT_BOOL, &gpgpu_local_mem_map,
"Mapping from local memory space address to simulated GPU physical address space (default = enabled)",
"1");
@@ -331,8 +335,11 @@ void shader_core_config::reg_options(class OptionParser * opp)
"Number if ldst units (default=1) WARNING: not hooked up to anything",
"1");
option_parser_register(opp, "-gpgpu_scheduler", OPT_CSTR, &gpgpu_scheduler_string,
- "Scheduler configuration: lrr|tl:num_active_warps default: lrr",
- "lrr");
+ "Scheduler configuration: < lrr | gto | two_level_active > "
+ "If two_level_active:<num_active_warps>:<inner_prioritization>:<outer_prioritization>"
+ "For complete list of prioritization values see shader.h enum scheduler_prioritization_type"
+ "Default: gto",
+ "gto");
}
void gpgpu_sim_config::reg_options(option_parser_t opp)
@@ -387,6 +394,17 @@ void gpgpu_sim_config::reg_options(option_parser_t opp)
option_parser_register(opp, "-visualizer_zlevel", OPT_INT32,
&g_visualizer_zlevel, "Compression level of the visualizer output log (0=no comp, 9=highest)",
"6");
+ option_parser_register(opp, "-trace_enabled", OPT_BOOL,
+ &Trace::enabled, "Turn on traces",
+ "0");
+ option_parser_register(opp, "-trace_components", OPT_CSTR,
+ &Trace::config_str, "comma seperated list of traces to enable. "
+ "Complete list found in trace_streams.tup. "
+ "Default none",
+ "none");
+ option_parser_register(opp, "-trace_sampling_core", OPT_INT32,
+ &Trace::sampling_core, "The core which is printed using CORE_DPRINTF. Default 0",
+ "0");
ptx_file_line_stats_options(opp);
}
@@ -770,6 +788,7 @@ void gpgpu_sim::gpu_print_stat()
printf( "gpu_total_sim_rate=%u\n", (unsigned)( ( gpu_tot_sim_insn + gpu_sim_insn ) / elapsed_time ) );
shader_print_l1_miss_stat( stdout );
+ shader_print_scheduler_stat( stdout, true );
m_shader_stats->print(stdout);
#ifdef GPGPUSIM_POWER_MODEL
@@ -1141,6 +1160,8 @@ void gpgpu_sim::cycle()
shader_print_runtime_stat( stdout );
if (m_config.gpu_runtime_stat_flag & GPU_RSTAT_L1MISS)
shader_print_l1_miss_stat( stdout );
+ if (m_config.gpu_runtime_stat_flag & GPU_RSTAT_SCHED)
+ shader_print_scheduler_stat( stdout, false );
}
}
diff --git a/src/gpgpu-sim/gpu-sim.h b/src/gpgpu-sim/gpu-sim.h
index e121030..8572092 100644
--- a/src/gpgpu-sim/gpu-sim.h
+++ b/src/gpgpu-sim/gpu-sim.h
@@ -30,6 +30,7 @@
#include "../option_parser.h"
#include "../abstract_hardware_model.h"
+#include "../trace.h"
#include "addrdec.h"
#include "shader.h"
#include <iostream>
@@ -280,6 +281,7 @@ public:
m_memory_config.init();
init_clock_domains();
power_config::init();
+ Trace::init();
// initialize file name if it is not set
@@ -416,6 +418,7 @@ private:
void L2c_print_cache_stat() const;
void shader_print_runtime_stat( FILE *fout );
void shader_print_l1_miss_stat( FILE *fout ) const;
+ void shader_print_scheduler_stat( FILE* fout, bool print_dynamic_info ) const;
void visualizer_printstat();
void print_shader_cycle_distro( FILE *fout ) const;
diff --git a/src/gpgpu-sim/scoreboard.cc b/src/gpgpu-sim/scoreboard.cc
index e2379fd..f412054 100644
--- a/src/gpgpu-sim/scoreboard.cc
+++ b/src/gpgpu-sim/scoreboard.cc
@@ -28,6 +28,7 @@
#include "scoreboard.h"
#include "shader.h"
#include "../cuda-sim/ptx_sim.h"
+#include "shader_trace.h"
//Constructor
@@ -60,6 +61,8 @@ void Scoreboard::reserveRegister(unsigned wid, unsigned regnum)
printf("Error: trying to reserve an already reserved register (sid=%d, wid=%d, regnum=%d).", m_sid, wid, regnum);
abort();
}
+ SHADER_DPRINTF( SCOREBOARD,
+ "Reserved Register - warp:%d, reg: %d\n", wid, regnum );
reg_table[wid].insert(regnum);
}
@@ -68,6 +71,8 @@ void Scoreboard::releaseRegister(unsigned wid, unsigned regnum)
{
if( !(reg_table[wid].find(regnum) != reg_table[wid].end()) )
return;
+ SHADER_DPRINTF( SCOREBOARD,
+ "Release register - warp:%d, reg: %d\n", wid, regnum );
reg_table[wid].erase(regnum);
}
@@ -77,16 +82,32 @@ const bool Scoreboard::islongop (unsigned warp_id,unsigned regnum) {
void Scoreboard::reserveRegisters(const class warp_inst_t* inst)
{
- for( unsigned r=0; r < 4; r++)
- if(inst->out[r] > 0) reserveRegister(inst->warp_id(), inst->out[r]);
+ for( unsigned r=0; r < 4; r++) {
+ if(inst->out[r] > 0) {
+ reserveRegister(inst->warp_id(), inst->out[r]);
+ SHADER_DPRINTF( SCOREBOARD,
+ "Reserved register - warp:%d, reg: %d\n",
+ inst->warp_id(),
+ inst->out[r] );
+ }
+ }
//Keep track of long operations
if (inst->is_load() &&
( inst->space.get_type() == global_space ||
inst->space.get_type() == local_space ||
+ inst->space.get_type() == param_space_kernel ||
+ inst->space.get_type() == param_space_local ||
+ inst->space.get_type() == param_space_unclassified ||
inst->space.get_type() == tex_space)){
for ( unsigned r=0; r<4; r++) {
- if(inst->out[r] > 0) longopregs[inst->warp_id()].insert(r);
+ if(inst->out[r] > 0) {
+ SHADER_DPRINTF( SCOREBOARD,
+ "New longopreg marked - warp:%d, reg: %d\n",
+ inst->warp_id(),
+ inst->out[r] );
+ longopregs[inst->warp_id()].insert(inst->out[r]);
+ }
}
}
}
@@ -94,9 +115,16 @@ void Scoreboard::reserveRegisters(const class warp_inst_t* inst)
// Release registers for an instruction
void Scoreboard::releaseRegisters(const class warp_inst_t *inst)
{
- for( unsigned r=0; r < 4; r++)
- if(inst->out[r] > 0) releaseRegister(inst->warp_id(), inst->out[r]);
- longopregs[inst->warp_id()].clear();
+ for( unsigned r=0; r < 4; r++) {
+ if(inst->out[r] > 0) {
+ SHADER_DPRINTF( SCOREBOARD,
+ "Register Released - warp:%d, reg: %d\n",
+ inst->warp_id(),
+ inst->out[r] );
+ releaseRegister(inst->warp_id(), inst->out[r]);
+ longopregs[inst->warp_id()].erase(inst->out[r]);
+ }
+ }
}
/**
diff --git a/src/gpgpu-sim/scoreboard.h b/src/gpgpu-sim/scoreboard.h
index 8559131..4a76ea3 100644
--- a/src/gpgpu-sim/scoreboard.h
+++ b/src/gpgpu-sim/scoreboard.h
@@ -50,6 +50,7 @@ public:
const bool islongop(unsigned warp_id, unsigned regnum);
private:
void reserveRegister(unsigned wid, unsigned regnum);
+ int get_sid() const { return m_sid; }
unsigned m_sid;
diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc
index 7a822b2..9d974db 100644
--- a/src/gpgpu-sim/shader.cc
+++ b/src/gpgpu-sim/shader.cc
@@ -45,9 +45,11 @@
#include "icnt_wrapper.h"
#include <string.h>
#include <limits.h>
+#include "shader_trace.h"
#define PRIORITIZE_MSHR_OVER_WB 1
#define MAX(a,b) (((a)>(b))?(a):(b))
+
/////////////////////////////////////////////////////////////////////////////
@@ -72,170 +74,213 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu,
: m_barriers( config->max_warps_per_shader, config->max_cta_per_core ),
m_dynamic_warp_id(0)
{
- m_kernel = NULL;
- m_gpu = gpu;
- m_cluster = cluster;
- m_config = config;
- m_memory_config = mem_config;
- m_stats = stats;
- unsigned warp_size=config->warp_size;
-
- m_sid = shader_id;
- m_tpc = tpc_id;
-
- m_pipeline_reg.reserve(N_PIPELINE_STAGES);
- for (int j = 0; j<N_PIPELINE_STAGES; j++) {
- m_pipeline_reg.push_back(register_set(m_config->pipe_widths[j],pipeline_stage_name_decode[j]));
- }
-
- m_threadState = (thread_ctx_t*) calloc(sizeof(thread_ctx_t), config->n_thread_per_shader);
- m_thread = (ptx_thread_info**) calloc(sizeof(ptx_thread_info*), config->n_thread_per_shader);
-
- m_not_completed = 0;
- m_active_threads.reset();
- m_n_active_cta = 0;
- for (unsigned i = 0; i<MAX_CTA_PER_SHADER; i++ )
- m_cta_status[i]=0;
- for (unsigned i = 0; i<config->n_thread_per_shader; i++) {
- m_thread[i]= NULL;
- m_threadState[i].m_cta_id = -1;
- m_threadState[i].m_active = false;
- }
-
- // m_icnt = new shader_memory_interface(this,cluster);
+ m_kernel = NULL;
+ m_gpu = gpu;
+ m_cluster = cluster;
+ m_config = config;
+ m_memory_config = mem_config;
+ m_stats = stats;
+ unsigned warp_size=config->warp_size;
+
+ m_sid = shader_id;
+ m_tpc = tpc_id;
+
+ m_pipeline_reg.reserve(N_PIPELINE_STAGES);
+ for (int j = 0; j<N_PIPELINE_STAGES; j++) {
+ m_pipeline_reg.push_back(register_set(m_config->pipe_widths[j],pipeline_stage_name_decode[j]));
+ }
+
+ m_threadState = (thread_ctx_t*) calloc(sizeof(thread_ctx_t), config->n_thread_per_shader);
+ m_thread = (ptx_thread_info**) calloc(sizeof(ptx_thread_info*), config->n_thread_per_shader);
+
+ m_not_completed = 0;
+ m_active_threads.reset();
+ m_n_active_cta = 0;
+ for ( unsigned i = 0; i<MAX_CTA_PER_SHADER; i++ )
+ m_cta_status[i]=0;
+ for (unsigned i = 0; i<config->n_thread_per_shader; i++) {
+ m_thread[i]= NULL;
+ m_threadState[i].m_cta_id = -1;
+ m_threadState[i].m_active = false;
+ }
+
+ // m_icnt = new shader_memory_interface(this,cluster);
if ( m_config->gpgpu_perfect_mem ) {
m_icnt = new perfect_memory_interface(this,cluster);
} else {
m_icnt = new shader_memory_interface(this,cluster);
}
- m_mem_fetch_allocator = new shader_core_mem_fetch_allocator(shader_id,tpc_id,mem_config);
-
- // fetch
- m_last_warp_fetched = 0;
-
- #define STRSIZE 1024
- char name[STRSIZE];
- snprintf(name, STRSIZE, "L1I_%03d", m_sid);
- m_L1I = new read_only_cache( name,m_config->m_L1I_config,m_sid,get_shader_instruction_cache_id(),m_icnt,IN_L1I_MISS_QUEUE);
-
- m_warp.resize(m_config->max_warps_per_shader, shd_warp_t(this, warp_size));
- initilizeSIMTStack(config->max_warps_per_shader,this->get_config()->warp_size);
- m_scoreboard = new Scoreboard(m_sid, m_config->max_warps_per_shader);
-
- //scedulers
- //must currently occur after all inputs have been initialized.
- std::string sched_config = m_config->gpgpu_scheduler_string;
- bool tlsched = sched_config.find("tl") != std::string::npos;
- int tlmaw;
- if (tlsched){
- sscanf(m_config->gpgpu_scheduler_string, "tl:%d", &tlmaw);
- }
- for (int i = 0; i < m_config->gpgpu_num_sched_per_core; i++) {
- //###CONFIGURATION
- if (tlsched){
- schedulers.push_back(new TwoLevelScheduler(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],
- tlmaw));
- } else {
- schedulers.push_back(new LooseRoundRobbinScheduler(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 };
- m_operand_collector.add_cu_set(SP_CUS, m_config->gpgpu_operand_collector_num_units_sp, m_config->gpgpu_operand_collector_num_out_ports_sp);
- m_operand_collector.add_cu_set(SFU_CUS, m_config->gpgpu_operand_collector_num_units_sfu, m_config->gpgpu_operand_collector_num_out_ports_sfu);
- m_operand_collector.add_cu_set(MEM_CUS, m_config->gpgpu_operand_collector_num_units_mem, m_config->gpgpu_operand_collector_num_out_ports_mem);
- m_operand_collector.add_cu_set(GEN_CUS, m_config->gpgpu_operand_collector_num_units_gen, m_config->gpgpu_operand_collector_num_out_ports_gen);
-
- opndcoll_rfu_t::port_vector_t in_ports;
- opndcoll_rfu_t::port_vector_t out_ports;
- opndcoll_rfu_t::uint_vector_t cu_sets;
- for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_sp; i++) {
- in_ports.push_back(&m_pipeline_reg[ID_OC_SP]);
- out_ports.push_back(&m_pipeline_reg[OC_EX_SP]);
- cu_sets.push_back((unsigned)SP_CUS);
- cu_sets.push_back((unsigned)GEN_CUS);
- m_operand_collector.add_port(in_ports,out_ports,cu_sets);
- in_ports.clear(),out_ports.clear(),cu_sets.clear();
- }
-
- for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_sfu; i++) {
- in_ports.push_back(&m_pipeline_reg[ID_OC_SFU]);
- out_ports.push_back(&m_pipeline_reg[OC_EX_SFU]);
- cu_sets.push_back((unsigned)SFU_CUS);
- cu_sets.push_back((unsigned)GEN_CUS);
- m_operand_collector.add_port(in_ports,out_ports,cu_sets);
- in_ports.clear(),out_ports.clear(),cu_sets.clear();
- }
-
- for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_mem; i++) {
- in_ports.push_back(&m_pipeline_reg[ID_OC_MEM]);
- out_ports.push_back(&m_pipeline_reg[OC_EX_MEM]);
- cu_sets.push_back((unsigned)MEM_CUS);
- cu_sets.push_back((unsigned)GEN_CUS);
- m_operand_collector.add_port(in_ports,out_ports,cu_sets);
- in_ports.clear(),out_ports.clear(),cu_sets.clear();
- }
-
-
- for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_gen; i++) {
- in_ports.push_back(&m_pipeline_reg[ID_OC_SP]);
- in_ports.push_back(&m_pipeline_reg[ID_OC_SFU]);
- in_ports.push_back(&m_pipeline_reg[ID_OC_MEM]);
- out_ports.push_back(&m_pipeline_reg[OC_EX_SP]);
- out_ports.push_back(&m_pipeline_reg[OC_EX_SFU]);
- out_ports.push_back(&m_pipeline_reg[OC_EX_MEM]);
- cu_sets.push_back((unsigned)GEN_CUS);
- m_operand_collector.add_port(in_ports,out_ports,cu_sets);
- in_ports.clear(),out_ports.clear(),cu_sets.clear();
- }
-
- m_operand_collector.init( m_config->gpgpu_num_reg_banks, this );
-
- // execute
- m_num_function_units = m_config->gpgpu_num_sp_units + m_config->gpgpu_num_sfu_units + 1; // sp_unit, sfu, ldst_unit
- //m_dispatch_port = new enum pipeline_stage_name_t[ m_num_function_units ];
- //m_issue_port = new enum pipeline_stage_name_t[ m_num_function_units ];
-
- //m_fu = new simd_function_unit*[m_num_function_units];
-
- for (int k = 0; k < m_config->gpgpu_num_sp_units; k++) {
- m_fu.push_back(new sp_unit( &m_pipeline_reg[EX_WB], m_config, this ));
- m_dispatch_port.push_back(ID_OC_SP);
- m_issue_port.push_back(OC_EX_SP);
- }
-
- for (int k = 0; k < m_config->gpgpu_num_sfu_units; k++) {
- m_fu.push_back(new sfu( &m_pipeline_reg[EX_WB], m_config, this ));
- m_dispatch_port.push_back(ID_OC_SFU);
- m_issue_port.push_back(OC_EX_SFU);
- }
-
- m_ldst_unit = new ldst_unit( m_icnt, m_mem_fetch_allocator, this, &m_operand_collector, m_scoreboard, config, mem_config, stats, shader_id, tpc_id );
- m_fu.push_back(m_ldst_unit);
- m_dispatch_port.push_back(ID_OC_MEM);
- m_issue_port.push_back(OC_EX_MEM);
-
- assert(m_num_function_units == m_fu.size() and m_fu.size() == m_dispatch_port.size() and m_fu.size() == m_issue_port.size());
-
- //there are as many result buses as the width of the EX_WB stage
- num_result_bus = config->pipe_widths[EX_WB];
- for(unsigned i=0; i<num_result_bus; i++){
- this->m_result_bus.push_back(new std::bitset<MAX_ALU_LATENCY>());
- }
-
- m_last_inst_gpu_sim_cycle = 0;
- m_last_inst_gpu_tot_sim_cycle = 0;
+ m_mem_fetch_allocator = new shader_core_mem_fetch_allocator(shader_id,tpc_id,mem_config);
+
+ // fetch
+ m_last_warp_fetched = 0;
+
+ #define STRSIZE 1024
+ char name[STRSIZE];
+ snprintf(name, STRSIZE, "L1I_%03d", m_sid);
+ m_L1I = new read_only_cache( name,m_config->m_L1I_config,m_sid,get_shader_instruction_cache_id(),m_icnt,IN_L1I_MISS_QUEUE);
+
+ m_warp.resize(m_config->max_warps_per_shader, shd_warp_t(this, warp_size));
+ initilizeSIMTStack(config->max_warps_per_shader,this->get_config()->warp_size);
+ m_scoreboard = new Scoreboard(m_sid, m_config->max_warps_per_shader);
+
+ //scedulers
+ //must currently occur after all inputs have been initialized.
+ std::string sched_config = m_config->gpgpu_scheduler_string;
+ const concrete_scheduler scheduler = sched_config.find("lrr") != std::string::npos ?
+ CONCRETE_SCHEDULER_LRR :
+ sched_config.find("two_level_active") != std::string::npos ?
+ CONCRETE_SCHEDULER_TWO_LEVEL_ACTIVE :
+ sched_config.find("gto") != std::string::npos ?
+ CONCRETE_SCHEDULER_GTO :
+ NUM_CONCRETE_SCHEDULERS;
+ assert ( scheduler != NUM_CONCRETE_SCHEDULERS );
+
+ for (int i = 0; i < m_config->gpgpu_num_sched_per_core; i++) {
+ switch( scheduler )
+ {
+ case CONCRETE_SCHEDULER_LRR:
+ schedulers.push_back(
+ new lrr_scheduler( 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],
+ i
+ )
+ );
+ break;
+ case CONCRETE_SCHEDULER_TWO_LEVEL_ACTIVE:
+ schedulers.push_back(
+ new two_level_active_scheduler( 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],
+ i,
+ config->gpgpu_scheduler_string
+ )
+ );
+ break;
+ case CONCRETE_SCHEDULER_GTO:
+ schedulers.push_back(
+ new gto_scheduler( 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],
+ i
+ )
+ );
+ break;
+ default:
+ abort();
+ };
+ }
+
+ 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);
+ }
+ for ( int i = 0; i < m_config->gpgpu_num_sched_per_core; ++i ) {
+ schedulers[i]->done_adding_supervised_warps();
+ }
+
+ //op collector configuration
+ enum { SP_CUS, SFU_CUS, MEM_CUS, GEN_CUS };
+ m_operand_collector.add_cu_set(SP_CUS, m_config->gpgpu_operand_collector_num_units_sp, m_config->gpgpu_operand_collector_num_out_ports_sp);
+ m_operand_collector.add_cu_set(SFU_CUS, m_config->gpgpu_operand_collector_num_units_sfu, m_config->gpgpu_operand_collector_num_out_ports_sfu);
+ m_operand_collector.add_cu_set(MEM_CUS, m_config->gpgpu_operand_collector_num_units_mem, m_config->gpgpu_operand_collector_num_out_ports_mem);
+ m_operand_collector.add_cu_set(GEN_CUS, m_config->gpgpu_operand_collector_num_units_gen, m_config->gpgpu_operand_collector_num_out_ports_gen);
+
+ opndcoll_rfu_t::port_vector_t in_ports;
+ opndcoll_rfu_t::port_vector_t out_ports;
+ opndcoll_rfu_t::uint_vector_t cu_sets;
+ for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_sp; i++) {
+ in_ports.push_back(&m_pipeline_reg[ID_OC_SP]);
+ out_ports.push_back(&m_pipeline_reg[OC_EX_SP]);
+ cu_sets.push_back((unsigned)SP_CUS);
+ cu_sets.push_back((unsigned)GEN_CUS);
+ m_operand_collector.add_port(in_ports,out_ports,cu_sets);
+ in_ports.clear(),out_ports.clear(),cu_sets.clear();
+ }
+
+ for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_sfu; i++) {
+ in_ports.push_back(&m_pipeline_reg[ID_OC_SFU]);
+ out_ports.push_back(&m_pipeline_reg[OC_EX_SFU]);
+ cu_sets.push_back((unsigned)SFU_CUS);
+ cu_sets.push_back((unsigned)GEN_CUS);
+ m_operand_collector.add_port(in_ports,out_ports,cu_sets);
+ in_ports.clear(),out_ports.clear(),cu_sets.clear();
+ }
+
+ for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_mem; i++) {
+ in_ports.push_back(&m_pipeline_reg[ID_OC_MEM]);
+ out_ports.push_back(&m_pipeline_reg[OC_EX_MEM]);
+ cu_sets.push_back((unsigned)MEM_CUS);
+ cu_sets.push_back((unsigned)GEN_CUS);
+ m_operand_collector.add_port(in_ports,out_ports,cu_sets);
+ in_ports.clear(),out_ports.clear(),cu_sets.clear();
+ }
+
+
+ for (unsigned i = 0; i < m_config->gpgpu_operand_collector_num_in_ports_gen; i++) {
+ in_ports.push_back(&m_pipeline_reg[ID_OC_SP]);
+ in_ports.push_back(&m_pipeline_reg[ID_OC_SFU]);
+ in_ports.push_back(&m_pipeline_reg[ID_OC_MEM]);
+ out_ports.push_back(&m_pipeline_reg[OC_EX_SP]);
+ out_ports.push_back(&m_pipeline_reg[OC_EX_SFU]);
+ out_ports.push_back(&m_pipeline_reg[OC_EX_MEM]);
+ cu_sets.push_back((unsigned)GEN_CUS);
+ m_operand_collector.add_port(in_ports,out_ports,cu_sets);
+ in_ports.clear(),out_ports.clear(),cu_sets.clear();
+ }
+
+ m_operand_collector.init( m_config->gpgpu_num_reg_banks, this );
+
+ // execute
+ m_num_function_units = m_config->gpgpu_num_sp_units + m_config->gpgpu_num_sfu_units + 1; // sp_unit, sfu, ldst_unit
+ //m_dispatch_port = new enum pipeline_stage_name_t[ m_num_function_units ];
+ //m_issue_port = new enum pipeline_stage_name_t[ m_num_function_units ];
+
+ //m_fu = new simd_function_unit*[m_num_function_units];
+
+ for (int k = 0; k < m_config->gpgpu_num_sp_units; k++) {
+ m_fu.push_back(new sp_unit( &m_pipeline_reg[EX_WB], m_config, this ));
+ m_dispatch_port.push_back(ID_OC_SP);
+ m_issue_port.push_back(OC_EX_SP);
+ }
+
+ for (int k = 0; k < m_config->gpgpu_num_sfu_units; k++) {
+ m_fu.push_back(new sfu( &m_pipeline_reg[EX_WB], m_config, this ));
+ m_dispatch_port.push_back(ID_OC_SFU);
+ m_issue_port.push_back(OC_EX_SFU);
+ }
+
+ m_ldst_unit = new ldst_unit( m_icnt, m_mem_fetch_allocator, this, &m_operand_collector, m_scoreboard, config, mem_config, stats, shader_id, tpc_id );
+ m_fu.push_back(m_ldst_unit);
+ m_dispatch_port.push_back(ID_OC_MEM);
+ m_issue_port.push_back(OC_EX_MEM);
+
+ assert(m_num_function_units == m_fu.size() and m_fu.size() == m_dispatch_port.size() and m_fu.size() == m_issue_port.size());
+
+ //there are as many result buses as the width of the EX_WB stage
+ num_result_bus = config->pipe_widths[EX_WB];
+ for(unsigned i=0; i<num_result_bus; i++){
+ this->m_result_bus.push_back(new std::bitset<MAX_ALU_LATENCY>());
+ }
+
+ m_last_inst_gpu_sim_cycle = 0;
+ m_last_inst_gpu_tot_sim_cycle = 0;
}
void shader_core_ctx::reinit(unsigned start_thread, unsigned end_thread, bool reset_not_completed )
@@ -433,6 +478,10 @@ void shader_core_stats::event_warp_issued( unsigned s_id, unsigned warp_id, unsi
m_shader_dynamic_warp_issue_distro[ s_id ].resize(dynamic_warp_id + 1);
}
++m_shader_dynamic_warp_issue_distro[ s_id ][ dynamic_warp_id ];
+ if ( m_shader_warp_slot_issue_distro[ s_id ].size() <= warp_id ) {
+ m_shader_warp_slot_issue_distro[ s_id ].resize(warp_id + 1);
+ }
+ ++m_shader_warp_slot_issue_distro[ s_id ][ warp_id ];
}
}
@@ -457,6 +506,47 @@ void shader_core_stats::visualizer_print( gzFile visualizer_file )
}
gzprintf(visualizer_file,"\n");
+ // warp issue breakdown
+ unsigned sid = m_config->gpgpu_warp_issue_shader;
+ gzprintf(visualizer_file, "WarpIssueSlotBreakdown:");
+ unsigned count = 0;
+ unsigned warp_id_issued_sum = 0;
+ for ( std::vector<unsigned>::const_iterator iter = m_shader_warp_slot_issue_distro[ sid ].begin();
+ iter != m_shader_warp_slot_issue_distro[ sid ].end(); iter++, count++ ) {
+ unsigned diff = count < m_last_shader_warp_slot_issue_distro.size() ?
+ *iter - m_last_shader_warp_slot_issue_distro[ count ] :
+ *iter;
+ gzprintf( visualizer_file, " %d", diff );
+ warp_id_issued_sum += diff;
+ }
+ m_last_shader_warp_slot_issue_distro = m_shader_warp_slot_issue_distro[ sid ];
+ gzprintf(visualizer_file,"\n");
+
+ #define DYNAMIC_WARP_PRINT_RESOLUTION 32
+ unsigned total_issued_this_resolution = 0;
+ unsigned dynamic_id_issued_sum = 0;
+ count = 0;
+ gzprintf(visualizer_file, "WarpIssueDynamicIdBreakdown:");
+ for ( std::vector<unsigned>::const_iterator iter = m_shader_dynamic_warp_issue_distro[ sid ].begin();
+ iter != m_shader_dynamic_warp_issue_distro[ sid ].end(); iter++, count++ ) {
+ unsigned diff = count < m_last_shader_dynamic_warp_issue_distro.size() ?
+ *iter - m_last_shader_dynamic_warp_issue_distro[ count ] :
+ *iter;
+ total_issued_this_resolution += diff;
+ if ( ( count + 1 ) % DYNAMIC_WARP_PRINT_RESOLUTION == 0 ) {
+ gzprintf( visualizer_file, " %d", total_issued_this_resolution );
+ dynamic_id_issued_sum += total_issued_this_resolution;
+ total_issued_this_resolution = 0;
+ }
+ }
+ if ( count % DYNAMIC_WARP_PRINT_RESOLUTION != 0 ) {
+ gzprintf( visualizer_file, " %d", total_issued_this_resolution );
+ dynamic_id_issued_sum += total_issued_this_resolution;
+ }
+ m_last_shader_dynamic_warp_issue_distro = m_shader_dynamic_warp_issue_distro[ sid ];
+ gzprintf(visualizer_file,"\n");
+ assert( warp_id_issued_sum == dynamic_id_issued_sum );
+
// overall cache miss rates
gzprintf(visualizer_file, "gpgpu_n_cache_bkconflict: %d\n", gpgpu_n_cache_bkconflict);
gzprintf(visualizer_file, "gpgpu_n_shmem_bkconflict: %d\n", gpgpu_n_shmem_bkconflict);
@@ -631,15 +721,113 @@ shd_warp_t& scheduler_unit::warp(int i){
return (*m_warp)[i];
}
-void LooseRoundRobbinScheduler::cycle()
+
+/**
+ * A general function to order things in a Loose Round Robin way. The simplist use of this
+ * function would be to implement a loose RR scheduler between all the warps assigned to this core.
+ * A more sophisticated usage would be to order a set of "fetch groups" in a RR fashion.
+ * In the first case, the templated class variable would be a simple unsigned int representing the
+ * warp_id. In the 2lvl case, T could be a struct or a list representing a set of warp_ids.
+ * @param result_list: The resultant list the caller wants returned. This list is cleared and then populated
+ * in a loose round robin way
+ * @param input_list: The list of things that should be put into the result_list. For a simple scheduler
+ * this can simply be the m_supervised_warps list.
+ * @param last_issued_from_input: An iterator pointing the last member in the input_list that issued.
+ * Since this function orders in a RR fashion, the object pointed
+ * to by this iterator will be last in the prioritization list
+ * @param num_warps_to_add: The number of warps you want the scheudler to pick between this cycle.
+ * Normally, this will be all the warps availible on the core, i.e.
+ * m_supervised_warps.size(). However, a more sophisticated scheduler may wish to
+ * limit this number. If the number if < m_supervised_warps.size(), then only
+ * the warps with highest RR priority will be placed in the result_list.
+ */
+template < class T >
+void scheduler_unit::order_lrr( 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 )
+{
+ assert( num_warps_to_add <= input_list.size() );
+ result_list.clear();
+ typename std::vector< T >::const_iterator iter
+ = ( last_issued_from_input == input_list.end() ) ? input_list.begin()
+ : last_issued_from_input + 1;
+
+ for ( unsigned count = 0;
+ count < num_warps_to_add;
+ ++iter, ++count) {
+ if ( iter == input_list.end() ) {
+ iter = input_list.begin();
+ }
+ result_list.push_back( *iter );
+ }
+}
+
+/**
+ * A general function to order things in an priority-based way.
+ * The core usage of the function is similar to order_lrr.
+ * The explanation of the additional parameters (beyond order_lrr) explains the further extensions.
+ * @param ordering: An enum that determines how the age function will be treated in prioritization
+ * see the definition of OrderingType.
+ * @param priority_function: This function is used to sort the input_list. It is passed to stl::sort as
+ * the sorting fucntion. So, if you wanted to sort a list of integer warp_ids
+ * with the oldest warps having the most priority, then the priority_function
+ * would compare the age of the two warps.
+ */
+template < class T >
+void scheduler_unit::order_by_priority( 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,
+ OrderingType ordering,
+ bool (*priority_func)(T lhs, T rhs) )
+{
+ assert( num_warps_to_add <= input_list.size() );
+ result_list.clear();
+ typename std::vector< T > temp = input_list;
+
+
+ if ( ORDERING_GREEDY_THEN_PRIORITY_FUNC == ordering ) {
+ T greedy_value = *last_issued_from_input;
+ result_list.push_back( greedy_value );
+
+ std::sort( temp.begin(), temp.end(), priority_func );
+ typename std::vector< T >::iterator iter = temp.begin();
+ for ( unsigned count = 0; count < num_warps_to_add; ++count, ++iter ) {
+ if ( *iter != greedy_value ) {
+ result_list.push_back( *iter );
+ }
+ }
+ } else if ( ORDERED_PRIORITY_FUNC_ONLY == ordering ) {
+ std::sort( temp.begin(), temp.end(), priority_func );
+ typename std::vector< T >::iterator iter = temp.begin();
+ for ( unsigned count = 0; count < num_warps_to_add; ++count, ++iter ) {
+ result_list.push_back( *iter );
+ }
+ } else {
+ fprintf( stderr, "Unknown ordering - %d\n", ordering );
+ abort();
+ }
+}
+
+void scheduler_unit::cycle()
{
+ SCHED_DPRINTF( "scheduler_unit::cycle()\n" );
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 < supervised_warps.size(); i++ ) {
- unsigned supervised_id = (m_last_sup_id_issued+1+i) % supervised_warps.size();
- unsigned warp_id = supervised_warps[supervised_id];
+ order_warps();
+ for ( std::vector< shd_warp_t* >::const_iterator iter = m_next_cycle_prioritized_warps.begin();
+ iter != m_next_cycle_prioritized_warps.end();
+ iter++ ) {
+ // Don't consider warps that are not yet valid
+ if ( (*iter) == NULL || (*iter)->done_exit() ) {
+ continue;
+ }
+ SCHED_DPRINTF( "Testing (warp_id %u, dynamic_warp_id %u)\n",
+ (*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id() );
+ unsigned warp_id = (*iter)->get_warp_id();
unsigned checked=0;
unsigned issued=0;
unsigned max_issue = m_shader->m_config->gpgpu_max_insn_issue_per_warp;
@@ -649,15 +837,22 @@ void LooseRoundRobbinScheduler::cycle()
bool warp_inst_issued = false;
unsigned pc,rpc;
m_simt_stack[warp_id]->get_pdom_stack_top_info(&pc,&rpc);
+ SCHED_DPRINTF( "Warp (warp_id %u, dynamic_warp_id %u) has valid instruction (%s)\n",
+ (*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id(),
+ ptx_get_insn_str( pc).c_str() );
if( pI ) {
assert(valid);
if( pc != pI->pc ) {
+ SCHED_DPRINTF( "Warp (warp_id %u, dynamic_warp_id %u) control hazard instruction flush\n",
+ (*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id() );
// control hazard
warp(warp_id).set_next_pc(pc);
warp(warp_id).ibuffer_flush();
} else {
valid_inst = true;
if ( !m_scoreboard->checkCollision(warp_id, pI) ) {
+ SCHED_DPRINTF( "Warp (warp_id %u, dynamic_warp_id %u) passes scoreboard\n",
+ (*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id() );
ready_inst = true;
const active_mask_t &active_mask = m_simt_stack[warp_id]->get_active_mask();
assert( warp(warp_id).inst_in_pipeline() );
@@ -686,19 +881,40 @@ void LooseRoundRobbinScheduler::cycle()
}
}
}
+ } else {
+ SCHED_DPRINTF( "Warp (warp_id %u, dynamic_warp_id %u) fails scoreboard\n",
+ (*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id() );
}
}
} else if( valid ) {
// this case can happen after a return instruction in diverged warp
+ SCHED_DPRINTF( "Warp (warp_id %u, dynamic_warp_id %u) return from diverged warp flush\n",
+ (*iter)->get_warp_id(), (*iter)->get_dynamic_warp_id() );
warp(warp_id).set_next_pc(pc);
warp(warp_id).ibuffer_flush();
}
- if(warp_inst_issued)
- warp(warp_id).ibuffer_step();
+ if(warp_inst_issued) {
+ SCHED_DPRINTF( "Warp (warp_id %u, dynamic_warp_id %u) issued %u instructions\n",
+ (*iter)->get_warp_id(),
+ (*iter)->get_dynamic_warp_id(),
+ issued );
+ do_on_warp_issued( warp_id, issued, iter );
+ }
checked++;
}
if ( issued ) {
- m_last_sup_id_issued=supervised_id;
+ // This might be a bit inefficient, but we need to maintain
+ // two ordered list for proper scheduler execution.
+ // We could remove the need for this loop by associating a
+ // supervised_is index with each entry in the m_next_cycle_prioritized_warps
+ // vector. For now, just run through until you find the right warp_id
+ for ( std::vector< shd_warp_t* >::const_iterator supervised_iter = m_supervised_warps.begin();
+ supervised_iter != m_supervised_warps.end();
+ ++supervised_iter ) {
+ if ( *iter == *supervised_iter ) {
+ m_last_supervised_issued = supervised_iter;
+ }
+ }
break;
}
}
@@ -712,138 +928,110 @@ void LooseRoundRobbinScheduler::cycle()
m_stats->shader_cycle_distro[2]++; // pipeline stalled
}
-void TwoLevelScheduler::cycle() {
- //Move waiting warps to pendingWarps
- for ( std::list<int>::iterator iter = activeWarps.begin();
- iter != activeWarps.end();
- iter ++) {
- bool waiting = warp(*iter).waiting();
- for (int i=0; i<4; i++){
- const warp_inst_t* inst = warp(*iter).ibuffer_next_inst();
- //Is the instruction waiting on a long operation?
- if ( inst && inst->in[i] > 0 && this->m_scoreboard->islongop(*iter, inst->in[i])){
- waiting = true;
- }
- }
-
- if(waiting){
- pendingWarps.push_back(*iter);
- activeWarps.erase(iter);
- break;
- }
- }
+void scheduler_unit::do_on_warp_issued( unsigned warp_id,
+ unsigned num_issued,
+ const std::vector< shd_warp_t* >::const_iterator& prioritized_iter )
+{
+ m_stats->event_warp_issued( m_shader->get_sid(),
+ warp_id,
+ num_issued,
+ warp(warp_id).get_dynamic_warp_id() );
+ warp(warp_id).ibuffer_step();
+}
- //If there is space in activeWarps, try to find ready warps in pendingWarps
- if (this->activeWarps.size() < maxActiveWarps){
- for ( std::list<int>::iterator iter = pendingWarps.begin();
- iter != pendingWarps.end();
- iter++){
- if(!warp(*iter).waiting()){
- activeWarps.push_back(*iter);
- pendingWarps.erase(iter);
- break;
- }
- }
- }
+bool scheduler_unit::sort_warps_by_oldest_dynamic_id(shd_warp_t* lhs, shd_warp_t* rhs)
+{
+ if (rhs && lhs) {
+ return lhs->get_dynamic_warp_id() < rhs->get_dynamic_warp_id();
+ } else {
+ return lhs < rhs;
+ }
+}
- //Do the scheduling only from activeWarps
- //If you schedule an instruction, move it to the end of the list
+void lrr_scheduler::order_warps()
+{
+ order_lrr( m_next_cycle_prioritized_warps,
+ m_supervised_warps,
+ m_last_supervised_issued,
+ m_supervised_warps.size() );
+}
- 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
+void gto_scheduler::order_warps()
+{
+ order_by_priority( m_next_cycle_prioritized_warps,
+ m_supervised_warps,
+ m_last_supervised_issued,
+ m_supervised_warps.size(),
+ ORDERING_GREEDY_THEN_PRIORITY_FUNC,
+ scheduler_unit::sort_warps_by_oldest_dynamic_id );
+}
- for ( std::list<int>::iterator warp_id = activeWarps.begin();
- warp_id != activeWarps.end();
- warp_id++) {
- unsigned checked=0;
- unsigned issued=0;
- unsigned max_issue = m_shader->m_config->gpgpu_max_insn_issue_per_warp;
- while(!warp(*warp_id).waiting() && !warp(*warp_id).ibuffer_empty() && (checked < max_issue) && (checked <= issued) && (issued < max_issue) ) {
- const warp_inst_t *pI = warp(*warp_id).ibuffer_next_inst();
- bool valid = warp(*warp_id).ibuffer_next_valid();
- bool warp_inst_issued = false;
- 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
- 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( warp(*warp_id).inst_in_pipeline() );
- if ( (pI->op == LOAD_OP) || (pI->op == STORE_OP) || (pI->op == MEMORY_BARRIER_OP) ) {
- if( m_mem_out->has_free() ) {
- m_shader->issue_warp(*m_mem_out,pI,active_mask,*warp_id);
- issued++;
- issued_inst=true;
- warp_inst_issued = true;
- // Move it to pendingWarps
- unsigned currwarp = *warp_id;
- activeWarps.erase(warp_id);
- activeWarps.push_back(currwarp);
- }
- } else {
- bool sp_pipe_avail = m_sp_out->has_free();
- bool sfu_pipe_avail = m_sfu_out->has_free();
- if( sp_pipe_avail && (pI->op != SFU_OP) ) {
- // always prefer SP pipe for operations that can use both SP and SFU pipelines
- m_shader->issue_warp(*m_sp_out,pI,active_mask,*warp_id);
- issued++;
- issued_inst=true;
- warp_inst_issued = true;
- //Move it to end of the activeWarps
- unsigned currwarp = *warp_id;
- activeWarps.erase(warp_id);
- activeWarps.push_back(currwarp);
- } else if ( (pI->op == SFU_OP) || (pI->op == ALU_SFU_OP) ) {
- if( sfu_pipe_avail ) {
- m_shader->issue_warp(*m_sfu_out,pI,active_mask,*warp_id);
- issued++;
- issued_inst=true;
- warp_inst_issued = true;
- //Move it to end of the activeWarps
- unsigned currwarp = *warp_id;
- activeWarps.erase(warp_id);
- activeWarps.push_back(currwarp);
+void
+two_level_active_scheduler::do_on_warp_issued( unsigned warp_id,
+ unsigned num_issued,
+ const std::vector< shd_warp_t* >::const_iterator& prioritized_iter )
+{
+ scheduler_unit::do_on_warp_issued( warp_id, num_issued, prioritized_iter );
+ if ( SCHEDULER_PRIORITIZATION_LRR == m_inner_level_prioritization ) {
+ std::vector< shd_warp_t* > new_active;
+ order_lrr( new_active,
+ m_next_cycle_prioritized_warps,
+ prioritized_iter,
+ m_next_cycle_prioritized_warps.size() );
+ m_next_cycle_prioritized_warps = new_active;
+ } else {
+ fprintf( stderr,
+ "Unimplemented m_inner_level_prioritization: %d\n",
+ m_inner_level_prioritization );
+ abort();
+ }
+}
- }
- }
- }
- }
- }
- } else if( valid ) {
- // this case can happen after a return instruction in diverged warp
- warp(*warp_id).set_next_pc(pc);
- warp(*warp_id).ibuffer_flush();
+void two_level_active_scheduler::order_warps()
+{
+ //Move waiting warps to m_pending_warps
+ unsigned num_demoted = 0;
+ for ( std::vector< shd_warp_t* >::iterator iter = m_next_cycle_prioritized_warps.begin();
+ iter != m_next_cycle_prioritized_warps.end(); ) {
+ bool waiting = (*iter)->waiting();
+ for (int i=0; i<4; i++){
+ const warp_inst_t* inst = (*iter)->ibuffer_next_inst();
+ //Is the instruction waiting on a long operation?
+ if ( inst && inst->in[i] > 0 && this->m_scoreboard->islongop((*iter)->get_warp_id(), inst->in[i])){
+ waiting = true;
}
- if(warp_inst_issued)
- warp(*warp_id).ibuffer_step();
- checked++;
- }
- if ( issued ) {
- break;
}
+
+ if( waiting ) {
+ m_pending_warps.push_back(*iter);
+ iter = m_next_cycle_prioritized_warps.erase(iter);
+ SCHED_DPRINTF( "DEMOTED warp_id=%d, dynamic_warp_id=%d\n",
+ (*iter)->get_warp_id(),
+ (*iter)->get_dynamic_warp_id() );
+ ++num_demoted;
+ } else {
+ ++iter;
+ }
}
- // tgrogers - fixing a warning about unused variables at the top of this fucntion...
- // This scheduler has A LOT of copied code from the LRR scheduler.
- // TODO - this thing really needs to be re-written in a modular way.
- // For now, to get rid of the warnings I am including the stats epilogue
- // from the original scheduler function that the author of this function forgot to copy/paste
- //
- // issue stall statistics:
- if( !valid_inst )
- m_stats->shader_cycle_distro[0]++; // idle or control hazard
- else if( !ready_inst )
- m_stats->shader_cycle_distro[1]++; // waiting for RAW hazards (possibly due to memory)
- else if( !issued_inst )
- m_stats->shader_cycle_distro[2]++; // pipeline stalled
+ //If there is space in m_next_cycle_prioritized_warps, promote the next m_pending_warps
+ unsigned num_promoted = 0;
+ if ( SCHEDULER_PRIORITIZATION_SRR == m_outer_level_prioritization ) {
+ while ( m_next_cycle_prioritized_warps.size() < m_max_active_warps ) {
+ m_next_cycle_prioritized_warps.push_back(m_pending_warps.front());
+ m_pending_warps.pop_front();
+ SCHED_DPRINTF( "PROMOTED warp_id=%d, dynamic_warp_id=%d\n",
+ (m_next_cycle_prioritized_warps.back())->get_warp_id(),
+ (m_next_cycle_prioritized_warps.back())->get_dynamic_warp_id() );
+ ++num_promoted;
+ }
+ } else {
+ fprintf( stderr,
+ "Unimplemented m_outer_level_prioritization: %d\n",
+ m_outer_level_prioritization );
+ abort();
+ }
+ assert( num_promoted == num_demoted );
}
void shader_core_ctx::read_operands()
@@ -1727,6 +1915,46 @@ void gpgpu_sim::shader_print_runtime_stat( FILE *fout )
}
+void gpgpu_sim::shader_print_scheduler_stat( FILE* fout, bool print_dynamic_info ) const
+{
+ // Print out the stats from the sampling shader core
+ const unsigned scheduler_sampling_core = m_shader_config->gpgpu_warp_issue_shader;
+ #define STR_SIZE 55
+ char name_buff[ STR_SIZE ];
+ name_buff[ STR_SIZE - 1 ] = '\0';
+ const std::vector< unsigned >& distro
+ = print_dynamic_info ?
+ m_shader_stats->get_dynamic_warp_issue()[ scheduler_sampling_core ] :
+ m_shader_stats->get_warp_slot_issue()[ scheduler_sampling_core ];
+ if ( print_dynamic_info ) {
+ snprintf( name_buff, STR_SIZE - 1, "dynamic_warp_id" );
+ } else {
+ snprintf( name_buff, STR_SIZE - 1, "warp_id" );
+ }
+ fprintf( fout,
+ "Shader %d %s issue ditsribution:\n",
+ scheduler_sampling_core,
+ name_buff );
+ const unsigned num_warp_ids = distro.size();
+ // First print out the warp ids
+ fprintf( fout, "%s:\n", name_buff );
+ for ( unsigned warp_id = 0;
+ warp_id < num_warp_ids;
+ ++warp_id ) {
+ fprintf( fout, "%d, ", warp_id );
+ }
+
+ fprintf( fout, "\ndistro:\n" );
+ // Then print out the distribution of instuctions issued
+ for ( std::vector< unsigned >::const_iterator iter = distro.begin();
+ iter != distro.end();
+ iter++ ) {
+ fprintf( fout, "%d, ", *iter );
+ }
+ fprintf( fout, "\n" );
+}
+
+
void gpgpu_sim::shader_print_l1_miss_stat( FILE *fout ) const
{
unsigned total_d1_misses = 0, total_d1_accesses = 0;
diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h
index c74fa96..952651e 100644
--- a/src/gpgpu-sim/shader.h
+++ b/src/gpgpu-sim/shader.h
@@ -259,6 +259,27 @@ 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
+};
+
+// 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,
+ 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,
@@ -266,21 +287,74 @@ public:
std::vector<shd_warp_t>* warp,
register_set* sp_out,
register_set* sfu_out,
- register_set* mem_out)
- : supervised_warps(), m_last_sup_id_issued(0), m_stats(stats), m_shader(shader),
+ 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_sfu_out(sfu_out),m_mem_out(mem_out){}
+ m_sp_out(sp_out),m_sfu_out(sfu_out),m_mem_out(mem_out), m_id(id){}
virtual ~scheduler_unit(){}
virtual void add_supervised_warp_id(int i) {
- supervised_warps.push_back(i);
+ m_supervised_warps.push_back(&warp(i));
+ }
+ virtual void done_adding_supervised_warps() {
+ m_last_supervised_issued = m_supervised_warps.end();
}
- virtual void cycle()=0;
+
+ // 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 );
+
+ 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;
+
+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);
- std::vector<int> supervised_warps;
- int m_last_sup_id_issued;
+ // 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.
@@ -291,45 +365,89 @@ protected:
register_set* m_sp_out;
register_set* m_sfu_out;
register_set* m_mem_out;
+
+ int m_id;
};
-class LooseRoundRobbinScheduler : public scheduler_unit {
+class lrr_scheduler : public scheduler_unit {
public:
- LooseRoundRobbinScheduler (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* sfu_out,
- register_set* mem_out)
- : scheduler_unit (stats, shader, scoreboard, simt, warp, sp_out, sfu_out, mem_out){}
- virtual ~LooseRoundRobbinScheduler () {}
- virtual void cycle ();
+ 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* sfu_out,
+ register_set* mem_out,
+ int id )
+ : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_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* sfu_out,
+ register_set* mem_out,
+ int id )
+ : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_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 TwoLevelScheduler : public scheduler_unit {
+
+class two_level_active_scheduler : public scheduler_unit {
public:
- TwoLevelScheduler (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* sfu_out,
- register_set* mem_out,
- unsigned maw)
- : scheduler_unit (stats, shader, scoreboard, simt, warp, sp_out, sfu_out, mem_out),
- activeWarps(),
- pendingWarps(){
- maxActiveWarps = maw;
- }
- virtual ~TwoLevelScheduler () {}
- virtual void cycle ();
- virtual void add_supervised_warp_id(int i) {
- pendingWarps.push_back(i);
+ 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* sfu_out,
+ register_set* mem_out,
+ int id,
+ char* config_str )
+ : scheduler_unit ( stats, shader, scoreboard, simt, warp, sp_out, sfu_out, mem_out, id ),
+ m_pending_warps()
+ {
+ int ret = sscanf( config_str,
+ "two_level_active:%d:%d:%d",
+ &m_max_active_warps,
+ (int*)&m_inner_level_prioritization,
+ (int*)&m_outer_level_prioritization );
+ assert( 3 == ret );
+ }
+ 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 );
+
private:
- unsigned maxActiveWarps;
- std::list<int> activeWarps;
- std::list<int> pendingWarps;
+ 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;
};
@@ -1158,6 +1276,7 @@ struct shader_core_config : public core_config
//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;
@@ -1324,7 +1443,7 @@ public:
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() );
}
void new_grid()
@@ -1342,10 +1461,18 @@ public:
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;
+ }
+
private:
const shader_core_config *m_config;
// 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;
@@ -1750,4 +1877,7 @@ private:
simt_core_cluster *m_cluster;
};
+
+inline int scheduler_unit::get_sid() const { return m_shader->get_sid(); }
+
#endif /* SHADER_H */
diff --git a/src/gpgpu-sim/shader_trace.h b/src/gpgpu-sim/shader_trace.h
new file mode 100644
index 0000000..8a433cb
--- /dev/null
+++ b/src/gpgpu-sim/shader_trace.h
@@ -0,0 +1,74 @@
+// Copyright (c) 2009-2011, Tor M. Aamodt, Tim Rogers
+// George L. Yuan, Andrew Turner, Inderpreet Singh
+// The University of British Columbia
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 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.
+//
+// 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_TRACE_H__
+#define __SHADER_TRACE_H__
+
+#include "../trace.h"
+
+
+#if TRACING_ON
+
+#define SHADER_PRINT_STR SIM_PRINT_STR "Core %d - "
+#define SCHED_PRINT_STR SHADER_PRINT_STR "Scheduler %d - "
+#define SHADER_DTRACE(x) (DTRACE(x) && Trace::sampling_core == get_sid())
+
+// Intended to be called from inside components of a shader core.
+// Depends on a get_sid() function
+#define SHADER_DPRINTF(x, ...) do {\
+ if (SHADER_DTRACE(x)) {\
+ printf( SHADER_PRINT_STR,\
+ gpu_sim_cycle + gpu_tot_sim_cycle,\
+ Trace::trace_streams_str[Trace::x],\
+ get_sid() );\
+ printf(__VA_ARGS__);\
+ }\
+} while (0)
+
+// Intended to be called from inside a scheduler_unit.
+// Depends on a m_id member
+#define SCHED_DPRINTF(...) do {\
+ if (SHADER_DTRACE(WARP_SCHEDULER)) {\
+ printf( SCHED_PRINT_STR,\
+ gpu_sim_cycle + gpu_tot_sim_cycle,\
+ Trace::trace_streams_str[Trace::WARP_SCHEDULER],\
+ get_sid(),\
+ m_id );\
+ printf(__VA_ARGS__);\
+ }\
+} while (0)
+
+#else
+
+#define SHADER_DTRACE(x) (false)
+#define SHADER_DPRINTF(x, ...) do {} while (0)
+#define SCHED_DPRINTF(x, ...) do {} while (0)
+
+#endif
+
+#endif
diff --git a/src/trace.cc b/src/trace.cc
new file mode 100644
index 0000000..05b9d6b
--- /dev/null
+++ b/src/trace.cc
@@ -0,0 +1,55 @@
+// Copyright (c) 2009-2013, Tor M. Aamodt, Timothy Rogers,
+// The University of British Columbia
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 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.
+//
+// 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.
+
+#include "trace.h"
+#include "string.h"
+
+namespace Trace {
+
+
+#define TS_TUP_BEGIN(X) const char* trace_streams_str[] = {
+#define TS_TUP(X) #X
+#define TS_TUP_END(X) };
+#include "trace_streams.tup"
+#undef TS_TUP_BEGIN
+#undef TS_TUP
+#undef TS_TUP_END
+
+ bool enabled = false;
+ int sampling_core = 0;
+ bool trace_streams_enabled[NUM_TRACE_STREAMS] = {false};
+ const char* config_str;
+
+ void init()
+ {
+ for ( unsigned i = 0; i < NUM_TRACE_STREAMS; ++i ) {
+ if ( strstr( config_str, trace_streams_str[i] ) != NULL ) {
+ trace_streams_enabled[ i ] = true;
+ }
+ }
+ }
+}
diff --git a/src/trace.h b/src/trace.h
new file mode 100644
index 0000000..c7b389e
--- /dev/null
+++ b/src/trace.h
@@ -0,0 +1,79 @@
+// Copyright (c) 2009-2013, Tor M. Aamodt, Timothy Rogers,
+// The University of British Columbia
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 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.
+//
+// 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 file is inspired by the trace system in gem5.
+// This is a highly simplified version adpated for gpgpusim
+
+#ifndef __TRACE_H__
+#define __TRACE_H__
+
+extern unsigned long long gpu_sim_cycle;
+extern unsigned long long gpu_tot_sim_cycle;
+
+namespace Trace {
+
+#define TS_TUP_BEGIN(X) enum X {
+#define TS_TUP(X) X
+#define TS_TUP_END(X) };
+#include "trace_streams.tup"
+#undef TS_TUP_BEGIN
+#undef TS_TUP
+#undef TS_TUP_END
+
+ extern bool enabled;
+ extern int sampling_core;
+ extern const char* trace_streams_str[];
+ extern bool trace_streams_enabled[NUM_TRACE_STREAMS];
+ extern const char* config_str;
+
+ void init();
+
+} // namespace Trace
+
+
+#if TRACING_ON
+
+#define SIM_PRINT_STR "GPGPU-Sim Cycle %llu: %s - "
+#define DTRACE(x) ((Trace::trace_streams_enabled[Trace::x]) && Trace::enabled)
+#define DPRINTF(x, ...) do {\
+ if (DTRACE(x)) {\
+ printf( SIM_PRINT_STR,\
+ gpu_sim_cycle + gpu_tot_sim_cycle,\
+ Trace::trace_streams_str[Trace::x] );\
+ printf(__VA_ARGS__);\
+ }\
+} while (0)
+
+
+#else
+
+#define DTRACE(x) (false)
+#define DPRINTF(x, ...) do {} while (0)
+
+#endif
+
+#endif
diff --git a/src/trace_streams.tup b/src/trace_streams.tup
new file mode 100644
index 0000000..fa6fd1e
--- /dev/null
+++ b/src/trace_streams.tup
@@ -0,0 +1,32 @@
+// Copyright (c) 2009 by Tor M. Aamodt, Tim Rogers and
+// The University of British Columbia
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 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.
+//
+// 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.
+
+TS_TUP_BEGIN( trace_streams_type )
+ TS_TUP( WARP_SCHEDULER ),
+ TS_TUP( SCOREBOARD ),
+ TS_TUP( NUM_TRACE_STREAMS )
+TS_TUP_END( trace_streams_type )