summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTor Aamodt <[email protected]>2010-10-18 02:43:17 -0800
committerTor Aamodt <[email protected]>2010-10-18 02:43:17 -0800
commit87e4da5fc6086c3d0a661af1929255a8cbd728d7 (patch)
treea4f40e66f5ca0d6efdf9d51672a1180c8a381170 /src
parentb577cbcdf229a2c02d1bf8584c6e82be7a14cb33 (diff)
Re-designed cache model:
- read only cache model with integrated mshrs (no L1D, yet); new cache interface should be easily extendable to support texture cache with latency fifo and separate tag/data arrays, though this is not yet added (currently tags and data arrays are not decoupled for texture) - new partition model using the above removes all old MSHRs, L1D etc... passing CUDA 3.1 regression [git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 7875]
Diffstat (limited to 'src')
-rw-r--r--src/abstract_hardware_model.cc28
-rw-r--r--src/abstract_hardware_model.h74
-rw-r--r--src/cuda-sim/Makefile193
-rw-r--r--src/gpgpu-sim/delayqueue.h26
-rw-r--r--src/gpgpu-sim/dram.cc151
-rw-r--r--src/gpgpu-sim/dram.h14
-rw-r--r--src/gpgpu-sim/dram_sched.cc21
-rw-r--r--src/gpgpu-sim/dram_sched.h8
-rw-r--r--src/gpgpu-sim/gpu-cache.cc354
-rw-r--r--src/gpgpu-sim/gpu-cache.h443
-rw-r--r--src/gpgpu-sim/gpu-sim.cc144
-rw-r--r--src/gpgpu-sim/gpu-sim.h39
-rw-r--r--src/gpgpu-sim/l2cache.cc744
-rw-r--r--src/gpgpu-sim/l2cache.h175
-rw-r--r--src/gpgpu-sim/mem_fetch.cc48
-rw-r--r--src/gpgpu-sim/mem_fetch.h66
-rw-r--r--src/gpgpu-sim/mem_latency_stat.cc6
-rw-r--r--src/gpgpu-sim/mem_latency_stat.h7
-rw-r--r--src/gpgpu-sim/shader.cc872
-rw-r--r--src/gpgpu-sim/shader.h235
-rw-r--r--src/gpgpu-sim/stat-tool.h20
-rw-r--r--src/gpgpu-sim/stats.h1
-rw-r--r--src/gpgpu-sim/visualizer.cc16
-rw-r--r--src/gpgpu-sim/visualizer.h2
-rw-r--r--src/intersim/interconnect_interface.cpp15
-rw-r--r--src/tr1_hash_map.h38
26 files changed, 1423 insertions, 2317 deletions
diff --git a/src/abstract_hardware_model.cc b/src/abstract_hardware_model.cc
index 2134cfc..507e02f 100644
--- a/src/abstract_hardware_model.cc
+++ b/src/abstract_hardware_model.cc
@@ -29,12 +29,6 @@ unsigned core_config::shmem_bank_func(address_type addr, unsigned) const
return ((addr/WORD_SIZE) % gpgpu_n_shmem_bank);
}
-unsigned core_config::dcache_bank_func(address_type add, unsigned line_size) const
-{
- if (gpgpu_no_dl1) return 1; //no banks
- else return (add / line_size) & (gpgpu_n_cache_bank - 1);
-}
-
address_type null_tag_func(address_type address, unsigned line_size)
{
return address; //no modification: each address is its own tag.
@@ -101,20 +95,18 @@ void warp_inst_t::get_memory_access_list()
case global_space: case local_space: case param_space_local:
global_mem_access=true;
warp_parts = 1;
- line_size = m_config->gpgpu_cache_dl1_linesize;
+ line_size = 0;
if( m_config->gpgpu_coalesce_arch == 13 ){
warp_parts = 2;
- if( m_config->gpgpu_no_dl1 ) {
- // line size is dependant on instruction;
- switch (data_size) {
- case 1: line_size = 32; break;
- case 2: line_size = 64; break;
- case 4: case 8: case 16: line_size = 128; break;
- default: assert(0);
- }
+ // line size is dependant on instruction;
+ switch (data_size) {
+ case 1: line_size = 32; break;
+ case 2: line_size = 64; break;
+ case 4: case 8: case 16: line_size = 128; break;
+ default: assert(0);
}
- }
- bank_func = &core_config::dcache_bank_func;
+ } else abort();
+ bank_func = &core_config::null_bank_func;
tag_func = line_size_based_tag_func;
limit_broadcast = false;
break;
@@ -178,7 +170,7 @@ void warp_inst_t::get_memory_access_list()
// Now that we have the accesses, if we don't have a cache we can adjust request sizes to
// include only the data referenced by the threads
for (unsigned i = 0; i < get_accessq_size(); i++) {
- if (m_config->gpgpu_coalesce_arch == 13 && m_config->gpgpu_no_dl1) {
+ if (m_config->gpgpu_coalesce_arch == 13) {
// do coalescing here.
char* quarter_counts = accessq(i).quarter_count;
bool low = quarter_counts[0] or quarter_counts[1];
diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h
index ed832b6..fc2f0d4 100644
--- a/src/abstract_hardware_model.h
+++ b/src/abstract_hardware_model.h
@@ -1,6 +1,24 @@
#ifndef ABSTRACT_HARDWARE_MODEL_INCLUDED
#define ABSTRACT_HARDWARE_MODEL_INCLUDED
+enum _memory_space_t {
+ undefined_space=0,
+ reg_space,
+ local_space,
+ shared_space,
+ param_space_unclassified,
+ param_space_kernel, /* global to all threads in a kernel : read-only */
+ param_space_local, /* local to a thread : read-writable */
+ const_space,
+ tex_space,
+ surf_space,
+ global_space,
+ generic_space,
+ instruction_space
+};
+
+#ifdef __cplusplus
+
#include <string.h>
#include <stdio.h>
@@ -23,30 +41,12 @@ enum uarch_op_t {
};
typedef enum uarch_op_t op_type;
-enum _memory_space_t {
- undefined_space=0,
- reg_space,
- local_space,
- shared_space,
- param_space_unclassified,
- param_space_kernel, /* global to all threads in a kernel : read-only */
- param_space_local, /* local to a thread : read-writable */
- const_space,
- tex_space,
- surf_space,
- global_space,
- generic_space,
- instruction_space
-};
-
enum _memory_op_t {
no_memory_op = 0,
memory_load,
memory_store
};
-#ifdef __cplusplus
-
#include <bitset>
#include <list>
#include <vector>
@@ -60,6 +60,29 @@ struct dim3 {
};
#endif
+#if 0
+
+// detect gcc 4.3 and use unordered map (part of c++0x)
+// unordered map doesn't play nice with _GLIBCXX_DEBUG, just use a map if its enabled.
+#if defined( __GNUC__ ) and not defined( _GLIBCXX_DEBUG )
+#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 3
+ #include <unordered_map>
+ #define my_hash_map std::unordered_map
+#else
+ #include <ext/hash_map>
+ namespace std {
+ using namespace __gnu_cxx;
+ }
+ #define my_hash_map std::hash_map
+#endif
+#else
+ #include <map>
+ #define my_hash_map std::map
+ #define USE_MAP
+#endif
+
+#endif
+
void increment_x_then_y_then_z( dim3 &i, const dim3 &bound);
class kernel_info_t {
@@ -139,18 +162,14 @@ struct core_config {
// memory request architecture parameters
int gpgpu_coalesce_arch;
- bool gpgpu_no_dl1;
int gpgpu_shmem_pipe_speedup;
unsigned gpgpu_cache_texl1_linesize;
unsigned gpgpu_cache_constl1_linesize;
- unsigned gpgpu_cache_dl1_linesize;
static const address_type WORD_SIZE=4;
unsigned null_bank_func(address_type, unsigned) const { return 1; }
int gpgpu_n_shmem_bank;
unsigned shmem_bank_func(address_type addr, unsigned) const;
- int gpgpu_n_cache_bank;
- unsigned dcache_bank_func(address_type add, unsigned line_size) const;
};
class core_t {
@@ -363,7 +382,6 @@ private:
recheck_cache = false;
need_wb = false;
wb_addr = 0;
- reserved_mshr = NULL;
}
public:
@@ -382,12 +400,19 @@ public:
bool recheck_cache;
bool need_wb;
address_type wb_addr; // writeback address (if necessary).
- class mshr_entry* reserved_mshr;
private:
static unsigned next_access_uid;
};
+class mem_fetch;
+
+class mem_fetch_interface {
+public:
+ virtual bool full( unsigned size, bool write ) const = 0;
+ virtual void push( mem_fetch *mf ) = 0;
+};
+
#define MAX_REG_OPERANDS 8
struct dram_callback_t {
@@ -634,4 +659,5 @@ void move_warp( warp_inst_t *&dst, warp_inst_t *&src );
size_t get_kernel_code_size( class function_info *entry );
#endif // #ifdef __cplusplus
+
#endif // #ifndef ABSTRACT_HARDWARE_MODEL_INCLUDED
diff --git a/src/cuda-sim/Makefile b/src/cuda-sim/Makefile
index 39a6641..0b1a793 100644
--- a/src/cuda-sim/Makefile
+++ b/src/cuda-sim/Makefile
@@ -169,6 +169,199 @@ cuda_device_printf.o: ptx.tab.c
ptx_ir.o: ptx.tab.c ptx_parser_decode.def
ptx_loader.o: ptx.tab.c ptx_parser_decode.def
ptx_parser.o: ptx.tab.c ptx_parser_decode.def
+ptxinfo.tab.o: ptx.tab.c
+ptx-stats.o: ptx.tab.c
+ptx_sim.o: ptx.tab.c
+cuda-sim.o: ptx.tab.c
+lex.ptxinfo_.o: ptx.tab.c
+lex.ptx_.o: ptx.tab.c
# DO NOT DELETE
+cuda_device_printf.o: cuda_device_printf.h ptx_ir.h
+cuda_device_printf.o: ../abstract_hardware_model.h /usr/include/assert.h
+cuda_device_printf.o: /usr/include/features.h /usr/include/sys/cdefs.h
+cuda_device_printf.o: /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h
+cuda_device_printf.o: /usr/include/gnu/stubs-64.h ptx_sim.h
+cuda_device_printf.o: /usr/include/stdlib.h /usr/include/sys/types.h
+cuda_device_printf.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
+cuda_device_printf.o: /usr/include/time.h /usr/include/endian.h
+cuda_device_printf.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
+cuda_device_printf.o: /usr/include/sys/select.h /usr/include/bits/select.h
+cuda_device_printf.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
+cuda_device_printf.o: /usr/include/sys/sysmacros.h
+cuda_device_printf.o: /usr/include/bits/pthreadtypes.h /usr/include/alloca.h
+cuda_device_printf.o: dram_callback.h ../tr1_hash_map.h opcodes.h opcodes.def
+cuda_device_printf.o: memory.h /usr/include/string.h /usr/include/stdio.h
+cuda_device_printf.o: /usr/include/libio.h /usr/include/_G_config.h
+cuda_device_printf.o: /usr/include/wchar.h /usr/include/bits/stdio_lim.h
+cuda_device_printf.o: /usr/include/bits/sys_errlist.h ../option_parser.h
+cuda-sim.o: cuda-sim.h ../abstract_hardware_model.h dram_callback.h
+cuda-sim.o: /usr/include/stdlib.h /usr/include/features.h
+cuda-sim.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
+cuda-sim.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
+cuda-sim.o: /usr/include/sys/types.h /usr/include/bits/types.h
+cuda-sim.o: /usr/include/bits/typesizes.h /usr/include/time.h
+cuda-sim.o: /usr/include/endian.h /usr/include/bits/endian.h
+cuda-sim.o: /usr/include/bits/byteswap.h /usr/include/sys/select.h
+cuda-sim.o: /usr/include/bits/select.h /usr/include/bits/sigset.h
+cuda-sim.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h
+cuda-sim.o: /usr/include/bits/pthreadtypes.h /usr/include/alloca.h ptx_ir.h
+cuda-sim.o: /usr/include/assert.h ptx_sim.h ../tr1_hash_map.h opcodes.h
+cuda-sim.o: opcodes.def memory.h /usr/include/string.h /usr/include/stdio.h
+cuda-sim.o: /usr/include/libio.h /usr/include/_G_config.h
+cuda-sim.o: /usr/include/wchar.h /usr/include/bits/stdio_lim.h
+cuda-sim.o: /usr/include/bits/sys_errlist.h ../option_parser.h
+cuda-sim.o: ../intersim/statwraper.h ptx-stats.h ptx_loader.h ptx_parser.h
+cuda-sim.o: ../gpgpu-sim/gpu-sim.h ../gpgpu-sim/addrdec.h
+cuda-sim.o: ../gpgpu-sim/shader.h /usr/include/math.h
+cuda-sim.o: /usr/include/bits/huge_val.h /usr/include/bits/mathdef.h
+cuda-sim.o: /usr/include/bits/mathcalls.h ../cuda-sim/dram_callback.h
+cuda-sim.o: ../gpgpu-sim/delayqueue.h ../gpgpu-sim/gpu-misc.h
+cuda-sim.o: ../gpgpu-sim/stack.h ../gpgpu-sim/dram.h /usr/include/zlib.h
+cuda-sim.o: /usr/include/zconf.h /usr/include/unistd.h
+cuda-sim.o: /usr/include/bits/posix_opt.h /usr/include/bits/confname.h
+cuda-sim.o: /usr/include/getopt.h ../gpgpu-sim/scoreboard.h
+cuda-sim.o: ../gpgpu-sim/mem_fetch.h ../gpgpu-sim/stats.h
+cuda-sim.o: ../gpgpu-sim/gpu-cache.h ../gpgpusim_entrypoint.h
+cuda-sim.o: ../abstract_hardware_model.h
+cuda-sim.o: decuda_pred_table/decuda_pred_table.h
+instructions.o: ptx_ir.h ../abstract_hardware_model.h /usr/include/assert.h
+instructions.o: /usr/include/features.h /usr/include/sys/cdefs.h
+instructions.o: /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h
+instructions.o: /usr/include/gnu/stubs-64.h ptx_sim.h /usr/include/stdlib.h
+instructions.o: /usr/include/sys/types.h /usr/include/bits/types.h
+instructions.o: /usr/include/bits/typesizes.h /usr/include/time.h
+instructions.o: /usr/include/endian.h /usr/include/bits/endian.h
+instructions.o: /usr/include/bits/byteswap.h /usr/include/sys/select.h
+instructions.o: /usr/include/bits/select.h /usr/include/bits/sigset.h
+instructions.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h
+instructions.o: /usr/include/bits/pthreadtypes.h /usr/include/alloca.h
+instructions.o: dram_callback.h ../tr1_hash_map.h opcodes.h opcodes.def
+instructions.o: memory.h /usr/include/string.h /usr/include/stdio.h
+instructions.o: /usr/include/libio.h /usr/include/_G_config.h
+instructions.o: /usr/include/wchar.h /usr/include/bits/stdio_lim.h
+instructions.o: /usr/include/bits/sys_errlist.h ../option_parser.h
+instructions.o: /usr/include/math.h /usr/include/bits/huge_val.h
+instructions.o: /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h
+instructions.o: /usr/include/fenv.h /usr/include/bits/fenv.h cuda-math.h
+instructions.o: ptx_loader.h cuda_device_printf.h ../gpgpu-sim/gpu-sim.h
+instructions.o: ../gpgpu-sim/addrdec.h ../gpgpu-sim/shader.h
+instructions.o: ../cuda-sim/dram_callback.h ../gpgpu-sim/delayqueue.h
+instructions.o: ../intersim/statwraper.h ../gpgpu-sim/gpu-misc.h
+instructions.o: ../gpgpu-sim/stack.h ../gpgpu-sim/dram.h /usr/include/zlib.h
+instructions.o: /usr/include/zconf.h /usr/include/unistd.h
+instructions.o: /usr/include/bits/posix_opt.h /usr/include/bits/confname.h
+instructions.o: /usr/include/getopt.h ../gpgpu-sim/scoreboard.h
+instructions.o: ../gpgpu-sim/mem_fetch.h ../gpgpu-sim/stats.h
+instructions.o: ../gpgpu-sim/gpu-cache.h ../gpgpu-sim/shader.h
+memory.o: memory.h ../abstract_hardware_model.h /usr/include/assert.h
+memory.o: /usr/include/features.h /usr/include/sys/cdefs.h
+memory.o: /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h
+memory.o: /usr/include/gnu/stubs-64.h /usr/include/string.h
+memory.o: /usr/include/stdio.h /usr/include/bits/types.h
+memory.o: /usr/include/bits/typesizes.h /usr/include/libio.h
+memory.o: /usr/include/_G_config.h /usr/include/wchar.h
+memory.o: /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
+memory.o: /usr/include/stdlib.h /usr/include/sys/types.h /usr/include/time.h
+memory.o: /usr/include/endian.h /usr/include/bits/endian.h
+memory.o: /usr/include/bits/byteswap.h /usr/include/sys/select.h
+memory.o: /usr/include/bits/select.h /usr/include/bits/sigset.h
+memory.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h
+memory.o: /usr/include/bits/pthreadtypes.h /usr/include/alloca.h ../debug.h
+memory.o: ../abstract_hardware_model.h
+ptx_ir.o: ptx_parser.h ../abstract_hardware_model.h ptx_ir.h
+ptx_ir.o: /usr/include/assert.h /usr/include/features.h
+ptx_ir.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
+ptx_ir.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h ptx_sim.h
+ptx_ir.o: /usr/include/stdlib.h /usr/include/sys/types.h
+ptx_ir.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
+ptx_ir.o: /usr/include/time.h /usr/include/endian.h
+ptx_ir.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
+ptx_ir.o: /usr/include/sys/select.h /usr/include/bits/select.h
+ptx_ir.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
+ptx_ir.o: /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
+ptx_ir.o: /usr/include/alloca.h dram_callback.h ../tr1_hash_map.h opcodes.h
+ptx_ir.o: opcodes.def memory.h /usr/include/string.h /usr/include/stdio.h
+ptx_ir.o: /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h
+ptx_ir.o: /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
+ptx_ir.o: ../option_parser.h cuda-sim.h
+ptx_loader.o: ptx_loader.h ptx_ir.h ../abstract_hardware_model.h
+ptx_loader.o: /usr/include/assert.h /usr/include/features.h
+ptx_loader.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
+ptx_loader.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h ptx_sim.h
+ptx_loader.o: /usr/include/stdlib.h /usr/include/sys/types.h
+ptx_loader.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
+ptx_loader.o: /usr/include/time.h /usr/include/endian.h
+ptx_loader.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
+ptx_loader.o: /usr/include/sys/select.h /usr/include/bits/select.h
+ptx_loader.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
+ptx_loader.o: /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
+ptx_loader.o: /usr/include/alloca.h dram_callback.h ../tr1_hash_map.h
+ptx_loader.o: opcodes.h opcodes.def memory.h /usr/include/string.h
+ptx_loader.o: /usr/include/stdio.h /usr/include/libio.h
+ptx_loader.o: /usr/include/_G_config.h /usr/include/wchar.h
+ptx_loader.o: /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
+ptx_loader.o: ../option_parser.h cuda-sim.h ptx_parser.h
+ptx_loader.o: /usr/include/dirent.h /usr/include/bits/dirent.h
+ptx_loader.o: /usr/include/bits/posix1_lim.h /usr/include/bits/local_lim.h
+ptx_loader.o: /usr/include/linux/limits.h
+ptx_parser.o: ptx_parser.h ../abstract_hardware_model.h ptx_ir.h
+ptx_parser.o: /usr/include/assert.h /usr/include/features.h
+ptx_parser.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
+ptx_parser.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h ptx_sim.h
+ptx_parser.o: /usr/include/stdlib.h /usr/include/sys/types.h
+ptx_parser.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
+ptx_parser.o: /usr/include/time.h /usr/include/endian.h
+ptx_parser.o: /usr/include/bits/endian.h /usr/include/bits/byteswap.h
+ptx_parser.o: /usr/include/sys/select.h /usr/include/bits/select.h
+ptx_parser.o: /usr/include/bits/sigset.h /usr/include/bits/time.h
+ptx_parser.o: /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h
+ptx_parser.o: /usr/include/alloca.h dram_callback.h ../tr1_hash_map.h
+ptx_parser.o: opcodes.h opcodes.def memory.h /usr/include/string.h
+ptx_parser.o: /usr/include/stdio.h /usr/include/libio.h
+ptx_parser.o: /usr/include/_G_config.h /usr/include/wchar.h
+ptx_parser.o: /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
+ptx_parser.o: ../option_parser.h
+ptx_sim.o: ptx_sim.h /usr/include/stdlib.h /usr/include/features.h
+ptx_sim.o: /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h
+ptx_sim.o: /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h
+ptx_sim.o: /usr/include/sys/types.h /usr/include/bits/types.h
+ptx_sim.o: /usr/include/bits/typesizes.h /usr/include/time.h
+ptx_sim.o: /usr/include/endian.h /usr/include/bits/endian.h
+ptx_sim.o: /usr/include/bits/byteswap.h /usr/include/sys/select.h
+ptx_sim.o: /usr/include/bits/select.h /usr/include/bits/sigset.h
+ptx_sim.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h
+ptx_sim.o: /usr/include/bits/pthreadtypes.h /usr/include/alloca.h
+ptx_sim.o: dram_callback.h ../abstract_hardware_model.h ../tr1_hash_map.h
+ptx_sim.o: /usr/include/assert.h opcodes.h opcodes.def memory.h
+ptx_sim.o: /usr/include/string.h /usr/include/stdio.h /usr/include/libio.h
+ptx_sim.o: /usr/include/_G_config.h /usr/include/wchar.h
+ptx_sim.o: /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
+ptx_sim.o: ptx_ir.h ../option_parser.h ../gpgpu-sim/gpu-sim.h
+ptx_sim.o: ../gpgpu-sim/addrdec.h ../gpgpu-sim/shader.h /usr/include/math.h
+ptx_sim.o: /usr/include/bits/huge_val.h /usr/include/bits/mathdef.h
+ptx_sim.o: /usr/include/bits/mathcalls.h ../cuda-sim/dram_callback.h
+ptx_sim.o: ../gpgpu-sim/delayqueue.h ../intersim/statwraper.h
+ptx_sim.o: ../gpgpu-sim/gpu-misc.h ../gpgpu-sim/stack.h ../gpgpu-sim/dram.h
+ptx_sim.o: /usr/include/zlib.h /usr/include/zconf.h /usr/include/unistd.h
+ptx_sim.o: /usr/include/bits/posix_opt.h /usr/include/bits/confname.h
+ptx_sim.o: /usr/include/getopt.h ../gpgpu-sim/scoreboard.h
+ptx_sim.o: ../gpgpu-sim/mem_fetch.h ../gpgpu-sim/stats.h
+ptx_sim.o: ../gpgpu-sim/gpu-cache.h ../gpgpu-sim/shader.h
+ptx-stats.o: ptx_ir.h ../abstract_hardware_model.h /usr/include/assert.h
+ptx-stats.o: /usr/include/features.h /usr/include/sys/cdefs.h
+ptx-stats.o: /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h
+ptx-stats.o: /usr/include/gnu/stubs-64.h ptx_sim.h /usr/include/stdlib.h
+ptx-stats.o: /usr/include/sys/types.h /usr/include/bits/types.h
+ptx-stats.o: /usr/include/bits/typesizes.h /usr/include/time.h
+ptx-stats.o: /usr/include/endian.h /usr/include/bits/endian.h
+ptx-stats.o: /usr/include/bits/byteswap.h /usr/include/sys/select.h
+ptx-stats.o: /usr/include/bits/select.h /usr/include/bits/sigset.h
+ptx-stats.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h
+ptx-stats.o: /usr/include/bits/pthreadtypes.h /usr/include/alloca.h
+ptx-stats.o: dram_callback.h ../tr1_hash_map.h opcodes.h opcodes.def memory.h
+ptx-stats.o: /usr/include/string.h /usr/include/stdio.h /usr/include/libio.h
+ptx-stats.o: /usr/include/_G_config.h /usr/include/wchar.h
+ptx-stats.o: /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
+ptx-stats.o: ../option_parser.h ptx-stats.h
diff --git a/src/gpgpu-sim/delayqueue.h b/src/gpgpu-sim/delayqueue.h
index 050a916..cb5ded0 100644
--- a/src/gpgpu-sim/delayqueue.h
+++ b/src/gpgpu-sim/delayqueue.h
@@ -77,14 +77,14 @@ template <class T>
struct fifo_data {
T *m_data;
fifo_data *m_next;
- unsigned long long push_time; //for stat collection
};
template <class T>
class fifo_pipeline {
public:
- fifo_pipeline(const char* nm, unsigned int minlen, unsigned int maxlen, unsigned long long current_time )
+ fifo_pipeline(const char* nm, unsigned int minlen, unsigned int maxlen )
{
+ assert(maxlen);
m_name = nm;
m_min_len = minlen;
m_max_len = maxlen;
@@ -93,8 +93,7 @@ public:
m_head = NULL;
m_tail = NULL;
for (unsigned i=0;i<m_min_len;i++)
- push(NULL,current_time);
- m_lat_stat = StatCreate(m_name,1,32);
+ push(NULL);
}
~fifo_pipeline()
@@ -106,9 +105,9 @@ public:
}
}
- void push(T* data, unsigned long long current_time )
+ void push(T* data )
{
- if (m_max_len) assert(m_length < m_max_len);
+ assert(m_length < m_max_len);
if (m_head) {
if (m_tail->m_data || m_length < m_min_len) {
m_tail->m_next = new fifo_data<T>();
@@ -123,17 +122,15 @@ public:
}
m_tail->m_next = NULL;
m_tail->m_data = data;
- m_tail->push_time = current_time;
}
- T* pop( unsigned long long current_time )
+ T* pop()
{
fifo_data<T>* next;
T* data;
if (m_head) {
next = m_head->m_next;
data = m_head->m_data;
- StatAddSample(m_lat_stat, LOGB2 (current_time - m_head->push_time));
if ( m_head == m_tail ) {
assert( next == NULL );
m_tail = NULL;
@@ -147,7 +144,7 @@ public:
}
m_n_element--;
if (m_min_len && m_length < m_min_len) {
- push(NULL,current_time);
+ push(NULL);
m_n_element--; // uncount NULL elements inserted to create delays
}
} else {
@@ -165,14 +162,14 @@ public:
}
}
- void set_min_length(unsigned int new_min_len, unsigned long long current_time)
+ void set_min_length(unsigned int new_min_len)
{
if (new_min_len == m_min_len) return;
if (new_min_len > m_min_len) {
m_min_len = new_min_len;
while (m_length < m_min_len) {
- push(NULL,current_time);
+ push(NULL);
m_n_element--; // uncount NULL elements inserted to create delays
}
} else {
@@ -188,7 +185,7 @@ public:
if (!iter) {
// there is only one node, and that node is empty
assert(m_head->m_data == 0);
- pop(current_time);
+ pop();
} else {
// there are more than one node, and tail node is empty
assert(iter->m_next == m_tail);
@@ -206,7 +203,6 @@ public:
unsigned get_n_element() const { return m_n_element; }
unsigned get_length() const { return m_length; }
unsigned get_max_len() const { return m_max_len; }
- void* get_lat_stat() { return m_lat_stat; }
void print() const
{
@@ -229,8 +225,6 @@ private:
fifo_data<T> *m_head;
fifo_data<T> *m_tail;
-
- void* m_lat_stat; //a pointer to latency stats distribution structure
};
#endif
diff --git a/src/gpgpu-sim/dram.cc b/src/gpgpu-sim/dram.cc
index 9f79c7e..a1187ec 100644
--- a/src/gpgpu-sim/dram.cc
+++ b/src/gpgpu-sim/dram.cc
@@ -1,5 +1,5 @@
/*
- * dram.c
+ * dram.cc
*
* Copyright (c) 2009 by Tor M. Aamodt, Wilson W. L. Fung, George L. Yuan,
* Ivan Sham, Justin Kwong, Dan O'Connor and the
@@ -69,6 +69,7 @@
#include "dram.h"
#include "mem_latency_stat.h"
#include "dram_sched.h"
+#include "mem_fetch.h"
#ifdef DRAM_VERIFY
int PRINT_CYCLE = 0;
@@ -98,12 +99,12 @@ dram_t::dram_t( unsigned int partition_id, const struct memory_config *config, m
bk[i]->state = BANK_IDLE;
prio = 0;
- rwq = new fifo_pipeline<dram_req_t>("rwq",m_config->CL,m_config->CL+1,gpu_sim_cycle);
- mrqq = new fifo_pipeline<dram_req_t>("mrqq",0,0,gpu_sim_cycle);
- returnq = new fifo_pipeline<mem_fetch>("dramreturnq",0,m_config->gpgpu_dram_sched_queue_size,gpu_sim_cycle);
+ rwq = new fifo_pipeline<dram_req_t>("rwq",m_config->CL,m_config->CL+1);
+ mrqq = new fifo_pipeline<dram_req_t>("mrqq",0,2);
+ returnq = new fifo_pipeline<mem_fetch>("dramreturnq",0,m_config->gpgpu_dram_sched_queue_size);
m_fast_ideal_scheduler = NULL;
- if ( m_config->scheduler_type == DRAM_IDEAL_FAST )
- m_fast_ideal_scheduler = new ideal_dram_scheduler(m_config,this,stats);
+ if ( m_config->scheduler_type == DRAM_FRFCFS )
+ m_fast_ideal_scheduler = new frfcfs_scheduler(m_config,this,stats);
n_cmd = 0;
n_activity = 0;
n_nop = 0;
@@ -137,24 +138,20 @@ dram_t::dram_t( unsigned int partition_id, const struct memory_config *config, m
mrqq_Dist = StatCreate("mrqq_length",1,64); //track up to 64 entries
}
-int dram_t::full()
+bool dram_t::full() const
{
- int full = 0;
- if ( m_config->gpgpu_dram_sched_queue_size == 0 ) return 0;
- if ( m_config->scheduler_type == DRAM_IDEAL_FAST ) {
- unsigned nreqs = m_fast_ideal_scheduler->num_pending() + mrqq->get_n_element();
- full = (nreqs >= m_config->gpgpu_dram_sched_queue_size);
- } else {
- full = (mrqq->get_length() >= m_config->gpgpu_dram_sched_queue_size);
- }
-
- return full;
+ if( m_config->gpgpu_dram_sched_queue_size == 0 )
+ return false;
+ if( m_config->scheduler_type == DRAM_FRFCFS )
+ return m_fast_ideal_scheduler->num_pending() >= m_config->gpgpu_dram_sched_queue_size;
+ else
+ return mrqq->full();
}
-unsigned int dram_t::que_length() const
+unsigned dram_t::que_length() const
{
unsigned nreqs = 0;
- if (m_config->scheduler_type == DRAM_IDEAL_FAST ) {
+ if (m_config->scheduler_type == DRAM_FRFCFS ) {
nreqs = m_fast_ideal_scheduler->num_pending();
} else {
nreqs = mrqq->get_length();
@@ -195,12 +192,13 @@ dram_req_t::dram_req_t( class mem_fetch *mf )
void dram_t::push( class mem_fetch *data )
{
dram_req_t *mrq = new dram_req_t(data);
- mrqq->push(mrq,gpu_sim_cycle);
+ data->set_status(IN_PARTITION_MC_INTERFACE_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
+ mrqq->push(mrq);
// stats...
n_req += 1;
n_req_partial += 1;
- if ( m_config->scheduler_type == DRAM_IDEAL_FAST ) {
+ if ( m_config->scheduler_type == DRAM_FRFCFS ) {
unsigned nreqs = m_fast_ideal_scheduler->num_pending();
if ( nreqs > max_mrqs_temp)
max_mrqs_temp = nreqs;
@@ -215,10 +213,10 @@ void dram_t::scheduler_fifo()
if (!mrqq->empty()) {
unsigned int bkn;
dram_req_t *head_mrqq = mrqq->top();
+ head_mrqq->data->set_status(IN_PARTITION_MC_BANK_ARB_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
bkn = head_mrqq->bk;
- if (!bk[bkn]->mrq) {
- bk[bkn]->mrq = mrqq->pop(gpu_sim_cycle);
- }
+ if (!bk[bkn]->mrq)
+ bk[bkn]->mrq = mrqq->pop();
}
}
@@ -226,23 +224,40 @@ void dram_t::scheduler_fifo()
#define DEC2ZERO(x) x = (x)? (x-1) : 0;
#define SWAP(a,b) a ^= b; b ^= a; a ^= b;
-void dram_t::issueCMD()
+void dram_t::cycle()
{
- unsigned i,j,k;
- unsigned char issued;
- issued = 0;
+
+ if( !returnq->full() ) {
+ dram_req_t *cmd = rwq->pop();
+ if( cmd ) {
+#ifdef DRAM_VIEWCMD
+ printf("\tDQ: BK%d Row:%03x Col:%03x", cmd->bk, cmd->row, cmd->col + cmd->dqbytes);
+#endif
+ cmd->dqbytes += m_config->BL * m_config->busW * m_config->gpu_n_mem_per_ctrlr; /*16 bytes*/
+ if (cmd->dqbytes >= cmd->nbytes) {
+ mem_fetch *data = cmd->data;
+ data->set_status(IN_PARTITION_MC_RETURNQ,gpu_sim_cycle+gpu_tot_sim_cycle);
+ data->set_type(REPLY_DATA);
+ returnq->push(data);
+ delete cmd;
+ }
+#ifdef DRAM_VIEWCMD
+ printf("\n");
+#endif
+ }
+ }
/* check if the upcoming request is on an idle bank */
/* Should we modify this so that multiple requests are checked? */
switch (m_config->scheduler_type) {
case DRAM_FIFO: scheduler_fifo(); break;
- case DRAM_IDEAL_FAST: fast_scheduler_ideal(); break;
+ case DRAM_FRFCFS: fast_scheduler_ideal(); break;
default:
printf("Error: Unknown DRAM scheduler type\n");
assert(0);
}
- if ( m_config->scheduler_type == DRAM_IDEAL_FAST ) {
+ if ( m_config->scheduler_type == DRAM_FRFCFS ) {
unsigned nreqs = m_fast_ideal_scheduler->num_pending();
if ( nreqs > max_mrqs) {
max_mrqs = nreqs;
@@ -256,11 +271,15 @@ void dram_t::issueCMD()
ave_mrqs += mrqq->get_length();
ave_mrqs_partial += mrqq->get_length();
}
- k=m_config->nbk;
+
+ unsigned k=m_config->nbk;
+ bool issued = false;
+
// check if any bank is ready to issue a new read
- for (i=0;i<m_config->nbk;i++) {
- j = (i + prio) % m_config->nbk;
+ for (unsigned i=0;i<m_config->nbk;i++) {
+ unsigned j = (i + prio) % m_config->nbk;
if (bk[j]->mrq) { //if currently servicing a memory request
+ bk[j]->mrq->data->set_status(IN_PARTITION_DRAM,gpu_sim_cycle+gpu_tot_sim_cycle);
// correct row activated for a READ
if ( !issued && !CCDc && !bk[j]->RCDc &&
(bk[j]->curr_row == bk[j]->mrq->row) &&
@@ -269,13 +288,13 @@ void dram_t::issueCMD()
!rwq->full() ) {
if (rw==WRITE) {
rw=READ;
- rwq->set_min_length(m_config->CL,gpu_sim_cycle);
+ rwq->set_min_length(m_config->CL);
}
- rwq->push(bk[j]->mrq,gpu_sim_cycle);
+ rwq->push(bk[j]->mrq);
bk[j]->mrq->txbytes += m_config->BL * m_config->busW * m_config->gpu_n_mem_per_ctrlr; //16 bytes
CCDc = m_config->tCCD;
RTWc = m_config->tRTW;
- issued = 1;
+ issued = true;
n_rd++;
bwutil+= m_config->BL/2;
bwutil_partial += m_config->BL/2;
@@ -299,13 +318,13 @@ void dram_t::issueCMD()
!rwq->full() ) {
if (rw==READ) {
rw=WRITE;
- rwq->set_min_length(m_config->WL,gpu_sim_cycle);
+ rwq->set_min_length(m_config->WL);
}
- rwq->push(bk[j]->mrq,gpu_sim_cycle);
+ rwq->push(bk[j]->mrq);
bk[j]->mrq->txbytes += m_config->BL * m_config->busW * m_config->gpu_n_mem_per_ctrlr; /*16 bytes*/
CCDc = m_config->tCCD;
- issued = 1;
+ issued = true;
n_wr++;
bwutil+=2;
bwutil_partial += m_config->BL/2;
@@ -340,7 +359,7 @@ void dram_t::issueCMD()
bk[j]->RASc = m_config->tRAS;
bk[j]->RCc = m_config->tRC;
prio = (j + 1) % m_config->nbk;
- issued = 1;
+ issued = true;
n_act_partial++;
n_act++;
}
@@ -355,7 +374,7 @@ void dram_t::issueCMD()
bk[j]->state = BANK_IDLE;
bk[j]->RPc = m_config->tRP;
prio = (j + 1) % m_config->nbk;
- issued = 1;
+ issued = true;
n_pre++;
n_pre_partial++;
#ifdef DRAM_VERIFY
@@ -388,7 +407,7 @@ void dram_t::issueCMD()
DEC2ZERO(CCDc);
DEC2ZERO(RTWc);
DEC2ZERO(WTRc);
- for (j=0;j<m_config->nbk;j++) {
+ for (unsigned j=0;j<m_config->nbk;j++) {
DEC2ZERO(bk[j]->RCDc);
DEC2ZERO(bk[j]->RASc);
DEC2ZERO(bk[j]->RCc);
@@ -404,44 +423,7 @@ void dram_t::issueCMD()
//if mrq is being serviced by dram, gets popped after CL latency fulfilled
class mem_fetch* dram_t::pop()
{
- class mem_fetch *data = NULL;
- dram_req_t *mrq = rwq->pop(gpu_sim_cycle);
- if (mrq) {
-#ifdef DRAM_VIEWCMD
- printf("\tDQ: BK%d Row:%03x Col:%03x",
- mrq->bk, mrq->row, mrq->col + mrq->dqbytes);
-#endif
- mrq->dqbytes += m_config->BL * m_config->busW * m_config->gpu_n_mem_per_ctrlr; /*16 bytes*/
- if (mrq->dqbytes >= mrq->nbytes) {
- if (m_config->gpgpu_memlatency_stat) {
- unsigned dq_latency = gpu_sim_cycle + gpu_tot_sim_cycle - mrq->timestamp;
- m_stats->dq_lat_table[LOGB2(dq_latency)]++;
- if (dq_latency > m_stats->max_dq_latency)
- m_stats->max_dq_latency = dq_latency;
- }
- data = mrq->data;
- delete mrq;
- }
- }
-#ifdef DRAM_VIEWCMD
- printf("\n");
-#endif
- return data;
-}
-
-void dram_t::returnq_push( class mem_fetch *mf, unsigned long long gpu_sim_cycle)
-{
- returnq->push(mf,gpu_sim_cycle);
-}
-
-class mem_fetch* dram_t::returnq_pop( unsigned long long gpu_sim_cycle)
-{
- return returnq->pop(gpu_sim_cycle);
-}
-
-class mem_fetch* dram_t::returnq_top()
-{
- return returnq->top();
+ return returnq->pop();
}
void dram_t::print( FILE* simFile) const
@@ -501,15 +483,6 @@ void dram_t::print_stat( FILE* simFile )
max_mrqs_temp = 0;
}
-void dram_t::queue_latency_log_dump( FILE *fp )
-{
- fprintf(fp,"(LOGB2)Latency DRAM[%d] ",id);
- StatDisp(mrqq->get_lat_stat());
- fprintf(fp,"(LOGB2)Latency DRAM[%d] ",id);
- StatDisp(rwq->get_lat_stat());
- dram_log(DUMPLOG);
-}
-
void dram_t::visualizer_print( gzFile visualizer_file )
{
// dram specific statistics
diff --git a/src/gpgpu-sim/dram.h b/src/gpgpu-sim/dram.h
index cf9f68d..2a94a31 100644
--- a/src/gpgpu-sim/dram.h
+++ b/src/gpgpu-sim/dram.h
@@ -125,22 +125,18 @@ class dram_t
public:
dram_t( unsigned int parition_id, const struct memory_config *config, class memory_stats_t *stats );
- int full();
+ bool full() const;
void print( FILE* simFile ) const;
void visualize() const;
void print_stat( FILE* simFile );
- unsigned int que_length() const;
+ unsigned que_length() const;
bool returnq_full() const;
unsigned int queue_limit() const;
void visualizer_print( gzFile visualizer_file );
class mem_fetch* pop();
- void returnq_push( class mem_fetch *mf, unsigned long long gpu_sim_cycle);
- class mem_fetch* returnq_pop( unsigned long long gpu_sim_cycle);
- class mem_fetch* returnq_top();
void push( class mem_fetch *data );
- void issueCMD();
- void queue_latency_log_dump( FILE *fp );
+ void cycle();
void dram_log (int task);
struct memory_partition_unit *m_memory_partition_unit;
@@ -188,7 +184,7 @@ private:
unsigned int max_mrqs;
unsigned int ave_mrqs;
- class ideal_dram_scheduler* m_fast_ideal_scheduler;
+ class frfcfs_scheduler* m_fast_ideal_scheduler;
unsigned int n_cmd_partial;
unsigned int n_activity_partial;
@@ -202,7 +198,7 @@ private:
struct memory_stats_t *m_stats;
class Stats* mrqq_Dist; //memory request queue inside DRAM
- friend class ideal_dram_scheduler;
+ friend class frfcfs_scheduler;
};
#endif /*DRAM_H*/
diff --git a/src/gpgpu-sim/dram_sched.cc b/src/gpgpu-sim/dram_sched.cc
index 110894f..8881e8f 100644
--- a/src/gpgpu-sim/dram_sched.cc
+++ b/src/gpgpu-sim/dram_sched.cc
@@ -70,7 +70,7 @@
#include "../abstract_hardware_model.h"
#include "mem_latency_stat.h"
-ideal_dram_scheduler::ideal_dram_scheduler( const memory_config *config, dram_t *dm, memory_stats_t *stats )
+frfcfs_scheduler::frfcfs_scheduler( const memory_config *config, dram_t *dm, memory_stats_t *stats )
{
m_config = config;
m_stats = stats;
@@ -91,20 +91,15 @@ ideal_dram_scheduler::ideal_dram_scheduler( const memory_config *config, dram_t
}
-void ideal_dram_scheduler::add_req( dram_req_t *req )
+void frfcfs_scheduler::add_req( dram_req_t *req )
{
m_num_pending++;
-
m_queue[req->bk].push_front(req);
std::list<dram_req_t*>::iterator ptr = m_queue[req->bk].begin();
-
m_bins[req->bk][req->row].push_front( ptr ); //newest reqs to the front
-
-
}
-
-inline void ideal_dram_scheduler::data_collection(unsigned int bank)
+void frfcfs_scheduler::data_collection(unsigned int bank)
{
if (gpu_sim_cycle > row_service_timestamp[bank]) {
curr_row_service_time[bank] = gpu_sim_cycle - row_service_timestamp[bank];
@@ -120,7 +115,7 @@ inline void ideal_dram_scheduler::data_collection(unsigned int bank)
m_stats->num_activates[m_dram->id][bank]++;
}
-dram_req_t *ideal_dram_scheduler::schedule( unsigned bank, unsigned curr_row )
+dram_req_t *frfcfs_scheduler::schedule( unsigned bank, unsigned curr_row )
{
int row_hit = 0;
if ( m_last_row[bank] == NULL ) {
@@ -164,7 +159,7 @@ dram_req_t *ideal_dram_scheduler::schedule( unsigned bank, unsigned curr_row )
}
-void ideal_dram_scheduler::print( FILE *fp )
+void frfcfs_scheduler::print( FILE *fp )
{
for ( unsigned b=0; b < m_config->nbk; b++ ) {
printf(" %u: queue length = %u\n", b, (unsigned)m_queue[b].size() );
@@ -174,9 +169,10 @@ void ideal_dram_scheduler::print( FILE *fp )
void dram_t::fast_scheduler_ideal()
{
unsigned mrq_latency;
- ideal_dram_scheduler *sched = m_fast_ideal_scheduler;
+ frfcfs_scheduler *sched = m_fast_ideal_scheduler;
while ( !mrqq->empty() && (!m_config->gpgpu_dram_sched_queue_size || sched->num_pending() < m_config->gpgpu_dram_sched_queue_size)) {
- dram_req_t *req = mrqq->pop(gpu_sim_cycle);
+ dram_req_t *req = mrqq->pop();
+ req->data->set_status(IN_PARTITION_MC_INPUT_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
sched->add_req(req);
}
@@ -189,6 +185,7 @@ void dram_t::fast_scheduler_ideal()
req = sched->schedule(b, bk[b]->curr_row);
if ( req ) {
+ req->data->set_status(IN_PARTITION_MC_BANK_ARB_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
prio = (prio+1)%m_config->nbk;
bk[b]->mrq = req;
if (m_config->gpgpu_memlatency_stat) {
diff --git a/src/gpgpu-sim/dram_sched.h b/src/gpgpu-sim/dram_sched.h
index eaad744..9f99209 100644
--- a/src/gpgpu-sim/dram_sched.h
+++ b/src/gpgpu-sim/dram_sched.h
@@ -74,13 +74,11 @@
#include <list>
#include <map>
-class ideal_dram_scheduler {
+class frfcfs_scheduler {
public:
- ideal_dram_scheduler( const memory_config *config, dram_t *dm, memory_stats_t *stats );
+ frfcfs_scheduler( const memory_config *config, dram_t *dm, memory_stats_t *stats );
void add_req( dram_req_t *req );
- std::list<dram_req_t*>::iterator binarysort_VFTF(dram_req_t *req);
- std::list<dram_req_t*>::iterator sort_VFTF(dram_req_t *req);
- inline void data_collection(unsigned bank);
+ void data_collection(unsigned bank);
dram_req_t *schedule( unsigned bank, unsigned curr_row );
void print( FILE *fp );
unsigned num_pending() const { return m_num_pending;}
diff --git a/src/gpgpu-sim/gpu-cache.cc b/src/gpgpu-sim/gpu-cache.cc
index 98909ce..b26afb2 100644
--- a/src/gpgpu-sim/gpu-cache.cc
+++ b/src/gpgpu-sim/gpu-cache.cc
@@ -1,5 +1,5 @@
/*
- * gpu-cache.c
+ * gpu-cache.cc
*
* Copyright (c) 2009 by Tor M. Aamodt, Wilson W. L. Fung, Ali Bakhoda,
* George L. Yuan and the
@@ -65,291 +65,163 @@
*/
#include "gpu-cache.h"
-#include "gpu-misc.h"
-#include "addrdec.h"
#include "stat-tool.h"
-#include "gpu-sim.h"
#include <assert.h>
-#include <string.h>
-cache_t::~cache_t()
+tag_array::~tag_array()
{
delete m_lines;
}
-cache_t::cache_t( const char *name, const cache_config &config, int core_id, int type_id )
+tag_array::tag_array( const cache_config &config, int core_id, int type_id )
: m_config(config)
{
- m_name = name;
- m_nset = config.nset;
- m_nset_log2 = LOGB2(config.nset);
- m_assoc = config.assoc;
- m_line_sz = config.line_sz;
- m_line_sz_log2 = LOGB2(config.line_sz);
- m_replacement_policy = config.replacement_policy;
- m_write_policy = config.get_write_policy();
- unsigned nlines = config.get_num_lines();
- m_lines = new cache_block_t[nlines];
+ assert( m_config.m_write_policy == READ_ONLY );
+ m_lines = new cache_block_t[ config.get_num_lines()];
// initialize snapshot counters for visualizer
m_prev_snapshot_access = 0;
m_prev_snapshot_miss = 0;
- m_prev_snapshot_merge_hit = 0;
+ m_prev_snapshot_pending_hit = 0;
m_core_id = core_id;
m_type_id = type_id;
}
-enum cache_request_status cache_t::access( new_addr_type addr, bool write, unsigned int cycle, address_type *wb_address )
+enum cache_request_status tag_array::probe( new_addr_type addr, unsigned &idx ) const
{
- m_access++;
- unsigned set_index = (addr >> m_line_sz_log2) & ( (1<<m_nset_log2) - 1 );
- new_addr_type tag = addr >> (m_line_sz_log2 + m_nset_log2);
+ assert( m_config.m_write_policy == READ_ONLY );
+ unsigned set_index = m_config.set_index(addr);
+ new_addr_type tag = m_config.tag(addr);
- bool all_reserved = true;
- cache_block_t *pending_line = NULL;
- cache_block_t *clean_line = NULL;
+ unsigned invalid_line = (unsigned)-1;
+ unsigned valid_line = (unsigned)-1;
+ unsigned valid_timestamp = (unsigned)-1;
- shader_cache_access_log(m_core_id, m_type_id, 0);
-
- for (unsigned way=0; way<m_assoc; way++) {
- cache_block_t *line = &(m_lines[set_index*m_assoc+way] );
- if (line->tag == tag) {
- if (line->status & RESERVED) {
- pending_line = line;
- break;
- } else if (line->status & VALID) {
- line->last_used = cycle;
- if (write)
- line->status |= DIRTY;
- if (m_write_policy == write_through)
- return HIT_W_WT;
- return HIT;
- }
- }
- if (!(line->status & RESERVED)) {
- all_reserved = false;
- if (!(line->status & VALID))
- clean_line = line;
- }
+ bool all_reserved = true;
+
+ // check for hit or pending hit
+ for (unsigned way=0; way<m_config.m_assoc; way++) {
+ unsigned index = set_index*m_config.m_assoc+way;
+ cache_block_t *line = &m_lines[index];
+ if (line->m_tag == tag) {
+ if( line->m_status == RESERVED ) {
+ idx = index;
+ return HIT_RESERVED;
+ } else if( line->m_status == VALID ) {
+ idx = index;
+ return HIT;
+ } else {
+ assert( line->m_status == INVALID );
+ }
+ }
+ if(line->m_status != RESERVED) {
+ all_reserved = false;
+ if(line->m_status == INVALID) {
+ invalid_line = index;
+ } else {
+ // valid line : keep track of most appropriate replacement candidate
+ if( m_config.m_replacement_policy == LRU ) {
+ if( line->m_last_access_time < valid_timestamp ) {
+ valid_timestamp = line->m_last_access_time;
+ valid_line = index;
+ }
+ } else if( m_config.m_replacement_policy == FIFO ) {
+ if( line->m_alloc_time < valid_timestamp ) {
+ valid_timestamp = line->m_alloc_time;
+ valid_line = index;
+ }
+ }
+ }
+ }
}
- m_miss++;
- shader_cache_access_log(m_core_id, m_type_id, 1);
-
- if (pending_line || m_write_policy != write_back || write) {
- if (pending_line) {
- if( write ) // write hit-under-miss (irrelevant whether write-back or write-through)
- // - timing assumes a large enough write buffer in shader core that we never
- // encounter a structural hazard
- // - write buffer merged with returning cache block in zero cycles
- pending_line->status |= DIRTY;
- return WB_HIT_ON_MISS;
- }
- return MISS_NO_WB;
+ if( all_reserved ) {
+ assert( m_config.m_alloc_policy == ON_MISS );
+ return RESERVATION_FAIL; // miss and not enough space in cache to allocate on miss
}
- // at this point: this must be a write back cache (and not a hit-under-miss)
- assert( m_write_policy == write_back );
+ if( invalid_line != (unsigned)-1 ) {
+ idx = invalid_line;
+ } else if( valid_line != (unsigned)-1) {
+ idx = valid_line;
+ } else abort(); // if an unreserved block exists, it is either invalid or replaceable
- if (all_reserved)
- // cannot service this request, because we can't garantee that we have room for the line when it comes back
- return RESERVATION_FAIL;
+ return MISS;
+}
- if (clean_line) {
- // found a clean line in the cache so, no need to do a writeback
- clean_line->status |= RESERVED;
- clean_line->tag = tag;
- return MISS_NO_WB;
- }
+enum cache_request_status tag_array::access( new_addr_type addr, unsigned time, unsigned &idx )
+{
+ m_access++;
+ shader_cache_access_log(m_core_id, m_type_id, 0); // log accesses to cache
+ enum cache_request_status status = probe(addr,idx);
+ switch(status) {
+ case HIT_RESERVED:
+ m_pending_hit++;
+ case HIT:
+ m_lines[idx].m_last_access_time=time;
+ break;
+ case MISS:
+ m_miss++;
+ shader_cache_access_log(m_core_id, m_type_id, 1); // log cache misses
+ if( m_config.m_alloc_policy == ON_MISS )
+ m_lines[idx].allocate( m_config.tag(addr), m_config.block_addr(addr), time );
+ break;
+ case RESERVATION_FAIL:
+ m_miss++;
+ shader_cache_access_log(m_core_id, m_type_id, 1); // log cache misses
+ break;
+ }
+ return status;
+}
- // no clean lines, need to kick a line out to reserve a spot
- cache_block_t *wb_line = NULL;
-
- for (unsigned way=0; way<m_assoc; way++) {
- cache_block_t *line = &(m_lines[set_index*m_assoc+way] );
- if (line->status & VALID && !(line->status & RESERVED)) {
- if (!wb_line) {
- wb_line = line;
- continue;
- }
- switch (m_replacement_policy) {
- case LRU:
- if (line->last_used < wb_line->last_used)
- wb_line = line;
- break;
- case FIFO:
- if (line->fetch_time < wb_line->fetch_time)
- wb_line = line;
- break;
- default:
- abort();
- }
- }
- }
- assert(wb_line); // should always find a line
- assert((wb_line->status & (DIRTY|VALID)) == (DIRTY|VALID)); // should be dirty (or we would have found a clean line earlier)
-
- // reserve line
- wb_line->status = RESERVED;
- wb_line->tag = tag;
- *wb_address = wb_line->addr;
+void tag_array::fill( new_addr_type addr, unsigned time )
+{
+ assert( m_config.m_alloc_policy == ON_FILL );
+ unsigned idx;
+ enum cache_request_status status = probe(addr,idx);
+ assert(status==MISS); // MSHR should have prevented redundant memory request
+ m_lines[idx].allocate( m_config.tag(addr), m_config.block_addr(addr), time );
+ m_lines[idx].fill(time);
+}
- return MISS_W_WB;
+void tag_array::fill( unsigned index, unsigned time )
+{
+ assert( m_config.m_alloc_policy == ON_MISS );
+ m_lines[index].fill(time);
}
-// Obtain the windowed cache miss rate for visualizer
-float cache_t::windowed_cache_miss_rate( int minus_merge_hit )
+void tag_array::flush()
{
- cache_t *cp = this;
- unsigned int n_access = cp->m_access - cp->m_prev_snapshot_access;
- unsigned int n_miss = cp->m_miss - cp->m_prev_snapshot_miss;
- unsigned int n_merge_hit = cp->m_merge_hit - cp->m_prev_snapshot_merge_hit;
+ for (unsigned i=0; i < m_config.get_num_lines(); i++)
+ m_lines[i].m_status = INVALID;
+}
+
+float tag_array::windowed_miss_rate( bool minus_pending_hit ) const
+{
+ unsigned n_access = m_access - m_prev_snapshot_access;
+ unsigned n_miss = m_miss - m_prev_snapshot_miss;
+ unsigned n_pending_hit = m_pending_hit - m_prev_snapshot_pending_hit;
- if (minus_merge_hit)
- n_miss -= n_merge_hit;
+ if (minus_pending_hit)
+ n_miss -= n_pending_hit;
float missrate = 0.0f;
if (n_access != 0)
missrate = (float) n_miss / n_access;
-
return missrate;
}
-// start a new sampling window
-void cache_t::new_window()
+void tag_array::new_window()
{
m_prev_snapshot_access = m_access;
m_prev_snapshot_miss = m_miss;
- m_prev_snapshot_merge_hit = m_merge_hit;
-}
-
-// Fetch requested data into cache line.
-// Returning address on the replaced line if it is dirty, or -1 if it is clean
-// Assume the line is filled all at once.
-new_addr_type cache_t::fill( new_addr_type addr, unsigned int sim_cycle )
-{
- unsigned int base = 0 ;
- unsigned int maxway = m_assoc;
- cache_block_t *pline, *cline;
- new_addr_type packed_addr = addr;
- unsigned set = (packed_addr >> m_line_sz_log2) & ( (1<<m_nset_log2) - 1 );
- unsigned long long tag = packed_addr >> (m_line_sz_log2 + m_nset_log2);
-
- if (m_write_policy == write_back) {
- //this request must have a reserved spot
- cline = NULL;
- for (unsigned i=base; i<maxway; i++) {
- pline = &(m_lines[set*m_assoc+i] );
- if ((pline->tag == tag) && (pline->status & RESERVED)) {
- cline = pline;
- break;
- }
- if ((pline->tag == tag) && (pline->status & VALID)) {
- //A second fill has returned to a line in the cache
- //discard it as line in cache may have been modified, or is the same
- return -1;
- }
- }
-
- if (!cline) printf("----!!! about to abort - this probably happened because global memory msrh merging is not enabled with a writeback cache !!!----\n");
-
- assert(cline); //error if it doesn't have a reserved space
-
- /* Fetch data into block */
- cline->status &= ~RESERVED;
- cline->status |= VALID;
- //cline->status &= ~DIRTY; Don't clear dirty bit, as might be dirty from write.
- cline->tag = tag;
- cline->addr = addr;
- cline->last_used = sim_cycle;
- cline->fetch_time = sim_cycle;
-
- // no wb, already handled.
- return -1;
- }
-
- //behavior unchanged for write through cache... probably not all necessary.
-
- // Look for any free slots and the possibility that the line is in the cache already
- bool nofreeslot = true;
- bool line_exists = false;
- for (unsigned i=base; i<maxway; i++) {
- pline = &(m_lines[set*m_assoc+i] );
- if (!(pline->status & VALID)) {
- cline = pline;
- nofreeslot = false;
- break;
- } else if (pline->tag == tag) {
- cline = pline;
- line_exists = true;
- break;
- }
- }
-
- if (line_exists) {
- return -1; // don't need to spill any line, nor it needs to be filled
- }
-
- if (nofreeslot) {
- cline = &(m_lines[set*m_assoc+base] );
- for (unsigned i=1+base; i<maxway; i++) {
- pline = &(m_lines[set*m_assoc+i] );
- if (pline->status & VALID) {
- switch (m_replacement_policy) {
- case LRU:
- if (pline->last_used < cline->last_used)
- cline = pline;
- break;
- case FIFO:
- if (pline->fetch_time < cline->fetch_time)
- cline = pline;
- break;
- default:
- break;
- }
- }
- }
- }
-
- /* Set the replaced cache line address */
- unsigned long long int repl_addr;
- if ((cline->status & (DIRTY|VALID)) == (DIRTY|VALID)) {
- repl_addr = cline->addr;
- } else {
- repl_addr = -1;
- }
-
- /* Fetch data into block */
- cline->status |= VALID;
- cline->status &= ~DIRTY;
- cline->tag = tag;
- cline->addr = addr;
- cline->last_used = sim_cycle;
- cline->fetch_time = sim_cycle;
-
- return repl_addr;
-}
-
-unsigned int cache_t::flush()
-{
- int dirty_lines_flushed = 0 ;
- for (unsigned i = 0; i < m_nset * m_assoc ; i++) {
- if ( (m_lines[i].status & (DIRTY|VALID)) == (DIRTY|VALID) ) {
- dirty_lines_flushed++;
- }
- m_lines[i].status &= ~VALID;
- m_lines[i].status &= ~DIRTY;
- }
- return dirty_lines_flushed;
+ m_prev_snapshot_pending_hit = m_pending_hit;
}
-void cache_t::print( FILE *stream, unsigned &total_access, unsigned &total_misses )
+void tag_array::print( FILE *stream, unsigned &total_access, unsigned &total_misses ) const
{
- fprintf( stream, "Cache %s:\t", m_name.c_str() );
- fprintf( stream, "Size = %d B (%d Set x %d-way x %d byte line)\n",
- m_line_sz * m_nset * m_assoc,
- m_nset, m_assoc, m_line_sz );
+ m_config.print(stream);
fprintf( stream, "\t\tAccess = %d, Miss = %d (%.3g), -MgHts = %d (%.3g)\n",
m_access, m_miss, (float) m_miss / m_access,
- m_miss - m_merge_hit, (float) (m_miss - m_merge_hit) / m_access);
+ m_miss - m_pending_hit, (float) (m_miss - m_pending_hit) / m_access);
total_misses+=m_miss;
total_access+=m_access;
}
diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h
index 89a2ed0..440b98b 100644
--- a/src/gpgpu-sim/gpu-cache.h
+++ b/src/gpgpu-sim/gpu-cache.h
@@ -1,5 +1,5 @@
/*
- * gpu-cache.c
+ * gpu-cache.h
*
* Copyright (c) 2009 by Tor M. Aamodt, Wilson W. L. Fung, Ali Bakhoda,
* George L. Yuan and the
@@ -64,57 +64,84 @@
* Vancouver, BC V6T 1Z4
*/
+#ifndef GPU_CACHE_H
+#define GPU_CACHE_H
+
#include <stdio.h>
#include <stdlib.h>
+#include "gpu-misc.h"
+#include "mem_fetch.h"
#include "../abstract_hardware_model.h"
+#include "../tr1_hash_map.h"
-#ifndef GPU_CACHE_H
-#define GPU_CACHE_H
+class mem_fetch; // mem_fetch opaque to cache and mshrs
-#define VALID 0x01 // block is valid (and present in cache)
-#define DIRTY 0x02 // block is dirty
-#define RESERVED 0x04 // there is an outstanding request for this block, but it has not returned yet
+enum cache_block_state {
+ INVALID,
+ RESERVED,
+ VALID
+};
enum cache_request_status {
HIT,
- HIT_W_WT, // Hit, but write through cache, still needs to send to memory
- MISS_NO_WB, // miss, but witeback not necessary
- MISS_W_WB, // miss, must do writeback
- WB_HIT_ON_MISS, // request hit on a reservation in wb cache
- RESERVATION_FAIL,
- NUM_CACHE_REQUEST_STATUS
+ HIT_RESERVED,
+ MISS,
+ RESERVATION_FAIL
};
struct cache_block_t {
cache_block_t()
{
- tag=0;
- addr=0;
- fetch_time=0;
- last_used=0;
- status=0;
+ m_tag=0;
+ m_block_addr=0;
+ m_alloc_time=0;
+ m_fill_time=0;
+ m_last_access_time=0;
+ m_status=INVALID;
+ }
+ void allocate( new_addr_type tag, new_addr_type block_addr, unsigned time )
+ {
+ m_tag=tag;
+ m_block_addr=block_addr;
+ m_alloc_time=time;
+ m_last_access_time=time;
+ m_fill_time=0;
+ m_status=RESERVED;
+ }
+ void fill( unsigned time )
+ {
+ assert( m_status == RESERVED );
+ m_status=VALID;
+ m_fill_time=time;
}
- new_addr_type tag;
- new_addr_type addr;
- unsigned fetch_time;
- unsigned last_used;
- unsigned char status; /* valid, dirty... etc */
+
+ new_addr_type m_tag;
+ new_addr_type m_block_addr;
+ unsigned m_alloc_time;
+ unsigned m_last_access_time;
+ unsigned m_fill_time;
+ cache_block_state m_status;
};
-enum replacement_policy {
+enum replacement_policy_t {
LRU,
FIFO
};
-enum write_policy {
- no_writes, // line replacement when new line arrives
- write_back, // line replacement when new line arrives
- write_through // reservation based, use much handle reservation full error.
+enum write_policy_t {
+ READ_ONLY,
+ WRITE_BACK,
+ WRITE_THROUGH
};
-enum allocation_policy {
- on_miss,
- on_fill
+enum allocation_policy_t {
+ ON_MISS,
+ ON_FILL
+};
+
+enum mshr_config_t {
+ TEX_FIFO,
+ ASSOC // normal cache
};
class cache_config {
@@ -127,94 +154,356 @@ public:
void init()
{
assert( m_config_string );
- int ntok = sscanf(m_config_string,"%d:%d:%d:%c:%c:%c", &nset, &line_sz, &assoc, &replacement_policy, &write_policy, &alloc_policy);
- if( ntok != 6 ) {
- printf("GPGPU-Sim uArch: cache configuration parsing error (%s)\n", m_config_string );
- abort();
+ char rp, wp, ap, mshr_type;
+ int ntok = sscanf(m_config_string,"%u:%u:%u:%c:%c:%c,%c:%u:%u,%u",
+ &m_nset, &m_line_sz, &m_assoc, &rp, &wp, &ap,
+ &mshr_type,&m_mshr_entries,&m_mshr_max_merge,&m_miss_queue_size);
+ if( ntok < 10 )
+ exit_parse_error();
+ switch(rp) {
+ case 'L': m_replacement_policy = LRU; break;
+ case 'F': m_replacement_policy = FIFO; break;
+ default: exit_parse_error();
+ }
+ switch(wp) {
+ case 'R': m_write_policy = READ_ONLY; break;
+ case 'B': m_write_policy = WRITE_BACK; break;
+ case 'T': m_write_policy = WRITE_THROUGH; break;
+ default: exit_parse_error();
}
+ switch(ap) {
+ case 'm': m_alloc_policy = ON_MISS; break;
+ case 'f': m_alloc_policy = ON_FILL; break;
+ default: exit_parse_error();
+ }
+ switch(mshr_type) {
+ case 'F': m_mshr_type = TEX_FIFO; break;
+ case 'A': m_mshr_type = ASSOC; break;
+ default: exit_parse_error();
+ }
+ m_line_sz_log2 = LOGB2(m_line_sz);
+ m_nset_log2 = LOGB2(m_nset);
m_valid = true;
}
unsigned get_line_sz() const
{
assert( m_valid );
- return line_sz;
+ return m_line_sz;
}
unsigned get_num_lines() const
{
assert( m_valid );
- return nset * assoc;
+ return m_nset * m_assoc;
}
- enum write_policy get_write_policy() const
+ void print( FILE *fp ) const
{
- if( write_policy == 'R' )
- return no_writes;
- else if( write_policy == 'B' )
- return write_back;
- else if( write_policy == 'T' )
- return write_through;
- else
- abort();
+ fprintf( fp, "Size = %d B (%d Set x %d-way x %d byte line)\n",
+ m_line_sz * m_nset * m_assoc,
+ m_nset, m_assoc, m_line_sz );
+ }
+
+ unsigned set_index( new_addr_type addr ) const
+ {
+ return (addr >> m_line_sz_log2) & (m_nset-1);
+ }
+ new_addr_type tag( new_addr_type addr ) const
+ {
+ return addr >> (m_line_sz_log2+m_nset_log2);
+ }
+ new_addr_type block_addr( new_addr_type addr ) const
+ {
+ return addr & ~(m_line_sz-1);
}
char *m_config_string;
private:
+ void exit_parse_error()
+ {
+ printf("GPGPU-Sim uArch: cache configuration parsing error (%s)\n", m_config_string );
+ abort();
+ }
+
bool m_valid;
- unsigned int nset;
- unsigned int line_sz;
- unsigned int assoc;
- unsigned char replacement_policy; // 'L' = LRU, 'F' = FIFO, 'R' = RANDOM
- unsigned char write_policy; // 'T' = write through, 'B' = write back, 'R' = read only
- unsigned char alloc_policy; // 'm' = allocate on miss, 'f' = allocate on fill
+ unsigned m_line_sz;
+ unsigned m_line_sz_log2;
+ unsigned m_nset;
+ unsigned m_nset_log2;
+ unsigned m_assoc;
+
+ enum replacement_policy_t m_replacement_policy; // 'L' = LRU, 'F' = FIFO
+ enum write_policy_t m_write_policy; // 'T' = write through, 'B' = write back, 'R' = read only
+ enum allocation_policy_t m_alloc_policy; // 'm' = allocate on miss, 'f' = allocate on fill
+ enum mshr_config_t m_mshr_type;
+ unsigned m_mshr_entries;
+ unsigned m_mshr_max_merge;
+ unsigned m_miss_queue_size;
+
+ friend class tag_array;
friend class cache_t;
};
-class cache_t {
+class tag_array {
public:
- cache_t( const char *name, const cache_config &config, int core_id, int type_id );
- ~cache_t();
+ tag_array( const cache_config &config, int core_id, int type_id );
+ ~tag_array();
- enum cache_request_status access( new_addr_type addr,
- bool write,
- unsigned int sim_cycle,
- address_type *wb_address );
+ enum cache_request_status probe( new_addr_type addr, unsigned &idx ) const;
+ enum cache_request_status access( new_addr_type addr, unsigned time, unsigned &idx );
- new_addr_type fill( new_addr_type addr, unsigned int sim_cycle );
+ void fill( new_addr_type addr, unsigned time );
+ void fill( unsigned idx, unsigned time );
- unsigned flush();
-
- void print( FILE *stream, unsigned &total_access, unsigned &total_misses );
- float windowed_cache_miss_rate(int);
- void new_window();
+ void flush(); // flash invalidate all entries
+ void new_window();
+
+ void print( FILE *stream, unsigned &total_access, unsigned &total_misses ) const;
+ float windowed_miss_rate( bool minus_pending_hit ) const;
+
+protected:
-private:
- std::string m_name;
const cache_config &m_config;
cache_block_t *m_lines; /* nbanks x nset x assoc lines in total */
- unsigned m_n_banks;
- unsigned m_nset;
- unsigned m_nset_log2;
- unsigned m_assoc;
- unsigned m_line_sz; // bytes
- unsigned m_line_sz_log2;
-
- enum write_policy m_write_policy;
- unsigned char m_replacement_policy;
unsigned m_access;
unsigned m_miss;
- unsigned m_merge_hit; // number of cache miss that hit the same line (and merged as a result)
+ unsigned m_pending_hit; // number of cache miss that hit a line that is allocated but not filled
// performance counters for calculating the amount of misses within a time window
unsigned m_prev_snapshot_access;
unsigned m_prev_snapshot_miss;
- unsigned m_prev_snapshot_merge_hit;
+ unsigned m_prev_snapshot_pending_hit;
int m_core_id; // which shader core is using this
int m_type_id; // what kind of cache is this (normal, texture, constant)
};
+class mshr_table {
+public:
+ mshr_table( unsigned num_entries, unsigned max_merged )
+ : m_num_entries(num_entries),
+ m_max_merged(max_merged),
+#ifndef USE_MAP
+ m_data(2*num_entries)
+#endif
+ {
+ }
+
+ // is there a pending request to the lower memory level already?
+ bool probe( new_addr_type block_addr ) const
+ {
+ table::const_iterator a = m_data.find(block_addr);
+ return a != m_data.end();
+ }
+
+ // is there space for tracking a new memory access?
+ bool full( new_addr_type block_addr ) const
+ {
+ table::const_iterator i=m_data.find(block_addr);
+ if( i != m_data.end() )
+ return i->second.size() >= m_max_merged;
+ else
+ return m_data.size() >= m_num_entries;
+ }
+
+ // add or merge this access
+ void add( new_addr_type block_addr, mem_fetch *mf )
+ {
+ m_data[block_addr].push_back(mf);
+ assert( m_data.size() <= m_num_entries );
+ assert( m_data[block_addr].size() <= m_max_merged );
+ }
+
+ // true if cannot accept new fill responses
+ bool busy() const
+ {
+ return false;
+ }
+
+ // accept a new cache fill response: mark entry ready for processing
+ void mark_ready( new_addr_type block_addr )
+ {
+ assert( !busy() );
+ table::iterator a = m_data.find(block_addr);
+ assert( a != m_data.end() ); // don't remove same request twice
+ m_current_response.push_back( block_addr );
+ assert( m_current_response.size() <= m_data.size() );
+ }
+
+ // true if ready accesses exist
+ bool access_ready() const
+ {
+ return !m_current_response.empty();
+ }
+
+ // next ready access
+ mem_fetch *next_access()
+ {
+ assert( access_ready() );
+ new_addr_type block_addr = m_current_response.front();
+ assert( !m_data[block_addr].empty() );
+ mem_fetch *result = m_data[block_addr].front();
+ m_data[block_addr].pop_front();
+ if( m_data[block_addr].empty() ) {
+ // release entry
+ m_data.erase(block_addr);
+ m_current_response.pop_front();
+ }
+ return result;
+ }
+
+ void display( FILE *fp ) const
+ {
+ fprintf(fp,"MSHR contents\n");
+ for( table::const_iterator e=m_data.begin(); e!=m_data.end(); ++e ) {
+ unsigned block_addr = e->first;
+ fprintf(fp,"MSHR: tag=0x%06x, %zu entries : ", block_addr, e->second.size());
+ if( !e->second.empty() ) {
+ mem_fetch *mf = e->second.front();
+ fprintf(fp,"%p :",mf);
+ mf->print(fp);
+ } else {
+ fprintf(fp," no memory requests???\n");
+ }
+ }
+ }
+
+private:
+
+ // finite sized, fully associative table, with a finite maximum number of merged requests
+ const unsigned m_num_entries;
+ const unsigned m_max_merged;
+
+ typedef std::list<mem_fetch*> entry;
+ typedef my_hash_map<new_addr_type,entry> table;
+ table m_data;
+
+ // it may take several cycles to process the merged requests
+ bool m_current_response_ready;
+ std::list<new_addr_type> m_current_response;
+};
+
+class cache_t {
+public:
+ cache_t( const char *name, const cache_config &config, int core_id, int type_id, mem_fetch_interface *memport )
+ : m_config(config), m_tag_array(config,core_id,type_id), m_mshrs(config.m_mshr_entries,config.m_mshr_max_merge)
+ {
+ m_name = name;
+ assert(config.m_mshr_type == ASSOC);
+ assert(config.m_write_policy == READ_ONLY);
+ m_memport=memport;
+ }
+
+ // access cache: returns RESERVATION_FAIL if request could not be accepted (for any reason)
+ enum cache_request_status access( new_addr_type addr, mem_fetch *mf, unsigned time )
+ {
+ new_addr_type block_addr = m_config.block_addr(addr);
+ unsigned cache_index = (unsigned)-1;
+ enum cache_request_status status = m_tag_array.probe(block_addr,cache_index);
+ if( status == HIT )
+ return HIT;
+ if( status != RESERVATION_FAIL ) {
+ bool mshr_hit = m_mshrs.probe(block_addr);
+ bool mshr_avail = !m_mshrs.full(block_addr);
+ if( mshr_hit && mshr_avail ) {
+ m_tag_array.access(addr,time,cache_index);
+ m_mshrs.add(block_addr,mf);
+ return MISS;
+ } else if( !mshr_hit && mshr_avail && (m_miss_queue.size() < m_config.m_miss_queue_size) ) {
+ m_tag_array.access(addr,time,cache_index);
+ m_mshrs.add(block_addr,mf);
+ m_extra_mf_fields[mf] = extra_mf_fields(block_addr,cache_index);
+ m_miss_queue.push_back(mf);
+ return MISS;
+ }
+ }
+ return RESERVATION_FAIL;
+ }
+
+ void cycle()
+ {
+ // send next request to lower level of memory
+ if( !m_miss_queue.empty() ) {
+ mem_fetch *mf = m_miss_queue.front();
+ if( !m_memport->full(mf->get_data_size(),mf->get_is_write()) ) {
+ m_miss_queue.pop_front();
+ m_memport->push(mf);
+ }
+ }
+ }
+
+ // interface for response from lower memory level (model bandwidth restictions in caller)
+ void fill( mem_fetch *mf, unsigned time )
+ {
+ extra_mf_fields_lookup::iterator e = m_extra_mf_fields.find(mf);
+ assert( e != m_extra_mf_fields.end() );
+ assert( e->second.m_valid );
+ if ( m_config.m_alloc_policy == ON_MISS )
+ m_tag_array.fill(e->second.m_cache_index,time);
+ else if ( m_config.m_alloc_policy == ON_FILL )
+ m_tag_array.fill(e->second.m_block_addr,time);
+ else abort();
+ m_mshrs.mark_ready(e->second.m_block_addr);
+ m_extra_mf_fields.erase(mf);
+ }
+
+ // are any (accepted) accesses that had to wait for memory now ready? (does not include accesses that "HIT")
+ bool access_ready() const
+ {
+ return m_mshrs.access_ready();
+ }
+
+ // pop next ready access (does not include accesses that "HIT")
+ mem_fetch *next_access()
+ {
+ return m_mshrs.next_access();
+ }
+
+ // flash invalidate all entries in cache
+ void flush()
+ {
+ m_tag_array.flush();
+ }
+
+ void print(FILE *fp, unsigned &accesses, unsigned &misses) const
+ {
+ fprintf( fp, "Cache %s:\t", m_name.c_str() );
+ m_tag_array.print(fp,accesses,misses);
+ }
+
+ void display_state( FILE *fp ) const
+ {
+ fprintf(fp,"Cache %s:\n", m_name.c_str() );
+ m_mshrs.display(fp);
+ fprintf(fp,"\n");
+ }
+
+private:
+ std::string m_name;
+ const cache_config &m_config;
+ tag_array m_tag_array;
+ mshr_table m_mshrs;
+ std::list<mem_fetch*> m_miss_queue;
+ mem_fetch_interface *m_memport;
+
+ struct extra_mf_fields {
+ extra_mf_fields() { m_valid = false; }
+ extra_mf_fields( new_addr_type a, unsigned i )
+ {
+ m_block_addr = a;
+ m_cache_index = i;
+ m_valid = true;
+ }
+ bool m_valid;
+ new_addr_type m_block_addr;
+ unsigned m_cache_index;
+ };
+ typedef std::map<mem_fetch*,extra_mf_fields> extra_mf_fields_lookup;
+ extra_mf_fields_lookup m_extra_mf_fields;
+};
+
+
#endif
diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc
index b3bc56a..0228704 100644
--- a/src/gpgpu-sim/gpu-sim.cc
+++ b/src/gpgpu-sim/gpu-sim.cc
@@ -177,14 +177,6 @@ void gpgpu_sim::reg_options(option_parser_t opp)
"per-shader L1 constant memory cache (READ-ONLY) config, i.e., {<nsets>:<linesize>:<assoc>:<repl>|none}",
"64:64:2:L:R:f");
- option_parser_register(opp, "-gpgpu_no_dl1", OPT_BOOL, &m_shader_config->gpgpu_no_dl1,
- "no dl1 cache (voids -gpgpu_cache:dl1 option)",
- "0");
-
- option_parser_register(opp, "-gpgpu_cache:dl1", OPT_CSTR, &m_shader_config->m_L1D_config.m_config_string,
- "shader L1 data cache config, i.e., {<nsets>:<bsize>:<assoc>:<repl>|none}",
- "256:128:1:L");
-
option_parser_register(opp, "-gpgpu_cache:il1", OPT_CSTR, &m_shader_config->m_L1I_config.m_config_string,
"shader L1 instruction cache config, i.e., {<nsets>:<bsize>:<assoc>:<repl>|none}",
"4:256:4:L:R:f");
@@ -238,10 +230,6 @@ void gpgpu_sim::reg_options(option_parser_t opp)
"Number of MSHRs per shader",
"64");
- option_parser_register(opp, "-gpgpu_interwarp_mshr_merge", OPT_INT32, &m_shader_config->gpgpu_interwarp_mshr_merge,
- "interwarp coalescing",
- "0");
-
option_parser_register(opp, "-gpgpu_dram_sched_queue_size", OPT_INT32, &m_memory_config->gpgpu_dram_sched_queue_size,
"0 = unlimited (default); # entries per chip",
"0");
@@ -279,15 +267,10 @@ void gpgpu_sim::reg_options(option_parser_t opp)
"Stop the simulation at deadlock (1=on (default), 0=off)",
"1");
- option_parser_register(opp, "-gpgpu_n_cache_bank", OPT_INT32, &m_shader_config->gpgpu_n_cache_bank,
- "Number of banks in L1 cache, also for memory coalescing stall",
- "1");
-
option_parser_register(opp, "-gpgpu_warpdistro_shader", OPT_INT32, &m_shader_config->gpgpu_warpdistro_shader,
"Specify which shader core to collect the warp size distribution from",
"-1");
-
option_parser_register(opp, "-gpgpu_pdom_sched_type", OPT_INT32, &m_pdom_sched_type,
"0 = first ready warp found, 1 = random, 8 = loose round robin",
"8");
@@ -311,12 +294,6 @@ void gpgpu_sim::reg_options(option_parser_t opp)
option_parser_register(opp, "-gpgpu_shmem_port_per_bank", OPT_INT32, &m_shader_config->gpgpu_shmem_port_per_bank,
"Number of access processed by a shared memory bank per cycle (default = 2)",
"2");
- option_parser_register(opp, "-gpgpu_cache_port_per_bank", OPT_INT32, &m_shader_config->gpgpu_cache_port_per_bank,
- "Number of access processed by a cache bank per cycle (default = 2)",
- "2");
- option_parser_register(opp, "-gpgpu_const_port_per_bank", OPT_INT32, &m_shader_config->gpgpu_const_port_per_bank,
- "Number of access processed by a constant cache bank per cycle (default = 2)",
- "2");
option_parser_register(opp, "-gpgpu_cflog_interval", OPT_INT32, &gpgpu_cflog_interval,
"Interval between each snapshot in control flow logger",
"0");
@@ -438,6 +415,9 @@ void gpgpu_sim::init_gpu()
set_ptx_warp_size(m_shader_config);
m_shader_config->init();
+ m_memory_config->init();
+
+ ptx_set_tex_cache_linesize(m_shader_config->m_L1T_config.get_line_sz());
m_shader_stats->num_warps_issuable = (int*) calloc(m_shader_config->max_warps_per_shader+1, sizeof(int));
m_shader_stats->num_warps_issuable_pershader = (int*) calloc(m_shader_config->n_simt_clusters*m_shader_config->n_simt_cores_per_cluster, sizeof(int));
@@ -461,15 +441,14 @@ void gpgpu_sim::init_gpu()
m_memory_stats = new memory_stats_t(num_shader(),m_shader_config,m_memory_config);
- m_memory_config->init();
m_memory_partition_unit = new memory_partition_unit*[m_memory_config->m_n_mem];
for (unsigned i=0;i<m_memory_config->m_n_mem;i++)
m_memory_partition_unit[i] = new memory_partition_unit(i, m_memory_config, m_memory_stats);
icnt_init(m_shader_config->n_simt_clusters, m_memory_config->m_n_mem,m_shader_config);
- time_vector_create(NUM_MEM_REQ_STAT,MR_2SH_ICNT_INJECTED);
- fprintf(stdout, "GPU performance model initialization complete.\n");
+ time_vector_create(NUM_MEM_REQ_STAT);
+ fprintf(stdout, "GPGPU-Sim uArch: performance model initialization complete.\n");
init_clock_domains();
}
@@ -637,15 +616,6 @@ unsigned int gpgpu_sim::run_gpu_sim()
icnt_overal_stat();
printf("----------------------------END-of-Interconnect-DETAILS-------------------------" );
}
- if (m_memory_config->gpgpu_memlatency_stat & GPU_MEMLATSTAT_QUEUELOGS ) {
- for (unsigned i=0;i<m_memory_config->m_n_mem;i++)
- m_memory_partition_unit[i]->queue_latency_log_dump(stdout);
- if (m_memory_config->m_L2_config.get_num_lines() > 0 ) {
- for(unsigned i=0; i<m_memory_config->m_n_mem; i++)
- m_memory_partition_unit[i]->L2c_log(DUMPLOG);
- L2c_latency_log_dump();
- }
- }
if (gpu_deadlock_detect && gpu_deadlock) {
fflush(stdout);
@@ -727,9 +697,6 @@ void gpgpu_sim::gpu_print_stat() const
//for (unsigned i=0; i< m_n_shader; i++) printf("%d ", m_sc[i]->get_max_mshr_used() );
//printf("\n");
- if (m_memory_config->m_L2_config.get_num_lines())
- m_memory_stats->L2c_print_stat( m_memory_config->m_n_mem );
-
for (unsigned i=0;i<m_memory_config->m_n_mem;i++)
m_memory_partition_unit[i]->print(stdout);
/*
@@ -789,8 +756,6 @@ void gpgpu_sim::shader_print_accstats( FILE* fout ) const
fprintf(fout, "gpgpu_n_intrawarp_mshr_merge = %d\n", m_shader_stats->gpgpu_n_intrawarp_mshr_merge);
fprintf(fout, "gpgpu_n_cmem_portconflict = %d\n", m_shader_stats->gpgpu_n_cmem_portconflict);
- fprintf(fout, "gpgpu_n_partial_writes = %d\n", m_shader_stats->gpgpu_n_partial_writes);
-
fprintf(fout, "gpgpu_stall_shd_mem[c_mem][bk_conf] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[C_MEM][BK_CONF]);
fprintf(fout, "gpgpu_stall_shd_mem[c_mem][mshr_rc] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[C_MEM][MSHR_RC_FAIL]);
fprintf(fout, "gpgpu_stall_shd_mem[c_mem][icnt_rc] = %d\n", m_shader_stats->gpu_stall_shd_mem_breakdown[C_MEM][ICNT_RC_FAIL]);
@@ -834,7 +799,7 @@ unsigned gpgpu_sim::threads_per_core() const
return m_shader_config->n_thread_per_shader;
}
-void gpgpu_sim::mem_instruction_stats(warp_inst_t &inst)
+void gpgpu_sim::mem_instruction_stats(const warp_inst_t &inst)
{
//this breaks some encapsulation: the is_[space] functions, if you change those, change this.
switch (inst.space.get_type()) {
@@ -938,95 +903,6 @@ void shader_core_ctx::issue_block2core( kernel_info_t &kernel )
///////////////////////////////////////////////////////////////////////////////////////////
-void memory_partition_unit::push( mem_fetch* req, unsigned long long cycle )
-{
- if (req) {
- m_request_tracker.insert(req);
- rop_delay_t r;
- r.req = req;
- r.ready_cycle = cycle + 115; // Add 115*4=460 delay cycles
- m_rop.push(r);
- }
- if ( !m_rop.empty() && (cycle >= m_rop.front().ready_cycle) ) {
- mem_fetch* mf = m_rop.front().req;
- m_rop.pop();
- m_stats->memlatstat_icnt2mem_pop(mf);
- if (m_config->m_L2_config.get_num_lines()) {
- if (m_config->gpgpu_l2_readoverwrite && mf->get_is_write())
- m_icnt2cache_write_queue->push(mf,gpu_sim_cycle);
- else
- m_icnt2cache_queue->push(mf,gpu_sim_cycle);
- m_accessLocality->access(mf);
- mf->set_status(IN_CBTOL2QUEUE,MR_DRAMQ,gpu_sim_cycle+gpu_tot_sim_cycle);
- } else {
- m_dram->push(mf);
- mf->set_status(IN_DRAM_REQ_QUEUE,MR_DRAMQ,gpu_sim_cycle+gpu_tot_sim_cycle);
- }
- }
-}
-
-mem_fetch* memory_partition_unit::pop()
-{
- mem_fetch* mf;
- if( m_config->m_L2_config.get_num_lines()) {
- mf = L2tocbqueue->pop(gpu_sim_cycle);
- if( mf && mf->isatomic() )
- mf->do_atomic();
- } else {
- mf = m_dram->returnq_pop(gpu_sim_cycle);
- if( mf ) {
- mf->set_type( REPLY_DATA );
- if( mf->isatomic() )
- mf->do_atomic();
- }
- }
- m_request_tracker.erase(mf);
- return mf;
-}
-
-mem_fetch* memory_partition_unit::top()
-{
- if (m_config->m_L2_config.get_num_lines()) {
- return L2tocbqueue->top();
- } else {
- mem_fetch* mf = m_dram->returnq_top();
- if (mf) mf->set_type( REPLY_DATA );
- return mf;
- }
-}
-
-void memory_partition_unit::issueCMD()
-{
- if (m_config->m_L2_config.get_num_lines()) {
- // pop completed memory request from dram and push it to dram-to-L2 queue
- if ( !(dramtoL2queue->full() || dramtoL2writequeue->full()) ) {
- mem_fetch* mf = m_dram->pop();
- if (mf) {
- if( mf->get_mem_acc() == L2_WRBK_ACC ) {
- m_request_tracker.erase(mf);
- delete mf;
- } else {
- if (m_config->gpgpu_l2_readoverwrite && mf->get_is_write() )
- dramtoL2writequeue->push(mf,gpu_sim_cycle);
- else
- dramtoL2queue->push(mf,gpu_sim_cycle);
- mf->set_status(IN_DRAMTOL2QUEUE,MR_DRAM_OUTQ,gpu_sim_cycle+gpu_tot_sim_cycle);
- }
- }
- }
- } else {
- if ( m_dram->returnq_full() )
- return;
- mem_fetch* mf = m_dram->pop();
- if (mf) {
- m_dram->returnq_push(mf,gpu_sim_cycle);
- mf->set_status(IN_DRAMRETURN_Q,MR_DRAM_OUTQ,gpu_sim_cycle+gpu_tot_sim_cycle);
- }
- }
- m_dram->issueCMD();
- m_dram->dram_log(SAMPLELOG);
-}
-
void dram_t::dram_log( int task )
{
if (task == SAMPLELOG) {
@@ -1078,25 +954,23 @@ void gpgpu_sim::cycle()
for (unsigned i=0;i<m_memory_config->m_n_mem;i++) {
mem_fetch* mf = m_memory_partition_unit[i]->top();
if (mf) {
- mf->set_status(IN_ICNT2SHADER,MR_2SH_ICNT_PUSHED,gpu_sim_cycle+gpu_tot_sim_cycle);
unsigned response_size = mf->get_is_write()?mf->get_ctrl_size():mf->size();
if ( ::icnt_has_buffer( m_shader_config->mem2device(i), response_size ) ) {
if (!mf->get_is_write())
mf->set_return_timestamp(gpu_sim_cycle+gpu_tot_sim_cycle);
+ mf->set_status(IN_ICNT_TO_SHADER,gpu_sim_cycle+gpu_tot_sim_cycle);
::icnt_push( m_shader_config->mem2device(i), mf->get_tpc(), mf, response_size );
m_memory_partition_unit[i]->pop();
} else {
gpu_stall_icnt2sh++;
}
- } else {
- m_memory_partition_unit[i]->pop();
}
}
}
if (clock_mask & DRAM) {
for (unsigned i=0;i<m_memory_config->m_n_mem;i++)
- m_memory_partition_unit[i]->issueCMD(); // Issue the dram command (scheduler + delay model)
+ m_memory_partition_unit[i]->dram_cycle(); // Issue the dram command (scheduler + delay model)
}
// L2 operations follow L2 clock domain
@@ -1214,8 +1088,6 @@ void gpgpu_sim::cycle()
}
}
- for (unsigned i=0;i<m_memory_config->m_n_mem;i++)
- m_memory_stats->acc_mrq_length[i] += m_memory_partition_unit[i]->dram_que_length();
if (!(gpu_sim_cycle % 20000)) {
// deadlock detection
if (gpu_deadlock_detect && gpu_sim_insn == last_gpu_sim_insn) {
diff --git a/src/gpgpu-sim/gpu-sim.h b/src/gpgpu-sim/gpu-sim.h
index b881806..0c1a473 100644
--- a/src/gpgpu-sim/gpu-sim.h
+++ b/src/gpgpu-sim/gpu-sim.h
@@ -71,7 +71,6 @@
#include "../abstract_hardware_model.h"
#include "addrdec.h"
-#include "gpu-cache.h"
#include "shader.h"
#include <list>
@@ -86,7 +85,6 @@
#define GPU_RSTAT_PDOM 0x20
#define GPU_RSTAT_SCHED 0x40
#define GPU_MEMLATSTAT_MC 0x2
-#define GPU_MEMLATSTAT_QUEUELOGS 0x4
// constants for configuring merging of coalesced scatter-gather requests
#define TEX_MSHR_MERGE 0x4
@@ -102,7 +100,7 @@
enum dram_ctrl_t {
DRAM_FIFO=0,
- DRAM_IDEAL_FAST=1
+ DRAM_FRFCFS=1
};
struct memory_config {
@@ -128,31 +126,30 @@ struct memory_config {
char *gpgpu_dram_timing_opt;
char *gpgpu_L2_queue_config;
- bool gpgpu_l2_readoverwrite;
bool l2_ideal;
unsigned gpgpu_dram_sched_queue_size;
enum dram_ctrl_t scheduler_type;
bool gpgpu_memlatency_stat;
unsigned m_n_mem;
- unsigned int gpu_n_mem_per_ctrlr;
+ unsigned gpu_n_mem_per_ctrlr;
// DRAM parameters
- unsigned int tCCD; //column to column delay
- unsigned int tRRD; //minimal time required between activation of rows in different banks
- unsigned int tRCD; //row to column delay - time required to activate a row before a read
- unsigned int tRCDWR; //row to column delay for a write command
- unsigned int tRAS; //time needed to activate row
- unsigned int tRP; //row precharge ie. deactivate row
- unsigned int tRC; //row cycle time ie. precharge current, then activate different row
+ unsigned tCCD; //column to column delay
+ unsigned tRRD; //minimal time required between activation of rows in different banks
+ unsigned tRCD; //row to column delay - time required to activate a row before a read
+ unsigned tRCDWR; //row to column delay for a write command
+ unsigned tRAS; //time needed to activate row
+ unsigned tRP; //row precharge ie. deactivate row
+ unsigned tRC; //row cycle time ie. precharge current, then activate different row
- unsigned int CL; //CAS latency
- unsigned int WL; //WRITE latency
- unsigned int BL; //Burst Length in bytes (we're using 4? could be 8)
- unsigned int tRTW; //time to switch from read to write
- unsigned int tWTR; //time to switch from write to read 5? look in datasheet
- unsigned int busW;
+ unsigned CL; //CAS latency
+ unsigned WL; //WRITE latency
+ unsigned BL; //Burst Length in bytes (we're using 4? could be 8)
+ unsigned tRTW; //time to switch from read to write
+ unsigned tWTR; //time to switch from write to read 5? look in datasheet
+ unsigned busW;
- unsigned int nbk;
+ unsigned nbk;
linear_to_raw_address_translation m_address_mapping;
};
@@ -195,7 +192,7 @@ public:
unsigned num_shader() const { return m_shader_config->n_simt_clusters*m_shader_config->n_simt_cores_per_cluster; }
unsigned threads_per_core() const;
- void mem_instruction_stats( class warp_inst_t &inst);
+ void mem_instruction_stats( const class warp_inst_t &inst);
void gpu_print_stat() const;
void dump_pipeline( int mask, int s, int m ) const;
@@ -213,8 +210,6 @@ private:
void cycle();
void L2c_options(class OptionParser *opp);
void L2c_print_cache_stat() const;
- void L2c_print_debug();
- void L2c_latency_log_dump();
void shader_print_runtime_stat( FILE *fout );
void shader_print_l1_miss_stat( FILE *fout );
void shader_print_accstats( FILE* fout ) const;
diff --git a/src/gpgpu-sim/l2cache.cc b/src/gpgpu-sim/l2cache.cc
index d2b61d7..634fa55 100644
--- a/src/gpgpu-sim/l2cache.cc
+++ b/src/gpgpu-sim/l2cache.cc
@@ -83,649 +83,211 @@
#include "shader.h"
#include "mem_latency_stat.h"
-template class fifo_pipeline<mem_fetch>;
-
-address_type L2c_mshr::cache_tag(const mem_fetch *mf) const
-{
- return (mf->get_addr() & ~(m_linesize - 1));
-}
-
-address_type L2c_miss_tracker::cache_tag(const mem_fetch *mf) const
-{
- return (mf->get_addr() & ~(m_linesize - 1));
-}
-
-address_type L2c_access_locality::cache_tag(const mem_fetch *mf) const
-{
- return (mf->get_addr() & ~(m_linesize - 1));
-}
-
void gpgpu_sim::L2c_options(option_parser_t opp)
{
- option_parser_register(opp, "-gpgpu_L2_queue", OPT_CSTR, &m_memory_config->gpgpu_L2_queue_config,
- "L2 data cache queue length and latency config",
- "0:0:0:0:0:0:10:10");
+ option_parser_register(opp, "-gpgpu_dram_partition_queues", OPT_CSTR, &m_memory_config->gpgpu_L2_queue_config,
+ "i2$:$2d:d2$:$2i",
+ "8:8:8:8");
- option_parser_register(opp, "-gpgpu_l2_readoverwrite", OPT_BOOL, &m_memory_config->gpgpu_l2_readoverwrite,
- "Prioritize read requests over write requests for L2",
- "0");
-
- option_parser_register(opp, "-l2_ideal", OPT_BOOL, &m_memory_config->l2_ideal,
- "Use a ideal L2 cache that always hit",
- "0");
+ option_parser_register(opp, "-l2_ideal", OPT_BOOL, &m_memory_config->l2_ideal,
+ "Use a ideal L2 cache that always hit",
+ "0");
}
+//////////
-////////////////////////////////////////////////
-// L2 MSHR model
-
-bool L2c_mshr::new_miss(const mem_fetch *mf)
-{
- address_type cacheTag = cache_tag(mf);
- mem_fetch_list &missGroup = m_L2missgroup[cacheTag];
-
- bool mshr_hit = not missGroup.empty();
-
- missGroup.push_front(mf);
-
- m_n_miss += 1;
- if (mshr_hit)
- m_n_mshr_hits += 1;
- m_entries_used += 1;
- m_max_entries_used = std::max(m_max_entries_used, m_entries_used);
-
- return mshr_hit;
-}
-
-void L2c_mshr::miss_serviced(const mem_fetch *mf)
-{
- assert(m_active_mshr_chain.list == NULL);
- address_type cacheTag = cache_tag(mf);
- L2missGroup::iterator missGroup = m_L2missgroup.find(cacheTag);
- if (missGroup == m_L2missgroup.end() || mf->get_type() == L2_WTBK_DATA) {
- assert(mf->get_type() == L2_WTBK_DATA); // only this returning mem req can be missed by the MSHR
- return;
- }
- assert(missGroup->first == cacheTag);
-
- m_active_mshr_chain.cacheTag = cacheTag;
- m_active_mshr_chain.list = &(missGroup->second);
-
- m_n_miss_serviced_by_dram += 1;
-}
-
-bool L2c_mshr::mshr_chain_empty()
-{
- return (m_active_mshr_chain.list == NULL);
-}
-
-mem_fetch *L2c_mshr::mshr_chain_top()
-{
- const mem_fetch *mf = m_active_mshr_chain.list->back();
- assert(cache_tag(mf) == m_active_mshr_chain.cacheTag);
-
- return const_cast<mem_fetch*>(mf);
-}
-
-void L2c_mshr::mshr_chain_pop()
-{
- m_entries_used -= 1;
- m_active_mshr_chain.list->pop_back();
- if (m_active_mshr_chain.list->empty()) {
- address_type cacheTag = m_active_mshr_chain.cacheTag;
- m_L2missgroup.erase(cacheTag);
- m_active_mshr_chain.list = NULL;
- }
-}
-
-void L2c_mshr::print(FILE *fout)
-{
- fprintf(fout, "L2c MSHR: n_entries_used = %zu\n", m_entries_used);
- L2missGroup::iterator missGroup;
- for (missGroup = m_L2missgroup.begin(); missGroup != m_L2missgroup.end(); ++missGroup) {
- fprintf(fout, "%#08x: ", missGroup->first);
- mem_fetch_list &mf_list = missGroup->second;
- for (mem_fetch_list::iterator imf = mf_list.begin(); imf != mf_list.end(); ++imf)
- (*imf)->print(fout);
- fprintf(fout, "\n");
- }
-}
-
-void L2c_mshr::print_stat(FILE *fout) const
-{
- fprintf(fout, "L2c MSHR: max_entry = %zu, n_miss = %d, n_mshr_hits = %d, n_serviced_by_dram %d\n",
- m_max_entries_used, m_n_miss, m_n_mshr_hits, m_n_miss_serviced_by_dram);
-}
-
-////////////////////////////////////////////////
-// track redundant dram access generated by L2 cache
-
-void L2c_miss_tracker::new_miss(mem_fetch *mf)
-{
- address_type cacheTag = cache_tag(mf);
- mem_fetch_set &missGroup = m_L2missgroup[cacheTag];
-
- if (missGroup.size() != 0) {
- m_L2redundantCnt[cacheTag] += 1;
- m_totalL2redundantAcc += 1;
- }
-
- missGroup.insert(mf);
-}
-
-void L2c_miss_tracker::miss_serviced(mem_fetch *mf)
-{
- address_type cacheTag = cache_tag(mf);
- L2missGroup::iterator iMissGroup = m_L2missgroup.find(cacheTag);
- if (iMissGroup == m_L2missgroup.end()) return; // this is possible for write miss
- mem_fetch_set &missGroup = iMissGroup->second;
-
- missGroup.erase(mf);
-
- // remove the miss group if it goes empty
- if (missGroup.empty()) {
- m_L2missgroup.erase(iMissGroup);
- }
-}
-
-void L2c_miss_tracker::print(FILE *fout, bool brief)
-{
- L2missGroup::iterator iMissGroup;
- for (iMissGroup = m_L2missgroup.begin(); iMissGroup != m_L2missgroup.end(); ++iMissGroup) {
- fprintf(fout, "%#08x: ", iMissGroup->first);
- for (mem_fetch_set::iterator iMemSet = iMissGroup->second.begin(); iMemSet != iMissGroup->second.end(); ++iMemSet) {
- fprintf(fout, "%p ", *iMemSet);
- }
- fprintf(fout, "\n");
- }
-}
-
-void L2c_miss_tracker::print_stat(FILE *fout, bool brief) const
-{
- fprintf(fout, "RedundantMiss = %d\n", m_totalL2redundantAcc);
- if (brief == true) return;
- fprintf(fout, " Detail:");
- for (L2redundantCnt::const_iterator iL2rc = m_L2redundantCnt.begin(); iL2rc != m_L2redundantCnt.end(); ++iL2rc) {
- fprintf(fout, "%#08x:%d ", iL2rc->first, iL2rc->second);
- }
- fprintf(fout, "\n");
-}
-
-////////////////////////////////////////////////
-// track all locality of L2 cache access
-void L2c_access_locality::access(mem_fetch *mf)
-{
- address_type cacheTag = cache_tag(mf);
- m_L2accCnt[cacheTag] += 1;
- m_totalL2accAcc += 1;
-}
-
-void L2c_access_locality::print_stat(FILE *fout, bool brief) const
-{
- float access_locality = (float) m_totalL2accAcc / m_L2accCnt.size();
- fprintf(fout, "Access Locality = %d / %zu (%f) \n", m_totalL2accAcc, m_L2accCnt.size(), access_locality);
- if (brief == true) return;
- fprintf(fout, " Detail:");
- pow2_histogram locality_histo(" Hits");
- for (L2accCnt::const_iterator iL2rc = m_L2accCnt.begin(); iL2rc != m_L2accCnt.end(); ++iL2rc) {
- locality_histo.add2bin(iL2rc->second);
- }
- locality_histo.fprint(fout);
- fprintf(fout, "\n");
-}
-
-memory_partition_unit::~memory_partition_unit()
-{
- delete m_mshr;
- delete m_missTracker;
- delete m_accessLocality;
-}
-
-void memory_partition_unit::cache_cycle()
-{
- process_dram_output(); // pop from dram
- L2c_push_miss_to_dram(); // push to dram
- L2c_service_mem_req(); // pop(push) from(to) icnt2l2(l2toicnt) queues; service l2 requests
- if (m_config->m_L2_config.get_num_lines()) { // L2 cache enabled
- L2c_update_stat();
- L2c_log(SAMPLELOG);
- }
-}
-
-unsigned memory_partition_unit::L2c_get_linesize()
-{
- return m_config->m_L2_config.get_line_sz();
-}
-
-bool memory_partition_unit::full() const
-{
- if (m_config->m_L2_config.get_num_lines()) {
- return m_icnt2cache_queue->full() || m_icnt2cache_write_queue->full();
- } else {
- return( m_config->gpgpu_dram_sched_queue_size && m_dram->full() );
- }
-}
-
-////////////////////////////////////////////////
-// L2 access functions
-
-// L2 Cache Creation
memory_partition_unit::memory_partition_unit( unsigned partition_id,
struct memory_config *config,
class memory_stats_t *stats )
{
- m_id = partition_id;
- m_config=config;
- m_stats=stats;
- m_dram = new dram_t(m_id,m_config,m_stats);
+ m_id = partition_id;
+ m_config=config;
+ m_stats=stats;
+ m_dram = new dram_t(m_id,m_config,m_stats);
- if( m_config->m_L2_config.get_num_lines() ) {
- char L2c_name[32];
- snprintf(L2c_name, 32, "L2_bank_%03d", m_id);
- m_L2cache = new cache_t(L2c_name,m_config->m_L2_config,-1,-1);
- unsigned l2_line_sz = m_config->m_L2_config.get_line_sz();
- m_mshr = new L2c_mshr( l2_line_sz );
- m_missTracker = new L2c_miss_tracker( l2_line_sz );
- m_accessLocality = new L2c_access_locality( l2_line_sz );
- } else {
- m_L2cache=NULL;
- m_mshr=NULL;
- m_missTracker=NULL;
- m_accessLocality=NULL;
- }
+ char L2c_name[32];
+ snprintf(L2c_name, 32, "L2_bank_%03d", m_id);
+ m_L2interface = new L2interface(this);
+ m_L2cache = new cache_t(L2c_name,m_config->m_L2_config,-1,-1,m_L2interface);
- unsigned int L2c_cb_L2_length;
- unsigned int L2c_cb_L2w_length;
- unsigned int L2c_L2_dm_length;
- unsigned int L2c_dm_L2_length;
- unsigned int L2c_dm_L2w_length;
- unsigned int L2c_L2_cb_length;
- unsigned int L2c_L2_cb_minlength;
- unsigned int L2c_L2_dm_minlength;
+ unsigned int icnt_L2;
+ unsigned int L2_dram;
+ unsigned int dram_L2;
+ unsigned int L2_icnt;
- sscanf(m_config->gpgpu_L2_queue_config,"%d:%d:%d:%d:%d:%d:%d:%d",
- &L2c_cb_L2_length, &L2c_cb_L2w_length, &L2c_L2_dm_length,
- &L2c_dm_L2_length, &L2c_dm_L2w_length, &L2c_L2_cb_length,
- &L2c_L2_cb_minlength, &L2c_L2_dm_minlength );
- //(<name>,<latency>,<min_length>,<max_length>)
- m_icnt2cache_queue = new fifo_pipeline<mem_fetch>("cbtoL2queue", 0,L2c_cb_L2_length, gpu_sim_cycle);
- m_icnt2cache_write_queue = new fifo_pipeline<mem_fetch>("cbtoL2writequeue", 0,L2c_cb_L2w_length, gpu_sim_cycle);
- L2todramqueue = new fifo_pipeline<mem_fetch>("L2todramqueue", L2c_L2_dm_minlength, L2c_L2_dm_length, gpu_sim_cycle);
- dramtoL2queue = new fifo_pipeline<mem_fetch>("dramtoL2queue", 0,L2c_dm_L2_length, gpu_sim_cycle);
- dramtoL2writequeue = new fifo_pipeline<mem_fetch>("dramtoL2writequeue",0,L2c_dm_L2w_length, gpu_sim_cycle);
- L2tocbqueue = new fifo_pipeline<mem_fetch>("L2tocbqueue", L2c_L2_cb_minlength, L2c_L2_cb_length, gpu_sim_cycle);
- L2todram_wbqueue = new fifo_pipeline<mem_fetch>("L2todram_wbqueue", L2c_L2_dm_minlength, L2c_L2_dm_minlength + m_config->gpgpu_dram_sched_queue_size + L2c_dm_L2_length, gpu_sim_cycle);
- L2dramout = NULL;
- wb_addr=-1;
- if (m_config->m_L2_config.get_num_lines() && 1) {
- cbtol2_Dist = StatCreate("cbtoL2",1, m_icnt2cache_queue->get_max_len());
- cbtoL2wr_Dist = StatCreate("cbtoL2write",1, m_icnt2cache_write_queue->get_max_len());
- L2tocb_Dist = StatCreate("L2tocb",1, L2tocbqueue->get_max_len());
- dramtoL2_Dist = StatCreate("dramtoL2",1, dramtoL2queue->get_max_len());
- dramtoL2wr_Dist = StatCreate("dramtoL2write",1, dramtoL2writequeue->get_max_len());
- L2todram_Dist = StatCreate("L2todram",1, L2todramqueue->get_max_len());
- L2todram_wb_Dist = StatCreate("L2todram_wb",1, L2todram_wbqueue->get_max_len());
- } else {
- cbtol2_Dist = NULL;
- cbtoL2wr_Dist = NULL;
- L2tocb_Dist = NULL;
- dramtoL2_Dist = NULL;
- dramtoL2wr_Dist = NULL;
- L2todram_Dist = NULL;
- L2todram_wb_Dist = NULL;
- }
+ sscanf(m_config->gpgpu_L2_queue_config,"%u:%u:%u:%u", &icnt_L2,&L2_dram,&dram_L2,&L2_icnt );
+ m_icnt_L2_queue = new fifo_pipeline<mem_fetch>("icnt-to-L2",0,icnt_L2);
+ m_L2_dram_queue = new fifo_pipeline<mem_fetch>("L2-to-dram",0,L2_dram);
+ m_dram_L2_queue = new fifo_pipeline<mem_fetch>("dram-to-L2",0,dram_L2);
+ m_L2_icnt_queue = new fifo_pipeline<mem_fetch>("L2-to-icnt",0,L2_icnt);
+ wb_addr=-1;
}
-void memory_partition_unit::L2c_service_mem_req()
+memory_partition_unit::~memory_partition_unit()
{
- // service memory request in icnt-to-L2 queue, writing to L2 as necessary
- if( L2tocbqueue->full() || L2todramqueue->full() )
- return;
- mem_fetch* mf = m_icnt2cache_queue->pop(gpu_sim_cycle);
- if( !mf )
- mf = m_icnt2cache_write_queue->pop(gpu_sim_cycle);
- if( !mf )
- return;
- switch (mf->get_type()) {
- case RD_REQ:
- case WT_REQ: {
- address_type rep_block;
- enum cache_request_status status = MISS_NO_WB;
- if( mf->istexture() )
- status = m_L2cache->access( mf->get_partition_addr(), mf->get_is_write(), gpu_sim_cycle, &rep_block);
- if( (status==HIT) || m_config->l2_ideal ) {
- mf->set_type( REPLY_DATA );
- assert( mf != NULL );
- L2tocbqueue->push(mf,gpu_sim_cycle);
- if (!mf->get_is_write()) {
- m_stats->L2_read_hit++;
- mf->set_return_timestamp(gpu_sim_cycle+gpu_tot_sim_cycle);
- mf->set_status(IN_L2TOCBQUEUE_HIT,MR_DRAM_OUTQ,gpu_sim_cycle+gpu_tot_sim_cycle);
- } else {
- m_stats->L2_write_hit++;
- }
- } else {
- // L2 Cache Miss
- // if a miss hits in the mshr, that means there is another inflight request for the same data
- // this miss just need to access the cache later when this request is serviced
- bool mshr_hit = m_mshr->new_miss(mf);
- if (not mshr_hit)
- L2todramqueue->push(mf,gpu_sim_cycle);
- mf->set_status(IN_L2TODRAMQUEUE,MR_DRAM_OUTQ,gpu_sim_cycle+gpu_tot_sim_cycle);
- }
- }
- break;
- default: assert(0);
- }
+ delete m_icnt_L2_queue;
+ delete m_L2_dram_queue;
+ delete m_dram_L2_queue;
+ delete m_L2_icnt_queue;
+ delete m_L2cache;
+ delete m_L2interface;
}
-// service memory request in L2todramqueue, pushing to dram
-void memory_partition_unit::L2c_push_miss_to_dram()
+void memory_partition_unit::cache_cycle()
{
- if ( m_config->gpgpu_dram_sched_queue_size && m_dram->full() )
- return;
- mem_fetch* mf = L2todram_wbqueue->pop(gpu_sim_cycle); //prioritize writeback
- if (!mf) mf = L2todramqueue->pop(gpu_sim_cycle);
- if (mf) {
- if (mf->get_is_write())
- m_stats->L2_write_miss++;
- else
- m_stats->L2_read_miss++;
- m_missTracker->new_miss(mf);
- m_dram->push(mf);
- mf->set_status(IN_DRAM_REQ_QUEUE, MR_DRAMQ, gpu_sim_cycle+gpu_tot_sim_cycle);
- }
-}
+ // L2 fill responses
+ if ( m_L2cache->access_ready() && !m_L2_icnt_queue->full() ) {
+ mem_fetch *mf = m_L2cache->next_access();
+ mf->set_type(REPLY_DATA);
+ mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
+ m_L2_icnt_queue->push(mf);
+ }
+ // DRAM to L2 (texture) and icnt (not texture)
+ if ( !m_dram_L2_queue->empty() ) {
+ mem_fetch *mf = m_dram_L2_queue->top();
+ if ( mf->istexture() ) {
+ mf->set_status(IN_PARTITION_L2_FILL_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
+ m_L2cache->fill(mf,gpu_sim_cycle+gpu_tot_sim_cycle);
+ m_dram_L2_queue->pop();
+ } else if ( !m_L2_icnt_queue->full() ) {
+ mf->set_status(IN_PARTITION_L2_TO_ICNT_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
+ m_L2_icnt_queue->push(mf);
+ m_dram_L2_queue->pop();
+ }
+ }
-// service memory request in dramtoL2queue, writing to L2 as necessary
-// (may cause cache eviction and subsequent writeback)
-void memory_partition_unit::process_dram_output()
-{
- if (L2dramout == NULL) {
- // pop from mshr chain if it is not empty, otherwise, pop a new cacheline from dram output queue
- if (m_mshr->mshr_chain_empty() == false) {
- L2dramout = m_mshr->mshr_chain_top();
- m_mshr->mshr_chain_pop();
- } else {
- L2dramout = dramtoL2queue->pop(gpu_sim_cycle);
- if (!L2dramout)
- L2dramout = dramtoL2writequeue->pop(gpu_sim_cycle);
- if (L2dramout != NULL) {
- m_mshr->miss_serviced(L2dramout);
- if (m_mshr->mshr_chain_empty() == false) { // possible if this is a L2 writeback
- L2dramout = m_mshr->mshr_chain_top();
- m_mshr->mshr_chain_pop();
- }
- }
- }
- }
- mem_fetch* mf = L2dramout;
- if (mf) {
- if (!mf->get_is_write()) { //service L2 read miss
- // it is a pre-fill dramout mf
- if (wb_addr == (unsigned long long int)-1) {
- if ( L2tocbqueue->full() ) {
- assert (L2dramout || wb_addr == (unsigned long long int)-1);
- return;
- }
- mf->set_status(IN_L2TOCBQUEUE_MISS,MR_DRAM_OUTQ,gpu_sim_cycle+gpu_tot_sim_cycle);
- //only transfer across icnt once the whole line has been received by L2 cache
- mf->set_type(REPLY_DATA);
- L2tocbqueue->push(mf,gpu_sim_cycle);
- if( mf->istexture() )
- wb_addr = m_L2cache->fill(mf->get_partition_addr(), gpu_sim_cycle);
- }
- // only perform a write on cache eviction (write-back policy)
- // it is the 1st or nth time trial to writeback
- if (wb_addr != (unsigned long long int)-1) {
- // performing L2 writeback (no false sharing for memory-side cache)
- int wb_succeed = L2c_write_back(wb_addr, m_config->m_L2_config.get_line_sz());
- if (!wb_succeed) {
- assert (L2dramout || wb_addr == (unsigned long long int)-1);
- return;
+ // prior L2 misses inserted into m_L2_dram_queue here
+ m_L2cache->cycle();
+
+ // new L2 texture accesses and/or non-texture accesses
+ if ( !m_L2_dram_queue->full() && !m_icnt_L2_queue->empty() ) {
+ mem_fetch *mf = m_icnt_L2_queue->top();
+ if ( mf->istexture() ) {
+ // in this model, L2 is for texture only
+ if ( !m_L2_icnt_queue->full() ) {
+ enum cache_request_status status = m_L2cache->access(mf->get_partition_addr(),mf,gpu_sim_cycle+gpu_tot_sim_cycle);
+ if ( status == HIT ) {
+ // L2 cache replies with data
+ mf->set_type(REPLY_DATA);
+ m_L2_icnt_queue->push(mf);
+ m_icnt_L2_queue->pop();
+ } else if ( status != RESERVATION_FAIL ) {
+ // L2 cache accepted request
+ m_icnt_L2_queue->pop();
+ } else {
+ // L2 cache lock-up: will try again next cycle
+ }
}
- }
- m_missTracker->miss_serviced(mf);
- L2dramout = NULL;
- wb_addr = -1;
- } else { //service L2 write miss
- m_missTracker->miss_serviced(mf);
- mf->set_type(REPLY_DATA);
- L2tocbqueue->push(mf,gpu_sim_cycle);
- L2dramout = NULL;
- wb_addr = -1;
- }
- }
- assert (L2dramout || wb_addr == (unsigned long long int)-1);
+ } else {
+ // non-texture access
+ mf->set_status(IN_PARTITION_L2_TO_DRAM_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
+ m_L2_dram_queue->push(mf);
+ m_icnt_L2_queue->pop();
+ }
+ }
}
-// Writeback from L2 to DRAM:
-// - Takes in memory address and their parameters and pushes to dram request queue
-// - This is used only for L2 writeback
-bool memory_partition_unit::L2c_write_back( unsigned long long int addr, int bsize )
+bool memory_partition_unit::full() const
{
- if ( L2todram_wbqueue->full() )
- return false;
- mem_fetch *mf = new mem_fetch(addr,
- bsize,
- READ_PACKET_SIZE,
- (unsigned)-1/*sid*/,
- (unsigned)-1/*tpc*/,
- (unsigned)-1/*wid*/,
- (unsigned)-1/*mshr_id*/,
- NULL/*inst*/,
- true/*write*/,
- partial_write_mask_t(),
- L2_WRBK_ACC,
- L2_WTBK_DATA,
- m_config );
- L2todram_wbqueue->push(mf,gpu_sim_cycle);
- return true;
+ return m_icnt_L2_queue->full();
}
-void memory_partition_unit::L2c_print_cache_stat(unsigned &accesses, unsigned &misses) const
+void memory_partition_unit::print_cache_stat(unsigned &accesses, unsigned &misses) const
{
- FILE *fp = stdout;
- m_L2cache->print(fp,accesses,misses);
- m_mshr->print_stat(fp);
- m_missTracker->print_stat(fp);
- m_accessLocality->print_stat(fp, false);
+ FILE *fp = stdout;
+ m_L2cache->print(fp,accesses,misses);
}
void memory_partition_unit::print( FILE *fp ) const
{
- if( !m_request_tracker.empty() ) {
- fprintf(fp,"Memory Parition %u: pending memory requests:\n", m_id);
- for( std::set<mem_fetch*>::const_iterator r=m_request_tracker.begin(); r != m_request_tracker.end(); ++r ) {
- mem_fetch *mf = *r;
- if( mf )
- mf->print(fp);
- else
- fprintf(fp," <NULL mem_fetch?>\n");
- }
- }
- m_dram->print(fp);
-}
-
-void memory_partition_unit::L2c_update_stat()
-{
- unsigned i=m_id;
- if (m_icnt2cache_queue->get_length() > m_stats->L2_cbtoL2length[i])
- m_stats->L2_cbtoL2length[i] = m_icnt2cache_queue->get_length();
- if (m_icnt2cache_write_queue->get_length() > m_stats->L2_cbtoL2writelength[i])
- m_stats->L2_cbtoL2writelength[i] = m_icnt2cache_write_queue->get_length();
- if (L2tocbqueue->get_length() > m_stats->L2_L2tocblength[i])
- m_stats->L2_L2tocblength[i] = L2tocbqueue->get_length();
- if (dramtoL2queue->get_length() > m_stats->L2_dramtoL2length[i])
- m_stats->L2_dramtoL2length[i] = dramtoL2queue->get_length();
- if (dramtoL2writequeue->get_length() > m_stats->L2_dramtoL2writelength[i])
- m_stats->L2_dramtoL2writelength[i] = dramtoL2writequeue->get_length();
- if (L2todramqueue->get_length() > m_stats->L2_L2todramlength[i])
- m_stats->L2_L2todramlength[i] = L2todramqueue->get_length();
-}
-
-void memory_stats_t::L2c_print_stat( unsigned n_mem )
-{
- unsigned i;
-
- printf(" ");
- for (i=0;i<n_mem;i++) {
- printf(" dram[%d]", i);
- }
- printf("\n");
-
- printf("cbtoL2 queue maximum length =");
- for (i=0;i<n_mem;i++) {
- printf("%8d", L2_cbtoL2length[i]);
- }
- printf("\n");
-
- printf("cbtoL2 write queue maximum length =");
- for (i=0;i<n_mem;i++) {
- printf("%8d", L2_cbtoL2writelength[i]);
- }
- printf("\n");
-
- printf("L2tocb queue maximum length =");
- for (i=0;i<n_mem;i++) {
- printf("%8d", L2_L2tocblength[i]);
- }
- printf("\n");
-
- printf("dramtoL2 queue maximum length =");
- for (i=0;i<n_mem;i++) {
- printf("%8d", L2_dramtoL2length[i]);
- }
- printf("\n");
-
- printf("dramtoL2 write queue maximum length =");
- for (i=0;i<n_mem;i++) {
- printf("%8d", L2_dramtoL2writelength[i]);
- }
- printf("\n");
-
- printf("L2todram queue maximum length =");
- for (i=0;i<n_mem;i++) {
- printf("%8d", L2_L2todramlength[i]);
- }
- printf("\n");
+ if ( !m_request_tracker.empty() ) {
+ fprintf(fp,"Memory Parition %u: pending memory requests:\n", m_id);
+ for ( std::set<mem_fetch*>::const_iterator r=m_request_tracker.begin(); r != m_request_tracker.end(); ++r ) {
+ mem_fetch *mf = *r;
+ if ( mf )
+ mf->print(fp);
+ else
+ fprintf(fp," <NULL mem_fetch?>\n");
+ }
+ }
+ m_dram->print(fp);
}
void memory_stats_t::print( FILE *fp )
{
- fprintf(fp,"L2_write_miss = %d\n", L2_write_miss);
- fprintf(fp,"L2_write_hit = %d\n", L2_write_hit);
- fprintf(fp,"L2_read_miss = %d\n", L2_read_miss);
- fprintf(fp,"L2_read_hit = %d\n", L2_read_hit);
+ fprintf(fp,"L2_write_miss = %d\n", L2_write_miss);
+ fprintf(fp,"L2_write_hit = %d\n", L2_write_hit);
+ fprintf(fp,"L2_read_miss = %d\n", L2_read_miss);
+ fprintf(fp,"L2_read_hit = %d\n", L2_read_hit);
}
void gpgpu_sim::L2c_print_cache_stat() const
{
- unsigned i, j, k;
- for (i=0,j=0,k=0;i<m_memory_config->m_n_mem;i++)
- m_memory_partition_unit[i]->L2c_print_cache_stat(k,j);
- printf("L2 Cache Total Miss Rate = %0.3f\n", (float)j/k);
+ unsigned i, j, k;
+ for (i=0,j=0,k=0;i<m_memory_config->m_n_mem;i++)
+ m_memory_partition_unit[i]->print_cache_stat(k,j);
+ printf("L2 Cache Total Miss Rate = %0.3f\n", (float)j/k);
}
-void gpgpu_sim::L2c_print_debug()
-{
- unsigned i;
-
- printf(" ");
- for (i=0;i<m_memory_config->m_n_mem;i++)
- printf(" dram[%d]", i);
- printf("\n");
-
- printf("cbtoL2 queue length =");
- for (i=0;i<m_memory_config->m_n_mem;i++)
- printf("%8d", m_memory_partition_unit[i]->get_cbtoL2queue_length() );
- printf("\n");
-
- printf("cbtoL2 write queue length =");
- for (i=0;i<m_memory_config->m_n_mem;i++)
- printf("%8d", m_memory_partition_unit[i]->get_cbtoL2writequeue_length());
- printf("\n");
-
- printf("L2tocb queue length =");
- for (i=0;i<m_memory_config->m_n_mem;i++) {
- printf("%8d", m_memory_partition_unit[i]->get_L2tocbqueue_length());
- }
- printf("\n");
-
- printf("dramtoL2 queue length =");
- for (i=0;i<m_memory_config->m_n_mem;i++) {
- printf("%8d", m_memory_partition_unit[i]->get_dramtoL2queue_length());
- }
- printf("\n");
-
- printf("dramtoL2 write queue length =");
- for (i=0;i<m_memory_config->m_n_mem;i++) {
- printf("%8d", m_memory_partition_unit[i]->get_dramtoL2writequeue_length());
- }
- printf("\n");
-
- printf("L2todram queue length =");
- for (i=0;i<m_memory_config->m_n_mem;i++) {
- printf("%8d", m_memory_partition_unit[i]->get_L2todramqueue_length());
- }
- printf("\n");
-
- printf("L2todram writeback queue length =");
- for (i=0;i<m_memory_config->m_n_mem;i++) {
- printf("%8d", m_memory_partition_unit[i]->get_L2todram_wbqueue_length());
- }
- printf("\n");
+unsigned memory_partition_unit::flushL2()
+{
+ m_L2cache->flush();
+ return 0; // L2 is read only in this version
}
-#define CREATELOG 111
-#define SAMPLELOG 222
-#define DUMPLOG 333
-
-void memory_partition_unit::L2c_log(int task)
+bool memory_partition_unit::busy() const
{
- if (task == SAMPLELOG) {
- StatAddSample(cbtol2_Dist, m_icnt2cache_queue->get_length());
- StatAddSample(cbtoL2wr_Dist, m_icnt2cache_write_queue->get_length());
- StatAddSample(L2tocb_Dist, L2tocbqueue->get_length());
- StatAddSample(dramtoL2_Dist, dramtoL2queue->get_length());
- StatAddSample(dramtoL2wr_Dist, dramtoL2writequeue->get_length());
- StatAddSample(L2todram_Dist, L2todramqueue->get_length());
- StatAddSample(L2todram_wb_Dist, L2todram_wbqueue->get_length());
- } else if (task == DUMPLOG) {
- printf ("Queue Length DRAM[%d] ",m_id); StatDisp(cbtol2_Dist);
- printf ("Queue Length DRAM[%d] ",m_id); StatDisp(cbtoL2wr_Dist);
- printf ("Queue Length DRAM[%d] ",m_id); StatDisp(L2tocb_Dist);
- printf ("Queue Length DRAM[%d] ",m_id); StatDisp(dramtoL2_Dist);
- printf ("Queue Length DRAM[%d] ",m_id); StatDisp(dramtoL2wr_Dist);
- printf ("Queue Length DRAM[%d] ",m_id); StatDisp(L2todram_Dist);
- printf ("Queue Length DRAM[%d] ",m_id); StatDisp(L2todram_wb_Dist);
- }
+ return !m_request_tracker.empty();
}
-unsigned memory_partition_unit::flushL2()
-{
- return m_L2cache->flush();
-}
-
-void gpgpu_sim::L2c_latency_log_dump()
+void memory_partition_unit::push( mem_fetch* req, unsigned long long cycle )
{
- for (unsigned i=0;i<m_memory_config->m_n_mem;i++)
- m_memory_partition_unit[i]->L2c_latency_log_dump();
+ if (req) {
+ m_request_tracker.insert(req);
+ rop_delay_t r;
+ r.req = req;
+ r.ready_cycle = cycle + 115; // Add 115*4=460 delay cycles
+ m_rop.push(r);
+ req->set_status(IN_PARTITION_ROP_DELAY,gpu_sim_cycle+gpu_tot_sim_cycle);
+ }
+ if ( !m_rop.empty() && (cycle >= m_rop.front().ready_cycle) ) {
+ mem_fetch* mf = m_rop.front().req;
+ m_rop.pop();
+ m_stats->memlatstat_icnt2mem_pop(mf);
+ m_icnt_L2_queue->push(mf);
+ mf->set_status(IN_PARTITION_ICNT_TO_L2_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
+ }
}
-void memory_partition_unit::L2c_latency_log_dump()
+mem_fetch* memory_partition_unit::pop()
{
- printf ("(LOGB2)Latency DRAM[%u] ",m_id); StatDisp(m_icnt2cache_queue->get_lat_stat());
- printf ("(LOGB2)Latency DRAM[%u] ",m_id); StatDisp(m_icnt2cache_write_queue->get_lat_stat());
- printf ("(LOGB2)Latency DRAM[%u] ",m_id); StatDisp(L2tocbqueue->get_lat_stat());
- printf ("(LOGB2)Latency DRAM[%u] ",m_id); StatDisp(dramtoL2queue->get_lat_stat());
- printf ("(LOGB2)Latency DRAM[%u] ",m_id); StatDisp(dramtoL2writequeue->get_lat_stat());
- printf ("(LOGB2)Latency DRAM[%u] ",m_id); StatDisp(L2todramqueue->get_lat_stat());
- printf ("(LOGB2)Latency DRAM[%u] ",m_id); StatDisp(L2todram_wbqueue->get_lat_stat());
+ mem_fetch* mf = m_L2_icnt_queue->pop();
+ if ( mf && mf->isatomic() )
+ mf->do_atomic();
+ m_request_tracker.erase(mf);
+ return mf;
}
-bool memory_partition_unit::busy() const
+mem_fetch* memory_partition_unit::top()
{
- return !m_request_tracker.empty();
+ return m_L2_icnt_queue->top();
}
+void memory_partition_unit::dram_cycle()
+{
+ // pop completed memory request from dram and push it to dram-to-L2 queue
+ if ( !m_dram_L2_queue->full() ) {
+ mem_fetch* mf = m_dram->pop();
+ if (mf) {
+ m_dram_L2_queue->push(mf);
+ mf->set_status(IN_PARTITION_DRAM_TO_L2_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
+ }
+ }
+ m_dram->cycle();
+ m_dram->dram_log(SAMPLELOG);
+
+ if( !m_dram->full() && !m_L2_dram_queue->empty() ) {
+ mem_fetch *mf = m_L2_dram_queue->pop();
+ m_dram->push(mf);
+ }
+}
diff --git a/src/gpgpu-sim/l2cache.h b/src/gpgpu-sim/l2cache.h
index b192986..6900394 100644
--- a/src/gpgpu-sim/l2cache.h
+++ b/src/gpgpu-sim/l2cache.h
@@ -67,7 +67,6 @@
#define MC_PARTITION_INCLUDED
#include "dram.h"
-#include "../tr1_hash_map.h"
#include "../abstract_hardware_model.h"
#include <list>
@@ -75,156 +74,37 @@
class mem_fetch;
-class L2c_mshr
-{
-private:
- typedef std::list<const mem_fetch*> mem_fetch_list;
- typedef tr1_hash_map<address_type, mem_fetch_list> L2missGroup;
- L2missGroup m_L2missgroup; // structure tracking redundant dram access
-
- struct active_chain {
- address_type cacheTag;
- mem_fetch_list *list;
- active_chain() : cacheTag(0xDEADBEEF), list(NULL) { }
- };
- active_chain m_active_mshr_chain;
- size_t m_linesize; // L2 cache line size
-
- const size_t m_n_entries; // total number of entries available
- size_t m_entries_used; // number of entries in use
-
- int m_n_miss;
- int m_n_miss_serviced_by_dram;
- int m_n_mshr_hits;
- size_t m_max_entries_used;
-
- address_type cache_tag(const mem_fetch *mf) const;
-
-public:
- L2c_mshr(size_t linesize, size_t n_entries = 64)
- : m_linesize(linesize), m_n_entries(n_entries), m_entries_used(0),
- m_n_miss(0), m_n_miss_serviced_by_dram(0), m_n_mshr_hits(0), m_max_entries_used(0) { }
-
- // add a cache miss to MSHR, return true if this access is hit another existing entry and merges with it
- bool new_miss(const mem_fetch *mf);
-
- // notify MSHR that a new cache line has been fetched, activate the associated MSHR chain
- void miss_serviced(const mem_fetch *mf);
-
- // probe if there are pending hits left in this MSHR chain
- bool mshr_chain_empty();
-
- // peek the first entry in the active MSHR chain
- mem_fetch *mshr_chain_top();
-
- // pop the first entry in the active MSHR chain
- void mshr_chain_pop();
-
- void print(FILE *fout = stdout);
- void print_stat(FILE *fout = stdout) const;
-};
-
-class L2c_miss_tracker
-{
-private:
- typedef std::set<mem_fetch*> mem_fetch_set;
- typedef tr1_hash_map<address_type, mem_fetch_set> L2missGroup;
- L2missGroup m_L2missgroup; // structure tracking redundant dram access
- size_t m_linesize; // L2 cache line size
-
- typedef tr1_hash_map<address_type, int> L2redundantCnt;
- L2redundantCnt m_L2redundantCnt;
-
- int m_totalL2redundantAcc;
-
- address_type cache_tag(const mem_fetch *mf) const;
-
-public:
- L2c_miss_tracker(size_t linesize) : m_linesize(linesize), m_totalL2redundantAcc(0) { }
- void new_miss(mem_fetch *mf);
- void miss_serviced(mem_fetch *mf);
-
- void print(FILE *fout, bool brief = true);
- void print_stat(FILE *fout, bool brief = true) const;
-};
-
-class L2c_access_locality
-{
-public:
- L2c_access_locality(size_t linesize) : m_linesize(linesize), m_totalL2accAcc(0) { }
- void print_stat(FILE *fout, bool brief = true) const;
- void access(mem_fetch *mf);
-private:
- address_type cache_tag(const mem_fetch *mf) const;
-
- size_t m_linesize; // L2 cache line size
-
- typedef tr1_hash_map<address_type, int> L2accCnt;
- L2accCnt m_L2accCnt;
- int m_totalL2accAcc;
-};
-
class memory_partition_unit
{
public:
memory_partition_unit( unsigned partition_id, struct memory_config *config, class memory_stats_t *stats );
~memory_partition_unit();
+ bool busy() const;
+
void cache_cycle();
+ void dram_cycle();
- bool has_cache() { return m_L2cache != NULL; }
- unsigned L2c_get_linesize();
bool full() const;
- bool busy() const;
-
void push( class mem_fetch* mf, unsigned long long clock_cycle );
class mem_fetch* pop();
class mem_fetch* top();
- void issueCMD();
- void visualizer_print( gzFile visualizer_file );
- void L2c_latency_log_dump();
- void L2c_log(int task);
- unsigned flushL2();
- void L2c_print_cache_stat(unsigned &accesses, unsigned &misses) const;
- unsigned get_cbtoL2queue_length() const { return m_icnt2cache_queue->get_length(); }
- unsigned get_cbtoL2writequeue_length() const { return m_icnt2cache_write_queue->get_length(); }
- unsigned get_dramtoL2queue_length() const { return dramtoL2queue->get_length(); }
- unsigned get_dramtoL2writequeue_length() const { return dramtoL2writequeue->get_length(); }
- unsigned get_L2todramqueue_length() const { return L2todramqueue->get_length(); }
- unsigned get_L2todram_wbqueue_length() const { return L2todram_wbqueue->get_length(); }
- unsigned get_L2tocbqueue_length() const { return L2tocbqueue->get_length(); }
+ unsigned flushL2();
+ void visualizer_print( gzFile visualizer_file );
+ void print_cache_stat(unsigned &accesses, unsigned &misses) const;
void print_stat( FILE *fp ) { m_dram->print_stat(fp); }
void visualize() const { m_dram->visualize(); }
- unsigned dram_que_length() const { return m_dram->que_length(); }
- void queue_latency_log_dump( FILE *fp ) { m_dram->queue_latency_log_dump(fp); }
void print( FILE *fp ) const;
private:
-
- // service memory request in icnt-to-L2 queue, writing to L2 as necessary
- // (if L2 writeback miss, writeback to memory)
- void L2c_service_mem_req();
-
- // service memory request in L2todramqueue, pushing to dram
- void L2c_push_miss_to_dram();
-
- // service memory request in dramtoL2queue, writing to L2 as necessary
- // (may cause cache eviction and subsequent writeback)
- void process_dram_output();
-
- bool L2c_write_back( unsigned long long int addr, int bsize );
-
- void L2c_init_stat(unsigned n_mem);
- void L2c_update_stat();
- void L2c_print_debug();
-
// data
unsigned m_id;
const struct memory_config *m_config;
class dram_t *m_dram;
class cache_t *m_L2cache;
+ class L2interface *m_L2interface;
// model delay of ROP units with a fixed latency
struct rop_delay_t
@@ -235,32 +115,35 @@ private:
std::queue<rop_delay_t> m_rop;
// these are various FIFOs between units within a memory partition
- fifo_pipeline<mem_fetch> *m_icnt2cache_queue;
- fifo_pipeline<mem_fetch> *m_icnt2cache_write_queue;
- fifo_pipeline<mem_fetch> *dramtoL2queue;
- fifo_pipeline<mem_fetch> *dramtoL2writequeue;
- fifo_pipeline<mem_fetch> *L2todramqueue;
- fifo_pipeline<mem_fetch> *L2todram_wbqueue;
- fifo_pipeline<mem_fetch> *L2tocbqueue; // L2 cache hit response queue
-
- L2c_mshr *m_mshr; // mshr model
- L2c_miss_tracker *m_missTracker; // tracker observing for redundant misses
- L2c_access_locality *m_accessLocality; // tracking true locality of L2 Cache access
+ fifo_pipeline<mem_fetch> *m_icnt_L2_queue;
+ fifo_pipeline<mem_fetch> *m_L2_dram_queue;
+ fifo_pipeline<mem_fetch> *m_dram_L2_queue;
+ fifo_pipeline<mem_fetch> *m_L2_icnt_queue; // L2 cache hit response queue
class mem_fetch *L2dramout;
unsigned long long int wb_addr;
class memory_stats_t *m_stats;
- class Stats *cbtol2_Dist;
- class Stats *cbtoL2wr_Dist;
- class Stats *L2tocb_Dist;
- class Stats *dramtoL2_Dist;
- class Stats *dramtoL2wr_Dist;
- class Stats *L2todram_Dist;
- class Stats *L2todram_wb_Dist;
-
std::set<mem_fetch*> m_request_tracker;
+
+ friend class L2interface;
+};
+
+class L2interface : public mem_fetch_interface {
+public:
+ L2interface( memory_partition_unit *unit ) { m_unit=unit; }
+ virtual bool full( unsigned size, bool write) const
+ {
+ // assume read and write packets all same size
+ return m_unit->m_L2_dram_queue->full();
+ }
+ virtual void push(mem_fetch *mf)
+ {
+ m_unit->m_L2_dram_queue->push(mf);
+ }
+private:
+ memory_partition_unit *m_unit;
};
#endif
diff --git a/src/gpgpu-sim/mem_fetch.cc b/src/gpgpu-sim/mem_fetch.cc
index 05835bf..0d9e4b2 100644
--- a/src/gpgpu-sim/mem_fetch.cc
+++ b/src/gpgpu-sim/mem_fetch.cc
@@ -77,13 +77,12 @@ mem_fetch::mem_fetch( new_addr_type addr,
unsigned sid,
unsigned tpc,
unsigned wid,
- unsigned mshr_id,
warp_inst_t *inst,
bool write,
partial_write_mask_t partial_write_mask,
enum mem_access_type mem_acc,
enum mf_type type,
- const memory_config *config )
+ const memory_config *config ) : m_inst()
{
m_request_uid = sm_next_mf_request_uid++;
@@ -93,7 +92,6 @@ mem_fetch::mem_fetch( new_addr_type addr,
m_sid = sid;
m_wid = wid;
m_tpc = tpc;
- m_mshr_id = mshr_id;
if( inst ) m_inst = *inst;
m_write = write;
config->m_address_mapping.addrdec_tlx(addr,&m_raw_addr);
@@ -103,20 +101,54 @@ mem_fetch::mem_fetch( new_addr_type addr,
m_timestamp = gpu_sim_cycle + gpu_tot_sim_cycle;
m_timestamp2 = 0;
- m_status = INITIALIZED;
+ m_status = MEM_FETCH_INITIALIZED;
+ m_status_change = gpu_sim_cycle + gpu_tot_sim_cycle;
}
+mem_fetch::~mem_fetch()
+{
+ m_status = MEM_FETCH_DELETED;
+}
+
+static const char* Status_str[] = {
+"INITIALIZED",
+"IN_ICNT_TO_MEM",
+"IN_PARTITION_ROP_DELAY",
+"IN_PARTITION_ICNT_TO_L2_QUEUE",
+"IN_PARTITION_L2_TO_DRAM_QUEUE",
+"IN_PARTITION_MC_INTERFACE_QUEUE",
+"IN_PARTITION_MC_INPUT_QUEUE",
+"IN_PARTITION_MC_BANK_ARB_QUEUE",
+"IN_PARTITION_DRAM",
+"IN_PARTITION_MC_RETURNQ",
+"IN_PARTITION_DRAM_TO_L2_QUEUE",
+"IN_PARTITION_L2_FILL_QUEUE",
+"IN_PARTITION_L2_TO_ICNT_QUEUE",
+"IN_ICNT_TO_SHADER",
+"IN_CLUSTER_TO_SHADER_QUEUE",
+"IN_SHADER_LDST_RESPONSE_FIFO",
+"IN_SHADER_FETCHED",
+"MEM_FETCH_DELETED",
+"??",
+"???"
+};
+
void mem_fetch::print( FILE *fp ) const
{
- fprintf(fp," mf: uid=%6u, addr=0x%08llx, sid=%u, wid=%u, mshr_id=%u, %s, bank=%u, ",
- m_request_uid, m_addr, m_sid, m_wid, m_mshr_id, (m_write?"write":"read "), m_raw_addr.bk);
+ fprintf(fp," mf: uid=%6u, addr=0x%08llx, sid=%u, wid=%u, %s, partition=%u, ",
+ m_request_uid, m_addr, m_sid, m_wid, (m_write?"write":"read "), m_raw_addr.chip);
+ if( (unsigned)m_status < NUM_MEM_REQ_STAT )
+ fprintf(fp," status = %s (%llu), ", Status_str[m_status], m_status_change );
+ else
+ fprintf(fp," status = %u??? (%llu), ", m_status, m_status_change );
if( !m_inst.empty() ) m_inst.print(fp);
else fprintf(fp,"\n");
}
-void mem_fetch::set_status( enum mshr_status status, enum mem_req_stat stat, unsigned long long cycle )
+void mem_fetch::set_status( enum mem_fetch_status status, unsigned long long cycle )
{
m_status = status;
+ m_status_change = cycle;
}
bool mem_fetch::isatomic() const
@@ -139,5 +171,5 @@ bool mem_fetch::istexture() const
bool mem_fetch::isconst() const
{
if( m_inst.empty() ) return false;
- return m_inst.space.get_type() == const_space;
+ return (m_inst.space.get_type() == const_space) || (m_inst.space.get_type() == param_space_kernel);
}
diff --git a/src/gpgpu-sim/mem_fetch.h b/src/gpgpu-sim/mem_fetch.h
index c922af5..3aae63f 100644
--- a/src/gpgpu-sim/mem_fetch.h
+++ b/src/gpgpu-sim/mem_fetch.h
@@ -91,41 +91,26 @@ enum mem_access_type {
NUM_MEM_ACCESS_TYPE = 8
};
-enum mshr_status {
- INITIALIZED = 0,
- INVALID,
- IN_ICNT2MEM,
- IN_CBTOL2QUEUE,
- IN_L2TODRAMQUEUE,
- IN_DRAM_REQ_QUEUE,
- IN_DRAMRETURN_Q,
- IN_DRAMTOL2QUEUE,
- IN_L2TOCBQUEUE_HIT,
- IN_L2TOCBQUEUE_MISS,
- IN_ICNT2SHADER,
- IN_CLUSTER2SHADER,
- FETCHED,
- NUM_MSHR_STATUS
-};
-
-//used to stages that time_vector will keep track of their timing
-enum mem_req_stat {
- MR_UNUSED,
- MR_FQPUSHED,
- MR_ICNT_PUSHED,
- MR_ICNT_INJECTED,
- MR_ICNT_AT_DEST,
- MR_DRAMQ, //icnt_pop at dram side and mem_ctrl_push
- MR_DRAM_PROCESSING_START,
- MR_DRAM_PROCESSING_END,
- MR_DRAM_OUTQ,
- MR_2SH_ICNT_PUSHED, // icnt_push and mem_ctl_pop //STORES END HERE!
- MR_2SH_ICNT_INJECTED,
- MR_2SH_ICNT_AT_DEST,
- MR_2SH_FQ_POP, //icnt_pop called inside fq_pop
- MR_RETURN_Q,
- MR_WRITEBACK, //done
- NUM_MEM_REQ_STAT
+enum mem_fetch_status {
+ MEM_FETCH_INITIALIZED = 0,
+ IN_ICNT_TO_MEM,
+ IN_PARTITION_ROP_DELAY,
+ IN_PARTITION_ICNT_TO_L2_QUEUE,
+ IN_PARTITION_L2_TO_DRAM_QUEUE,
+ IN_PARTITION_MC_INTERFACE_QUEUE,
+ IN_PARTITION_MC_INPUT_QUEUE,
+ IN_PARTITION_MC_BANK_ARB_QUEUE,
+ IN_PARTITION_DRAM,
+ IN_PARTITION_MC_RETURNQ,
+ IN_PARTITION_DRAM_TO_L2_QUEUE,
+ IN_PARTITION_L2_FILL_QUEUE,
+ IN_PARTITION_L2_TO_ICNT_QUEUE,
+ IN_ICNT_TO_SHADER,
+ IN_CLUSTER_TO_SHADER_QUEUE,
+ IN_SHADER_LDST_RESPONSE_FIFO,
+ IN_SHADER_FETCHED,
+ MEM_FETCH_DELETED,
+ NUM_MEM_REQ_STAT
};
const unsigned partial_write_mask_bits = 128; //must be at least size of largest memory access.
@@ -139,15 +124,15 @@ public:
unsigned sid,
unsigned tpc,
unsigned wid,
- unsigned mshr_id,
warp_inst_t *inst,
bool write,
partial_write_mask_t partial_write_mask,
enum mem_access_type mem_acc,
enum mf_type type,
const class memory_config *config );
+ ~mem_fetch();
- void set_status( enum mshr_status status, enum mem_req_stat stat, unsigned long long cycle );
+ void set_status( enum mem_fetch_status status, unsigned long long cycle );
void set_type( enum mf_type t ) { m_type=t; }
void do_atomic();
@@ -159,7 +144,6 @@ public:
unsigned size() const { return m_data_size+m_ctrl_size; }
new_addr_type get_addr() const { return m_addr; }
new_addr_type get_partition_addr() const { return m_partition_addr; }
- unsigned get_mshr() { return m_mshr_id; }
bool get_is_write() const { return m_write; }
unsigned get_request_uid() const { return m_request_uid; }
unsigned get_sid() const { return m_sid; }
@@ -177,7 +161,7 @@ public:
enum mem_access_type get_mem_acc() const { return m_mem_acc; }
address_type get_pc() const { return m_inst.empty()?-1:m_inst.pc; }
const warp_inst_t &get_inst() { return m_inst; }
- enum mshr_status get_status() const { return m_status; }
+ enum mem_fetch_status get_status() const { return m_status; }
private:
// request source information
@@ -185,10 +169,10 @@ private:
unsigned m_sid;
unsigned m_tpc;
unsigned m_wid;
- unsigned m_mshr_id;
// where is this request now?
- enum mshr_status m_status;
+ enum mem_fetch_status m_status;
+ unsigned long long m_status_change;
// request type, address, size, mask
bool m_write;
diff --git a/src/gpgpu-sim/mem_latency_stat.cc b/src/gpgpu-sim/mem_latency_stat.cc
index 2087fd2..f78717e 100644
--- a/src/gpgpu-sim/mem_latency_stat.cc
+++ b/src/gpgpu-sim/mem_latency_stat.cc
@@ -79,8 +79,11 @@
#include <stdlib.h>
#include <stdio.h>
-memory_stats_t::memory_stats_t( unsigned n_shader, struct shader_core_config *shader_config, struct memory_config *mem_config )
+memory_stats_t::memory_stats_t( unsigned n_shader, const struct shader_core_config *shader_config, const struct memory_config *mem_config )
{
+ assert( mem_config->m_valid );
+ assert( shader_config->m_valid );
+
unsigned i,j;
@@ -119,7 +122,6 @@ memory_stats_t::memory_stats_t( unsigned n_shader, struct shader_core_config *sh
mf_tot_lat_pw_perwarp = (unsigned *) calloc(max_warps, sizeof(unsigned int));
mf_total_lat_perwarp = (unsigned long long int *) calloc(max_warps, sizeof(unsigned long long int));
num_mfs_perwarp = (unsigned *) calloc(max_warps, sizeof(unsigned int));
- acc_mrq_length = (unsigned *) calloc(mem_config->m_n_mem, sizeof(unsigned int));
mf_tot_lat_pw = 0; //total latency summed up per window. divide by mf_num_lat_pw to obtain average latency Per Window
mf_total_lat = 0;
num_mfs = 0;
diff --git a/src/gpgpu-sim/mem_latency_stat.h b/src/gpgpu-sim/mem_latency_stat.h
index 14868ef..b7e4b64 100644
--- a/src/gpgpu-sim/mem_latency_stat.h
+++ b/src/gpgpu-sim/mem_latency_stat.h
@@ -73,8 +73,8 @@
class memory_stats_t {
public:
memory_stats_t( unsigned n_shader,
- struct shader_core_config *shader_config,
- struct memory_config *mem_config );
+ const struct shader_core_config *shader_config,
+ const struct memory_config *mem_config );
unsigned memlatstat_done( class mem_fetch *mf, unsigned n_warp_per_shader );
void memlatstat_read_done( class mem_fetch *mf, unsigned n_warp_per_shader);
@@ -83,8 +83,6 @@ public:
void memlatstat_lat_pw( unsigned n_shader, unsigned n_thread_per_shader, unsigned warp_size );
void memlatstat_print(unsigned n_mem, unsigned gpu_mem_n_bk);
- void L2c_print_stat(unsigned n_mem);
-
void print( FILE *fp );
unsigned m_n_shader;
@@ -121,7 +119,6 @@ public:
unsigned *mf_tot_lat_pw_perwarp; //total latency summed up per window per warp. divide by mf_num_lat_pw_perwarp to obtain average latency Per Window
unsigned long long int *mf_total_lat_perwarp;
unsigned *num_mfs_perwarp;
- unsigned *acc_mrq_length;
unsigned ***mem_access_type_stats; // dram access type classification
diff --git a/src/gpgpu-sim/shader.cc b/src/gpgpu-sim/shader.cc
index 2c5de09..1f0ebc4 100644
--- a/src/gpgpu-sim/shader.cc
+++ b/src/gpgpu-sim/shader.cc
@@ -88,195 +88,7 @@
#define PRIORITIZE_MSHR_OVER_WB 1
#define MAX(a,b) (((a)>(b))?(a):(b))
-
/////////////////////////////////////////////////////////////////////////////
-/*-------------------------------------------------------------------------*/
-/*-------------------------------------------------------------------------*/
-
-static const char* MSHR_Status_str[] = {
- "INITIALIZED",
- "INVALID",
- "IN_ICNT2MEM",
- "IN_CBTOL2QUEUE",
- "IN_L2TODRAMQUEUE",
- "IN_DRAM_REQ_QUEUE",
- "IN_DRAMRETURN_Q",
- "IN_DRAMTOL2QUEUE",
- "IN_L2TOCBQUEUE_HIT",
- "IN_L2TOCBQUEUE_MISS",
- "IN_ICNT2SHADER",
- "IN_CLUSTER2SHADER",
- "FETCHED",
-};
-
-void mshr_lookup::insert(mshr_entry* mshr)
-{
- using namespace std;
- new_addr_type tag_addr = mshr->get_addr();
- m_lut.insert(make_pair(tag_addr, mshr));
-}
-
-mshr_entry* mshr_lookup::lookup( new_addr_type addr ) const
-{
- std::pair<mshr_lut_t::const_iterator, mshr_lut_t::const_iterator> i_range = m_lut.equal_range(addr);
- if (i_range.first == i_range.second) {
- return NULL;
- } else {
- mshr_lut_t::const_iterator i_lut = i_range.first;
- return i_lut->second->get_last_merged();
- }
-}
-
-void mshr_lookup::remove(mshr_entry* mshr)
-{
- using namespace std;
- std::pair<mshr_lut_t::iterator, mshr_lut_t::iterator> i_range = m_lut.equal_range(mshr->get_addr());
-
- assert(i_range.first != i_range.second);
-
- for (mshr_lut_t::iterator i_lut = i_range.first; i_lut != i_range.second; ++i_lut) {
- if (i_lut->second == mshr) {
- m_lut.erase(i_lut);
- break;
- }
- }
-}
-
-//checks if we should do mshr merging for this mshr
-bool mshr_lookup::can_merge(mshr_entry * mshr)
-{
- if (mshr->iswrite())
- return false; // can't merge a write
- if (mshr->isatomic())
- return false; // can't merge a atomic operation
- bool interwarp_mshr_merge = m_shader_config->gpgpu_interwarp_mshr_merge & GLOBAL_MSHR_MERGE;
- if (mshr->istexture())
- interwarp_mshr_merge = m_shader_config->gpgpu_interwarp_mshr_merge & TEX_MSHR_MERGE;
- else if (mshr->isconst())
- interwarp_mshr_merge = m_shader_config->gpgpu_interwarp_mshr_merge & CONST_MSHR_MERGE;
- return interwarp_mshr_merge;
-}
-
-void mshr_lookup::mshr_fast_lookup_insert(mshr_entry* mshr)
-{
- if (!can_merge(mshr))
- return;
- insert(mshr);
-}
-
-void mshr_lookup::mshr_fast_lookup_remove(mshr_entry* mshr)
-{
- if (!can_merge(mshr))
- return;
- remove(mshr);
-}
-
-mshr_entry* mshr_lookup::shader_get_mergeable_mshr(mshr_entry* mshr)
-{
- if (!can_merge(mshr)) return NULL;
- return lookup(mshr->get_addr());
-}
-
-mshr_shader_unit::mshr_shader_unit( const shader_core_config *config ): m_max_mshr_used(0), m_mshr_lookup(config)
-{
- m_shader_config=config;
- m_mshrs.resize(config->n_mshr_per_shader);
- unsigned n=0;
- for (std::vector<mshr_entry>::iterator i = m_mshrs.begin(); i != m_mshrs.end(); i++) {
- mshr_entry &mshr = *i;
- mshr.set_id(n++);
- m_free_list.push_back(&mshr);
- }
-}
-
-mshr_entry* mshr_shader_unit::return_head()
-{
- if (has_return())
- return &(*choose_return_queue().front());
- else
- return NULL;
-}
-
-void mshr_shader_unit::pop_return_head()
-{
- free_mshr(return_head());
- choose_return_queue().pop_front();
-}
-
-mshr_entry *mshr_shader_unit::alloc_free_mshr(bool istexture)
-{
- assert(!m_free_list.empty());
- mshr_entry *mshr = m_free_list.back();
- m_free_list.pop_back();
- if (istexture)
- m_texture_mshr_pipeline.push_back(mshr);
- if (mshr_used() > m_max_mshr_used)
- m_max_mshr_used = mshr_used();
- return mshr;
-}
-
-void mshr_shader_unit::free_mshr( mshr_entry *mshr )
-{
- //clean up up for next time, since not reallocating memory.
- m_mshr_lookup.mshr_fast_lookup_remove(mshr);
- mshr->clear();
- m_free_list.push_back(mshr);
-}
-
-unsigned mshr_shader_unit::mshr_used() const
-{
- return m_shader_config->n_mshr_per_shader - m_free_list.size();
-}
-
-std::list<mshr_entry*> &mshr_shader_unit::choose_return_queue()
-{
- // prioritize a ready texture over a global/const...
- if ((not m_texture_mshr_pipeline.empty()) and m_texture_mshr_pipeline.front()->fetched())
- return m_texture_mshr_pipeline;
- assert(!m_mshr_return_queue.empty());
- return m_mshr_return_queue;
-}
-
-void mshr_shader_unit::mshr_return_from_mem(unsigned mshr_id)
-{
- if(mshr_id == (unsigned)-1) {
- return;
- }
- mshr_entry *mshr = &m_mshrs[mshr_id];
- mshr->set_fetched();
- mem_fetch *mf = mshr->get_mf();
- if( mf ) mf->set_status( FETCHED, MR_RETURN_Q, gpu_sim_cycle+gpu_tot_sim_cycle );
- if ( not mshr->istexture() ) {
- //place in return queue
- mshr->add_to_queue( m_mshr_return_queue );
- }
-}
-
-void mshr_shader_unit::print(FILE* fp)
-{
- unsigned n=0;
- unsigned num_outstanding = 0;
- for (mshr_storage_type::iterator it = m_mshrs.begin(); it != m_mshrs.end(); it++,n++) {
- mshr_entry *mshr = &(*it);
- if (find(m_free_list.begin(),m_free_list.end(), mshr) == m_free_list.end()) {
- num_outstanding++;
- mshr->print(fp);
- }
- }
- fprintf(fp,"ready texture mshrs:\n");
- std::list<mshr_entry*>::iterator m;
- for( m=m_texture_mshr_pipeline.begin(); m!=m_texture_mshr_pipeline.end(); m++ ) {
- mshr_entry *mshr = *m;
- mshr->print(fp);
- }
- fprintf(fp,"ready non-texture mshrs:\n");
- for( m=m_mshr_return_queue.begin(); m!=m_mshr_return_queue.end(); m++ ) {
- mshr_entry *mshr = *m;
- mshr->print(fp);
- }
- fprintf(fp,"outstanding memory requests = %u\n", num_outstanding );
-}
-
std::list<unsigned> shader_core_ctx::get_regs_written( const inst_t &fvt ) const
{
@@ -322,6 +134,8 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu,
m_thread[i].m_functional_model_thread_state = NULL;
m_thread[i].m_cta_id = -1;
}
+
+ m_icnt = new shader_memory_interface(cluster);
// fetch
m_last_warp_fetched = 0;
@@ -330,7 +144,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu,
#define STRSIZE 1024
char L1I_name[STRSIZE];
snprintf(L1I_name, STRSIZE, "L1I_%03d", m_sid);
- m_L1I = new cache_t(L1I_name,m_config->m_L1I_config,m_sid,get_shader_instruction_cache_id());
+ m_L1I = new cache_t(L1I_name,m_config->m_L1I_config,m_sid,get_shader_instruction_cache_id(),m_icnt);
m_warp.resize(m_config->max_warps_per_shader, shd_warp_t(this, warp_size));
m_pdom_warp = new pdom_warp_ctx_t*[config->max_warps_per_shader];
@@ -364,7 +178,7 @@ shader_core_ctx::shader_core_ctx( class gpgpu_sim *gpu,
m_dispatch_port[1] = ID_OC_SFU;
m_issue_port[1] = OC_EX_SFU;
- m_ldst_unit = new ldst_unit( cluster, this, &m_operand_collector, m_scoreboard, config, mem_config, stats, shader_id, tpc_id );
+ m_ldst_unit = new ldst_unit( m_icnt, this, &m_operand_collector, m_scoreboard, config, mem_config, stats, shader_id, tpc_id );
m_fu[2] = m_ldst_unit;
m_dispatch_port[2] = ID_OC_MEM;
m_issue_port[2] = OC_EX_MEM;
@@ -607,43 +421,47 @@ void shader_core_ctx::fetch()
if( !m_warp[warp_id].done() && !m_warp[warp_id].imiss_pending() && m_warp[warp_id].ibuffer_empty() ) {
address_type pc = m_warp[warp_id].get_pc();
address_type ppc = pc + PROGRAM_MEM_START;
- address_type wb=0;
unsigned nbytes=16;
unsigned offset_in_block = pc & (m_config->m_L1I_config.get_line_sz()-1);
if( (offset_in_block+nbytes) > m_config->m_L1I_config.get_line_sz() )
nbytes = (m_config->m_L1I_config.get_line_sz()-offset_in_block);
- enum cache_request_status status = m_L1I->access( (unsigned long long)pc, 0, gpu_sim_cycle, &wb );
- if( status != HIT ) {
- unsigned req_size = READ_PACKET_SIZE;
- if( !m_cluster->icnt_injection_buffer_full(ppc, req_size, false) ) {
- m_last_warp_fetched=warp_id;
- mem_fetch *mf = new mem_fetch(pc,
- req_size,
- READ_PACKET_SIZE,
- m_sid,
- m_tpc,
- warp_id,
- (unsigned)-1/*mshr_id*/,
- NULL/*we don't have an instruction yet*/,
- false,
- NO_PARTIAL_WRITE,
- INST_ACC_R,
- RD_REQ,
- m_memory_config );
- m_cluster->icnt_inject_request_packet(mf);
-
- m_warp[warp_id].set_imiss_pending();
- m_warp[warp_id].set_last_fetch(gpu_sim_cycle);
- }
- } else {
+ mem_fetch *mf = new mem_fetch(ppc,
+ nbytes,
+ READ_PACKET_SIZE,
+ m_sid,
+ m_tpc,
+ warp_id,
+ NULL/*we don't have an instruction yet*/,
+ false,
+ NO_PARTIAL_WRITE,
+ INST_ACC_R,
+ RD_REQ,
+ m_memory_config );
+ enum cache_request_status status = m_L1I->access( (new_addr_type)ppc, mf, gpu_sim_cycle+gpu_tot_sim_cycle );
+ if( status == MISS ) {
+ m_last_warp_fetched=warp_id;
+ m_warp[warp_id].set_imiss_pending();
+ m_warp[warp_id].set_last_fetch(gpu_sim_cycle);
+ } else if( status == HIT ) {
m_last_warp_fetched=warp_id;
m_inst_fetch_buffer = ifetch_buffer_t(pc,nbytes,warp_id);
m_warp[warp_id].set_last_fetch(gpu_sim_cycle);
+ } else {
+ assert( status == RESERVATION_FAIL );
+ delete mf;
}
break;
}
}
}
+
+ m_L1I->cycle();
+
+ if( m_L1I->access_ready() ) {
+ mem_fetch *mf = m_L1I->next_access();
+ m_warp[mf->get_wid()].clear_imiss_pending();
+ delete mf;
+ }
}
void shader_core_ctx::func_exec_inst( warp_inst_t &inst )
@@ -791,178 +609,53 @@ void shader_core_ctx::execute()
}
}
-mshr_entry* mshr_shader_unit::add_mshr(mem_access_t &access, warp_inst_t* pinst)
-{
- // creates an mshr based on the access struct information
- mshr_entry* mshr = alloc_free_mshr(pinst->space == tex_space);
- mshr->init(access.addr,pinst->is_store(),pinst->space,pinst->warp_id());
- warp_inst_t inst = *pinst;
- inst.set_active(access.warp_indices);
- mshr->add_inst(inst);
- if( m_shader_config->gpgpu_interwarp_mshr_merge ) {
- mshr_entry* mergehit = m_mshr_lookup.shader_get_mergeable_mshr(mshr);
- if (mergehit) {
- mergehit->merge(mshr);
- if (mergehit->fetched())
- mshr_return_from_mem(mshr->get_id());
- }
- m_mshr_lookup.mshr_fast_lookup_insert(mshr);
- }
- return mshr;
-}
-
-void ldst_unit::const_cache_access(warp_inst_t &inst)
+mem_fetch *ldst_unit::create_data_mem_fetch(warp_inst_t &inst, mem_access_t &access)
{
- // do cache checks here for each request (non-physical), could be
- // done later for more accurate timing of cache accesses, but probably uneccesary;
- for (unsigned i = 0; i < inst.get_accessq_size(); i++) {
- mem_access_t &req = inst.accessq(i);
- if ( inst.space == param_space_kernel ) {
- req.cache_hit = true;
- } else {
- cache_request_status status = m_L1C->access( req.addr,
- 0, //should always be a read
- gpu_sim_cycle+gpu_tot_sim_cycle,
- NULL/*should never writeback*/);
- req.cache_hit = (status == HIT);
- if (m_config->gpgpu_perfect_mem) req.cache_hit = true;
- if (req.cache_hit) m_stats->L1_const_miss++;
- }
- req.cache_checked = true;
+ bool is_write = inst.is_store();
+ mem_access_type access_type;
+ switch (inst.space.get_type()) {
+ case const_space:
+ case param_space_kernel:
+ access_type = CONST_ACC_R;
+ break;
+ case tex_space:
+ access_type = TEXTURE_ACC_R;
+ break;
+ case global_space:
+ access_type = is_write? GLOBAL_ACC_W: GLOBAL_ACC_R;
+ break;
+ case local_space:
+ case param_space_local:
+ access_type = is_write? LOCAL_ACC_W: LOCAL_ACC_R;
+ break;
+ default: assert(0); break;
}
-}
-
-void ldst_unit::tex_cache_access(warp_inst_t &inst)
-{
- // do cache checks here for each request (non-hardware), could be done later
- // for more accurate timing of cache accesses, but probably uneccesary;
- for (unsigned i = 0; i < inst.get_accessq_size(); i++) {
- mem_access_t &req = inst.accessq(i);
- cache_request_status status = m_L1T->access( req.addr,
- 0, //should always be a read
- gpu_sim_cycle+gpu_tot_sim_cycle,
- NULL /*should never writeback*/);
- req.cache_hit = (status == HIT);
- if (m_config->gpgpu_perfect_mem) req.cache_hit = true;
- if (req.cache_hit) m_stats->L1_texture_miss++;
- req.cache_checked = true;
- }
-}
-
-mem_stage_stall_type ldst_unit::send_mem_request(warp_inst_t &inst, mem_access_t &access)
-{
- // Attempt to send an request/write to memory based on information in access.
-
- // If the cache told us it needed to write back a dirty line, do this now
- // It is possible to do this writeback in the same cycle as the access request, this may not be realistic.
- if (access.need_wb) {
- unsigned req_size = m_config->gpgpu_cache_dl1_linesize + WRITE_PACKET_SIZE;
- if ( m_cluster->icnt_injection_buffer_full(access.wb_addr, req_size, true) ) {
- m_stats->gpu_stall_sh2icnt++;
- return WB_ICNT_RC_FAIL;
- }
- mem_fetch *mf = new mem_fetch(access.wb_addr,
- req_size,
- READ_PACKET_SIZE,
- m_sid,
- m_tpc,
- -1/*wid*/,
- -1/*mshr id*/,
- NULL,
- true,
- NO_PARTIAL_WRITE,
- inst.space.is_local()?LOCAL_ACC_W:GLOBAL_ACC_W, //space of cache line is same as new request
- WT_REQ,
- m_memory_config );
- m_cluster->icnt_inject_request_packet(mf);
- inst.clear_active(access.warp_indices);
- m_stats->L1_writeback++;
- access.need_wb = false;
- }
-
- bool is_write = inst.is_store();
- mem_access_type access_type;
- bool requires_mshr = false;
- switch(inst.space.get_type()) {
- case const_space:
- case param_space_kernel:
- access_type = CONST_ACC_R;
- break;
- case tex_space:
- access_type = TEXTURE_ACC_R;
- break;
- case global_space:
- access_type = is_write? GLOBAL_ACC_W: GLOBAL_ACC_R;
- break;
- case local_space:
- case param_space_local:
- access_type = is_write? LOCAL_ACC_W: LOCAL_ACC_R;
- break;
- default: assert(0); break;
- }
- //reserve mshr
- if (requires_mshr && !access.reserved_mshr) {
- if (not m_mshr_unit->has_mshr(1))
- return MSHR_RC_FAIL;
- access.reserved_mshr = m_mshr_unit->add_mshr(access, &inst);
- access.recheck_cache = false;
- //we have an mshr now, so have checked cache in same cycle as checking mshrs, so have merged if necessary.
- }
- //require inct if access is this far without reserved mshr, or has and mshr but not merged with another request
- bool requires_icnt = (!access.reserved_mshr) || (!access.reserved_mshr->ismerged());
- if (requires_icnt) {
- //calculate request size for icnt check (and later send);
- unsigned request_size = access.req_size;
- if (is_write) {
- if (requires_mshr)
- request_size += READ_PACKET_SIZE + WRITE_MASK_SIZE; // needs information for a load back into cache.
- else
- request_size += WRITE_PACKET_SIZE + WRITE_MASK_SIZE; //plain write
- }
- if ( m_cluster->icnt_injection_buffer_full(access.addr, request_size, is_write) ) {
- // can't allocate icnt
- m_stats->gpu_stall_sh2icnt++;
- return ICNT_RC_FAIL;
- }
- //send over interconnect
- partial_write_mask_t write_mask = NO_PARTIAL_WRITE;
- unsigned warp_id = inst.warp_id();
- if (is_write) {
- m_core->inc_store_req(warp_id);
- for (unsigned i=0;i < access.warp_indices.size();i++) {
+ unsigned request_size = access.req_size;
+ partial_write_mask_t write_mask = NO_PARTIAL_WRITE;
+ if (is_write) {
+ for (unsigned i=0;i < access.warp_indices.size();i++) {
unsigned w = access.warp_indices[i];
int data_offset = inst.get_addr(w) & ((unsigned long long int)access.req_size - 1);
- for (unsigned b = data_offset; b < data_offset + inst.data_size; b++) write_mask.set(b);
- }
- if (write_mask.count() != access.req_size)
- m_stats->gpgpu_n_partial_writes++;
- }
- unsigned mshr_id = access.reserved_mshr?access.reserved_mshr->get_id():-1;
- warp_inst_t inst_copy = inst;
- inst_copy.set_active(access.warp_indices);
- mem_fetch *mf = new mem_fetch(access.addr,
- request_size,
- is_write?WRITE_PACKET_SIZE:READ_PACKET_SIZE,
- m_sid,
- m_tpc,
- warp_id,
- mshr_id,
- &inst_copy,
- is_write,
- write_mask,
- access_type,
- is_write?WT_REQ:RD_REQ,
- m_memory_config);
- if( access.reserved_mshr )
- access.reserved_mshr->set_mf(mf);
- m_cluster->icnt_inject_request_packet(mf);
- if( inst.is_load() ) {
- for( unsigned r=0; r < 4; r++)
- if(inst.out[r] > 0)
- m_pending_writes[inst.warp_id()][inst.out[r]]++;
- }
- }
- return NO_RC_FAIL;
+ for (unsigned b = data_offset; b < data_offset + inst.data_size; b++)
+ write_mask.set(b);
+ }
+ }
+ warp_inst_t inst_copy = inst;
+ inst_copy.set_active(access.warp_indices);
+ unsigned warp_id = inst.warp_id();
+ mem_fetch *mf = new mem_fetch(access.addr,
+ request_size,
+ is_write?WRITE_PACKET_SIZE:READ_PACKET_SIZE,
+ m_sid,
+ m_tpc,
+ warp_id,
+ &inst_copy,
+ is_write,
+ write_mask,
+ access_type,
+ is_write?WT_REQ:RD_REQ,
+ m_memory_config);
+ return mf;
}
void shader_core_ctx::writeback()
@@ -1003,54 +696,40 @@ bool ldst_unit::shared_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail,
return inst.accessq_empty(); //done if empty.
}
-mem_stage_stall_type ldst_unit::process_memory_access_queue( ldst_unit::cache_check_t cache_check,
- unsigned ports_per_bank,
- unsigned memory_send_max,
- warp_inst_t &inst )
+mem_stage_stall_type ldst_unit::process_memory_access_queue( cache_t *cache, warp_inst_t &inst )
{
- // Generic algorithm for processing a single cycle of accesses for the memory space types that go to L2 or DRAM.
-
- // precondition: accessq sorted by mem_access_t::order
- mem_stage_stall_type hazard_cond = NO_RC_FAIL;
- unsigned mem_req_count = 0; // number of requests to sent to memory this cycle
- for (unsigned i = 0; i < ports_per_bank; i++) {
- if (inst.accessq_empty())
- break;
- unsigned current_order = inst.accessq_back().order;
- // consume all requests of the same "order" but stop if we hit a structural hazard
- while( !inst.accessq_empty() && inst.accessq_back().order == current_order && hazard_cond == NO_RC_FAIL) {
- hazard_cond = (this->*cache_check)(inst,inst.accessq_back());
- if (hazard_cond != NO_RC_FAIL)
- break; // can't complete this request this cycle.
- if ( !inst.accessq_back().cache_hit ){
- if (mem_req_count < memory_send_max) {
- mem_req_count++;
- hazard_cond = send_mem_request(inst,inst.accessq_back());
- }
- else hazard_cond = COAL_STALL; // not really a coal stall, its a too many memory request stall;
- if ( hazard_cond != NO_RC_FAIL)
- break; //can't complete this request this cycle.
- }
- inst.accessq_pop_back();
- }
- }
- if (!inst.accessq_empty() && hazard_cond == NO_RC_FAIL) {
- //no resource failed so must be a bank comflict.
- hazard_cond = BK_CONF;
- }
- return hazard_cond;
-}
+ mem_stage_stall_type result = NO_RC_FAIL;
+ unsigned current_order = inst.accessq_back().order;
+ while ((!inst.accessq_empty()) && inst.accessq_back().order == current_order) {
+ mem_fetch *mf = create_data_mem_fetch(inst,inst.accessq_back());
+ enum cache_request_status status = cache->access(mf->get_addr(),mf,gpu_sim_cycle+gpu_tot_sim_cycle);
+ if( status == HIT ) {
+ inst.accessq_pop_back();
+ delete mf;
+ } else if( status == RESERVATION_FAIL ) {
+ result = COAL_STALL; // todo: unify enums
+ delete mf;
+ break;
+ } else {
+ assert( status == MISS );
+ inst.accessq_pop_back();
+ if( inst.is_load() ) {
+ for( unsigned r=0; r < 4; r++)
+ if(inst.out[r] > 0)
+ m_pending_writes[inst.warp_id()][inst.out[r]]++;
+ }
+ }
+ }
+ if( !inst.accessq_empty() && (inst.accessq_back().order != current_order) )
+ result = BK_CONF;
+ return result;
+}
bool ldst_unit::constant_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type)
{
if( (inst.space.get_type() != const_space) && (inst.space.get_type() != param_space_kernel) )
return true;
-
- // Process a single cycle of activity from the the constant memory queue.
- mem_stage_stall_type fail = process_memory_access_queue(&ldst_unit::ccache_check,
- m_config->gpgpu_const_port_per_bank,
- 1, //memory send max per cycle
- inst );
+ mem_stage_stall_type fail = process_memory_access_queue(m_L1C,inst);
if (fail != NO_RC_FAIL){
rc_fail = fail; //keep other fails if this didn't fail.
fail_type = C_MEM;
@@ -1065,13 +744,7 @@ bool ldst_unit::texture_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail,
{
if( inst.space.get_type() != tex_space )
return true;
-
- // Process a single cycle of activity from the the texture memory queue.
-
- mem_stage_stall_type fail = process_memory_access_queue(&ldst_unit::tcache_check,
- 1, //how is tex memory banked?
- 1, //memory send max per cycle
- inst );
+ mem_stage_stall_type fail = process_memory_access_queue(m_L1T,inst);
if (fail != NO_RC_FAIL){
rc_fail = fail; //keep other fails if this didn't fail.
fail_type = T_MEM;
@@ -1079,77 +752,32 @@ bool ldst_unit::texture_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail,
return inst.accessq_empty(); //done if empty.
}
-mem_stage_stall_type ldst_unit::dcache_check(warp_inst_t &inst, mem_access_t& access)
-{
- // Global memory (data cache) checks the cache for each access at the time it is processed.
- // This is more accurate to hardware, and necessary for proper action of the writeback cache.
-
- if (access.cache_checked && !access.recheck_cache)
- return NO_RC_FAIL;
- if (!m_config->gpgpu_no_dl1 && !m_config->gpgpu_perfect_mem) {
- //check cache
- cache_request_status status = m_L1D->access( access.addr,
- inst.is_store(),
- gpu_sim_cycle+gpu_tot_sim_cycle,
- &access.wb_addr );
- if (status == RESERVATION_FAIL) {
- access.cache_checked = false;
- return WB_CACHE_RSRV_FAIL;
- }
- access.cache_hit = (status == HIT); //if HIT_W_WT then still send to memory so "MISS"
- if (status == MISS_W_WB)
- access.need_wb = true;
- if (status == WB_HIT_ON_MISS && inst.is_store())
- {
- //write has hit a reserved cache line
- //it has writen its data into the cache line, so no need to go to memory
- access.cache_hit = true;
- m_stats->L1_write_hit_on_miss++;
- // here we would search the MSHRs for the originating read,
- // and mask off the writen bytes, so they are not overwritten in the cache when it comes back
- // --- don't actually do this since we don't functionally execute based upon values in cache
- // MSHR will still forward the unmasked value to its dependant reads.
- // if doing stall on use, must stall this thread after this write (otherwise, inproper values may be forwarded to future reads).
- }
- if (status == WB_HIT_ON_MISS && !inst.is_store() ) {
- //read has hit on a reserved cache line,
- //we need to make sure cache check happens on same cycle as a mshr merge happens, otherwise we might miss it coming back
- access.recheck_cache = true;
- }
- access.cache_checked = true;
- } else {
- access.cache_hit = false;
- }
-
- if (m_config->gpgpu_perfect_mem)
- access.cache_hit = true;
-
- if (inst.isatomic()) {
- if (m_config->gpgpu_perfect_mem) {
- // complete functional execution of atomic here
- inst.do_atomic();
- } else {
- // atomics always go to memory
- access.cache_hit = false;
- }
- }
-
- if (!access.cache_hit) {
- if (inst.is_store()) m_stats->L1_write_miss++;
- else m_stats->L1_read_miss++;
- }
- return NO_RC_FAIL;
-}
-
bool ldst_unit::memory_cycle( warp_inst_t &inst, mem_stage_stall_type &stall_reason, mem_stage_access_type &access_type )
{
if( (inst.space.get_type() != global_space) &&
(inst.space.get_type() != local_space) &&
(inst.space.get_type() != param_space_local) )
return true;
-
- // Process a single cycle of activity from the the global/local memory queue.
- mem_stage_stall_type stall_cond = process_memory_access_queue(&ldst_unit::dcache_check,m_config->gpgpu_cache_port_per_bank,1,inst);
+ mem_stage_stall_type stall_cond = NO_RC_FAIL;
+ unsigned current_order = inst.accessq_back().order;
+ while ((!inst.accessq_empty()) && inst.accessq_back().order == current_order) {
+ if( m_icnt->full(inst.accessq_back().req_size, inst.is_store()) ) {
+ stall_cond = ICNT_RC_FAIL;
+ break;
+ } else {
+ mem_fetch *mf = create_data_mem_fetch(inst,inst.accessq_back());
+ m_icnt->push(mf);
+ inst.accessq_pop_back();
+ if( inst.is_load() ) {
+ for( unsigned r=0; r < 4; r++)
+ if(inst.out[r] > 0)
+ m_pending_writes[inst.warp_id()][inst.out[r]]++;
+ } else if( inst.is_store() )
+ m_core->inc_store_req( inst.warp_id() );
+ }
+ }
+ if( !inst.accessq_empty() )
+ stall_cond = COAL_STALL;
if (stall_cond != NO_RC_FAIL) {
stall_reason = stall_cond;
bool iswrite = inst.is_store();
@@ -1170,33 +798,13 @@ bool ldst_unit::response_buffer_full() const
void ldst_unit::fill( mem_fetch *mf )
{
+ mf->set_status(IN_SHADER_LDST_RESPONSE_FIFO,gpu_sim_cycle+gpu_tot_sim_cycle);
m_response_fifo.push_back(mf);
}
void ldst_unit::flush()
{
- m_L1D->flush();
- // TODO: add flush 'interface' object to provide functionality commented out below
- /*
-
- unsigned int i;
- unsigned int set;
- unsigned long long int flush_addr;
- cache_t *cp = m_L1D;
- cache_block_t *pline;
- for (i=0; i<cp->m_nset*cp->m_assoc; i++) {
- pline = &(cp->m_lines[i]);
- set = i / cp->m_assoc;
- if ((pline->status & (DIRTY|VALID)) == (DIRTY|VALID)) {
- flush_addr = pline->addr;
- fq_push(flush_addr, m_L1D->get_line_sz(), 1, NO_PARTIAL_WRITE, 0, NULL, 0, GLOBAL_ACC_W, -1);
- pline->status &= ~VALID;
- pline->status &= ~DIRTY;
- } else if (pline->status & VALID) {
- pline->status &= ~VALID;
- }
- }
- */
+ // no L1D
}
void ldst_unit::generate_mem_accesses(warp_inst_t &inst)
@@ -1210,19 +818,9 @@ void ldst_unit::generate_mem_accesses(warp_inst_t &inst)
if( inst.mem_accesses_created() )
return;
inst.get_memory_access_list();
- switch( inst.space.get_type() ) {
- case shared_space: break;
- case tex_space: tex_cache_access(inst); break;
- case const_space: case param_space_kernel: const_cache_access(inst); break;
- case global_space: case local_space: case param_space_local: break;
- case param_space_unclassified: abort(); break;
- default: break; // non-memory operations
- }
- m_cluster->mem_instruction_stats(inst);
inst.set_mem_accesses_created();
}
-
simd_function_unit::simd_function_unit( const shader_core_config *config )
{
m_config=config;
@@ -1252,7 +850,7 @@ pipelined_simd_unit::pipelined_simd_unit( warp_inst_t **result_port, const shade
m_pipeline_reg[i] = new warp_inst_t( config );
}
-ldst_unit::ldst_unit( simt_core_cluster *cluster,
+ldst_unit::ldst_unit( shader_memory_interface *icnt,
shader_core_ctx *core,
opndcoll_rfu_t *operand_collector,
Scoreboard *scoreboard,
@@ -1260,10 +858,10 @@ ldst_unit::ldst_unit( simt_core_cluster *cluster,
const memory_config *mem_config,
shader_core_stats *stats,
unsigned sid,
- unsigned tpc ) : pipelined_simd_unit(NULL,config,6)
+ unsigned tpc ) : pipelined_simd_unit(NULL,config,6), m_next_wb(config)
{
m_memory_config = mem_config;
- m_cluster = cluster;
+ m_icnt = icnt;
m_core = core;
m_operand_collector = operand_collector;
m_scoreboard = scoreboard;
@@ -1271,64 +869,74 @@ ldst_unit::ldst_unit( simt_core_cluster *cluster,
m_sid = sid;
m_tpc = tpc;
#define STRSIZE 1024
- char L1D_name[STRSIZE];
char L1T_name[STRSIZE];
char L1C_name[STRSIZE];
- snprintf(L1D_name, STRSIZE, "L1D_%03d", m_sid);
snprintf(L1T_name, STRSIZE, "L1T_%03d", m_sid);
snprintf(L1C_name, STRSIZE, "L1C_%03d", m_sid);
- m_L1D = new cache_t(L1D_name,m_config->m_L1D_config,m_sid,get_shader_normal_cache_id());
- m_L1T = new cache_t(L1T_name,m_config->m_L1T_config,m_sid,get_shader_texture_cache_id());
- m_L1C = new cache_t(L1C_name,m_config->m_L1C_config,m_sid,get_shader_constant_cache_id());
- m_cluster->get_gpu()->ptx_set_tex_cache_linesize(m_config->m_L1T_config.get_line_sz());
- m_mshr_unit = new mshr_shader_unit(m_config);
+ m_L1T = new cache_t(L1T_name,m_config->m_L1T_config,m_sid,get_shader_texture_cache_id(),icnt);
+ m_L1C = new cache_t(L1C_name,m_config->m_L1C_config,m_sid,get_shader_constant_cache_id(),icnt);
m_mem_rc = NO_RC_FAIL;
+ m_num_writeback_clients=4; // = shared memory, global/local, L1T, L1C
+ m_writeback_arb = 0;
+ m_next_global=NULL;
}
void ldst_unit::writeback()
{
- mshr_entry *m = m_mshr_unit->return_head();
- if( m ) m_mshr_unit->pop_return_head();
-
- if( !m_pipeline_reg[0]->empty() ) {
- // shared memory has priority
- if( m_operand_collector->writeback(*m_pipeline_reg[0]) ) {
- m_scoreboard->releaseRegisters(m_pipeline_reg[0]);
- m_core->dec_inst_in_pipeline(m_pipeline_reg[0]->warp_id());
- m_pipeline_reg[0]->clear();
- }
- }
-
- if( !m_response_fifo.empty() ) {
- mem_fetch *mf = m_response_fifo.front();
- if( mf->get_is_write() ) {
- m_core->store_ack(mf);
- m_response_fifo.pop_front();
- } else {
- const warp_inst_t &inst = mf->get_inst();
- if( m_operand_collector->writeback(inst) ) {
- m_response_fifo.pop_front();
- if( mf->isatomic() )
- m_core->decrement_atomic_count(mf->get_wid(),inst.active_count());
- for( unsigned r=0; r < 4; r++ ) {
- if( inst.out[r] > 0 ) {
- assert( m_pending_writes[inst.warp_id()][inst.out[r]] > 0 );
- unsigned still_pending = --m_pending_writes[inst.warp_id()][inst.out[r]];
+ // process next instruction that is going to writeback
+ if( !m_next_wb.empty() ) {
+ if( m_operand_collector->writeback(m_next_wb) ) {
+ for( unsigned r=0; r < 4; r++ ) {
+ if( m_next_wb.out[r] > 0 ) {
+ if( m_next_wb.space.get_type() != shared_space ) {
+ assert( m_pending_writes[m_next_wb.warp_id()][m_next_wb.out[r]] > 0 );
+ unsigned still_pending = --m_pending_writes[m_next_wb.warp_id()][m_next_wb.out[r]];
if( !still_pending ) {
- m_pending_writes[inst.warp_id()].erase(inst.out[r]);
- m_scoreboard->releaseRegister( inst.warp_id(), inst.out[r] );
+ m_pending_writes[m_next_wb.warp_id()].erase(m_next_wb.out[r]);
+ m_scoreboard->releaseRegister( m_next_wb.warp_id(), m_next_wb.out[r] );
}
- }
+ } else // shared
+ m_scoreboard->releaseRegister( m_next_wb.warp_id(), m_next_wb.out[r] );
}
- m_mshr_unit->mshr_return_from_mem(mf->get_mshr());
- if (mf->istexture())
- m_L1T->fill(mf->get_addr(),gpu_sim_cycle+gpu_tot_sim_cycle);
- else if (mf->isconst())
- m_L1C->fill(mf->get_addr(),gpu_sim_cycle+gpu_tot_sim_cycle);
- else if (!m_config->gpgpu_no_dl1)
- m_L1D->fill(mf->get_addr(),gpu_sim_cycle+gpu_tot_sim_cycle);
+ }
+ m_next_wb.clear();
+ }
+ }
+
+ for( unsigned c=0; m_next_wb.empty() && (c < m_num_writeback_clients); c++ ) {
+ unsigned next_client = (c+m_writeback_arb)%m_num_writeback_clients;
+ switch( next_client ) {
+ case 0: // shared memory
+ if( !m_pipeline_reg[0]->empty() ) {
+ m_next_wb = *m_pipeline_reg[0];
+ m_core->dec_inst_in_pipeline(m_pipeline_reg[0]->warp_id());
+ m_pipeline_reg[0]->clear();
+ }
+ break;
+ case 1: // texture response
+ if( m_L1T->access_ready() ) {
+ mem_fetch *mf = m_L1T->next_access();
+ m_next_wb = mf->get_inst();
+ delete mf;
+ }
+ break;
+ case 2: // const cache response
+ if( m_L1C->access_ready() ) {
+ mem_fetch *mf = m_L1C->next_access();
+ m_next_wb = mf->get_inst();
delete mf;
}
+ break;
+ case 3: // global/local
+ if( m_next_global ) {
+ m_next_wb = m_next_global->get_inst();
+ if( m_next_global->isatomic() )
+ m_core->decrement_atomic_count(m_next_global->get_wid(),m_next_wb.active_count());
+ delete m_next_global;
+ m_next_global = NULL;
+ }
+ break;
+ default: abort();
}
}
}
@@ -1339,6 +947,34 @@ void ldst_unit::cycle()
if( m_pipeline_reg[stage]->empty() && !m_pipeline_reg[stage+1]->empty() )
move_warp(m_pipeline_reg[stage], m_pipeline_reg[stage+1]);
+ if( !m_response_fifo.empty() ) {
+ mem_fetch *mf = m_response_fifo.front();
+ if (mf->istexture()) {
+ mf->set_status(IN_SHADER_FETCHED,gpu_sim_cycle+gpu_tot_sim_cycle);
+ m_L1T->fill(mf,gpu_sim_cycle+gpu_tot_sim_cycle);
+ m_response_fifo.pop_front();
+ } else if (mf->isconst()) {
+ mf->set_status(IN_SHADER_FETCHED,gpu_sim_cycle+gpu_tot_sim_cycle);
+ m_L1C->fill(mf,gpu_sim_cycle+gpu_tot_sim_cycle);
+ m_response_fifo.pop_front();
+ } else {
+ if( mf->get_is_write() ) {
+ m_core->store_ack(mf);
+ m_response_fifo.pop_front();
+ delete mf;
+ } else {
+ if( m_next_global == NULL ) {
+ mf->set_status(IN_SHADER_FETCHED,gpu_sim_cycle+gpu_tot_sim_cycle);
+ m_response_fifo.pop_front();
+ m_next_global = mf;
+ }
+ }
+ }
+ }
+
+ m_L1T->cycle();
+ m_L1C->cycle();
+
// process new memory requests
warp_inst_t &pipe_reg = *m_dispatch_reg;
generate_mem_accesses(pipe_reg);
@@ -1556,7 +1192,8 @@ void ldst_unit::print(FILE *fout) const
}
fprintf(fout,"\n");
}
- m_mshr_unit->print(fout);
+ fprintf(fout,"LD/ST wb = ");
+ m_next_wb.print(fout);
fprintf(fout,"Pending register writes:\n");
std::map<unsigned/*warp_id*/, std::map<unsigned/*regnum*/,unsigned/*count*/> >::const_iterator w;
for( w=m_pending_writes.begin(); w!=m_pending_writes.end(); w++ ) {
@@ -1571,6 +1208,8 @@ void ldst_unit::print(FILE *fout) const
}
fprintf(fout,"\n");
}
+ m_L1C->display_state(fout);
+ m_L1T->display_state(fout);
}
void shader_core_ctx::display_pipeline(FILE *fout, int print_mem, int mask )
@@ -1583,6 +1222,8 @@ void shader_core_ctx::display_pipeline(FILE *fout, int print_mem, int mask )
dump_istream_state(fout);
fprintf(fout,"\n");
+ m_L1I->display_state(fout);
+
fprintf(fout, "IF/ID = ");
if( !m_inst_fetch_buffer.m_valid )
fprintf(fout,"bubble\n");
@@ -1691,10 +1332,6 @@ void shader_core_ctx::cache_flush()
m_ldst_unit->flush();
}
-static int *_inmatch;
-static int *_outmatch;
-static int **_request;
-
// modifiers
std::list<opndcoll_rfu_t::op_t> opndcoll_rfu_t::arbiter_t::allocate_reads()
{
@@ -1707,14 +1344,6 @@ std::list<opndcoll_rfu_t::op_t> opndcoll_rfu_t::arbiter_t::allocate_reads()
int _square = ( _inputs > _outputs ) ? _inputs : _outputs;
int _pri = (int)m_last_cu;
- if( _inmatch == NULL ) {
- _inmatch = new int[ _inputs ];
- _outmatch = new int[ _outputs ];
- _request = new int*[ _inputs ];
- for(int i=0; i<_inputs;i++)
- _request[i] = new int[_outputs];
- }
-
// Clear matching
for ( int i = 0; i < _inputs; ++i )
_inmatch[i] = -1;
@@ -1749,14 +1378,14 @@ std::list<opndcoll_rfu_t::op_t> opndcoll_rfu_t::arbiter_t::allocate_reads()
// Step through the current diagonal
for ( input = 0; input < _inputs; ++input ) {
+ assert( input < _inputs );
+ assert( output < _outputs );
if ( ( output < _outputs ) &&
( _inmatch[input] == -1 ) &&
( _outmatch[output] == -1 ) &&
( _request[input][output]/*.label != -1*/ ) ) {
// Grant!
- assert( input < _inputs );
_inmatch[input] = output;
- assert( output < _outputs );
_outmatch[output] = input;
}
@@ -1953,9 +1582,8 @@ bool shader_core_ctx::fetch_unit_response_buffer_full() const
void shader_core_ctx::accept_fetch_response( mem_fetch *mf )
{
- m_L1I->fill(mf->get_addr(),gpu_sim_cycle+gpu_tot_sim_cycle);
- m_warp[mf->get_wid()].clear_imiss_pending();
- delete mf;
+ mf->set_status(IN_SHADER_FETCHED,gpu_sim_cycle+gpu_tot_sim_cycle);
+ m_L1I->fill(mf,gpu_sim_cycle+gpu_tot_sim_cycle);
}
bool shader_core_ctx::ldst_unit_response_buffer_full()
@@ -1966,7 +1594,6 @@ bool shader_core_ctx::ldst_unit_response_buffer_full()
void shader_core_ctx::accept_ldst_unit_response(mem_fetch * mf)
{
m_ldst_unit->fill(mf);
- //freed_read_mfs++;
}
void shader_core_ctx::store_ack( class mem_fetch *mf )
@@ -2076,39 +1703,6 @@ unsigned pdom_warp_ctx_t::get_active_mask() const
return m_active_mask[m_stack_top];
}
-void mshr_entry::init( new_addr_type address, bool wr, memory_space_t space, unsigned warp_id )
-{
- static unsigned next_request_uid = 1;
- m_request_uid = next_request_uid++;
- m_addr = address;
- m_mf = NULL;
- m_merged_on_other_reqest = false;
- m_merged_requests =NULL;
- m_iswrite = wr;
- m_isinst = space==instruction_space;
- m_islocal = space.is_local();
- m_isconst = space.is_const();
- m_istexture = space==tex_space;
- m_isatomic = false;
- m_insts.clear();
- m_warp_id = warp_id;
-}
-
-void mshr_entry::print(FILE *fp) const
-{
- fprintf(fp, "MSHR(%u): w%2u req uid=%5u, %s (0x%llx) merged:%d status:%s ",
- m_id,
- m_warp_id,
- m_request_uid,
- (m_iswrite)? "store" : "load ",
- m_addr,
- (m_merged_requests != NULL || m_merged_on_other_reqest),
- m_mf?MSHR_Status_str[ m_mf->get_status() ]:"???");
- if ( m_mf )
- ptx_print_insn( m_mf->get_pc(), fp );
- fprintf(fp,"\n");
-}
-
void opndcoll_rfu_t::add_port( unsigned num_collector_units,
warp_inst_t **input_port,
warp_inst_t **output_port )
@@ -2368,14 +1962,12 @@ void simt_core_cluster::cache_flush()
m_core[i]->cache_flush();
}
-bool simt_core_cluster::icnt_injection_buffer_full(new_addr_type addr, int bsize, bool write )
+bool simt_core_cluster::icnt_injection_buffer_full(unsigned size, bool write)
{
- //requests should be single always now
- int rsize = bsize;
- //maintain similar functionality with fq_push, if its a read, bsize is the load size, not the request's size
+ unsigned request_size = size;
if (!write)
- rsize = READ_PACKET_SIZE;
- return ! ::icnt_has_buffer(m_cluster_id, rsize);
+ request_size = READ_PACKET_SIZE;
+ return ! ::icnt_has_buffer(m_cluster_id, request_size);
}
void simt_core_cluster::icnt_inject_request_packet(class mem_fetch *mf)
@@ -2395,7 +1987,7 @@ void simt_core_cluster::icnt_inject_request_packet(class mem_fetch *mf)
}
unsigned destination = mf->get_tlx_addr().chip;
- mf->set_status(IN_ICNT2MEM,MR_ICNT_PUSHED,gpu_sim_cycle+gpu_tot_sim_cycle);
+ mf->set_status(IN_ICNT_TO_MEM,gpu_sim_cycle+gpu_tot_sim_cycle);
if (!mf->get_is_write()) {
mf->set_type(RD_REQ);
::icnt_push(m_cluster_id, m_config->mem2device(destination), (void*)mf, mf->get_ctrl_size() );
@@ -2406,12 +1998,6 @@ void simt_core_cluster::icnt_inject_request_packet(class mem_fetch *mf)
}
}
-void simt_core_cluster::icnt_eject_response_packet(class mem_fetch * mf)
-{
- assert( mf->get_tpc() == m_cluster_id );
- m_response_fifo.push_back(mf);
-}
-
void simt_core_cluster::icnt_cycle()
{
if( !m_response_fifo.empty() ) {
@@ -2437,13 +2023,13 @@ void simt_core_cluster::icnt_cycle()
return;
assert(mf->get_tpc() == m_cluster_id);
assert(mf->get_type() == REPLY_DATA);
- mf->set_status(IN_CLUSTER2SHADER,MR_2SH_FQ_POP,gpu_sim_cycle+gpu_tot_sim_cycle);
+ mf->set_status(IN_CLUSTER_TO_SHADER_QUEUE,gpu_sim_cycle+gpu_tot_sim_cycle);
//m_memory_stats->memlatstat_read_done(mf,m_shader_config->max_warps_per_shader);
m_response_fifo.push_back(mf);
}
}
-void simt_core_cluster::mem_instruction_stats(class warp_inst_t &inst)
+void simt_core_cluster::mem_instruction_stats(const class warp_inst_t &inst)
{
m_gpu->mem_instruction_stats(inst);
}
diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h
index 786913a..0d74e95 100644
--- a/src/gpgpu-sim/shader.h
+++ b/src/gpgpu-sim/shader.h
@@ -64,6 +64,9 @@
* Vancouver, BC V6T 1Z4
*/
+#ifndef SHADER_H
+#define SHADER_H
+
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
@@ -80,7 +83,6 @@
#include "../cuda-sim/ptx.tab.h"
#include "../cuda-sim/dram_callback.h"
-#include "gpu-cache.h"
#include "delayqueue.h"
#include "stack.h"
#include "dram.h"
@@ -88,9 +90,7 @@
#include "scoreboard.h"
#include "mem_fetch.h"
#include "stats.h"
-
-#ifndef SHADER_H
-#define SHADER_H
+#include "gpu-cache.h"
#define NO_OP_FLAG 0xFF
@@ -298,102 +298,6 @@ private:
unsigned long long *m_branch_div_cycle;
};
-
-class mshr_entry {
-public:
- mshr_entry()
- {
- m_merged_requests=NULL;
- m_mf=NULL;
- m_id=0;
- m_status = INITIALIZED;
- m_isatomic=false;
- }
- void set_id( unsigned n ) { m_id = n; }
- unsigned get_id() const { return m_id; }
- void init( new_addr_type address, bool wr, memory_space_t space, unsigned warp_id );
- void clear() { m_insts.clear(); }
- void set_mf( class mem_fetch *mf ) { m_mf=mf; }
- class mem_fetch *get_mf() { return m_mf; }
- void add_inst( warp_inst_t inst )
- {
- m_insts.push_back(inst);
- m_isatomic = inst.isatomic();
- }
- void merge( mshr_entry *mshr )
- {
- //merge this request;
- m_merged_requests = mshr;
- mshr->m_merged_on_other_reqest = true;
- }
- void set_fetched()
- {
- mshr_entry *mshr = this;
- while( mshr ) {
- mshr->m_status=FETCHED;
- mshr->m_mf=NULL;
- mshr=mshr->m_merged_requests;
- }
- }
- mshr_entry *get_last_merged()
- {
- mshr_entry *mshr_hit = this;
- while (mshr_hit->m_merged_requests)
- mshr_hit = mshr_hit->m_merged_requests;
- return mshr_hit;
- }
- void get_insts( std::vector<inst_t> &done_insts )
- {
- done_insts.insert(done_insts.end(),m_insts.begin(),m_insts.end());
- }
- void add_to_queue( std::list<mshr_entry*> &q )
- {
- // place all merged requests in return queue
- mshr_entry *req = this;
- while (req) {
- q.push_back(req);
- req = req->m_merged_requests;
- }
- }
-
- unsigned get_warp_id() const { return m_warp_id; }
- bool ismerged() const { return m_merged_on_other_reqest; }
- bool fetched() const { return m_status==FETCHED;}
- bool iswrite() const { return m_iswrite; }
- bool isinst() const { return m_isinst; }
- bool istexture() const { return m_istexture; }
- bool isconst() const { return m_isconst; }
- bool islocal() const { return m_islocal; }
- bool has_inst() const { return m_insts.size()>0; }
- unsigned num_inst() const { return m_insts.size(); }
- inst_t &get_inst(unsigned n)
- {
- assert(n<m_insts.size());
- return m_insts[n];
- }
- bool isatomic() const { return m_isatomic; }
- new_addr_type get_addr() const { return m_addr; }
- void print(FILE *fp) const;
-
-private:
- unsigned m_id;
- unsigned m_request_uid;
- unsigned m_warp_id;
- new_addr_type m_addr; // address being fetched
- std::vector<warp_inst_t> m_insts;
- bool m_iswrite;
- bool m_merged_on_other_reqest; //true if waiting for another mshr - this mshr doesn't send a memory request
- struct mshr_entry *m_merged_requests; //mshrs waiting on this mshr
- class mem_fetch *m_mf; // link to corresponding memory fetch structure
- enum mshr_status m_status;
- bool m_isinst; //if it's a request from the instruction cache
- bool m_istexture; //if it's a request from the texture cache
- bool m_isconst; //if it's a request from the constant cache
- bool m_islocal; //if it's a request to the local memory of a thread
- bool m_wt_no_w2cache; //in write_through, sometimes need to prevent writing back returning data into cache, because its been written in the meantime.
- bool m_isatomic;
-};
-
const unsigned WARP_PER_CTA_MAX = 32;
typedef std::bitset<WARP_PER_CTA_MAX> warp_set_t;
@@ -556,11 +460,19 @@ private:
m_queue=NULL;
m_allocated_bank=NULL;
m_allocator_rr_head=NULL;
+ _inmatch=NULL;
+ _outmatch=NULL;
+ _request=NULL;
}
void init( unsigned num_cu, unsigned num_banks )
{
m_num_collectors = num_cu;
m_num_banks = num_banks;
+ _inmatch = new int[ m_num_banks ];
+ _outmatch = new int[ m_num_collectors ];
+ _request = new int*[ m_num_banks ];
+ for(unsigned i=0; i<m_num_banks;i++)
+ _request[i] = new int[m_num_collectors];
m_queue = new std::list<op_t>[num_banks];
m_allocated_bank = new allocation_t[num_banks];
m_allocator_rr_head = new unsigned[num_cu];
@@ -634,6 +546,10 @@ private:
unsigned *m_allocator_rr_head; // cu # -> next bank to check for request (rr-arb)
unsigned m_last_cu; // first cu to check while arb-ing banks (rr)
+
+ int *_inmatch;
+ int *_outmatch;
+ int **_request;
};
class collector_unit_t {
@@ -786,63 +702,6 @@ private:
warp_set_t m_warp_at_barrier;
};
-class mshr_lookup {
-public:
- mshr_lookup( const struct shader_core_config *config ) { m_shader_config = config; }
- bool can_merge(mshr_entry * mshr);
- void mshr_fast_lookup_insert(mshr_entry* mshr);
- void mshr_fast_lookup_remove(mshr_entry* mshr);
- mshr_entry* shader_get_mergeable_mshr(mshr_entry* mshr);
-
-private:
- void insert(mshr_entry* mshr);
- mshr_entry* lookup(new_addr_type addr) const;
- void remove(mshr_entry* mshr);
-
- typedef std::multimap<new_addr_type, mshr_entry*> mshr_lut_t; // multimap since multiple mshr entries can have the same tag
-
- const shader_core_config *m_shader_config;
- mshr_lut_t m_lut;
-};
-
-class mshr_shader_unit {
-public:
- mshr_shader_unit( const shader_core_config *config );
-
- bool has_mshr(unsigned num) const { return (num <= m_free_list.size()); }
-
- mshr_entry* return_head();
-
- //return queue pop; (includes texture pipeline return)
- void pop_return_head();
-
- mshr_entry* add_mshr(mem_access_t &access, warp_inst_t* inst);
- void mshr_return_from_mem(unsigned mshr_id);
- unsigned get_max_mshr_used() const {return m_max_mshr_used;}
- void print(FILE* fp);
-
-private:
- mshr_entry *alloc_free_mshr(bool istexture);
- void free_mshr( mshr_entry *mshr );
- unsigned mshr_used() const;
- bool has_return()
- {
- return (not m_mshr_return_queue.empty()) or
- ((not m_texture_mshr_pipeline.empty()) and m_texture_mshr_pipeline.front()->fetched());
- }
- std::list<mshr_entry*> &choose_return_queue();
-
- const struct shader_core_config *m_shader_config;
-
- typedef std::vector<mshr_entry> mshr_storage_type;
- mshr_storage_type m_mshrs;
- std::list<mshr_entry*> m_free_list;
- std::list<mshr_entry*> m_mshr_return_queue;
- std::list<mshr_entry*> m_texture_mshr_pipeline;
- unsigned m_max_mshr_used;
- mshr_lookup m_mshr_lookup;
-};
-
struct insn_latency_info {
unsigned pc;
unsigned long latency;
@@ -865,6 +724,8 @@ struct ifetch_buffer_t {
unsigned m_warp_id;
};
+class shader_core_config;
+
class simd_function_unit {
public:
simd_function_unit( const shader_core_config *config );
@@ -966,10 +827,12 @@ public:
};
class simt_core_cluster;
+class shader_memory_interface;
+class cache_t;
class ldst_unit: public pipelined_simd_unit {
public:
- ldst_unit( simt_core_cluster *cluster,
+ ldst_unit( shader_memory_interface *icnt,
shader_core_ctx *core,
opndcoll_rfu_t *operand_collector,
Scoreboard *scoreboard,
@@ -1001,41 +864,33 @@ public:
private:
void generate_mem_accesses(warp_inst_t &pipe_reg);
- void tex_cache_access(warp_inst_t &inst);
- void const_cache_access(warp_inst_t &inst);
bool shared_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type);
bool constant_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type);
bool texture_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type);
bool memory_cycle( warp_inst_t &inst, mem_stage_stall_type &rc_fail, mem_stage_access_type &fail_type);
- mem_stage_stall_type ccache_check(warp_inst_t &inst, mem_access_t& access){ return NO_RC_FAIL;}
- mem_stage_stall_type tcache_check(warp_inst_t &inst, mem_access_t& access){ return NO_RC_FAIL;}
- mem_stage_stall_type dcache_check(warp_inst_t &inst, mem_access_t& access);
-
- typedef mem_stage_stall_type (ldst_unit::*cache_check_t)(warp_inst_t &,mem_access_t&);
-
- mem_stage_stall_type process_memory_access_queue( ldst_unit::cache_check_t cache_check,
- unsigned ports_per_bank,
- unsigned memory_send_max,
- warp_inst_t &inst );
- mem_stage_stall_type send_mem_request(warp_inst_t &inst, mem_access_t &access);
+ mem_stage_stall_type process_memory_access_queue( cache_t *cache, warp_inst_t &inst );
+ mem_fetch *create_data_mem_fetch(warp_inst_t &inst, mem_access_t &access);
const memory_config *m_memory_config;
- class simt_core_cluster *m_cluster;
+ class shader_memory_interface *m_icnt;
class shader_core_ctx *m_core;
unsigned m_sid;
unsigned m_tpc;
- cache_t *m_L1D; // data cache (global/local memory accesses)
cache_t *m_L1T; // texture cache
cache_t *m_L1C; // constant cache
- mshr_shader_unit *m_mshr_unit;
std::map<unsigned/*warp_id*/, std::map<unsigned/*regnum*/,unsigned/*count*/> > m_pending_writes;
std::list<mem_fetch*> m_response_fifo;
opndcoll_rfu_t *m_operand_collector;
Scoreboard *m_scoreboard;
+ mem_fetch *m_next_global;
+ warp_inst_t m_next_wb;
+ unsigned m_writeback_arb; // round-robin arbiter for writeback contention between L1T, L1C, shared
+ unsigned m_num_writeback_clients;
+
enum mem_stage_stall_type m_mem_rc;
shader_core_stats *m_stats;
@@ -1065,8 +920,6 @@ struct shader_core_config : public core_config
m_L1I_config.init();
m_L1T_config.init();
m_L1C_config.init();
- m_L1D_config.init();
- gpgpu_cache_dl1_linesize = m_L1D_config.get_line_sz();
gpgpu_cache_texl1_linesize = m_L1T_config.get_line_sz();
gpgpu_cache_constl1_linesize = m_L1C_config.get_line_sz();
@@ -1083,7 +936,6 @@ struct shader_core_config : public core_config
cache_config m_L1I_config;
cache_config m_L1T_config;
cache_config m_L1C_config;
- cache_config m_L1D_config;
unsigned n_mshr_per_shader;
bool gpgpu_dwf_reg_bankconflict;
@@ -1095,10 +947,7 @@ struct shader_core_config : public core_config
unsigned gpgpu_shmem_size;
unsigned gpgpu_shader_registers;
int gpgpu_warpdistro_shader;
- int gpgpu_interwarp_mshr_merge;
int gpgpu_shmem_port_per_bank;
- int gpgpu_cache_port_per_bank;
- int gpgpu_const_port_per_bank;
unsigned gpgpu_num_reg_banks;
unsigned gpu_max_cta_per_shader; // TODO: modify this for fermi... computed based upon kernel
// resource usage; used in shader_core_ctx::translate_local_memaddr
@@ -1213,6 +1062,9 @@ private:
// thread contexts
thread_ctx_t *m_thread; // functional state, per thread fetch state
+ // interconnect interface
+ shader_memory_interface *m_icnt;
+
// fetch
cache_t *m_L1I; // instruction cache
int m_last_warp_fetched;
@@ -1255,11 +1107,9 @@ public:
void issue_block2core( class kernel_info_t &kernel );
void cache_flush();
- bool icnt_injection_buffer_full(new_addr_type addr, int bsize, bool write );
+ bool icnt_injection_buffer_full(unsigned size, bool write);
void icnt_inject_request_packet(class mem_fetch *mf);
- bool icnt_ejection_buffer_full() const { return m_response_fifo.size() >= m_config->n_simt_ejection_buffer_size; }
- void icnt_eject_response_packet(class mem_fetch * mf);
- void mem_instruction_stats(class warp_inst_t &inst);
+ void mem_instruction_stats(const class warp_inst_t &inst);
void get_pdom_stack_top_info( unsigned sid, unsigned tid, unsigned *pc, unsigned *rpc );
gpgpu_sim *get_gpu() { return m_gpu; }
@@ -1280,4 +1130,21 @@ private:
std::list<mem_fetch*> m_response_fifo;
};
+class shader_memory_interface : public mem_fetch_interface {
+public:
+ shader_memory_interface( simt_core_cluster *port ) { m_port=port; }
+ virtual bool full( unsigned size, bool write ) const
+ {
+ return m_port->icnt_injection_buffer_full(size,write);
+ }
+ virtual void push(mem_fetch *mf)
+ {
+ if( !mf->get_inst().empty() )
+ m_port->mem_instruction_stats(mf->get_inst()); // not I$-fetch
+ m_port->icnt_inject_request_packet(mf);
+ }
+private:
+ simt_core_cluster *m_port;
+};
+
#endif /* SHADER_H */
diff --git a/src/gpgpu-sim/stat-tool.h b/src/gpgpu-sim/stat-tool.h
index ebac6c2..00b7771 100644
--- a/src/gpgpu-sim/stat-tool.h
+++ b/src/gpgpu-sim/stat-tool.h
@@ -68,29 +68,11 @@
#include "../abstract_hardware_model.h"
#include "histogram.h"
+#include "../tr1_hash_map.h"
#include <stdio.h>
#include <zlib.h>
-// detect gcc 4.3 and use unordered map (part of c++0x)
-// unordered map doesn't play nice with _GLIBCXX_DEBUG, just use a map if its enabled.
-#if defined( __GNUC__ ) and not defined( _GLIBCXX_DEBUG )
-#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 3
- #include <unordered_map>
- #define my_hash_map std::unordered_map
-#else
- #include <ext/hash_map>
- namespace std {
- using namespace __gnu_cxx;
- }
- #define my_hash_map std::hash_map
-#endif
-#else
- #include <map>
- #define my_hash_map std::map
- #define USE_MAP
-#endif
-
/////////////////////////////////////////////////////////////////////////////////////
// logger snapshot trigger:
// - automate the snap_shot part of loggers to avoid modifying simulation loop everytime
diff --git a/src/gpgpu-sim/stats.h b/src/gpgpu-sim/stats.h
index 8115eae..0abdb22 100644
--- a/src/gpgpu-sim/stats.h
+++ b/src/gpgpu-sim/stats.h
@@ -102,7 +102,6 @@ struct shader_core_stats
unsigned int gpgpu_n_cache_bkconflict;
int gpgpu_n_intrawarp_mshr_merge;
unsigned int gpgpu_n_cmem_portconflict;
- int gpgpu_n_partial_writes;
unsigned int gpu_stall_shd_mem_breakdown[N_MEM_STAGE_ACCESS_TYPE][N_MEM_STAGE_STALL_TYPE];
unsigned int gpu_reg_bank_conflict_stalls;
unsigned int *shader_cycle_distro;
diff --git a/src/gpgpu-sim/visualizer.cc b/src/gpgpu-sim/visualizer.cc
index 440f9e0..51348d5 100644
--- a/src/gpgpu-sim/visualizer.cc
+++ b/src/gpgpu-sim/visualizer.cc
@@ -259,7 +259,7 @@ public:
void update_ld(unsigned int uid,unsigned int slot, long int time) {
if ( ld_time_map.find( uid )!=ld_time_map.end() ) {
ld_time_map[uid][slot]=time;
- } else if (slot <= MR_2SH_FQ_POP ) {
+ } else if (slot < NUM_MEM_REQ_STAT ) {
std::vector<long int> time_vec;
time_vec.resize(ld_vector_size);
time_vec[slot] = time;
@@ -280,15 +280,15 @@ public:
}
void check_ld_update(unsigned int uid,unsigned int slot, long int latency) {
if ( ld_time_map.find( uid )!=ld_time_map.end() ) {
- int our_latency = ld_time_map[uid][slot] - ld_time_map[uid][MR_ICNT_PUSHED];
+ int our_latency = ld_time_map[uid][slot] - ld_time_map[uid][IN_ICNT_TO_MEM];
assert( our_latency == latency);
- } else if (slot <= MR_2SH_FQ_POP ) {
+ } else if (slot < NUM_MEM_REQ_STAT ) {
abort();
}
}
void check_st_update(unsigned int uid,unsigned int slot, long int latency) {
if ( st_time_map.find( uid )!=st_time_map.end() ) {
- int our_latency = st_time_map[uid][slot] - st_time_map[uid][MR_ICNT_PUSHED];
+ int our_latency = st_time_map[uid][slot] - st_time_map[uid][IN_ICNT_TO_MEM];
assert( our_latency == latency);
} else {
abort();
@@ -306,7 +306,7 @@ private:
while (iter != ld_time_map.end()) {
last_update=0;
first=-1;
- if (!iter->second[MR_WRITEBACK]) {
+ if (!iter->second[IN_SHADER_FETCHED]) {
//this request is not done yet skip it!
++iter;
continue;
@@ -351,7 +351,7 @@ private:
while ( iter != st_time_map.end() ) {
last_update=0;
first=-1;
- if (!iter->second[MR_2SH_ICNT_PUSHED]) {
+ if (!iter->second[IN_SHADER_FETCHED]) {
//this request is not done yet skip it!
++iter;
continue;
@@ -465,8 +465,8 @@ public:
my_time_vector* g_my_time_vector;
-void time_vector_create(int ld_size,int st_size) {
- g_my_time_vector = new my_time_vector(ld_size,st_size);
+void time_vector_create(int size) {
+ g_my_time_vector = new my_time_vector(size,size);
}
diff --git a/src/gpgpu-sim/visualizer.h b/src/gpgpu-sim/visualizer.h
index 0d9424a..8c74d53 100644
--- a/src/gpgpu-sim/visualizer.h
+++ b/src/gpgpu-sim/visualizer.h
@@ -67,7 +67,7 @@
void visualizer_options(class OptionParser *opp);
void visualizer_printstat( class shader_core_ctx **sc, unsigned n_shader, class dram_t **dram, unsigned n_mem );
-void time_vector_create(int ld_size,int st_size);
+void time_vector_create(int size);
void time_vector_print(void);
void time_vector_update(unsigned int uid,int slot ,long int cycle,int type);
void check_time_vector_update(unsigned int uid,int slot ,long int latency,int type);
diff --git a/src/intersim/interconnect_interface.cpp b/src/intersim/interconnect_interface.cpp
index 1b4ffea..b838dcf 100644
--- a/src/intersim/interconnect_interface.cpp
+++ b/src/intersim/interconnect_interface.cpp
@@ -17,9 +17,8 @@
#include "injection.hpp"
#include "interconnect_interface.h"
#include "../gpgpu-sim/mem_fetch.h"
-#include "../gpgpu-sim/gpu-sim.h"
-#include "../gpgpu-sim/shader.h"
#include <string.h>
+#include <math.h>
int _flit_size ;
@@ -317,6 +316,9 @@ bool interconnect_has_buffer(unsigned int input_node, unsigned int tot_req_size)
return has_buffer;
}
+extern unsigned long long gpu_sim_cycle;
+extern unsigned long long gpu_tot_sim_cycle;
+
void interconnect_push ( unsigned int input_node, unsigned int output_node,
void* data, unsigned int size)
{
@@ -465,14 +467,9 @@ void init_interconnect (char* config_file,
if (icnt_config.GetInt("input_buf_size")) {
input_buffer_capacity = icnt_config.GetInt("input_buf_size");
} else {
- if (shader_config->m_L1D_config.get_num_lines() && !shader_config->gpgpu_no_dl1) {
- int l1cache_linesize = shader_config->m_L1D_config.get_line_sz();
- input_buffer_capacity = shader_config->n_thread_per_shader*(l1cache_linesize/_flit_size+(int)ceil(8.0f/_flit_size));
- } else {
- input_buffer_capacity = shader_config->n_thread_per_shader*((int)ceil(8.0f/_flit_size));
- }
+ input_buffer_capacity = 8;
}
- create_buf(traffic[0]->_dests,shader_config->warp_size,icnt_config.GetInt( "num_vcs" ));
+ create_buf(traffic[0]->_dests,input_buffer_capacity,icnt_config.GetInt( "num_vcs" ));
MATLAB_OUTPUT = icnt_config.GetInt("MATLAB_OUTPUT");
DISPLAY_LAT_DIST = icnt_config.GetInt("DISPLAY_LAT_DIST");
DISPLAY_HOP_DIST = icnt_config.GetInt("DISPLAY_HOP_DIST");
diff --git a/src/tr1_hash_map.h b/src/tr1_hash_map.h
index 1ff7c8e..f7813ae 100644
--- a/src/tr1_hash_map.h
+++ b/src/tr1_hash_map.h
@@ -3,20 +3,38 @@
// detection and fallback for unordered_map in C++0x
#ifdef __cplusplus
#ifdef __GNUC__
- #if __GNUC__ >= 4 && __GNUC_MINOR__ >= 3
- #include <unordered_map>
- #define tr1_hash_map std::unordered_map
- #define tr1_hash_map_ismap 0
+ #if __GNUC__ >= 4 && __GNUC_MINOR__ >= 3
+ #include <unordered_map>
+ #define tr1_hash_map std::unordered_map
+ #define tr1_hash_map_ismap 0
+ #else
+ #include <map>
+ #define tr1_hash_map std::map
+ #define tr1_hash_map_ismap 1
+ #endif
#else
#include <map>
#define tr1_hash_map std::map
#define tr1_hash_map_ismap 1
#endif
- #else
- #include <map>
- #define tr1_hash_map std::map
- #define tr1_hash_map_ismap 1
- #endif
-#endif
+ // detect gcc 4.3 and use unordered map (part of c++0x)
+ // unordered map doesn't play nice with _GLIBCXX_DEBUG, just use a map if its enabled.
+ #if defined( __GNUC__ ) and not defined( _GLIBCXX_DEBUG )
+ #if __GNUC__ >= 4 && __GNUC_MINOR__ >= 3
+ #include <unordered_map>
+ #define my_hash_map std::unordered_map
+ #else
+ #include <ext/hash_map>
+ namespace std {
+ using namespace __gnu_cxx;
+ }
+ #define my_hash_map std::hash_map
+ #endif
+ #else
+ #include <map>
+ #define my_hash_map std::map
+ #define USE_MAP
+ #endif
+#endif